feat(inspection): 添加巡检任务执行日志功能

- 创建巡检任务执行日志表结构,包含任务实例ID、点位信息、执行状态等字段
- 实现巡检任务执行日志的增删改查接口和业务逻辑
- 在巡检流程执行监听器中集成日志记录功能
- 添加巡检日志类型枚举类用于区分不同类型的日志
- 实现巡检任务执行过程中的实时日志记录和推送
- 提供批量插入日志的功能以提高性能
- 完成日志相关的控制器和数据访问层代码实现
This commit is contained in:
lixiaolong 2026-06-05 15:35:14 +08:00
parent f57c9b9dda
commit 43e491c0b6
9 changed files with 469 additions and 16 deletions

View File

@ -0,0 +1,85 @@
package com.cmvr.web.controller.inspection;
import com.cmvr.common.core.controller.BaseController;
import com.cmvr.common.core.domain.AjaxResult;
import com.cmvr.common.core.page.TableDataInfo;
import com.cmvr.inspection.domain.InspectionTaskLog;
import com.cmvr.inspection.service.IInspectionTaskLogService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 巡检任务执行日志Controller
*
* @author cmvr-iot
* @since 2026-06-05
*/
@Api(tags = "巡检任务执行日志管理")
@RestController
@RequestMapping("/inspection/taskLog")
public class InspectionTaskLogController extends BaseController
{
@Autowired
private IInspectionTaskLogService inspectionTaskLogService;
/**
* 查询巡检任务执行日志列表
*/
@ApiOperation("查询巡检任务执行日志列表")
@GetMapping("/list")
public TableDataInfo list(@ApiParam("任务实例ID") @RequestParam String taskInstanceId) {
startPage();
List<InspectionTaskLog> list = inspectionTaskLogService.selectInspectionTaskLogList(taskInstanceId);
return getDataTable(list);
}
/**
* 获取巡检任务执行日志详细信息
*/
@ApiOperation("获取巡检任务执行日志详细信息")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@ApiParam("日志ID") @PathVariable("id") String id) {
return success(inspectionTaskLogService.getById(id));
}
/**
* 新增巡检任务执行日志
*/
@ApiOperation("新增巡检任务执行日志")
@PostMapping
public AjaxResult add(@RequestBody InspectionTaskLog inspectionTaskLog) {
return toAjax(inspectionTaskLogService.insertInspectionTaskLog(inspectionTaskLog));
}
/**
* 批量新增巡检任务执行日志
*/
@ApiOperation("批量新增巡检任务执行日志")
@PostMapping("/batch")
public AjaxResult batchAdd(@RequestBody List<InspectionTaskLog> logList) {
return toAjax(inspectionTaskLogService.batchInsertInspectionTaskLog(logList));
}
/**
* 修改巡检任务执行日志
*/
@ApiOperation("修改巡检任务执行日志")
@PutMapping
public AjaxResult edit(@RequestBody InspectionTaskLog inspectionTaskLog) {
return toAjax(inspectionTaskLogService.updateById(inspectionTaskLog));
}
/**
* 删除巡检任务执行日志
*/
@ApiOperation("删除巡检任务执行日志")
@DeleteMapping("/{ids}")
public AjaxResult remove(@ApiParam("日志ID数组") @PathVariable String[] ids) {
return toAjax(inspectionTaskLogService.removeByIds(java.util.Arrays.asList(ids)));
}
}

View File

