Explorar o código

合同段树节点颜色相关

liuyc hai 1 ano
pai
achega
eec7f77d15

+ 4 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsTreeContractLazyVO.java

@@ -5,6 +5,7 @@ import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import java.io.Serializable;
+import java.util.List;
 
 /**
  * 客户端合同段树懒加载VO
@@ -73,4 +74,7 @@ public class WbsTreeContractLazyVO implements Serializable {
     @ApiModelProperty("是否又混泥土,0否1是")
     private Integer isConcrete;
 
+    @ApiModelProperty(value = "子级集合(在构造树形结构时使用)")
+    private List<WbsTreeContractLazyVO> children;
+
 }

+ 209 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/bean/NodeVO.java

@@ -0,0 +1,209 @@
+package org.springblade.manager.bean;
+
+import cn.hutool.core.util.ObjectUtil;
+import lombok.Data;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.stream.Collectors;
+
+/**
+ * @author liuyc
+ * @date 2023年9月27日16:46:43
+ * @description 计算节点颜色状态
+ */
+@Data
+public class NodeVO {
+
+    private Long pKeyId;
+    private Long id;
+    private Long parentId;
+    private List<NodeVO> children;
+    private Integer status;
+
+    /**
+     * DFS
+     *
+     * @param nodeList
+     */
+    public static void calculateStatusToDFS(List<NodeVO> nodeList, Map<Long, NodeVO> nodeParentGroupToIdMap) {
+        NodeVO rootNode = findRootNode(nodeList);
+        if (rootNode != null) {
+            calculateNodeStatusToDFS(rootNode, nodeParentGroupToIdMap);
+        }
+    }
+
+    /**
+     * BFS
+     *
+     * @param nodeList
+     * @param nodeParentGroupToIdMap
+     */
+    public static void calculateStatusToBFS(List<NodeVO> nodeList, Map<Long, NodeVO> nodeParentGroupToIdMap) {
+        //计算根节点的颜色
+        NodeVO rootNode = findRootNode(nodeList);
+        if (rootNode != null) {
+            calculateNodeStatusToBFS(rootNode);
+
+            Queue<NodeVO> queue = new LinkedList<>();
+            queue.addAll(rootNode.getChildren());
+
+            while (!queue.isEmpty()) {
+                NodeVO node = queue.poll();
+                if (node != null) {
+                    calculateNodeStatusToBFS(node);
+
+                    if (node.getParentId() != null) {
+                        NodeVO nodeVO = nodeParentGroupToIdMap.get(node.getParentId());
+                        if (nodeVO != null) {
+                            List<NodeVO> children = nodeVO.getChildren();
+                            if (children != null) {
+                                queue.addAll(children);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+
+    /**
+     * 获取根节点
+     *
+     * @param nodeList
+     * @return
+     */
+    private static NodeVO findRootNode(List<NodeVO> nodeList) {
+        for (NodeVO node : nodeList) {
+            if (node.getParentId().equals(0L)) {
+                return node;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * DFS 判断节点状态
+     *
+     * @param node
+     */
+    private static void calculateNodeStatusToDFS(NodeVO node, Map<Long, NodeVO> nodeParentGroupToIdMap) {
+        //最底层节点直接返回
+        if (ObjectUtil.isEmpty(node.getChildren())) {
+            return;
+        }
+
+        //递归处理子节点
+        for (NodeVO child : node.getChildren()) {
+            calculateNodeStatusToDFS(child, nodeParentGroupToIdMap);
+        }
+
+        //判断子级
+        List<Integer> childStatusList = node.getChildren().stream().map(NodeVO::getStatus).collect(Collectors.toList());
+
+        //如果子节点都是相同的状态,则父节点状态也为该状态
+        if (childStatusList.stream().distinct().count() == 1) {
+            node.setStatus(childStatusList.get(0));
+            // 更新父节点的状态
+            if (node.getParentId() != null) {
+                NodeVO parentNode = nodeParentGroupToIdMap.get(node.getParentId());
+                if (parentNode != null) {
+                    calculateNodeStatusToDFS(parentNode, nodeParentGroupToIdMap);
+                }
+            }
+            return;
+        }
+
+        //判断是否存在同时只存在1、3的情况
+        if (childStatusList.contains(1) && childStatusList.contains(3) && !childStatusList.contains(2)) {
+            node.setStatus(2);
+            return;
+        }
+
+        //判断是否存在同时只存在3、4的情况
+        if (childStatusList.contains(3) && childStatusList.contains(4) && !childStatusList.contains(1) && !childStatusList.contains(2)) {
+            node.setStatus(3);
+            return;
+        }
+
+        //判断是否存在只有1但不全是1的情况
+        if (childStatusList.contains(1) && !childStatusList.contains(2) && !childStatusList.contains(3) && !childStatusList.contains(4)) {
+            node.setStatus(2);
+            return;
+        }
+
+        //判断是否存在只有2但不全是2的情况
+        if (childStatusList.contains(2) && !childStatusList.contains(1) && !childStatusList.contains(3) && !childStatusList.contains(4)) {
+            node.setStatus(2);
+            return;
+        }
+
+        //判断是否存在只有3但不全是3的情况
+        if (childStatusList.contains(3) && !childStatusList.contains(1) && !childStatusList.contains(2) && !childStatusList.contains(4)) {
+            node.setStatus(3);
+            return;
+        }
+
+        //其他情况,父节点状态默认为2
+        node.setStatus(2);
+    }
+
+    /**
+     * BFS
+     *
+     * @param node
+     */
+    private static void calculateNodeStatusToBFS(NodeVO node) {
+        //最底层节点直接返回
+        if (ObjectUtil.isEmpty(node.getChildren())) {
+            return;
+        }
+
+        //判断子级
+        List<Integer> childStatusList = node.getChildren().stream().map(NodeVO::getStatus).collect(Collectors.toList());
+
+        //如果子节点都是相同的状态,则父节点状态也为该状态
+        if (childStatusList.stream().distinct().count() == 1) {
+            node.setStatus(childStatusList.get(0));
+            return;
+        }
+
+        //判断是否存在同时只存在1、3的情况
+        if (childStatusList.contains(1) && childStatusList.contains(3) && !childStatusList.contains(2)) {
+            node.setStatus(2);
+            return;
+        }
+
+        //判断是否存在同时只存在3、4的情况
+        if (childStatusList.contains(3) && childStatusList.contains(4) && !childStatusList.contains(1) && !childStatusList.contains(2)) {
+            node.setStatus(3);
+            return;
+        }
+
+        //判断是否存在只有1但不全是1的情况
+        if (childStatusList.contains(1) && !childStatusList.contains(2) && !childStatusList.contains(3) && !childStatusList.contains(4)) {
+            node.setStatus(2);
+            return;
+        }
+
+        //判断是否存在只有2但不全是2的情况
+        if (childStatusList.contains(2) && !childStatusList.contains(1) && !childStatusList.contains(3) && !childStatusList.contains(4)) {
+            node.setStatus(2);
+            return;
+        }
+
+        //判断是否存在只有3但不全是3的情况
+        if (childStatusList.contains(3) && !childStatusList.contains(1) && !childStatusList.contains(2) && !childStatusList.contains(4)) {
+            node.setStatus(3);
+            return;
+        }
+
+        //其他情况,父节点状态默认为2
+        node.setStatus(2);
+    }
+
+
+}

+ 2 - 2
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreeContractController.java

@@ -256,14 +256,14 @@ public class WbsTreeContractController extends BladeController {
     }
 
     /**
-     * 影像资料-懒加载获取影像资料合同段树(统计颜色、存储部位文件数量)
+     * 影像资料-懒加载获取影像资料合同段树(存储部位文件数量)
      *
      * @author liuyc
      * @date 2023年8月24日14:21:03
      */
     @GetMapping("/image/lazyQueryContractWbsTree")
     @ApiOperationSupport(order = 9)
-    @ApiOperation(value = "影像资料-懒加载获取影像资料合同段树(统计颜色、存储部位文件数量)")
+    @ApiOperation(value = "影像资料-懒加载获取影像资料合同段树(存储部位文件数量)")
     @ApiImplicitParams(value = {
             @ApiImplicitParam(name = "primaryKeyId"),
             @ApiImplicitParam(name = "parentId", value = "父节点id,为空则查询第一级节点"),

+ 119 - 135
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeContractServiceImpl.java

@@ -28,6 +28,7 @@ import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.secure.utils.SecureUtil;
 import org.springblade.core.tool.node.ForestNodeMerger;
 import org.springblade.core.tool.utils.*;
+import org.springblade.manager.bean.NodeVO;
 import org.springblade.manager.dto.RangeInfo;
 import org.springblade.manager.dto.WbsTreeContractDTO;
 import org.springblade.manager.dto.WbsTreeContractDTO2;
@@ -679,7 +680,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
         if (ObjectUtil.isNotEmpty(contractId)) {
             ContractInfo contractInfo = jdbcTemplate.query("select contract_name,contract_type from m_contract_info where id = " + contractId, new BeanPropertyRowMapper<>(ContractInfo.class)).stream().findAny().orElse(null);
             if (contractInfo != null) {
-                //TODO 施工合同段
+                //TODO ************ 施工合同段 ************
                 if (new Integer(1).equals(contractInfo.getContractType())) {
                     //获取当前合同段所有缓存节点信息
                     List<WbsTreeContractLazyVO> nodesAll;
@@ -702,8 +703,6 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                         Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(WbsTreeContractLazyVO::getPKeyId))),
                                         ArrayList::new
                                 ));
-                        //所有节点Map
-                        //Map<Long, List<WbsTreeContractLazyVO>> allNodesParentGroup = distinctNodesAll.stream().collect(Collectors.groupingBy(WbsTreeContractLazyVO::getParentId));
 
                         //所有最底层节点
                         List<WbsTreeContractLazyVO> distinctLowestNodesAll = distinctNodesAll.stream().filter(f -> f.getHasChildren().equals(0)).collect(Collectors.collectingAndThen(
@@ -722,7 +721,8 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                 .collect(Collectors.toMap(WbsTreeContractLazyQueryInfoVO::getWbsId, WbsTreeContractLazyQueryInfoVO::getStatus, (existingValue, newValue) -> existingValue));
                         List<Long> pKeyIdList = new ArrayList<>(queryInfoMaps.keySet());
 
-                        //填报过的所有最底层节点,处理数量
+                        //TODO 处理数量
+                        //填报过的所有最底层节点
                         List<WbsTreeContractLazyVO> lowestNodesTB = distinctLowestNodesAll.stream().filter(f -> pKeyIdList.contains(f.getPKeyId())).collect(Collectors.toList());
                         List<Long> lowestNodeParentIdsTB = lowestNodesTB.stream().map(WbsTreeContractLazyVO::getParentId).collect(Collectors.toList());
                         List<WbsTreeContractLazyVO> resultParentNodesTB = new ArrayList<>();
@@ -740,18 +740,22 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                         vo.setColorStatus(1);
                                     }
                                 }).collect(Collectors.toMap(WbsTreeContractLazyVO::getPKeyId, Function.identity()));
-                        /*List<WbsTreeContractLazyVO> lowestNodesReList = new ArrayList<>(lowestNodesMap.values());
-                        Map<Long, WbsTreeContractLazyVO> distinctParentNodesTBIdKeyMap = resultParentNodesTB.stream()
-                                .collect(Collectors.collectingAndThen(
-                                        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(WbsTreeContractLazyVO::getPKeyId))),
-                                        ArrayList::new
-                                )).stream().collect(Collectors.toMap(WbsTreeContractLazyVO::getId, Function.identity()));
-
-                        //构造完成的所有最底层节点,处理父节点颜色
-                        Map<Long, WbsTreeContractLazyVO> nodeColorMap = new HashMap<>();
-                        this.recursiveParentNodeColorStatus(lowestNodesReList, distinctParentNodesTBIdKeyMap, allNodesParentGroup, nodeColorMap);*/
 
-                        //处理最终结果集
+                        //TODO 处理颜色
+                        //先将WbsTreeContractLazyVO转为NodeVO
+                        List<NodeVO> nodeVOList = distinctNodesAll.stream().map(this::convertToNodeVO).collect(Collectors.toList());
+                        //转为Map<Long, NodeVO>
+                        Map<Long, NodeVO> nodeVOMap = nodeVOList.stream().collect(Collectors.toMap(NodeVO::getId, vo -> vo, (existing, replacement) -> existing));
+                        //把distinctNodesAll把所有节点转为树形结构,再转为List<NodeVO>对象
+                        List<NodeVO> treeNodeVOList = this.buildNodeTreeByStream(distinctNodesAll, lowestNodesMap);
+                        //处理节点颜色
+                        NodeVO.calculateStatusToDFS(treeNodeVOList, nodeVOMap);
+                        //把树形结构转为普通List集合
+                        List<NodeVO> nodeVOS = this.flattenTree(treeNodeVOList);
+                        //获取所有节点颜色Map
+                        Map<Long, Integer> nodeColorStatusMap = nodeVOS.stream().collect(Collectors.toMap(NodeVO::getPKeyId, NodeVO::getStatus, (existing, replacement) -> existing));
+
+                        //TODO 处理最终结果集
                         if (lazyNodes.size() > 0) {
                             //处理填报数量
                             Map<Long, Integer> countMap = new HashMap<>();
@@ -775,26 +779,25 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                     }
                                 }
 
+                                //设置数量
                                 lazyNodeVO.setSubmitCounts(ObjectUtil.isNotEmpty(countMap.get(lazyNodeVO.getPKeyId())) ? countMap.get(lazyNodeVO.getPKeyId()) : (ObjectUtil.isNotEmpty(queryInfoMaps.get(lazyNodeVO.getPKeyId())) ? 1 : 0));
 
-                                if (lazyNodeVO.getSubmitCounts() >= 1) {
-                                    lazyNodeVO.setColorStatus(2);
-                                }
-                                /*WbsTreeContractLazyVO vo = nodeColorMap.get(lazyNodeVO.getPKeyId());
-                                if (vo != null) {
-                                    lazyNodeVO.setColorStatus(vo.getColorStatus());
-                                } else {*/
-                                WbsTreeContractLazyVO lowestNode = lowestNodesMap.get(lazyNodeVO.getPKeyId());
-                                if (lowestNode != null) {
-                                    lazyNodeVO.setColorStatus(lowestNode.getColorStatus());
+                                //设置颜色
+                                Integer parentColorStatus = nodeColorStatusMap.get(lazyNodeVO.getPKeyId());
+                                if (parentColorStatus != null) {
+                                    lazyNodeVO.setColorStatus(parentColorStatus);
+                                } else {
+                                    WbsTreeContractLazyVO lowestNode = lowestNodesMap.get(lazyNodeVO.getPKeyId());
+                                    if (lowestNode != null) {
+                                        lazyNodeVO.setColorStatus(lowestNode.getColorStatus());
+                                    }
                                 }
-                                //}
                             }
                         }
                         return lazyNodes;
                     }
 
-                    //TODO 监理、业主合同段
+                    //TODO ************ 监理、业主合同段 ************
                 } else if (new Integer("2").equals(contractInfo.getContractType()) || new Integer("3").equals(contractInfo.getContractType())) {
                     List<WbsTreeContractLazyVO> lazyNodesAll = new ArrayList<>();
                     List<String> contractIds = new ArrayList<>();
@@ -833,8 +836,6 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                                 Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(WbsTreeContractLazyVO::getPKeyId))),
                                                 ArrayList::new
                                         ));
-                                //所有节点Map
-                                //Map<Long, List<WbsTreeContractLazyVO>> allNodesParentGroup = distinctNodesAll.stream().collect(Collectors.groupingBy(WbsTreeContractLazyVO::getParentId));
 
                                 //所有最底层节点
                                 List<WbsTreeContractLazyVO> distinctLowestNodesAll = distinctNodesAll.stream().filter(f -> f.getHasChildren().equals(0)).collect(Collectors.collectingAndThen(
@@ -853,7 +854,8 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                         .collect(Collectors.toMap(WbsTreeContractLazyQueryInfoVO::getWbsId, WbsTreeContractLazyQueryInfoVO::getStatus, (existingValue, newValue) -> existingValue));
                                 List<Long> pKeyIdList = new ArrayList<>(queryInfoMaps.keySet());
 
-                                //填报过的所有最底层节点,处理数量
+                                //TODO 处理数量
+                                //填报过的所有最底层节点
                                 List<WbsTreeContractLazyVO> lowestNodesTB = distinctLowestNodesAll.stream().filter(f -> pKeyIdList.contains(f.getPKeyId())).collect(Collectors.toList());
                                 List<Long> lowestNodeParentIdsTB = lowestNodesTB.stream().map(WbsTreeContractLazyVO::getParentId).collect(Collectors.toList());
                                 List<WbsTreeContractLazyVO> resultParentNodesTB = new ArrayList<>();
@@ -871,18 +873,22 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                                 vo.setColorStatus(1);
                                             }
                                         }).collect(Collectors.toMap(WbsTreeContractLazyVO::getPKeyId, Function.identity()));
-                                /*List<WbsTreeContractLazyVO> lowestNodesReList = new ArrayList<>(lowestNodesMap.values());
-                                Map<Long, WbsTreeContractLazyVO> distinctParentNodesTBIdKeyMap = resultParentNodesTB.stream()
-                                        .collect(Collectors.collectingAndThen(
-                                                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(WbsTreeContractLazyVO::getPKeyId))),
-                                                ArrayList::new
-                                        )).stream().collect(Collectors.toMap(WbsTreeContractLazyVO::getId, Function.identity()));
 
-                                //构造完成的所有最底层节点,处理父节点颜色
-                                Map<Long, WbsTreeContractLazyVO> nodeColorMap = new HashMap<>();
-                                this.recursiveParentNodeColorStatus(lowestNodesReList, distinctParentNodesTBIdKeyMap, allNodesParentGroup, nodeColorMap);*/
-
-                                //处理最终结果集
+                                //TODO 处理颜色
+                                //先将WbsTreeContractLazyVO转为NodeVO
+                                List<NodeVO> nodeVOList = distinctNodesAll.stream().map(this::convertToNodeVO).collect(Collectors.toList());
+                                //转为Map<Long, NodeVO>
+                                Map<Long, NodeVO> nodeVOMap = nodeVOList.stream().collect(Collectors.toMap(NodeVO::getId, vo -> vo, (existing, replacement) -> existing));
+                                //把distinctNodesAll把所有节点转为树形结构,再转为List<NodeVO>对象
+                                List<NodeVO> treeNodeVOList = this.buildNodeTreeByStream(distinctNodesAll, lowestNodesMap);
+                                //处理节点颜色
+                                NodeVO.calculateStatusToDFS(treeNodeVOList, nodeVOMap);
+                                //把树形结构转为普通List集合
+                                List<NodeVO> nodeVOS = this.flattenTree(treeNodeVOList);
+                                //获取所有节点颜色Map
+                                Map<Long, Integer> nodeColorStatusMap = nodeVOS.stream().collect(Collectors.toMap(NodeVO::getPKeyId, NodeVO::getStatus, (existing, replacement) -> existing));
+
+                                //TODO 处理最终结果集
                                 if (lazyNodes.size() > 0) {
                                     //处理填报数量
                                     Map<Long, Integer> countMap = new HashMap<>();
@@ -907,20 +913,19 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                             }
                                         }
 
+                                        //设置数量
                                         lazyNodeVO.setSubmitCounts(ObjectUtil.isNotEmpty(countMap.get(lazyNodeVO.getPKeyId())) ? countMap.get(lazyNodeVO.getPKeyId()) : (ObjectUtil.isNotEmpty(queryInfoMaps.get(lazyNodeVO.getPKeyId())) ? 1 : 0));
 
-                                        if (lazyNodeVO.getSubmitCounts() >= 1) {
-                                            lazyNodeVO.setColorStatus(2);
-                                        }
-                                        /*WbsTreeContractLazyVO vo = nodeColorMap.get(lazyNodeVO.getPKeyId());
-                                        if (vo != null) {
-                                            lazyNodeVO.setColorStatus(vo.getColorStatus());
-                                        } else {*/
-                                        WbsTreeContractLazyVO lowestNode = lowestNodesMap.get(lazyNodeVO.getPKeyId());
-                                        if (lowestNode != null) {
-                                            lazyNodeVO.setColorStatus(lowestNode.getColorStatus());
+                                        //设置颜色
+                                        Integer parentColorStatus = nodeColorStatusMap.get(lazyNodeVO.getPKeyId());
+                                        if (parentColorStatus != null) {
+                                            lazyNodeVO.setColorStatus(parentColorStatus);
+                                        } else {
+                                            WbsTreeContractLazyVO lowestNode = lowestNodesMap.get(lazyNodeVO.getPKeyId());
+                                            if (lowestNode != null) {
+                                                lazyNodeVO.setColorStatus(lowestNode.getColorStatus());
+                                            }
                                         }
-                                        //}
                                     }
                                 }
                                 lazyNodesAll.addAll(lazyNodes);
