Browse Source

Merge branch 'master' of http://121.41.40.202:3000/zhuwei/bladex

huangtf 1 year ago
parent
commit
20b87f8171
19 changed files with 398 additions and 198 deletions
  1. 43 0
      blade-service-api/blade-land-api/src/main/java/org/springblade/land/entity/ClearingAgreementInfo.java
  2. 4 1
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/FormData.java
  3. 19 0
      blade-service/blade-land/src/main/java/org/springblade/land/controller/ClearingAgreementInfoController.java
  4. 23 15
      blade-service/blade-land/src/main/java/org/springblade/land/controller/CompensationInfoController.java
  5. 34 0
      blade-service/blade-land/src/main/java/org/springblade/land/mapper/ClearingAgreementInfoMapper.java
  6. 5 0
      blade-service/blade-land/src/main/java/org/springblade/land/mapper/ClearingAgreementInfoMapper.xml
  7. 2 0
      blade-service/blade-land/src/main/java/org/springblade/land/mapper/CompensationInfoMapper.java
  8. 8 0
      blade-service/blade-land/src/main/java/org/springblade/land/mapper/CompensationInfoMapper.xml
  9. 35 0
      blade-service/blade-land/src/main/java/org/springblade/land/service/IClearingAgreementInfoService.java
  10. 2 0
      blade-service/blade-land/src/main/java/org/springblade/land/service/ICompensationInfoService.java
  11. 24 0
      blade-service/blade-land/src/main/java/org/springblade/land/service/impl/ClearingAgreementInfoServiceImpl.java
  12. 11 0
      blade-service/blade-land/src/main/java/org/springblade/land/service/impl/CompensationInfoServiceImpl.java
  13. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java
  14. 8 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/TableElementConverter.java
  15. 3 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IFormulaService.java
  16. 71 125
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ContractInfoServiceImpl.java
  17. 30 6
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java
  18. 71 46
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java
  19. 4 4
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeContractServiceImpl.java

+ 43 - 0
blade-service-api/blade-land-api/src/main/java/org/springblade/land/entity/ClearingAgreementInfo.java

@@ -0,0 +1,43 @@
+package org.springblade.land.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.core.mp.base.BaseEntity;
+
+import java.math.BigDecimal;
+
+/**
+ * @Param
+ * @Author wangwl
+ * @Date 2023/10/7 17:31
+ **/
+@Data
+@TableName("l_clearing_agreement_info")
+@EqualsAndHashCode(callSuper = true)
+public class ClearingAgreementInfo extends BaseEntity {
+    @ApiModelProperty(value = "项目id")
+    private Long projectId;
+
+    @ApiModelProperty(value = "计量期")
+    private Long periodId;
+
+    @ApiModelProperty(value = "协议名称")
+    private String name;
+
+    @ApiModelProperty(value = "协议类型")
+    private Integer type;
+
+    @ApiModelProperty(value = "协议金额")
+    private BigDecimal agreementMoney;
+
+    @ApiModelProperty(value = "协议PDF路径")
+    private String mergePdfUrl;
+
+    @ApiModelProperty(value = "区域id")
+    private Long areaId;
+
+    @ApiModelProperty(value = "补偿协议ids")
+    private String agreementIds;
+}

+ 4 - 1
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/FormData.java

