From 8ab7e7cc055862a283b16ce9795658d5801d92a6 Mon Sep 17 00:00:00 2001 From: lzh Date: Sat, 14 Feb 2026 12:26:47 +0800 Subject: [PATCH] =?UTF-8?q?fix(ops):=20=E5=AE=8C=E5=96=84=E6=89=8B?= =?UTF-8?q?=E5=8A=A8=E5=8F=96=E6=B6=88=E5=B7=A5=E5=8D=95=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E7=9A=84=E7=8A=B6=E6=80=81=E6=9C=BA=E3=80=81=E6=A0=A1=E9=AA=8C?= =?UTF-8?q?=E5=92=8C=E4=BA=8B=E4=BB=B6=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 状态机允许 ARRIVED→CANCELLED,与业务枚举 canCancel() 保持一致 - cancelOrder 增加已取消幂等返回,已完成改用 ServiceException - cancelOrder 构建请求时传递 assigneeId 确保事件链路完整 - CleanOrderEventListener 新增 handleCancelled:记录扩展表取消时间、 自动调度下一个等待任务;业务日志由 LifecycleManager 统一记录 Co-Authored-By: Claude Opus 4.6 --- .../listener/CleanOrderEventListener.java | 46 ++++++++++++++++++- .../lifecycle/OrderLifecycleManagerImpl.java | 1 + .../ops/service/fsm/OrderStateMachine.java | 3 +- .../service/order/OpsOrderServiceImpl.java | 15 ++++-- 4 files changed, 58 insertions(+), 7 deletions(-) diff --git a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/integration/listener/CleanOrderEventListener.java b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/integration/listener/CleanOrderEventListener.java index 6b24c5f7..c9a4efaa 100644 --- a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/integration/listener/CleanOrderEventListener.java +++ b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/integration/listener/CleanOrderEventListener.java @@ -186,8 +186,8 @@ public class CleanOrderEventListener { clearTrafficActiveOrder(event); break; case CANCELLED: - // 设备状态由 BadgeDeviceStatusEventListener 统一处理 - log.debug("[CleanOrderEventListener] CANCELLED 状态已处理: orderId={}", event.getOrderId()); + + handleCancelled(event); clearTrafficActiveOrder(event); break; case QUEUED: @@ -377,6 +377,48 @@ public class CleanOrderEventListener { log.info("[CleanOrderEventListener] 完成时间已记录: orderId={}, deviceId={}", orderId, deviceId); } + /** + * 处理取消状态 + *

+ * 参照 handleCompleted 模式: + * 1. 记录取消时间到保洁扩展表 + * 2. 异步触发自动调度下一个等待任务 + * 3. 记录业务日志 + */ + @Async("ops-task-executor") + public void handleCancelled(OrderStateChangedEvent event) { + Long orderId = event.getOrderId(); + + // 获取 deviceId(优先从 payload 获取 assigneeId,其次从工单获取) + Long deviceId = event.getPayloadLong("assigneeId"); + if (deviceId == null) { + OpsOrderDO order = opsOrderMapper.selectById(orderId); + if (order != null) { + deviceId = order.getAssigneeId(); + } + } + + // 1. 记录取消时间到扩展表(复用 completedTime 字段记录取消时间点) + OpsOrderCleanExtDO updateExt = new OpsOrderCleanExtDO(); + updateExt.setOpsOrderId(orderId); + updateExt.setCompletedTime(LocalDateTime.now()); + cleanExtMapper.insertOnDuplicateKeyUpdate(updateExt); + + // 2. 业务日志由 OrderLifecycleManagerImpl.cancelOrder() 统一记录,此处不重复 + + // 3. 自动调度下一个等待任务(如果有 assignee) + if (deviceId != null) { + try { + cleanOrderService.autoDispatchNextOrder(orderId, deviceId); + log.info("[CleanOrderEventListener] 取消后自动调度下一个任务: orderId={}, deviceId={}", orderId, deviceId); + } catch (Exception e) { + log.error("[CleanOrderEventListener] 取消后自动调度失败: orderId={}, deviceId={}", orderId, deviceId, e); + } + } + + log.info("[CleanOrderEventListener] 取消时间已记录: orderId={}, deviceId={}", orderId, deviceId); + } + // ==================== 工单完成事件 ==================== /** diff --git a/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/core/lifecycle/OrderLifecycleManagerImpl.java b/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/core/lifecycle/OrderLifecycleManagerImpl.java index aa0eae7f..29fef7c2 100644 --- a/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/core/lifecycle/OrderLifecycleManagerImpl.java +++ b/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/core/lifecycle/OrderLifecycleManagerImpl.java @@ -309,6 +309,7 @@ public class OrderLifecycleManagerImpl implements OrderLifecycleManager { .operatorType(operatorType) .operatorId(operatorId) .reason(reason) + .assigneeId(order != null ? order.getAssigneeId() : null) .build(); // 执行状态转换 diff --git a/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/service/fsm/OrderStateMachine.java b/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/service/fsm/OrderStateMachine.java index e2a0338a..50d098f0 100644 --- a/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/service/fsm/OrderStateMachine.java +++ b/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/service/fsm/OrderStateMachine.java @@ -78,7 +78,8 @@ public class OrderStateMachine { // 作业中 WorkOrderStatusEnum.ARRIVED, Set.of( WorkOrderStatusEnum.PAUSED, // 暂停作业 - WorkOrderStatusEnum.COMPLETED // 完成作业 + WorkOrderStatusEnum.COMPLETED, // 完成作业 + WorkOrderStatusEnum.CANCELLED // 取消作业 ), // 暂停状态 diff --git a/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/service/order/OpsOrderServiceImpl.java b/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/service/order/OpsOrderServiceImpl.java index 7bb5c2c6..96330dad 100644 --- a/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/service/order/OpsOrderServiceImpl.java +++ b/viewsh-module-ops/viewsh-module-ops-biz/src/main/java/com/viewsh/module/ops/service/order/OpsOrderServiceImpl.java @@ -1,5 +1,6 @@ package com.viewsh.module.ops.service.order; +import com.viewsh.framework.common.exception.ServiceException; import com.viewsh.framework.common.pojo.PageResult; import com.viewsh.framework.common.util.object.BeanUtils; import com.viewsh.module.ops.core.lifecycle.OrderLifecycleManager; @@ -274,12 +275,18 @@ public class OpsOrderServiceImpl implements OpsOrderService { throw new RuntimeException("工单不存在: " + orderId); } - // 2. 校验:已完成的工单不能取消 - if (WorkOrderStatusEnum.COMPLETED.getStatus().equals(order.getStatus())) { - throw new RuntimeException("已完成的工单不能取消"); + // 2. 校验:已取消的工单幂等返回 + if (WorkOrderStatusEnum.CANCELLED.getStatus().equals(order.getStatus())) { + log.info("工单已处于取消状态,幂等返回: orderId={}", orderId); + return; } - // 3. 委托给 OrderLifecycleManager 处理(确保工单和队列状态同步) + // 3. 校验:已完成的工单不能取消 + if (WorkOrderStatusEnum.COMPLETED.getStatus().equals(order.getStatus())) { + throw new ServiceException(400, "已完成的工单不能取消"); + } + + // 4. 委托给 OrderLifecycleManager 处理(确保工单和队列状态同步) orderLifecycleManager.cancelOrder(orderId, operatorId, operatorType, reason); log.info("取消工单成功: orderId={}, reason={}", orderId, reason);