Browse Source

feat: 优化1——登录背景图,筛选选项展示优化,初始化流程查看优化

wuwenyi 3 ngày trước cách đây
mục cha
commit
50a1730f1c

+ 9 - 0
src/main/java/com/qqflow/engine/config/WebConfig.java

@@ -2,10 +2,12 @@ package com.qqflow.engine.config;
 
 import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
 import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
+import com.qqflow.engine.common.config.HttpLoggingInterceptor;
 import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
 import java.time.format.DateTimeFormatter;
@@ -32,5 +34,12 @@ public class WebConfig implements WebMvcConfigurer {
                 .maxAge(3600);
     }
 
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        registry.addInterceptor(new HttpLoggingInterceptor())
+                .addPathPatterns("/**")
+                .excludePathPatterns("/static/**", "/swagger-ui/**", "/v3/api-docs/**", "/doc.html");
+    }
+
     // 文件下载不再通过静态资源映射公开访问,统一走 FileDownloadController 做权限校验
 }

+ 3 - 2
src/main/java/com/qqflow/engine/domain/flow/controller/ProcessInstanceController.java

@@ -50,10 +50,11 @@ public class ProcessInstanceController {
             @RequestParam(defaultValue = "1") Integer pageNum,
             @RequestParam(defaultValue = "10") Integer pageSize,
             @RequestParam(required = false) Integer status,
+            @RequestParam(required = false) Long processDefinitionId,
             @RequestParam(required = false) String definitionName,
             @RequestParam(required = false) String currentNodeName,
             @RequestParam(required = false) String applicantName) {
-        return Result.ok(this.processInstanceService.list(null, status, definitionName, currentNodeName, applicantName, pageNum, pageSize));
+        return Result.ok(this.processInstanceService.list(null, status, processDefinitionId, definitionName, currentNodeName, applicantName, pageNum, pageSize));
     }
 
     @GetMapping("/mine")
@@ -65,7 +66,7 @@ public class ProcessInstanceController {
             @RequestParam(required = false) String definitionName,
             @RequestParam(required = false) String currentNodeName) {
         Long applicantId = SecurityUtils.getUserId();
-        return Result.ok(this.processInstanceService.list(applicantId, status, definitionName, currentNodeName, null, pageNum, pageSize));
+        return Result.ok(this.processInstanceService.list(applicantId, status, null, definitionName, currentNodeName, null, pageNum, pageSize));
     }
 
     @GetMapping("/{id}")

+ 1 - 1
src/main/java/com/qqflow/engine/domain/flow/service/ProcessInstanceService.java

