云上教室选座系统开发实战:基于 Vue3、Express 与 MongoDB 的全栈实践

一、项目架构与技术栈

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. 选座功能实现

前端交互流程

  1. 座位渲染 :根据后端返回的 矩阵,在页面上动态生成座位元素,空闲座位显示为绿色,已占用显示为红色。layout
  2. 点击事件 :绑定点击事件,获取点击座位的 ,调用后端 接口预约座位。seat_id``/api/seat/book
  3. 状态更新:预约成功后,更新本地状态并重新渲染座位列表。

后端 API 设计

  • 接口路径POST /api/seat/book

  • 请求参数

    JSON 格式

    json 复制代码
    {
      "roomID": 506,
      "seat_id": 1,
      "user_num": "235030101", // 学号
      "time": "2025-02-28 14:00:00", // 预约时间
      "ampm": "下午" // 时段(上午/下午)
    }
  • 业务逻辑

    1. 检查该座位在对应时段是否已被占用(查询 集合)。座位记录
    2. 检查用户是否已在该时段预约其他座位(唯一约束)。
    3. 插入预约记录到 集合,并更新 集合中对应座位的 状态为 。座位记录``教室``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. 部署步骤

  1. 前端打包

    arduino 复制代码
    pnpm run build

    生成的静态文件存放在 目录,部署至 Nginx 或静态服务器。dist

  2. 后端部署

    bash 复制代码
    # 安装 PM2 进程管理器
    pnpm install pm2 -g
    
    # 启动应用
    pm2 start app.js --name "cloud-classroom-server"
  3. Nginx 配置(HTTPS):

    bash 复制代码
    server {
      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

      php 复制代码
      const cors = require('cors');
      app.use(cors({
        origin: 'https://your-frontend-domain.com',
        methods: ['GET', 'POST', 'PUT', 'DELETE']
      }));

2. 座位预约冲突检测

  • 问题:同一座位同一时段被多个用户预约。

  • 解决方案

    • 在 MongoDB 中为 集合添加唯一复合索引:seat_log

      JavaScript

      php 复制代码
      db.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 证书。

五、功能扩展与优化方向

1. 功能扩展建议

  • 用户认证:添加 JWT token 认证,确保只有登录用户可预约座位。
  • 时段管理:支持自定义上课时段(如上午、下午、晚上),并限制每个时段的预约时间范围。
  • 数据统计:统计教室使用率、热门座位排行等,为教室管理提供数据支持。

2. 性能优化

  • 前端 :使用 Vue 的 / 优化座位列表渲染性能,对大数据量采用虚拟滚动列表。v-show``v-if
  • 后端 :对高频查询的字段(如 、)添加索引,减少数据库查询耗时。roomID``seat_id
  • 缓存:使用 Redis 缓存热门教室数据,降低数据库压力。

六、总结

云上教室选座系统通过 Vue3 实现了动态交互的前端界面,结合 Express 和 MongoDB 构建了灵活的数据管理后端,解决了教室座位预约的核心需求。开发过程中需重点关注数据模型设计、跨域请求处理和业务逻辑的原子性,后续可通过扩展认证体系和数据分析功能进一步提升系统实用性。

在线演示dudubb.cn

相关推荐
IT瘾君1 小时前
JavaWeb:前端工程化-Vue
前端·javascript·vue.js
zhang98800001 小时前
JavaScript 核心原理深度解析-不停留于表面的VUE等的使用!
开发语言·javascript·vue.js
potender1 小时前
前端框架Vue
前端·vue.js·前端框架
拉不动的猪4 小时前
都25年啦,还有谁分不清双向绑定原理,响应式原理、v-model实现原理
前端·javascript·vue.js
清幽竹客6 小时前
vue-18(使用 Vuex 插件实现高级功能)
前端·vue.js·前端框架·vue
哈贝#8 小时前
vue和uniapp聊天页面右侧滚动条自动到底部
javascript·vue.js·uni-app
Lazy_zheng8 小时前
🚀 前端开发福音:用 json-server 快速搭建本地 Mock 数据服务
前端·javascript·vue.js
林太白8 小时前
前端必会之Nuxt.js
前端·javascript·vue.js
晓晓莺歌8 小时前
vue-router路由问题:可以通过$router.push()跳转,但刷新后又变成空白页面
前端·javascript·vue.js
前端大卫8 小时前
vxe-table 在项目中的实践!【附源码】
前端·vue.js·前端工程化