@@ -76,7 +76,10 @@ public class FormData {
      */
     private List<ElementData> backup;
     private Map<String, ElementData> vMap = new HashMap<>();
-
+    /**
+     * 公式id
+     */
+    private Long formulaId;
     /**
      * 公式对象
      */

+ 19 - 0
blade-service/blade-land/src/main/java/org/springblade/land/controller/ClearingAgreementInfoController.java

@@ -0,0 +1,19 @@
+package org.springblade.land.controller;
+
+import io.swagger.annotations.Api;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @Param
+ * @Author wangwl
+ * @Date 2023/10/7 17:40
+ **/
+@RestController
+@AllArgsConstructor
+@RequestMapping("/clearingAgreementInfo")
+@Api(value = "结算协议", tags = "结算协议接口")
+public class ClearingAgreementInfoController {
+
+}

+ 23 - 15
blade-service/blade-land/src/main/java/org/springblade/land/controller/CompensationInfoController.java

@@ -156,7 +156,7 @@ public class CompensationInfoController extends BladeController {
     }
 
     @GetMapping("/get-buss-pdfInfo")
-    @ApiOperationSupport(order = 18)
+    @ApiOperationSupport(order = 9)
     @ApiOperation(value = "单表pdf预览", notes = "单表pdf预览")
     @ApiImplicitParams(value = {
             @ApiImplicitParam(name = "id", value = "当前表单的id", required = true)
@@ -166,7 +166,7 @@ public class CompensationInfoController extends BladeController {
     }
 
     @GetMapping("/get-buss-pdfs")
-    @ApiOperationSupport(order = 21)
+    @ApiOperationSupport(order = 10)
     @ApiOperation(value = "多表预览", notes = "多表预览")
     @ApiImplicitParams(value = {
             @ApiImplicitParam(name = "agreementId", value = "协议的id", required = true),
@@ -175,21 +175,9 @@ public class CompensationInfoController extends BladeController {
         return compensationInfoService.getPdfS(agreementId);
     }
 
-//    @PostMapping("/add-cope-tab")
-//    @ApiOperationSupport(order = 19)
-//    @ApiOperation(value = "表单新增复制", notes = "表单新增复制,,返回协议id")
-//    @ApiImplicitParams(value = {
-//            @ApiImplicitParam(name = "projectId", value = "项目id", required = true),
-//            @ApiImplicitParam(name = "areaId", value = "当前树节点id", required = true),
-//            @ApiImplicitParam(name = "tableId", value = "表单的tableId", required = true),
-//            @ApiImplicitParam(name = "nodeType", value = "新增返回的nodeType", required = true)
-//    })
-//    public R addCopeTab(@RequestBody TableCopyVO vo) {
-//        return compensationInfoService.addCopeTab(vo);
-//    }
 
     @GetMapping("/cope-tab")
-    @ApiOperationSupport(order = 19)
+    @ApiOperationSupport(order = 11)
     @ApiOperation(value = "表单复制", notes = "表单复制,传入当前表id,返回协议id")
     @ApiImplicitParams(value = {
             @ApiImplicitParam(name = "id", value = "当前表单的id", required = true)
@@ -198,4 +186,24 @@ public class CompensationInfoController extends BladeController {
         return compensationInfoService.updateCopeTab(id);
     }
 
+
+    /**
+     * 结算获取补偿协议,不分页,不显示已经引用的
+     * @param info
+     * @return
+     */
+    @GetMapping("/getAgreementList")
+    @ApiOperationSupport(order = 12)
+    @ApiOperation(value = "结算查询补偿协议", notes = "结算查询补偿协议")
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "projectId", value = "项目id", required = true),
+            @ApiImplicitParam(name = "areaId", value = "当前树节点id", required = true),
+            @ApiImplicitParam(name = "type", value = "协议类型1征地补偿2坟地补偿3专项设施", required = true),
+            @ApiImplicitParam(name = "number", value = "编号搜索值", required = false)
+    })
+    public R<List<CompensationInfo>> getAgreementList(CompensationInfo info)  {
+        List<CompensationInfo> list = compensationInfoService.getAgreementList(info);
+        return R.data(list);
+    }
+
 }

+ 34 - 0
blade-service/blade-land/src/main/java/org/springblade/land/mapper/ClearingAgreementInfoMapper.java

@@ -0,0 +1,34 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.land.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
+import org.springblade.land.entity.ClearingAgreementInfo;
+import org.springblade.land.entity.SettlementInterval;
+
+
+/**
+ *  Mapper 接口
+ *
+ * @author BladeX
+ * @since 2023-02-17
+ */
+public interface ClearingAgreementInfoMapper extends BaseMapper<ClearingAgreementInfo> {
+
+
+}

+ 5 - 0
blade-service/blade-land/src/main/java/org/springblade/land/mapper/ClearingAgreementInfoMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.springblade.land.mapper.ClearingAgreementInfoMapper">
+
+</mapper>

+ 2 - 0
blade-service/blade-land/src/main/java/org/springblade/land/mapper/CompensationInfoMapper.java

@@ -67,4 +67,6 @@ public interface CompensationInfoMapper extends BaseMapper<CompensationInfo> {
     IPage<CompensationInfo> page(IPage<CompensationInfo> iPage,@Param("info") CompensationInfo info);
 
     Integer getNumber(@Param("areaId") Long areaId);
+
+    List<CompensationInfo> getAgreementList(@Param("info") CompensationInfo info);
 }

+ 8 - 0
blade-service/blade-land/src/main/java/org/springblade/land/mapper/CompensationInfoMapper.xml

@@ -59,6 +59,14 @@
         select count(1)
         from l_compensation_info where area_id = #{areaId}
     </select>
+    <select id="getAgreementList" resultType="org.springblade.land.entity.CompensationInfo">
+        select id,number,name,all_money,is_quote from l_compensation_info
+        where project_id = #{info.projectId} and is_deleted = 0 and `type` = #{info.type} and is_quote = 0
+        and area_id in (select id from l_region_tree_info where is_deleted = 0 and (id = #{info.areaId} or ancestors like CONCAT(CONCAT('%', #{info.areaId}), '%')))
+        <if test="info.number != null and info.number != ''">
+            and number like CONCAT(CONCAT('%', #{info.number}), '%')
+        </if>
+    </select>
 
 
 </mapper>

+ 35 - 0
blade-service/blade-land/src/main/java/org/springblade/land/service/IClearingAgreementInfoService.java

@@ -0,0 +1,35 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.land.service;
+
+
+import org.springblade.core.mp.base.BaseService;
+import org.springblade.land.dto.SettlementIntervalDTO;
+import org.springblade.land.entity.ClearingAgreementInfo;
+import org.springblade.land.entity.SettlementInterval;
+
+
+/**
+ *  服务类
+ *
+ * @author BladeX
+ * @since 2023-02-17
+ */
+public interface IClearingAgreementInfoService extends BaseService<ClearingAgreementInfo> {
+
+
+}

+ 2 - 0
blade-service/blade-land/src/main/java/org/springblade/land/service/ICompensationInfoService.java

@@ -68,4 +68,6 @@ public interface ICompensationInfoService extends BaseService<CompensationInfo>
     Long add(Long projectId, Long areaId, Integer type);
 
     void remove(List<Long> ids);
+
+    List<CompensationInfo> getAgreementList(CompensationInfo info);
 }

+ 24 - 0
blade-service/blade-land/src/main/java/org/springblade/land/service/impl/ClearingAgreementInfoServiceImpl.java

@@ -0,0 +1,24 @@
+package org.springblade.land.service.impl;
+
+
+import lombok.AllArgsConstructor;
+import org.springblade.core.log.exception.ServiceException;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.land.dto.SettlementIntervalDTO;
+import org.springblade.land.entity.ClearingAgreementInfo;
+import org.springblade.land.entity.SettlementInterval;
+import org.springblade.land.mapper.ClearingAgreementInfoMapper;
+import org.springblade.land.mapper.SettlementIntervalMapper;
+import org.springblade.land.service.IClearingAgreementInfoService;
+import org.springblade.land.service.ISettlementIntervalService;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDate;
+import java.util.List;
+
+@Service
+@AllArgsConstructor
+public class ClearingAgreementInfoServiceImpl extends BaseServiceImpl<ClearingAgreementInfoMapper, ClearingAgreementInfo> implements IClearingAgreementInfoService {
+
+
+}

+ 11 - 0
blade-service/blade-land/src/main/java/org/springblade/land/service/impl/CompensationInfoServiceImpl.java

@@ -474,6 +474,17 @@ public class CompensationInfoServiceImpl extends BaseServiceImpl<CompensationInf
         this.deleteLogic(ids);
     }
 
+    /**
+     * 结算获取补偿协议列表
+     * @param info
+     * @return
+     */
+    @Override
+    public List<CompensationInfo> getAgreementList(CompensationInfo info) {
+        List<CompensationInfo> list = baseMapper.getAgreementList(info);
+        return list;
+    }
+
     //获取当前节点的补偿编号
     private String getNumber(Long areaId) {
         Integer number = baseMapper.getNumber(areaId);

+ 1 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java

@@ -3818,7 +3818,7 @@ public class ExcelTabController extends BladeController {
      * @return
      * @throws Exception
      */
-    @PostMapping("/save_buss_data3")
+    @PostMapping("/save_buss_data2")
     @ApiOperationSupport(order = 13)
     @ApiOperation(value = "填报页面数据保存", notes = "填报页面数据保存")
     public R saveBussData(@Valid @RequestBody JSONObject dataInfo) throws Exception {

+ 8 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/TableElementConverter.java

@@ -108,6 +108,14 @@ public class TableElementConverter implements ITableElementConverter {
     }
 
     /*优化测试新增属性start*/
+
+    public TableElementConverter(List<FormData>curFormDatas,List<FormData> processFds, Map<String, Map<String, String>> coordinateMap, CurrentNode wtc, List<NodeTable> tableAll) {
+        this.coordinateMap = coordinateMap;
+        this.nodeId = wtc.getPkId();
+        this.wbsTreeId = wtc.getId();
+        this.currentNode = wtc;
+        this.tableAll = tableAll;
+    }
     /*优化测试新增属性end*/
 
     public TableElementConverter(List<TableInfo> tableInfoList, List<KeyMapper> keyMappers, List<Formula> formulas, Map<String, Map<String, String>> coordinateMap, CurrentNode wtc, List<NodeTable> tableAll) {

+ 3 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/IFormulaService.java

@@ -56,6 +56,9 @@ public interface IFormulaService extends BaseService<Formula> {
      */
     List<KeyMapper> getKeyMapperList(List<Long> ids, String projectId, String nodeId, ExecuteType executeType);
 
+   void formulaInto(List<FormData> curFormDatas, String projectId, String nodeId, ExecuteType executeType);
+
+
     Map<String, Object> getElementInfoByCodes(String codes);
 
     /**根据wbs_tree_contract 的pkeyId查询项目级对应节点*/

+ 71 - 125
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ContractInfoServiceImpl.java

@@ -22,6 +22,7 @@ import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.node.ForestNodeMerger;
 import org.springblade.core.tool.utils.BeanUtil;
 import org.springblade.core.tool.utils.ObjectUtil;
+import org.springblade.manager.bean.NodeVO;
 import org.springblade.manager.dto.FindAllUserByConditionDTO;
 import org.springblade.manager.dto.SaveUserInfoByProjectDTO;
 import org.springblade.manager.entity.*;
@@ -394,7 +395,8 @@ public class ContractInfoServiceImpl extends BaseServiceImpl<ContractInfoMapper,
                         Map<Long, Integer> informationQueryMaps = informationQueryList.stream().collect(Collectors.toMap(InformationQuery::getWbsId, InformationQuery::getStatus, (v1, v2) -> v1));
                         List<Long> pKeyIdList = new ArrayList<>(informationQueryMaps.keySet());
 
-                        //填报过的所有最底层节点(并且是查询有效节点的最下级节点)处理数量
+                        //TODO 处理数量
+                        //填报过的所有最底层节点
                         List<WbsTreeContractLazyVO> lowestNodesTB = distinctLowestNodesAll.stream().filter(f -> pKeyIdList.contains(f.getPKeyId()) && resultNodesPKeyIds.contains(f.getPKeyId())).collect(Collectors.toList());
                         List<Long> lowestNodeParentIdsTB = lowestNodesTB.stream().map(WbsTreeContractLazyVO::getParentId).collect(Collectors.toList());
                         List<WbsTreeContractLazyVO> resultParentNodesTB = new ArrayList<>();
@@ -413,6 +415,20 @@ public class ContractInfoServiceImpl extends BaseServiceImpl<ContractInfoMapper,
                                     }
                                 }).collect(Collectors.toMap(WbsTreeContractLazyVO::getPKeyId, Function.identity()));
 
+                        //TODO 处理颜色
+                        //先将WbsTreeContractLazyVO转为NodeVO
+                        List<NodeVO> nodeVOList = distinctNodesAll.stream().map(wbsTreeContractServiceImpl::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 = wbsTreeContractServiceImpl.buildNodeTreeByStream(distinctNodesAll, lowestNodesMap);
+                        //处理节点颜色
+                        NodeVO.calculateStatusToDFS(treeNodeVOList, nodeVOMap);
+                        //把树形结构转为普通List集合
+                        List<NodeVO> nodeVOS = wbsTreeContractServiceImpl.flattenTree(treeNodeVOList);
+                        //获取所有节点颜色Map
+                        Map<Long, Integer> nodeColorStatusMap = nodeVOS.stream().collect(Collectors.toMap(NodeVO::getPKeyId, NodeVO::getStatus, (existing, replacement) -> existing));
+
                         //构造vo
                         if (wbsTreeContractList.size() > 0) {
                             //处理填报数量
@@ -425,24 +441,31 @@ public class ContractInfoServiceImpl extends BaseServiceImpl<ContractInfoMapper,
                                     countMap.put(key, 1L);
                                 }
                             }
-                            List<WbsTreeContractTreeAllVO> wbsTreeContractTreeAllVOS = wbsTreeContractList.stream().map(node -> {
-                                WbsTreeContractTreeAllVO vo = BeanUtil.copyProperties(node, WbsTreeContractTreeAllVO.class);
-                                if (vo != null) {
-                                    vo.setContractIdRelation(node.getContractId());
-                                    vo.setType(ObjectUtils.isNotEmpty(node.getNodeType()) ? node.getNodeType() : 0);
-                                    vo.setTitle(ObjectUtil.isNotEmpty(node.getFullName()) ? node.getFullName() : node.getNodeName());
-                                    vo.setPrimaryKeyId(node.getPKeyId());
-                                    vo.setSubmitCounts(ObjectUtil.isNotEmpty(countMap.get(vo.getPrimaryKeyId())) ? countMap.get(vo.getPrimaryKeyId()) : (ObjectUtil.isNotEmpty(informationQueryMaps.get(vo.getPrimaryKeyId())) ? 1L : 0L));
-                                    if (vo.getSubmitCounts() >= 1L) {
-                                        vo.setColorStatus(2);
-                                    }
-                                    WbsTreeContractLazyVO lowestNode = lowestNodesMap.get(vo.getPrimaryKeyId());
-                                    if (lowestNode != null) {
-                                        vo.setColorStatus(lowestNode.getColorStatus());
-                                    }
-                                }
-                                return vo;
-                            }).collect(Collectors.toList());
+                            List<WbsTreeContractTreeAllVO> wbsTreeContractTreeAllVOS = wbsTreeContractList.stream()
+                                    .map(node -> {
+                                        WbsTreeContractTreeAllVO vo = BeanUtil.copyProperties(node, WbsTreeContractTreeAllVO.class);
+                                        if (vo != null) {
+                                            vo.setContractIdRelation(node.getContractId());
+                                            vo.setType(ObjectUtils.isNotEmpty(node.getNodeType()) ? node.getNodeType() : 0);
+                                            vo.setTitle(ObjectUtil.isNotEmpty(node.getFullName()) ? node.getFullName() : node.getNodeName());
+                                            vo.setPrimaryKeyId(node.getPKeyId());
+
+                                            //设置数量
+                                            vo.setSubmitCounts(ObjectUtil.isNotEmpty(countMap.get(vo.getPrimaryKeyId())) ? countMap.get(vo.getPrimaryKeyId()) : (ObjectUtil.isNotEmpty(informationQueryMaps.get(vo.getPrimaryKeyId())) ? 1L : 0L));
+
+                                            //设置颜色
+                                            Integer parentColorStatus = nodeColorStatusMap.get(vo.getPrimaryKeyId());
+                                            if (parentColorStatus != null) {
+                                                vo.setColorStatus(parentColorStatus);
+                                            } else {
+                                                WbsTreeContractLazyVO lowestNode = lowestNodesMap.get(vo.getPrimaryKeyId());
+                                                if (lowestNode != null) {
+                                                    vo.setColorStatus(lowestNode.getColorStatus());
+                                                }
+                                            }
+                                        }
+                                        return vo;
+                                    }).collect(Collectors.toList());
                             return R.data(this.buildWbsTreeByStreamByTreeAll(wbsTreeContractTreeAllVOS));
                         }
                     }
@@ -514,6 +537,13 @@ public class ContractInfoServiceImpl extends BaseServiceImpl<ContractInfoMapper,
                                         }
                                     }).collect(Collectors.toMap(WbsTreeContractLazyVO::getPKeyId, Function.identity()));
 
+                            List<NodeVO> nodeVOList = distinctNodesAll.stream().map(wbsTreeContractServiceImpl::convertToNodeVO).collect(Collectors.toList());
+                            Map<Long, NodeVO> nodeVOMap = nodeVOList.stream().collect(Collectors.toMap(NodeVO::getId, vo -> vo, (existing, replacement) -> existing));
+                            List<NodeVO> treeNodeVOList = wbsTreeContractServiceImpl.buildNodeTreeByStream(distinctNodesAll, lowestNodesMap);
+                            NodeVO.calculateStatusToDFS(treeNodeVOList, nodeVOMap);
+                            List<NodeVO> nodeVOS = wbsTreeContractServiceImpl.flattenTree(treeNodeVOList);
+                            Map<Long, Integer> nodeColorStatusMap = nodeVOS.stream().collect(Collectors.toMap(NodeVO::getPKeyId, NodeVO::getStatus, (existing, replacement) -> existing));
+
                             if (wbsTreeContractList.size() > 0) {
                                 Map<Long, Long> countMap = new HashMap<>();
                                 for (WbsTreeContractLazyVO node : resultParentNodesTB) {
@@ -524,24 +554,28 @@ public class ContractInfoServiceImpl extends BaseServiceImpl<ContractInfoMapper,
                                         countMap.put(key, 1L);
                                     }
                                 }
-                                List<WbsTreeContractTreeAllVO> wbsTreeContractTreeAllVOS = wbsTreeContractList.stream().map(node -> {
-                                    WbsTreeContractTreeAllVO vo = BeanUtil.copyProperties(node, WbsTreeContractTreeAllVO.class);
-                                    if (vo != null) {
-                                        vo.setContractIdRelation(node.getContractId());
-                                        vo.setType(ObjectUtils.isNotEmpty(node.getNodeType()) ? node.getNodeType() : 0);
-                                        vo.setTitle(ObjectUtil.isNotEmpty(node.getFullName()) ? node.getFullName() : node.getNodeName());
-                                        vo.setPrimaryKeyId(node.getPKeyId());
-                                        vo.setSubmitCounts(ObjectUtil.isNotEmpty(countMap.get(vo.getPrimaryKeyId())) ? countMap.get(vo.getPrimaryKeyId()) : (ObjectUtil.isNotEmpty(informationQueryMaps.get(vo.getPrimaryKeyId())) ? 1L : 0L));
-                                        if (vo.getSubmitCounts() >= 1L) {
-                                            vo.setColorStatus(2);
-                                        }
-                                        WbsTreeContractLazyVO lowestNode = lowestNodesMap.get(vo.getPrimaryKeyId());
-                                        if (lowestNode != null) {
-                                            vo.setColorStatus(lowestNode.getColorStatus());
-                                        }
-                                    }
-                                    return vo;
-                                }).collect(Collectors.toList());
+                                List<WbsTreeContractTreeAllVO> wbsTreeContractTreeAllVOS = wbsTreeContractList.stream()
+                                        .map(node -> {
+                                            WbsTreeContractTreeAllVO vo = BeanUtil.copyProperties(node, WbsTreeContractTreeAllVO.class);
+                                            if (vo != null) {
+                                                vo.setContractIdRelation(node.getContractId());
+                                                vo.setType(ObjectUtils.isNotEmpty(node.getNodeType()) ? node.getNodeType() : 0);
+                                                vo.setTitle(ObjectUtil.isNotEmpty(node.getFullName()) ? node.getFullName() : node.getNodeName());
+                                                vo.setPrimaryKeyId(node.getPKeyId());
+                                                vo.setSubmitCounts(ObjectUtil.isNotEmpty(countMap.get(vo.getPrimaryKeyId())) ? countMap.get(vo.getPrimaryKeyId()) : (ObjectUtil.isNotEmpty(informationQueryMaps.get(vo.getPrimaryKeyId())) ? 1L : 0L));
+
+                                                Integer parentColorStatus = nodeColorStatusMap.get(vo.getPrimaryKeyId());
+                                                if (parentColorStatus != null) {
+                                                    vo.setColorStatus(parentColorStatus);
+                                                } else {
+                                                    WbsTreeContractLazyVO lowestNode = lowestNodesMap.get(vo.getPrimaryKeyId());
+                                                    if (lowestNode != null) {
+                                                        vo.setColorStatus(lowestNode.getColorStatus());
+                                                    }
+                                                }
+                                            }
+                                            return vo;
+                                        }).collect(Collectors.toList());
                                 resultMaps.put(contractRelationJlyz.getContractIdSg(), this.buildWbsTreeByStreamByTreeAll(wbsTreeContractTreeAllVOS));
                             }
                         }
