feat(ops): 新增业务日志枚举类

- 新增 EventDomain:事件领域枚举
- 新增 EventLevel:事件级别枚举

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
lzh
2026-01-21 18:43:32 +08:00
parent c88dc3fc10
commit a82b59ac46
9 changed files with 1012 additions and 0 deletions

View File

@@ -0,0 +1,138 @@
package com.viewsh.module.ops.dal.dataobject.log;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import com.viewsh.framework.mybatis.core.dataobject.BaseDO;
import lombok.*;
import java.time.LocalDateTime;
import java.util.Map;
/**
* 通用业务事件日志 DO
* <p>
* 用于记录所有模块的业务事件日志支持多模块clean/repair/patrol等
* 采用方案A在记录时<E5BD95><E697B6>步填充设备/人员名称冗余字段,便于展示时直接查询
*
* @author lzh
*/
@TableName(value = "ops_business_event_log", autoResultMap = true)
@KeySequence("ops_business_event_log_seq")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class OpsBusinessEventLogDO extends BaseDO {
// ==================== 主键 ====================
/**
* 主键ID
*/
@TableId
private Long id;
// ==================== 时间与级别 ====================
/**
* 事件时间
*/
private LocalDateTime eventTime;
/**
* 日志级别INFO=信息/WARN=警告/ERROR=错误)
*/
private String eventLevel;
// ==================== 业务分类 ====================
/**
* 模块标识clean=保洁/repair=维修/patrol=巡检)
*/
private String module;
/**
* 事件域DISPATCH=调度/BEACON=信标/TRAFFIC=客流/DEVICE=设备/SYSTEM=系统/AUDIT=审计)
*/
private String eventDomain;
/**
* 事件类型ARRIVE_CONFIRMED/TTS_SENT/AUTO_DISPATCH
*/
private String eventType;
// ==================== 设备关联 ====================
/**
* 设备ID关联 iot_device.id
*/
private Long deviceId;
/**
* 设备名称(冗余字段,异步填充)
*/
private String deviceName;
/**
* 设备编码(冗余字段,如设备序列号)
*/
private String deviceCode;
/**
* 设备类型冗余字段BADGE/TRAFFIC_COUNTER/BEACON
*/
private String deviceType;
// ==================== 人员关联 ====================
/**
* 人员ID保洁员/巡检员等)
*/
private Long personId;
/**
* 人员姓名(冗余字段,异步填充)
*/
private String personName;
/**
* 人员类型冗余字段CLEANER/INSPECTOR
*/
private String personType;
// ==================== 业务实体关联 ====================
/**
* 业务实体ID如工单ID、区域ID
*/
private Long targetId;
/**
* 业务实体类型order=工单/area=区域/task=任务)
*/
private String targetType;
// ==================== 日志内容 ====================
/**
* 事件描述(完整描述)
*/
private String eventMessage;
/**
* 简要摘要(用于列表展示,可选)
*/
private String eventSummary;
/**
* 扩展数据JSON格式存储额外结构化信息
*/
@TableField(typeHandler = JacksonTypeHandler.class)
private Map<String, Object> eventPayload;
}

View File

