Эх сурвалжийг харах

Merge branch 'master' of http://47.110.251.215:3000/java_org/bladex

huangtf 2 жил өмнө
parent
commit
e87bd83c37

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

@@ -136,7 +136,7 @@ public class ExcelTabController extends BladeController {
     @ApiOperationSupport(order = 1)
     @ApiOperation(value = "详情", notes = "传入excelTab")
     public R<ExcelTabVO> detail(ExcelTab excelTab) {
-        ExcelTab detail = excelTabService.getOne(Condition.getQueryWrapper(excelTab));
+        ExcelTab detail = excelTabService.getOne(Condition.getQueryWrapper(excelTab) );
         return R.data(ExcelTabWrapper.build().entityVO(detail));
     }
 

+ 6 - 6
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreePrivateController.java

@@ -495,20 +495,20 @@ public class WbsTreePrivateController extends BladeController {
      * 同步项目下所有节点参数
      */
     @ApiOperationSupport(order = 14)
-    @ApiOperation(value = "同步项目下所有节点参数", notes = "传入项目projectId")
+    @ApiOperation(value = "同步项目下所有节点参数", notes = "传入项目projectId、节点pKeyId")
     @RequestMapping(value = "/sync-node-param", method = RequestMethod.POST)
-    public R syncNodeParam(@RequestParam String projectId) {
-        return R.status(wbsTreePrivateService.syncNodeParam(projectId));
+    public R syncNodeParam(@RequestParam String projectId, @RequestParam String pKeyId) {
+        return R.status(wbsTreePrivateService.syncNodeParam(projectId, pKeyId));
     }
 
     /**
      * 同步项目下所有节点的电签默认信息
      */
     @ApiOperationSupport(order = 14)
-    @ApiOperation(value = "同步项目下所有节点的电签默认信息", notes = "传入项目projectId")
+    @ApiOperation(value = "同步项目下所有节点的电签默认信息", notes = "传入项目projectId、节点pKeyId")
     @RequestMapping(value = "/sync-project-eVisa", method = RequestMethod.POST)
-    public R syncProjectEVisa(@RequestParam String projectId) {
-        return R.status(wbsTreePrivateService.syncProjectEVisa(projectId));
+    public R syncProjectEVisa(@RequestParam String projectId, @RequestParam String pKeyId) {
+        return R.status(wbsTreePrivateService.syncProjectEVisa(projectId, pKeyId));
     }
 
     /**

+ 7 - 7
blade-service/blade-manager/src/main/java/org/springblade/manager/service/IWbsTreePrivateService.java

@@ -48,15 +48,19 @@ public interface IWbsTreePrivateService extends BaseService<WbsTreePrivate> {
 
     boolean updateStatus(String pKeyId);
 
-    boolean updateBatchByIds(List<WbsTree> wbsTreeListAll, List<WbsTreePrivate> wbsTreePrivatesAll, String projectId, Integer wbsType);
+    boolean asyncUpdateWbsPublic(List<WbsTree> wbsTreeListAll, List<WbsTreePrivate> wbsTreePrivatesAll, String projectId, Integer wbsType);
 
-    boolean updateBatchByIds2(List<WbsTreePrivate> wbsTreePrivates, List<WbsTreePrivate> wbsTreePrivatesAllNow, String projectId, String wbsId, Integer wbsType);
+    boolean asyncUpdateWbsPrivate(List<WbsTreePrivate> wbsTreePrivates, List<WbsTreePrivate> wbsTreePrivatesAllNow, String projectId, String wbsId, Integer wbsType);
 
     WbsNodeTabAndParamVO getNodeTabAndParam(String id, String wbsId, String projectId);
 
     boolean submitFullName(String pKeyId, String fullNames);
 
-    boolean syncNodeParam(String projectId);
+    boolean syncNodeParam(String projectId, String pKeyId);
+
+    boolean syncProjectEVisa(String projectId, String pKeyId);
+
+    void eVisInfoRepeatDel(String pid);
 
     boolean syncNodeTable(String primaryKeyId);
 
@@ -77,10 +81,6 @@ public interface IWbsTreePrivateService extends BaseService<WbsTreePrivate> {
 
     Object getExcelHtml(String primaryKeyId) throws IOException;
 
-    boolean syncProjectEVisa(String projectId);
-
-    void eVisInfoRepeatDel(String pid);
-
     //批量重新保存文件htmlUrl
     void batchResetHtmlUrl(List<WbsTreePrivate> wbsTreePrivateList) throws IOException, InterruptedException;
 

+ 486 - 384
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreePrivateServiceImpl.java

@@ -393,125 +393,116 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
     }
 
     @Override
-    public boolean updateBatchByIds(List<WbsTree> wbsTreeListAll, List<WbsTreePrivate> wbsTreePrivatesAll, String projectId, Integer wbsType) {
+    public boolean asyncUpdateWbsPublic(List<WbsTree> wbsTreeListAll, List<WbsTreePrivate> wbsTreePrivatesAll, String projectId, Integer wbsType) {
+        //结果集
         List<WbsTreePrivate> listPrivate = new ArrayList<>();
         List<WbsTreeContract> listContract = new ArrayList<>();
+
         //获取当前项目下所有合同段信息
-        List<ContractInfo> contractInfos = contractInfoMapper.selectList(Wrappers.<ContractInfo>query().lambda().eq(ContractInfo::getPId, projectId));
+        List<ContractInfo> contractInfos = contractInfoMapper.selectList(Wrappers.<ContractInfo>query().lambda().select(ContractInfo::getId, ContractInfo::getContractType).eq(ContractInfo::getPId, projectId));
+        List<Long> contractInfosIds = contractInfos.stream().filter(f -> 1 == f.getContractType()).map(ContractInfo::getId).collect(Collectors.toList());
+        Map<Long, WbsTreePrivate> maps = wbsTreePrivatesAll.stream().collect(Collectors.toMap(WbsTreePrivate::getId, wbsTreePrivate -> wbsTreePrivate, (obj1, obj2) -> obj1));
 
         for (WbsTree wbsTree : wbsTreeListAll) {
-            for (WbsTreePrivate wbsTreePrivate : wbsTreePrivatesAll) {
-                //判断相同节点基础信息、元素表类型、元素表所属方是否发生改变
-                if (wbsTree.getId().equals(wbsTreePrivate.getId()) &&
-                        (!wbsTree.getNodeName().equals(wbsTreePrivate.getNodeName())
-                                || (ObjectUtils.isNotEmpty(wbsTree.getNodeType()) && !wbsTree.getNodeType().equals(wbsTreePrivate.getNodeType()))
-                                || (ObjectUtils.isNotEmpty(wbsTree.getMajorDataType()) && !wbsTree.getMajorDataType().equals(wbsTreePrivate.getMajorDataType()))
-                                || (ObjectUtils.isNotEmpty(wbsTree.getTableType()) && !wbsTree.getTableType().equals(wbsTreePrivate.getTableType()))
-                                || (ObjectUtils.isNotEmpty(wbsTree.getTableOwner()) && !wbsTree.getTableOwner().equals(wbsTreePrivate.getTableOwner()))
-                                || (ObjectUtils.isNotEmpty(wbsTree.getImportMatchingInfo()) && !wbsTree.getImportMatchingInfo().equals(wbsTreePrivate.getImportMatchingInfo()))
-                                || (ObjectUtils.isNotEmpty(wbsTree.getMixRatioTestIds()) && !wbsTree.getMixRatioTestIds().equals(wbsTreePrivate.getMixRatioTestIds()))
-                                || (ObjectUtils.isNotEmpty(wbsTree.getInitTableId()) && !wbsTree.getInitTableId().toString().equals(wbsTreePrivate.getInitTableId()))
-                                || (ObjectUtils.isNotEmpty(wbsTree.getInitTableName()) && !wbsTree.getInitTableName().equals(wbsTreePrivate.getInitTableName()))
-                                || ((new Integer(1)).equals(wbsTreePrivate.getType()) && ObjectUtils.isNotEmpty(wbsTree.getSort()) && !wbsTree.getSort().equals(wbsTreePrivate.getSort()))
-                        )) {
-                    //修改项目wbs信息
-                    WbsTreePrivate wbsPrivate = BeanUtil.copyProperties(wbsTree, WbsTreePrivate.class);
-                    if (wbsPrivate != null) {
-                        wbsPrivate.setProjectId(projectId);
-                        listPrivate.add(wbsPrivate);
-                    }
-                    for (ContractInfo contractInfo : contractInfos) {
-                        //修改合同段wbs信息
-                        WbsTreeContract wbsContract = BeanUtil.copyProperties(wbsTree, WbsTreeContract.class);
-                        if (wbsContract != null) {
-                            wbsContract.setContractId(String.valueOf(contractInfo.getId()));
-                            wbsContract.setProjectId(projectId);
-                            listContract.add(wbsContract);
-                        }
+            WbsTreePrivate wbsTreePrivate = maps.get(wbsTree.getId());
+            //判断相同节点基础信息、元素表类型、元素表所属方是否发生改变
+            if (wbsTreePrivate != null && this.fieldsNotEqualPublicWbs(wbsTree, wbsTreePrivate)) {
+                //修改项目wbs信息
+                WbsTreePrivate wbsPrivate = BeanUtil.copyProperties(wbsTree, WbsTreePrivate.class);
+                if (wbsPrivate != null) {
+                    wbsPrivate.setProjectId(projectId);
+                    listPrivate.add(wbsPrivate);
+                }
+                for (ContractInfo contractInfo : contractInfos) {
+                    //修改合同段wbs信息
+                    WbsTreeContract wbsContract = BeanUtil.copyProperties(wbsTree, WbsTreeContract.class);
+                    if (wbsContract != null) {
+                        wbsContract.setContractId(String.valueOf(contractInfo.getId()));
+                        wbsContract.setProjectId(projectId);
+                        listContract.add(wbsContract);
                     }
                 }
             }
         }
 
+        //修改到项目
         if (listPrivate.size() > 0) {
             baseMapper.updateBatchWbsPrivate(listPrivate);
         }
-        if (listContract.size() > 0) {
-            //获取合同段下的复制、新增节点
-            List<WbsTreeContract> wbsTreeContractsCopyOrAddAll = new ArrayList<>();
-            for (ContractInfo contractInfo : contractInfos) {
-                List<WbsTreeContract> wbsTreeContractsCopyOrAdd = wbsTreeContractMapper.selectList(Wrappers.<WbsTreeContract>lambdaQuery()
-                        .eq(WbsTreeContract::getProjectId, projectId)
-                        .eq(WbsTreeContract::getContractId, contractInfo.getId())
-                        .eq(WbsTreeContract::getWbsType, wbsType)
-                        .eq(WbsTreeContract::getType, 1)
-                        .isNotNull(WbsTreeContract::getOldId)
-                );
-                wbsTreeContractsCopyOrAddAll.addAll(wbsTreeContractsCopyOrAdd);
-            }
 
+        //修改到合同段
+        if (listContract.size() > 0) {
+            //获取当前项目下所有合同段下的复制、新增节点
+            String sql = "select id,old_id,project_id,contract_id from m_wbs_tree_contract where project_id = " + projectId + " and contract_id in(" + org.apache.commons.lang.StringUtils.join(contractInfosIds, ",") + ") and wbs_type = " + wbsType + " and type = 1 and status = 1 and is_deleted = 0 and old_id is not null";
+            List<WbsTreeContract> wbsTreeContractsCopyOrAddAll = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(WbsTreeContract.class));
+            Map<String, List<WbsTreeContract>> copyAddNodes = wbsTreeContractsCopyOrAddAll.stream().collect(Collectors.groupingBy(WbsTreeContract::getOldId));
             List<WbsTreeContract> listContractAdd = new ArrayList<>();
-
             for (WbsTreeContract obj1 : listContract) {
-                for (WbsTreeContract obj2 : wbsTreeContractsCopyOrAddAll) {
-                    if (obj1.getId().toString().equals(obj2.getOldId()) && obj1.getProjectId().equals(obj2.getProjectId()) && obj1.getContractId().equals(obj2.getContractId())) {
+                List<WbsTreeContract> copyAddNodesNow = copyAddNodes.get(obj1.getId().toString());
+                if (ObjectUtils.isNotEmpty(copyAddNodesNow) && copyAddNodesNow.size() > 0) {
+                    WbsTreeContract obj2 = copyAddNodesNow.stream().filter(f -> f.getContractId().equals(obj1.getContractId()) && f.getProjectId().equals(obj1.getProjectId())).findAny().orElse(null);
+                    if (obj2 != null) {
                         obj2.setNodeName(obj1.getNodeName());
                         obj2.setNodeType(obj1.getNodeType());
                         obj2.setMajorDataType(obj1.getMajorDataType());
                         obj2.setTableType(obj1.getTableType());
                         obj2.setTableOwner(obj1.getTableOwner());
+                        obj2.setHtmlUrl(obj1.getHtmlUrl());
                         listContractAdd.add(obj2);
                     }
                 }
             }
-
             listContractAdd.addAll(listContract);
             wbsTreeContractMapper.updateBatchWbsContract(listContractAdd);
+
+            //更新redis缓存
+            this.refreshRedisCache(listContractAdd);
         }
         return true;
     }
 
+    @Async
+    public void refreshRedisCache(List<WbsTreeContract> listContractAdd) {
+        Map<Long, List<String>> contractIdByParentIds = listContractAdd.stream()
+                .collect(Collectors.groupingBy(WbsTreeContract::getParentId,
+                        Collectors.mapping(WbsTreeContract::getContractId, Collectors.toList())));
+        Set<Long> parentIds = contractIdByParentIds.keySet();
+        for (Long parentId : parentIds) {
+            String contractId = contractIdByParentIds.get(parentId).stream().findAny().orElse(null);
+            informationQueryClient.AsyncWbsTree("", parentId + "", contractId + "", "", "1");
+        }
+    }
+
     @Override
-    public boolean updateBatchByIds2(List<WbsTreePrivate> wbsTreePrivates, List<WbsTreePrivate> wbsTreePrivatesAllNow, String projectId, String wbsId, Integer wbsType) {
+    public boolean asyncUpdateWbsPrivate(List<WbsTreePrivate> wbsTreePrivates, List<WbsTreePrivate> wbsTreePrivatesAllNow, String projectId, String wbsId, Integer wbsType) {
+        //结果集
         List<WbsTreePrivate> listPrivate = new ArrayList<>();
         List<WbsTreeContract> listContract = new ArrayList<>();
+
         //获取当前项目下所有合同段信息
-        List<ContractInfo> contractInfos = contractInfoMapper.selectList(Wrappers.<ContractInfo>query().lambda().select(ContractInfo::getId, ContractInfo::getContractType)
-                .eq(ContractInfo::getContractType, 1)
-                .eq(ContractInfo::getPId, projectId));
+        List<ContractInfo> contractInfos = contractInfoMapper.selectList(Wrappers.<ContractInfo>query().lambda().select(ContractInfo::getId, ContractInfo::getContractType).eq(ContractInfo::getContractType, 1).eq(ContractInfo::getPId, projectId));
         List<Long> contractInfosIds = contractInfos.stream().filter(f -> 1 == f.getContractType()).map(ContractInfo::getId).collect(Collectors.toList());
 
         Map<Long, WbsTreePrivate> maps = wbsTreePrivatesAllNow.stream().collect(Collectors.toMap(WbsTreePrivate::getId, wbsTreePrivate -> wbsTreePrivate, (obj1, obj2) -> obj1));
 
         for (WbsTreePrivate wbsTreePrivate : wbsTreePrivates) {
             WbsTreePrivate treePrivateNow = maps.get(wbsTreePrivate.getId());
-            if (treePrivateNow != null) {
-                if (!wbsTreePrivate.getNodeName().equals(treePrivateNow.getNodeName())
-                        || (ObjectUtils.isNotEmpty(wbsTreePrivate.getNodeType()) && !wbsTreePrivate.getNodeType().equals(treePrivateNow.getNodeType()))
-                        || (ObjectUtils.isNotEmpty(wbsTreePrivate.getMajorDataType()) && !wbsTreePrivate.getMajorDataType().equals(treePrivateNow.getMajorDataType()))
-                        || (ObjectUtils.isNotEmpty(wbsTreePrivate.getTableType()) && !wbsTreePrivate.getTableType().equals(treePrivateNow.getTableType()))
-                        || (ObjectUtils.isNotEmpty(wbsTreePrivate.getTableOwner()) && !wbsTreePrivate.getTableOwner().equals(treePrivateNow.getTableOwner()))
-                        || (ObjectUtils.isNotEmpty(wbsTreePrivate.getImportMatchingInfo()) && !wbsTreePrivate.getImportMatchingInfo().equals(treePrivateNow.getImportMatchingInfo()))
-                        || (ObjectUtils.isNotEmpty(wbsTreePrivate.getMixRatioTestIds()) && !wbsTreePrivate.getMixRatioTestIds().equals(treePrivateNow.getMixRatioTestIds()))
-                        || (ObjectUtils.isNotEmpty(wbsTreePrivate.getInitTableId()) && !wbsTreePrivate.getInitTableId().equals(treePrivateNow.getInitTableId()))
-                        || (ObjectUtils.isNotEmpty(wbsTreePrivate.getInitTableName()) && !wbsTreePrivate.getInitTableName().equals(treePrivateNow.getInitTableName())
-                        || (ObjectUtils.isNotEmpty(wbsTreePrivate.getHtmlUrl()) && !wbsTreePrivate.getHtmlUrl().equals(treePrivateNow.getHtmlUrl())))
-                        || ((new Integer(1)).equals(wbsTreePrivate.getType()) && ObjectUtils.isNotEmpty(wbsTreePrivate.getSort()) && !wbsTreePrivate.getSort().equals(treePrivateNow.getSort()))) {
-                    //修改项目wbs信息
-                    WbsTreePrivate wbsPrivate = BeanUtil.copyProperties(wbsTreePrivate, WbsTreePrivate.class);
-                    if (wbsPrivate != null) {
-                        wbsPrivate.setWbsId(wbsId);
-                        wbsPrivate.setProjectId(projectId);
-                        listPrivate.add(wbsPrivate);
-                    }
-                    for (Long id : contractInfosIds) {
-                        //修改合同段wbs信息
-                        WbsTreeContract wbsContract = BeanUtil.copyProperties(wbsTreePrivate, WbsTreeContract.class);
-                        if (wbsContract != null) {
-                            wbsContract.setContractId(id.toString());
-                            wbsContract.setProjectId(projectId);
-                            listContract.add(wbsContract);
-                        }
+            //判断相同节点基础信息、元素表类型、元素表所属方是否发生改变
+            if (treePrivateNow != null && this.fieldsNotEqualPrivateWbs(wbsTreePrivate, treePrivateNow)) {
+                //修改项目wbs信息
+                WbsTreePrivate wbsPrivate = BeanUtil.copyProperties(wbsTreePrivate, WbsTreePrivate.class);
+                if (wbsPrivate != null) {
+                    wbsPrivate.setWbsId(wbsId);
+                    wbsPrivate.setProjectId(projectId);
+                    listPrivate.add(wbsPrivate);
+                }
+                for (Long id : contractInfosIds) {
+                    //修改合同段wbs信息
+                    WbsTreeContract wbsContract = BeanUtil.copyProperties(wbsTreePrivate, WbsTreeContract.class);
+                    if (wbsContract != null) {
+                        wbsContract.setContractId(id.toString());
+                        wbsContract.setProjectId(projectId);
+                        listContract.add(wbsContract);
                     }
                 }
             }
@@ -528,7 +519,6 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
             String sql = "select id,old_id,project_id,contract_id from m_wbs_tree_contract where project_id = " + projectId + " and contract_id in(" + org.apache.commons.lang.StringUtils.join(contractInfosIds, ",") + ") and wbs_type = " + wbsType + " and type = 1 and status = 1 and is_deleted = 0 and old_id is not null";
             List<WbsTreeContract> wbsTreeContractsCopyOrAddAll = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(WbsTreeContract.class));
             Map<String, List<WbsTreeContract>> copyAddNodes = wbsTreeContractsCopyOrAddAll.stream().collect(Collectors.groupingBy(WbsTreeContract::getOldId));
-
             List<WbsTreeContract> listContractAdd = new ArrayList<>();
             for (WbsTreeContract obj1 : listContract) {
                 List<WbsTreeContract> copyAddNodesNow = copyAddNodes.get(obj1.getId().toString());
@@ -545,13 +535,89 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
                     }
                 }
             }
-
             listContractAdd.addAll(listContract);
             wbsTreeContractMapper.updateBatchWbsContract(listContractAdd);
+
+            //更新redis缓存
+            this.refreshRedisCache(listContractAdd);
         }
         return true;
     }
 
+    /**
+     * 比较对象字段是否相等 公有wbs
+     *
+     * @param a
+     * @param b
+     * @return boolean
+     */
+    private boolean fieldsNotEqualPublicWbs(WbsTree a, WbsTreePrivate b) {
+        if (new Integer(1).equals(a.getType())) {
+            return !Objects.equals(nonNull(a.getNodeName()), nonNull(b.getNodeName()))
+                    || !Objects.equals(nonNull(a.getNodeType()), nonNull(b.getNodeType()))
+                    || !Objects.equals(nonNull(a.getMajorDataType()), nonNull(b.getMajorDataType()))
+                    || !Objects.equals(nonNull(a.getTableType()), nonNull(b.getTableType()))
+                    || !Objects.equals(nonNull(a.getTableOwner()), nonNull(b.getTableOwner()))
+                    || !Objects.equals(nonNull(a.getImportMatchingInfo()), nonNull(b.getImportMatchingInfo()))
+                    || !Objects.equals(nonNull(a.getMixRatioTestIds()), nonNull(b.getMixRatioTestIds()))
+                    || !Objects.equals(nonNull(a.getInitTableId()), nonNull(b.getInitTableId()))
+                    || !Objects.equals(nonNull(a.getInitTableName()), nonNull(b.getInitTableName()))
+                    || !Objects.equals(a.getSort(), b.getSort());
+        }
+        return !Objects.equals(nonNull(a.getNodeName()), nonNull(b.getNodeName()))
+                || !Objects.equals(nonNull(a.getNodeType()), nonNull(b.getNodeType()))
+                || !Objects.equals(nonNull(a.getMajorDataType()), nonNull(b.getMajorDataType()))
+                || !Objects.equals(nonNull(a.getTableType()), nonNull(b.getTableType()))
+                || !Objects.equals(nonNull(a.getTableOwner()), nonNull(b.getTableOwner()))
+                || !Objects.equals(nonNull(a.getImportMatchingInfo()), nonNull(b.getImportMatchingInfo()))
+                || !Objects.equals(nonNull(a.getMixRatioTestIds()), nonNull(b.getMixRatioTestIds()))
+                || !Objects.equals(nonNull(a.getInitTableId()), nonNull(b.getInitTableId()))
+                || !Objects.equals(nonNull(a.getInitTableName()), nonNull(b.getInitTableName()));
+    }
+
+    /**
+     * 比较对象字段是否相等 私有wbs
+     *
+     * @param a
+     * @param b
+     * @return boolean
+     */
+    private boolean fieldsNotEqualPrivateWbs(WbsTreePrivate a, WbsTreePrivate b) {
+        if (new Integer(1).equals(a.getType())) {
+            return !Objects.equals(nonNull(a.getNodeName()), nonNull(b.getNodeName()))
+                    || !Objects.equals(nonNull(a.getNodeType()), nonNull(b.getNodeType()))
+                    || !Objects.equals(nonNull(a.getMajorDataType()), nonNull(b.getMajorDataType()))
+                    || !Objects.equals(nonNull(a.getTableType()), nonNull(b.getTableType()))
+                    || !Objects.equals(nonNull(a.getTableOwner()), nonNull(b.getTableOwner()))
+                    || !Objects.equals(nonNull(a.getImportMatchingInfo()), nonNull(b.getImportMatchingInfo()))
+                    || !Objects.equals(nonNull(a.getMixRatioTestIds()), nonNull(b.getMixRatioTestIds()))
+                    || !Objects.equals(nonNull(a.getInitTableId()), nonNull(b.getInitTableId()))
+                    || !Objects.equals(nonNull(a.getInitTableName()), nonNull(b.getInitTableName()))
+                    || !Objects.equals(nonNull(a.getHtmlUrl()), nonNull(b.getHtmlUrl()))
+                    || !Objects.equals(nonNull(a.getSort()), nonNull(b.getSort()));
+        }
+        return !Objects.equals(nonNull(a.getNodeName()), nonNull(b.getNodeName()))
+                || !Objects.equals(nonNull(a.getNodeType()), nonNull(b.getNodeType()))
+                || !Objects.equals(nonNull(a.getMajorDataType()), nonNull(b.getMajorDataType()))
+                || !Objects.equals(nonNull(a.getTableType()), nonNull(b.getTableType()))
+                || !Objects.equals(nonNull(a.getTableOwner()), nonNull(b.getTableOwner()))
+                || !Objects.equals(nonNull(a.getImportMatchingInfo()), nonNull(b.getImportMatchingInfo()))
+                || !Objects.equals(nonNull(a.getMixRatioTestIds()), nonNull(b.getMixRatioTestIds()))
+                || !Objects.equals(nonNull(a.getInitTableId()), nonNull(b.getInitTableId()))
+                || !Objects.equals(nonNull(a.getInitTableName()), nonNull(b.getInitTableName()))
+                || !Objects.equals(nonNull(a.getHtmlUrl()), nonNull(b.getHtmlUrl()));
+    }
+
+    /**
+     * 字段非空判断
+     *
+     * @param obj
+     * @return
+     */
+    private Object nonNull(Object obj) {
+        return obj != null ? obj : "";
+    }
+
     @Override
     public WbsNodeTabAndParamVO getNodeTabAndParam(String id, String wbsId, String projectId) {
         WbsNodeTabAndParamVO resultList = new WbsNodeTabAndParamVO();
@@ -591,230 +657,366 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
         return false;
     }
 
+    /**
+     * 节点参数同步-获取所有子级节点
+     */
+    private List<WbsTreePrivate> getChildNodes(WbsTreePrivate obj) {
+        if (obj != null) {
+            List<WbsTreePrivate> wbsTreePrivates = Collections.singletonList(obj);
+            List<WbsTreePrivate> result = new ArrayList<>();
+            this.recursionGetChildNodes(wbsTreePrivates, result, obj);
+            if (result.size() > 0) {
+                return result;
+            }
+        }
+        return null;
+    }
+
+    private void recursionGetChildNodes(List<WbsTreePrivate> list, List<WbsTreePrivate> result, WbsTreePrivate obj) {
+        List<Long> ids = list.stream().map(WbsTreePrivate::getId).collect(Collectors.toList());
+        if (ids.size() > 0) {
+            List<WbsTreePrivate> query = baseMapper.selectList(Wrappers.<WbsTreePrivate>lambdaQuery()
+                    .select(WbsTreePrivate::getPKeyId, WbsTreePrivate::getId)
+                    .in(WbsTreePrivate::getParentId, ids)
+                    .eq(WbsTreePrivate::getProjectId, obj.getProjectId())
+                    .eq(WbsTreePrivate::getWbsId, obj.getWbsId())
+                    .eq(WbsTreePrivate::getWbsType, obj.getWbsType())
+                    .eq(WbsTreePrivate::getType, 1)
+                    .eq(WbsTreePrivate::getStatus, 1));
+            if (query.size() > 0) {
+                result.addAll(query);
+                recursionGetChildNodes(query, result, obj);
+            }
+        }
+    }
+
+
     @Override
-    public boolean syncNodeParam(String projectId) {
-        if (StringUtils.isNotEmpty(projectId)) {
+    public boolean syncNodeParam(String projectId, String pKeyId) {
+        if (StringUtils.isNotEmpty(projectId) && StringUtils.isNotEmpty(pKeyId)) {
+            //当前选择同步的节点信息
+            WbsTreePrivate selectNodeNow = baseMapper.selectOne(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getPKeyId, pKeyId).eq(WbsTreePrivate::getStatus, 1));
+            if (selectNodeNow == null) {
+                throw new ServiceException("未获取到当前选择同步的节点信息,请联系管理员");
+            }
+
             //结果集
             List<WbsParam> updateList = new ArrayList<>();
             List<WbsParam> insertList = new ArrayList<>();
+            List<WbsParamVO> paramListData = new ArrayList<>();
+            List<WbsParam> wbsParamOldList = new ArrayList<>();
+
+            //获取当前选择的节点与它所有子节点
+            List<WbsTreePrivate> selectNodeAndChildNodes = this.getChildNodes(selectNodeNow);
+            if (selectNodeAndChildNodes == null || selectNodeAndChildNodes.size() == 0) {
+                selectNodeAndChildNodes = new ArrayList<>();
+                selectNodeAndChildNodes.add(selectNodeNow);
+            } else {
+                selectNodeAndChildNodes.add(selectNodeNow);
+            }
+            List<Long> privateNodeIds = selectNodeAndChildNodes.stream().map(WbsTreePrivate::getId).collect(Collectors.toList());
+            List<Long> privateNodePKeyIds = selectNodeAndChildNodes.stream().map(WbsTreePrivate::getPKeyId).collect(Collectors.toList());
+
+            //获取对应公有树节点
+            Map<Long, WbsTree> treePublicNodeAll = wbsTreeMapper.selectList(Wrappers.<WbsTree>query().lambda()
+                    .select(WbsTree::getId)
+                    .in(WbsTree::getId, privateNodeIds)
+                    .eq(WbsTree::getStatus, 1)
+                    .eq(WbsTree::getType, 1))
+                    .stream().collect(Collectors.toMap(WbsTree::getId, Function.identity()));
+
+            if (treePublicNodeAll.size() > 0) {
+                //TODO ---------公有引用同步---------
+                Map<String, Long> map = new HashMap<>();
+                for (WbsTreePrivate wbsTreePrivate : selectNodeAndChildNodes) {
+                    WbsTree wbsTree = treePublicNodeAll.get(wbsTreePrivate.getId());
+                    if (wbsTree != null) {
+                        map.put(wbsTreePrivate.getPKeyId() + "," + wbsTree.getId(), wbsTree.getId());
+                    }
+                }
 
-            //获取项目节点树、包括试验、资料填报
-            List<WbsTreePrivate> wbsTreePrivateAllNow = baseMapper.selectList(Wrappers.<WbsTreePrivate>query().lambda()
-                    .select(WbsTreePrivate::getPKeyId, WbsTreePrivate::getId, WbsTreePrivate::getWbsId)
-                    .eq(WbsTreePrivate::getProjectId, projectId)
-                    .eq(WbsTreePrivate::getStatus, 1)
-                    .eq(WbsTreePrivate::getType, 1)
-                    .in(WbsTreePrivate::getWbsType, Arrays.asList(1, 2)));
-
-            Map<String, List<String>> collect = wbsTreePrivateAllNow.stream().map(WbsTreePrivate::getWbsId).collect(Collectors.groupingBy(Object::toString));
-            for (Map.Entry<String, List<String>> wbsIds : collect.entrySet()) {
-                String wbsId = wbsIds.getKey();
-                if (StringUtils.isNotEmpty(wbsId)) {
-                    List<WbsParamVO> paramListData = new ArrayList<>();
-                    //获取公有树
-                    Map<Long, WbsTree> treePublicNodeAll = wbsTreeMapper.selectList(Wrappers.<WbsTree>query().lambda()
-                            .select(WbsTree::getId)
-                            .eq(WbsTree::getWbsId, wbsId)
-                            .eq(WbsTree::getStatus, 1)
-                            .eq(WbsTree::getType, 1))
-                            .stream().collect(Collectors.toMap(WbsTree::getId, Function.identity()));
-
-                    if (treePublicNodeAll.size() > 0) {
-                        //TODO ---------公有引用同步---------
-                        Map<String, Long> map = new HashMap<>();
-                        for (WbsTreePrivate wbsTreePrivate : wbsTreePrivateAllNow) {
-                            WbsTree wbsTree = treePublicNodeAll.get(wbsTreePrivate.getId());
-                            if (wbsTree != null) {
-                                map.put(wbsTreePrivate.getPKeyId() + "," + wbsTree.getId(), wbsTree.getId());
+                //分组查询公有节点的对应节点参数信息
+                Set<String> keyIds = map.keySet();
+                List<Long> wbsTreeIds = new ArrayList<>(map.values());
+                List<List<Long>> partition = Lists.partition(wbsTreeIds, 1000);
+                for (List<Long> ids : partition) {
+                    String sql = "select id,name,k,v,node_id,remark from m_wbs_param where node_id in (" + org.apache.commons.lang.StringUtils.join(ids, ",") + ")";
+                    List<WbsParam> wbsParams = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(WbsParam.class));
+                    wbsParamOldList.addAll(wbsParams);
+                }
+
+                //构造当前项目的节点参数信息
+                for (String ids : keyIds) {
+                    String nodePKeyIdNow = ids.split(",")[0];
+                    String nodeIdOld = ids.split(",")[1];
+                    List<WbsParam> wbsParams = wbsParamOldList.stream().filter(f -> ObjectUtils.isNotEmpty(f.getNodeId()) && f.getNodeId().toString().equals(nodeIdOld)).collect(Collectors.toList());
+                    //获取引用的节点参数
+                    if (wbsParams.size() > 0) {
+                        for (WbsParam wbsParam : wbsParams) {
+                            WbsParamVO param = BeanUtil.copyProperties(wbsParam, WbsParamVO.class);
+                            if (param != null) {
+                                param.setProjectId(Long.parseLong(projectId));
+                                param.setId(SnowFlakeUtil.getId());
+                                param.setNodeId(Long.parseLong(nodePKeyIdNow));
+                                param.setOldId(wbsParam.getId());
+                                param.setType(1);
+                                param.setStatus(1);
+                                param.setIsDeleted(0);
+                                paramListData.add(param);
                             }
                         }
+                    }
+                }
 
-                        Set<String> keyIds = map.keySet();
-                        List<Long> wbsTreeIds = new ArrayList<>(map.values());
-                        List<WbsParam> wbsParamList = new ArrayList<>();
-                        //分组查询
-                        List<List<Long>> partition = Lists.partition(wbsTreeIds, 1000);
-                        for (List<Long> ids : partition) {
-                            String sql = "select id,name,k,v,node_id,remark from m_wbs_param where node_id in (" + org.apache.commons.lang.StringUtils.join(ids, ",") + ")";
-                            List<WbsParam> wbsParams = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(WbsParam.class));
-                            wbsParamList.addAll(wbsParams);
-                        }
+            } else {
+                //TODO ---------私有引用同步---------
+                Map<String, Long> map = new HashMap<>();
+                //获取当前私有引用模板的根节点信息
+                WbsTreePrivate treePrivateRootNode = baseMapper.selectOne(Wrappers.<WbsTreePrivate>query().lambda()
+                        .select(WbsTreePrivate::getWbsId, WbsTreePrivate::getProjectId)
+                        .eq(WbsTreePrivate::getPKeyId, selectNodeNow.getWbsId()).eq(WbsTreePrivate::getParentId, 0L).eq(WbsTreePrivate::getStatus, 1).eq(WbsTreePrivate::getType, 1));
+
+                //获取当前私有引用模板的对应节点与它的所有子节点
+                WbsTreePrivate selectRecordNode = baseMapper.selectOne(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getWbsId, treePrivateRootNode.getWbsId()).eq(WbsTreePrivate::getId, selectNodeNow.getId()).eq(WbsTreePrivate::getProjectId, treePrivateRootNode.getProjectId()).eq(WbsTreePrivate::getStatus, 1));
+                List<WbsTreePrivate> selectNodeAndChildNodesRecord = this.getChildNodes(selectRecordNode);
+                selectNodeAndChildNodesRecord.add(selectRecordNode);
+                Map<Long, WbsTreePrivate> treePrivateNodeAll = selectNodeAndChildNodesRecord.stream().collect(Collectors.toMap(WbsTreePrivate::getId, Function.identity()));
+
+                for (WbsTreePrivate wbsTreePrivate : selectNodeAndChildNodes) {
+                    WbsTreePrivate wbsTreePrivateYS = treePrivateNodeAll.get(wbsTreePrivate.getId());
+                    if (wbsTreePrivateYS != null) {
+                        map.put(wbsTreePrivate.getPKeyId() + "," + wbsTreePrivateYS.getPKeyId(), wbsTreePrivateYS.getPKeyId());
+                    }
+                }
 
-                        for (String ids : keyIds) {
-                            String nodePKeyIdNow = ids.split(",")[0];
-                            String nodeIdOld = ids.split(",")[1];
-                            List<WbsParam> wbsParams = wbsParamList.stream().filter(f -> ObjectUtils.isNotEmpty(f.getNodeId()) && f.getNodeId().toString().equals(nodeIdOld)).collect(Collectors.toList());
-                            //获取引用的节点参数
-                            if (wbsParams.size() > 0) {
-                                for (WbsParam wbsParam : wbsParams) {
-                                    WbsParamVO param = BeanUtil.copyProperties(wbsParam, WbsParamVO.class);
-                                    if (param != null) {
-                                        param.setProjectId(Long.parseLong(projectId));
-                                        param.setId(SnowFlakeUtil.getId());
-                                        param.setNodeId(Long.parseLong(nodePKeyIdNow));
-                                        param.setOldId(wbsParam.getId());
-                                        param.setType(1);
-                                        param.setStatus(1);
-                                        param.setIsDeleted(0);
-                                        paramListData.add(param);
-                                    }
-                                }
-                            }
-                        }
+                //分组查询公有节点的对应节点参数信息
+                Set<String> keyIds = map.keySet();
+                List<Long> wbsTreeIds = new ArrayList<>(map.values());
+                List<List<Long>> partition = Lists.partition(wbsTreeIds, 1000);
+                for (List<Long> ids : partition) {
+                    String sql = "select id,name,k,v,node_id,remark from m_wbs_param where node_id in (" + org.apache.commons.lang.StringUtils.join(ids, ",") + ")";
+                    List<WbsParam> wbsParams = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(WbsParam.class));
+                    wbsParamOldList.addAll(wbsParams);
+                }
 
 
-                    } else {
-                        //TODO ---------私有引用同步---------
-                        Map<String, Long> map = new HashMap<>();
-                        WbsTreePrivate treePrivateRootNode = baseMapper.selectOne(Wrappers.<WbsTreePrivate>query().lambda()
-                                .select(WbsTreePrivate::getWbsId, WbsTreePrivate::getProjectId)
-                                .eq(WbsTreePrivate::getPKeyId, wbsId).eq(WbsTreePrivate::getParentId, 0L).eq(WbsTreePrivate::getStatus, 1).eq(WbsTreePrivate::getType, 1));
-
-                        Map<Long, WbsTreePrivate> treePrivateNodeAll = baseMapper.selectList(Wrappers.<WbsTreePrivate>query().lambda()
-                                .select(WbsTreePrivate::getPKeyId, WbsTreePrivate::getId)
-                                .eq(WbsTreePrivate::getWbsId, treePrivateRootNode.getWbsId()).eq(WbsTreePrivate::getProjectId, treePrivateRootNode.getProjectId())
-                                .eq(WbsTreePrivate::getStatus, 1).eq(WbsTreePrivate::getType, 1)).stream().collect(Collectors.toMap(WbsTreePrivate::getId, Function.identity()));
-
-                        for (WbsTreePrivate wbsTreePrivate : wbsTreePrivateAllNow) {
-                            WbsTreePrivate wbsTreePrivateYS = treePrivateNodeAll.get(wbsTreePrivate.getId());
-                            if (wbsTreePrivateYS != null) {
-                                map.put(wbsTreePrivate.getPKeyId() + "," + wbsTreePrivateYS.getPKeyId(), wbsTreePrivateYS.getPKeyId());
+                //构造当前项目的节点参数信息
+                for (String ids : keyIds) {
+                    String nodePKeyIdNow = ids.split(",")[0];
+                    String nodePKeyIdYs = ids.split(",")[1];
+                    List<WbsParam> wbsParams = wbsParamOldList.stream().filter(f -> ObjectUtils.isNotEmpty(f.getNodeId()) && f.getNodeId().toString().equals(nodePKeyIdYs)).collect(Collectors.toList());
+                    //获取引用的节点参数
+                    if (wbsParams.size() > 0) {
+                        for (WbsParam wbsParam : wbsParams) {
+                            WbsParamVO param = BeanUtil.copyProperties(wbsParam, WbsParamVO.class);
+                            if (param != null) {
+                                param.setProjectId(Long.parseLong(projectId));
+                                param.setId(SnowFlakeUtil.getId());
+                                param.setNodeId(Long.parseLong(nodePKeyIdNow));
+                                param.setOldId(wbsParam.getId());
+                                param.setType(1);
+                                param.setStatus(1);
+                                param.setIsDeleted(0);
+                                paramListData.add(param);
                             }
                         }
+                    }
+                }
+            }
 
-                        Set<String> keyIds = map.keySet();
-                        List<Long> wbsTreeIds = new ArrayList<>(map.values());
-                        List<WbsParam> wbsParamList = new ArrayList<>();
-                        //分组查询
-                        List<List<Long>> partition = Lists.partition(wbsTreeIds, 1000);
-                        for (List<Long> ids : partition) {
-                            String sql = "select id,name,k,v,node_id,remark from m_wbs_param where node_id in (" + org.apache.commons.lang.StringUtils.join(ids, ",") + ")";
-                            List<WbsParam> wbsParams = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(WbsParam.class));
-                            wbsParamList.addAll(wbsParams);
-                        }
+            //当前引用模板的节点参数,数据源Map
+            Map<Long, WbsParam> paramOldDataMap = wbsParamOldList.stream().collect(Collectors.toMap(WbsParam::getId, Function.identity()));
+            //获取当前项目的选择的该节点的节点、以及子节点下的参数信息
+            List<WbsParam> paramListNow = wbsParamMapper.selectList(Wrappers.<WbsParam>lambdaQuery().select(WbsParam::getK, WbsParam::getV, WbsParam::getName, WbsParam::getId, WbsParam::getRemark, WbsParam::getNodeId).eq(WbsParam::getProjectId, Long.parseLong(projectId)).in(WbsParam::getNodeId, privateNodePKeyIds));
+            //将参数名称、K和nodeId作为唯一标识存储到一个Map中
+            Map<String, WbsParam> paramMap = new HashMap<>();
+            for (WbsParam nowObj : paramListNow) {
+                String key = nowObj.getName() + "_" + nowObj.getK() + "_" + nowObj.getNodeId();
+                paramMap.put(key, nowObj);
+            }
 
-                        for (String ids : keyIds) {
-                            String nodePKeyIdNow = ids.split(",")[0];
-                            String nodePKeyIdYs = ids.split(",")[1];
-                            List<WbsParam> wbsParams = wbsParamList.stream().filter(f -> ObjectUtils.isNotEmpty(f.getNodeId()) && f.getNodeId().toString().equals(nodePKeyIdYs)).collect(Collectors.toList());
-                            //获取引用的节点参数
-                            if (wbsParams.size() > 0) {
-                                for (WbsParam wbsParam : wbsParams) {
-                                    WbsParamVO param = BeanUtil.copyProperties(wbsParam, WbsParamVO.class);
-                                    if (param != null) {
-                                        param.setProjectId(Long.parseLong(projectId));
-                                        param.setId(SnowFlakeUtil.getId());
-                                        param.setNodeId(Long.parseLong(nodePKeyIdNow));
-                                        param.setOldId(wbsParam.getId());
-                                        param.setType(1);
-                                        param.setStatus(1);
-                                        param.setIsDeleted(0);
-                                        paramListData.add(param);
-                                    }
-                                }
-                            }
+            //数据构造
+            for (WbsParamVO next : paramListData) {
+                //获取引用模板节点上的源数据节点参数信息
+                WbsParam oldObj = paramOldDataMap.get(next.getOldId());
+                if (oldObj != null) {
+                    //获取当前项目选择的节点、子节点上的现有参数信息,通过name、K、nodeId判断
+                    WbsParam nowObj = paramMap.getOrDefault(next.getName() + "_" + next.getK() + "_" + next.getNodeId(), null);
+                    if (nowObj == null) {
+                        //新增
+                        WbsParam wbsParam = BeanUtil.copyProperties(next, WbsParam.class);
+                        if (wbsParam != null) {
+                            wbsParam.setId(SnowFlakeUtil.getId());
+                            insertList.add(wbsParam);
+                        }
+                    } else if (!Objects.equals(oldObj.getV(), nowObj.getV()) || !Objects.equals(oldObj.getRemark(), nowObj.getRemark())) {
+                        //修改
+                        WbsParam wbsParam1 = BeanUtil.copyProperties(nowObj, WbsParam.class);
+                        if (wbsParam1 != null) {
+                            wbsParam1.setProjectId(Long.parseLong(projectId));
+                            wbsParam1.setV(oldObj.getV());
+                            wbsParam1.setRemark(oldObj.getRemark());
+                            wbsParam1.setType(1);
+                            wbsParam1.setStatus(1);
+                            wbsParam1.setIsDeleted(0);
+                            updateList.add(wbsParam1);
                         }
                     }
+                }
+            }
+
+            //修改
+            if (!updateList.isEmpty()) {
+                List<List<WbsParam>> partition = Lists.partition(updateList, 1000);
+                for (List<WbsParam> updateData : partition) {
+                    this.wbsParamServiceImpl.updateBatchById(updateData, 1000);
+                }
+            }
+
+            //新增
+            if (!insertList.isEmpty()) {
+                List<List<WbsParam>> partition = Lists.partition(insertList, 1000);
+                for (List<WbsParam> addData : partition) {
+                    wbsParamServiceImpl.insertBatch(addData, 1000);
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * 电签同步-获取所有子级节点、表
+     */
+    private List<WbsTreePrivate> getChildNodesAndTabs(WbsTreePrivate obj) {
+        if (obj != null) {
+            List<WbsTreePrivate> wbsTreePrivates = Collections.singletonList(obj);
+            List<WbsTreePrivate> result = new ArrayList<>();
+            this.recursionGetChildNodesAndTabs(wbsTreePrivates, result, obj);
+            if (result.size() > 0) {
+                return result;
+            }
+        }
+        return null;
+    }
 
-                    List<WbsParam> paramListOldAll = new ArrayList<>();
+    private void recursionGetChildNodesAndTabs(List<WbsTreePrivate> list, List<WbsTreePrivate> result, WbsTreePrivate obj) {
+        List<Long> ids = list.stream().map(WbsTreePrivate::getId).collect(Collectors.toList());
+        if (ids.size() > 0) {
+            List<WbsTreePrivate> query = jdbcTemplate.query("select p_key_id,id,type,parent_id,html_url from m_wbs_tree_private where parent_id in(" + org.apache.commons.lang.StringUtils.join(ids, ",") + ") and status = 1 and is_deleted = 0 and project_id = " + obj.getProjectId(), new BeanPropertyRowMapper<>(WbsTreePrivate.class));
+            if (query.size() > 0) {
+                result.addAll(query);
+                recursionGetChildNodesAndTabs(query, result, obj);
+            }
+        }
+    }
 
-                    List<Long> oldIds = paramListData.stream().map(WbsParamVO::getOldId).distinct().collect(Collectors.toList());
-                    //分组查询
-                    List<List<Long>> partition = Lists.partition(oldIds, 1000);
-                    for (List<Long> ids : partition) {
-                        String sql1 = "select id,name,k,v,node_id,remark from m_wbs_param where id in( " + org.apache.commons.lang.StringUtils.join(ids, ",") + ")";
-                        List<WbsParam> query = jdbcTemplate.query(sql1, new BeanPropertyRowMapper<>(WbsParam.class));
-                        paramListOldAll.addAll(query);
+    @Override
+    public boolean syncProjectEVisa(String projectId, String pKeyId) {
+        if (StringUtils.isNotEmpty(projectId) && StringUtils.isNotEmpty(pKeyId)) {
+            ProjectInfo projectInfo = projectInfoMapper.selectById(projectId);
+            if (projectInfo != null && ("private").equals(projectInfo.getReferenceWbsTemplateType()) && ObjectUtils.isNotEmpty(projectInfo.getReferenceWbsTemplateId())) {
+                //构造参数集合
+                List<TextdictInfo> insertData = new ArrayList<>();
+                Map<Long, List<TextdictInfo>> textDictInfoData = new HashMap<>();
+
+                //获取当前选择的节点下的所有节点、表、独立表
+                WbsTreePrivate selectNodeNow = baseMapper.selectOne(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getPKeyId, pKeyId).eq(WbsTreePrivate::getStatus, 1));
+                if (selectNodeNow == null) {
+                    throw new ServiceException("未获取到当前选择同步的节点信息,请联系管理员");
+                }
+                List<WbsTreePrivate> wbsTreePrivatesNodeAndTabNow = this.getChildNodesAndTabs(selectNodeNow);
+
+                //当前项目独立表
+                Map<Long, WbsTreePrivate> wbsTreePrivatesTableDL = wbsTreePrivatesNodeAndTabNow.stream().filter(f -> f.getType().equals(10) && f.getParentId().equals(-10L)).collect(Collectors.toMap(WbsTreePrivate::getId, Function.identity()));
+                //当前项目选择的同步的节点信息
+                Map<Long, WbsTreePrivate> nowNodeTreeAll = wbsTreePrivatesNodeAndTabNow.stream().filter(f -> f.getType().equals(1)).collect(Collectors.toList()).stream().collect(Collectors.toMap(WbsTreePrivate::getId, WbsTreePrivate -> WbsTreePrivate, (obj1, obj2) -> obj1));
+
+                //获取当前引用的项目节点树的根节点信息
+                WbsTreePrivate oneRecordRoot = this.getOne(Wrappers.<WbsTreePrivate>lambdaQuery().select(WbsTreePrivate::getProjectId, WbsTreePrivate::getWbsId).eq(WbsTreePrivate::getPKeyId, projectInfo.getReferenceWbsTemplateId()));
+                //选择节点对应所引用的关联对应的节点、表、独立表
+                WbsTreePrivate selectOneRecord = baseMapper.selectOne(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getProjectId, oneRecordRoot.getProjectId()).eq(WbsTreePrivate::getId, selectNodeNow.getId()).eq(WbsTreePrivate::getWbsId, oneRecordRoot.getWbsId()));
+                List<WbsTreePrivate> wbsTreePrivatesNodeAndTabRecord = this.getChildNodesAndTabs(selectOneRecord);
+
+                //引用的节点树对应的节点、表、独立表
+
+                //获取当前对应电签位置配置信息
+                List<WbsTreePrivate> collect1 = wbsTreePrivatesNodeAndTabRecord.stream().filter(f -> f.getType().equals(10) || f.getType().equals(2)).collect(Collectors.toList());
+                List<Long> pKeyIds = collect1.stream().map(WbsTreePrivate::getPKeyId).collect(Collectors.toList());
+
+                //分组查询
+                List<TextdictInfo> textDictInfosAll = new ArrayList<>();
+                List<List<Long>> partition = Lists.partition(pKeyIds, 1000);
+                for (List<Long> ids : partition) {
+                    String sql = "select id,name,type,tab_id,col_key,sig_role_id,is_deleted,sig_role_name,col_name,pyzbx,pyzby from m_textdict_info where tab_id in(" + org.apache.commons.lang.StringUtils.join(ids, ",") + ")";
+                    List<TextdictInfo> textDictInfos = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(TextdictInfo.class));
+                    textDictInfosAll.addAll(textDictInfos);
+                }
+
+                //构造原始电签信息
+                Map<String, List<TextdictInfo>> collect3 = textDictInfosAll.stream().collect(Collectors.groupingBy(TextdictInfo::getTabId));
+                for (WbsTreePrivate wbsTreePrivate : collect1) {
+                    if (wbsTreePrivate.getType() == 2) {
+                        WbsTreePrivate obj = nowNodeTreeAll.get(wbsTreePrivate.getParentId());
+                        if (obj != null) {
+                            List<TextdictInfo> textDictInfos = collect3.get(String.valueOf(wbsTreePrivate.getPKeyId()));
+                            if (textDictInfos != null && textDictInfos.size() > 0) {
+                                textDictInfoData.put(wbsTreePrivate.getId(), textDictInfos);
+                            }
+                        }
                     }
 
-                    //转换为map
-                    Map<Long, WbsParam> mapOld = paramListOldAll.stream().collect(Collectors.toMap(WbsParam::getId, Function.identity()));
-
-                    //获取当前项目的节点参数
-                    List<WbsParam> paramListNow = wbsParamMapper.selectList(Wrappers.<WbsParam>lambdaQuery()
-                            .select(WbsParam::getK, WbsParam::getV, WbsParam::getName, WbsParam::getId, WbsParam::getRemark, WbsParam::getNodeId)
-                            .eq(WbsParam::getProjectId, Long.parseLong(projectId)));
-
-                    //判断是否存在
-                    Iterator<WbsParamVO> iterator = paramListData.iterator();
-                    while (iterator.hasNext()) {
-                        WbsParamVO next = iterator.next();
-
-                        //获取引用的节点上的源参数信息
-                        WbsParam oldObj = mapOld.get(next.getOldId());
-                        //获取被引用的节点上的现参数信息
-                        WbsParam newObj = paramListNow.stream().filter(f -> f.getK().equals(next.getK())
-                                && f.getV().equals(next.getV())
-                                && f.getName().equals(next.getName())
-                                && f.getRemark().equals(next.getRemark())
-                                && f.getNodeId().equals(next.getNodeId())
-                        ).findAny().orElse(null);
-
-                        if (oldObj != null && newObj != null) {
-                            //如果源节点参数与现节点参数名称、K、V、备注一致,那么就跳过
-                            if (oldObj.getName().equals(newObj.getName()) && oldObj.getK().equals(newObj.getK()) && oldObj.getV().equals(newObj.getV()) && oldObj.getRemark().equals(newObj.getRemark())) {
-                                iterator.remove();
-
-                                //如果源节点参数与现节点参数名称、K一致,V、备注不一致,那么就修改当前名称下的节点参数
-                            } else if (oldObj.getName().equals(newObj.getName()) && oldObj.getK().equals(newObj.getK()) && (!oldObj.getV().equals(newObj.getV()) || !oldObj.getRemark().equals(newObj.getRemark()))) {
-                                newObj.setProjectId(Long.parseLong(projectId));
-                                newObj.setName(oldObj.getName());
-                                newObj.setK(oldObj.getK());
-                                newObj.setV(oldObj.getV());
-                                newObj.setRemark(oldObj.getRemark());
-                                newObj.setType(1);
-                                newObj.setStatus(1);
-                                newObj.setIsDeleted(0);
-                                updateList.add(newObj);
-
-                                //如果源节点参数与现节点参数名称不一致,那么新增
-                            } else if (!oldObj.getName().equals(newObj.getName())) {
-                                insertList.add(next);
+                    if (wbsTreePrivate.getType() == 10 && wbsTreePrivate.getParentId() == -10) { //type=10,parentId=-10 独立库
+                        //判断是否存在独立表单,存在则不新增
+                        WbsTreePrivate wbsTreePrivate1 = wbsTreePrivatesTableDL.get(wbsTreePrivate.getId());
+                        if (ObjectUtils.isEmpty(wbsTreePrivate1)) {
+                            //根据元素表pKeyId,获取电签位置匹配信息、编辑默认信息
+                            List<TextdictInfo> textDictInfos = collect3.get(String.valueOf(wbsTreePrivate.getPKeyId()));
+                            if (textDictInfos != null && textDictInfos.size() > 0) {
+                                textDictInfoData.put(wbsTreePrivate.getId(), textDictInfos);
                             }
+                        }
+                    }
+                }
 
-                        } else if (oldObj != null) {
-                            //二次过滤,节点名称、节点id相同,修改
-                            List<WbsParam> query = paramListNow.stream().filter(f -> f.getName().equals(next.getName())
-                                    && f.getNodeId().equals(next.getNodeId())
-                            ).collect(Collectors.toList());
-
-                            if (query.size() > 0) {
-                                for (WbsParam wbsParam : query) {
-                                    if (oldObj.getName().equals(wbsParam.getName())) {
-                                        //修改
-                                        wbsParam.setProjectId(Long.parseLong(projectId));
-                                        wbsParam.setName(next.getName());
-                                        wbsParam.setK(next.getK());
-                                        wbsParam.setV(next.getV());
-                                        wbsParam.setRemark(next.getRemark());
-                                        wbsParam.setType(1);
-                                        wbsParam.setStatus(1);
-                                        wbsParam.setIsDeleted(0);
-                                        updateList.add(wbsParam);
-                                    }
-                                }
-                            } else {
-                                //新增
-                                insertList.add(next);
+                //只同步独立库中有关联过清表的元素表type=10,以及原始方式的元素表type=2
+                List<WbsTreePrivate> collect = wbsTreePrivatesNodeAndTabNow.stream().filter(f -> f.getType().equals(2) || (f.getHtmlUrl() != null && f.getType().equals(10))).collect(Collectors.toList());
+                collect.forEach(tree -> {
+                    List<TextdictInfo> textDictInfos = textDictInfoData.get(tree.getId());
+                    if (textDictInfos != null) {
+                        for (TextdictInfo textdictInfo : textDictInfos) {
+                            TextdictInfo obj = BeanUtil.copyProperties(textdictInfo, TextdictInfo.class);
+                            if (obj != null) {
+                                obj.setId(SnowFlakeUtil.getId());
+                                obj.setTabId(tree.getPKeyId().toString()); //重新赋值绑定到对应的表上
+                                insertData.add(obj);
                             }
                         }
+                    }
+                });
 
+                //去重,删除当前表的电签信息
+                List<String> collect2 = insertData.stream().map(TextdictInfo::getTabId).collect(Collectors.toList());
+                if (!collect2.isEmpty()) {
+                    List<List<String>> partitionDel = Lists.partition(collect2, 1000);
+                    for (List<String> ids : partitionDel) {
+                        String delSql = "delete from m_textdict_info where tab_id in (" + org.apache.commons.lang.StringUtils.join(ids, ",") + ")";
+                        jdbcTemplate.execute(delSql);
                     }
                 }
-            }
 
-            if (updateList.size() > 0) {
-                this.wbsParamServiceImpl.updateBatchById(updateList, 1000);
-            }
-            if (insertList.size() > 0) {
-                List<List<WbsParam>> partition1 = Lists.partition(insertList, 1000);
-                for (List<WbsParam> addList : partition1) {
-                    wbsParamServiceImpl.insertBatch(addList, 1000);
+                //新增
+                if (!insertData.isEmpty()) {
+                    List<List<TextdictInfo>> partition1 = Lists.partition(insertData, 1000);
+                    for (List<TextdictInfo> addList : partition1) {
+                        textDictInfoService.insertBatch(addList, 1000);
+                    }
                 }
-                return true;
             }
+            return true;
+        } else {
+            throw new ServiceException("当前项目关联的wbs树不是私有关联,无法同步电签信息");
         }
-        return false;
     }
 
     @Override
@@ -823,10 +1025,8 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
             //获取当前节点对应节点信息
             WbsTreePrivate wbsTreePrivate = baseMapper.selectOne(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getPKeyId, primaryKeyId));
             //获取项目信息
-            ProjectInfo projectInfo = projectInfoMapper.selectOne(Wrappers.<ProjectInfo>lambdaQuery()
-                    .select(ProjectInfo::getReferenceWbsTemplateType, ProjectInfo::getReferenceWbsTemplateTypeTrial)
-                    .eq(ProjectInfo::getId, wbsTreePrivate.getProjectId()));
-
+            ProjectInfo projectInfo = projectInfoMapper.selectOne(Wrappers.<ProjectInfo>lambdaQuery().select(ProjectInfo::getReferenceWbsTemplateType, ProjectInfo::getReferenceWbsTemplateTypeTrial).eq(ProjectInfo::getId, wbsTreePrivate.getProjectId()));
+            //结果集
             List<WbsTreePrivate> insertDataPrivateList = new ArrayList<>();
 
             if (("1").equals(wbsTreePrivate.getWbsType())) {
@@ -842,15 +1042,15 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
                         );
                     } else {
                         wbsTreesPublicTables = wbsTreeMapper.selectList(Wrappers.<WbsTree>query().lambda().eq(WbsTree::getWbsId, wbsTree.getWbsId()).eq(WbsTree::getType, 2)
-                               /*.eq(WbsTree::getStatus,1)*/
+                                /*.eq(WbsTree::getStatus,1)*/
                                 .like(WbsTree::getAncestors, wbsTree.getId())
                         );
                     }
 
                     //获取当前项目树下的元素表 节点
                     List<WbsTreePrivate> wbsTreePrivatesProjectAll = baseMapper.selectList(Wrappers.<WbsTreePrivate>query().lambda()
-                            .eq(WbsTreePrivate::getProjectId, wbsTreePrivate.getProjectId())
-                            .eq(WbsTreePrivate::getWbsId, wbsTreePrivate.getWbsId())
+                                    .eq(WbsTreePrivate::getProjectId, wbsTreePrivate.getProjectId())
+                                    .eq(WbsTreePrivate::getWbsId, wbsTreePrivate.getWbsId())
                             /*.eq(WbsTreePrivate::getStatus, 1)*/
                     );
                     List<WbsTreePrivate> wbsTreePrivatesProjectNodes = wbsTreePrivatesProjectAll.stream().filter(f -> f.getType().equals(1)).collect(Collectors.toList());
@@ -1006,7 +1206,7 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
                     if (wbsTreePrivate.getAncestors().equals("0")) {
                         //根节点
                         wbsTreePrivateRootTables = baseMapper.selectList(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getProjectId, wbsTreePrivateRoot.getProjectId())
-                                .eq(WbsTreePrivate::getWbsId, wbsTreePrivateRoot.getWbsId()).eq(WbsTreePrivate::getType, 2)
+                                        .eq(WbsTreePrivate::getWbsId, wbsTreePrivateRoot.getWbsId()).eq(WbsTreePrivate::getType, 2)
                                 /*.eq(WbsTreePrivate::getStatus, 1)*/
                         );
                     } else {
@@ -1053,115 +1253,17 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
                     }
                 }
             }
-            //新增
-            if (insertDataPrivateList.size() > 0) {
-                this.insertBatch(insertDataPrivateList, 1000);
-            }
-            return true;
-        }
-        return false;
-    }
-
-    @Override
-    public boolean syncProjectEVisa(String projectId) {
-        if (StringUtils.isNotEmpty(projectId)) {
-            ProjectInfo projectInfo = projectInfoMapper.selectById(projectId);
-            if (projectInfo != null && ("private").equals(projectInfo.getReferenceWbsTemplateType()) && ObjectUtils.isNotEmpty(projectInfo.getReferenceWbsTemplateId())) {
-                //构造参数集合
-                List<TextdictInfo> insertData = new ArrayList<>();
-                Map<Long, List<TextdictInfo>> textDictInfoData = new HashMap<>();
 
-                //获取当前引用的项目节点树的根节点信息
-                WbsTreePrivate oneRecordRoot = this.getOne(Wrappers.<WbsTreePrivate>lambdaQuery().select(WbsTreePrivate::getProjectId, WbsTreePrivate::getWbsId).eq(WbsTreePrivate::getPKeyId, projectInfo.getReferenceWbsTemplateId()));
-
-                //获取当前项目下节点树所有节点、表、独立表
-                String sqlNodeTreeAllNow = "SELECT p_key_id,id,type,parent_id,html_url FROM m_wbs_tree_private WHERE project_id = " + projectId + " AND STATUS = 1 AND is_deleted = 0 AND (((type = 1 OR type = 2) AND wbs_type = 1) OR (type= 10 AND parent_id = -10 ))";
-                List<WbsTreePrivate> wbsTreePrivatesNodeAndTabNow = jdbcTemplate.query(sqlNodeTreeAllNow, new BeanPropertyRowMapper<>(WbsTreePrivate.class));
-                Map<Long, WbsTreePrivate> wbsTreePrivatesTableDL = wbsTreePrivatesNodeAndTabNow.stream().filter(f -> f.getType().equals(10) && f.getParentId().equals(-10L)).collect(Collectors.toMap(WbsTreePrivate::getId, Function.identity()));
-
-                //获取当前项目节点树
-                Map<Long, WbsTreePrivate> nowNodeTreeAll = wbsTreePrivatesNodeAndTabNow.stream().filter(f -> f.getType().equals(1)).collect(Collectors.toList()).stream()
-                        .collect(Collectors.toMap(WbsTreePrivate::getId, WbsTreePrivate -> WbsTreePrivate, (obj1, obj2) -> obj1));
-
-                //获取当前引用的节点树下所有节点、表、独立表
-                String sqlNodeTreeAllOld = "SELECT p_key_id,id,type,parent_id FROM m_wbs_tree_private WHERE project_id = " + oneRecordRoot.getProjectId() + " AND STATUS = 1 AND is_deleted = 0 AND (((type = 1 OR type = 2) AND wbs_id = " + oneRecordRoot.getWbsId() + ") OR ((type= 10 OR parent_id = -10 ) AND wbs_id IS NULL))";
-                List<WbsTreePrivate> wbsTreePrivatesNodeAndTab = jdbcTemplate.query(sqlNodeTreeAllOld, new BeanPropertyRowMapper<>(WbsTreePrivate.class));
-
-                //获取当前对应电签位置配置信息
-                List<WbsTreePrivate> collect1 = wbsTreePrivatesNodeAndTab.stream().filter(f -> f.getType().equals(10) || f.getType().equals(2)).collect(Collectors.toList());
-                List<Long> pKeyIds = collect1.stream().map(WbsTreePrivate::getPKeyId).collect(Collectors.toList());
-
-                //分组查询
-                List<TextdictInfo> textDictInfosAll = new ArrayList<>();
-                List<List<Long>> partition = Lists.partition(pKeyIds, 1000);
-                for (List<Long> ids : partition) {
-                    String sql = "select id,name,type,tab_id,col_key,sig_role_id,is_deleted,sig_role_name,col_name,pyzbx,pyzby from m_textdict_info where tab_id in(" + org.apache.commons.lang.StringUtils.join(ids, ",") + ")";
-                    List<TextdictInfo> textDictInfos = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(TextdictInfo.class));
-                    textDictInfosAll.addAll(textDictInfos);
-                }
-
-                //转换map
-                Map<String, List<TextdictInfo>> collect3 = textDictInfosAll.stream().collect(Collectors.groupingBy(TextdictInfo::getTabId));
-
-                //构造原始电签信息
-                for (WbsTreePrivate wbsTreePrivate : collect1) {
-                    if (wbsTreePrivate.getType() == 2) {
-                        WbsTreePrivate obj = nowNodeTreeAll.get(wbsTreePrivate.getParentId());
-                        if (obj != null) {
-                            List<TextdictInfo> textDictInfos = collect3.get(String.valueOf(wbsTreePrivate.getPKeyId()));
-                            if (textDictInfos != null && textDictInfos.size() > 0) {
-                                textDictInfoData.put(wbsTreePrivate.getId(), textDictInfos);
-                            }
-                        }
-                    }
-
-                    if (wbsTreePrivate.getType() == 10 && wbsTreePrivate.getParentId() == -10) { //type=10,parentId=-10 独立库
-                        //判断是否存在独立表单,存在则不新增
-                        WbsTreePrivate wbsTreePrivate1 = wbsTreePrivatesTableDL.get(wbsTreePrivate.getId());
-                        if (ObjectUtils.isEmpty(wbsTreePrivate1)) {
-                            //根据元素表pKeyId,获取电签位置匹配信息、编辑默认信息
-                            List<TextdictInfo> textDictInfos = collect3.get(String.valueOf(wbsTreePrivate.getPKeyId()));
-                            if (textDictInfos != null && textDictInfos.size() > 0) {
-                                textDictInfoData.put(wbsTreePrivate.getId(), textDictInfos);
-                            }
-                        }
-                    }
-                }
-
-                //只同步独立库中有关联过清表的元素表type=10,以及原始方式的元素表type=2
-                List<WbsTreePrivate> collect = wbsTreePrivatesNodeAndTabNow.stream().filter(f -> f.getType().equals(2) || (f.getHtmlUrl() != null && f.getType().equals(10))).collect(Collectors.toList());
-
-                collect.forEach(tree -> {
-                    List<TextdictInfo> textDictInfos = textDictInfoData.get(tree.getId());
-                    if (textDictInfos != null) {
-                        for (TextdictInfo textdictInfo : textDictInfos) {
-                            TextdictInfo obj = BeanUtil.copyProperties(textdictInfo, TextdictInfo.class);
-                            if (obj != null) {
-                                obj.setId(SnowFlakeUtil.getId());
-                                obj.setTabId(tree.getPKeyId().toString()); //重新赋值绑定到对应的表上
-                                insertData.add(obj);
-                            }
-                        }
-                    }
-                });
-
-                //去重,删除当前表的电签信息
-                List<String> collect2 = insertData.stream().map(TextdictInfo::getTabId).collect(Collectors.toList());
-                List<List<String>> partitionDel = Lists.partition(collect2, 1000);
-                for (List<String> ids : partitionDel) {
-                    String delSql = "delete from m_textdict_info where tab_id in (" + org.apache.commons.lang.StringUtils.join(ids, ",") + ")";
-                    jdbcTemplate.execute(delSql);
-                }
-
-                List<List<TextdictInfo>> partition1 = Lists.partition(insertData, 1000);
-                for (List<TextdictInfo> addList : partition1) {
-                    textDictInfoService.insertBatch(addList, 1000);
+            //新增
+            if (!insertDataPrivateList.isEmpty()) {
+                List<List<WbsTreePrivate>> partition = Lists.partition(insertDataPrivateList, 1000);
+                for (List<WbsTreePrivate> wbsTreePrivates : partition) {
+                    this.insertBatch(wbsTreePrivates, 1000);
                 }
             }
             return true;
-        } else {
-            throw new ServiceException("当前项目关联的wbs树不是私有关联");
         }
+        return false;
     }
 
     @Override

+ 142 - 75
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeServiceImpl.java

@@ -320,97 +320,165 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
         WbsTreePrivate wbsTreePrivate = wbsTreePrivateService.getBaseMapper().selectOne(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getPKeyId, pKeyId).eq(WbsTreePrivate::getStatus, 1));
 
         //获取当前项目引用
-        String sql = "select reference_wbs_template_id,reference_wbs_template_type,reference_wbs_template_id_trial,reference_wbs_template_type_trial from m_project_info where id = " + wbsTreePrivate.getProjectId();
+        String sql = "select reference_wbs_template_id,reference_wbs_template_type,reference_wbs_template_id_trial,reference_wbs_template_type_trial from m_project_info where is_deleted = 0 and id = " + wbsTreePrivate.getProjectId();
         ProjectInfo projectInfo = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(ProjectInfo.class)).stream().findAny().orElse(null);
         if (projectInfo != null) {
             if (("1").equals(wbsTreePrivate.getWbsType())) {
-                //质检公有
+                //TODO =====质检公有=====
                 if (ObjectUtil.isNotEmpty(projectInfo.getReferenceWbsTemplateId()) && (ObjectUtil.isNotEmpty(projectInfo.getReferenceWbsTemplateType()) && ("public").equals(projectInfo.getReferenceWbsTemplateType()))) {
-                    //获取公有树
-                    List<WbsTree> wbsTreeListAll = wbsTreeMapper.selectList(Wrappers.<WbsTree>lambdaQuery()
-                            .select(WbsTree::getId, WbsTree::getNodeName, WbsTree::getNodeType, WbsTree::getMajorDataType,
-                                    WbsTree::getTableType, WbsTree::getTableOwner, WbsTree::getImportMatchingInfo,
-                                    WbsTree::getMixRatioTestIds, WbsTree::getInitTableId,
-                                    WbsTree::getInitTableName, WbsTree::getSort)
-                            .eq(WbsTree::getWbsId, projectInfo.getReferenceWbsTemplateId()).eq(WbsTree::getType, 1).eq(WbsTree::getStatus, 1));
-                    //获取项目私节点、元素表
-                    List<WbsTreePrivate> wbsTreePrivatesAll = wbsTreePrivateMapper.selectList(Wrappers.<WbsTreePrivate>lambdaQuery()
-                            .select(WbsTreePrivate::getId, WbsTreePrivate::getNodeName, WbsTreePrivate::getNodeType, WbsTreePrivate::getMajorDataType,
-                                    WbsTreePrivate::getTableType, WbsTreePrivate::getTableOwner, WbsTreePrivate::getImportMatchingInfo,
-                                    WbsTreePrivate::getMixRatioTestIds, WbsTreePrivate::getInitTableId,
-                                    WbsTreePrivate::getInitTableName, WbsTreePrivate::getHtmlUrl, WbsTreePrivate::getSort)
-                            .eq(WbsTreePrivate::getWbsId, projectInfo.getReferenceWbsTemplateId()).eq(WbsTreePrivate::getProjectId, wbsTreePrivate.getProjectId()).eq(WbsTreePrivate::getStatus, 1));
-                    //同步修改
-                    this.updateWbsInfoPrivateAsync(wbsTreeListAll, wbsTreePrivatesAll, wbsTreePrivate.getProjectId(), Integer.parseInt(wbsTreePrivate.getWbsType()));
-
-                    //质检私有
+                    //获取引用的公有树节点信息,没有元素表
+                    WbsTree wbsTree = wbsTreeMapper.selectOne(Wrappers.<WbsTree>lambdaQuery().eq(WbsTree::getId, wbsTreePrivate.getId()).eq(WbsTree::getStatus, 1));
+                    List<WbsTree> childNodesAllPublic = this.getChildNodes(wbsTree);
+                    if (childNodesAllPublic == null) {
+                        childNodesAllPublic = new ArrayList<>();
+                    }
+                    childNodesAllPublic.add(wbsTree);
+
+                    //获取当前项目私节点、元素表
+                    List<WbsTreePrivate> childNodesAllNowProject = this.getChildNodesAllNowProject(wbsTreePrivate);
+                    //公有引用,由于没有关联清表,html_url不存在,所以不同步表的html_url信息
+                    List<WbsTreePrivate> childNodesAllNowProjectNodes = childNodesAllNowProject.stream().filter(f -> new Integer(1).equals(f.getType())).collect(Collectors.toList());
+
+                    //修改公有引用信息
+                    this.asyncUpdateWbsPublic(childNodesAllPublic, childNodesAllNowProjectNodes, wbsTreePrivate.getProjectId(), Integer.parseInt(wbsTreePrivate.getWbsType()));
+
                 } else if (ObjectUtil.isNotEmpty(projectInfo.getReferenceWbsTemplateId()) && ObjectUtil.isNotEmpty(projectInfo.getReferenceWbsTemplateType()) && ("private").equals(projectInfo.getReferenceWbsTemplateType())) {
+                    //TODO =====质检私有=====
                     //获取私有引用根节点
-                    WbsTreePrivate wbsTreePrivateRecord = wbsTreePrivateMapper.selectOne(Wrappers.<WbsTreePrivate>query().lambda()
-                            .select(WbsTreePrivate::getProjectId, WbsTreePrivate::getWbsId)
-                            .eq(WbsTreePrivate::getPKeyId, projectInfo.getReferenceWbsTemplateId()));
-                    //获取私有引用项目树
-                    List<WbsTreePrivate> wbsTreePrivateAllOld = wbsTreePrivateMapper.selectList(Wrappers.<WbsTreePrivate>query().lambda()
-                            .select(WbsTreePrivate::getId, WbsTreePrivate::getNodeName, WbsTreePrivate::getNodeType, WbsTreePrivate::getMajorDataType,
-                                    WbsTreePrivate::getTableType, WbsTreePrivate::getTableOwner, WbsTreePrivate::getImportMatchingInfo,
-                                    WbsTreePrivate::getMixRatioTestIds, WbsTreePrivate::getInitTableId,
-                                    WbsTreePrivate::getInitTableName, WbsTreePrivate::getHtmlUrl, WbsTreePrivate::getSort)
-                            .eq(WbsTreePrivate::getStatus, 1)
-                            .eq(WbsTreePrivate::getProjectId, Long.parseLong(wbsTreePrivateRecord.getProjectId()))
-                            .and(obj -> obj.eq(WbsTreePrivate::getWbsId, Long.parseLong(wbsTreePrivateRecord.getWbsId())).or().isNull(WbsTreePrivate::getWbsId))
-                    );
-                    //获取当前项目私有树、元素表
-                    List<WbsTreePrivate> wbsTreePrivatesAllNow = wbsTreePrivateMapper.selectList(Wrappers.<WbsTreePrivate>query().lambda()
-                            .select(WbsTreePrivate::getId, WbsTreePrivate::getNodeName, WbsTreePrivate::getNodeType, WbsTreePrivate::getMajorDataType,
-                                    WbsTreePrivate::getTableType, WbsTreePrivate::getTableOwner, WbsTreePrivate::getImportMatchingInfo,
-                                    WbsTreePrivate::getMixRatioTestIds, WbsTreePrivate::getInitTableId,
-                                    WbsTreePrivate::getInitTableName, WbsTreePrivate::getHtmlUrl, WbsTreePrivate::getSort)
-                            .eq(WbsTreePrivate::getStatus, 1)
-                            .eq(WbsTreePrivate::getProjectId, Long.parseLong(wbsTreePrivate.getProjectId()))
-                            .and(obj -> obj.eq(WbsTreePrivate::getWbsId, projectInfo.getReferenceWbsTemplateId()).or().isNull(WbsTreePrivate::getWbsId))
-                    );
-                    //同步修改
-                    this.updateWbsInfoContractAsync(wbsTreePrivateAllOld, wbsTreePrivatesAllNow, wbsTreePrivate.getProjectId(), projectInfo.getReferenceWbsTemplateId().toString(), Integer.parseInt(wbsTreePrivate.getWbsType()));
+                    WbsTreePrivate wbsTreePrivateRecord = wbsTreePrivateMapper.selectOne(Wrappers.<WbsTreePrivate>query().lambda().select(WbsTreePrivate::getProjectId, WbsTreePrivate::getWbsId).eq(WbsTreePrivate::getPKeyId, projectInfo.getReferenceWbsTemplateId()));
+
+                    //引用模板的对应节点
+                    WbsTreePrivate recordSelectNode = wbsTreePrivateMapper.selectOne(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getId, wbsTreePrivate.getId()).eq(WbsTreePrivate::getProjectId, wbsTreePrivateRecord.getProjectId()).eq(WbsTreePrivate::getWbsId, wbsTreePrivateRecord.getWbsId()));
+                    //关联项目的对应节点的所有子级
+                    List<WbsTreePrivate> childNodesAllRecordProject = this.getChildNodes(recordSelectNode);
+                    if (childNodesAllRecordProject == null) {
+                        childNodesAllRecordProject = new ArrayList<>();
+                    }
+                    childNodesAllRecordProject.add(recordSelectNode);
+
+                    //获取当前项目私节点、元素表
+                    List<WbsTreePrivate> childNodesAllNowProject = this.getChildNodesAllNowProject(wbsTreePrivate);
+
+                    //修改私有引用信息
+                    this.asyncUpdateWbsPrivate(childNodesAllRecordProject, childNodesAllNowProject, wbsTreePrivate.getProjectId(), projectInfo.getReferenceWbsTemplateId().toString(), Integer.parseInt(wbsTreePrivate.getWbsType()));
                 }
 
             } else if (("2").equals(wbsTreePrivate.getWbsType())) {
-                //试验公有
+                //TODO =====试验公有=====
                 if (ObjectUtil.isNotEmpty(projectInfo.getReferenceWbsTemplateIdTrial()) && (ObjectUtil.isNotEmpty(projectInfo.getReferenceWbsTemplateTypeTrial()) && ("public").equals(projectInfo.getReferenceWbsTemplateTypeTrial()))) {
+                    //获取引用的公有树节点信息,没有元素表
+                    WbsTree wbsTree = wbsTreeMapper.selectOne(Wrappers.<WbsTree>lambdaQuery().eq(WbsTree::getId, wbsTreePrivate.getId()).eq(WbsTree::getWbsId, projectInfo.getReferenceWbsTemplateIdTrial()).eq(WbsTree::getStatus, 1));
+                    List<WbsTree> childNodesAllPublic = this.getChildNodes(wbsTree);
+                    if (childNodesAllPublic == null) {
+                        childNodesAllPublic = new ArrayList<>();
+                    }
+                    childNodesAllPublic.add(wbsTree);
 
-                    List<WbsTree> wbsTreeListAll = wbsTreeMapper.selectList(Wrappers.<WbsTree>lambdaQuery().eq(WbsTree::getWbsId, projectInfo.getReferenceWbsTemplateId()).eq(WbsTree::getType, 1).eq(WbsTree::getStatus, 1));
-
-                    List<WbsTreePrivate> wbsTreePrivatesAll = wbsTreePrivateMapper.selectList(Wrappers.<WbsTreePrivate>query().lambda().eq(WbsTreePrivate::getWbsId, projectInfo.getReferenceWbsTemplateId()).eq(WbsTreePrivate::getProjectId, wbsTreePrivate.getProjectId()).eq(WbsTreePrivate::getStatus, 1));
+                    //获取当前项目私节点、元素表
+                    List<WbsTreePrivate> childNodesAllNowProject = this.getChildNodesAllNowProject(wbsTreePrivate);
+                    //公有引用,由于没有关联清表,html_url不存在,所以不同步表的html_url信息
+                    List<WbsTreePrivate> childNodesAllNowProjectNodes = childNodesAllNowProject.stream().filter(f -> new Integer(1).equals(f.getType())).collect(Collectors.toList());
 
-                    this.updateWbsInfoPrivateAsync(wbsTreeListAll, wbsTreePrivatesAll, wbsTreePrivate.getProjectId(), Integer.parseInt(wbsTreePrivate.getWbsType()));
+                    this.asyncUpdateWbsPublic(childNodesAllPublic, childNodesAllNowProjectNodes, wbsTreePrivate.getProjectId(), Integer.parseInt(wbsTreePrivate.getWbsType()));
 
-                    //试验私有
                 } else if (ObjectUtil.isNotEmpty(projectInfo.getReferenceWbsTemplateIdTrial()) && (ObjectUtil.isNotEmpty(projectInfo.getReferenceWbsTemplateTypeTrial()) && ("private").equals(projectInfo.getReferenceWbsTemplateTypeTrial()))) {
+                    //TODO =====试验私有=====
+                    //私有引用试验根节点
+                    WbsTreePrivate wbsTreePrivateRecord = wbsTreePrivateMapper.selectOne(Wrappers.<WbsTreePrivate>query().lambda().select(WbsTreePrivate::getProjectId, WbsTreePrivate::getWbsId).eq(WbsTreePrivate::getPKeyId, projectInfo.getReferenceWbsTemplateIdTrial()).eq(WbsTreePrivate::getStatus, 1));
+                    //引用模板的对应节点
+                    WbsTreePrivate recordSelectNode = wbsTreePrivateMapper.selectOne(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getId, wbsTreePrivate.getId()).eq(WbsTreePrivate::getProjectId, wbsTreePrivateRecord.getProjectId()).eq(WbsTreePrivate::getWbsId, wbsTreePrivateRecord.getWbsId()));
+                    //关联项目的对应节点的所有子级
+                    List<WbsTreePrivate> childNodesAllRecordProject = this.getChildNodes(recordSelectNode);
+                    if (childNodesAllRecordProject == null) {
+                        childNodesAllRecordProject = new ArrayList<>();
+                    }
+                    childNodesAllRecordProject.add(recordSelectNode);
 
-                    WbsTreePrivate wbsTreePrivateRecord = wbsTreePrivateMapper.selectOne(Wrappers.<WbsTreePrivate>query().lambda()
-                            .select(WbsTreePrivate::getProjectId, WbsTreePrivate::getWbsId)
-                            .eq(WbsTreePrivate::getPKeyId, projectInfo.getReferenceWbsTemplateIdTrial()));
-
-                    List<WbsTreePrivate> wbsTreePrivateAllOld = wbsTreePrivateMapper.selectList(Wrappers.<WbsTreePrivate>query().lambda()
-                            .select(WbsTreePrivate::getId, WbsTreePrivate::getNodeName, WbsTreePrivate::getNodeType, WbsTreePrivate::getMajorDataType, WbsTreePrivate::getTableType, WbsTreePrivate::getTableOwner, WbsTreePrivate::getImportMatchingInfo, WbsTreePrivate::getMixRatioTestIds, WbsTreePrivate::getInitTableId, WbsTreePrivate::getInitTableName, WbsTreePrivate::getHtmlUrl)
-                            .eq(WbsTreePrivate::getStatus, 1)
-                            .eq(WbsTreePrivate::getProjectId, Long.parseLong(wbsTreePrivate.getProjectId()))
-                            .and(obj -> obj.eq(WbsTreePrivate::getWbsId, Long.parseLong(wbsTreePrivateRecord.getWbsId())).or().isNull(WbsTreePrivate::getWbsId))
-                    );
-
-                    List<WbsTreePrivate> wbsTreePrivatesAllNow = wbsTreePrivateMapper.selectList(Wrappers.<WbsTreePrivate>query().lambda()
-                            .select(WbsTreePrivate::getId, WbsTreePrivate::getNodeName, WbsTreePrivate::getNodeType, WbsTreePrivate::getMajorDataType, WbsTreePrivate::getTableType, WbsTreePrivate::getTableOwner, WbsTreePrivate::getImportMatchingInfo, WbsTreePrivate::getMixRatioTestIds, WbsTreePrivate::getInitTableId, WbsTreePrivate::getInitTableName, WbsTreePrivate::getHtmlUrl)
-                            .eq(WbsTreePrivate::getStatus, 1)
-                            .eq(WbsTreePrivate::getProjectId, Long.parseLong(wbsTreePrivate.getProjectId()))
-                            .and(obj -> obj.eq(WbsTreePrivate::getWbsId, projectInfo.getReferenceWbsTemplateIdTrial()).or().isNull(WbsTreePrivate::getWbsId))
-                    );
-
-                    this.updateWbsInfoContractAsync(wbsTreePrivateAllOld, wbsTreePrivatesAllNow, wbsTreePrivate.getProjectId(), projectInfo.getReferenceWbsTemplateIdTrial().toString(), Integer.parseInt(wbsTreePrivate.getWbsType()));
+                    //获取当前项目私节点、元素表
+                    List<WbsTreePrivate> childNodesAllNowProject = this.getChildNodesAllNowProject(wbsTreePrivate);
+
+                    this.asyncUpdateWbsPrivate(childNodesAllRecordProject, childNodesAllNowProject, wbsTreePrivate.getProjectId(), projectInfo.getReferenceWbsTemplateIdTrial().toString(), Integer.parseInt(wbsTreePrivate.getWbsType()));
                 }
             }
         }
         return true;
     }
 
+    private List<WbsTreePrivate> getChildNodesAllNowProject(WbsTreePrivate obj) {
+        List<WbsTreePrivate> childNodesAllNowProject = this.getChildNodes(obj);
+        if (childNodesAllNowProject == null) {
+            childNodesAllNowProject = new ArrayList<>();
+        }
+        childNodesAllNowProject.add(obj);
+        return childNodesAllNowProject;
+    }
+
+    /**
+     * 获取所有子级节点-私有项目引用
+     */
+    private List<WbsTreePrivate> getChildNodes(WbsTreePrivate obj) {
+        if (obj != null) {
+            List<WbsTreePrivate> wbsTreePrivates = Collections.singletonList(obj);
+            List<WbsTreePrivate> result = new ArrayList<>();
+            this.recursionGetChildNodes(wbsTreePrivates, result, obj);
+            if (result.size() > 0) {
+                return result;
+            }
+        }
+        return null;
+    }
+
+    private void recursionGetChildNodes(List<WbsTreePrivate> list, List<WbsTreePrivate> result, WbsTreePrivate obj) {
+        List<Long> ids = list.stream().map(WbsTreePrivate::getId).collect(Collectors.toList());
+        if (ids.size() > 0) {
+            List<WbsTreePrivate> query = wbsTreePrivateMapper.selectList(Wrappers.<WbsTreePrivate>lambdaQuery()
+                    .select(WbsTreePrivate::getWbsId,WbsTreePrivate::getPKeyId, WbsTreePrivate::getId, WbsTreePrivate::getType, WbsTreePrivate::getNodeName,
+                            WbsTreePrivate::getNodeType, WbsTreePrivate::getMajorDataType, WbsTreePrivate::getTableType, WbsTreePrivate::getTableOwner,
+                            WbsTreePrivate::getImportMatchingInfo, WbsTreePrivate::getMixRatioTestIds, WbsTreePrivate::getInitTableId,
+                            WbsTreePrivate::getInitTableName, WbsTreePrivate::getSort, WbsTreePrivate::getHtmlUrl)
+                    .in(WbsTreePrivate::getParentId, ids)
+                    .eq(WbsTreePrivate::getProjectId, obj.getProjectId())
+                    .eq(WbsTreePrivate::getWbsId, obj.getWbsId())
+                    .eq(WbsTreePrivate::getWbsType, obj.getWbsType())
+                    //.eq(WbsTreePrivate::getType, 1) 要同步表的html_url,所以表也要同步
+                    .eq(WbsTreePrivate::getStatus, 1));
+            if (query.size() > 0) {
+                result.addAll(query);
+                recursionGetChildNodes(query, result, obj);
+            }
+        }
+    }
+
+    /**
+     * 获取所有子级节点-公有引用
+     */
+    private List<WbsTree> getChildNodes(WbsTree obj) {
+        if (obj != null) {
+            List<WbsTree> wbsTrees = Collections.singletonList(obj);
+            List<WbsTree> result = new ArrayList<>();
+            this.recursionGetChildNodes(wbsTrees, result, obj);
+            if (result.size() > 0) {
+                return result;
+            }
+        }
+        return null;
+    }
+
+    private void recursionGetChildNodes(List<WbsTree> list, List<WbsTree> result, WbsTree obj) {
+        List<Long> ids = list.stream().map(WbsTree::getId).collect(Collectors.toList());
+        if (ids.size() > 0) {
+            List<WbsTree> query = baseMapper.selectList(Wrappers.<WbsTree>lambdaQuery()
+                    .select(WbsTree::getId, WbsTree::getType, WbsTree::getNodeName, WbsTree::getNodeType, WbsTree::getWbsId, WbsTree::getMajorDataType, WbsTree::getTableType, WbsTree::getTableOwner, WbsTree::getImportMatchingInfo, WbsTree::getMixRatioTestIds, WbsTree::getInitTableId, WbsTree::getInitTableName, WbsTree::getSort)
+                    .in(WbsTree::getParentId, ids)
+                    .eq(WbsTree::getWbsId, obj.getWbsId())
+                    .eq(WbsTree::getType, 1) //没有绑定清表,html_url字段为null,不同步
+                    .eq(WbsTree::getStatus, 1));
+            if (query.size() > 0) {
+                result.addAll(query);
+                recursionGetChildNodes(query, result, obj);
+            }
+        }
+    }
 
     @Override
     public List<WbsNodeTableVO> selectByNodeTable(String id) {
@@ -842,14 +910,13 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
     }
 
     @Async
-    public boolean updateWbsInfoPrivateAsync(List<WbsTree> wbsTreeListAll, List<WbsTreePrivate> wbsTreePrivatesAll, String projectId, Integer wbsType) {
-        return wbsTreePrivateService.updateBatchByIds(wbsTreeListAll, wbsTreePrivatesAll, projectId, wbsType);
+    public boolean asyncUpdateWbsPublic(List<WbsTree> wbsTreeListAll, List<WbsTreePrivate> wbsTreePrivatesAll, String projectId, Integer wbsType) {
+        return wbsTreePrivateService.asyncUpdateWbsPublic(wbsTreeListAll, wbsTreePrivatesAll, projectId, wbsType);
     }
 
     @Async
-    public boolean updateWbsInfoContractAsync(List<WbsTreePrivate> wbsTreePrivates, List<WbsTreePrivate> wbsTreePrivatesAllNow, String
-            projectId, String primaryKeyId, Integer wbsType) {
-        return wbsTreePrivateService.updateBatchByIds2(wbsTreePrivates, wbsTreePrivatesAllNow, projectId, primaryKeyId, wbsType);
+    public boolean asyncUpdateWbsPrivate(List<WbsTreePrivate> wbsTreePrivates, List<WbsTreePrivate> wbsTreePrivatesAllNow, String projectId, String primaryKeyId, Integer wbsType) {
+        return wbsTreePrivateService.asyncUpdateWbsPrivate(wbsTreePrivates, wbsTreePrivatesAllNow, projectId, primaryKeyId, wbsType);
     }
 
     //新增独立表单库数据