7.5 KiB
7.5 KiB
【前端待处理·管理后台】车务派车看板与矩阵 SSE 实时刷新
目标前端
- 端类型:管理后台(Web)
- 目标仓库:
mmg/hl-ui - 仓库地址:https://git.1814.love:8443/mmg/hl-ui.git
- 联调/验收环境:http://192.168.100.160:9527
- 目标角色:当前登录角色为
VEHICLE_MANAGER(车务管理员) - 小程序、司机 H5:无需处理
问题与后端结论
2026-07-21 复现:订单详情新增用车需求后,fleet-service 已生成未派车占位,但已打开的派车看板和矩阵派单不会实时刷新;多个车务管理员同时在线时,其他人的页面也无法感知变化。
根因是原管理后台 SSE 只接入消息、聊天、在线状态和房务抢单池信令,没有车务派单数据变更事件,也没有看板/矩阵的刷新订阅。
后端已补充以下链路:
- fleet-service 在用车需求展开事务真正提交后发布
REQUIREMENT_EXPANDED事件,避免页面刷新早于未派占位落库。 - fleet-service 调 user-service 内部广播接口。
- user-service 经 Redis Pub/Sub 把信令分发到所有实例。
- 每个实例只向当前连接角色为
VEHICLE_MANAGER的 SSE 连接发送fleet-dispatch-changed。 - 信令不绑定单个
adminId,因此多个车务管理员、多个浏览器标签和多个 user-service Pod 均可收到。
后端代码和定向测试已完成;测试环境是否已部署须以前后端发布记录为准。前端不得在后端未部署时把“收不到新事件”误判为页面监听实现失败。
SSE 契约
继续复用现有管理后台 SSE 连接,不新增浏览器请求接口:
GET /ws/admin-msg/stream?token=<accessToken>
Accept: text/event-stream
新增具名事件:
event: fleet-dispatch-changed
data: {"type":"FLEET_DISPATCH","targetRoleKey":"VEHICLE_MANAGER","fleetEvent":"REQUIREMENT_EXPANDED","orderId":"2079494135466643457","requirementId":"..."}
字段说明:
| 字段 | 类型 | 当前值/说明 |
|---|---|---|
type |
String | 固定 FLEET_DISPATCH |
targetRoleKey |
String | 固定 VEHICLE_MANAGER |
fleetEvent |
String | 当前为 REQUIREMENT_EXPANDED |
orderId |
String/Long | 变更涉及的订单 ID;仅作定位提示,按字符串处理 |
requirementId |
String/Long | 变更涉及的用车需求 ID;仅作定位提示,按字符串处理 |
- 前端不得对雪花 ID 使用
Number();如需比较,统一String(value)后比较。 - 本事件是“数据已变化”的轻量信令,不携带看板或矩阵业务正文。
- 收到事件后必须重拉现有权威查询接口,不能根据信令自行拼装订单、派车组或矩阵占用条。
- 后端只向当前角色为
VEHICLE_MANAGER的连接投递。SUPER_ADMIN只有切换并以车务管理员当前角色重新建立 SSE 后才会收到。
前端接入要求
1. 全局 SSE 接收
在 src/composables/useAdminMessageSSE.js 增加具名事件监听:
es.addEventListener('fleet-dispatch-changed', handleFleetDispatchSignal)
解析 JSON 后转入独立的车务派单信令总线。不要复用聊天信令或房务 lastGrabPoolSignal,避免模块语义互相污染。
建议在现有总线文件中新增:
export const lastFleetDispatchSignal = ref(null)
export function pushFleetDispatchSignal(signal) {
if (!signal) return
lastFleetDispatchSignal.value = { ...signal, _seq: Date.now() }
}
连续事件必须保证每次都能触发订阅;实现可沿用现有 _gseq 自增模式,不强制使用 Date.now()。
2. 派车看板刷新
目标页面:src/views/fleet/board/index.vue
- 订阅
lastFleetDispatchSignal。 - 页面处于挂载状态并收到
REQUIREMENT_EXPANDED后调用现有fetchBoard()。 - 保留当前筛选条件、分页/视图模式和搜索输入,不得重置用户工作区。
- 多条短时间信令可做 100~300ms 合并刷新,避免重复并发请求。
- 沿用现有请求序号/取消机制,迟到响应不得覆盖较新的看板数据。
3. 矩阵派单刷新
目标页面:
src/views/fleet/matrix/index.vuesrc/views/fleet/matrix/solo/index.vue(如独立挂载数据上下文)src/views/fleet/matrix/composables/useFleetMatrixData.js
处理要求:
- 收到信令后调用现有
fetchMatrix(requestFilters.value)或等价的当前筛选刷新入口。 - 同步刷新未派订单池、顶部统计和矩阵占用数据;不能只刷新车辆行而保留旧未派数量。
- 保留当前年月、车队、车型和其他筛选条件。
- 若派单弹窗正在提交,不得关闭弹窗或清空用户输入;提交结束后以最后一次权威查询结果收敛页面。
- 矩阵分窗复用主页面数据组件时只订阅一次,避免同一事件发起重复请求。
4. 断线重连对账
Redis Pub/Sub 和 SSE 均不提供历史事件重放。断线期间可能漏过 fleet-dispatch-changed,因此:
- SSE 重新收到
connected后,若派车看板或矩阵当前已打开,应主动重拉一次当前页面数据。 - 不要仅依赖实时事件维持页面正确性。
- 仍按现有 SSE 生命周期要求保证全局只有一条连接,不得为看板和矩阵各自新建
EventSource。
不影响范围
- 不修改派车看板、矩阵派单现有查询接口及响应结构。
- 不修改现有
message、unread-count、im-chat、im-chat-read、presence、grab-pool-changed事件。 - 不要求前端调用
/internal/sse/fleet-dispatch/broadcast;该路径仅供服务间 Feign 使用,管理后台不得直接访问。 - 本次只覆盖用车需求展开后实时刷新。后续其他派单动作如扩展新的
fleetEvent,将另行补充契约。
验收清单
- 以车务管理员 A 打开
/fleet/board,车务管理员 B 或定制师新增用车需求后,A 的看板无需手动刷新即可出现新未派订单。 - 以车务管理员 A 打开
/fleet/matrix,新增用车需求后未派订单池、顶部统计和矩阵数据自动更新。 - 两个不同车务管理员同时在线并分别打开看板/矩阵,两边均收到同一变更并刷新。
- 同一车务管理员两个浏览器标签同时在线,两个标签均能刷新且互不关闭 SSE。
- 当前角色为
SUPER_ADMIN且未切换车务角色时不接收本事件。 SUPER_ADMIN切换为VEHICLE_MANAGER并重建 SSE 后可以接收。- 收到信令时保留看板和矩阵当前筛选条件,不跳回默认月份或清空搜索项。
- 短时间连续提交用车需求不会产生请求风暴或旧响应覆盖新数据。
- SSE 断线期间新增需求,连接恢复并收到
connected后页面主动对账并显示最新数据。 - Network 中只存在一条
/ws/admin-msg/stream长连接,没有为车务页面新增独立 SSE。
后端验证记录
- fleet-service:
AssignmentServiceTest239 项通过。 - fleet-service:车务派单 AFTER_COMMIT 通知测试 2 项通过。
- user-service:
AdminSseServiceTest37 项通过,覆盖两个车务同时接收、非车务角色隔离。 - user-service:车务广播与内部接口测试 3 项通过。
hl-fleet-service、hl-user-service模块级mvn -DskipTests package均通过。
发布说明
- 本文是前端接入与联调通知,不代表已修改或发布
mmg/hl-ui。 - 前端完成后应在
mmg/hl-ui走自身 Issue、分支、PR、测试和发布流程。 - 联调材料不得包含 access token、带 token 的完整 SSE URL、Cookie 或真实管理员身份信息。