feat(ops): 事件日志增强与空闲设备待办检查
- 实现空闲设备待办工单检查定时任务 - 修复事件日志 orderId 关联 (使用 targetId) - 增强语音播报和工单事件的日志完整性
This commit is contained in:
@@ -36,12 +36,7 @@ import java.util.concurrent.TimeUnit;
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RocketMQMessageListener(
|
||||
topic = "ops-order-audit",
|
||||
consumerGroup = "ops-clean-order-audit-group",
|
||||
consumeMode = ConsumeMode.CONCURRENTLY,
|
||||
selectorExpression = "*"
|
||||
)
|
||||
@RocketMQMessageListener(topic = "ops-order-audit", consumerGroup = "ops-clean-order-audit-group", consumeMode = ConsumeMode.CONCURRENTLY, selectorExpression = "*")
|
||||
public class CleanOrderAuditEventHandler implements RocketMQListener<String> {
|
||||
|
||||
/**
|
||||
@@ -148,7 +143,7 @@ public class CleanOrderAuditEventHandler implements RocketMQListener<String> {
|
||||
return;
|
||||
}
|
||||
|
||||
sendTts(event.getDeviceId(), ttsText);
|
||||
sendTts(event.getDeviceId(), ttsText, event.getOrderId());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -187,15 +182,16 @@ public class CleanOrderAuditEventHandler implements RocketMQListener<String> {
|
||||
String ttsText = CleanNotificationConstants.VoiceBuilder.buildQuery(currentOrderTitle, pendingCount.intValue());
|
||||
|
||||
// 4. 下发 TTS
|
||||
sendTts(deviceId, ttsText);
|
||||
Long orderId = currentOrder != null ? currentOrder.getId() : null;
|
||||
sendTts(deviceId, ttsText, orderId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 下发 TTS 语音播报
|
||||
*/
|
||||
private void sendTts(Long deviceId, String text) {
|
||||
private void sendTts(Long deviceId, String text, Long orderId) {
|
||||
try {
|
||||
voiceBroadcastService.broadcast(deviceId, text);
|
||||
voiceBroadcastService.broadcast(deviceId, text, orderId);
|
||||
log.info("[CleanOrderAuditEventHandler] TTS 下发成功: deviceId={}, text={}", deviceId, text);
|
||||
} catch (Exception e) {
|
||||
log.error("[CleanOrderAuditEventHandler] TTS 下发异常: deviceId={}", deviceId, e);
|
||||
|
||||
@@ -34,12 +34,7 @@ import java.util.concurrent.TimeUnit;
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RocketMQMessageListener(
|
||||
topic = "ops-order-create",
|
||||
consumerGroup = "ops-clean-order-create-group",
|
||||
consumeMode = ConsumeMode.CONCURRENTLY,
|
||||
selectorExpression = "*"
|
||||
)
|
||||
@RocketMQMessageListener(topic = "ops-order-create", consumerGroup = "ops-clean-order-create-group", consumeMode = ConsumeMode.CONCURRENTLY, selectorExpression = "*")
|
||||
public class CleanOrderCreateEventHandler implements RocketMQListener<String> {
|
||||
|
||||
/**
|
||||
@@ -102,8 +97,8 @@ public class CleanOrderCreateEventHandler implements RocketMQListener<String> {
|
||||
createReq.setSourceType("TRAFFIC"); // 系统触发
|
||||
createReq.setTitle(generateOrderTitle(event));
|
||||
createReq.setDescription(generateOrderDescription(event));
|
||||
createReq.setPriority(PriorityEnum.fromPriority(event.getPriority() != null ?
|
||||
event.getPriority() : 2).getPriority());
|
||||
createReq.setPriority(
|
||||
PriorityEnum.fromPriority(event.getPriority() != null ? event.getPriority() : 2).getPriority());
|
||||
createReq.setAreaId(event.getAreaId());
|
||||
|
||||
// 扩展字段
|
||||
@@ -133,7 +128,8 @@ public class CleanOrderCreateEventHandler implements RocketMQListener<String> {
|
||||
/**
|
||||
* 记录工单创建业务日志
|
||||
*/
|
||||
private void recordOrderCreatedLog(CleanOrderCreateEventDTO event, Long orderId, CleanOrderAutoCreateReqDTO createReq) {
|
||||
private void recordOrderCreatedLog(CleanOrderCreateEventDTO event, Long orderId,
|
||||
CleanOrderAutoCreateReqDTO createReq) {
|
||||
try {
|
||||
// 确定事件域
|
||||
EventDomain domain = determineDomain(event.getTriggerSource());
|
||||
|
||||
@@ -28,13 +28,41 @@ import org.springframework.stereotype.Component;
|
||||
* <p>
|
||||
* 状态处理:
|
||||
* <table>
|
||||
* <tr><th>状态</th><th>设备状态</th><th>工单关联</th></tr>
|
||||
* <tr><td>DISPATCHED</td><td>BUSY</td><td>设置</td></tr>
|
||||
* <tr><td>CONFIRMED</td><td>保持BUSY</td><td>设置</td></tr>
|
||||
* <tr><td>ARRIVED</td><td>保持BUSY</td><td>设置完整信息</td></tr>
|
||||
* <tr><td>PAUSED</td><td>PAUSED</td><td>保持</td></tr>
|
||||
* <tr><td>COMPLETED</td><td>检查等待任务</td><td>清除</td></tr>
|
||||
* <tr><td>CANCELLED</td><td>IDLE</td><td>清除</td></tr>
|
||||
* <tr>
|
||||
* <th>状态</th>
|
||||
* <th>设备状态</th>
|
||||
* <th>工单关联</th>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>DISPATCHED</td>
|
||||
* <td>BUSY</td>
|
||||
* <td>设置</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>CONFIRMED</td>
|
||||
* <td>保持BUSY</td>
|
||||
* <td>设置</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>ARRIVED</td>
|
||||
* <td>保持BUSY</td>
|
||||
* <td>设置完整信息</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>PAUSED</td>
|
||||
* <td>PAUSED</td>
|
||||
* <td>保持</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>COMPLETED</td>
|
||||
* <td>检查等待任务</td>
|
||||
* <td>清除</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>CANCELLED</td>
|
||||
* <td>IDLE</td>
|
||||
* <td>清除</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*
|
||||
* @author lzh
|
||||
@@ -99,14 +127,16 @@ public class BadgeDeviceStatusEventListener {
|
||||
/**
|
||||
* 根据工单状态更新设备工牌关联
|
||||
*/
|
||||
private void handleOrderStatusTransition(Long deviceId, Long orderId, WorkOrderStatusEnum newStatus, OrderStateChangedEvent event) {
|
||||
private void handleOrderStatusTransition(Long deviceId, Long orderId, WorkOrderStatusEnum newStatus,
|
||||
OrderStateChangedEvent event) {
|
||||
var waitingTasks = orderQueueService.getWaitingTasksByUserId(deviceId);
|
||||
switch (newStatus) {
|
||||
case DISPATCHED:
|
||||
// 工单已推送到工牌,设置工单关联,设备状态转为 BUSY
|
||||
badgeDeviceStatusService.setCurrentOrder(deviceId, orderId);
|
||||
badgeDeviceStatusService.updateBadgeStatus(deviceId, BadgeDeviceStatusEnum.BUSY, null, "新工单已推送");
|
||||
log.info("[BadgeDeviceStatusEventListener] 工单已推送,设备状态转为 BUSY: deviceId={}, orderId={}", deviceId, orderId);
|
||||
log.info("[BadgeDeviceStatusEventListener] 工单已推送,设备状态转为 BUSY: deviceId={}, orderId={}", deviceId,
|
||||
orderId);
|
||||
break;
|
||||
|
||||
case CONFIRMED:
|
||||
@@ -128,7 +158,8 @@ public class BadgeDeviceStatusEventListener {
|
||||
if (urgentOrderId != null) {
|
||||
// P0 打断场景:不修改设备状态,保持当前状态
|
||||
// 紧接着会有 P0 工单的 DISPATCHED 事件,将当前工单更新为 P0 工单
|
||||
log.info("[BadgeDeviceStatusEventListener] P0打断场景,工单已暂停,等待P0工单派发: pausedOrderId={}, urgentOrderId={}, deviceId={}",
|
||||
log.info(
|
||||
"[BadgeDeviceStatusEventListener] P0打断场景,工单已暂停,等待P0工单派发: pausedOrderId={}, urgentOrderId={}, deviceId={}",
|
||||
orderId, urgentOrderId, deviceId);
|
||||
} else {
|
||||
// 普通暂停场景:设备状态转为 PAUSED
|
||||
@@ -174,7 +205,8 @@ public class BadgeDeviceStatusEventListener {
|
||||
}
|
||||
} else {
|
||||
// 取消的不是当前工单(可能是队列中的等待任务),不需要修改设备状态
|
||||
log.debug("[BadgeDeviceStatusEventListener] 取消的工单非当前执行工单,跳过设备状态更新: cancelledOrderId={}, currentOrderId={}, deviceId={}",
|
||||
log.debug(
|
||||
"[BadgeDeviceStatusEventListener] 取消的工单非当前执行工单,跳过设备状态更新: cancelledOrderId={}, currentOrderId={}, deviceId={}",
|
||||
orderId, currentOrderId, deviceId);
|
||||
}
|
||||
break;
|
||||
@@ -207,8 +239,7 @@ public class BadgeDeviceStatusEventListener {
|
||||
orderId,
|
||||
event.getNewStatus().getStatus(),
|
||||
areaId,
|
||||
beaconMac
|
||||
);
|
||||
beaconMac);
|
||||
|
||||
log.debug("[BadgeDeviceStatusEventListener] 设备工单信息已更新: deviceId={}, orderId={}, areaId={}, beaconMac={}",
|
||||
deviceId, orderId, areaId, beaconMac);
|
||||
@@ -242,4 +273,3 @@ public class BadgeDeviceStatusEventListener {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -539,7 +539,7 @@ public class CleanOrderEventListener {
|
||||
|
||||
// 1. 语音播报 - 通知保洁员工单已完成
|
||||
if (deviceId != null) {
|
||||
playVoice(deviceId, CleanNotificationConstants.VoiceTemplate.ORDER_COMPLETED);
|
||||
playVoice(deviceId, CleanNotificationConstants.VoiceTemplate.ORDER_COMPLETED, orderId);
|
||||
}
|
||||
|
||||
// 2. 发送站内信(给管理员)
|
||||
@@ -569,8 +569,15 @@ public class CleanOrderEventListener {
|
||||
* 语音播报
|
||||
*/
|
||||
private void playVoice(Long deviceId, String message) {
|
||||
playVoice(deviceId, message, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 语音播报(带工单ID)
|
||||
*/
|
||||
private void playVoice(Long deviceId, String message, Long orderId) {
|
||||
try {
|
||||
voiceBroadcastService.broadcast(deviceId, message);
|
||||
voiceBroadcastService.broadcast(deviceId, message, orderId);
|
||||
log.debug("[语音播报] 调用成功: deviceId={}, message={}", deviceId, message);
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
package com.viewsh.module.ops.environment.job;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.viewsh.framework.tenant.core.job.TenantJob;
|
||||
import com.viewsh.module.ops.api.badge.BadgeDeviceStatusDTO;
|
||||
import com.viewsh.module.ops.core.dispatch.DispatchEngine;
|
||||
import com.viewsh.module.ops.core.dispatch.model.DispatchResult;
|
||||
import com.viewsh.module.ops.dal.dataobject.workorder.OpsOrderDO;
|
||||
import com.viewsh.module.ops.dal.mysql.workorder.OpsOrderMapper;
|
||||
import com.viewsh.module.ops.enums.BadgeDeviceStatusEnum;
|
||||
import com.viewsh.module.ops.enums.WorkOrderStatusEnum;
|
||||
import com.viewsh.module.ops.environment.service.badge.BadgeDeviceStatusService;
|
||||
import com.viewsh.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import com.xxl.job.core.handler.annotation.XxlJob;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 空闲设备待办工单检查 Job
|
||||
* <p>
|
||||
* 职责:
|
||||
* 1. 每15分钟扫描所有IDLE状态的设备
|
||||
* 2. 检查设备是否有QUEUED状态的待办工单
|
||||
* 3. 如有,自动推送第一条工单
|
||||
* <p>
|
||||
* 场景:
|
||||
* - 工单完成后自动调度失败的补偿
|
||||
* - 设备上线后有待办但未自动推送的补偿
|
||||
* - 消息丢失导致未推送的兜底检查
|
||||
* <p>
|
||||
* XXL-Job 配置:
|
||||
* - JobHandler: idleDevicePendingOrderCheckJob
|
||||
* - Cron: 0 0/15 * * * ? (每 15 分钟)
|
||||
*
|
||||
* @author AI
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class IdleDevicePendingOrderCheckJob {
|
||||
|
||||
@Resource
|
||||
private BadgeDeviceStatusService badgeDeviceStatusService;
|
||||
|
||||
@Resource
|
||||
private OpsOrderMapper opsOrderMapper;
|
||||
|
||||
@Resource
|
||||
private DispatchEngine dispatchEngine;
|
||||
|
||||
/**
|
||||
* 执行空闲设备待办检查
|
||||
* <p>
|
||||
* XXL-Job 调度入口
|
||||
*
|
||||
* @return 执行结果
|
||||
*/
|
||||
@XxlJob("idleDevicePendingOrderCheckJob")
|
||||
@TenantJob
|
||||
public String execute() {
|
||||
try {
|
||||
CheckResult result = checkAndDispatchPendingOrders();
|
||||
return StrUtil.format("空闲设备待办检查完成: 检查 {} 台空闲设备,发现 {} 台有待办,成功推送 {} 个工单,耗时 {} ms",
|
||||
result.idleDeviceCount, result.deviceWithPendingCount, result.dispatchedCount, result.durationMs);
|
||||
} catch (Exception e) {
|
||||
log.error("[IdleDevicePendingOrderCheckJob] 执行失败", e);
|
||||
return StrUtil.format("空闲设备待办检查失败: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查并推送待办工单
|
||||
*
|
||||
* @return 检查结果
|
||||
*/
|
||||
public CheckResult checkAndDispatchPendingOrders() {
|
||||
log.info("[IdleDevicePendingOrderCheckJob] 开始检查空闲设备待办工单");
|
||||
long startTime = System.currentTimeMillis();
|
||||
int idleDeviceCount = 0;
|
||||
int deviceWithPendingCount = 0;
|
||||
int dispatchedCount = 0;
|
||||
|
||||
// 1. 获取所有空闲状态的设备
|
||||
List<BadgeDeviceStatusDTO> idleDevices = badgeDeviceStatusService.listActiveBadges().stream()
|
||||
.filter(dto -> dto.getStatus() == BadgeDeviceStatusEnum.IDLE)
|
||||
.toList();
|
||||
|
||||
if (CollUtil.isEmpty(idleDevices)) {
|
||||
log.info("[IdleDevicePendingOrderCheckJob] 无空闲设备,跳过检查");
|
||||
return new CheckResult(0, 0, 0, System.currentTimeMillis() - startTime);
|
||||
}
|
||||
|
||||
idleDeviceCount = idleDevices.size();
|
||||
log.info("[IdleDevicePendingOrderCheckJob] 发现 {} 台空闲设备,开始检查待办工单", idleDeviceCount);
|
||||
|
||||
// 2. 逐个检查是否有待办工单
|
||||
for (BadgeDeviceStatusDTO deviceStatus : idleDevices) {
|
||||
Long deviceId = deviceStatus.getDeviceId();
|
||||
try {
|
||||
// 查询该设备的待办工单(QUEUED状态,按优先级和时间排序)
|
||||
OpsOrderDO pendingOrder = opsOrderMapper.selectOne(new LambdaQueryWrapperX<OpsOrderDO>()
|
||||
.eq(OpsOrderDO::getAssigneeDeviceId, deviceId)
|
||||
.eq(OpsOrderDO::getStatus, WorkOrderStatusEnum.QUEUED.getStatus())
|
||||
.orderByAsc(OpsOrderDO::getPriority) // 优先级高的排前面
|
||||
.orderByAsc(OpsOrderDO::getCreateTime) // 时间早的排前面
|
||||
.last("LIMIT 1"));
|
||||
|
||||
if (pendingOrder != null) {
|
||||
deviceWithPendingCount++;
|
||||
log.info("[IdleDevicePendingOrderCheckJob] 发现空闲设备有待办工单: deviceId={}, orderId={}, orderCode={}",
|
||||
deviceId, pendingOrder.getId(), pendingOrder.getOrderCode());
|
||||
|
||||
// 3. 自动推送工单
|
||||
DispatchResult result = dispatchEngine.autoDispatchNext(null, deviceId);
|
||||
if (result.isSuccess()) {
|
||||
dispatchedCount++;
|
||||
log.info("[IdleDevicePendingOrderCheckJob] 自动推送成功: deviceId={}, orderId={}",
|
||||
deviceId, pendingOrder.getId());
|
||||
} else {
|
||||
log.warn("[IdleDevicePendingOrderCheckJob] 自动推送失败: deviceId={}, reason={}",
|
||||
deviceId, result.getMessage());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("[IdleDevicePendingOrderCheckJob] 检查设备待办失败: deviceId={}", deviceId, e);
|
||||
}
|
||||
}
|
||||
|
||||
long duration = System.currentTimeMillis() - startTime;
|
||||
log.info("[IdleDevicePendingOrderCheckJob] 检查完成: 空闲设备 {} 台,有待办 {} 台,成功推送 {} 个,耗时 {} ms",
|
||||
idleDeviceCount, deviceWithPendingCount, dispatchedCount, duration);
|
||||
|
||||
return new CheckResult(idleDeviceCount, deviceWithPendingCount, dispatchedCount, duration);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查结果
|
||||
*/
|
||||
public record CheckResult(int idleDeviceCount, int deviceWithPendingCount, int dispatchedCount, long durationMs) {
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,8 @@ import cn.hutool.core.map.MapUtil;
|
||||
import com.viewsh.module.iot.api.device.IotDeviceControlApi;
|
||||
import com.viewsh.module.iot.api.device.dto.IotDeviceServiceInvokeReqDTO;
|
||||
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 jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -75,7 +77,14 @@ public class VoiceBroadcastService {
|
||||
* @param text 播报文本
|
||||
*/
|
||||
public void broadcast(Long deviceId, String text) {
|
||||
broadcast(deviceId, text, TTS_FLAG_URGENT);
|
||||
broadcast(deviceId, text, TTS_FLAG_URGENT, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 播报语音(带工单ID)
|
||||
*/
|
||||
public void broadcast(Long deviceId, String text, Long orderId) {
|
||||
broadcast(deviceId, text, TTS_FLAG_URGENT, orderId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,6 +95,18 @@ public class VoiceBroadcastService {
|
||||
* @param ttsFlag 播报标志(0x01=静默, 0x08=普通, 0x09=紧急)
|
||||
*/
|
||||
public void broadcast(Long deviceId, String text, int ttsFlag) {
|
||||
broadcast(deviceId, text, ttsFlag, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 播报语音(指定播报类型和工单ID)
|
||||
*
|
||||
* @param deviceId 设备ID
|
||||
* @param text 播报文本
|
||||
* @param ttsFlag 播报标志
|
||||
* @param orderId 工单ID(可选)
|
||||
*/
|
||||
public void broadcast(Long deviceId, String text, int ttsFlag, Long orderId) {
|
||||
if (deviceId == null || text == null) {
|
||||
return;
|
||||
}
|
||||
@@ -104,15 +125,38 @@ public class VoiceBroadcastService {
|
||||
deviceId, text, Integer.toHexString(ttsFlag));
|
||||
|
||||
// 记录日志
|
||||
eventLogRecorder.info("clean", EventDomain.DEVICE, "TTS_SENT",
|
||||
"语音播报: " + text, deviceId);
|
||||
if (orderId != null) {
|
||||
eventLogRecorder.info("clean", EventDomain.DEVICE, "TTS_SENT",
|
||||
"语音播报: " + text, orderId, deviceId, null);
|
||||
} else {
|
||||
eventLogRecorder.info("clean", EventDomain.DEVICE, "TTS_SENT",
|
||||
"语音播报: " + text, deviceId);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("[VoiceBroadcast] 播报失败: deviceId={}, text={}", deviceId, text, e);
|
||||
|
||||
// 记录错误日志
|
||||
eventLogRecorder.error("clean", EventDomain.DEVICE, "TTS_FAILED",
|
||||
"语音播报失败: " + e.getMessage(), deviceId, e);
|
||||
if (orderId != null) {
|
||||
eventLogRecorder.error("clean", EventDomain.DEVICE, "TTS_FAILED",
|
||||
"语音播报失败: " + e.getMessage(), deviceId, e); // error方法目前没有支持orderId的重载,或者需要检查一下
|
||||
// 检查 EventLogRecorder 接口,error 方法可能有带 orderId 的重载吗?
|
||||
// 刚才看 EventLogRecorderImpl 好像没有特别全的重载,或者我需要用 record() 方法手动构建
|
||||
// 让我先用简单方式,error 日志暂时不强求 orderId,或者手动构建
|
||||
eventLogRecorder.record(EventLogRecord.builder()
|
||||
.module("clean")
|
||||
.domain(EventDomain.DEVICE)
|
||||
.eventType("TTS_FAILED")
|
||||
.message("语音播报失败: " + e.getMessage())
|
||||
.targetId(orderId)
|
||||
.targetType("order")
|
||||
.deviceId(deviceId)
|
||||
.level(EventLevel.ERROR)
|
||||
.build());
|
||||
} else {
|
||||
eventLogRecorder.error("clean", EventDomain.DEVICE, "TTS_FAILED",
|
||||
"语音播报失败: " + e.getMessage(), deviceId, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +181,11 @@ public class VoiceBroadcastService {
|
||||
* @param text 播报文本
|
||||
*/
|
||||
public void broadcastUrgent(Long deviceId, String text) {
|
||||
broadcast(deviceId, text, TTS_FLAG_URGENT);
|
||||
broadcast(deviceId, text, TTS_FLAG_URGENT, null);
|
||||
}
|
||||
|
||||
public void broadcastUrgent(Long deviceId, String text, Long orderId) {
|
||||
broadcast(deviceId, text, TTS_FLAG_URGENT, orderId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -112,6 +112,11 @@ public class EventLogRecord {
|
||||
*/
|
||||
private String targetType;
|
||||
|
||||
/**
|
||||
* 工单ID(便于直接关联查询)
|
||||
*/
|
||||
private Long orderId;
|
||||
|
||||
// ==================== 扩展字段 ====================
|
||||
|
||||
/**
|
||||
@@ -181,7 +186,7 @@ public class EventLogRecord {
|
||||
* 创建设备事件日志
|
||||
*/
|
||||
public static EventLogRecord forDevice(String module, EventDomain domain, String eventType,
|
||||
String message, Long deviceId) {
|
||||
String message, Long deviceId) {
|
||||
return EventLogRecord.builder()
|
||||
.module(module)
|
||||
.domain(domain)
|
||||
@@ -195,7 +200,7 @@ public class EventLogRecord {
|
||||
* 创建工单事件日志
|
||||
*/
|
||||
public static EventLogRecord forOrder(String module, EventDomain domain, String eventType,
|
||||
String message, Long orderId, Long deviceId, Long personId) {
|
||||
String message, Long orderId, Long deviceId, Long personId) {
|
||||
return EventLogRecord.builder()
|
||||
.module(module)
|
||||
.domain(domain)
|
||||
@@ -212,7 +217,7 @@ public class EventLogRecord {
|
||||
* 创建系统事件日志
|
||||
*/
|
||||
public static EventLogRecord forSystem(String module, EventDomain domain, String eventType,
|
||||
String message) {
|
||||
String message) {
|
||||
return EventLogRecord.builder()
|
||||
.module(module)
|
||||
.domain(domain)
|
||||
|
||||
@@ -8,6 +8,8 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 事件日志记录器实现
|
||||
* <p>
|
||||
@@ -31,7 +33,6 @@ public class EventLogRecorderImpl implements EventLogRecorder {
|
||||
@Resource
|
||||
private EventLogPersister persister;
|
||||
|
||||
|
||||
/**
|
||||
* 异步记录日志(默认方式)
|
||||
* <p>
|
||||
@@ -110,7 +111,7 @@ public class EventLogRecorderImpl implements EventLogRecorder {
|
||||
|
||||
@Override
|
||||
public void info(String module, EventDomain domain, String eventType, String message,
|
||||
Long orderId, Long deviceId, Long personId) {
|
||||
Long orderId, Long deviceId, Long personId) {
|
||||
record(EventLogRecord.builder()
|
||||
.module(module)
|
||||
.domain(domain)
|
||||
@@ -165,7 +166,7 @@ public class EventLogRecorderImpl implements EventLogRecorder {
|
||||
|
||||
@Override
|
||||
public void error(String module, EventDomain domain, String eventType, String message,
|
||||
Long deviceId, Throwable throwable) {
|
||||
Long deviceId, Throwable throwable) {
|
||||
EventLogRecord record = EventLogRecord.builder()
|
||||
.module(module)
|
||||
.domain(domain)
|
||||
@@ -185,6 +186,12 @@ public class EventLogRecorderImpl implements EventLogRecorder {
|
||||
* 转换为 DO
|
||||
*/
|
||||
private OpsBusinessEventLogDO convertToDO(EventLogRecord record) {
|
||||
// payload 为空或空 Map 时设为 null,避免存储 {}
|
||||
Map<String, Object> payload = record.getPayload();
|
||||
if (payload != null && payload.isEmpty()) {
|
||||
payload = null;
|
||||
}
|
||||
|
||||
return OpsBusinessEventLogDO.builder()
|
||||
.eventTime(record.getEventTime())
|
||||
.eventLevel(record.getLevel() != null ? record.getLevel().getCode() : EventLevel.INFO.getCode())
|
||||
@@ -202,7 +209,7 @@ public class EventLogRecorderImpl implements EventLogRecorder {
|
||||
.targetType(record.getTargetType())
|
||||
.eventMessage(record.getMessage())
|
||||
.eventSummary(record.getSummary())
|
||||
.eventPayload(record.getPayload())
|
||||
.eventPayload(payload)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -228,10 +235,12 @@ public class EventLogRecorderImpl implements EventLogRecorder {
|
||||
*/
|
||||
private void logConsole(EventLogRecord record) {
|
||||
String deviceInfo = record.getDeviceId() != null
|
||||
? " [设备:" + record.getDeviceId() + (record.getDeviceName() != null ? "(" + record.getDeviceName() + ")" : "") + "]"
|
||||
? " [设备:" + record.getDeviceId()
|
||||
+ (record.getDeviceName() != null ? "(" + record.getDeviceName() + ")" : "") + "]"
|
||||
: "";
|
||||
String personInfo = record.getPersonId() != null
|
||||
? " [人员:" + record.getPersonId() + (record.getPersonName() != null ? "(" + record.getPersonName() + ")" : "") + "]"
|
||||
? " [人员:" + record.getPersonId()
|
||||
+ (record.getPersonName() != null ? "(" + record.getPersonName() + ")" : "") + "]"
|
||||
: "";
|
||||
String targetInfo = record.getTargetId() != null
|
||||
? " [" + record.getTargetType() + ":" + record.getTargetId() + "]"
|
||||
|
||||
Reference in New Issue
Block a user