- 新增 deploy/docker/:Docker 本机模拟部署,含 Dockerfile、docker-compose、deploy.sh 一键脚本 - 新增 deploy/remote/:远程服务器部署,含 SSH 自动上传、重启、回滚脚本 - 新增 deploy/README.md:完整使用手册,含现状分析、落地调整工作清单、命令速查 - 新增 build.sh/start.sh:本地构建和启动脚本(含飞书通知) - 新增前端 .env.docker 环境配置,API 指向测试服务器 - 前端 package.json 新增 build-docker 命令 - 更新 .gitignore:排除 IDE 配置、SQL 数据、Docker 敏感文件 - 前端 UI 样式优化(多个页面组件) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
58 KiB
58 KiB
智慧清洁 SaaS 平台 - 系统流程架构图
一、系统整体架构
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 客户端层 │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Web 管理后台 │ │ 手机 APP │ │ 智能手表 │ │
│ │ (Vue 3 SPA) │ │ (Android/iOS)│ │ (IoT 设备) │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
│ │ HTTP/REST │ HTTP/REST │ MQTT │
└─────────┼───────────────────┼───────────────────┼──────────────────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 服务层 │
│ ┌─────────────────────────────────┐ ┌─────────────────────────────────┐ │
│ │ Web 服务 (端口 8095) │ │ Task 服务 (端口 8097) │ │
│ │ ┌───────────┐ ┌─────────────┐ │ │ ┌───────────┐ ┌────────────┐ │ │
│ │ │ Controller│ │ Interceptor │ │ │ │ XXL-Job │ │ @Scheduled │ │ │
│ │ │ (API) │ │ (认证签名) │ │ │ │ (定时任务) │ │ (消息队列) │ │ │
│ │ └─────┬─────┘ └──────┬──────┘ │ │ └─────┬─────┘ └─────┬──────┘ │ │
│ │ │ │ │ │ │ │ │ │
│ │ ┌─────▼──────────────▼──────┐ │ │ ┌─────▼─────────────▼───────┐ │ │
│ │ │ Service 层 │ │ │ │ Service 层 │ │ │
│ │ └─────────────┬─────────────┘ │ │ └────────────┬──────────────┘ │ │
│ │ │ │ │ │ │ │
│ │ ┌─────────────▼─────────────┐ │ │ ┌────────────▼──────────────┐ │ │
│ │ │ Mapper (MyBatis-Plus) │ │ │ │ Mapper (MyBatis-Plus) │ │ │
│ │ └─────────────┬─────────────┘ │ │ └────────────┬──────────────┘ │ │
│ └────────────────┼────────────────┘ └───────────────┼─────────────────┘ │
│ │ │ │
└───────────────────┼─────────────────────────────────────┼──────────────────────┘
│ │
┌─────────▼─────────────────────────────────────▼──────────┐
│ 数据层 │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ MySQL DB1 │ │ MySQL DB2 │ │ Redis │ │
│ │ (基础信息) │ │ (业务数据) │ │ (DB4+DB5) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────┘
二、Web 请求完整链路
2.1 前端 HTTP 请求 → 后端响应
┌──────────────────────────────────────────────────────────────────────────────┐
│ 前端 (Vue 3 SPA) │
│ │
│ 用户操作 (点击按钮/提交表单) │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ ApiService (如 taskCenterService.js) │ │
│ │ 调用封装的 API 方法 │ │
│ └──────────────────────────┬──────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ requestUtils.js - Axios 请求拦截器 │ │
│ │ │ │
│ │ ① 从 sessionStorage 读取登录信息 (UUID, phone) │ │
│ │ ② 生成签名: MD5(MD5(uuid) + MD5(timestamp + phone)) │ │
│ │ ③ 设置请求头: │ │
│ │ - signature: 签名值 │ │
│ │ - uuid: 用户UUID │ │
│ │ - timestamp: 当前时间戳 │ │
│ │ - webId: 当前页面ID │ │
│ │ ④ 清除空值参数 │ │
│ │ ⑤ 设置 withCredentials: true │ │
│ └──────────────────────────┬──────────────────────────────────────┘ │
│ │ │
│ │ POST /api/xxx │
│ │ (通过 Vite proxy 代理到 localhost:8095) │
└─────────────────────────────┼────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────────────────┐
│ 后端 Web 服务 (Spring Boot, 端口 8095) │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ ① SystemInterceptor (请求拦截器) │ │
│ │ │ │
│ │ 排除路径: /login, /sms/sendCode, /doc.html, /swagger │ │
│ │ │ │
│ │ a. 提取请求头: uuid, signature, timestamp │ │
│ │ b. 验证时间戳 (10秒有效窗口) │ │
│ │ c. 从 Redis 查询登录态: │ │
│ │ Redis GET uuid → 获取用户信息(mobile等) │ │
│ │ d. 验证签名: │ │
│ │ 服务端重算 MD5 签名 vs 请求头签名 │ │
│ │ e. 验证通过 → 将用户信息存入 Request Attribute │ │
│ │ f. 验证失败 → 返回 code 104 (需重新登录) │ │
│ │ │ │
│ └──────────────────────────┬──────────────────────────────────────┘ │
│ │ 认证通过 │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ ② RepeatSubmitAspect (AOP 防重复提交) │ │
│ │ │ │
│ │ a. 生成锁 Key: "redis_lock_" + 请求路径 │ │
│ │ b. Redis SETNX 尝试加锁 (30秒过期) │ │
│ │ c. 获取锁 → 继续执行 │ │
│ │ d. 未获取锁 → 返回 "请勿重复提交" │ │
│ │ │ │
│ └──────────────────────────┬──────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ ③ Controller (如 TaskController) │ │
│ │ │ │
│ │ a. 接收请求参数 (@RequestBody / @RequestParam) │ │
│ │ b. 从 Request Attribute 获取当前用户信息 │ │
│ │ c. 调用 Service 层处理业务逻辑 │ │
│ │ │ │
│ └──────────────────────────┬──────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ ④ Service 层 │ │
│ │ │ │
│ │ a. 业务逻辑处理 │ │
│ │ b. 组合多个 Mapper 查询/更新 │ │
│ │ c. 操作 Redis 缓存 (读/写) │ │
│ │ d. 写入变更日志 (ChangeLog) │ │
│ │ │ │
│ └──────────────────────────┬──────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ ⑤ Mapper 层 (MyBatis-Plus) │ │
│ │ │ │
│ │ a. DB1 Mapper → MySQL xiaoqu_comples_d (基础数据) │ │
│ │ b. DB2 Mapper → MySQL xiaoqu_intellectual_d (业务数据) │ │
│ │ c. 支持分页查询 (IPage) │ │
│ │ d. 支持动态条件构造 (QueryWrapper) │ │
│ │ │ │
│ └──────────────────────────┬──────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ ⑥ SetUserAspect (AOP 审计日志) │ │
│ │ │ │
│ │ a. 记录操作人 (create_id / modify_id) │ │
│ │ b. 记录操作时间 (create_time / modify_time) │ │
│ │ c. 记录变更日志 (ChangeLog) │ │
│ │ │ │
│ └──────────────────────────┬──────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ ⑦ 构造响应 (统一返回格式) │ │
│ │ │ │
│ │ 成功: { code: 100, data: {...}, msg: "操作成功" } │ │
│ │ 失败: { code: 101, data: null, msg: "错误信息" } │ │
│ │ 未登录: { code: 104, data: null, msg: "请重新登录" } │ │
│ │ 指纹无效: { code: 113, data: null, msg: "指纹无效" } │ │
│ │ │ │
│ └──────────────────────────┬──────────────────────────────────────┘ │
│ │ │
└─────────────────────────────┼────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────────────────┐
│ 前端 (Vue 3 SPA) │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ requestUtils.js - Axios 响应拦截器 │ │
│ │ │ │
│ │ ① code == 100 → 返回 data 给业务组件 │ │
│ │ ② code == 104 → 清除 sessionStorage → 跳转登录页 │ │
│ │ ③ code == 113 → 指纹无效 → 跳转登录页 │ │
│ │ ④ 其他 code → 显示错误提示 (ElMessage) │ │
│ │ │ │
│ └──────────────────────────┬──────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ 页面组件渲染 │ │
│ │ │ │
│ │ a. qu-table 根据权限组动态渲染列 (fetchFields) │ │
│ │ b. qu-button-group 根据权限组动态渲染按钮 (fetchButtons) │ │
│ │ c. 数据绑定到 Vuex Store / 组件 data │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────────────────┘
2.2 登录认证流程
用户输入手机号
│
▼
┌──────────────┐ GET /sms/sendCode?mobile=xxx
│ 获取验证码 │ ──────────────────────────────────► SendSmsController
└──────┬───────┘ │
│ ▼
│ 生成验证码 → Redis SET
│ 调用短信平台发送
│
▼
┌──────────────┐ POST /login {mobile, code}
│ 提交登录 │ ──────────────────────────────────► LoginController
└──────┬───────┘ │
│ ▼
│ ① 验证码校验 (Redis GET)
│ ② 查询用户 (MySQL user表)
│ ③ 生成 UUID
│ ④ Redis SET uuid → 用户信息 (30天)
│ ⑤ 记录登录日志 (login_log)
│ ⑥ 返回: uuid + 用户信息 + 菜单权限
│
▼
┌──────────────┐
│ sessionStorage│ ← 存储 loginInfo(base64), uuid, phone
│ 后续请求携带 │ → signature, uuid, timestamp 请求头
└──────────────┘
三、任务调度完整链路
3.1 计划 → 任务生成 → 派单 → 推送
┌─────────────────────────────────────────────────────────────────────────────┐
│ 阶段一:计划创建与启用 (Web 服务) │
│ │
│ 管理员操作 (Web后台) │
│ │ │
│ ▼ │
│ POST /plan/addOrUpdatePlan │
│ │ │
│ ▼ │
│ PlanController → PlanService │
│ │ 保存计划: Plan + PlanObject + PlanOperation + PlanScenes │
│ │ + PlanUser + PlanWorkGroup │
│ ▼ │
│ POST /plan/enablePlan │
│ │ │
│ ▼ │
│ 创建 XXL-Job 定时任务 (planCreateTask) │
│ 设置 cron 表达式 (根据周期配置) │
│ Redis SET Plan:<type>:<planId> → xxlJobId │
│ │
└───────────────────────────────┬─────────────────────────────────────────────┘
│ XXL-Job 定时触发
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 阶段二:任务生成 (Task 服务 - PlanTimeTask) │
│ │
│ planCreateTask 触发 │
│ │ │
│ ▼ │
│ ① 检查节假日 (Holiday表) │
│ │ eliminate_type=1 且为节假日 → 跳过 │
│ ▼ │
│ ② 检查禁用标志 │
│ │ Redis GET Disable:d:<districtId>:<taskTypeId> │
│ │ 如果 "1" → 存入 RebuildTask 等待恢复 │
│ ▼ │
│ ③ 生成任务 │
│ │ Redis LPUSH PlanTaskQueue ← planId │
│ ▼ │
│ ④ 计算下一次执行时间 │
│ │ 根据 circle_type (天/周/月) + circle_no 计算 │
│ │ 动态更新 XXL-Job cron 表达式 │
│ ▼ │
│ ⑤ 创建 TaskInfo 记录 (MySQL) │
│ │ 状态: status=0 (已生成) │
│ │ 关联: plan_id, district_id, task_type │
│ │ 创建: TaskScenes, TaskUser │
│ │
└───────────────────────────────┬─────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 阶段三:任务派单 (Task 服务 - TaskCorrelationSetTask, 每秒执行) │
│ │
│ Redis RPOP taskUserQueue │
│ │ │
│ ▼ │
│ ① 读取派单配置 │
│ │ Redis HMGET Dictionary: │
│ │ UserAppointFlag (是否指定人员) │
│ │ UserAreaFlag (是否限定区域) │
│ │ UserDutyFlag (是否按职责) │
│ ▼ │
│ ② 匹配可用人员 │
│ │ 查询: 用户状态=空闲, 所属站点, 技能匹配, 服务区域 │
│ │ 排序: 按优先级/距离 │
│ ▼ │
│ ③ 分配任务 │
│ │ 更新 TaskInfo.status = 1 (已匹配) / 2 (待抢单) / 3 (已接单) │
│ │ 创建/更新 TaskUser 记录 │
│ ▼ │
│ ④ 触发推送 │
│ │ Redis LPUSH taskPushQueue ← TaskPushInfo │
│ │ Redis LPUSH WatchTaskUserList ← taskUserId │
│ │ Redis LPUSH IntellectualTaskIdList ← taskId │
│ │
└──────────┬──────────────────────────────┬───────────────────────────────────┘
│ │
▼ ▼
┌────────────────────────┐ ┌──────────────────────────────────────────────┐
│ 阶段四A:APP推送 │ │ 阶段四B:手表推送 │
│ (TaskPushMessage, 每秒) │ │ (ScheduledTask, 每2秒) │
│ │ │ │
│ Redis RPOP │ │ Redis RPOP WatchTaskUserList │
│ taskPushQueue │ │ │ │
│ │ │ │ ▼ │
│ ▼ │ │ 构建 WatchTaskMessage │
│ 判断推送类型: │ │ (任务名/类型/位置/时间) │
│ status=1 新任务 │ │ │ │
│ status=2 抢单池 │ │ ▼ │
│ status=3 已接单 │ │ Redis LPUSH MqttWatchTaskMessage │
│ status=7/8 已取消 │ │ │ │
│ │ │ │ ▼ │
│ ▼ │ │ Redis RPOP MqttWatchTaskMessage │
│ 调用个推 SDK: │ │ │ │
│ 在线→NotificationTpl │ │ ▼ │
│ 离线→TransmissionTpl │ │ MQTT publish → 手表 (topic=imei) │
│ │ │ │ │
│ ▼ │ │ │
│ 保存 PushLog │ │ │
│ │ │ │ │
│ ▼ │ │ │
│ ┌──────────┐ │ │ ┌──────────┐ │
│ │ 手机 APP │ │ │ │ 智能手表 │ │
│ │ 收到通知 │ │ │ │ 收到任务 │ │
│ └──────────┘ │ │ └──────────┘ │
└────────────────────────┘ └──────────────────────────────────────────────┘
3.2 任务状态变更推送流程
员工操作 (APP: 接单/开始/完成)
│
▼
Web API → 更新 TaskInfo.status
│
▼
Redis LPUSH IntellectualTaskIdList ← taskId
│
▼ (Task 服务, 每2秒)
┌─────────────────────────────────────────────┐
│ TodayDynamicMessage │
│ │
│ ① Redis LPOP IntellectualTaskIdList │
│ ② 查询 TaskInfo 详情 │
│ ③ 确定推送对象: │
│ - 代理人员 (Agent用户) │
│ - 物业管理员 │
│ - 任务分配人员 │
│ - 指派管理员 │
│ ④ 生成 TodayDynamic 记录 (MySQL) │
│ ⑤ Redis LPUSH MqttTaskStateMessage │
└──────────────────┬──────────────────────────┘
│
▼ (每2秒)
┌─────────────────────────────────────────────┐
│ MqttTaskStateMessage │
│ │
│ ① Redis RPOP MqttTaskStateMessage │
│ ② 构建推送消息 │
│ ③ MQTT publish → mobile_<districtId> │
│ │
│ ┌──────────┐ │
│ │ 手机 APP │ ← 实时接收任务动态 │
│ └──────────┘ │
└─────────────────────────────────────────────┘
四、设备告警 → 维护任务流程
┌──────────────┐
│ IoT 设备 │ (纸巾机/空气净化器/传感器)
│ 检测到异常 │
└──────┬───────┘
│ 告警数据
▼
┌──────────────────────────────────────────────────────────────┐
│ 设备告警 → Redis │
│ │
│ Redis LPUSH taskCommand ← TaskCommandInfo JSON │
│ { │
│ snCode: "设备SN", │
│ taskTypeId: 23, // 空气质量/纸巾不足等 │
│ districtId: 1, │
│ scenesId: 5 │
│ } │
└──────────────────────────┬───────────────────────────────────┘
│
▼ (Task 服务 - TaskCreateQueue, 每秒)
┌──────────────────────────────────────────────────────────────┐
│ TaskCreateQueue.taskCommandHandle() │
│ │
│ ① Redis RPOP taskCommand (DB5) │
│ ② 检查任务开关: │
│ Redis GET DevTaskFlag:<districtId> (DB4) │
│ 如果 "0" → 跳过 │
│ ③ 检查禁用标志: │
│ Redis GET Disable:d/t/p:<id>:<taskTypeId> (DB4) │
│ 如果 "1" → 存入 RebuildTask 等待恢复 │
│ ④ 去重检查: │
│ 查询是否存在同设备未完成任务 │
│ 如果存在 → 跳过 │
│ ⑤ 创建 TaskInfo (MySQL): │
│ status=0, task_type=设备维护 │
│ 关联: sn_code, district_id, scenes_id │
│ ⑥ 创建 TaskScenes, TaskUser │
│ ⑦ Redis LPUSH taskPushQueue ← 推送消息 │
│ ⑧ Redis LPUSH WatchTaskUserList ← 手表任务 │
│ │
└──────────────────────────┬───────────────────────────────────┘
│
▼
(走标准推送流程,同 3.1 阶段四)
│
┌────────────┼────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ APP 通知 │ │ 手表提醒 │ │ Web 后台 │
│ 维护员收到│ │ 震动+语音 │ │ 任务列表 │
└──────────┘ └──────────┘ └──────────┘
五、MQTT 设备通信流程
5.1 手表上下线监控
智能手表
│
│ MQTT connect/disconnect
▼
┌──────────────────────────────────────────────┐
│ MQTT Broker (tcp://mqtt:1883) │
│ │
│ Topic: $SYS/brokers/+/clients/# │
│ 消息: {clientid:"watch_IMEI_xxx", │
│ connected_at: 1700000000} │
└──────────────────┬───────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ PushCallback (MQTT 消息回调) │
│ │
│ ① 过滤: clientid 包含 "watch" │
│ ② 解析: connected_at / disconnected_at │
│ ③ Redis LPUSH WatchConnectList ← 连接事件 │
└──────────────────┬───────────────────────────┘
│
▼ (每秒)
┌──────────────────────────────────────────────┐
│ ScheduledTask.WatchConnectList() │
│ │
│ ① Redis RPOP WatchConnectList │
│ ② 解析连接/断开: │
│ connected_at ≠ null → 上线 (status=1) │
│ disconnected_at ≠ null → 离线 (status=0) │
│ ③ 创建 WatchOffLog (MySQL) │
│ ④ 更新 Watch 表状态 (MySQL) │
└──────────────────────────────────────────────┘
5.2 蓝牙定位流程
┌──────────────┐
│ 智能手表 │ 持续扫描周围蓝牙信标
│ BLE 扫描 │
└──────┬───────┘
│ 信标数据: {mac, rssi, imei}
▼
┌──────────────────────────────────────────────┐
│ 数据上报 → Redis │
│ Redis LPUSH BleutoothLocationQueue ← JSON │
└──────────────────┬───────────────────────────┘
│
▼ (每秒)
┌──────────────────────────────────────────────────────────────┐
│ LocationTask.BleutoothLocationTask() │
│ │
│ ① Redis RPOP BleutoothLocationQueue │
│ ② 根据信标 MAC 查询 Beacon 表 → 获取位置信息 │
│ ③ RSSI 阈值判断: │
│ ┌────────────────────────────────────────────────┐ │
│ │ RSSI ≥ 阈值 (进入范围) │ │
│ │ → 保存 UserLocation (MySQL) │ │
│ │ → 创建 UserTrajectory (status=0, 进行中) │ │
│ │ → Redis SET Location:<userId> ← 位置信息 │ │
│ ├────────────────────────────────────────────────┤ │
│ │ 同一位置停留 < 5秒 │ │
│ │ → 更新 UserTrajectory.stay_time │ │
│ ├────────────────────────────────────────────────┤ │
│ │ 同一位置停留 ≥ 5秒 │ │
│ │ → 保存当前轨迹 (status=1, 完成) │ │
│ │ → 创建新的 UserTrajectory │ │
│ ├────────────────────────────────────────────────┤ │
│ │ RSSI < 阈值 (离开范围) │ │
│ │ → 记录离开时间 │ │
│ │ → 标记轨迹完成 (status=1) │ │
│ └────────────────────────────────────────────────┘ │
│ │
│ ④ 定位数据支撑: │
│ → Web 后台实时位置显示 │
│ → 人效分析报表 │
│ → 考勤打卡佐证 │
└──────────────────────────────────────────────────────────────┘
六、员工休息管理流程
员工点击 "休息" (APP)
│
▼
Web API → 创建休息请求
│
▼ (Task 服务 - XXL-Job)
┌──────────────────────────────────────────────────────────────┐
│ userRestStartTask │
│ │
│ ① 创建 RestRecord (punchType=0, MySQL) │
│ ② 查询站点配置 → 获取休息时长 (默认60分钟) │
│ ③ Redis ZADD CleaningRestLastTime │
│ score=截止时间戳 value=userId │
│ ④ 更新 UserDistrictAttendance.workAtStatus=3 (休息中) │
│ ⑤ Redis SET CleaningUpWorkAtStatus:<mobile> ← 原状态 │
│ ⑥ Redis LPUSH AttendanceStatusMessage ← 考勤消息 │
│ │ │
│ ▼ (ScheduledTask, 每秒) │
│ MQTT publish → 手表 (messageType=5, 关闭蓝牙) │
│ │
└──────────────────────────────┬───────────────────────────────┘
│
┌──────────┴──────────┐
▼ ▼
正常结束休息 超时自动恢复
┌─────────────────────────┐ ┌─────────────────────────┐
│ userRestEndTask │ │ restCountDown (每秒检查) │
│ (XXL-Job 定时触发) │ │ │
│ │ │ Redis ZRANGEBYSCORE │
│ ① RestRecord │ │ CleaningRestLastTime │
│ (punchType=1) │ │ 0 ~ 当前时间戳 │
│ ② 计算实际休息时长 │ │ │ │
│ ③ 恢复 workAtStatus │ │ ▼ │
│ (从 Redis 读取原状态) │ │ 发现超时员工 │
│ ④ 清除 Redis 标记 │ │ → 自动创建恢复记录 │
│ │ │ → 恢复 workAtStatus=2 │
└─────────────────────────┘ └─────────────────────────┘
七、数据导出流程
管理员点击 "导出" (Web 后台)
│
▼
POST /xxx/export
│
▼
┌──────────────────────────────────────────────────────────────┐
│ Controller.export() │
│ │
│ ① 接收查询条件 (同列表查询) │
│ ② 查询权限组字段 (FieldWebpageAuthority) │
│ → 确定可导出的列 │
│ ③ Service 查询数据 (不分页, 全量) │
│ ④ 构造 Excel (Apache POI / EasyExcel) │
│ → 根据权限动态设置列 │
│ ⑤ 设置响应头: │
│ Content-Type: application/octet-stream │
│ Content-Disposition: attachment; filename=xxx.xlsx │
│ ⑥ 输出流写入 Response │
└──────────────────────────┬───────────────────────────────────┘
│
▼
┌──────────────┐
│ 浏览器下载 │
│ Excel 文件 │
└──────────────┘
八、权限动态加载流程
页面加载 / 路由切换
│
▼
┌──────────────────────────────────────────────────────────────┐
│ router-guard.js (路由守卫) │
│ │
│ ① 检查 sessionStorage 登录态 │
│ ② 读取路由 query: wId (页面ID), pageType │
│ ③ 触发 Vuex actions: │
│ store.dispatch('fetchFields', {wId, pageType}) │
│ store.dispatch('fetchButtons', {wId, pageType}) │
└──────────────────────────┬───────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────┐
│ Vuex Store │
│ │
│ fetchFields: │
│ POST /webPage/getFieldsByAuthority │
│ → 返回当前用户权限组下该页面可见字段列表 │
│ → 存入 state.fields │
│ │
│ fetchButtons: │
│ POST /webPage/getButtonsByAuthority │
│ → 返回当前用户权限组下该页面可见按钮列表 │
│ → 存入 state.buttons │
└──────────────────────────┬───────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────┐
│ 页面组件渲染 │
│ │
│ <qu-table> │
│ 遍历 state.fields → 动态生成 <el-table-column> │
│ 字段不在权限列表 → 不渲染该列 │
│ │
│ <qu-button-group> │
│ 遍历 state.buttons → 动态生成 <el-button> │
│ 按钮不在权限列表 → 不渲染该按钮 │
└──────────────────────────────────────────────────────────────┘
九、Redis 消息队列数据流全景
┌─────────────┐
│ DB 4 │
└──────┬──────┘
│
┌──────────────────────────────┬┼┬──────────────────────────────┐
│ │ ││ │ │
▼ ▼ ▼▼ ▼ ▼
┌────────┐ ┌──────────┐ ┌─────────────┐ ┌──────────┐ ┌────────────┐
│taskUser│ │taskPush │ │WatchTask │ │Mqtt │ │Bleutooth │
│Queue │ │Queue │ │UserList │ │TaskState │ │Location │
│ │ │ │ │ │ │Message │ │Queue │
└───┬────┘ └────┬─────┘ └──────┬──────┘ └────┬─────┘ └─────┬──────┘
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
┌────────┐ ┌──────────┐ ┌─────────────┐ ┌──────────┐ ┌────────────┐
│派单 │ │个推推送 │ │构建手表消息 │ │MQTT推送 │ │位置计算 │
│匹配 │ │APP通知 │ │ │ │到手机端 │ │轨迹记录 │
└────────┘ └──────────┘ └──────┬──────┘ └──────────┘ └────────────┘
│
▼
┌─────────────┐
│MqttWatch │
│TaskMessage │
└──────┬──────┘
│
▼
┌─────────────┐
│MQTT推送 │
│到手表 │
└─────────────┘
┌─────────────┐
│ DB 5 │
└──────┬──────┘
│
┌──────────────────────┬───────┼───────┬──────────────────────┐
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
┌────────┐ ┌──────────┐ ┌────┐ ┌──────────┐ ┌──────────┐
│task │ │Finish │ │实体│ │Dictionary│ │Location │
│Command │ │TaskQueue │ │缓存│ │ (Hash) │ │:<userId> │
│(设备告警)│ │(完成队列)│ │ │ │(系统配置)│ │(实时位置) │
└───┬────┘ └────┬─────┘ └────┘ └──────────┘ └──────────┘
│ │
▼ ▼
┌────────┐ ┌──────────┐
│生成 │ │完成后 │
│维护任务│ │处理逻辑 │
└────────┘ └──────────┘