应急演练系统 - 数据存储与认证方案

一、当前系统现状

现状分析

二、数据存储方案设计

方案一:云端数据库存储(推荐)

技术架构

┌─────────────┐
│  手机端H5   │ ──扫码登录──> ┌──────────────┐
│  (前端)     │               │  后端API服务  │
└─────────────┘               │  (Node.js/   │
                              │   Python)    │
       │                      └──────────────┘
       │                             │
       │ HTTPS请求                   │
       │                             │
       ▼                             ▼
┌─────────────┐              ┌──────────────┐
│  云存储OSS  │              │  云数据库     │
│  (图片/音频) │              │  (MySQL/     │
└─────────────┘              │   MongoDB)   │
                             └──────────────┘
                

数据库设计

-- 演练基本信息表 CREATE TABLE drills ( id INT PRIMARY KEY AUTO_INCREMENT, drill_name VARCHAR(200), drill_type VARCHAR(50), location VARCHAR(200), gps_lat DECIMAL(10,6), gps_lng DECIMAL(10,6), start_time DATETIME, end_time DATETIME, status VARCHAR(20), created_by INT, created_at TIMESTAMP ); -- 参演队伍表 CREATE TABLE teams ( id INT PRIMARY KEY AUTO_INCREMENT, drill_id INT, team_name VARCHAR(100), team_type VARCHAR(50), team_size INT, equipment TEXT, arrival_time DATETIME, FOREIGN KEY (drill_id) REFERENCES drills(id) ); -- 现场采集记录表 CREATE TABLE field_records ( id INT PRIMARY KEY AUTO_INCREMENT, drill_id INT, record_type VARCHAR(50), content TEXT, voice_url VARCHAR(500), photos JSON, recorder_id INT, record_time DATETIME, FOREIGN KEY (drill_id) REFERENCES drills(id) ); -- 专家点评表 CREATE TABLE expert_reviews ( id INT PRIMARY KEY AUTO_INCREMENT, drill_id INT, expert_id INT, rating VARCHAR(20), comments TEXT, suggestions TEXT, review_time DATETIME, FOREIGN KEY (drill_id) REFERENCES drills(id) ); -- 用户表 CREATE TABLE users ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50), phone VARCHAR(20), role VARCHAR(20), unit VARCHAR(100), created_at TIMESTAMP );
✓ 优点
  • 数据集中管理,永久保存
  • 支持多人协同采集
  • 实时数据同步
  • 便于统计分析
  • 支持数据导出
⚠ 注意事项
  • 需要服务器和域名
  • 需要开发后端API
  • 依赖网络连接
  • 需要运维维护

方案二:混合存储(本地+云端)

工作原理

// 混合存储示例代码 class DataSync { async saveRecord(data) { // 先保存到本地 this.saveToLocal(data); // 尝试上传到云端 if (navigator.onLine) { try { await this.uploadToCloud(data); this.markAsSynced(data.id); } catch (error) { console.log('离线模式,稍后同步'); } } } async syncPendingData() { const pending = this.getUnsyncedData(); for (let data of pending) { await this.uploadToCloud(data); this.markAsSynced(data.id); } } } // 监听网络状态 window.addEventListener('online', () => { dataSync.syncPendingData(); });
✓ 优点
  • 支持离线使用
  • 数据不丢失
  • 用户体验好
  • 适合网络不稳定场景
⚠ 注意事项
  • 需要处理同步冲突
  • 本地存储有容量限制
  • 实现复杂度较高

方案三:轻量级方案(腾讯云开发/Firebase)

使用云开发服务

// 腾讯云开发示例 const db = wx.cloud.database(); // 保存采集记录 async function saveRecord(data) { return await db.collection('drill_records').add({ data: { ...data, createTime: new Date() } }); } // 查询记录 async function getRecords(drillId) { return await db.collection('drill_records') .where({ drillId }) .orderBy('createTime', 'desc') .get(); }
✓ 优点
  • 无需自建服务器
  • 开发速度快
  • 自动扩容
  • 成本低
