From 5419a949d4183ad12db0b1aadde0e431d6178898 Mon Sep 17 00:00:00 2001 From: lzh Date: Mon, 19 Jan 2026 10:56:30 +0800 Subject: [PATCH] =?UTF-8?q?feat(ops):=20=E5=B7=A5=E5=8D=95=E5=88=9B?= =?UTF-8?q?=E5=BB=BA=E5=8F=91=E5=B8=83=E4=BA=8B=E4=BB=B6=EF=BC=88=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6=E9=A9=B1=E5=8A=A8=E8=B0=83=E5=BA=A6=EF=BC=89=20&=20?= =?UTF-8?q?=20=E5=B7=A5=E5=8D=95=E5=AE=8C=E6=88=90=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E4=B8=8B=E4=B8=80=E4=B8=AA=E4=BB=BB=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CleanOrderCompleteEventHandler.java | 13 ++- .../listener/OrderCreatedEventListener.java | 91 +++++++++++++++++++ .../cleanorder/CleanOrderServiceImpl.java | 28 ++++-- 3 files changed, 123 insertions(+), 9 deletions(-) create mode 100644 viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/integration/listener/OrderCreatedEventListener.java diff --git a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/integration/consumer/CleanOrderCompleteEventHandler.java b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/integration/consumer/CleanOrderCompleteEventHandler.java index 386df6cf..0d5308f5 100644 --- a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/integration/consumer/CleanOrderCompleteEventHandler.java +++ b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/integration/consumer/CleanOrderCompleteEventHandler.java @@ -8,6 +8,7 @@ import com.viewsh.module.ops.dal.mysql.workorder.OpsOrderMapper; import com.viewsh.module.ops.enums.OperatorTypeEnum; import com.viewsh.module.ops.enums.WorkOrderStatusEnum; import com.viewsh.module.ops.environment.integration.dto.CleanOrderCompleteEventDTO; +import com.viewsh.module.ops.environment.service.cleanorder.CleanOrderService; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.apache.rocketmq.spring.annotation.ConsumeMode; @@ -68,6 +69,9 @@ public class CleanOrderCompleteEventHandler implements RocketMQListener @Resource private OrderLifecycleManager orderLifecycleManager; + @Resource + private CleanOrderService cleanOrderService; + @Override public void onMessage(String message) { try { @@ -142,8 +146,13 @@ public class CleanOrderCompleteEventHandler implements RocketMQListener // 6. 清除 Redis 缓存(设备当前工单) clearDeviceCurrentOrder(event.getDeviceId()); - log.info("[CleanOrderCompleteEventHandler] 工单完成成功: eventId={}, orderId={}, duration={}ms", - event.getEventId(), event.getOrderId(), + // 7. 自动调度下一个任务(优先恢复被中断的任务) + if (order.getAssigneeId() != null) { + cleanOrderService.autoDispatchNextOrder(event.getOrderId(), order.getAssigneeId()); + } + + log.info("[CleanOrderCompleteEventHandler] 工单完成成功: eventId={}, orderId={}, assigneeId={}, duration={}ms", + event.getEventId(), event.getOrderId(), order.getAssigneeId(), event.getTriggerData() != null ? event.getTriggerData().get("durationMs") : "N/A"); } diff --git a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/integration/listener/OrderCreatedEventListener.java b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/integration/listener/OrderCreatedEventListener.java new file mode 100644 index 00000000..828c71e0 --- /dev/null +++ b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/integration/listener/OrderCreatedEventListener.java @@ -0,0 +1,91 @@ +package com.viewsh.module.ops.environment.integration.listener; + +import com.viewsh.module.ops.core.dispatch.DispatchEngine; +import com.viewsh.module.ops.core.dispatch.model.OrderDispatchContext; +import com.viewsh.module.ops.core.event.OrderCreatedEvent; +import com.viewsh.module.ops.dal.dataobject.workorder.OpsOrderDO; +import com.viewsh.module.ops.dal.mysql.workorder.OpsOrderMapper; +import com.viewsh.module.ops.enums.PriorityEnum; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; +import org.springframework.transaction.event.TransactionPhase; +import org.springframework.transaction.event.TransactionalEventListener; + +/** + * 工单创建事件监听器 + *

+ * 监听工单创建事件,自动触发调度流程 + *

+ * 职责: + * - 工单创建后自动调用调度引擎进行派单 + * - 支持 P0 紧急任务的打断逻辑(通过 CleanerPriorityScheduleStrategy) + * + * @author AI + */ +@Slf4j +@Component +public class OrderCreatedEventListener { + + @Resource + private DispatchEngine dispatchEngine; + + @Resource + private OpsOrderMapper opsOrderMapper; + + /** + * 监听工单创建事件,触发自动调度 + *

+ * 使用 @TransactionalEventListener 确保在事务提交后才执行调度 + * 这样可以避免调度失败导致工单创建回滚 + */ + @org.springframework.transaction.event.TransactionalEventListener( + phase = TransactionPhase.AFTER_COMMIT + ) + public void onOrderCreated(OrderCreatedEvent event) { + try { + log.info("[OrderCreatedEventListener] 收到工单创建事件: orderId={}, orderType={}, priority={}", + event.getOrderId(), event.getOrderType(), event.getPriority()); + + // 只处理保洁工单 + if (!"CLEAN".equals(event.getOrderType())) { + log.debug("[OrderCreatedEventListener] 跳过非保洁工单: orderType={}", event.getOrderType()); + return; + } + + // 查询工单信息 + OpsOrderDO order = opsOrderMapper.selectById(event.getOrderId()); + if (order == null) { + log.warn("[OrderCreatedEventListener] 工单不存在,无法调度: orderId={}", event.getOrderId()); + return; + } + + // 构建调度上下文 + OrderDispatchContext context = OrderDispatchContext.builder() + .orderId(order.getId()) + .orderCode(order.getOrderCode()) + .orderTitle(order.getTitle()) + .businessType(order.getOrderType()) + .areaId(event.getAreaId() != null ? event.getAreaId() : order.getAreaId()) + .priority(PriorityEnum.fromPriority(event.getPriority())) + .build(); + + // 使用调度引擎执行调度(包含 P0 打断逻辑) + var result = dispatchEngine.dispatch(context); + + if (result.isSuccess()) { + log.info("[OrderCreatedEventListener] 自动调度成功: orderId={}, assigneeId={}, path={}", + event.getOrderId(), result.getAssigneeId(), result.getPath()); + } else { + log.warn("[OrderCreatedEventListener] 自动调度失败: orderId={}, reason={}", + event.getOrderId(), result.getMessage()); + } + + } catch (Exception e) { + // 调度失败不应影响工单创建 + log.error("[OrderCreatedEventListener] 自动调度异常: orderId={}", event.getOrderId(), e); + } + } +} diff --git a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/cleanorder/CleanOrderServiceImpl.java b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/cleanorder/CleanOrderServiceImpl.java index 7a2d9c8a..7f1a1943 100644 --- a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/cleanorder/CleanOrderServiceImpl.java +++ b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/service/cleanorder/CleanOrderServiceImpl.java @@ -5,6 +5,8 @@ import com.viewsh.module.ops.api.queue.OrderQueueService; import com.viewsh.module.ops.core.dispatch.DispatchEngine; import com.viewsh.module.ops.core.dispatch.model.DispatchResult; import com.viewsh.module.ops.core.dispatch.model.OrderDispatchContext; +import com.viewsh.module.ops.core.event.OrderCreatedEvent; +import com.viewsh.module.ops.core.event.OrderEventPublisher; import com.viewsh.module.ops.core.lifecycle.OrderLifecycleManager; import com.viewsh.module.ops.core.lifecycle.model.OrderTransitionRequest; import com.viewsh.module.ops.dal.dataobject.workorder.OpsOrderDO; @@ -64,11 +66,11 @@ public class CleanOrderServiceImpl implements CleanOrderService { @Resource private OrderQueueService orderQueueService; - @Resource - private CleanerAreaAssignStrategy cleanerAreaAssignStrategy; - - @Resource - private CleanerStatusService cleanerStatusService; +// @Resource +// private CleanerAreaAssignStrategy cleanerAreaAssignStrategy; +// +// @Resource +// private CleanerStatusService cleanerStatusService; @Resource private DispatchEngine dispatchEngine; @@ -79,6 +81,9 @@ public class CleanOrderServiceImpl implements CleanOrderService { @Resource private CleanOrderEventHandler cleanOrderEventHandler; + @Resource + private OrderEventPublisher orderEventPublisher; + // ==================== 工单创建 ==================== @Override @@ -100,8 +105,17 @@ public class CleanOrderServiceImpl implements CleanOrderService { log.info("创建自动保洁工单成功: orderId={}, expectedDuration={}分钟", orderId, createReq.getExpectedDuration()); - // 3. 调度引擎分配 - autoAssignOrder(orderId, createReq.getAreaId(), PriorityEnum.fromPriority(createReq.getPriority())); + // 3. 发布工单创建事件,由 OrderCreatedEventListener 触发调度 + OrderCreatedEvent event = OrderCreatedEvent.builder() + .orderId(orderId) + .orderType("CLEAN") + .areaId(createReq.getAreaId()) + .priority(PriorityEnum.fromPriority(createReq.getPriority()).getPriority()) + .createTime(java.time.LocalDateTime.now()) + .build() + .addPayload("isAuto", true) + .addPayload("expectedDuration", createReq.getExpectedDuration()); + orderEventPublisher.publishOrderCreated(event); return orderId; }