@@ -553,94 +587,6 @@ public class ContractInfoServiceImpl extends BaseServiceImpl<ContractInfoMapper,
         return null;
     }
 
-    /**
-     * 处理submitCounts计数、colorStatus颜色问题
-     *
-     * @param reNodes 数据源
-     */
-    private void reSetSubmitCountsAndColorStatus(List<WbsTreeContractTreeAllVO> reNodes) {
-        //反向for循环解决顺序问题,最底层节点才是数据源
-        for (int i = reNodes.size() - 1; i >= 0; i--) {
-            WbsTreeContractTreeAllVO node = reNodes.get(i);
-            if (node.getChildren() != null && !node.getChildren().isEmpty()) {
-                //计数
-                long childSubmitCounts = 0L;
-                for (WbsTreeContractTreeAllVO child : node.getChildren()) {
-                    if (child.getSubmitCounts() == 1L) {
-                        childSubmitCounts++;
-                    } else if (child.getSubmitCounts() > 1L) {
-                        childSubmitCounts = child.getSubmitCounts();
-                    }
-                }
-                node.setSubmitCounts(childSubmitCounts);
-
-                //颜色
-                boolean allThree = true; //是否所有子节点的getColorStatus都等于3
-                boolean allFour = true; //是否所有子节点的getColorStatus都等于4
-                boolean hasTwo = false; //是否存在子节点的getColorStatus等于2
-                boolean hasOne = false; //是否存在子节点的getColorStatus等于1
-                boolean hasThreeOrFour = false; //是否存在子节点的getColorStatus等于3或4
-                for (WbsTreeContractTreeAllVO child : node.getChildren()) {
-                    if (child.getColorStatus() != 3) {
-                        allThree = false;
-                    }
-                    if (child.getColorStatus() != 4) {
-                        allFour = false;
-                    }
-                    if (child.getColorStatus() == 2) {
-                        hasTwo = true;
-                    }
-                    if (child.getColorStatus() == 1) {
-                        hasOne = true;
-                    }
-                    if (child.getColorStatus() == 3 || child.getColorStatus() == 4) {
-                        hasThreeOrFour = true;
-                    }
-                }
-                if (allThree) {
-                    node.setColorStatus(3);
-                } else if (allFour) {
-                    node.setColorStatus(4);
-                } else if (hasTwo || (hasOne && hasThreeOrFour)) {
-                    node.setColorStatus(2);
-                } else {
-                    node.setColorStatus(1);
-                }
-
-            } else if (node.getSubmitCounts() == 1L) {
-                node.setSubmitCounts(1L);
-                //最底层节点颜色
-                if (ObjectUtils.isNotEmpty(node.getColorStatus())) {
-                    if (node.getColorStatus().equals(0)) { //任务状态=0,未上报
-                        node.setColorStatus(2); //蓝色
-                    } else if (node.getColorStatus().equals(1)) { //任务状态=1,待审批
-                        node.setColorStatus(3); //橙色
-                    } else if (node.getColorStatus().equals(2)) { //任务状态=2,已审批
-                        node.setColorStatus(4); //绿色
-                    }
-                }
-            } else if (node.getSubmitCounts() == 0L && ObjectUtils.isEmpty(node.getColorStatus())) {
-                node.setColorStatus(1); //黑色 //任务状态=null,未填报
-            }
-        }
-    }
-
-
-    /**
-     * 获取构造完的List集合
-     *
-     * @param reNodes 数据源
-     * @param result  结果集
-     */
-    private void getNodesAll(List<WbsTreeContractTreeAllVO> reNodes, LinkedList<WbsTreeContractTreeAllVO> result) {
-        for (WbsTreeContractTreeAllVO node : reNodes) {
-            if (node.getChildren() != null && !node.getChildren().isEmpty()) {
-                result.addAll(node.getChildren());
-                this.getNodesAll(node.getChildren(), result);
-            }
-        }
-    }
-
     /**
      * 反向递归获取父级
      *

+ 30 - 6
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java

@@ -409,13 +409,21 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                                            "select d.id,c.tab_ch_name tableChName,d.e_type eType,d.e_name eName,d.e_length eLength,d.e_allow_deviation eAllowDeviation,CONCAT(c.tab_en_name,':',d.e_key) code from m_table_info c join m_wbs_form_element d  on  c.id=d.f_id where d.is_deleted=0 and c.tab_en_name in("+tableNames+")"
                                            ,FormData.class
                                    );
-               List<KeyMapper> keyMappers = this.formulaService.getKeyMapperList(tableInfoList.stream().map(TableInfo::getPkeyId).filter(Func::isNotEmpty).map(Long::parseLong).collect(Collectors.toList()), tableInfoList.get(0).getProjectId(), String.valueOf(nodeId), type);
-               if (Func.isNotEmpty(keyMappers) && Func.isNotEmpty(tableAll)) {
-                   Map<String, Map<String, String>> coordinateMap = createCoordinateMap(keyMappers, type);
-                   List<Formula> formulas = this.formulaService.getFormulaList(keyMappers);
+               List<Long> pkeyIds =tableInfoList.stream().map(TableInfo::getPkeyId).map(Long::parseLong).collect(Collectors.toList());
+               List<String> curTableNames=tableAll.stream().filter(e->pkeyIds.contains(e.getPKeyId())).map(NodeTable::getInitTableName).collect(Collectors.toList());
+               List<NodeTable> curNodeTables=tableAll.stream().filter(e->curTableNames.contains(e.getInitTableName())).collect(Collectors.toList());
+               /*当前提交的元素*/
+               List<FormData> curFormDatas=processFds.stream().filter(e->curTableNames.contains(e.getTableName())).collect(Collectors.toList());
+              /*嵌入公式*/
+              this.formulaService.formulaInto(curFormDatas,tableInfoList.get(0).getProjectId(), String.valueOf(nodeId), type);
+              // List<KeyMapper> keyMappers = this.formulaService.getKeyMapperList(tableAll.stream().map(NodeTable::getPKeyId).filter(Func::isNotEmpty).collect(Collectors.toList()), tableInfoList.get(0).getProjectId(), String.valueOf(nodeId), type);
+               if (Func.isNotEmpty(tableAll)) {
+                   Map<String, Map<String, String>> coordinateMap = createCoordinateMap2(pkeyIds, type);
+                   //List<Formula> formulas = this.formulaService.getFormulaList(keyMappers);
                    /*要找到最小加载数量
                    * 1.根据依赖溯源然后确定当前页面修改数据的影响范围
                    * 2.区分能部分执行和必须整体执行公式的元素*/
+                   List<FormData> relyFds=  curFormDatas.stream().filter(e->e.getFormula()!=null&&e.getFormula().getRelyList()!=null).collect(Collectors.toList());
 
                    /*判断哪些元素是可部分执行和整体执行*/
                    CurrentNode currentNode = null;
@@ -435,7 +443,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                        projectId = Long.parseLong(wtp.getProjectId());
                    }
                    if (currentNode != null) {
-                       TableElementConverter tec = new TableElementConverter(tableInfoList, keyMappers, formulas, coordinateMap, currentNode, tableAll);
+                       TableElementConverter tec = new TableElementConverter(curFormDatas, processFds, coordinateMap, currentNode, tableAll);
                        tec.setLog(log);
                        tec.setExecuteType(type);
                        tec.setContractId(contractId);
@@ -447,7 +455,6 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                        } else {
                            tec.getLog().put(FormulaLog.OTHER, "没有执行任何公式");
                        }