⚠ 注意事项
  • 依赖第三方平台
  • 功能受限
  • 数据迁移困难

三、认证方案设计

方案一:手机号验证码登录(推荐)

流程设计

  1. 用户扫码进入系统
  2. 输入手机号,点击"获取验证码"
  3. 收到短信验证码,输入验证
  4. 验证通过,生成 JWT Token
  5. 后续请求携带 Token 访问
// 登录流程示例 // 1. 发送验证码 POST /api/auth/send-code { "phone": "13800138000" } // 2. 验证登录 POST /api/auth/login { "phone": "13800138000", "code": "123456" } // 返回 { "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "user": { "id": 1, "phone": "13800138000", "role": "collector", "name": "张三" } } // 3. 后续请求携带 Token GET /api/drills/123 Headers: { "Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." }
✓ 优点
  • 无需记密码
  • 安全性高
  • 用户体验好
  • 实名制管理
⚠ 注意事项
  • 需要短信服务(成本)
  • 依赖手机信号
  • 需要防刷机制

方案二:扫码自动登录

流程设计

  1. 管理员创建演练,生成专属二维码
  2. 二维码包含:演练ID + 临时Token + 角色信息
  3. 用户扫码自动登录,无需输入账号密码
  4. Token 有效期:演练期间有效
// 二维码内容示例 https://drill.example.com/join? drillId=12345& token=abc123def456& role=collector& expires=1737590400 // 扫码后自动登录 GET /api/auth/qrcode-login?token=abc123def456 // 返回用户信息 { "drillId": 12345, "role": "collector", "permissions": ["record", "photo", "voice"] }
✓ 优点
  • 零操作登录
  • 无需手机号
  • 快速分发
  • 适合临时使用
⚠ 注意事项
  • 二维码泄露风险
  • 需要设置有效期
  • 无法追溯个人

方案三:微信授权登录

流程设计

  1. 用户扫码进入微信小程序
  2. 点击"微信授权登录"
  3. 获取微信 openid 作为唯一标识
  4. 首次登录补充手机号和姓名
// 微信授权登录 wx.login({ success: (res) => { // 发送 code 到后端 fetch('/api/auth/wechat-login', { method: 'POST', body: JSON.stringify({ code: res.code }) }); } }); // 后端换取 openid const result = await axios.get( `https://api.weixin.qq.com/sns/jscode2session? appid=${appId}& secret=${appSecret}& js_code=${code}& grant_type=authorization_code` ); // 返回 openid,作为用户唯一标识
✓ 优点
  • 微信生态内流畅
  • 无需额外注册
  • 用户信任度高
  • 可获取用户头像昵称
⚠ 注意事项
  • 仅限微信内使用
  • 需要小程序资质
  • 依赖微信平台

四、权限管理设计

角色 权限 说明
系统管理员 全部权限 创建演练、分配角色、查看所有数据、导出报告
演练指挥员 查看、导出 实时查看演练数据、导出演练报告
信息采集员 录入、查看 录入现场信息、上传照片、查看自己的记录
专家评审员 查看、点评 查看演练数据、提交专家点评意见
参演人员 仅查看 查看演练基本信息和自己队伍的信息
// 权限控制中间件 function checkPermission(requiredRole) { return (req, res, next) => { const user = req.user; const roleLevel = { 'admin': 5, 'commander': 4, 'collector': 3, 'expert': 3, 'participant': 1 }; if (roleLevel[user.role] >= roleLevel[requiredRole]) { next(); } else { res.status(403).json({ error: '权限不足' }); } }; } // 使用示例 app.post('/api/drills', authenticate, checkPermission('admin'), createDrill );

五、推荐方案

🎯 综合推荐方案

数据存储:混合存储(本地+云端)

认证方案:手机号验证码 + 扫码快捷登录

技术栈建议

成本估算(按月)

六、实施步骤

第一阶段:基础功能(2周)

第二阶段:核心功能(2周)

第三阶段:优化完善(1周)

七、安全建议