@@ -0,0 +1,125 @@
package com.viewsh.module.ops.dal.mysql.log;
import com.viewsh.framework.mybatis.core.mapper.BaseMapperX;
import com.viewsh.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.viewsh.module.ops.dal.dataobject.log.OpsBusinessEventLogDO;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* 通用业务事件日志 Mapper
*
* @author lzh
*/
@Mapper
public interface OpsBusinessEventLogMapper extends BaseMapperX<OpsBusinessEventLogDO> {
/**
* 根据模块查询日志
*
* @param module 模块标识clean/repair/patrol
* @return 日志列表
*/
default List<OpsBusinessEventLogDO> selectListByModule(String module) {
return selectList(new LambdaQueryWrapperX<OpsBusinessEventLogDO>()
.eq(OpsBusinessEventLogDO::getModule, module)
.orderByDesc(OpsBusinessEventLogDO::getEventTime));
}
/**
* 根据模块和事件域查询日志
*
* @param module 模块标识
* @param eventDomain 事件域
* @return 日志列表
*/
default List<OpsBusinessEventLogDO> selectListByModuleAndDomain(String module, String eventDomain) {
return selectList(new LambdaQueryWrapperX<OpsBusinessEventLogDO>()
.eq(OpsBusinessEventLogDO::getModule, module)
.eq(OpsBusinessEventLogDO::getEventDomain, eventDomain)
.orderByDesc(OpsBusinessEventLogDO::getEventTime));
}
/**
* 根据设备ID查询日志
*
* @param deviceId 设备ID
* @return 日志列表
*/
default List<OpsBusinessEventLogDO> selectListByDeviceId(Long deviceId) {
return selectList(new LambdaQueryWrapperX<OpsBusinessEventLogDO>()
.eq(OpsBusinessEventLogDO::getDeviceId, deviceId)
.orderByDesc(OpsBusinessEventLogDO::getEventTime));
}
/**
* 根据人员ID查询日志
*
* @param personId 人员ID
* @return 日志列表
*/
default List<OpsBusinessEventLogDO> selectListByPersonId(Long personId) {
return selectList(new LambdaQueryWrapperX<OpsBusinessEventLogDO>()
.eq(OpsBusinessEventLogDO::getPersonId, personId)
.orderByDesc(OpsBusinessEventLogDO::getEventTime));
}
/**
* 根据目标实体查询日志
*
* @param targetType 目标类型order/area/task
* @param targetId 目标ID
* @return 日志列表
*/
default List<OpsBusinessEventLogDO> selectListByTarget(String targetType, Long targetId) {
return selectList(new LambdaQueryWrapperX<OpsBusinessEventLogDO>()
.eq(OpsBusinessEventLogDO::getTargetType, targetType)
.eq(OpsBusinessEventLogDO::getTargetId, targetId)
.orderByDesc(OpsBusinessEventLogDO::getEventTime));
}
/**
* 根据工单ID查询日志
*
* @param orderId 工单ID
* @return 日志列表
*/
default List<OpsBusinessEventLogDO> selectListByOrderId(Long orderId) {
return selectList(new LambdaQueryWrapperX<OpsBusinessEventLogDO>()
.eq(OpsBusinessEventLogDO::getTargetType, "order")
.eq(OpsBusinessEventLogDO::getTargetId, orderId)
.orderByDesc(OpsBusinessEventLogDO::getEventTime));
}
/**
* 根据事件域和类型查询日志
*
* @param eventDomain 事件域
* @param eventType 事件类型
* @return 日志列表
*/
default List<OpsBusinessEventLogDO> selectListByDomainAndType(String eventDomain, String eventType) {
return selectList(new LambdaQueryWrapperX<OpsBusinessEventLogDO>()
.eq(OpsBusinessEventLogDO::getEventDomain, eventDomain)
.eq(OpsBusinessEventLogDO::getEventType, eventType)
.orderByDesc(OpsBusinessEventLogDO::getEventTime));
}
/**
* 根据模块、事件域和类型查询日志
*
* @param module 模块标识
* @param eventDomain 事件域
* @param eventType 事件类型
* @return 日志列表
*/
default List<OpsBusinessEventLogDO> selectListByModuleDomainAndType(String module, String eventDomain, String eventType) {
return selectList(new LambdaQueryWrapperX<OpsBusinessEventLogDO>()
.eq(OpsBusinessEventLogDO::getModule, module)
.eq(OpsBusinessEventLogDO::getEventDomain, eventDomain)
.eq(OpsBusinessEventLogDO::getEventType, eventType)
.orderByDesc(OpsBusinessEventLogDO::getEventTime));
}
}

View File

@@ -0,0 +1,57 @@
package com.viewsh.module.ops.infrastructure.log.enumeration;
/**
* 事件域枚举
* <p>
* 用于标识业务事件发生的领域/模块
*
* @author lzh
*/
public enum EventDomain {
/**
* 调度域 - 工单派发、分配等
*/
DISPATCH("dispatch", "调度"),
/**
* 信标域 - 信标检测、到岗确认等
*/
BEACON("beacon", "信标"),
/**
* 客流域 - 客流统计、阈值触发等
*/
TRAFFIC("traffic", "客流"),
/**
* 设备域 - 设备控制、TTS<54><53>震动等
*/
DEVICE("device", "设备"),
/**
* 系统域 - 系统级事件
*/
SYSTEM("system", "系统"),
/**
* 审计域 - 审计日志
*/
AUDIT("audit", "审计");
private final String code;
private final String description;
EventDomain(String code, String description) {
this.code = code;
this.description = description;
}
public String getCode() {
return code;
}
public String getDescription() {
return description;
}
}

