优化flowable流程和节点状态查询
This commit is contained in:
@@ -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"
|
||||
}
|
||||
|
||||
@@ -76,10 +76,10 @@ public class FlowableClientFeignClientImpl implements IFlowableFeignClient {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SdmResponse<ProcessInstanceDetailResponse> getProcessAndNodeDetailByInstanceId(String processInstanceId) {
|
||||
public SdmResponse<ProcessInstanceDetailResponse> getProcessAndNodeDetailByInstanceId(String processDefinitionId,String processInstanceId) {
|
||||
SdmResponse<ProcessInstanceDetailResponse> 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<List<NodeStructureInfo>> listNodesByProcessDefinitionId(String processDefinitionId) {
|
||||
SdmResponse<List<NodeStructureInfo>> response;
|
||||
try {
|
||||
response = flowableFeignClient.listNodesByProcessDefinitionId(processDefinitionId);
|
||||
log.info("获取流程定义节点详细信息:"+ response);
|
||||
return response;
|
||||
} catch (Exception e) {
|
||||
log.error("获取流程定义节点详细信息失败", e);
|
||||
return SdmResponse.failed("获取流程定义节点详细信息失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,9 +32,5 @@ public interface IFlowableFeignClient {
|
||||
SdmResponse updateNodeParamProcessInstanceId(@RequestParam String processDefinitionId, @RequestParam String processInstanceId);
|
||||
|
||||
@GetMapping("/process/getProcessAndNodeDetailByInstanceId")
|
||||
SdmResponse<ProcessInstanceDetailResponse> getProcessAndNodeDetailByInstanceId(@RequestParam String processInstanceId);
|
||||
|
||||
@GetMapping("/listNodesByProcessDefinitionId")
|
||||
SdmResponse<List<NodeStructureInfo>> listNodesByProcessDefinitionId(@RequestParam String processDefinitionId);
|
||||
|
||||
SdmResponse<ProcessInstanceDetailResponse> getProcessAndNodeDetailByInstanceId(@RequestParam String processDefinitionId,@RequestParam(required = false) String processInstanceId);
|
||||
}
|
||||
|
||||
@@ -128,7 +128,9 @@ public class ProcessController implements IFlowableFeignClient {
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据流程实例 ID 查询流程状态以及节点状态
|
||||
* 查询流程实例及所有节点的详细状态(返回结构化 DTO)
|
||||
* 如果只传了processDefinitionId,根据流程定义返回流程基本信息和节点信息,
|
||||
* 如果还传了processInstanceId,再封装流程状态和节点状态
|
||||
*/
|
||||
@GetMapping("/getProcessAndNodeDetailByInstanceId")
|
||||
public SdmResponse<ProcessInstanceDetailResponse> getProcessAndNodeDetailByInstanceId(@RequestParam String processDefinitionId,@RequestParam(required = false) String processInstanceId) {
|
||||
|
||||
@@ -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<ProcessInstanceDetailResponse> getProcessAndNodeDetailByInstanceId(String processDefinitionId,String processInstanceId) {
|
||||
ProcessInstanceInfo processInfo = buildProcessInstanceInfo(processInstanceId);
|
||||
List<NodeDetailInfo> nodes = buildNodeDetails(processInstanceId, processInfo.getProcessDefinitionId());
|
||||
|
||||
public SdmResponse<ProcessInstanceDetailResponse> getProcessAndNodeDetailByInstanceId(String processDefinitionId, String processInstanceId) {
|
||||
ProcessInstanceDetailResponse response = new ProcessInstanceDetailResponse();
|
||||
|
||||
// 构建基础流程信息
|
||||
ProcessInstanceInfo processInfo = new ProcessInstanceInfo();
|
||||
processInfo.setProcessDefinitionId(processDefinitionId);
|
||||
|
||||
// 获取流程定义中的节点结构信息
|
||||
List<FlowNode> orderedNodes = getOrderedFlowNodes(processDefinitionId);
|
||||
List<NodeDetailInfo> nodes = orderedNodes.stream()
|
||||
.map(this::buildNodeDetailInfoFromFlowNode) // 直接构建NodeDetailInfo
|
||||
.peek(detail -> {
|
||||
Map<String, Object> params = processNodeParamService.getParam(processDefinitionId, detail.getId());
|
||||
detail.setUserParam(params);
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (processInstanceId != null && !processInstanceId.isEmpty()) {
|
||||
// 如果提供了流程实例ID,则补充完整状态信息
|
||||
processInfo = buildProcessInstanceInfo(processInstanceId);
|
||||
|
||||
// 补充节点状态信息
|
||||
List<HistoricActivityInstance> historicActivities = historyService.createHistoricActivityInstanceQuery()
|
||||
.processInstanceId(processInstanceId)
|
||||
.list();
|
||||
|
||||
Map<String, HistoricActivityInstance> activityMap = historicActivities.stream()
|
||||
.collect(Collectors.toMap(
|
||||
HistoricActivityInstance::getActivityId,
|
||||
Function.identity(),
|
||||
(a, b) -> a
|
||||
));
|
||||
|
||||
List<String> 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<NodeDetailInfo> buildNodeDetails(String processInstanceId, String processDefinitionId) {
|
||||
List<FlowNode> orderedNodes = getOrderedFlowNodes(processDefinitionId);
|
||||
|
||||
// 查询运行时 & 历史数据
|
||||
List<HistoricActivityInstance> historicActivities = historyService.createHistoricActivityInstanceQuery()
|
||||
.processInstanceId(processInstanceId)
|
||||
.list();
|
||||
|
||||
Map<String, HistoricActivityInstance> activityMap = historicActivities.stream()
|
||||
.collect(Collectors.toMap(
|
||||
HistoricActivityInstance::getActivityId,
|
||||
Function.identity(),
|
||||
(a, b) -> a
|
||||
));
|
||||
|
||||
List<String> 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<String, HistoricActivityInstance> activityMap,
|
||||
List<String> activeActivityIds) {
|
||||
String nodeId = node.getId();
|
||||
// 先构建静态结构
|
||||
NodeStructureInfo base = buildNodeStructureInfo(node);
|
||||
Map<String, Object> 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<ExtensionElement> 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;
|
||||
|
||||
@@ -16,5 +16,5 @@ import java.util.Map;
|
||||
public interface IProcessNodeParamService extends IService<ProcessNodeParam> {
|
||||
void saveParamByProcessDefinitionId(String processDefinitionId, String nodeId, Map<String, Object> params);
|
||||
void updateNodeParamProcessInstanceId(String processInstanceId, String processDefinitionId);
|
||||
Map<String, Object> getParam(String procInstId, String nodeId);
|
||||
Map<String, Object> getParam(String processDefinitionId, String nodeId);
|
||||
}
|
||||
@@ -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<ProcessNodeParamMap
|
||||
|
||||
// 流程启动后,更新流程实例ID
|
||||
public void updateNodeParamProcessInstanceId(String processInstanceId, String processDefinitionId) {
|
||||
ProcessNodeParam param = this.lambdaQuery().eq(ProcessNodeParam::getProcessDefinitionId, processDefinitionId).one();
|
||||
if (param != null) {
|
||||
param.setProcessInstanceId(processInstanceId);
|
||||
this.updateById(param);
|
||||
List<ProcessNodeParam> 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();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user