吉安感知网项目-后端
linwei
7 days ago 43214587a294fbcef392aaf90f21e38e5d5e39ac
feat(workorder): 添加事件状态时间线功能

- 在EventStatusEnum中新增getAllStatusCodes方法获取所有状态编码
- 修改GdClueEventController添加getStatusTimeline接口查询状态时间线
- 调整updateStatus接口的API文档顺序
- 修复GdClueEventDistributeParam中workOrderId字段验证问题
- 在GdClueEventStatusFlowServiceImpl中实现getStatusTimeline业务逻辑
- 添加GdClueEventStatusFlowVO的isReached字段标识状态是否已到达
- 实现完整的时间线展示功能,支持显示已到达和未到达状态
7 files modified
135 ■■■■■ changed files
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/controller/GdClueEventController.java 14 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/enums/EventStatusEnum.java 9 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/param/GdClueEventDistributeParam.java 1 ●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/IGdClueEventStatusFlowService.java 15 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdClueEventServiceImpl.java 2 ●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdClueEventStatusFlowServiceImpl.java 88 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/vo/GdClueEventStatusFlowVO.java 6 ●●●●● patch | view | raw | blame | history
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/controller/GdClueEventController.java
@@ -202,7 +202,7 @@
        List<GdClueDisposeRecordVO> disposeRecords = gdClueDisposeRecordService.getDisposeRecordsByEventId(id);
        // 3. 查询状态流转时间线
        List<GdClueEventStatusFlowVO> statusFlows = gdClueEventStatusFlowService.getStatusFlowsByEventId(id);
        List<GdClueEventStatusFlowVO> statusFlows = gdClueEventStatusFlowService.getStatusTimeline(id);
        // 4. 组装返回数据
        GdClueEventDetailVO detailVO = new GdClueEventDetailVO();
