Quellcode durchsuchen

流程进度展示优化

ye-zhaojia vor 2 Wochen
Ursprung
Commit
f2cb2ef263

+ 105 - 0
src/main/java/com/qqflow/engine/domain/flow/assembler/ApprovalTaskDTOAssembler.java

@@ -1,6 +1,15 @@
 package com.qqflow.engine.domain.flow.assembler;
 
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.qqflow.engine.domain.flow.dto.ApprovalTaskDTO;
+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.model.SubNodeConfig;
+import com.qqflow.engine.domain.flow.po.ProcessDefinition;
+import com.qqflow.engine.domain.flow.po.ProcessInstance;
 import com.qqflow.engine.domain.system.entity.SysRole;
 import com.qqflow.engine.domain.system.entity.SysUser;
 import com.qqflow.engine.domain.system.mapper.SysRoleMapper;
@@ -10,8 +19,10 @@ import org.springframework.stereotype.Component;
 import org.springframework.util.CollectionUtils;
 
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.stream.Collectors;
 
@@ -26,6 +37,9 @@ public class ApprovalTaskDTOAssembler {
 
     private final SysUserMapper sysUserMapper;
     private final SysRoleMapper sysRoleMapper;
+    private final ProcessInstanceMapper processInstanceMapper;
+    private final ProcessDefinitionMapper processDefinitionMapper;
+    private final ObjectMapper objectMapper;
 
     public void fillAssigneeName(List<ApprovalTaskDTO> records) {
         if (CollectionUtils.isEmpty(records)) {
@@ -66,4 +80,95 @@ public class ApprovalTaskDTOAssembler {
             }
         }
     }
+
+    /**
+     * 按流程定义的子节点配置填充任务 DTO 的 subNodeName(子节点名称)。
+     * 任务表仅保存 subNodeId,子节点名称需从对应流程定义模型的 properties.subNodes 解析。
+     */
+    public void fillSubNodeName(List<ApprovalTaskDTO> records) {
+        if (CollectionUtils.isEmpty(records)) {
+            return;
+        }
+        List<ApprovalTaskDTO> withSub = records.stream()
+                .filter(r -> r.getSubNodeId() != null && !r.getSubNodeId().isBlank())
+                .collect(Collectors.toList());
+        if (withSub.isEmpty()) {
+            return;
+        }
+        Set<Long> instanceIds = withSub.stream()
+                .map(ApprovalTaskDTO::getInstanceId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toSet());
+        if (instanceIds.isEmpty()) {
+            return;
+        }
+        List<ProcessInstance> instances = this.processInstanceMapper.selectBatchIds(instanceIds);
+        Map<Long, Long> instanceDefMap = new HashMap<>();
+        Set<Long> defIds = new HashSet<>();
+        for (ProcessInstance pi : instances) {
+            if (pi == null || pi.getProcessDefinitionId() == null) {
+                continue;
+            }
+            instanceDefMap.put(pi.getId(), pi.getProcessDefinitionId());
+            defIds.add(pi.getProcessDefinitionId());
+        }
+        if (defIds.isEmpty()) {
+            return;
+        }
+        // definitionId -> (nodeId -> (subNodeId -> subNodeName))
+        Map<Long, Map<String, Map<String, String>>> cache = new HashMap<>();
+        for (Long defId : defIds) {
+            ProcessDefinition def = this.processDefinitionMapper.selectById(defId);
+            if (def == null || def.getModelJson() == null) {
+                continue;
+            }
+            try {
+                FlowModel model = this.objectMapper.readValue(def.getModelJson(), FlowModel.class);
+                Map<String, Map<String, String>> nodeSubMap = new HashMap<>();
+                if (model != null && model.getNodes() != null) {
+                    for (FlowNode node : model.getNodes()) {
+                        Object subNodesObj = node.getProperties() != null ? node.getProperties().get("subNodes") : null;
+                        if (subNodesObj == null) {
+                            continue;
+                        }
+                        List<SubNodeConfig> subNodes = this.objectMapper.convertValue(
+                                subNodesObj, new TypeReference<List<SubNodeConfig>>() {});
+                        if (CollectionUtils.isEmpty(subNodes)) {
+                            continue;
+                        }
+                        Map<String, String> subNameMap = new HashMap<>();
+                        for (SubNodeConfig sn : subNodes) {
+                            if (sn.getId() != null) {
+                                subNameMap.put(sn.getId(), sn.getName());
+                            }
+                        }
+                        if (!subNameMap.isEmpty()) {
+                            nodeSubMap.put(node.getId(), subNameMap);
+                        }
+                    }
+                }
+                cache.put(defId, nodeSubMap);
+            } catch (Exception ignored) {
+                // 模型解析失败时该定义下的子节点名称保持为空
+            }
+        }
+        for (ApprovalTaskDTO record : withSub) {
+            Long defId = instanceDefMap.get(record.getInstanceId());
+            if (defId == null) {
+                continue;
+            }
+            Map<String, Map<String, String>> nodeSubMap = cache.get(defId);
+            if (nodeSubMap == null) {
+                continue;
+            }
+            Map<String, String> subNameMap = nodeSubMap.get(record.getNodeId());
+            if (subNameMap == null) {
+                continue;
+            }
+            String subName = subNameMap.get(record.getSubNodeId());
+            if (subName != null && !subName.isBlank()) {
+                record.setSubNodeName(subName);
+            }
+        }
+    }
 }

+ 3 - 0
src/main/java/com/qqflow/engine/domain/flow/service/impl/ApprovalTaskServiceImpl.java

@@ -102,6 +102,7 @@ public class ApprovalTaskServiceImpl implements ApprovalTaskService {
                 .peek(this::fillUrgency)
                 .collect(Collectors.toList());
         this.approvalTaskDTOAssembler.fillAssigneeName(records);
+        this.approvalTaskDTOAssembler.fillSubNodeName(records);
         return PageResult.of(page.getTotal(), records);
     }
 
@@ -142,6 +143,7 @@ public class ApprovalTaskServiceImpl implements ApprovalTaskService {
                 .map(ApprovalTaskDTO::of)
                 .collect(Collectors.toList());
         this.approvalTaskDTOAssembler.fillAssigneeName(records);
+        this.approvalTaskDTOAssembler.fillSubNodeName(records);
         return PageResult.of(page.getTotal(), records);
     }
 
@@ -309,6 +311,7 @@ public class ApprovalTaskServiceImpl implements ApprovalTaskService {
                 .map(ApprovalTaskDTO::of)
                 .collect(Collectors.toList());
         this.approvalTaskDTOAssembler.fillAssigneeName(records);
+        this.approvalTaskDTOAssembler.fillSubNodeName(records);
         return PageResult.of(page.getTotal(), records);
     }