|
@@ -8,8 +8,16 @@ import com.qqflow.engine.domain.flow.dto.analysis.ProcessEfficiencyDTO;
|
|
|
import com.qqflow.engine.domain.flow.dto.analysis.StuckInstanceDTO;
|
|
import com.qqflow.engine.domain.flow.dto.analysis.StuckInstanceDTO;
|
|
|
import com.qqflow.engine.domain.flow.dto.analysis.StatusDistributionDTO;
|
|
import com.qqflow.engine.domain.flow.dto.analysis.StatusDistributionDTO;
|
|
|
import com.qqflow.engine.domain.flow.dto.analysis.TrendDTO;
|
|
import com.qqflow.engine.domain.flow.dto.analysis.TrendDTO;
|
|
|
|
|
+import com.qqflow.engine.common.exception.BusinessException;
|
|
|
import com.qqflow.engine.domain.flow.mapper.AnalysisMapper;
|
|
import com.qqflow.engine.domain.flow.mapper.AnalysisMapper;
|
|
|
|
|
+import com.qqflow.engine.domain.flow.mapper.ProcessDefinitionMapper;
|
|
|
|
|
+import com.qqflow.engine.domain.flow.mapper.ProcessInstanceMapper;
|
|
|
|
|
+import com.qqflow.engine.domain.flow.model.FlowModel;
|
|
|
|
|
+import com.qqflow.engine.domain.flow.model.FlowNode;
|
|
|
|
|
+import com.qqflow.engine.domain.flow.po.ProcessDefinition;
|
|
|
|
|
+import com.qqflow.engine.domain.flow.po.ProcessInstance;
|
|
|
import com.qqflow.engine.domain.flow.service.AnalysisService;
|
|
import com.qqflow.engine.domain.flow.service.AnalysisService;
|
|
|
|
|
+import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
import lombok.RequiredArgsConstructor;
|
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
|
@@ -18,6 +26,7 @@ import java.time.LocalDateTime;
|
|
|
import java.time.format.DateTimeFormatter;
|
|
import java.time.format.DateTimeFormatter;
|
|
|
import java.util.ArrayList;
|
|
import java.util.ArrayList;
|
|
|
import java.util.HashMap;
|
|
import java.util.HashMap;
|
|
|
|
|
+import java.util.LinkedHashMap;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
import java.util.concurrent.TimeUnit;
|
|
@@ -32,6 +41,8 @@ public class AnalysisServiceImpl implements AnalysisService {
|
|
|
|
|
|
|
|
private final AnalysisMapper analysisMapper;
|
|
private final AnalysisMapper analysisMapper;
|
|
|
private final RedisCache redisCache;
|
|
private final RedisCache redisCache;
|
|
|
|
|
+ private final ProcessDefinitionMapper processDefinitionMapper;
|
|
|
|
|
+ private final ProcessInstanceMapper processInstanceMapper;
|
|
|
|
|
|
|
|
private static final String KEY_COMPLETED_EFFICIENCY = "analysis:completed-efficiency:%s:%s:%s";
|
|
private static final String KEY_COMPLETED_EFFICIENCY = "analysis:completed-efficiency:%s:%s:%s";
|
|
|
private static final String KEY_IN_PROGRESS_BY_NODE = "analysis:in-progress-by-node:%s";
|
|
private static final String KEY_IN_PROGRESS_BY_NODE = "analysis:in-progress-by-node:%s";
|
|
@@ -178,4 +189,48 @@ public class AnalysisServiceImpl implements AnalysisService {
|
|
|
default -> "未知";
|
|
default -> "未知";
|
|
|
};
|
|
};
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public List<Map<String, Object>> nodeCountByDefinition(Long processDefinitionId) {
|
|
|
|
|
+ ProcessDefinition def = this.processDefinitionMapper.selectById(processDefinitionId);
|
|
|
|
|
+ if (def == null || def.getModelJson() == null) {
|
|
|
|
|
+ throw new BusinessException("流程定义不存在");
|
|
|
|
|
+ }
|
|
|
|
|
+ try {
|
|
|
|
|
+ FlowModel model = new ObjectMapper().readValue(def.getModelJson(), FlowModel.class);
|
|
|
|
|
+ Map<String, String> nodeNameMap = new HashMap<>();
|
|
|
|
|
+ if (model.getNodes() != null) {
|
|
|
|
|
+ for (FlowNode node : model.getNodes()) {
|
|
|
|
|
+ nodeNameMap.put(node.getId(), node.getName());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ // 查询该流程下所有实例,按当前节点分组统计
|
|
|
|
|
+ List<ProcessInstance> instances = this.processInstanceMapper.selectList(
|
|
|
|
|
+ new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<ProcessInstance>()
|
|
|
|
|
+ .eq(ProcessInstance::getProcessDefinitionId, processDefinitionId)
|
|
|
|
|
+ .eq(ProcessInstance::getDeleted, 0));
|
|
|
|
|
+ Map<String, Long> countMap = new HashMap<>();
|
|
|
|
|
+ for (ProcessInstance pi : instances) {
|
|
|
|
|
+ if (pi.getCurrentNodeId() != null) {
|
|
|
|
|
+ countMap.merge(pi.getCurrentNodeId(), 1L, Long::sum);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ List<Map<String, Object>> result = new ArrayList<>();
|
|
|
|
|
+ if (model.getNodes() != null) {
|
|
|
|
|
+ for (FlowNode node : model.getNodes()) {
|
|
|
|
|
+ String type = node.getType();
|
|
|
|
|
+ if ("start".equals(type) || "end".equals(type) || "condition".equals(type) || "cc".equals(type)) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ Map<String, Object> item = new LinkedHashMap<>();
|
|
|
|
|
+ item.put("nodeName", node.getName());
|
|
|
|
|
+ item.put("count", countMap.getOrDefault(node.getId(), 0L));
|
|
|
|
|
+ result.add(item);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return result;
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ throw new BusinessException("流程模型解析失败");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|