-                       stopWatch.stop();
                        long totalTime = stopWatch.getTotalTimeMillis();
                        log.put(FormulaLog.PF, "公式执行消耗时间:" + (double)totalTime / 1000 + "秒");
                        StaticLog.info("公式执行用时:{}", totalTime);
@@ -494,6 +501,23 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
         }
         return coordinateMap;
     }
+    private Map<String, Map<String, String>> createCoordinateMap2( List<Long> pkeyIds, ExecuteType type) {
+        Map<String, Map<String, String>> coordinateMap = new HashMap<>(pkeyIds.size() * 2);
+        if (pkeyIds.size() > 0) {
+            if (ExecuteType.TESTING.equals(type)) {
+                List<WbsTreePrivate> list = wbsTreePrivateService.getBaseMapper().selectList(Wrappers.<WbsTreePrivate>query().lambda().in(WbsTreePrivate::getPKeyId, pkeyIds));
+                if (list.size() > 0) {
+                    list.forEach(e -> coordinateMap.computeIfAbsent(e.getInitTableName(), k -> FormulaUtils.getElementCell(e.getHtmlUrl())));
+                }
+            } else {
+                List<WbsTreeContract> list = wbsTreeContractService.getBaseMapper().selectList(Wrappers.<WbsTreeContract>query().lambda().in(WbsTreeContract::getPKeyId, pkeyIds));
+                if (list.size() > 0) {
+                    list.forEach(e -> coordinateMap.computeIfAbsent(e.getInitTableName(), k -> FormulaUtils.getElementCell(e.getHtmlUrl())));
+                }
+            }
+        }
+        return coordinateMap;
+    }
 
     private void updateFormulaLog(String log, Long pKeyId) {
         try {

+ 71 - 46
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java

@@ -15,6 +15,7 @@ import org.apache.poi.ss.usermodel.*;
 import org.springblade.common.utils.BaseUtils;
 import org.springblade.common.utils.CommonUtil;
 import org.springblade.common.utils.SnowFlakeUtil;
+import org.springblade.core.mp.base.BaseEntity;
 import org.springblade.core.mp.base.BaseServiceImpl;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.*;
@@ -1364,6 +1365,38 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
         return Collections.emptyList();
     }
 
+    @Override
+    public void formulaInto(List<FormData> curFormDatas, String projectId, String nodeId, ExecuteType executeType) {
+        if(executeType.equals(ExecuteType.INSPECTION)){
+            WbsTreePrivate wtp =wtpId(Long.parseLong(nodeId));
+            /*项目级*/
+            Long nodeIdPrivate= wtp.getId();
+            WbsTreePrivate origin =getOriginWtp(wtp.getPKeyId());
+            String wbsId =StringUtils.handleNull(origin.getPKeyId());
+            /*Wbs对应的节点*/
+            Long nodeIdWbs=origin.getId();
+            List<Map<String,Object>> efMap= this.jdbcTemplate.queryForList("select element_id elementId,formula_id formulaId,scope " +
+                    "from m_element_formula_mapping " +
+                    "where element_id in(" + curFormDatas.stream().map(FormData::getId).map(Func::toStr).collect(Collectors.joining(",")) + ") " +
+                    "and is_deleted=0 " + " and (scope=0 or (scope=1 and wbs_id="+wbsId+") or(scope=2  and wbs_id="+wbsId+" and node_id="+nodeIdWbs+")or (scope =10 and project_id = " + projectId + ") or (scope=20 and project_id =" + projectId + " and node_id=" +nodeIdPrivate +"))");
+            setFormula2(curFormDatas,efMap);
+            /*节点参数公式*/
+            setParamsFormula2( wtp.getPKeyId(),origin.getId(),curFormDatas);
+            List<Long> formulaIds = curFormDatas.stream().map(FormData::getFormulaId).distinct().collect(Collectors.toList());
+            if(formulaIds.size()>0) {
+                List<Formula> formulaList = this.listByIds(formulaIds);
+                if (formulaList.size() > 0) {
+                    Map<Long, Formula> idMap = formulaList.stream().collect(Collectors.toMap(Formula::getId, f -> f, (p, n) -> n));
+                    for (FormData fd : curFormDatas) {
+                        fd.setFormula(idMap.get(fd.getFormulaId()));
+                    }
+                }
+            }
+        }else if(executeType.equals(ExecuteType.TESTING)){
+
+        }
+    }
+
     @Override
     public WbsTreePrivate getOriginWtp(Long pkeyId) {
         WbsTreePrivate wtp = this.wbsTreePrivateService.getOne(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getPKeyId,pkeyId));
@@ -1480,7 +1513,31 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
         }
 
     }