View File

@@ -0,0 +1,40 @@
package com.viewsh.module.ops.infrastructure.log.enumeration;
/**
* 事件日志级别枚举
*
* @author lzh
*/
public enum EventLevel {
/**
* 信息级别 - 正常业务流程
*/
INFO("INFO", "信息"),
/**
* 警告级别 - 需要关注但不影响流程
*/
WARN("WARN", "警告"),
/**
* 错误级别 - 业务异常或失败
*/
ERROR("ERROR", "错误");
private final String code;
private final String description;
EventLevel(String code, String description) {
this.code = code;
this.description = description;
}
public String getCode() {
return code;
}
public String getDescription() {
return description;
}
}

View File

@@ -0,0 +1,29 @@
package com.viewsh.module.ops.infrastructure.log.recorder;
import com.viewsh.module.ops.dal.dataobject.log.OpsBusinessEventLogDO;
/**
* 事件日志持久化接口
* <p>
* 负责将日志记录持久化到数据库
*
* @author lzh
*/
public interface EventLogPersister {
/**
* 持久化日志记录(同步)
*
* @param recordDO 日志DO
* @return 是否成功
*/
boolean persist(OpsBusinessEventLogDO recordDO);
/**
* 持久化日志记录(异步)
*
* @param recordDO 日志DO
*/
void persistAsync(OpsBusinessEventLogDO recordDO);
}

View File

@@ -0,0 +1,40 @@
package com.viewsh.module.ops.infrastructure.log.recorder;
import com.viewsh.module.ops.dal.dataobject.log.OpsBusinessEventLogDO;
import com.viewsh.module.ops.dal.mysql.log.OpsBusinessEventLogMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
/**
* 事件日志持久化实现
*
* @author lzh
*/
@Slf4j
@Component
public class EventLogPersisterImpl implements EventLogPersister {
@Resource
private OpsBusinessEventLogMapper eventLogMapper;
@Override
public boolean persist(OpsBusinessEventLogDO recordDO) {
try {
int rows = eventLogMapper.insert(recordDO);
return rows > 0;
} catch (Exception e) {
log.error("[EventLogPersister] 持久化失败: module={}, domain={}, type={}",
recordDO.getModule(), recordDO.getEventDomain(), recordDO.getEventType(), e);
return false;
}
}
@Override
@Async("ops-task-executor")
public void persistAsync(OpsBusinessEventLogDO recordDO) {
persist(recordDO);
}
}

View File