@@ -244,10 +244,20 @@
    }
    /**
     * 查询状态时间线
     */
    @GetMapping("/statusTimeline")
    @ApiOperationSupport(order = 13)
    @ApiOperation(value = "查询状态时间线", notes = "传入事件ID,返回所有状态(包含已到达和未到达),并标识每个状态是否已到达")
    public R<List<GdClueEventStatusFlowVO>> getStatusTimeline(@ApiParam(value = "事件ID", required = true) @RequestParam Long eventId) {
        return R.data(gdClueEventStatusFlowService.getStatusTimeline(eventId));
    }
    /**
     * 更新事件状态
     */
    @PostMapping("/updateStatus")
    @ApiOperationSupport(order = 13)
    @ApiOperationSupport(order = 14)
    @ApiOperation(value = "更新事件状态(完成,处置中和已处置状态切换,退回)", notes = "传入事件ID和目标状态,必须符合状态流转矩阵")
    public R updateStatus(@Valid @RequestBody GdClueEventStatusUpdateParam updateParam) {
        return R.status(gdClueEventService.updateEventStatus(updateParam));
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/enums/EventStatusEnum.java
@@ -160,4 +160,13 @@
    public static boolean isValidCode(Integer code) {
        return getByCode(code) != null;
    }
    /**
     * 获取所有状态编码列表(按编码升序)
     *
     * @return 所有状态编码列表
     */
    public static List<Integer> getAllStatusCodes() {
        return Arrays.asList(0, 1, 2, 3, 4);
    }
}
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/param/GdClueEventDistributeParam.java
@@ -20,7 +20,6 @@
     * 工单任务ID
     */
    @ApiModelProperty(value = "工单任务ID", required = true)
    @NotNull(message = "工单任务ID不能为空")
    private Long workOrderId;
    /**
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/IGdClueEventStatusFlowService.java
@@ -56,4 +56,19 @@
     */
    boolean insertStatusFlow(Long eventId, Integer oldStatus, Integer newStatus, String operateContent, java.util.Date operateTime);
    /**
     * 根据事件ID查询状态时间线
     * <p>
     * 返回所有状态(包含已到达和未到达),并标识每个状态是否已到达。
     * 状态流转规则:
     * - 如果最后一条流转记录的目标状态是该状态,则已到达
     * - 如果最后一条流转记录的源状态是该状态,则未到达(已离开)
     * - 处置中(1)和已处置(3)可以来回切换
     * </p>
     *
     * @param eventId 事件ID
     * @return 状态时间线列表(按状态编码升序)
     */
    List<GdClueEventStatusFlowVO> getStatusTimeline(Long eventId);
}
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdClueEventServiceImpl.java
@@ -233,7 +233,7 @@
            clueEvent = new GdClueEventEntity();
        }
        clueEvent.setResultId(distributeParam.getResultId());
        clueEvent.setWorkOrderId(distributeParam.getWorkOrderId());
        clueEvent.setWorkOrderId(taskResult.getPatrolTaskId());
        clueEvent.setDisposeUser(distributeParam.getDisposeUser());
        clueEvent.setDisposeDept(distributeParam.getDisposeDept());
        clueEvent.setLongitude(distributeParam.getLongitude());
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdClueEventStatusFlowServiceImpl.java
@@ -19,16 +19,20 @@
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.secure.utils.AuthUtil;
import org.sxkj.gd.workorder.entity.GdClueEventEntity;
import org.sxkj.gd.workorder.entity.GdClueEventStatusFlowEntity;
import org.sxkj.gd.workorder.enums.EventStatusEnum;
import org.sxkj.gd.workorder.mapper.GdClueEventStatusFlowMapper;
import org.sxkj.gd.workorder.service.IGdClueEventService;
import org.sxkj.gd.workorder.service.IGdClueEventStatusFlowService;
import org.sxkj.gd.workorder.vo.GdClueEventStatusFlowVO;
import org.springframework.stereotype.Service;
import org.springblade.core.mp.base.BaseServiceImpl;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * 事件状态流转履历表 服务实现类
@@ -40,6 +44,8 @@
@Service
@AllArgsConstructor
public class GdClueEventStatusFlowServiceImpl extends BaseServiceImpl<GdClueEventStatusFlowMapper, GdClueEventStatusFlowEntity> implements IGdClueEventStatusFlowService {
    private final IGdClueEventService gdClueEventService;
    /**
     * 根据事件ID查询状态流转记录列表
@@ -123,4 +129,86 @@
        return save(flowEntity);
    }
    /**
     * 根据事件ID查询状态时间线
     * <p>
     * 步骤:
     * 1. 参数校验
     * 2. 查询事件当前状态
     * 3. 查询状态流转记录
     * 4. 构建已到达状态集合
     * 5. 生成完整的状态时间线
     * </p>
     *
     * @param eventId 事件ID
     * @return 状态时间线列表(按状态编码升序)
     */
    @Override
    public List<GdClueEventStatusFlowVO> getStatusTimeline(Long eventId) {
        // 1. 参数校验
        if (eventId == null) {
            throw new RuntimeException("事件ID不能为空");
        }
        // 2. 查询事件当前状态
        GdClueEventEntity event = gdClueEventService.getById(eventId);
        if (event == null) {
            throw new RuntimeException("事件不存在");
        }
        // 3. 查询状态流转记录
        List<GdClueEventStatusFlowVO> flows = baseMapper.selectStatusFlowsByEventId(eventId);
        // 4. 构建每个状态的最后流转记录
        // key: 状态编码, value: 最后的流转记录
        Map<Integer, GdClueEventStatusFlowVO> lastFlowMap = new HashMap<>();
        if (flows != null && !flows.isEmpty()) {
            for (GdClueEventStatusFlowVO flow : flows) {
                // 记录目标状态的最后流转
                if (flow.getNewStatus() != null) {
                    lastFlowMap.put(flow.getNewStatus(), flow);
                }
                // 记录源状态的最后流转
                if (flow.getOldStatus() != null) {
                    lastFlowMap.put(flow.getOldStatus(), flow);
                }
            }
        }
        // 5. 生成完整的状态时间线
        List<GdClueEventStatusFlowVO> timeline = new java.util.ArrayList<>();
        for (Integer statusCode : EventStatusEnum.getAllStatusCodes()) {
            GdClueEventStatusFlowVO item = new GdClueEventStatusFlowVO();
            // 使用 newStatus 字段存储当前状态编码
            item.setNewStatus(statusCode);
            item.setNewStatusName(EventStatusEnum.getNameByCode(statusCode));
            GdClueEventStatusFlowVO lastFlow = lastFlowMap.get(statusCode);
            if (lastFlow != null) {
                // 根据最后流转记录判断是否已到达
                // 如果目标是该状态,则已到达
                // 如果源是该状态(目标不是),则未到达(已离开)
                boolean isReached = lastFlow.getNewStatus().equals(statusCode);
                item.setIsReached(isReached);
                if (isReached) {
                    // 已到达状态:设置操作信息
                    item.setOperateUser(lastFlow.getOperateUser());
                    item.setOperateUserName(lastFlow.getOperateUserName());
                    item.setOperateDept(lastFlow.getOperateDept());
                    item.setOperateDeptName(lastFlow.getOperateDeptName());
                    item.setOperateContent(lastFlow.getOperateContent());
                    item.setOperateTime(lastFlow.getOperateTime());
                }
            } else {
                // 没有流转记录,未到达
                item.setIsReached(false);
            }
            timeline.add(item);
        }
        return timeline;
    }
}
drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/vo/GdClueEventStatusFlowVO.java
@@ -116,4 +116,10 @@
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private Date createTime;
    /**
     * 是否已到达(用于状态时间线展示)
     */
    @ApiModelProperty(value = "是否已到达:true-已到达,false-未到达")
    private Boolean isReached;
}