一、项目架构与技术栈
1. 整体架构设计
- 前端:采用 Vue3 + Vite 构建单页应用(SPA),使用 Vue Router 实现路由管理,通过 Axios 与后端 API 交互。
- 后端:基于 Express 搭建 RESTful API 服务,使用 MongoDB 作为数据库存储教室、座位、用户等数据,通过 Mongoose作数据库。
- 部署:前端通过 Vite 打包为静态文件,后端使用 PM2 进程管理工具部署,配合 Nginx 实现反向代理和 HTTPS 支持。
2. 技术栈详情
技术 / 工具 | 版本号 | 作用 |
---|---|---|
Vue3 | ^3.5.13 | 构建用户界面,采用 Composition API |
Vite | ^6.1.0 | 前端打包工具,支持快速热更新(HMR) |
Express | ^5.0.1 | 后端 Web 框架,处理路由和中间件 |
MongoDB 数据库 | ^6.13.0 | 非关系型数据库,存储教室座位数据 |
PNPM | ^9.0 | 包管理工具,管理项目依赖 |
Axios | ^1.4.0 | 前端 HTTP 客户端,用于 API 调用 |
CORS | ^2.8.5 | 解决跨域资源共享(CORS)问题 |
二、核心功能开发
1. 教室与座位数据结构设计
数据模型说明
JSON 格式
csharp
{
"roomID": 506, // 教室编号
"arr": [ // 座位布局矩阵(1 表示有座位,0 表示过道)
[1, 0, 1, 1, 0, 1],
[1, 0, 1, 1, 0, 1]
],
"layout": [ // 座位 ID 映射矩阵,对应 arr 中的 1 位置
[1, 0, 2, 3, 0, 4],
[5, 0, 6, 7, 0, 8]
],
"data": [ // 座位详细信息数组
{
"seat_id": 1,
"remark": "备注",
"is_free": true, // 是否空闲
"reArr": [] // 预约记录数组
}
]
}
生成逻辑(参考 )ADB.js
-
通过双重循环遍历 矩阵,为每个值为 1 的位置分配唯一 ,生成 和 数组。
arr``seat_id``layout``data
-
示例代码片段:
JavaScript
ini
function 生成数据(roomID, arr) {
let seatId = 1;
const layout = [];
const data = [];
for (let i = 0; i < arr.length; i++) {
const row = [];
for (let j = 0; j < arr[i].length; j++) {
if (arr[i][j] === 1) {
row.push(seatId);
data.push({
seat_id: seatId,
remark: '备注',
is_free: true,
reArr: []
});
seatId++;
} else {
row.push(0);
}
}
layout.push(row);
}
return { roomID, arr, layout, data };
}
2. 选座功能实现
前端交互流程
- 座位渲染 :根据后端返回的 矩阵,在页面上动态生成座位元素,空闲座位显示为绿色,已占用显示为红色。
layout
- 点击事件 :绑定点击事件,获取点击座位的 ,调用后端 接口预约座位。
seat_id``/api/seat/book
- 状态更新:预约成功后,更新本地状态并重新渲染座位列表。
后端 API 设计
-
接口路径 :
POST /api/seat/book
-
请求参数:
JSON 格式
json{ "roomID": 506, "seat_id": 1, "user_num": "235030101", // 学号 "time": "2025-02-28 14:00:00", // 预约时间 "ampm": "下午" // 时段(上午/下午) }
-
业务逻辑:
- 检查该座位在对应时段是否已被占用(查询 集合)。
座位记录
- 检查用户是否已在该时段预约其他座位(唯一约束)。
- 插入预约记录到 集合,并更新 集合中对应座位的 状态为 。
座位记录``教室``is_free``false
- 检查该座位在对应时段是否已被占用(查询 集合)。
3. 数据库操作
集合设计
- 教室(room): 存储教室布局及座位基础信息。
- 座位记录(seat_log): 存储预约记录,包含用户信息、座位 ID、预约时间等。
- 用户(student): 存储用户基本信息(学号、姓名、token 等)。
示例查询(MongoDB Aggregation)
查询教室 506 中所有已被预约的座位:
JavaScript
php
const result = await db.collection('room').aggregate([
{
$lookup: {
from: "seat_log",
localField: "data.seat_id",
foreignField: "seat_id",
as: "booked_seats"
}
},
{
$match: {
roomID: 506,
"booked_seats": { $exists: true, $not: { $size: 0 } }
}
}
]).toArray();
三、开发与部署流程
1. 前端项目初始化
php
# 创建 Vite + Vue3 项目
pnpm create vite@latest frontend --template vue
cd frontend
pnpm install
# 配置代理(vite.config.js)
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
server: {
proxy: {
'/api': {
target: 'https://dudubb.cn', // 后端 API 地址
changeOrigin: true,
secure: true,
rewrite: (path) => path.replace(/^/api/, '')
}
}
}
})
2. 后端项目结构
csharp
backend/
├─ src/
│ ├─ routes/ # 路由模块(seat.js、room.js)
│ ├─ models/ # 数据库模型(room.model.js)
│ ├─ app.js # 主入口文件
│ └─ db.js # 数据库连接模块
├─ package.json # 依赖清单
└─ pnpm-lock.yaml # 依赖锁文件
3. 部署步骤
-
前端打包:
arduinopnpm run build
生成的静态文件存放在 目录,部署至 Nginx 或静态服务器。
dist
-
后端部署:
bash# 安装 PM2 进程管理器 pnpm install pm2 -g # 启动应用 pm2 start app.js --name "cloud-classroom-server"
-
Nginx 配置(HTTPS):
bashserver { listen 443 ssl; server_name dudubb.cn; ssl_certificate /path/to/dudubb.cn.pem; ssl_certificate_key /path/to/dudubb.cn.key; location / { root /path/to/frontend/dist; index index.html; try_files $uri $uri/ /index.html; } location /api { proxy_pass http://localhost:3000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }
四、关键问题与解决方案
1. 跨域问题
-
现象 :前端调用后端 API 时出现 错误。
Access-Control-Allow-Origin
-
解决方案:
-
后端使用 中间件全局允许跨域:
cors
JavaScript
phpconst cors = require('cors'); app.use(cors({ origin: 'https://your-frontend-domain.com', methods: ['GET', 'POST', 'PUT', 'DELETE'] }));
-
2. 座位预约冲突检测
-
问题:同一座位同一时段被多个用户预约。
-
解决方案:
-
在 MongoDB 中为 集合添加唯一复合索引:
seat_log
JavaScript
phpdb.seat_log.createIndex({ seat_id: 1, time: 1, ampm: 1 }, { unique: true });
-
后端在处理预约请求时,先通过索引查询是否存在冲突记录,再执行插入操作。
-
3. HTTPS 证书配置
-
问题 :浏览器提示证书无效()。
ERR_CERT_COMMON_NAME_INVALID
-
解决方案:
- 确保 Vue 项目中 API 请求使用域名而非 IP 地址(修改前端代码中的请求地址为 )。
https://dudubb.cn/api
- 检查 Nginx 配置中的证书路径是否正确,重新生成或更新 SSL 证书。
- 确保 Vue 项目中 API 请求使用域名而非 IP 地址(修改前端代码中的请求地址为 )。
五、功能扩展与优化方向
1. 功能扩展建议
- 用户认证:添加 JWT token 认证,确保只有登录用户可预约座位。
- 时段管理:支持自定义上课时段(如上午、下午、晚上),并限制每个时段的预约时间范围。
- 数据统计:统计教室使用率、热门座位排行等,为教室管理提供数据支持。
2. 性能优化
- 前端 :使用 Vue 的 / 优化座位列表渲染性能,对大数据量采用虚拟滚动列表。
v-show``v-if
- 后端 :对高频查询的字段(如 、)添加索引,减少数据库查询耗时。
roomID``seat_id
- 缓存:使用 Redis 缓存热门教室数据,降低数据库压力。
六、总结
云上教室选座系统通过 Vue3 实现了动态交互的前端界面,结合 Express 和 MongoDB 构建了灵活的数据管理后端,解决了教室座位预约的核心需求。开发过程中需重点关注数据模型设计、跨域请求处理和业务逻辑的原子性,后续可通过扩展认证体系和数据分析功能进一步提升系统实用性。
在线演示 :dudubb.cn