@@ -15,7 +15,7 @@ public interface ProcessInstanceService {
     /** 从指定节点发起流程(导入时使用),前置节点自动跳过 */
     Long startProcessAtNode(StartProcessDTO dto, String nodeName);
 
-    PageResult<ProcessInstanceDTO> list(Long applicantId, Integer status, String definitionName, String currentNodeName, String applicantName, Integer pageNum, Integer pageSize);
+    PageResult<ProcessInstanceDTO> list(Long applicantId, Integer status, Long processDefinitionId, String definitionName, String currentNodeName, String applicantName, Integer pageNum, Integer pageSize);
 
     ProcessInstanceDTO getDetail(Long id);
 

+ 59 - 4
src/main/java/com/qqflow/engine/domain/flow/service/impl/ProcessInstanceServiceImpl.java

@@ -27,6 +27,7 @@ import com.qqflow.engine.domain.flow.mapper.ApprovalTaskMapper;
 import com.qqflow.engine.domain.flow.mapper.AttachmentMapper;
 import com.qqflow.engine.domain.flow.mapper.ProcessDefinitionMapper;
 import com.qqflow.engine.domain.flow.mapper.ProcessInstanceMapper;
+import com.qqflow.engine.domain.flow.model.FlowEdge;
 import com.qqflow.engine.domain.flow.model.FlowModel;
 import com.qqflow.engine.domain.flow.model.FlowNode;
 import com.qqflow.engine.domain.flow.po.ApprovalRecord;
@@ -50,8 +51,12 @@ import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
+import java.util.ArrayDeque;
 import java.util.Collections;
+import java.util.Deque;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -110,9 +115,9 @@ public class ProcessInstanceServiceImpl implements ProcessInstanceService {
     }
 
     @Override
-    public PageResult<ProcessInstanceDTO> list(Long applicantId, Integer status, String definitionName, String currentNodeName, String applicantName, Integer pageNum, Integer pageSize) {
+    public PageResult<ProcessInstanceDTO> list(Long applicantId, Integer status, Long processDefinitionId, String definitionName, String currentNodeName, String applicantName, Integer pageNum, Integer pageSize) {
         Page<ProcessInstance> page = new Page<>(pageNum, pageSize);
-        this.processInstanceMapper.selectInstanceList(page, applicantId, status, definitionName, currentNodeName, applicantName, null);
+        this.processInstanceMapper.selectInstanceList(page, applicantId, status, definitionName, currentNodeName, applicantName, processDefinitionId);
         List<ProcessInstanceDTO> records = this.enrichInstanceDtos(page.getRecords());
         if (currentNodeName != null && !currentNodeName.isBlank()) {
             records = records.stream()
@@ -214,11 +219,12 @@ public class ProcessInstanceServiceImpl implements ProcessInstanceService {
         String currentNodeId = instance.getCurrentNodeId();
         Integer instanceStatus = instance.getStatus();
 
-        // 构建节点进度列表
+        // 构建节点进度列表(按流程拓扑顺序排序)
         List<NodeProgressDTO> nodeProgressList = new ArrayList<>();
         int remainingCount = 0;
 
-        for (FlowNode node : model.getNodes()) {
+        List<FlowNode> sortedNodes = this.sortByFlowOrder(model.getNodes(), model.getEdges());
+        for (FlowNode node : sortedNodes) {
             String type = node.getType();
             if (NodeType.START.getCode().equals(type) || NodeType.END.getCode().equals(type)
                     || NodeType.CONDITION.getCode().equals(type) || NodeType.CC.getCode().equals(type)) {
@@ -771,4 +777,53 @@ public class ProcessInstanceServiceImpl implements ProcessInstanceService {
         }
         return null;
     }
+
+    /**
+     * 按流程拓扑顺序排序节点:从 START 节点出发 BFS,沿 edges 遍历。
+     * 不可达节点(不应出现)追加在末尾。
+     */
+    private List<FlowNode> sortByFlowOrder(List<FlowNode> nodes, List<FlowEdge> edges) {
+        if (nodes == null || nodes.isEmpty()) return new ArrayList<>();
+        List<FlowEdge> safeEdges = edges != null ? edges : Collections.emptyList();
+
+        // 构建邻接表:sourceId → [targetIds]
+        Map<String, List<String>> adj = new LinkedHashMap<>();
+        for (FlowEdge edge : safeEdges) {
+            adj.computeIfAbsent(edge.getSourceNodeId(), k -> new ArrayList<>()).add(edge.getTargetNodeId());
+        }
+
+        // 节点 ID → 节点映射
+        Map<String, FlowNode> nodeMap = nodes.stream()
+                .collect(Collectors.toMap(FlowNode::getId, n -> n, (a, b) -> a));
+
+        // 查找 START 节点
+        FlowNode startNode = nodes.stream()
+                .filter(n -> NodeType.START.getCode().equals(n.getType()))
+                .findFirst().orElse(null);
+        if (startNode == null) return new ArrayList<>(nodes);
+
+        // BFS
+        List<FlowNode> sorted = new ArrayList<>();
+        Set<String> visited = new HashSet<>();
+        Deque<String> queue = new ArrayDeque<>();
+        queue.add(startNode.getId());
+
+        while (!queue.isEmpty()) {
+            String id = queue.poll();
+            if (!visited.add(id)) continue;
+            FlowNode node = nodeMap.get(id);
+            if (node != null) sorted.add(node);
+
+            for (String nextId : adj.getOrDefault(id, Collections.emptyList())) {
+                if (!visited.contains(nextId)) queue.add(nextId);
+            }
+        }
+
+        // 追加不可达节点
+        for (FlowNode node : nodes) {
+            if (!visited.contains(node.getId())) sorted.add(node);
+        }
+
+        return sorted;
+    }
 }