+    private void setParamsFormula2(Long privatePkeyId,Long wbsNodeId, List<FormData> list){
+        if(StringUtils.isNotEmpty(privatePkeyId,wbsNodeId)){
+            List<WbsParam> total = new ArrayList<>();
+            List<WbsParam> wpsPublic = this.wpService.list(Wrappers.<WbsParam>lambdaQuery().eq(WbsParam::getNodeId,wbsNodeId));
+            /*同时获取WBS和 项目级的节点参数,如果存在同名则项目级覆盖WBS*/
+            if(Func.isNotEmpty(wpsPublic)){
+                total.addAll(wpsPublic);
+            }
+            List<WbsParam> wpsPrivate = this.wpService.list(Wrappers.<WbsParam>lambdaQuery().eq(WbsParam::getNodeId,privatePkeyId));
+            if(Func.isNotEmpty(wpsPrivate)){
+                total.addAll(wpsPrivate);
+            }
+            if(Func.isNotEmpty(total)){
+                List<ElementFormulaMapping> mappingList =  this.elementFormulaMappingService.list(Wrappers.<ElementFormulaMapping>lambdaQuery().in(ElementFormulaMapping::getParamId,total.stream().map(WbsParam::getId).collect(Collectors.toList())));
+                if(Func.isNotEmpty(mappingList)){
+                    list.forEach(e->{
+                        mappingList.stream().filter(m->StringUtils.isEquals(m.getElementId(),e.getId())).findAny().ifPresent(d-> e.setFormulaId(d.getFormulaId()));
+                    });
+
+                }
+            }
 
+        }
+
+    }
     private List<KeyMapper> listForPrivate(List<Long> ids,String projectId,String nodeId){
         /**/
         List<Map<String,Object>> listMap  = listMap(ids,ExecuteType.TESTING);
@@ -1522,6 +1579,19 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
             });
         }
     }
