liuyc 1 жил өмнө
parent
commit
59fa38fb5f

+ 5 - 20
blade-service/blade-user/src/main/java/org/springblade/system/user/controller/WbsTreeController.java

@@ -35,9 +35,10 @@ public class WbsTreeController extends BladeController {
 
     /**
      * 客户端懒加载获取合同段树(统计颜色、填报数量)
+     * (从manager服务剥离到user服务,解决manager服务与mysql不在同一服务器中,网络延迟问题)
      *
      * @author liuyc
-     * @date 2023年12月6日09:52:54(接口剥离,从manager剥离到user,解决manager服务与mysql不在同一服务器中,网络延迟问题)
+     * @date 2023年12月6日09:52:54
      */
     @GetMapping("/lazyQueryContractWbsTree")
     @ApiOperationSupport(order = 1)
@@ -50,52 +51,36 @@ public class WbsTreeController extends BladeController {
             @ApiImplicitParam(name = "classifyType", value = "合同段区分,施工合同段=1,监理合同段=2"),
             @ApiImplicitParam(name = "tableOwner", value = "所属方节点权限,施工=1,监理=2,区分节点的数量、颜色")
     })
-    public R<List<WbsTreeContractLazyVO>> lazyQueryContractWbsTree(@RequestParam String primaryKeyId, @RequestParam String parentId, @RequestParam String contractId, @RequestParam String contractIdRelation, @RequestParam String classifyType, @RequestParam String tableOwner) {
-        //这里是对应的监理合同段下,加载树时primaryKeyId=parentId;与前端对接时没沟通好入参,就不单独处理了,直接重新映射赋值一下
+    public R<List<WbsTreeContractLazyVO>> lazyQueryContractWbsTree(@RequestParam String primaryKeyId, @RequestParam String parentId,
+                                                                   @RequestParam String contractId, @RequestParam String contractIdRelation,
+                                                                   @RequestParam String classifyType, @RequestParam String tableOwner) {
         if (StringUtils.isNotEmpty(primaryKeyId)) {
             parentId = primaryKeyId;
         }
-
-        //结果集
         List<WbsTreeContractLazyVO> vos;
-
-        //构造Redis缓存Key
         String dataInfoId = "";
         if (("1").equals(classifyType)) {
             dataInfoId = contractId + "_" + parentId + "_" + classifyType + "_" + tableOwner;
         } else if (("2").equals(classifyType)) {
-            //监理合同段下,classifyType=1,直接查询对应的施工树缓存
             dataInfoId = contractIdRelation + "_" + parentId + "_" + "1" + "_" + tableOwner;
         }
-
-        //获取Redis缓存信息
         Object data = null;
         if (ObjectUtil.isNotEmpty(dataInfoId)) {
             if (("2").equals(classifyType) && ObjectUtil.isNotEmpty(contractIdRelation)) {
-                //监理根据contractIdRelation关联合同段id来判断获取缓存
                 data = redisTemplate.opsForValue().get("blade-manager::contract:wbstree:" + dataInfoId);
             } else if (("1").equals(classifyType)) {
-                //施工直接获取缓存
                 data = redisTemplate.opsForValue().get("blade-manager::contract:wbstree:" + dataInfoId);
             }
         }
-
         if (data != null) {
-            //返回缓存
             vos = JSON.parseArray(data.toString(), WbsTreeContractLazyVO.class);
-
         } else {
-            //响应结果集
             vos = iUserService.lazyQueryContractWbsTree(parentId, contractId, contractIdRelation, tableOwner);
-
-            //存储缓存
             if (vos != null && ObjectUtil.isNotEmpty(dataInfoId)) {
-                //监理根据contractIdRelation关联合同段id来判断存储缓存
                 if (("2").equals(classifyType) && ObjectUtil.isNotEmpty(contractIdRelation)) {
                     JSONArray array = JSONArray.parseArray(JSON.toJSONString(vos));
                     redisTemplate.opsForValue().set("blade-manager::contract:wbstree:" + dataInfoId, JSON.toJSON(array).toString());
                 } else if (("1").equals(classifyType)) {
-                    //施工直接存储缓存
                     JSONArray array = JSONArray.parseArray(JSON.toJSONString(vos));
                     redisTemplate.opsForValue().set("blade-manager::contract:wbstree:" + dataInfoId, JSON.toJSON(array).toString());
                 }

+ 141 - 207
blade-service/blade-user/src/main/java/org/springblade/system/user/service/impl/UserServiceImpl.java

@@ -8,6 +8,8 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.AllArgsConstructor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springblade.common.constant.CommonConstant;
 import org.springblade.common.constant.TenantConstant;
 import org.springblade.core.log.exception.ServiceException;
@@ -67,6 +69,8 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
         System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "6");
     }
 
+    private static Logger _logger = LoggerFactory.getLogger(UserServiceImpl.class);
+
     /*存储当前合同段contractId对应的合同段树*/
     private final Map<String, List<WbsTreeContractLazyVO>> localCacheNodes = new ConcurrentHashMap<>();
     /*存储当前合同段contractId_tableOwner对应的资料查询信息*/
@@ -687,57 +691,38 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
     @Override
     public List<WbsTreeContractLazyVO> lazyQueryContractWbsTree(String id, String contractId, String contractIdRelation, String tableOwner) {
         if (org.apache.commons.lang.StringUtils.isEmpty(tableOwner)) {
-            throw new ServiceException("tableOwner is not null");
+            throw new ServiceException("Param error,tableOwner cannot be empty");
         }
         if (cn.hutool.core.util.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) {
-                /*施工合同段*/
+                /* =========================== 施工合同段 =========================== */
                 if (new Integer(1).equals(contractInfo.getContractType())) {
-                    //获取当前层懒加载节点
                     String sql = "select p_key_id,contract_id,(SELECT id FROM u_contract_tree_drawings where process_id = p_key_id and is_deleted = 0 limit 1) AS drawingsId,id,parent_id,node_type,type,wbs_type,is_concrete,major_data_type,partition_code,old_id,contract_id_relation,is_concealed_works_node,CASE (SELECT count(1) FROM u_tree_contract_first AS tcf WHERE tcf.is_deleted = 0 AND tcf.wbs_node_id = a.p_key_id) WHEN 0 THEN 'false' ELSE 'true' END AS isFirst,IFNULL(if(length(trim(full_name))>0,full_name,node_name),node_name) AS title,(SELECT CASE WHEN count(1) > 0 THEN 1 ELSE 0 END FROM m_wbs_tree_contract b WHERE b.parent_id = a.id AND b.type = 1 and b.status = 1 AND b.contract_id = " + contractId + " AND b.is_deleted = 0 ) AS hasChildren from m_wbs_tree_contract a where a.node_type != 111 and a.type = 1 and a.status = 1 and a.is_deleted = 0 and parent_id = " + (org.apache.commons.lang.StringUtils.isNotEmpty(id) ? id : 0) + " and contract_id = " + contractId + " ORDER BY a.sort,title,a.create_time";
                     List<WbsTreeContractLazyVO> lazyNodes = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
                     if (lazyNodes.size() > 0) {
-
-                        /*根节点直接返回*/
-                        if (lazyNodes.stream().anyMatch(f -> f.getParentId().equals(0L))) {
-                            for (WbsTreeContractLazyVO lazyNode : lazyNodes) {
-                                lazyNode.setSubmitCounts(0);
-                                lazyNode.setColorStatus(2);
-                                lazyNode.setType(lazyNode.getNodeType());
-                                lazyNode.setNotExsitChild(!lazyNode.getHasChildren().equals(1));
-                                lazyNode.setPrimaryKeyId(lazyNode.getPKeyId());
-                                lazyNode.setTitle(contractInfo.getContractName());
-                            }
-                            return lazyNodes;
-                        }
-
-                        //获取本地缓存节点信息
+                        /*获取当前合同段节点本地缓存信息*/
                         List<WbsTreeContractLazyVO> nodesAll = this.getNodeAll(contractId);
                         List<WbsTreeContractLazyVO> distinctNodesAll = nodesAll.stream()
                                 .collect(Collectors.collectingAndThen(
                                         Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(WbsTreeContractLazyVO::getPKeyId))),
                                         ArrayList::new
                                 ));
-
-                        //所有最底层节点
                         List<WbsTreeContractLazyVO> distinctLowestNodesAll = distinctNodesAll.stream().filter(f -> f.getHasChildren().equals(0)).collect(Collectors.collectingAndThen(
                                 Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(WbsTreeContractLazyVO::getPKeyId))),
                                 ArrayList::new
                         ));
 
-                        //获取本地缓存资料信息
+                        /*获取当前合同段节点对应的资料填报QueryInfo本地缓存信息*/
                         List<WbsTreeContractLazyQueryInfoVO> queryInfoList = this.getQueryInfoList(contractId, tableOwner);
-
                         Map<Long, Integer> queryInfoMaps = queryInfoList.stream().filter(f -> cn.hutool.core.util.ObjectUtil.isNotEmpty(f.getWbsId()))
                                 .collect(Collectors.toMap(WbsTreeContractLazyQueryInfoVO::getWbsId, WbsTreeContractLazyQueryInfoVO::getStatus, (existingValue, newValue) -> existingValue));
                         List<Long> pKeyIdList = new ArrayList<>(queryInfoMaps.keySet());
 
-                        /*处理数量*/
-                        //填报过的所有最底层节点
+                        /* ================ 处理数量 ================ */
                         List<WbsTreeContractLazyVO> lowestNodesTB = distinctLowestNodesAll.parallelStream().filter(f -> pKeyIdList.contains(f.getPKeyId())).collect(Collectors.toList());
                         List<Long> lowestNodeParentIdsTB = lowestNodesTB.parallelStream().map(WbsTreeContractLazyVO::getParentId).collect(Collectors.toList());
-                        //获取本地缓存节点数量统计
+                        /*获取当前合同段节点对应计数统计本地缓存信息*/
                         List<WbsTreeContractLazyVO> resultParentNodesTB = this.getCachedParentCountNodes(contractId, lowestNodeParentIdsTB, nodesAll, tableOwner);
 
                         /*List<WbsTreeContractLazyVO> resultParentNodesTB = new ArrayList<>();
@@ -745,9 +730,8 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
                         this.recursiveGetParentNodes(resultParentNodesTB, lowestNodeParentIdsTB, nodesAll);
                         long endTime1 = System.currentTimeMillis();
                         long executionTime1 = endTime1 - startTime1;
-                        System.out.println("合同段 " + contractId + " wbs节点树 数量计算 执行时间:" + executionTime1 + " ms");*/
+                        _logger.info("合同段 " + contractId + " wbs节点树 数量计算 执行时间:" + executionTime1 + " ms");*/
 
-                        //最底层节点颜色构造后Map
                         Map<Long, WbsTreeContractLazyVO> lowestNodesMap = lowestNodesTB.stream()
                                 .peek(vo -> {
                                     Integer colorStatus = queryInfoMaps.get(vo.getPKeyId());
@@ -761,27 +745,20 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
                                     }
                                 }).collect(Collectors.toMap(WbsTreeContractLazyVO::getPKeyId, Function.identity()));
 
-                        /*处理颜色*/
+                        /* ================ 处理颜色 ================ */
                         long startTime = System.currentTimeMillis();
-                        //先将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));
                         long endTime = System.currentTimeMillis();
                         long executionTime = endTime - startTime;
-                        System.out.println("合同段 " + contractId + " 处理颜色 执行时间:" + executionTime + " ms");
+                        _logger.info("合同段 " + contractId + " 处理颜色 执行时间:" + executionTime + " ms");
 
-                        /*处理最终结果集*/
+                        /* ================ 处理最终结果集 ================ */
                         if (lazyNodes.size() > 0) {
-                            //处理填报数量
                             Map<Long, Integer> countMap = new HashMap<>();
                             for (WbsTreeContractLazyVO node : resultParentNodesTB) {
                                 Long key = node.getPKeyId();
@@ -791,10 +768,8 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
                                     countMap.put(key, 1);
                                 }
                             }
-
-                            //返回最终结果集
                             for (WbsTreeContractLazyVO lazyNodeVO : lazyNodes) {
-                                lazyNodeVO.setType(lazyNodeVO.getNodeType()); //前端显示需要一样的,所以修改成一样的
+                                lazyNodeVO.setType(lazyNodeVO.getNodeType());
                                 lazyNodeVO.setNotExsitChild(!lazyNodeVO.getHasChildren().equals(1));
                                 lazyNodeVO.setPrimaryKeyId(lazyNodeVO.getPKeyId());
                                 if (lazyNodeVO.getParentId() == 0L) {
@@ -803,10 +778,8 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
                                     }
                                 }
 
-                                //设置数量
                                 lazyNodeVO.setSubmitCounts(cn.hutool.core.util.ObjectUtil.isNotEmpty(countMap.get(lazyNodeVO.getPKeyId())) ? countMap.get(lazyNodeVO.getPKeyId()) : (cn.hutool.core.util.ObjectUtil.isNotEmpty(queryInfoMaps.get(lazyNodeVO.getPKeyId())) ? 1 : 0));
 
-                                //设置颜色
                                 if (lazyNodeVO.getSubmitCounts().equals(0)) {
                                     lazyNodeVO.setColorStatus(1);
                                     continue;
@@ -826,7 +799,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
                         return lazyNodes;
                     }
 
-                    /*监理、业主合同段*/
+                    /* =========================== 监理、业主合同段 =========================== */
                 } else if (new Integer("2").equals(contractInfo.getContractType()) || new Integer("3").equals(contractInfo.getContractType())) {
                     List<WbsTreeContractLazyVO> lazyNodesAll = new ArrayList<>();
                     List<String> contractIds = new ArrayList<>();
@@ -845,20 +818,6 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
                         if (sgContractInfo != null) {
                             List<WbsTreeContractLazyVO> lazyNodes = jdbcTemplate.query("select p_key_id,contract_id,(SELECT id FROM u_contract_tree_drawings where process_id = p_key_id and is_deleted = 0 limit 1) AS drawingsId,id,parent_id,node_type,type,wbs_type,major_data_type,partition_code,old_id,contract_id_relation,is_concealed_works_node,CASE (SELECT count(1) FROM u_tree_contract_first AS tcf WHERE tcf.is_deleted = 0 AND tcf.wbs_node_id = a.p_key_id) WHEN 0 THEN 'false' ELSE 'true' END AS isFirst,IFNULL(if(length(trim(full_name))>0,full_name,node_name),node_name) AS title,(SELECT CASE WHEN count(1) > 0 THEN 1 ELSE 0 END FROM m_wbs_tree_contract b WHERE b.parent_id = a.id AND  b.type = 1 and b.status = 1 AND b.contract_id = " + sgContractId + " AND b.is_deleted = 0 ) AS hasChildren from m_wbs_tree_contract a where a.node_type != 111 and a.type = 1 and a.status = 1 and a.is_deleted = 0 and parent_id = " + (org.apache.commons.lang.StringUtils.isNotEmpty(id) ? id : 0) + " and contract_id = " + sgContractId + " ORDER BY a.sort,title,a.create_time", new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
                             if (lazyNodes.size() > 0) {
-
-                                if (lazyNodes.stream().anyMatch(f -> f.getParentId().equals(0L))) {
-                                    for (WbsTreeContractLazyVO lazyNode : lazyNodes) {
-                                        lazyNode.setSubmitCounts(0);
-                                        lazyNode.setColorStatus(2);
-                                        lazyNode.setType(lazyNode.getNodeType());
-                                        lazyNode.setNotExsitChild(!lazyNode.getHasChildren().equals(1));
-                                        lazyNode.setPrimaryKeyId(lazyNode.getPKeyId());
-                                        lazyNode.setContractIdRelation(sgContractId);
-                                        lazyNode.setTitle(sgContractInfo.getContractName());
-                                    }
-                                    return lazyNodes;
-                                }
-
                                 List<WbsTreeContractLazyVO> nodesAll = this.getNodeAll(sgContractId);
                                 List<WbsTreeContractLazyVO> distinctNodesAll = nodesAll.stream()
                                         .collect(Collectors.collectingAndThen(
@@ -948,7 +907,11 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
         return null;
     }
 
-    /*非批量电签时,清理缓存,如资料填报保存、任务上报等*/
+    /**
+     * 非批量电签时,主动清理本地缓存,如资料填报保存、任务上报等
+     *
+     * @param contractId
+     */
     @Override
     public void deleteContractLocalCache(String contractId) {
         /*删除节点缓存*/
@@ -975,7 +938,9 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
         }
     }
 
-    /*定时清理缓存(本地+Redis)信息,不在批量电签时删除,批量电签是多线程,会一直删除,导致缓存基本不生效*/
+    /**
+     * 定时清理本地缓存信息,不在批量电签时删除,批量电签是多线程,会一直删除,导致缓存基本不生效(已废除Redis缓存,走本地缓存不需要Redis)
+     */
     @Scheduled(fixedRate = 120000) //每2分钟执行一次
     public void clearContractLocalCacheAndRedisCache() {
         //获取锁
@@ -987,15 +952,16 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
             localCacheQueryInfos.clear();
             localCacheParentCountNodes.clear();
 
-            //清除RedisWbs树节点缓存
+            //清除RedisWbs树节点缓存(此处的Redis为每层懒加载缓存)
             Set<String> keysByNodes = redisTemplate.keys("blade-manager::contract:wbstree:*");
             if (keysByNodes != null) {
                 redisTemplate.delete(keysByNodes);
             }
+
         } finally {
             //释放锁
             lock.unlock();
-            System.out.println("定时执行任务:{clearContractLocalCacheAndRedisCache} 完成 ... ");
+            _logger.info("定时执行任务:{clearContractLocalCacheAndRedisCache} 完成 ... ");
         }
     }
 
@@ -1010,70 +976,110 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
         List<WbsTreeContractLazyVO> nodesAll = localCacheNodes.get(contractId);
 
         if (nodesAll == null || nodesAll.isEmpty()) {
-            //从Redis获取数据
-            Object data = redisTemplate.opsForValue().get("blade-manager::contract:wbstree:" + contractId);
-            if (data != null) {
-                nodesAll = JSON.parseArray(data.toString(), WbsTreeContractLazyVO.class);
-                //更新本地缓存
-                localCacheNodes.put(contractId, nodesAll);
-            } else {
-                //返回数据库数据
-                long startTime = System.currentTimeMillis();
-
-                /*分页查询,每次5000条*/
-                int pageSize = 5000;
-                int pageNumber = 1;
-                int offset;
-
-                nodesAll = new ArrayList<>();
-                List<WbsTreeContractLazyVO> nodesAllPage;
-                do {
-                    offset = (pageNumber - 1) * pageSize;
-                    nodesAllPage = jdbcTemplate.query(
-                            "SELECT p_key_id, id, parent_id FROM m_wbs_tree_contract " +
-                                    "WHERE type = 1 " +
-                                    "AND status = 1 " +
-                                    "AND is_deleted = 0 " +
-                                    "AND contract_id = ? " +
-                                    "LIMIT ? OFFSET ?",
-                            new Object[]{contractId, pageSize, offset},
-                            new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class)
-                    );
-                    nodesAll.addAll(nodesAllPage);
-                    pageNumber++;
-                } while (nodesAllPage.size() == pageSize);
-
-                long endTime = System.currentTimeMillis();
-                long executionTime = endTime - startTime;
-                System.out.println("合同段 " + contractId + " 查询所有wbs节点树 执行时间:" + executionTime + " ms");
-
-                if (nodesAll.size() > 0) {
-                    //判断是否有子级,赋值
-                    Map<Long, List<WbsTreeContractLazyVO>> groupedByParentId = nodesAll.stream().collect(Collectors.groupingBy(WbsTreeContractLazyVO::getParentId));
-                    for (WbsTreeContractLazyVO vo : nodesAll) {
-                        if (vo.getParentId() == 0) {
-                            vo.setHasChildren(1);
-                        }
-                        List<WbsTreeContractLazyVO> childNodes = groupedByParentId.getOrDefault(vo.getId(), null);
-                        if (childNodes != null && childNodes.size() > 0) {
-                            vo.setHasChildren(1);
-                        } else {
-                            vo.setHasChildren(0);
-                        }
-                    }
+            //返回数据库数据
+            long startTime = System.currentTimeMillis();
+
+            /*分页查询,每次5000条*/
+            int pageSize = 5000;
+            int pageNumber = 1;
+            int offset;
 
-                    //存储到Redis中
-                    JSONArray array = JSONArray.parseArray(JSON.toJSONString(nodesAll));
-                    redisTemplate.opsForValue().set("blade-manager::contract:wbstree:" + contractId, JSON.toJSON(array).toString());
+            nodesAll = new ArrayList<>();
+            List<WbsTreeContractLazyVO> nodesAllPage;
+            do {
+                offset = (pageNumber - 1) * pageSize;
+                nodesAllPage = jdbcTemplate.query(
+                        "SELECT p_key_id, id, parent_id FROM m_wbs_tree_contract " +
+                                "WHERE type = 1 " +
+                                "AND status = 1 " +
+                                "AND is_deleted = 0 " +
+                                "AND contract_id = ? " +
+                                "LIMIT ? OFFSET ?",
+                        new Object[]{contractId, pageSize, offset},
+                        new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class)
+                );
+                nodesAll.addAll(nodesAllPage);
+                pageNumber++;
+            } while (nodesAllPage.size() == pageSize);
 
-                    //更新本地缓存
-                    localCacheNodes.put(contractId, nodesAll);
+            long endTime = System.currentTimeMillis();
+            long executionTime = endTime - startTime;
+            _logger.info("合同段 " + contractId + " 查询所有wbs节点树 执行时间:" + executionTime + " ms");
+
+            if (nodesAll.size() > 0) {
+                //判断是否有子级,赋值
+                Map<Long, List<WbsTreeContractLazyVO>> groupedByParentId = nodesAll.stream().collect(Collectors.groupingBy(WbsTreeContractLazyVO::getParentId));
+                for (WbsTreeContractLazyVO vo : nodesAll) {
+                    if (vo.getParentId() == 0) {
+                        vo.setHasChildren(1);
+                    }
+                    List<WbsTreeContractLazyVO> childNodes = groupedByParentId.getOrDefault(vo.getId(), null);
+                    if (childNodes != null && childNodes.size() > 0) {
+                        vo.setHasChildren(1);
+                    } else {
+                        vo.setHasChildren(0);
+                    }
                 }
+                //更新本地缓存
+                localCacheNodes.put(contractId, nodesAll);
             }
         }
         return nodesAll;
     }
 
+    /**
+     * 获取当前合同段所有填报资料缓存信息
+     *
+     * @param contractId
+     * @param tableOwner
+     * @return
+     */
+    public List<WbsTreeContractLazyQueryInfoVO> getQueryInfoList(String contractId, String tableOwner) {
+        //从本地缓存获取
+        String cacheKey = contractId + "_" + tableOwner;
+        List<WbsTreeContractLazyQueryInfoVO> cachedQueryInfoList = localCacheQueryInfos.get(cacheKey);
+
+        if (cachedQueryInfoList != null && !cachedQueryInfoList.isEmpty()) {
+            return cachedQueryInfoList;
+        }
+
+        List<WbsTreeContractLazyQueryInfoVO> queryInfoList = new ArrayList<>();
+
+        //返回数据库数据
+        long startTime = System.currentTimeMillis();
+
+        /*分页查询,每次5000条*/
+        int pageSize = 5000;
+        int pageNumber = 1;
+        int offset;
+
+        List<WbsTreeContractLazyQueryInfoVO> queryInfoListPage;
+
+        do {
+            offset = (pageNumber - 1) * pageSize;
+            queryInfoListPage = jdbcTemplate.query(
+                    "SELECT wbs_id, status FROM u_information_query " +
+                            "WHERE type = 1 " +
+                            "AND contract_id = ? " +
+                            "AND classify = ? " +
+                            "LIMIT ? OFFSET ?",
+                    new Object[]{contractId, tableOwner, pageSize, offset},
+                    new BeanPropertyRowMapper<>(WbsTreeContractLazyQueryInfoVO.class));
+            queryInfoList.addAll(queryInfoListPage);
+            pageNumber++;
+        } while (queryInfoListPage.size() == pageSize);
+
+        long endTime = System.currentTimeMillis();
+        long executionTime = endTime - startTime;
+        _logger.info("合同段 " + contractId + " 查询所有资料信息 执行时间:" + executionTime + " ms");
+
+        if (queryInfoList.size() > 0) {
+            //更新本地缓存
+            localCacheQueryInfos.put(cacheKey, queryInfoList);
+        }
+        return queryInfoList;
+    }
+
     /**
      * 获取节点数量统计缓存
      *
@@ -1088,36 +1094,22 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
         List<WbsTreeContractLazyVO> resultParentNodesTB = localCacheParentCountNodes.get(cacheKey);
 
         if (resultParentNodesTB == null || resultParentNodesTB.isEmpty()) {
+            resultParentNodesTB = new ArrayList<>();
 
-            //从Redis获取数据
-            Object data = redisTemplate.opsForValue().get("blade-manager::contract:wbstree:byParentCountNodes:" + cacheKey);
-            if (data != null) {
-                resultParentNodesTB = JSON.parseArray(data.toString(), WbsTreeContractLazyVO.class);
-                //更新本地缓存
-                localCacheParentCountNodes.put(cacheKey, resultParentNodesTB);
-
-            } else {
-                /*重新计算,进行递归获取父节点计数统计*/
-                resultParentNodesTB = new ArrayList<>();
-                long startTime = System.currentTimeMillis();
-
-                this.recursiveGetParentNodes(resultParentNodesTB, lowestNodeParentIdsTB, nodesAll);
+            long startTime = System.currentTimeMillis();
 
-                long endTime = System.currentTimeMillis();
-                long executionTime = endTime - startTime;
-                System.out.println("合同段 " + contractId + " wbs节点树 数量计算 执行时间:" + executionTime + " ms");
+            /*重新计算,进行递归获取父节点计数统计*/
+            this.recursiveGetParentNodes(resultParentNodesTB, lowestNodeParentIdsTB, nodesAll);
 
-                if (resultParentNodesTB.size() > 0) {
-                    //存储到Redis中
-                    JSONArray array = JSONArray.parseArray(JSON.toJSONString(resultParentNodesTB));
-                    redisTemplate.opsForValue().set("blade-manager::contract:wbstree:byParentCountNodes:" + cacheKey, JSON.toJSON(array).toString());
+            long endTime = System.currentTimeMillis();
+            long executionTime = endTime - startTime;
+            _logger.info("合同段 " + contractId + " wbs节点树 数量计算 执行时间:" + executionTime + " ms");
 
-                    //更新本地缓存
-                    localCacheParentCountNodes.put(cacheKey, resultParentNodesTB);
-                }
+            if (resultParentNodesTB.size() > 0) {
+                //更新本地缓存
+                localCacheParentCountNodes.put(cacheKey, resultParentNodesTB);
             }
         }
-
         return resultParentNodesTB;
     }
 
