diff --git a/common/src/main/java/com/sdm/common/entity/flowable/dto/ProcessInstanceInfo.java b/common/src/main/java/com/sdm/common/entity/flowable/dto/ProcessInstanceInfo.java index 5871d04f..73f73079 100644 --- a/common/src/main/java/com/sdm/common/entity/flowable/dto/ProcessInstanceInfo.java +++ b/common/src/main/java/com/sdm/common/entity/flowable/dto/ProcessInstanceInfo.java @@ -9,12 +9,11 @@ import java.util.Date; public class ProcessInstanceInfo { private String processInstanceId; private String processDefinitionId; - private String businessKey; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date startTime; @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date endTime; private Long durationInMillis; private String durationFormatted; - private String status; // "running" 或 "completed" + private String status; // "pending""running" 或 "completed" } diff --git a/common/src/main/java/com/sdm/common/feign/impl/flowable/FlowableClientFeignClientImpl.java b/common/src/main/java/com/sdm/common/feign/impl/flowable/FlowableClientFeignClientImpl.java index 4743b90a..0d5b2ed4 100644 --- a/common/src/main/java/com/sdm/common/feign/impl/flowable/FlowableClientFeignClientImpl.java +++ b/common/src/main/java/com/sdm/common/feign/impl/flowable/FlowableClientFeignClientImpl.java @@ -76,10 +76,10 @@ public class FlowableClientFeignClientImpl implements IFlowableFeignClient { } @Override - public SdmResponse getProcessAndNodeDetailByInstanceId(String processInstanceId) { + public SdmResponse getProcessAndNodeDetailByInstanceId(String processDefinitionId,String processInstanceId) { SdmResponse response; try { - response = flowableFeignClient.getProcessAndNodeDetailByInstanceId(processInstanceId); + response = flowableFeignClient.getProcessAndNodeDetailByInstanceId(processDefinitionId,processInstanceId); log.info("查询流程状态以及节点状态:"+ response); return response; } catch (Exception e) { @@ -87,17 +87,4 @@ public class FlowableClientFeignClientImpl implements IFlowableFeignClient { return SdmResponse.failed("查询流程状态以及节点状态失败"); } } - - @Override - public SdmResponse> listNodesByProcessDefinitionId(String processDefinitionId) { - SdmResponse> response; - try { - response = flowableFeignClient.listNodesByProcessDefinitionId(processDefinitionId); - log.info("获取流程定义节点详细信息:"+ response); - return response; - } catch (Exception e) { - log.error("获取流程定义节点详细信息失败", e); - return SdmResponse.failed("获取流程定义节点详细信息失败"); - } - } } diff --git a/common/src/main/java/com/sdm/common/feign/inter/flowable/IFlowableFeignClient.java b/common/src/main/java/com/sdm/common/feign/inter/flowable/IFlowableFeignClient.java index 44ad6b15..b7a45861 100644 --- a/common/src/main/java/com/sdm/common/feign/inter/flowable/IFlowableFeignClient.java +++ b/common/src/main/java/com/sdm/common/feign/inter/flowable/IFlowableFeignClient.java @@ -32,9 +32,5 @@ public interface IFlowableFeignClient { SdmResponse updateNodeParamProcessInstanceId(@RequestParam String processDefinitionId, @RequestParam String processInstanceId); @GetMapping("/process/getProcessAndNodeDetailByInstanceId") - SdmResponse getProcessAndNodeDetailByInstanceId(@RequestParam String processInstanceId); - - @GetMapping("/listNodesByProcessDefinitionId") - SdmResponse> listNodesByProcessDefinitionId(@RequestParam String processDefinitionId); - + SdmResponse getProcessAndNodeDetailByInstanceId(@RequestParam String processDefinitionId,@RequestParam(required = false) String processInstanceId); } diff --git a/flowable/src/main/java/com/sdm/flowable/controller/ProcessController.java b/flowable/src/main/java/com/sdm/flowable/controller/ProcessController.java index 3e577f50..70d7a024 100644 --- a/flowable/src/main/java/com/sdm/flowable/controller/ProcessController.java +++ b/flowable/src/main/java/com/sdm/flowable/controller/ProcessController.java @@ -128,7 +128,9 @@ public class ProcessController implements IFlowableFeignClient { } /** - * 根据流程实例 ID 查询流程状态以及节点状态 + * 查询流程实例及所有节点的详细状态(返回结构化 DTO) + * 如果只传了processDefinitionId,根据流程定义返回流程基本信息和节点信息, + * 如果还传了processInstanceId,再封装流程状态和节点状态 */ @GetMapping("/getProcessAndNodeDetailByInstanceId") public SdmResponse getProcessAndNodeDetailByInstanceId(@RequestParam String processDefinitionId,@RequestParam(required = false) String processInstanceId) { diff --git a/flowable/src/main/java/com/sdm/flowable/process/ProcessService.java b/flowable/src/main/java/com/sdm/flowable/process/ProcessService.java index 1396b65d..da8e595f 100644 --- a/flowable/src/main/java/com/sdm/flowable/process/ProcessService.java +++ b/flowable/src/main/java/com/sdm/flowable/process/ProcessService.java @@ -4,7 +4,6 @@ import com.sdm.common.common.SdmResponse; import com.sdm.flowable.constants.FlowableConfig; import com.sdm.flowable.delegate.UniversalDelegate; import com.sdm.common.entity.flowable.dto.NodeDetailInfo; -import com.sdm.common.entity.flowable.dto.NodeStructureInfo; import com.sdm.common.entity.flowable.dto.ProcessInstanceInfo; import com.sdm.common.entity.flowable.dto.ProcessDefinitionDTO; import com.sdm.flowable.dto.req.AsyncCallbackRequest; @@ -140,12 +139,69 @@ public class ProcessService { /** * 查询流程实例及所有节点的详细状态(返回结构化 DTO) + * 如果只传了processDefinitionId,根据流程定义返回流程基本信息和节点信息, + * 如果还传了processInstanceId,再封装流程状态和节点状态 */ - public SdmResponse getProcessAndNodeDetailByInstanceId(String processDefinitionId,String processInstanceId) { - ProcessInstanceInfo processInfo = buildProcessInstanceInfo(processInstanceId); - List nodes = buildNodeDetails(processInstanceId, processInfo.getProcessDefinitionId()); - + public SdmResponse getProcessAndNodeDetailByInstanceId(String processDefinitionId, String processInstanceId) { ProcessInstanceDetailResponse response = new ProcessInstanceDetailResponse(); + + // 构建基础流程信息 + ProcessInstanceInfo processInfo = new ProcessInstanceInfo(); + processInfo.setProcessDefinitionId(processDefinitionId); + + // 获取流程定义中的节点结构信息 + List orderedNodes = getOrderedFlowNodes(processDefinitionId); + List nodes = orderedNodes.stream() + .map(this::buildNodeDetailInfoFromFlowNode) // 直接构建NodeDetailInfo + .peek(detail -> { + Map params = processNodeParamService.getParam(processDefinitionId, detail.getId()); + detail.setUserParam(params); + }) + .collect(Collectors.toList()); + + if (processInstanceId != null && !processInstanceId.isEmpty()) { + // 如果提供了流程实例ID,则补充完整状态信息 + processInfo = buildProcessInstanceInfo(processInstanceId); + + // 补充节点状态信息 + List historicActivities = historyService.createHistoricActivityInstanceQuery() + .processInstanceId(processInstanceId) + .list(); + + Map activityMap = historicActivities.stream() + .collect(Collectors.toMap( + HistoricActivityInstance::getActivityId, + Function.identity(), + (a, b) -> a + )); + + List activeActivityIds = isProcessRunning(processInstanceId) + ? runtimeService.getActiveActivityIds(processInstanceId) + : Collections.emptyList(); + + // 更新节点状态信息 + for (NodeDetailInfo node : nodes) { + String nodeId = node.getId(); + + HistoricActivityInstance historicActivity = activityMap.get(nodeId); + boolean isActive = activeActivityIds.contains(nodeId); + boolean isFinished = historicActivity != null && historicActivity.getEndTime() != null; + + node.setStatus(isFinished ? "finished" : (isActive ? "active" : "pending")); + + if (historicActivity != null) { + node.setStartTime(historicActivity.getStartTime()); + if (isFinished) { + node.setEndTime(historicActivity.getEndTime()); + node.setDurationInMillis(historicActivity.getDurationInMillis()); + if (historicActivity.getDurationInMillis() != null) { + node.setDurationFormatted(formatDuration(historicActivity.getDurationInMillis())); + } + } + } + } + } + response.setProcessInfo(processInfo); response.setNodes(nodes); return SdmResponse.success(response); @@ -168,7 +224,6 @@ public class ProcessService { ProcessInstanceInfo info = new ProcessInstanceInfo(); info.setProcessInstanceId(historicInstance.getId()); info.setProcessDefinitionId(historicInstance.getProcessDefinitionId()); - info.setBusinessKey(historicInstance.getBusinessKey()); info.setStartTime(historicInstance.getStartTime()); info.setEndTime(historicInstance.getEndTime()); // 可能为 null @@ -183,31 +238,7 @@ public class ProcessService { return info; } - //构建节点列表 - private List buildNodeDetails(String processInstanceId, String processDefinitionId) { - List orderedNodes = getOrderedFlowNodes(processDefinitionId); - // 查询运行时 & 历史数据 - List historicActivities = historyService.createHistoricActivityInstanceQuery() - .processInstanceId(processInstanceId) - .list(); - - Map activityMap = historicActivities.stream() - .collect(Collectors.toMap( - HistoricActivityInstance::getActivityId, - Function.identity(), - (a, b) -> a - )); - - List activeActivityIds = isProcessRunning(processInstanceId) - ? runtimeService.getActiveActivityIds(processInstanceId) - : Collections.emptyList(); - - // 按有序节点构建详情 - return orderedNodes.stream() - .map(node -> buildNodeDetailInfo(node,processDefinitionId, activityMap, activeActivityIds)) - .collect(Collectors.toList()); - } /** * 根据流程定义 ID,按流程执行顺序(BFS)返回所有可达的 FlowNode @@ -264,55 +295,17 @@ public class ProcessService { .count() > 0; } - // --- 构建单个节点详情(返回 NodeDetailInfo)--- - private NodeDetailInfo buildNodeDetailInfo( - FlowNode node, - String processDefinitionId, - Map activityMap, - List activeActivityIds) { - String nodeId = node.getId(); - // 先构建静态结构 - NodeStructureInfo base = buildNodeStructureInfo(node); - Map params = processNodeParamService.getParam(processDefinitionId, nodeId); - base.setUserParam(params); - - // 再填充动态信息 + /** + * 从FlowNode构建NodeDetailInfo基础信息(不含状态) + */ + private NodeDetailInfo buildNodeDetailInfoFromFlowNode(FlowNode node) { NodeDetailInfo detail = new NodeDetailInfo(); - detail.setId(base.getId()); - detail.setName(base.getName()); - detail.setType(base.getType()); - detail.setNextNodeIds(base.getNextNodeIds()); - detail.setExecuteConfig(base.getExecuteConfig()); - - // 动态状态逻辑 - HistoricActivityInstance historicActivity = activityMap.get(nodeId); - boolean isActive = activeActivityIds.contains(nodeId); - boolean isFinished = historicActivity != null && historicActivity.getEndTime() != null; - - detail.setStatus(isFinished ? "finished" : (isActive ? "active" : "pending")); - - if (historicActivity != null) { - detail.setStartTime(historicActivity.getStartTime()); - if (isFinished) { - detail.setEndTime(historicActivity.getEndTime()); - detail.setDurationInMillis(historicActivity.getDurationInMillis()); - if (historicActivity.getDurationInMillis() != null) { - detail.setDurationFormatted(formatDuration(historicActivity.getDurationInMillis())); - } - } - } - - return detail; - } - - private NodeStructureInfo buildNodeStructureInfo(FlowNode node) { - NodeStructureInfo info = new NodeStructureInfo(); - info.setId(node.getId()); - info.setName(node.getName() != null ? node.getName() : ""); - info.setType(node.getClass().getSimpleName()); - + detail.setId(node.getId()); + detail.setName(node.getName() != null ? node.getName() : ""); + detail.setType(node.getClass().getSimpleName()); + // 后续节点 - info.setNextNodeIds( + detail.setNextNodeIds( node.getOutgoingFlows().stream() .map(SequenceFlow::getTargetRef) .collect(Collectors.toList()) @@ -322,14 +315,13 @@ public class ProcessService { if (node.getExtensionElements() != null) { List extList = node.getExtensionElements().get(FlowableConfig.EXECUTECONFIG); if (extList != null && !extList.isEmpty()) { - info.setExecuteConfig(extList.get(0).getElementText()); + detail.setExecuteConfig(extList.get(0).getElementText()); } } - - return info; + + return detail; } - // --- 工具方法:格式化耗时(毫秒 → 可读字符串)--- private String formatDuration(long millis) { long seconds = millis / 1000; diff --git a/flowable/src/main/java/com/sdm/flowable/service/IProcessNodeParamService.java b/flowable/src/main/java/com/sdm/flowable/service/IProcessNodeParamService.java index 3fe1a370..20598e2c 100644 --- a/flowable/src/main/java/com/sdm/flowable/service/IProcessNodeParamService.java +++ b/flowable/src/main/java/com/sdm/flowable/service/IProcessNodeParamService.java @@ -16,5 +16,5 @@ import java.util.Map; public interface IProcessNodeParamService extends IService { void saveParamByProcessDefinitionId(String processDefinitionId, String nodeId, Map params); void updateNodeParamProcessInstanceId(String processInstanceId, String processDefinitionId); - Map getParam(String procInstId, String nodeId); + Map getParam(String processDefinitionId, String nodeId); } \ No newline at end of file diff --git a/flowable/src/main/java/com/sdm/flowable/service/impl/ProcessNodeParamServiceImpl.java b/flowable/src/main/java/com/sdm/flowable/service/impl/ProcessNodeParamServiceImpl.java index c6034b56..eb992c6e 100644 --- a/flowable/src/main/java/com/sdm/flowable/service/impl/ProcessNodeParamServiceImpl.java +++ b/flowable/src/main/java/com/sdm/flowable/service/impl/ProcessNodeParamServiceImpl.java @@ -7,11 +7,13 @@ import com.sdm.flowable.entity.ProcessNodeParam; import com.sdm.flowable.dao.ProcessNodeParamMapper; import com.sdm.flowable.service.IProcessNodeParamService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.apache.commons.lang3.ObjectUtils; import org.flowable.engine.RuntimeService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -54,10 +56,15 @@ public class ProcessNodeParamServiceImpl extends ServiceImpl processNodeParams = this.lambdaQuery().eq(ProcessNodeParam::getProcessDefinitionId, processDefinitionId).list(); + + if (ObjectUtils.isNotEmpty(processNodeParams)) { + processNodeParams.forEach(param -> { + this.lambdaUpdate() + .eq(ProcessNodeParam::getId, param.getId()) + .set(ProcessNodeParam::getProcessInstanceId, processInstanceId) + .update(); + }); } }