+    private void setFormula2(List<FormData> list,List<Map<String,Object>> efMap){
+        if(Func.isNotEmpty(efMap)){
+            Map<Long,List<Map<String,Object>>> efGroup= efMap.stream().collect(Collectors.groupingBy(e->Func.toLong(e.get("elementId"))));
+            list.forEach(e->{
+                List<Map<String,Object>> tmp = efGroup.get(e.getId());
+                if(Func.isNotEmpty(tmp)){
+                    tmp.stream().max(Comparator.comparing(oo->Func.toInt(oo.get("scope")))).ifPresent(d->{
+                       e.setFormulaId(Func.toLong(d.get("formulaId")));
+                    });
+                }
+            });
+        }
+    }
 
     @Override
     public List<Formula> getFormulaList(List<KeyMapper> keyMapperList) {
@@ -1537,42 +1607,6 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
 
 
 
-/*    public  List<Object> slice(List<LocalVariable>  local,String formula){
-        int min =0;
-        List<Object> result = new ArrayList<>();
-        try {
-            pretreatment(local,formula);
-            List<Object>  r= local.stream().map(e-> {
-                *//*所有依赖元素的内容必须非空才进行计算,否则返回空值*//*
-                return e.hasEmptyElementValue()?"": Expression.parse(e.getFormula()).calculate(e.getCurrentMap());
-            }).collect(Collectors.toList());
-            if(CollectionUtil.isNotEmpty(r)&&r.stream().anyMatch(StringUtils::isNotEmpty)){
-                result.addAll(r);
-            }
-        }catch (Exception e){
-            StaticLog.error("公式:{},执行出错",formula);
-        }
-        return  result;
-    }*/
-
-/*    public void  pretreatment(List<LocalVariable>  local,String formula){
-        formula=StringUtils.removeMultiSpace(formula);
-        if(formula.contains("LIST")){
-            Matcher  m=RegexUtils.matcher("\\(([^)]*)\\)/LIST",formula);
-            while (m.find()){
-                List<String> codes=FormulaUtils.getCodeList(m.group(1).replaceAll("[+-]",","));
-                local=local.stream().peek(e->{
-                    @SuppressWarnings("unckecked")
-                    Map<String,Object> map = (Map<String, Object>) e.getCurrentMap().getOrDefault(E,new HashMap<>());
-                    int listSize=(int)codes.stream().filter(c->StringUtils.isNotEmpty(map.get(c))).count();
-                    if(listSize<=0||listSize>codes.size()){
-                        listSize=codes.size();
-                    }
-                    map.put("LIST",listSize);
-                }).collect(Collectors.toList());
-            }
-        }
-    }*/
 
 
     public  static void sort( List<FormData> list,int n){
@@ -1918,16 +1952,7 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
     }
 
 
-    /*从方法参数中获取全部code*/
-/*    public List<String> getCodeList(String param){
-        List<String> list = new ArrayList<>();
-        if(StringUtils.isNotEmpty(param)){
-            Arrays.stream(param.split(",")).forEach(s->{
-                list.add(s.replaceAll("[E\\[\\]']",""));
-            });
-        }
-        return list;
-    }*/
+
 
     public List<String> getCodeByEl(String el){
         List<String> l = new ArrayList<>();

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

@@ -2326,13 +2326,13 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
      * @param distinctNodesAll 去重后所有节点数据
      * @return
      */
-    private List<NodeVO> buildNodeTreeByStream(List<WbsTreeContractLazyVO> distinctNodesAll, Map<Long, WbsTreeContractLazyVO> lowestNodesMap) {
+    public 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) {
+    public 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)) {
@@ -2357,7 +2357,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
     }
 
     //转换VO
-    private NodeVO convertToNodeVO(WbsTreeContractLazyVO wbsTreeContractLazyVO) {
+    public NodeVO convertToNodeVO(WbsTreeContractLazyVO wbsTreeContractLazyVO) {
         NodeVO nodeVO = new NodeVO();
         nodeVO.setId(wbsTreeContractLazyVO.getId());
         nodeVO.setParentId(wbsTreeContractLazyVO.getParentId());
@@ -2367,7 +2367,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
     }
 
     //把树形结构转为普通List
-    private List<NodeVO> flattenTree(List<NodeVO> tree) {
+    public List<NodeVO> flattenTree(List<NodeVO> tree) {
         List<NodeVO> result = new ArrayList<>();
         for (NodeVO node : tree) {
             result.add(node);