@ -0,0 +1,88 @@
package com.cmvr.inspection.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import com.cmvr.common.annotation.Excel;
import com.cmvr.common.core.domain.BaseEntity;
import java.util.Date;
/**
* 巡检任务执行日志对象 inspection_task_log
*
* @author cmvr-iot
* @since 2026-06-05
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
@Builder
@ApiModel("巡检任务执行日志")
public class InspectionTaskLog extends BaseEntity
{
private static final long serialVersionUID = 1L;
@ApiModelProperty("id")
@TableId(value = "id", type = IdType.ASSIGN_UUID)
private String id;
@Excel(name = "任务实例ID")
@ApiModelProperty("任务实例ID")
private String taskInstanceId;
@Excel(name = "任务ID")
@ApiModelProperty("任务ID")
private String taskId;
@Excel(name = "点位ID")
@ApiModelProperty("点位ID")
private String waypointId;
@Excel(name = "点位名称")
@ApiModelProperty("点位名称")
private String waypointName;
@Excel(name = "节点ID")
@ApiModelProperty("节点ID")
private String nodeId;
@Excel(name = "节点名称")
@ApiModelProperty("节点名称")
private String nodeName;
@Excel(name = "日志类型")
@ApiModelProperty("日志类型(1文字 2图片 3视频 4音频)")
private Integer logType;
@Excel(name = "日志内容")
@ApiModelProperty("日志内容/文字描述")
private String logContent;
@Excel(name = "媒体URL")
@ApiModelProperty("媒体文件URL(图片/视频/音频)")
private String mediaUrl;
@Excel(name = "状态")
@ApiModelProperty("执行状态(0待执行 1执行中 2已完成 3已取消 4执行失败 5已暂停)")
private Integer status;
@Excel(name = "进度")
@ApiModelProperty("执行进度(百分比)")
private String progress;
@Excel(name = "日志时间")
@ApiModelProperty("日志时间")
private Date logTime;
@Excel(name = "扩展信息")
@ApiModelProperty("扩展信息(JSON格式)")
private String extraInfo;
}

View File

@ -0,0 +1,31 @@
package com.cmvr.inspection.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 巡检任务日志类型枚举
*
* @author cmvr-iot
* @since 2026-06-05
*/
@Getter
@AllArgsConstructor
public enum InspectionLogTypeEnum {
TEXT(1, "文字"),
IMAGE(2, "图片"),
VIDEO(3, "视频"),
AUDIO(4, "音频");
private final int code;
private final String desc;
public static InspectionLogTypeEnum fromCode(int code) {
for (InspectionLogTypeEnum type : values()) {
if (type.code == code) {
return type;
}
}
return null;
}
}

View File

