Browse Source

质检-资料填报-新增节点多个模式调整

LHB 3 tuần trước cách đây
mục cha
commit
e620794be5

+ 151 - 30
blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java

@@ -1967,13 +1967,20 @@ public R<Boolean> copyContractTreeNode(@RequestBody CopyContractTreeNodeVO vo) {
             }
 
             //TODO 20250414-lhb-新增 添加祖级字段 ancestorsPId
-            List<WbsTreeContract> contractWbsTreeByContractId = wbsTreeContractClient.getContractWbsTreeByContractId(Long.valueOf(needCopyNode.getContractId()));
-            contractWbsTreeByContractId.addAll(saveList);
-            Map<Long, WbsTreeContract> collect = contractWbsTreeByContractId.stream().collect(Collectors.toMap(WbsTreeContract::getPKeyId, Function.identity()));
-            saveList.forEach(node -> {
-                String correctAncestors = createAncestorsPId(node,collect);;
-                node.setAncestorsPId(correctAncestors);
-            });
+            //因为复制选中节点,所以要查询出选中节点的父节点信息 来组装祖级节点
+            if(needCopyNode != null){
+                Long parentPKeyId = null;
+                String ancestorsPId = null;
+                if(needCopyNode.getPId() == 0L){
+                    ancestorsPId = "0";
+                    parentPKeyId = 0L;
+                }else{
+                    WbsTreeContract parentNode = this.wbsTreeContractClient.getContractNodeByPrimaryKeyId(String.valueOf(needCopyNode.getPId()));
+                    ancestorsPId = parentNode.getAncestorsPId();
+                    parentPKeyId = parentNode.getPKeyId();
+                }
+                attachNodesToTarget(saveList,parentPKeyId,ancestorsPId);
+            }
         }
         needCopyNode.setNodeName(vo.getNeedCopyNodeName());
 
@@ -2141,6 +2148,26 @@ public R<Boolean> copyContractTreeNode(@RequestBody CopyContractTreeNodeVO vo) {
                                     this.addCopyTabData(needCopyNode, toCopyNode, tabOwner, resultTablesData, addTabList, vo.getIsCopyData(), addNewFileTabs);
                                 }
                             }
+
+
+                            /*重构祖级id*/
+                            List<WbsTreeContract> resultAll = new ArrayList<>();
+                            resultAll.addAll(addNodeList);
+                            resultAll.addAll(addTabList);
+                            //因为复制选中节点,所以要查询出选中节点的父节点信息 来组装祖级节点
+                            if(needCopyNode != null && CollectionUtil.isNotEmpty(resultAll)){
+                                Long parentPKeyId = null;
+                                String ancestorsPId = null;
+                                if(needCopyNode.getPId() == 0L){
+                                    ancestorsPId = "0";
+                                    parentPKeyId = 0L;
+                                }else{
+                                    WbsTreeContract parentNode = this.wbsTreeContractClient.getContractNodeByPrimaryKeyId(String.valueOf(toCopyVO.getPrimaryKeyId()));
+                                    ancestorsPId = parentNode.getAncestorsPId();
+                                    parentPKeyId = parentNode.getPKeyId();
+                                }
+                                attachNodesToTarget(resultAll,parentPKeyId,ancestorsPId);
+                            }
                         }
                     }
                 }