@@ -1019,10 +1024,8 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                         lazyNodeVO.setTitle(contractInfo.getContractName());
                                     }
                                 }
+                                //设置数量
                                 lazyNodeVO.setSubmitCounts(ObjectUtil.isNotEmpty(countMap.get(lazyNodeVO.getPKeyId())) ? countMap.get(lazyNodeVO.getPKeyId()) : (ObjectUtil.isNotEmpty(queryFileMaps.get(lazyNodeVO.getPKeyId())) ? queryFileMaps.get(lazyNodeVO.getPKeyId()) : 0));
-                                if (lazyNodeVO.getSubmitCounts() >= 1) {
-                                    lazyNodeVO.setColorStatus(2);
-                                }
                             }
                         }
                         return lazyNodes;
@@ -1124,10 +1127,8 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                                 lazyNodeVO.setTitle(sgContractInfo.getContractName());
                                             }
                                         }
+                                        //设置数量
                                         lazyNodeVO.setSubmitCounts(ObjectUtil.isNotEmpty(countMap.get(lazyNodeVO.getPKeyId())) ? countMap.get(lazyNodeVO.getPKeyId()) : (ObjectUtil.isNotEmpty(queryFileMaps.get(lazyNodeVO.getPKeyId())) ? queryFileMaps.get(lazyNodeVO.getPKeyId()) : 0));
