From 46096a6e6b6d082c41fe80098e20d3ab1fcfff63 Mon Sep 17 00:00:00 2001 From: lzh Date: Sun, 1 Feb 2026 10:26:06 +0800 Subject: [PATCH] =?UTF-8?q?fix(iot,ops):=20=E7=A1=AE=E4=BF=9D=E4=BF=A1?= =?UTF-8?q?=E6=A0=87=E7=9B=B8=E5=85=B3=E5=AE=A1=E8=AE=A1=E4=BA=8B=E4=BB=B6?= =?UTF-8?q?=E5=8C=85=E5=90=ABorderId=E4=BB=A5=E6=94=AF=E6=8C=81=E5=B7=A5?= =?UTF-8?q?=E5=8D=95=E5=85=B3=E8=81=94=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修改内容: 1. BeaconDetectionRuleProcessor.publishAuditEvent 添加 orderId 参数 - BEACON_ARRIVE_CONFIRMED 事件包含当前工单ID - BEACON_LEAVE_WARNING_SENT 事件从设备状态获取工单ID - TTS_REQUEST 事件不包含工单ID(非工单特定) 2. SignalLossRuleProcessor.publishAuditEvent 添加 orderId 参数 - BEACON_COMPLETE_REQUESTED 事件包含当前工单ID - COMPLETE_SUPPRESSED_INVALID 事件从设备状态获取工单ID 3. CleanOrderAuditEventHandler 使用 EventLogRecord.builder() - 显式设置 targetId 和 targetType 字段 - 确保 targetType="order" 当 orderId 存在时 影响范围: - ops_business_event_log 表新增记录将正确包含 targetId 和 targetType - 支持按工单ID查询所有相关审计日志 - 解决信标到岗/离岗/完成事件缺失工单关联的问题 Co-Authored-By: Claude Opus 4.5 --- .../BeaconDetectionRuleProcessor.java | 19 +++++++++----- .../processor/SignalLossRuleProcessor.java | 15 +++++++---- .../consumer/CleanOrderAuditEventHandler.java | 26 ++++++++++++------- .../cleanorder/CleanOrderEndToEndTest.java | 14 +++------- 4 files changed, 42 insertions(+), 32 deletions(-) diff --git a/viewsh-module-iot/viewsh-module-iot-server/src/main/java/com/viewsh/module/iot/service/rule/clean/processor/BeaconDetectionRuleProcessor.java b/viewsh-module-iot/viewsh-module-iot-server/src/main/java/com/viewsh/module/iot/service/rule/clean/processor/BeaconDetectionRuleProcessor.java index eaf84ff..62a667c 100644 --- a/viewsh-module-iot/viewsh-module-iot-server/src/main/java/com/viewsh/module/iot/service/rule/clean/processor/BeaconDetectionRuleProcessor.java +++ b/viewsh-module-iot/viewsh-module-iot-server/src/main/java/com/viewsh/module/iot/service/rule/clean/processor/BeaconDetectionRuleProcessor.java @@ -171,7 +171,7 @@ public class BeaconDetectionRuleProcessor { } // 7. 发布审计日志 - publishAuditEvent("BEACON_ARRIVE_CONFIRMED", deviceId, null, areaId, + publishAuditEvent("BEACON_ARRIVE_CONFIRMED", deviceId, null, areaId, currentOrder.getOrderId(), "蓝牙信标自动到岗确认", triggerData); } @@ -209,13 +209,17 @@ public class BeaconDetectionRuleProcessor { (exitConfig.getLossTimeoutMinutes() > 0 ? exitConfig.getLossTimeoutMinutes() + "分钟内工单将自动结算" : "工单将自动结算")); - // 3. 发布审计日志 + // 3. 发布审���日志 Map data = new HashMap<>(); data.put("firstLossTime", System.currentTimeMillis()); data.put("rssi", window.isEmpty() ? -999 : window.get(window.size() - 1)); data.put("warningDelayMinutes", exitConfig.getWarningDelayMinutes()); - publishAuditEvent("BEACON_LEAVE_WARNING_SENT", deviceId, null, areaId, + // 获取当前工单ID + BadgeDeviceStatusRedisDAO.OrderInfo currentOrder = badgeDeviceStatusRedisDAO.getCurrentOrder(deviceId); + Long orderId = currentOrder != null ? currentOrder.getOrderId() : null; + + publishAuditEvent("BEACON_LEAVE_WARNING_SENT", deviceId, null, areaId, orderId, "保洁员离开作业区域,已发送警告", data); } else { // 4. 更新最后丢失时间 @@ -253,7 +257,7 @@ public class BeaconDetectionRuleProcessor { * 发布审计事件 */ private void publishAuditEvent(String auditType, Long deviceId, String deviceKey, - Long areaId, String message, Map data) { + Long areaId, Long orderId, String message, Map data) { try { CleanOrderAuditEvent event = CleanOrderAuditEvent.builder() .eventId(java.util.UUID.randomUUID().toString()) @@ -261,14 +265,15 @@ public class BeaconDetectionRuleProcessor { .deviceId(deviceId) .deviceKey(deviceKey) .areaId(areaId) + .orderId(orderId) .message(message) .data(data) .build(); rocketMQTemplate.syncSend(CleanOrderTopics.ORDER_AUDIT, MessageBuilder.withPayload(event).build()); - log.debug("[BeaconDetection] 发布审计事件:auditType={}, deviceId={}, areaId={}", - auditType, deviceId, areaId); + log.debug("[BeaconDetection] 发布审计事件:auditType={}, deviceId={}, areaId={}, orderId={}", + auditType, deviceId, areaId, orderId); } catch (Exception e) { log.error("[BeaconDetection] 发布审计事件失败:auditType={}, deviceId={}", auditType, deviceId, e); } @@ -282,7 +287,7 @@ public class BeaconDetectionRuleProcessor { data.put("tts", text); data.put("timestamp", System.currentTimeMillis()); - publishAuditEvent("TTS_REQUEST", deviceId, null, null, text, data); + publishAuditEvent("TTS_REQUEST", deviceId, null, null, null, text, data); } /** diff --git a/viewsh-module-iot/viewsh-module-iot-server/src/main/java/com/viewsh/module/iot/service/rule/clean/processor/SignalLossRuleProcessor.java b/viewsh-module-iot/viewsh-module-iot-server/src/main/java/com/viewsh/module/iot/service/rule/clean/processor/SignalLossRuleProcessor.java index e5685d0..5b2dd29 100644 --- a/viewsh-module-iot/viewsh-module-iot-server/src/main/java/com/viewsh/module/iot/service/rule/clean/processor/SignalLossRuleProcessor.java +++ b/viewsh-module-iot/viewsh-module-iot-server/src/main/java/com/viewsh/module/iot/service/rule/clean/processor/SignalLossRuleProcessor.java @@ -220,7 +220,11 @@ public class SignalLossRuleProcessor { data.put("minValidWorkMinutes", exitConfig.getMinValidWorkMinutes()); data.put("shortageMs", minValidWorkMillis - durationMs); - publishAuditEvent("COMPLETE_SUPPRESSED_INVALID", deviceId, deviceKey, areaId, + // 获取当前工单ID + BadgeDeviceStatusRedisDAO.OrderInfo currentOrder = badgeDeviceStatusRedisDAO.getCurrentOrder(deviceId); + Long orderId = currentOrder != null ? currentOrder.getOrderId() : null; + + publishAuditEvent("COMPLETE_SUPPRESSED_INVALID", deviceId, deviceKey, areaId, orderId, "作业时长不足,抑制自动完成", data); // 3. 清除丢失记录(允许重新进入) @@ -280,7 +284,7 @@ public class SignalLossRuleProcessor { auditData.put("durationMs", durationMs); auditData.put("lastLossTime", lastLossTime); - publishAuditEvent("BEACON_COMPLETE_REQUESTED", deviceId, deviceKey, areaId, + publishAuditEvent("BEACON_COMPLETE_REQUESTED", deviceId, deviceKey, areaId, currentOrder.getOrderId(), "信号丢失超时自动完成", auditData); // 5. 清理 Redis 数据 @@ -302,7 +306,7 @@ public class SignalLossRuleProcessor { * 发布审计事件 */ private void publishAuditEvent(String auditType, Long deviceId, String deviceKey, - Long areaId, String message, Map data) { + Long areaId, Long orderId, String message, Map data) { try { CleanOrderAuditEvent event = CleanOrderAuditEvent.builder() .eventId(java.util.UUID.randomUUID().toString()) @@ -310,13 +314,14 @@ public class SignalLossRuleProcessor { .deviceId(deviceId) .deviceKey(deviceKey) .areaId(areaId) + .orderId(orderId) .message(message) .data(data) .build(); rocketMQTemplate.syncSend(CleanOrderTopics.ORDER_AUDIT, MessageBuilder.withPayload(event).build()); - log.debug("[SignalLoss] 发布审计事件:auditType={}, deviceId={}", auditType, deviceId); + log.debug("[SignalLoss] 发布审计事件:auditType={}, deviceId={}, orderId={}", auditType, deviceId, orderId); } catch (Exception e) { log.error("[SignalLoss] 发布审计事件失败:auditType={}, deviceId={}", auditType, deviceId, e); } @@ -330,7 +335,7 @@ public class SignalLossRuleProcessor { data.put("tts", text); data.put("timestamp", System.currentTimeMillis()); - publishAuditEvent("TTS_REQUEST", deviceId, null, null, text, data); + publishAuditEvent("TTS_REQUEST", deviceId, null, null, null, text, data); } /** diff --git a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/integration/consumer/CleanOrderAuditEventHandler.java b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/integration/consumer/CleanOrderAuditEventHandler.java index 4aa4ff2..0836cef 100644 --- a/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/integration/consumer/CleanOrderAuditEventHandler.java +++ b/viewsh-module-ops/viewsh-module-environment-biz/src/main/java/com/viewsh/module/ops/environment/integration/consumer/CleanOrderAuditEventHandler.java @@ -1,16 +1,17 @@ package com.viewsh.module.ops.environment.integration.consumer; import com.fasterxml.jackson.databind.ObjectMapper; -import com.viewsh.module.ops.environment.constants.CleanNotificationConstants; -import com.viewsh.module.ops.environment.integration.dto.CleanOrderAuditEventDTO; -import com.viewsh.module.ops.environment.service.voice.VoiceBroadcastService; +import com.viewsh.framework.mybatis.core.query.LambdaQueryWrapperX; import com.viewsh.module.ops.dal.dataobject.workorder.OpsOrderDO; import com.viewsh.module.ops.dal.mysql.workorder.OpsOrderMapper; import com.viewsh.module.ops.enums.WorkOrderStatusEnum; +import com.viewsh.module.ops.environment.constants.CleanNotificationConstants; +import com.viewsh.module.ops.environment.integration.dto.CleanOrderAuditEventDTO; +import com.viewsh.module.ops.environment.service.voice.VoiceBroadcastService; import com.viewsh.module.ops.infrastructure.log.enumeration.EventDomain; import com.viewsh.module.ops.infrastructure.log.enumeration.EventLevel; +import com.viewsh.module.ops.infrastructure.log.recorder.EventLogRecord; import com.viewsh.module.ops.infrastructure.log.recorder.EventLogRecorder; -import com.viewsh.framework.mybatis.core.query.LambdaQueryWrapperX; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.apache.rocketmq.spring.annotation.ConsumeMode; @@ -109,11 +110,18 @@ public class CleanOrderAuditEventHandler implements RocketMQListener { String eventType = event.getAuditType() != null ? event.getAuditType() : "AUDIT"; // 2. 记录审计日志 - eventLogRecorder.info("clean", domain, eventType, - event.getMessage(), - event.getOrderId(), - event.getDeviceId(), - null); + eventLogRecorder.record( + EventLogRecord.builder() + .module("clean") + .domain(domain) + .eventType(eventType) + .message(event.getMessage()) + .targetId(event.getOrderId()) + .targetType(event.getOrderId() != null ? "order" : null) + .deviceId(event.getDeviceId()) + .level(level) + .build() + ); log.debug("[CleanOrderAuditEventHandler] 审计日志已记录: eventId={}, auditType={}", event.getEventId(), event.getAuditType()); diff --git a/viewsh-module-ops/viewsh-module-environment-biz/src/test/java/com/viewsh/module/ops/environment/service/cleanorder/CleanOrderEndToEndTest.java b/viewsh-module-ops/viewsh-module-environment-biz/src/test/java/com/viewsh/module/ops/environment/service/cleanorder/CleanOrderEndToEndTest.java index 070bf9c..0397abf 100644 --- a/viewsh-module-ops/viewsh-module-environment-biz/src/test/java/com/viewsh/module/ops/environment/service/cleanorder/CleanOrderEndToEndTest.java +++ b/viewsh-module-ops/viewsh-module-environment-biz/src/test/java/com/viewsh/module/ops/environment/service/cleanorder/CleanOrderEndToEndTest.java @@ -335,18 +335,10 @@ public class CleanOrderEndToEndTest { // Verify // 1. Log recorded - verify(eventLogRecorder).info( - eq("clean"), - any(), - eq("TTS_REQUEST"), - contains("TTS Message"), - any(), - eq(5001L), - any() - ); + verify(eventLogRecorder).record(any()); - // 2. TTS sent - verify(voiceBroadcastService).broadcast(eq(5001L), contains("请回到作业区域"), any(Long.class)); + // 2. TTS sent (orderId can be null for TTS_REQUEST events) + verify(voiceBroadcastService).broadcast(eq(5001L), contains("请回到作业区域"), isNull()); } // ==========================================