@ -1,12 +1,15 @@
package com.cmvr.inspection.listener; package com.cmvr.inspection.listener;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.cmvr.common.utils.DateUtils; import com.cmvr.common.utils.DateUtils;
import com.cmvr.framework.websocket.service.MessagePushService; import com.cmvr.framework.websocket.service.MessagePushService;
import com.cmvr.inspection.domain.InspectionTaskInstance; import com.cmvr.inspection.domain.InspectionTaskInstance;
import com.cmvr.inspection.domain.InspectionTaskLog;
import com.cmvr.inspection.enums.InspectionLogTypeEnum;
import com.cmvr.inspection.enums.TaskStatusEnum; import com.cmvr.inspection.enums.TaskStatusEnum;
import com.cmvr.inspection.service.IInspectionTaskInstanceService; import com.cmvr.inspection.service.IInspectionTaskInstanceService;
import com.cmvr.inspection.service.IInspectionTaskLogService;
import com.cmvr.test.flow.runtime.event.FlowExecutionEvent; import com.cmvr.test.flow.runtime.event.FlowExecutionEvent;
import com.cmvr.test.flow.runtime.event.FlowExecutionListener; import com.cmvr.test.flow.runtime.event.FlowExecutionListener;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -18,6 +21,7 @@ import java.util.*;
@Slf4j @Slf4j
public class InspectionFlowExecutionListener implements FlowExecutionListener { public class InspectionFlowExecutionListener implements FlowExecutionListener {
private final IInspectionTaskInstanceService inspectionTaskInstanceService; private final IInspectionTaskInstanceService inspectionTaskInstanceService;
private final IInspectionTaskLogService inspectionTaskLogService;
private final MessagePushService messagePushService; private final MessagePushService messagePushService;
/** key:itemId, value:已完成节点集合 */ /** key:itemId, value:已完成节点集合 */
@ -25,8 +29,11 @@ public class InspectionFlowExecutionListener implements FlowExecutionListener {
/** key:taskInsId(流程实例id=taskInsId), value:已执行item集合 */ /** key:taskInsId(流程实例id=taskInsId), value:已执行item集合 */
private final Map<String, Set<String>> taskItemExecutMap = new HashMap<>(); private final Map<String, Set<String>> taskItemExecutMap = new HashMap<>();
public InspectionFlowExecutionListener(IInspectionTaskInstanceService inspectionTaskInstanceService, MessagePushService messagePushService) { public InspectionFlowExecutionListener(IInspectionTaskInstanceService inspectionTaskInstanceService,
IInspectionTaskLogService inspectionTaskLogService,
MessagePushService messagePushService) {
this.inspectionTaskInstanceService = inspectionTaskInstanceService; this.inspectionTaskInstanceService = inspectionTaskInstanceService;
this.inspectionTaskLogService = inspectionTaskLogService;
this.messagePushService = messagePushService; this.messagePushService = messagePushService;
} }
@ -111,17 +118,32 @@ public class InspectionFlowExecutionListener implements FlowExecutionListener {
} }
String info = event.getEventType() == FlowExecutionEvent.EventType.NODE_STARTED ? "开始执行" : "执行完成"; String info = event.getEventType() == FlowExecutionEvent.EventType.NODE_STARTED ? "开始执行" : "执行完成";
Map<String, Object> pushMap = MapUtil.<String, Object>builder() String logId = UUID.randomUUID().toString().replace("-", "");
.put("createTime", now)
.put("insId", taskInstance.getId()) // 保存日志到数据库
.put("logInfo", "节点【" + event.getNodeName() + "" + info) InspectionTaskLog taskLog = InspectionTaskLog.builder()
.put("status", targetStatus) .id(logId)
.put("progress", String.format("%.2f", progress)) .taskInstanceId(taskInstance.getId())
.put("itemId", itemId) .taskId(taskInstance.getTaskId())
.put("taskId", taskInstance.getTaskId()) .waypointId(itemId)
.waypointName(event.getNodeName())
.nodeId(nodeId)
.nodeName(event.getNodeName())
.logType(InspectionLogTypeEnum.TEXT.getCode())
.logContent("节点【" + event.getNodeName() + "" + info)
.status(targetStatus)
.progress(String.format("%.2f", progress))
.logTime(now)
.build(); .build();
try { try {
messagePushService.pushToChannel("InspectionTaskInstance", pushMap); inspectionTaskLogService.insertInspectionTaskLog(taskLog);
log.info("巡检任务日志保存成功,logId:{},taskInstanceId:{},nodeId:{}", logId, taskInstance.getId(), nodeId);
} catch (Exception e) {
log.error("巡检任务日志保存失败,taskInstanceId:{},nodeId:{}", taskInstance.getId(), nodeId, e);
}
try {
messagePushService.pushToChannel("InspectionTaskInstance", taskLog);
} catch (Exception e) { } catch (Exception e) {
log.info("消息推送异常,无订阅忽略,itemId:{}", itemId, e); log.info("消息推送异常,无订阅忽略,itemId:{}", itemId, e);
} }
@ -139,13 +161,26 @@ public class InspectionFlowExecutionListener implements FlowExecutionListener {
* 推送完成任务信息参数dbInsId为数据库主键ID * 推送完成任务信息参数dbInsId为数据库主键ID
*/ */
public void pushCompleteMsg(String dbInsId, Date now, int targetStatus) { public void pushCompleteMsg(String dbInsId, Date now, int targetStatus) {
Map<String, Object> pushMap = MapUtil.<String, Object>builder() String logId = UUID.randomUUID().toString().replace("-", "");
.put("createTime", now)
.put("insId", dbInsId) // 保存完成日志
.put("status", targetStatus) InspectionTaskLog taskLog = InspectionTaskLog.builder()
.id(logId)
.taskInstanceId(dbInsId)
.logType(InspectionLogTypeEnum.TEXT.getCode())
.logContent("任务执行完成")
.status(targetStatus)
.logTime(now)
.build(); .build();
try { try {
messagePushService.pushToChannel("InspectionTaskInstance", pushMap); inspectionTaskLogService.insertInspectionTaskLog(taskLog);
log.info("任务完成日志保存成功,logId:{},taskInstanceId:{}", logId, dbInsId);
} catch (Exception e) {
log.error("任务完成日志保存失败,taskInstanceId:{}", dbInsId, e);
}
try {
messagePushService.pushToChannel("InspectionTaskInstance", taskLog);
} catch (Exception e) { } catch (Exception e) {
log.info("消息推送异常,无订阅忽略,insId:{}", dbInsId, e); log.info("消息推送异常,无订阅忽略,insId:{}", dbInsId, e);
} }

View File

@ -0,0 +1,31 @@
package com.cmvr.inspection.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.cmvr.inspection.domain.InspectionTaskLog;
import java.util.List;
/**
* 巡检任务执行日志Mapper接口
*
* @author cmvr-iot
* @since 2026-06-05
*/
public interface InspectionTaskLogMapper extends BaseMapper<InspectionTaskLog> {
/**
* 查询巡检任务执行日志列表
*
* @param taskInstanceId 任务实例ID
* @return 巡检任务执行日志集合
*/
List<InspectionTaskLog> selectInspectionTaskLogList(String taskInstanceId);
/**
* 批量插入巡检任务执行日志
*
* @param logList 日志列表
* @return 结果
*/
int batchInsertInspectionTaskLog(List<InspectionTaskLog> logList);
}

View File

@ -0,0 +1,39 @@
package com.cmvr.inspection.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.cmvr.inspection.domain.InspectionTaskLog;
import java.util.List;
/**
* 巡检任务执行日志Service接口
*
* @author cmvr-iot
* @since 2026-06-05
*/
public interface IInspectionTaskLogService extends IService<InspectionTaskLog>
{
/**
* 查询巡检任务执行日志列表
*
* @param taskInstanceId 任务实例ID
* @return 巡检任务执行日志集合
*/
List<InspectionTaskLog> selectInspectionTaskLogList(String taskInstanceId);
/**
* 新增巡检任务执行日志
*
* @param inspectionTaskLog 巡检任务执行日志
* @return 结果
*/
int insertInspectionTaskLog(InspectionTaskLog inspectionTaskLog);
/**
* 批量新增巡检任务执行日志
*
* @param logList 日志列表
* @return 结果
*/
int batchInsertInspectionTaskLog(List<InspectionTaskLog> logList);
}

View File

@ -0,0 +1,54 @@
package com.cmvr.inspection.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cmvr.common.utils.DateUtils;
import com.cmvr.inspection.domain.InspectionTaskLog;
import com.cmvr.inspection.mapper.InspectionTaskLogMapper;
import com.cmvr.inspection.service.IInspectionTaskLogService;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 巡检任务执行日志Service业务层处理
*
* @author cmvr-iot
* @since 2026-06-05
*/
@Service
public class InspectionTaskLogServiceImpl extends ServiceImpl<InspectionTaskLogMapper, InspectionTaskLog> implements IInspectionTaskLogService
{
/**
* 查询巡检任务执行日志列表
*
* @param taskInstanceId 任务实例ID
* @return 巡检任务执行日志集合
*/
@Override
public List<InspectionTaskLog> selectInspectionTaskLogList(String taskInstanceId) {
return baseMapper.selectInspectionTaskLogList(taskInstanceId);
}
/**
* 新增巡检任务执行日志
*
* @param inspectionTaskLog 巡检任务执行日志
* @return 结果
*/
@Override
public int insertInspectionTaskLog(InspectionTaskLog inspectionTaskLog) {
inspectionTaskLog.setCreateTime(DateUtils.getNowDate());
return baseMapper.insert(inspectionTaskLog);
}
/**
* 批量新增巡检任务执行日志
*
* @param logList 日志列表
* @return 结果
*/
@Override
public int batchInsertInspectionTaskLog(List<InspectionTaskLog> logList) {
return baseMapper.batchInsertInspectionTaskLog(logList);
}
}

View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cmvr.inspection.mapper.InspectionTaskLogMapper">
<resultMap type="com.cmvr.inspection.domain.InspectionTaskLog" id="InspectionTaskLogResult">
<result property="id" column="id" />
<result property="taskInstanceId" column="task_instance_id" />
<result property="taskId" column="task_id" />
<result property="waypointId" column="waypoint_id" />
<result property="waypointName" column="waypoint_name" />
<result property="nodeId" column="node_id" />
<result property="nodeName" column="node_name" />
<result property="logType" column="log_type" />
<result property="logContent" column="log_content" />
<result property="mediaUrl" column="media_url" />
<result property="status" column="status" />
<result property="progress" column="progress" />
<result property="logTime" column="log_time" />
<result property="extraInfo" column="extra_info" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
<result property="remark" column="remark" />
</resultMap>
<sql id="selectInspectionTaskLogVo">
select id, task_instance_id, task_id, waypoint_id, waypoint_name, node_id, node_name,
log_type, log_content, media_url, status, progress, log_time, extra_info,
create_by, create_time, update_by, update_time, remark
from inspection_task_log
</sql>
<select id="selectInspectionTaskLogList" resultMap="InspectionTaskLogResult">
<include refid="selectInspectionTaskLogVo"/>
where task_instance_id = #{taskInstanceId}
order by log_time asc
</select>
<insert id="batchInsertInspectionTaskLog">
insert into inspection_task_log(
id, task_instance_id, task_id, waypoint_id, waypoint_name, node_id, node_name,
log_type, log_content, media_url, status, progress, log_time, extra_info,
create_by, create_time, remark
) values
<foreach collection="list" item="item" separator=",">
(
#{item.id}, #{item.taskInstanceId}, #{item.taskId}, #{item.waypointId},
#{item.waypointName}, #{item.nodeId}, #{item.nodeName},
#{item.logType}, #{item.logContent}, #{item.mediaUrl}, #{item.status},
#{item.progress}, #{item.logTime}, #{item.extraInfo},
#{item.createBy}, #{item.createTime}, #{item.remark}
)
</foreach>
</insert>
</mapper>

View File

@ -146,3 +146,34 @@ CREATE TABLE `inspection_alarm` (
KEY `idx_alarm_time` (`alarm_time`), KEY `idx_alarm_time` (`alarm_time`),
KEY `idx_handle_status` (`handle_status`) KEY `idx_handle_status` (`handle_status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='巡检告警表'; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='巡检告警表';
-- ----------------------------
-- 巡检任务执行日志表
-- ----------------------------
DROP TABLE IF EXISTS `inspection_task_log`;
CREATE TABLE `inspection_task_log` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`task_instance_id` varchar(64) DEFAULT NULL COMMENT '任务实例ID',
`task_id` varchar(64) DEFAULT NULL COMMENT '任务ID',
`waypoint_id` varchar(64) DEFAULT NULL COMMENT '点位ID',
`waypoint_name` varchar(255) DEFAULT NULL COMMENT '点位名称',
`node_id` varchar(64) DEFAULT NULL COMMENT '节点ID',
`node_name` varchar(255) DEFAULT NULL COMMENT '节点名称',
`log_type` int(11) DEFAULT '1' COMMENT '日志类型(1文字 2图片 3视频 4音频)',
`log_content` text COMMENT '日志内容/文字描述',
`media_url` varchar(500) DEFAULT NULL COMMENT '媒体文件URL(图片/视频/音频)',
`status` int(11) DEFAULT '1' COMMENT '执行状态(0待执行 1执行中 2已完成 3已取消 4执行失败 5已暂停)',
`progress` varchar(20) DEFAULT NULL COMMENT '执行进度(百分比)',
`log_time` datetime DEFAULT NULL COMMENT '日志时间',
`extra_info` text COMMENT '扩展信息(JSON格式)',
`create_by` varchar(64) DEFAULT '' COMMENT '创建者',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(64) DEFAULT '' COMMENT '更新者',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`remark` varchar(500) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`),
KEY `idx_task_instance_id` (`task_instance_id`),
KEY `idx_task_id` (`task_id`),
KEY `idx_log_time` (`log_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='巡检任务执行日志表';