-                                        if (lazyNodeVO.getSubmitCounts() >= 1) {
-                                            lazyNodeVO.setColorStatus(2);
-                                        }
                                     }
                                 }
                                 lazyNodesAll.addAll(lazyNodes);
@@ -1353,83 +1354,6 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
         }
     }
 
-    /**
-     * 反向递归处理父节点颜色
-     * (暂未解决父级颜色问题,因为按照这个方法构造出来的父级颜色,颜色会断层;目前上级统一显示蓝色,最底层填报数据显示上报审批状态的颜色)
-     */
-    private void recursiveParentNodeColorStatus(List<WbsTreeContractLazyVO> childNodeTBList, Map<Long, WbsTreeContractLazyVO> distinctParentNodesTBIdKeyMap, Map<Long, List<WbsTreeContractLazyVO>> allNodesParentGroup, Map<Long, WbsTreeContractLazyVO> nodeColorMap) {
-        if (childNodeTBList.size() > 0) {
-            List<WbsTreeContractLazyVO> parentNodeList = new ArrayList<>();
-            Map<Long, List<WbsTreeContractLazyVO>> lowestNodesParentGroup = childNodeTBList.stream().collect(Collectors.groupingBy(WbsTreeContractLazyVO::getParentId));
-            Map<Long, WbsTreeContractLazyVO> lowestNodesPKeyIdGroup = childNodeTBList.stream().collect(Collectors.toMap(WbsTreeContractLazyVO::getPKeyId, Function.identity()));
-
-            for (Map.Entry<Long, List<WbsTreeContractLazyVO>> lowestNodesParentGroupOne : lowestNodesParentGroup.entrySet()) {
-                Long parentId = lowestNodesParentGroupOne.getKey();
-
-                List<WbsTreeContractLazyVO> oneLevel = allNodesParentGroup.get(parentId); //根据填报的父级id,获取对应的父级id下面的所有子级,包括未填报的
-                if (oneLevel != null && oneLevel.size() > 0) {
-                    oneLevel.forEach(f -> {
-                        WbsTreeContractLazyVO tbNode = lowestNodesPKeyIdGroup.get(f.getPKeyId());
-                        if (tbNode != null) {
-                            f.setColorStatus(tbNode.getColorStatus());
-                        } else {
-                            f.setColorStatus(1);
-                        }
-                    });
-
-                    WbsTreeContractLazyVO parentNode = distinctParentNodesTBIdKeyMap.get(parentId); //获取父节点
-                    if (parentNode != null) {
-
-                        int parentColor = 0; //定义上级颜色
-                        boolean all_1 = oneLevel.stream().allMatch(node -> node.getColorStatus() == 1); // 全部是1
-                        boolean all_2 = oneLevel.stream().allMatch(node -> node.getColorStatus() == 2); // 全部是2
-                        boolean all_3 = oneLevel.stream().allMatch(node -> node.getColorStatus() == 3); // 全部是3
-                        boolean all_4 = oneLevel.stream().allMatch(node -> node.getColorStatus() == 4); // 全部是4
-
-                        boolean hasOnly_1_and_3 = oneLevel.stream()
-                                .anyMatch(node -> node.getColorStatus() == 1)
-                                && oneLevel.stream().anyMatch(node -> node.getColorStatus() == 3)
-                                && oneLevel.stream().noneMatch(node -> node.getColorStatus() != 1 && node.getColorStatus() != 3); //同时只存在1、3 == 2
-
-                        boolean hasNotAll_1 = oneLevel.stream()
-                                .anyMatch(node -> node.getColorStatus() == 1)
-                                && oneLevel.stream().anyMatch(node -> node.getColorStatus() != 1); //有1 但不全部都是1 == 2 (12、13、14、123、124、134、1234)
-                        boolean hasNotAll_2 = oneLevel.stream()
-                                .anyMatch(node -> node.getColorStatus() == 2)
-                                && oneLevel.stream().anyMatch(node -> node.getColorStatus() != 2); //有2 但不全部都是2 == 2 (12、123、1234、23、24、234)
-                        boolean hasNotAll_3 = oneLevel.stream()
-                                .anyMatch(node -> node.getColorStatus() == 3)
-                                && oneLevel.stream().anyMatch(node -> node.getColorStatus() != 3)
-                                && oneLevel.stream().noneMatch(node -> node.getColorStatus() != 3 && node.getColorStatus() != 4); //有3 但不全部都是3,且不包含34这种情况 == 2 (13、123、1234、23、234)
-                        boolean hasOnly_3_and_4 = oneLevel.stream()
-                                .anyMatch(node -> node.getColorStatus() == 3)
-                                && oneLevel.stream().anyMatch(node -> node.getColorStatus() == 4)
-                                && oneLevel.stream().noneMatch(node -> node.getColorStatus() != 3 && node.getColorStatus() != 4); //同时只存在3、4 == 3
-
-                        if (all_1) {
-                            parentColor = 1;
-                        } else if (all_3 || hasOnly_3_and_4) {
-                            parentColor = 3;
-                        } else if (hasOnly_1_and_3 || all_2 || hasNotAll_2 || hasNotAll_1 || hasNotAll_3) {
-                            parentColor = 2;
-                        } else if (all_4) {
-                            parentColor = 4;
-                        }
-
-                        parentNode.setColorStatus(parentColor);
-                        if (ObjectUtil.isEmpty(nodeColorMap.get(parentNode.getPKeyId()))) {
-                            nodeColorMap.put(parentNode.getPKeyId(), parentNode);
-                        }
-                        parentNodeList.add(parentNode);
-                    }
-                }
-            }
-            if (parentNodeList.size() > 0) { //递归处理父级颜色,当前父级作为下次循环子级
-                this.recursiveParentNodeColorStatus(parentNodeList, distinctParentNodesTBIdKeyMap, allNodesParentGroup, nodeColorMap);
-            }
-        }
-    }
-
     @Override
     public boolean syncTabData(String pKeyId) throws Exception {
         WbsTreeContract node = baseMapper.selectOne(Wrappers.<WbsTreeContract>lambdaQuery().eq(WbsTreeContract::getPKeyId, pKeyId));
@@ -2396,6 +2320,66 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
         }
     }
 