@@ -1163,74 +1155,11 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
     }
 
     /**
-     * 获取当前合同段所有填报资料缓存信息
+     * 转换VO
      *
-     * @param contractId
-     * @param tableOwner
+     * @param wbsTreeContractLazyVO
      * @return
      */
-    public List<WbsTreeContractLazyQueryInfoVO> getQueryInfoList(String contractId, String tableOwner) {
-        //从本地缓存获取
-        String cacheKey = contractId + "_" + tableOwner;
-        List<WbsTreeContractLazyQueryInfoVO> cachedQueryInfoList = localCacheQueryInfos.get(cacheKey);
-
-        if (cachedQueryInfoList != null && !cachedQueryInfoList.isEmpty()) {
-            return cachedQueryInfoList;
-        }
-
-        //从Redis获取数据
-        Object dataInformationQuery = redisTemplate.opsForValue().get("blade-manager::contract:wbstree:byInformationQuery:" + cacheKey);
-
-        List<WbsTreeContractLazyQueryInfoVO> queryInfoList = new ArrayList<>();
-        if (dataInformationQuery != null) {
-            queryInfoList = JSON.parseArray(dataInformationQuery.toString(), WbsTreeContractLazyQueryInfoVO.class);
-            //更新本地缓存
-            localCacheQueryInfos.put(cacheKey, queryInfoList);
-
-        } else {
-            //返回数据库数据
-            long startTime = System.currentTimeMillis();
-
-            /*分页查询,每次5000条*/
-            int pageSize = 5000;
-            int pageNumber = 1;
-            int offset;
-
-            List<WbsTreeContractLazyQueryInfoVO> queryInfoListPage;
-
-            do {
-                offset = (pageNumber - 1) * pageSize;
-                queryInfoListPage = jdbcTemplate.query(
-                        "SELECT wbs_id, status FROM u_information_query " +
-                                "WHERE type = 1 " +
-                                "AND contract_id = ? " +
-                                "AND classify = ? " +
-                                "LIMIT ? OFFSET ?",
-                        new Object[]{contractId, tableOwner, pageSize, offset},
-                        new BeanPropertyRowMapper<>(WbsTreeContractLazyQueryInfoVO.class));
-                queryInfoList.addAll(queryInfoListPage);
-                pageNumber++;
-            } while (queryInfoListPage.size() == pageSize);
-
-            long endTime = System.currentTimeMillis();
-            long executionTime = endTime - startTime;
-            System.out.println("合同段 " + contractId + " 查询所有资料信息 执行时间:" + executionTime + " ms");
-
-            if (queryInfoList.size() > 0) {
-                JSONArray array = JSONArray.parseArray(JSON.toJSONString(queryInfoList));
-
-                //存储到Redis中
-                redisTemplate.opsForValue().set("blade-manager::contract:wbstree:byInformationQuery:" + cacheKey, JSON.toJSON(array).toString());
-
-                //更新本地缓存
-                localCacheQueryInfos.put(cacheKey, queryInfoList);
-            }
-        }
-
-        return queryInfoList;
-    }
-
-    //转换VO
     public NodeVO convertToNodeVO(WbsTreeContractLazyVO wbsTreeContractLazyVO) {
         NodeVO nodeVO = new NodeVO();
         nodeVO.setId(wbsTreeContractLazyVO.getId());
@@ -1278,7 +1207,12 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
         return result;
     }
 
-    //把树形结构转为普通List
+    /**
+     * 树形层级结构转为普通List
+     *
+     * @param tree
+     * @return
+     */
     public List<NodeVO> flattenTree(List<NodeVO> tree) {
         List<NodeVO> result = new ArrayList<>();
         for (NodeVO node : tree) {