@@ -0,0 +1,223 @@
package com.viewsh.module.ops.infrastructure.log.recorder;
import com.viewsh.module.ops.infrastructure.log.enumeration.EventDomain;
import com.viewsh.module.ops.infrastructure.log.enumeration.EventLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
/**
* 事件日志记录实体
* <p>
* 用于记录业务事件日志,包含设备、人员、业务实体的关联信息
* 采用方案A在记录时异步填充名称冗余字段便于展示时直接查询
*
* @author lzh
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class EventLogRecord {
// ==================== 基础分类字段 ====================
/**
* 模块标识clean, repair, patrol
*/
private String module;
/**
* 事件域
*/
private EventDomain domain;
/**
* 事件类型ARRIVE_CONFIRMED, TTS_SENT, AUTO_DISPATCH
*/
private String eventType;
/**
* 日志级别
*/
@Builder.Default
private EventLevel level = EventLevel.INFO;
// ==================== 内容字段 ====================
/**
* 事件描述(完整描述)
*/
private String message;
/**
* 简要摘要(用于列表展示,可选)
*/
private String summary;
// ==================== 设备关联字段 ====================
/**
* 设备ID
*/
private Long deviceId;
/**
* 设备名称(冗余字段,异步填充)
*/
private String deviceName;
/**
* 设备编码(冗余字段,如设备序列号)
*/
private String deviceCode;
/**
* 设备类型冗余字段BADGE, TRAFFIC_COUNTER
*/
private String deviceType;
// ==================== 人员关联字段 ====================
/**
* 人员ID保洁员、巡检员等
*/
private Long personId;
/**
* 人员姓名(冗余字段,异步填充)
*/
private String personName;
/**
* 人员类型冗余字段CLEANER, INSPECTOR
*/
private String personType;
// ==================== 业务实体关联字段 ====================
/**
* 业务实体ID如工单ID、区域ID
*/
private Long targetId;
/**
* 业务实体类型order, area, task
*/
private String targetType;
// ==================== 扩展字段 ====================
/**
* 扩展数据JSON格式
*/
@Builder.Default
private Map<String, Object> payload = new HashMap<>();
/**
* 事件时间
*/
@Builder.Default
private LocalDateTime eventTime = LocalDateTime.now();
// ==================== 便捷方法 ====================
/**
* 添加扩展数据
*/
public void putPayload(String key, Object value) {
if (this.payload == null) {
this.payload = new HashMap<>();
}
this.payload.put(key, value);
}
/**
* 获取扩展数据
*/
public Object getPayload(String key) {
return payload != null ? payload.get(key) : null;
}
/**
* 获取扩展数据String类型
*/
public String getPayloadString(String key) {
Object value = getPayload(key);
return value != null ? String.valueOf(value) : null;
}
/**
* 获取扩展数据Long类型
*/
public Long getPayloadLong(String key) {
Object value = getPayload(key);
if (value instanceof Number) {
return ((Number) value).longValue();
}
return null;
}
/**
* 获取扩展数据Integer类型
*/
public Integer getPayloadInt(String key) {
Object value = getPayload(key);
if (value instanceof Number) {
return ((Number) value).intValue();
}
return null;
}
// ==================== 静态构建方法 ====================
/**
* 创建设备事件日志
*/
public static EventLogRecord forDevice(String module, EventDomain domain, String eventType,
String message, Long deviceId) {
return EventLogRecord.builder()
.module(module)
.domain(domain)
.eventType(eventType)
.message(message)
.deviceId(deviceId)
.build();
}
/**
* 创建工单事件日志
*/
public static EventLogRecord forOrder(String module, EventDomain domain, String eventType,
String message, Long orderId, Long deviceId, Long personId) {
return EventLogRecord.builder()
.module(module)
.domain(domain)
.eventType(eventType)
.message(message)
.targetId(orderId)
.targetType("order")
.deviceId(deviceId)
.personId(personId)
.build();
}
/**
* 创建系统事件日志
*/
public static EventLogRecord forSystem(String module, EventDomain domain, String eventType,
String message) {
return EventLogRecord.builder()
.module(module)
.domain(domain)
.eventType(eventType)
.message(message)
.build();
}
}

View File

@@ -0,0 +1,110 @@
package com.viewsh.module.ops.infrastructure.log.recorder;
import com.viewsh.module.ops.infrastructure.log.enumeration.EventDomain;
/**
* 事件日志记录器接口
* <p>
* 提供业务事件日志记录的统一入口
*
* @author lzh
*/
public interface EventLogRecorder {
/**
* 记录事件日志(同步)
*
* @param record 日志记录
*/
void record(EventLogRecord record);
/**
* 记录事件日志(异步)
*
* @param record 日志记录
*/
void recordAsync(EventLogRecord record);
// ==================== 便捷方法:按级别记录 ====================
/**
* 记录信息级别日志
*
* @param module 模块标识
* @param domain 事件域
* @param eventType 事件类型
* @param message 事件消息
*/
void info(String module, EventDomain domain, String eventType, String message);
/**
* 记录信息级别日志(带设备关联)
*
* @param module 模块标识
* @param domain 事件域
* @param eventType 事件类型
* @param message 事件消息
* @param deviceId 设备ID
*/
void info(String module, EventDomain domain, String eventType, String message, Long deviceId);
/**
* 记录信息级别日志(带工单关联)
*
* @param module 模块标识
* @param domain 事件域
* @param eventType 事件类型
* @param message 事件消息
* @param orderId 工单ID
* @param deviceId 设备ID
* @param personId 人员ID
*/
void info(String module, EventDomain domain, String eventType, String message,
Long orderId, Long deviceId, Long personId);
/**
* 记录警告级别日志
*
* @param module 模块标识
* @param domain 事件域
* @param eventType 事件类型
* @param message 事件消息
*/
void warn(String module, EventDomain domain, String eventType, String message);
/**
* 记录警告级别日志(带设备关联)
*
* @param module 模块标识
* @param domain 事件域
* @param eventType 事件类型
* @param message 事件消息
* @param deviceId 设备ID
*/
void warn(String module, EventDomain domain, String eventType, String message, Long deviceId);
/**
* 记录错误级别日志
*
* @param module 模块标识
* @param domain 事件域
* @param eventType 事件类型
* @param message 事件消息
* @param throwable 异常信息
*/
void error(String module, EventDomain domain, String eventType, String message, Throwable throwable);
/**
* 记录错误级别日志(带设备关联)
*
* @param module 模块标识
* @param domain 事件域
* @param eventType 事件类型
* @param message 事件消息
* @param deviceId 设备ID
* @param throwable 异常信息
*/
void error(String module, EventDomain domain, String eventType, String message,
Long deviceId, Throwable throwable);
}

