From 6c4153fe23e5be8de1877e5c95df71fa477ea4b6 Mon Sep 17 00:00:00 2001 From: lzh Date: Wed, 22 Apr 2026 18:04:10 +0800 Subject: [PATCH] =?UTF-8?q?fix(ops):=20=E6=89=8B=E5=8A=A8=E6=B4=BE?= =?UTF-8?q?=E5=8D=95=E6=8F=90=E5=89=8D=E5=86=99=E6=89=A7=E8=A1=8C=E4=BA=BA?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=EF=BC=8C=E4=BF=AE=E5=A4=8D=E6=8C=89=E9=94=AE?= =?UTF-8?q?=E6=8A=A5"=E6=B2=A1=E6=9C=89=E5=B7=A5=E5=8D=95"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题:管理员手动派单后,工牌按键查询持续返回"没有工单",TTS 循环播报"工单 来啦"但用户无法响应(线上日志可见 deviceId=58 一段时间内连续 8 次按键查询 全部命中 CleanOrderAuditEventHandler.handleQueryEvent 的"没有工单"分支)。 根因:ManualOrderActionFacade.dispatch() 原顺序是 1. transition() —— 事务内同步发布 OrderStateChangedEvent, BadgeDeviceStatusEventListener.onOrderStateChanged 重新 selectById 拿 assigneeId 决定是否写 Redis 工单关联; 2. update assigneeId / assigneeName。 第 1 步事件触发时 assigneeId 仍是 null,listener 走"工单未关联设备,跳过 处理"分支,Redis ops:badge:status:{deviceId} 的 currentOpsOrderId 永远不 会写入;同时主表 assigneeDeviceId 也始终为 null, CleanOrderAuditEventHandler.handleQueryEvent 用 "WHERE assignee_device_id=?" 查工单永远落空 → "没有工单"。 修复:把执行人字段更新前置到 transition() 之前,并补 setAssigneeDeviceId (与 OrderLifecycleManagerImpl.dispatch() 自动派单路径一致)。 事件 listener 此时 selectById 拿得到 deviceId,正常落 Redis;audit 查询也命中,按键路径恢复。 Co-Authored-By: Claude Opus 4.7 (1M context) --- .../core/manual/ManualOrderActionFacade.java | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/core/manual/ManualOrderActionFacade.java b/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/core/manual/ManualOrderActionFacade.java index c02168c3..f6d58b31 100644 --- a/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/core/manual/ManualOrderActionFacade.java +++ b/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/core/manual/ManualOrderActionFacade.java @@ -72,7 +72,19 @@ public class ManualOrderActionFacade { boolean idle = strategy.isAssigneeIdle(cmd, order); WorkOrderStatusEnum targetStatus = idle ? WorkOrderStatusEnum.DISPATCHED : WorkOrderStatusEnum.QUEUED; - // 4. 状态变更 + // 4. 提前写入执行人字段 + // 注:必须在 transition() 之前完成。transition() 在事务内同步发布 OrderStateChangedEvent, + // BadgeDeviceStatusEventListener 会再次 selectById 拿 assigneeId 决定是否写 Redis 工单关联; + // 若此处后置则事件触发时 assigneeId 仍为 null,工牌按键查询 (assigneeDeviceId) 永远查不到工单。 + // 同时写 assigneeDeviceId,与 OrderLifecycleManagerImpl.dispatch() 自动派单路径对齐。 + OpsOrderDO assigneeUpdate = new OpsOrderDO(); + assigneeUpdate.setId(cmd.getOrderId()); + assigneeUpdate.setAssigneeId(cmd.getAssigneeId()); + assigneeUpdate.setAssigneeName(cmd.getAssigneeName()); + assigneeUpdate.setAssigneeDeviceId(cmd.getAssigneeId()); + opsOrderMapper.updateById(assigneeUpdate); + + // 5. 状态变更 OrderTransitionRequest request = OrderTransitionRequest.builder() .orderId(cmd.getOrderId()) .targetStatus(targetStatus) @@ -89,13 +101,6 @@ public class ManualOrderActionFacade { throw new IllegalStateException("手动派单失败: " + result.getMessage()); } - // 5. 更新主表执行人(只更新 assignee 字段,避免覆盖状态机已写入的 status) - OpsOrderDO assigneeUpdate = new OpsOrderDO(); - assigneeUpdate.setId(cmd.getOrderId()); - assigneeUpdate.setAssigneeId(cmd.getAssigneeId()); - assigneeUpdate.setAssigneeName(cmd.getAssigneeName()); - opsOrderMapper.updateById(assigneeUpdate); - // 6. 条线后置 // 注:业务日志由生命周期事件 → 条线 EventListener 统一记录,此处不重复写 strategy.afterDispatch(cmd, order);