@@ -2150,14 +2177,6 @@ public R<Boolean> copyContractTreeNode(@RequestBody CopyContractTreeNodeVO vo) {
                 resultAll.addAll(addNodeList);
                 resultAll.addAll(addTabList);
 
-                //TODO 20250414-lhb-新增
-                List<WbsTreeContract> contractWbsTreeByContractId = wbsTreeContractClient.getContractWbsTreeByContractId(Long.valueOf(contractId));
-                contractWbsTreeByContractId.addAll(resultAll);
-                Map<Long, WbsTreeContract> collect = contractWbsTreeByContractId.stream().collect(Collectors.toMap(WbsTreeContract::getPKeyId, Function.identity()));
-                resultAll.forEach(node -> {
-                    String correctAncestors = createAncestorsPId(node,collect);;
-                    node.setAncestorsPId(correctAncestors);
-                });
 
                 List<WbsTreeContract> allData = this.reBuildAncestors(resultAll);
                 List<WbsTreeContract> nodes = allData.stream().filter(f -> f.getType().equals(1)).collect(Collectors.toList());
@@ -3966,24 +3985,20 @@ public R<Boolean> saveContractTreeNode(@RequestBody AddContractTreeNodeVO vo) {
             saveList.addAll(customResult);
         }
         //找到最顶级节点设置parentId
-        WbsTreeContract topLevelNode = findTopLevelNode(saveList);
-        if (ObjectUtils.isNotEmpty(topLevelNode)) {
+        List<WbsTreeContract> topLevelNode = findTopLevelNode(saveList);
+        if (CollectionUtil.isNotEmpty(topLevelNode)) {
             for (WbsTreeContract wbsTreeContract : saveList) {
-                if (topLevelNode.getPKeyId().equals(wbsTreeContract.getPKeyId())) {
-                    wbsTreeContract.setParentId(treeContract.getId());
-                    //TODO 20250414-lhb-新增
-                    wbsTreeContract.setPId(treeContract.getPKeyId());
+                for (WbsTreeContract contract : topLevelNode) {
+                    if (contract.getPKeyId().equals(wbsTreeContract.getPKeyId())) {
+                        wbsTreeContract.setParentId(treeContract.getId());
+                        //TODO 20250414-lhb-新增
+                        wbsTreeContract.setPId(treeContract.getPKeyId());
+                    }
                 }
             }
         }
         //TODO 20250414-lhb-新增 添加ancestorsPId字段
-        List<WbsTreeContract> contractWbsTreeByContractId = wbsTreeContractClient.getContractWbsTreeByContractId(Long.valueOf(treeContract.getContractId()));
-        contractWbsTreeByContractId.addAll(saveList);
-        Map<Long, WbsTreeContract> collect = contractWbsTreeByContractId.stream().collect(Collectors.toMap(WbsTreeContract::getPKeyId, Function.identity()));
-        saveList.forEach(node -> {
-            String correctAncestors = createAncestorsPId(node,collect);;
-            node.setAncestorsPId(correctAncestors);
-        });
+        attachNodesToTarget(saveList,treeContract.getPKeyId(),treeContract.getAncestorsPId());
 
         R<Boolean> booleanR = this.saveOrCopyNodeTree(saveList, saveLedger, 2, treeContract);
 
@@ -4009,16 +4024,20 @@ public R<String> getDICengNodeName(@RequestParam Long pKeyId,@RequestParam Long
     return R.data("");
 }
 
-public static WbsTreeContract findTopLevelNode(List<WbsTreeContract> saveList) {
+public static List<WbsTreeContract> findTopLevelNode(List<WbsTreeContract> saveList) {
     Set<Long> nodeIds = new HashSet<>();
     for (WbsTreeContract node : saveList) {
         nodeIds.add(node.getId());
     }
+    List<WbsTreeContract> parentNodes = new ArrayList<>();
     for (WbsTreeContract node : saveList) {
         if (!nodeIds.contains(node.getParentId())) {
-            return node;
+            parentNodes.add(node);
         }
     }
+    if(CollectionUtil.isNotEmpty(parentNodes)){
+        return parentNodes;
+    }
     return null;
 }
 
@@ -4893,4 +4912,106 @@ public R<Object> customAddContractNode(@RequestBody CustomAddContractNodeDTO dto
         }
     }
 
+    public void attachNodesToTarget(List<WbsTreeContract> newNodes, Long targetId, String targetAncestors) {
+        // 1. 找到新数据中的顶层节点(新树的根节点)
+        List<WbsTreeContract> newRoot = findRootNode(newNodes);
+
+        // 2. 将新树的根节点绑定到目标节点
+        newRoot.forEach(f -> {
+            f.setPId(targetId);
+            f.setAncestorsPId(calculateAncestors(targetAncestors, targetId));
+
+
+            // 3. 构建映射关系
+            Map<Long, WbsTreeContract> nodeMap = new HashMap<>();
+            Map<Long, List<WbsTreeContract>> childrenMap = new HashMap<>();
+
+            for (WbsTreeContract node : newNodes) {
+                nodeMap.put(node.getPKeyId(), node);
+                childrenMap.computeIfAbsent(node.getPId(), k -> new ArrayList<>()).add(node);
+            }
+
+            // 4. 安全层序遍历(带循环检测)
+            List<WbsTreeContract> list = childrenMap.get(f.getPKeyId());
+            if(CollectionUtil.isNotEmpty(list)){
+                //如果是多个根节点
+                safeBfsTraversal(f, childrenMap, newNodes.size());
+            }
+        });
+
+
+
+    }
+
+    private void safeBfsTraversal(WbsTreeContract root,
+                                  Map<Long, List<WbsTreeContract>> childrenMap,
+                                  int totalNodes) {
+        Queue<WbsTreeContract> queue = new LinkedList<>();
+        Set<Long> visited = new HashSet<>();  // 已访问节点集合
+        queue.add(root);
+        visited.add(root.getPKeyId());
+
+        int processedCount = 0;  // 已处理节点计数器
+        final int MAX_DEPTH = 100;  // 最大深度保护
+
+        while (!queue.isEmpty()) {
+            WbsTreeContract parent = queue.poll();
+            processedCount++;
+
+            // 安全检测1:防止循环引用导致无限循环
+            if (processedCount > totalNodes * 2) {
+                throw new IllegalStateException("处理节点数超过预期,可能存在循环引用。已处理: "
+                        + processedCount + ",总节点: " + totalNodes);
+            }
+
+            // 安全检测2:防止路径过长
+            if (parent.getAncestorsPId().split(",").length > MAX_DEPTH) {
+                throw new IllegalStateException("祖级路径超过最大深度限制: " + MAX_DEPTH);
+            }
+
+            List<WbsTreeContract> children = childrenMap.get(parent.getPKeyId());
+            if (children == null) continue;
+
+            for (WbsTreeContract child : children) {
+                // 安全检测3:检查循环引用
+                if (visited.contains(child.getPKeyId())) {
+                    throw new IllegalStateException("检测到循环引用: 节点" + child.getPKeyId()
+                            + " -> 节点" + parent.getPKeyId());
+                }
+
+                // 更新祖级路径 = 父路径 + 父ID
+                child.setAncestorsPId(calculateAncestors(parent.getAncestorsPId(), parent.getPKeyId()));
+
+                queue.add(child);
+                visited.add(child.getPKeyId());
+            }
+        }
+
+    }
+
+    private String calculateAncestors(String parentAncestors, Long parentId) {
+        if (parentAncestors == null || parentAncestors.isEmpty()) {
+            return parentId.toString();
+        }
+        return parentAncestors + "," + parentId;
+    }
+
+    private List<WbsTreeContract> findRootNode(List<WbsTreeContract> nodes) {
+        Set<Long> nodeIds = new HashSet<>();
+        for (WbsTreeContract node : nodes) {
+            nodeIds.add(node.getPKeyId());
+        }
+        List<WbsTreeContract> parentNodes = new ArrayList<>();
+        for (WbsTreeContract node : nodes) {
+            Long parentId = node.getPId();
+            // 父节点为空 或 父节点不在当前新数据列表中 → 视为根节点
+            if (parentId == null || !nodeIds.contains(parentId)) {
+                parentNodes.add(node);
+            }
+        }
+        if (CollectionUtil.isNotEmpty(parentNodes)) {
+            return parentNodes;
+        }
+        throw new IllegalArgumentException("新数据中未找到根节点");
+    }
 }