+    /**
+     * 构造树形结构数据 (解决节点颜色问题)
+     *
+     * @param distinctNodesAll 去重后所有节点数据
+     * @return
+     */
+    private List<NodeVO> buildNodeTreeByStream(List<WbsTreeContractLazyVO> distinctNodesAll, Map<Long, WbsTreeContractLazyVO> lowestNodesMap) {
+        List<WbsTreeContractLazyVO> list = distinctNodesAll.stream().filter(f -> f.getParentId().equals(0L)).collect(Collectors.toList());
+        Map<Long, List<WbsTreeContractLazyVO>> map = distinctNodesAll.stream().collect(Collectors.groupingBy(WbsTreeContractLazyVO::getParentId));
+        return recursionFnNodeTree(list, map, lowestNodesMap);
+    }
+
+    private List<NodeVO> recursionFnNodeTree(List<WbsTreeContractLazyVO> list, Map<Long, List<WbsTreeContractLazyVO>> map, Map<Long, WbsTreeContractLazyVO> lowestNodesMap) {
+        List<NodeVO> result = new ArrayList<>();
+        for (WbsTreeContractLazyVO vo : list) {
+            if (vo.getHasChildren().equals(0)) {
+                WbsTreeContractLazyVO lowestNodeVO = lowestNodesMap.getOrDefault(vo.getPKeyId(), null);
+                if (lowestNodeVO != null && ObjectUtil.isNotEmpty(lowestNodeVO.getColorStatus())) {
+                    //最底层颜色初始化
+                    vo.setColorStatus(lowestNodeVO.getColorStatus());
+                }
+            } else {
+                //非最底层节点,颜色默认=1黑色
+                vo.setColorStatus(1);
+            }
+            //转换为NodeVO
+            NodeVO nodeVO = convertToNodeVO(vo);
+            List<WbsTreeContractLazyVO> childrenList = map.get(vo.getId());
+            if (childrenList != null && !childrenList.isEmpty()) {
+                nodeVO.setChildren(recursionFnNodeTree(childrenList, map, lowestNodesMap));
+            }
+            result.add(nodeVO);
+        }
+        return result;
+    }
+
+    //转换VO
+    private NodeVO convertToNodeVO(WbsTreeContractLazyVO wbsTreeContractLazyVO) {
+        NodeVO nodeVO = new NodeVO();
+        nodeVO.setId(wbsTreeContractLazyVO.getId());
+        nodeVO.setParentId(wbsTreeContractLazyVO.getParentId());
+        nodeVO.setPKeyId(wbsTreeContractLazyVO.getPKeyId());
+        nodeVO.setStatus(ObjectUtil.isNotEmpty(wbsTreeContractLazyVO.getColorStatus()) ? wbsTreeContractLazyVO.getColorStatus() : 1);
+        return nodeVO;
+    }
+
+    //把树形结构转为普通List
+    private List<NodeVO> flattenTree(List<NodeVO> tree) {
+        List<NodeVO> result = new ArrayList<>();
+        for (NodeVO node : tree) {
+            result.add(node);
+            if (node.getChildren() != null && !node.getChildren().isEmpty()) {
+                result.addAll(flattenTree(node.getChildren()));
+                node.setChildren(null);
+            }
+        }
+        return result;
+    }
+
+
     private List<Map<Integer, String>> getResultList(ArrayList<Map<String, String>> result, Integer
             isSplicingNumber) {
         List<Map<Integer, String>> resultList = new ArrayList<>();