View File

@@ -0,0 +1,250 @@
package com.viewsh.module.ops.infrastructure.log.recorder;
import com.viewsh.module.ops.dal.dataobject.log.OpsBusinessEventLogDO;
import com.viewsh.module.ops.infrastructure.log.enumeration.EventDomain;
import com.viewsh.module.ops.infrastructure.log.enumeration.EventLevel;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
/**
* 事件日志记录器实现
* <p>
* 负责记录业务事件日志,包含:
* 1. 将 EventLogRecord 转换为 OpsBusinessEventLogDO
* 2. 异步填充设备/人员名称方案A冗余存储
* 3. 持久化到数据库
* 4. 输出到控制台(用于调试)
* <p>
* 设计说明:
* - record() 方法默认异步执行,不阻塞主业务流程
* - recordSync() 方法同步执行,用于需要确认日志写入成功的场景
* - recordAsync() 方法保留,语义更明确
*
* @author lzh
*/
@Slf4j
@Component
public class EventLogRecorderImpl implements EventLogRecorder {
@Resource
private EventLogPersister persister;
/**
* 异步记录日志(默认方式)
* <p>
* 使用 @Async 确保日志记录不阻塞主业务流程
*/
@Override
@Async("ops-task-executor")
public void record(EventLogRecord record) {
doRecord(record);
}
/**
* 异步记录日志(语义明确的方法名)
*/
@Override
@Async("ops-task-executor")
public void recordAsync(EventLogRecord record) {
doRecord(record);
}
/**
* 同步记录日志
* <p>
* 用于需要确认日志写入成功的场景(如测试、关键业务)
*/
public void recordSync(EventLogRecord record) {
doRecord(record);
}
/**
* 实际执行记录逻辑
*/
private void doRecord(EventLogRecord record) {
try {
// 转换为 DO
OpsBusinessEventLogDO recordDO = convertToDO(record);
// TODO: 方案A - 异步填充设备/人员名称
// 这里预留接口,后续通过 Feign 调用 IoT/Ops 模块获取名称
enrichRecord(recordDO);
// 持久化(同步写入,但在异步线程中执行)
persister.persist(recordDO);
// 控制台输出(便于调试)
logConsole(record);
} catch (Exception e) {
log.error("[EventLogRecorder] 记录失败: module={}, domain={}, type={}",
record.getModule(), record.getDomain(), record.getEventType(), e);
}
}
@Override
public void info(String module, EventDomain domain, String eventType, String message) {
record(EventLogRecord.builder()
.module(module)
.domain(domain)
.eventType(eventType)
.message(message)
.level(EventLevel.INFO)
.build());
}
@Override
public void info(String module, EventDomain domain, String eventType, String message, Long deviceId) {
record(EventLogRecord.builder()
.module(module)
.domain(domain)
.eventType(eventType)
.message(message)
.deviceId(deviceId)
.level(EventLevel.INFO)
.build());
}
@Override
public void info(String module, EventDomain domain, String eventType, String message,
Long orderId, Long deviceId, Long personId) {
record(EventLogRecord.builder()
.module(module)
.domain(domain)
.eventType(eventType)
.message(message)
.targetId(orderId)
.targetType("order")
.deviceId(deviceId)
.personId(personId)
.level(EventLevel.INFO)
.build());
}
@Override
public void warn(String module, EventDomain domain, String eventType, String message) {
record(EventLogRecord.builder()
.module(module)
.domain(domain)
.eventType(eventType)
.message(message)
.level(EventLevel.WARN)
.build());
}
@Override
public void warn(String module, EventDomain domain, String eventType, String message, Long deviceId) {
record(EventLogRecord.builder()
.module(module)
.domain(domain)
.eventType(eventType)
.message(message)
.deviceId(deviceId)
.level(EventLevel.WARN)
.build());
}
@Override
public void error(String module, EventDomain domain, String eventType, String message, Throwable throwable) {
EventLogRecord record = EventLogRecord.builder()
.module(module)
.domain(domain)
.eventType(eventType)
.message(message)
.level(EventLevel.ERROR)
.build();
if (throwable != null) {
record.putPayload("errorMessage", throwable.getMessage());
record.putPayload("errorClass", throwable.getClass().getSimpleName());
}
record(record);
}
@Override
public void error(String module, EventDomain domain, String eventType, String message,
Long deviceId, Throwable throwable) {
EventLogRecord record = EventLogRecord.builder()
.module(module)
.domain(domain)
.eventType(eventType)
.message(message)
.deviceId(deviceId)
.level(EventLevel.ERROR)
.build();
if (throwable != null) {
record.putPayload("errorMessage", throwable.getMessage());
record.putPayload("errorClass", throwable.getClass().getSimpleName());
}
record(record);
}
/**
* 转换为 DO
*/
private OpsBusinessEventLogDO convertToDO(EventLogRecord record) {
return OpsBusinessEventLogDO.builder()
.eventTime(record.getEventTime())
.eventLevel(record.getLevel() != null ? record.getLevel().getCode() : EventLevel.INFO.getCode())
.module(record.getModule())
.eventDomain(record.getDomain() != null ? record.getDomain().getCode() : null)
.eventType(record.getEventType())
.deviceId(record.getDeviceId())
.deviceName(record.getDeviceName())
.deviceCode(record.getDeviceCode())
.deviceType(record.getDeviceType())
.personId(record.getPersonId())
.personName(record.getPersonName())
.personType(record.getPersonType())
.targetId(record.getTargetId())
.targetType(record.getTargetType())
.eventMessage(record.getMessage())
.eventSummary(record.getSummary())
.eventPayload(record.getPayload())
.build();
}
/**
* 异步填充设备/人员名称方案A
* <p>
* TODO: 后续通过 Feign 调用以下接口异步填充:
* - IotDeviceApi.getBasicInfo(deviceId) -> 获取设备名称、编码、类型
* - CleanerService.getBasicInfo(personId) -> 获取人员姓名、类型
* <p>
* 当前先留空,待 Feign 接口创建后再补充
*/
private void enrichRecord(OpsBusinessEventLogDO recordDO) {
// 暂不实现异步填充,待后续完成 Feign 接口后再补充
// 设计时考虑:
// 1. 如果 recordDO.getDeviceId() 不为空,调用 IoT 模块获取设备信息
// 2. 如果 recordDO.getPersonId() 不为空,调用 Ops 模块获取人员信息
// 3. 填充冗余字段deviceName, deviceCode, deviceType, personName, personType
}
/**
* 控制台输出(便于调试)
*/
private void logConsole(EventLogRecord record) {
String deviceInfo = record.getDeviceId() != null
? " [设备:" + record.getDeviceId() + (record.getDeviceName() != null ? "(" + record.getDeviceName() + ")" : "") + "]"
: "";
String personInfo = record.getPersonId() != null
? " [人员:" + record.getPersonId() + (record.getPersonName() != null ? "(" + record.getPersonName() + ")" : "") + "]"
: "";
String targetInfo = record.getTargetId() != null
? " [" + record.getTargetType() + ":" + record.getTargetId() + "]"
: "";
log.info("[EventLog] [{}] {} {} {} - {}{}{}",
record.getLevel() != null ? record.getLevel().getCode() : "INFO",
record.getModule(),
record.getDomain() != null ? record.getDomain().getCode() : "UNKNOWN",
record.getEventType(),
record.getMessage(),
deviceInfo,
personInfo,
targetInfo);
}
}