Przeglądaj źródła

Merge remote-tracking branch 'origin/master' into master

yangyj 2 lat temu
rodzic
commit
34a71179df
37 zmienionych plików z 1074 dodań i 618 usunięć
  1. 9 1
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ArchiveTreeContract.java
  2. 4 3
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ArchiveTreeAutoRuleVO.java
  3. 10 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ArchiveTreeContractVO2.java
  4. 5 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ArchiveTreeVO2.java
  5. 11 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsTreeVO2.java
  6. 10 8
      blade-service/blade-business/src/main/java/org/springblade/business/controller/ImageClassificationFileController.java
  7. 69 23
      blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java
  8. 13 4
      blade-service/blade-business/src/main/java/org/springblade/business/controller/MaterialProgressController.java
  9. 4 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/InformationQueryMapper.java
  10. 23 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/InformationQueryMapper.xml
  11. 6 1
      blade-service/blade-business/src/main/java/org/springblade/business/service/IInformationQueryService.java
  12. 7 2
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/InformationQueryServiceImpl.java
  13. 0 1
      blade-service/blade-business/src/main/java/org/springblade/business/socket/WebSocket.java
  14. 1 2
      blade-service/blade-business/src/main/java/org/springblade/business/socket/WebSocketManager.java
  15. 4 2
      blade-service/blade-business/src/main/java/org/springblade/business/utils/FileUtils.java
  16. 2 31
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ArchiveTreeContractController.java
  17. 38 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ArchiveTreeController.java
  18. 38 22
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/TextdictInfoController.java
  19. 7 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsFormElementController.java
  20. 12 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreePrivateController.java
  21. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/feign/ArchiveTreeClientImpl.java
  22. 11 26
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeContractMapper.java
  23. 16 113
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeContractMapper.xml
  24. 25 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeMapper.java
  25. 118 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeMapper.xml
  26. 2 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreeMapper.xml
  27. 5 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreePrivateMapper.xml
  28. 2 18
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IArchiveTreeContractService.java
  29. 20 4
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IArchiveTreeService.java
  30. 2 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IWbsTreePrivateService.java
  31. 15 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArTreeContractInitServiceImpl.java
  32. 27 278
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeContractServiceImpl.java
  33. 232 34
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeServiceImpl.java
  34. 87 31
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreePrivateServiceImpl.java
  35. 46 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/utils/AsyncConfigurer.java
  36. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/utils/ForestNodeMerger.java
  37. 191 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/utils/ThreadPoolMonitor.java

+ 9 - 1
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ArchiveTreeContract.java

@@ -155,8 +155,11 @@ public class ArchiveTreeContract extends BaseEntity {
 	 */
 	private Integer archiveAutoGroupSelect;
 
+
+	//系统级模板Id
+	private Long baseId;
 	/**
-	 * 来源id,用于后续同步更新
+	 * 来源id,项目级,用于后续同步更新
 	 */
 	private Long fromId;
 	/**
@@ -169,6 +172,10 @@ public class ArchiveTreeContract extends BaseEntity {
 	 */
 	private String expDataType;
 
+	//权限编码
+	private String treeCode;
+
+
 
 	public ArchiveTreeContract() {
 	}
@@ -181,6 +188,7 @@ public class ArchiveTreeContract extends BaseEntity {
 		try {
 			BeanUtils.copyProperties(archiveTree,this);
 			this.fromId = archiveTree.getId();
+			this.baseId = archiveTree.getFromId();
 		} catch (BeansException e) {
 			e.printStackTrace();
 		}

+ 4 - 3
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ArchiveTreeContractAutoRuleVO.java → blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ArchiveTreeAutoRuleVO.java

@@ -7,7 +7,8 @@ import java.util.ArrayList;
 import java.util.List;
 
 @Data
-public class ArchiveTreeContractAutoRuleVO implements INode<ArchiveTreeContractAutoRuleVO> {
+public class ArchiveTreeAutoRuleVO implements INode<ArchiveTreeAutoRuleVO> {
+
 
     private Long nodeId;//节点id
 
@@ -24,7 +25,7 @@ public class ArchiveTreeContractAutoRuleVO implements INode<ArchiveTreeContractA
 
     private Integer archiveAutoGroupSelect;
 
-    private List<ArchiveTreeContractAutoRuleVO> children=new ArrayList<>();
+    private List<ArchiveTreeAutoRuleVO> children=new ArrayList<>();
 
     @Override
     public Long getId() {
@@ -37,7 +38,7 @@ public class ArchiveTreeContractAutoRuleVO implements INode<ArchiveTreeContractA
     }
 
     @Override
-    public List<ArchiveTreeContractAutoRuleVO> getChildren() {
+    public List<ArchiveTreeAutoRuleVO> getChildren() {
         return children;
     }
 }

+ 10 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ArchiveTreeContractVO2.java

@@ -158,6 +158,16 @@ public class ArchiveTreeContractVO2 implements INode<ArchiveTreeContractVO2> {
 
 	private String expDataType;
 
+	/**
+	 * 分类并卷的分类ID,当archiveAutoType=2时,用来确定同一类型。新增时随机生成,一同提交设置的节点都是同一类。 编辑时 采用已有的
+	 */
+	private Long archiveAutoGroupId;
+
+	/**
+	 * 设置分类并卷选择的节点设为1,其下范围内节点设为0
+	 */
+	private Integer archiveAutoGroupSelect;
+
 	public String toString() {
 		return "TreeNode(parentId=" + this.getParentId()
 				+ ",ancestors" + this.getAncestors()

+ 5 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ArchiveTreeVO2.java

@@ -175,4 +175,9 @@ public class ArchiveTreeVO2 implements INode<ArchiveTreeVO2> {
 
     private String expDataType;
 
+    /**
+     * 来源ID
+     */
+    private Long fromId;
+
 }

+ 11 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsTreeVO2.java

@@ -43,8 +43,11 @@ public class WbsTreeVO2 implements INode<WbsTreeVO2> {
 
     private Integer isExistForm;
 
+    private Integer majorDataType;
+
     private String ancestors;
 
+
     @JsonInclude(JsonInclude.Include.NON_EMPTY)
     private Boolean hasChildren;
 
@@ -136,6 +139,14 @@ public class WbsTreeVO2 implements INode<WbsTreeVO2> {
         this.value = value;
     }
 
+    public Integer getMajorDataType() {
+        return majorDataType;
+    }
+
+    public void setMajorDataType(Integer majorDataType) {
+        this.majorDataType = majorDataType;
+    }
+
 
     public String toString() {
         return "TreeNode(nodeType=" + this.getNodeType()

+ 10 - 8
blade-service/blade-business/src/main/java/org/springblade/business/controller/ImageClassificationFileController.java

@@ -163,8 +163,8 @@ public class ImageClassificationFileController extends BladeController {
                     //需要删除的本地文件集合
                     List<String> removeList = new ArrayList<>();
 
-                    // 压缩到小于指定文件大小200kb
-                    double targetSize = 200 * 1024;
+                    //压缩到小于指定文件大小100kb
+                    //double targetSize = 100 * 1024;
 
                     for (ImageClassificationFile file : fileResult) {
                         //获取图片文件流
@@ -204,11 +204,13 @@ public class ImageClassificationFileController extends BladeController {
 
                                             //获取文件流
                                             byte[] bytes = CommonUtil.InputStreamToBytes(CommonUtil.getOSSInputStream(urls.get(i)));
+
                                             //压缩文件大小
-                                            while (bytes.length > targetSize) {
+                                            /*while (bytes.length > targetSize) {
                                                 float reduceMultiple = 0.5f;
                                                 bytes = FileUtils.resizeImage(bytes, reduceMultiple);
-                                            }
+                                            }*/
+                                            bytes = FileUtils.resizeImage(bytes, 0f);
 
                                             //创建图片
                                             drawing.createPicture(anchor, workbook.addPicture(bytes, Workbook.PICTURE_TYPE_JPEG));
@@ -689,18 +691,18 @@ public class ImageClassificationFileController extends BladeController {
     }
 
     /**
-     *
      * @param urlStr
-     * @return  返回Url资源大小
+     * @return 返回Url资源大小
      * @throws IOException
      */
     public long getResourceLength(String urlStr) throws IOException {
-        URL url=new URL(urlStr);
-        URLConnection urlConnection=url.openConnection();
+        URL url = new URL(urlStr);
+        URLConnection urlConnection = url.openConnection();
         urlConnection.connect();
         //返回响应报文头字段Content-Length的值
         return urlConnection.getContentLength();
     }
+
     /**
      * 根据字节返回文件大小
      */

+ 69 - 23
blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java

@@ -38,6 +38,7 @@ import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.node.ForestNodeMerger;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.core.tool.utils.ObjectUtil;
+import org.springblade.core.tool.utils.StringUtil;
 import org.springblade.evisa.feign.EVisaClient;
 import org.springblade.evisa.vo.CertBeanVO;
 import org.springblade.manager.entity.*;
@@ -356,6 +357,15 @@ public class InformationWriteQueryController extends BladeController {
         if (StringUtils.isNotEmpty(copyVO.getNeedCopyPrimaryKeyId()) && copyVO.getCopyBatchToPaths().size() > 0) {
             //查询被复制节点
             WbsTreeContract wbsTreeContract = this.wbsTreeContractClient.getContractNodeByPrimaryKeyId(copyVO.getNeedCopyPrimaryKeyId());
+
+            //获取数据写入的节点信息
+            List<CopyContractTreeNodeVO.CopyBatch> batchPathList = copyVO.getCopyBatchToPaths();
+            //获取数据源节点
+            CopyContractTreeNodeVO.CopyBatch copyBatchResource = batchPathList.stream().filter(f -> f.getPrimaryKeyId().equals(wbsTreeContract.getPKeyId().toString())).findAny().orElse(null);
+            if (copyBatchResource != null) {
+                return R.fail("请选择除【" + wbsTreeContract.getNodeName() + "】源节点之外的节点进行复制");
+            }
+
             String tabOwner;
             if (("1,2").equals(copyVO.getClassify()) || ("2,1").equals(copyVO.getClassify())) {
                 tabOwner = "1,2,3,4,5,6";
@@ -378,31 +388,51 @@ public class InformationWriteQueryController extends BladeController {
                 //获取源数据
                 Map<String, List<List<Map<String, Object>>>> tableBusinessDataMap = new HashMap<>();
                 for (WbsTreeContract treeContract : tableList) {
-                    List<Map<String, Object>> tableBusinessData = this.jdbcTemplate.queryForList("select * from " + treeContract.getInitTableName() + " where p_key_id = " + treeContract.getPKeyId());
-                    if (tableBusinessData.size() > 0) {
-                        //设置参数
-                        List<List<Map<String, Object>>> list;
-                        if (tableBusinessDataMap.containsKey(treeContract.getId().toString())) {
-                            list = tableBusinessDataMap.get(treeContract.getId().toString());
-                        } else {
-                            list = new ArrayList<>();
+                    if (StringUtils.isNotEmpty(treeContract.getInitTableName())) {
+                        //判断表是否存在
+                        String isExitSql = "select * from information_schema.TABLES where TABLE_NAME='" + treeContract.getInitTableName() + "'";
+                        List<Map<String, Object>> tabList = this.jdbcTemplate.queryForList(isExitSql);
+                        if (tabList.size() == 0) {
+                            continue; //未找到实体表跳过
+                        }
+
+                        String sql = "select * from " + treeContract.getInitTableName() + " where p_key_id = " + treeContract.getPKeyId();
+                        List<Map<String, Object>> tableBusinessData = this.jdbcTemplate.queryForList(sql);
+                        if (tableBusinessData.size() > 0) {
+                            //设置参数
+                            List<List<Map<String, Object>>> list;
+                            if (tableBusinessDataMap.containsKey(treeContract.getId().toString())) {
+                                list = tableBusinessDataMap.get(treeContract.getId().toString());
+                            } else {
+                                list = new ArrayList<>();
+                            }
+                            list.add(tableBusinessData);
+                            tableBusinessDataMap.put(treeContract.getId().toString(), list);
                         }
-                        list.add(tableBusinessData);
-                        tableBusinessDataMap.put(treeContract.getId().toString(), list);
                     }
                 }
 
-                //获取数据写入的节点信息
-                List<CopyContractTreeNodeVO.CopyBatch> batchPathList = copyVO.getCopyBatchToPaths();
                 //删除数据SQL
                 List<String> removeSqlList = new ArrayList<>();
                 //新增数据SQL
                 List<String> saveSqlList = new ArrayList<>();
+                //已上报状态的节点名称
+                Map<String, String> taskStatusMap = new HashMap<>();
 
                 for (CopyContractTreeNodeVO.CopyBatch copyBatch : batchPathList) {
                     //获取选择的节点信息
                     WbsTreeContract selectNode = this.wbsTreeContractClient.getContractNodeByPrimaryKeyId(copyBatch.getPrimaryKeyId());
 
+                    //判断该节点是否已上报,1=待审批,2=已审批均属于已上报
+                    String sqlSb = "select classify from u_information_query where type = 1 and status in (1,2) and wbs_id = " + selectNode.getPKeyId() + " and classify in (" + copyVO.getClassify() + ")";
+                    List<InformationQuery> query = jdbcTemplate.query(sqlSb, new BeanPropertyRowMapper<>(InformationQuery.class));
+                    if (query.size() > 0) {
+                        for (InformationQuery informationQuery : query) {
+                            taskStatusMap.put((new Integer(1)).equals(informationQuery.getClassify()) ? "施工" : "监理", selectNode.getNodeName());
+                        }
+                        continue;
+                    }
+
                     //实际获取的数据
                     Map<String, List<List<Map<String, Object>>>> currentDataMap = new HashMap<>();
 
@@ -468,6 +498,16 @@ public class InformationWriteQueryController extends BladeController {
                         }
                     }
                 }
+
+                if (taskStatusMap.size() > 0) {
+                    List<String> str = new ArrayList<>();
+                    for (Map.Entry<String, String> map : taskStatusMap.entrySet()) {
+                        str.add("【" + map.getValue() + "-" + map.getKey() + "】");
+                    }
+                    String join = StringUtils.join(str, "、");
+                    return R.fail(StringUtil.format("节点{}已上报,无法复制数据,请重新选择", join));
+                }
+
                 //删除原本填写的数据,覆盖
                 if (removeSqlList.size() > 0) {
                     for (String sql : removeSqlList) {
@@ -486,7 +526,7 @@ public class InformationWriteQueryController extends BladeController {
 
             //复制附件信息
             for (WbsTreeContract sourceDataObj : tableList) {
-                if (sourceDataObj.getTabFileType() == 2) {
+                if (ObjectUtils.isNotEmpty(sourceDataObj.getTabFileType()) && sourceDataObj.getTabFileType() == 2) {
                     //获取源表中的附件信息
                     String sql = "select * from m_table_file where is_deleted = 0 and type = 2 and tab_id =" + sourceDataObj.getPKeyId();
                     List<TableFile> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(TableFile.class));
@@ -502,8 +542,8 @@ public class InformationWriteQueryController extends BladeController {
                                 //新增源数据附件到复制节点下对应表中
                                 tableFileClient.saveBatchFile(query, next.getPKeyId());
 
-                                //修改复制节点下对应表的按钮状态
-                                String updateStatus = "update m_wbs_tree_contract set tab_file_type = " + sourceDataObj.getTabFileType() + " ,is_tab_pdf = " + sourceDataObj.getIsTabPdf() + " ,pdf_url = '" + sourceDataObj.getPdfUrl() + "' ,is_buss_show = " + sourceDataObj.getIsBussShow() + " where p_key_id = " + next.getPKeyId();
+                                //修改复制节点下对应表的文件上传的按钮状态
+                                String updateStatus = "update m_wbs_tree_contract set tab_file_type = " + sourceDataObj.getTabFileType() + " where p_key_id = " + next.getPKeyId();
                                 jdbcTemplate.execute(updateStatus);
 
                                 iterator.remove();
@@ -512,7 +552,6 @@ public class InformationWriteQueryController extends BladeController {
                     }
                 }
             }
-
             return R.data(true);
         }
 
@@ -1310,7 +1349,7 @@ public class InformationWriteQueryController extends BladeController {
                     String sql = "select sort from m_wbs_tree_contract where contract_id = '" + node.getContractId() + "' and (id = '" + node.getId() + "' or old_id = '" + node.getId() + "')";
                     List<WbsTreeContract> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(WbsTreeContract.class));
                     List<Integer> collect = query.stream().filter(f -> ObjectUtils.isNotEmpty(f.getSort())).collect(Collectors.toList()).stream().map(WbsTreeContract::getSort).collect(Collectors.toList());
-                    Integer max=1;
+                    Integer max = 1;
                     if (collect.size() > 0) {
                         max = collect.stream().reduce(collect.get(0), Integer::max);
                     } else {
@@ -1391,7 +1430,7 @@ public class InformationWriteQueryController extends BladeController {
                         String sql = "select sort from m_wbs_tree_contract where contract_id = '" + node.getContractId() + "' and (id = '" + node.getId() + "' or old_id = '" + node.getId() + "')";
                         List<WbsTreeContract> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(WbsTreeContract.class));
                         List<Integer> collect = query.stream().filter(f -> ObjectUtils.isNotEmpty(f.getSort())).collect(Collectors.toList()).stream().map(WbsTreeContract::getSort).collect(Collectors.toList());
-                        Integer max=1;
+                        Integer max = 1;
                         if (collect.size() > 0) {
                             max = collect.stream().reduce(collect.get(0), Integer::max);
                         } else {
@@ -1697,10 +1736,18 @@ public class InformationWriteQueryController extends BladeController {
 
         //保存操作记录
         List<String> idArray = JSONArray.parseArray(JSONObject.toJSONString(ids.split(",")), String.class);
-
+        //获取当前节点的所有父节点
+        List<WbsTreeContract> result = new ArrayList<>();
+        result.add(removeNode);
+        this.queryParentNode(removeNode, result);
+        StringBuilder pathName = new StringBuilder();
+        for (int i = 1, l = result.size(); i <= l; i++) {
+            WbsTreeContract node = result.get(result.size() - i);
+            pathName.append("-").append(StringUtils.isNotEmpty(node.getFullName()) ? node.getFullName() : node.getNodeName());
+        }
         JSONObject json = new JSONObject();
         json.put("operationObjIds", idArray);
-        json.put("operationObjName", nodeName);
+        json.put("operationObjName", pathName.substring(1));
         this.operationLogClient.saveUserOperationLog(4, "资料管理", "工序资料", json);
 
         //保存进回收站
@@ -1833,7 +1880,7 @@ public class InformationWriteQueryController extends BladeController {
                 String sql = "select sort from m_wbs_tree_contract where contract_id = '" + treeContract.getContractId() + "' and (id = '" + half.getId() + "' or old_id = '" + half.getId() + "')";
                 List<WbsTreeContract> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(WbsTreeContract.class));
                 List<Integer> collect = query.stream().filter(f -> ObjectUtils.isNotEmpty(f.getSort())).collect(Collectors.toList()).stream().map(WbsTreeContract::getSort).collect(Collectors.toList());
-                Integer max =1 ;
+                Integer max = 1;
                 if (collect.size() > 0) {
                     max = collect.stream().reduce(collect.get(0), Integer::max);
                 } else {
@@ -1912,7 +1959,7 @@ public class InformationWriteQueryController extends BladeController {
         if (saveList.size() > 0) {
             //保存施工日志
             if (saveLedger.size() > 0) {
-                this.constructionLedgerService.saveBatch(saveLedger,1000);
+                this.constructionLedgerService.saveBatch(saveLedger, 1000);
             }
 
             try {
@@ -2287,7 +2334,6 @@ public class InformationWriteQueryController extends BladeController {
                 contractIds.add(contractIdRelation);
             }
             if (contractIds.size() > 0) {
-                //原始classify=2时查不出数量统计,所以改成传1
                 if (StringUtils.isNotEmpty(parentId)) {
                     //子节点
                     rootTreeNode = this.informationQueryService.queryContractTreeSupervision(contractIds, parentId, Integer.parseInt(classifyType));

+ 13 - 4
blade-service/blade-business/src/main/java/org/springblade/business/controller/MaterialProgressController.java

@@ -93,10 +93,19 @@ public class MaterialProgressController extends BladeController {
         } else {
             //找到根节点
             List<WbsTreeContractTreeVOS> nodeResult = this.wbsTreeContractClient.queryContractWbsTreeByContractIdAndType(contractId, 1, StringUtils.isNotEmpty(parentId) ? parentId : "0");
-            if(nodeResult != null && nodeResult.size() > 0){
-
-                //找到当前节点下的所有填报节点
-                List<QueryProcessDataVO> queryDataResult = this.informationQueryService.queryProcessDataByParentIdAndContractId(parentId, new Integer(classifyType), contractId);
+            if(nodeResult != null && nodeResult.size() > 0) {
+                List<QueryProcessDataVO> queryDataResult = new ArrayList<>();
+                if (StringUtils.isEmpty(parentId)) {
+                    //找到当前节点下的所有填报节点
+                    queryDataResult = this.informationQueryService.queryProcessDataByParentIdAndContractIdThree("", new Integer(classifyType), contractId);
+                } else{
+                    WbsTreeContract node = this.wbsTreeContractClient.getContractWbsTreeByContractIdAndId(Long.valueOf(parentId), Long.valueOf(contractId));
+                    if (node.getParentId() == 0){
+                        queryDataResult = this.informationQueryService.queryProcessDataByParentIdAndContractIdThree("", new Integer(classifyType), contractId);
+                    }else {
+                        queryDataResult = this.informationQueryService.queryProcessDataByParentIdAndContractIdThree(parentId, new Integer(classifyType), contractId);
+                    }
+                }
                 //统计
                 this.countAmount(nodeResult, queryDataResult, contractId, reVO);
 

+ 4 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/InformationQueryMapper.java

@@ -48,6 +48,10 @@ public interface InformationQueryMapper extends BaseMapper<InformationQuery> {
 	 * 查询工序节点的填报记录
 	 */
 	List<QueryProcessDataVO> queryProcessDataByParentIdAndContractIdTwo(@Param("parentId") String parentId, @Param("classify") Integer classify, @Param("contractId") String contractId);
+	/**
+	 * 查询工序节点的填报记录,资料进度使用
+	 */
+	List<QueryProcessDataVO> queryProcessDataByParentIdAndContractIdThree(@Param("parentId") String parentId, @Param("classify") Integer classify, @Param("contractId") String contractId);
 
 	/**
 	 * 根据节点ID及其填报的类型获取填报记录

+ 23 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/InformationQueryMapper.xml

@@ -570,4 +570,27 @@
           AND wtc.is_deleted = 0
     </select>
 
+    <select id="queryProcessDataByParentIdAndContractIdThree" resultMap="queryProcessDataMap">
+        SELECT
+            wtc.id AS treeId,
+            wtc.p_key_id,
+            wtc.ancestors,
+            wtc.major_data_type,
+            wtc.node_type AS nodeType,
+            IFNULL(if(length(trim(wtc.full_name)) > 0, wtc.full_name, wtc.node_name),wtc.node_name) AS title,
+            wtc.parent_id AS parentId,
+            uiq.id AS informationQueryId,
+            uiq.status,
+            uiq.type AS queryType
+        FROM
+            m_wbs_tree_contract AS wtc
+                LEFT JOIN u_information_query AS uiq ON wtc.p_key_id = uiq.wbs_id AND uiq.classify = #{classify} and uiq.is_deleted = 0
+        WHERE
+            wtc.type = 1
+          AND wtc.major_data_type in(1,2,3,4)
+          AND wtc.ancestors like concat('%',#{parentId},'%')
+          AND wtc.contract_id = #{contractId}
+          AND wtc.is_deleted = 0
+    </select>
+
 </mapper>

+ 6 - 1
blade-service/blade-business/src/main/java/org/springblade/business/service/IInformationQueryService.java

@@ -62,10 +62,15 @@ public interface IInformationQueryService extends BaseService<InformationQuery>
 	List<QueryProcessDataVO> queryProcessDataByParentIdAndContractId(String parentId, Integer classify, String contractId);
 
 	/**
-	 * 查询工序节点的填报记录2
+	 * 查询工序节点的填报记录,简化
 	 */
 	List<QueryProcessDataVO> queryProcessDataByParentIdAndContractIdTwo(String parentId, Integer classify, String contractId);
 
+	/**
+	 * 查询工序节点的填报记录,status不默认为0,资料进度统计
+	 */
+	List<QueryProcessDataVO> queryProcessDataByParentIdAndContractIdThree(String parentId, Integer classify, String contractId);
+
 	/**
 	 * 保存填报时新增或修改填报资料记录表数据
 	 * @param wbsId 当前填报节点

+ 7 - 2
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/InformationQueryServiceImpl.java

@@ -119,13 +119,18 @@ public class InformationQueryServiceImpl extends BaseServiceImpl<InformationQuer
         }
         return result;
     }
-
+    //简化
     @Override
     public List<QueryProcessDataVO> queryProcessDataByParentIdAndContractIdTwo(String parentId, Integer classify, String contractId) {
         List<QueryProcessDataVO> result = this.baseMapper.queryProcessDataByParentIdAndContractIdTwo(parentId, classify, contractId);
         return result;
     }
-
+    //资料进度统计使用
+    @Override
+    public List<QueryProcessDataVO> queryProcessDataByParentIdAndContractIdThree(String parentId, Integer classify, String contractId) {
+        List<QueryProcessDataVO> result = this.baseMapper.queryProcessDataByParentIdAndContractIdThree(parentId, classify, contractId);
+        return result;
+    }
 
     private List<FirstInformation> setFirstLinkData(List<JSONObject> linkDataList, String businessId) {
         List<FirstInformation> linkList = new ArrayList<>();

+ 0 - 1
blade-service/blade-business/src/main/java/org/springblade/business/socket/WebSocket.java

@@ -167,7 +167,6 @@ public class WebSocket {
     @Scheduled(cron = "0 0/5 * * * ?")
     public void reSendMessage() throws IOException {
         if (webSocketMap.isEmpty() || webSocketMessageMap.isEmpty()) {
-            logger.error("定时重发消息WebSocket,reSendMessage()方法未执行,原因:客户端未建立WebSocket链接");
             return;
         }
 

+ 1 - 2
blade-service/blade-business/src/main/java/org/springblade/business/socket/WebSocketManager.java

@@ -163,10 +163,9 @@ public class WebSocketManager {
     /***
      * 定时重发任务消息WebSocket - 后管
      */
-    @Scheduled(cron = "0 0/6 * * * ?")
+    @Scheduled(cron = "0 0/5 * * * ?")
     public void reSendMessageManager() throws IOException {
         if (webSocketMap2.isEmpty() || webSocketMessageMap2.isEmpty()) {
-            logger.error("定时重发消息WebSocket,reSendMessageManager()方法未执行,原因:客户端未建立WebSocket链接");
             return;
         }
 

+ 4 - 2
blade-service/blade-business/src/main/java/org/springblade/business/utils/FileUtils.java

@@ -104,8 +104,10 @@ public class FileUtils {
      */
     public static byte[] resizeImage(byte[] srcImgData, float reduceMultiple) throws IOException {
         BufferedImage bi = ImageIO.read(new ByteArrayInputStream(srcImgData));
-        int width = (int) (bi.getWidth() * reduceMultiple);
-        int height = (int) (bi.getHeight() * reduceMultiple);
+        /*int width = (int) (bi.getWidth() * reduceMultiple);
+        int height = (int) (bi.getHeight() * reduceMultiple);*/
+        int width = 768;
+        int height = 1024;
         Image image = bi.getScaledInstance(width, height, Image.SCALE_SMOOTH);
         BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
         Graphics g = tag.getGraphics();

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

@@ -37,9 +37,8 @@ import org.springblade.manager.dto.ArchiveTreeDTO;
 import org.springblade.manager.dto.ArchiveTreeSortDTO;
 import org.springblade.manager.entity.ArchiveTree;
 import org.springblade.manager.service.IArchiveTreeService;
-import org.springblade.manager.vo.ArchiveTreeContractAutoRuleVO;
 import org.springblade.manager.vo.ArchiveTreeContractVO2;
-import org.springblade.manager.vo.ArchiveTreeVO;
+
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.RequestParam;
 import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -203,6 +202,7 @@ public class ArchiveTreeContractController extends BladeController {
 	})
 	public R<List<ArchiveTreeContractVO2>> tree(Integer disPlayTree, Integer nodeType,Long projectId){
 
+
 		List<ArchiveTreeContractVO2> tree = archiveTreeContractService.tree2(AuthUtil.getTenantId(), disPlayTree, nodeType,projectId);
 		if (tree != null && tree.size() > 0) {
 			return R.data(tree);
@@ -229,36 +229,7 @@ public class ArchiveTreeContractController extends BladeController {
 	}
 
 
-	/**
-	 * 保存立卷规则设置
-	 */
-	@PostMapping("/saveArchiveAutoRule")
-	@ApiOperationSupport(order = 8)
-	@ApiOperation(value = "保存立卷规则设置", notes = "传入archiveAutoType规则类型,nodeIds逗号拼接选择节点id")
-	public R saveArchiveAutoRule(@ApiParam(value = "立卷规则", required = true) @RequestParam Integer archiveAutoType,
-					@ApiParam(value = "主键集合", required = true) @RequestParam String nodeIds) {
-		return R.status(archiveTreeContractService.saveArchiveAutoRule(archiveAutoType,nodeIds));
-	}
-
 
-	/**
-	 * 查看立卷规则设置
-	 */
-	@PostMapping("/getArchiveAutoRule")
-	@ApiOperationSupport(order = 9)
-	@ApiOperation(value = "查看立卷规则设置", notes = "传入节点id")
-	public R getArchiveAutoRule(@ApiParam(value = "主键", required = true) @RequestParam Long id) {
-		Map<String, Object> ruleMap=archiveTreeContractService.getArchiveAutoRule(id);
-		return R.data(ruleMap);
-	}
-
-	/**
-	 * 修改立卷规则设置
-	 */
-	@PostMapping("/updateArchiveAutoRule")
-	public R updateArchiveAutoRule(ArchiveTreeContractAutoRuleMapDTO dto) {
-		return R.status(archiveTreeContractService.updateArchiveAutoRule(dto));
-	}
 
 
 	/**

+ 38 - 3
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ArchiveTreeController.java

@@ -13,6 +13,7 @@ import org.springblade.core.secure.BladeUser;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.Func;
+import org.springblade.manager.dto.ArchiveTreeContractAutoRuleMapDTO;
 import org.springblade.manager.dto.ArchiveTreeDTO;
 import org.springblade.manager.dto.ArchiveTreeSortDTO;
 import org.springblade.manager.vo.ArchiveTreeVO2;
@@ -24,6 +25,7 @@ import org.springblade.manager.service.IArchiveTreeService;
 import org.springblade.core.boot.ctrl.BladeController;
 
 import java.util.List;
+import java.util.Map;
 
 import static org.springblade.core.cache.constant.CacheConstant.SYS_CACHE;
 
@@ -133,11 +135,12 @@ public class ArchiveTreeController extends BladeController {
     @ApiImplicitParams(value = {
             @ApiImplicitParam(name = "projectId", value = "项目id,0是系统级"),
             @ApiImplicitParam(name = "disPlayTree", value = "是否加载显示树 'null'=不加载 '1'=加载"),
-            @ApiImplicitParam(name = "nodeType", value = "'null'=全加载 '1'=关联电子原生文件类型树 '2'=文件上传类型树")
+            @ApiImplicitParam(name = "nodeType", value = "'null'=全加载 '1'=关联电子原生文件类型树 '2'=文件上传类型树"),
+            @ApiImplicitParam(name = "wbsId", value = "对应的wbs树,用于展示关联质检节点下的"),
     })
-    public R<List<ArchiveTreeVO2>> tree(Long projectId,Integer disPlayTree, Integer nodeType) {
+    public R<List<ArchiveTreeVO2>> tree(Long projectId,Integer disPlayTree, Integer nodeType,String wbsId) {
 
-        List<ArchiveTreeVO2> tree = archiveTreeService.tree2(AuthUtil.getTenantId(),projectId, disPlayTree, nodeType);
+        List<ArchiveTreeVO2> tree = archiveTreeService.tree2(AuthUtil.getTenantId(),projectId, disPlayTree, nodeType,wbsId,true);
         if (tree != null && tree.size() > 0) {
             return R.data(tree);
         }
@@ -194,4 +197,36 @@ public class ArchiveTreeController extends BladeController {
         return R.fail(200, "初始化创建失败");
     }
 
+
+    /**
+     * 保存立卷规则设置
+     */
+    @PostMapping("/saveArchiveAutoRule")
+    @ApiOperationSupport(order = 8)
+    @ApiOperation(value = "保存立卷规则设置", notes = "传入archiveAutoType规则类型,nodeIds逗号拼接选择节点id")
+    public R saveArchiveAutoRule(@ApiParam(value = "立卷规则", required = true) @RequestParam Integer archiveAutoType,
+                                 @ApiParam(value = "主键集合", required = true) @RequestParam String nodeIds) {
+        return R.status(archiveTreeService.saveArchiveAutoRule(archiveAutoType,nodeIds));
+    }
+
+
+    /**
+     * 查看立卷规则设置
+     */
+    @PostMapping("/getArchiveAutoRule")
+    @ApiOperationSupport(order = 9)
+    @ApiOperation(value = "查看立卷规则设置", notes = "传入节点id")
+    public R getArchiveAutoRule(@ApiParam(value = "主键", required = true) @RequestParam Long id) {
+        Map<String, Object> ruleMap=archiveTreeService.getArchiveAutoRule(id);
+        return R.data(ruleMap);
+    }
+
+    /**
+     * 修改立卷规则设置
+     */
+    @PostMapping("/updateArchiveAutoRule")
+    public R updateArchiveAutoRule(ArchiveTreeContractAutoRuleMapDTO dto) {
+        return R.status(archiveTreeService.updateArchiveAutoRule(dto));
+    }
+
 }

+ 38 - 22
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/TextdictInfoController.java

@@ -35,9 +35,12 @@ import org.jsoup.nodes.Element;
 import org.jsoup.select.Elements;
 import org.springblade.common.utils.CommonUtil;
 import org.springblade.common.utils.SnowFlakeUtil;
+import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
+import org.springblade.core.redis.cache.BladeRedis;
 import org.springblade.core.secure.BladeUser;
+import org.springblade.core.secure.utils.SecureUtil;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.*;
 import org.springblade.manager.entity.*;
@@ -84,7 +87,7 @@ public class TextdictInfoController extends BladeController {
     private final WbsTreePrivateMapper wbsTreePrivateMapper;
     private final WbsTreePrivateServiceImpl wbsTreePrivateService;
     private final WbsTreeContractServiceImpl wbsTreeContractService;
-
+    private final BladeRedis bladeRedis;
     private final JdbcTemplate jdbcTemplate;
 
     /**
@@ -212,7 +215,7 @@ public class TextdictInfoController extends BladeController {
         delIds.add(ids);
         textdictInfoService.getBaseMapper().deleteBatchIds(delIds);
 
-        return R.success("成功");
+        return R.success("删除成功");
     }
 
 
@@ -339,6 +342,10 @@ public class TextdictInfoController extends BladeController {
     @ApiOperationSupport(order = 7)
     @ApiOperation(value = "保存电签", notes = "保存电签")
     public R<String> saveSigInfo(@Valid @RequestBody JSONObject dataInfo) throws IOException {
+        String redisValue = bladeRedis.get("save-eVis-lock:" + SecureUtil.getUserId());
+        if (StringUtils.isNotEmpty(redisValue) && redisValue.equals("1")) {
+            throw new ServiceException("请勿重复提交,请3秒后再尝试");
+        }
         JSONArray jsonArray = dataInfo.getJSONArray("dataInfo");
         Long tableId = dataInfo.getLong("tabId");
 
@@ -352,10 +359,11 @@ public class TextdictInfoController extends BladeController {
                 .eq(WbsTreePrivate::getStatus, 1));
         List<Long> pKeyIds = wbsTreePrivatesEqual.stream().map(WbsTreePrivate::getPKeyId).collect(Collectors.toList());
         String ids = StringUtils.join(pKeyIds, ",");
-
-        //删除引用当前模板所有电签信息
-        String delSql = "delete from m_textdict_info where tab_id in(" + ids + ") and type in(2,6)";
-        jdbcTemplate.execute(delSql);
+        if (StringUtils.isNotEmpty(ids)) {
+            //删除引用当前模板所有电签信息
+            String delSql = "delete from m_textdict_info where tab_id in(" + ids + ") and type in(2,6)";
+            jdbcTemplate.execute(delSql);
+        }
 
         // 读取html页面信息
         File file1 = ResourceUtil.getFile(wbsTreePrivate.getHtmlUrl());
@@ -428,12 +436,12 @@ public class TextdictInfoController extends BladeController {
         FileUtil.writeToFile(writeFile, doc.html(), Boolean.parseBoolean("UTF-8"));
 
         String str1 = wbsTreePrivate.getHtmlUrl().replace("Desktop//privateUrl", "Desktop/privateUrl");
-
         String replace = str1.replace("\\", "\\\\");
-
-        //修改所有节点的htmlUrl
-        String updateSqlP = "update m_wbs_tree_private set html_url = '" + replace + "' where p_key_id in (" + ids + ")";
-        jdbcTemplate.execute(updateSqlP);
+        if (StringUtils.isNotEmpty(ids)){
+            //修改所有节点的htmlUrl
+            String updateSqlP = "update m_wbs_tree_private set html_url = '" + replace + "' where p_key_id in (" + ids + ")";
+            jdbcTemplate.execute(updateSqlP);
+        }
 
         //修改对应合同段的htmlUrl,当前项目下对应合同段的节点
         List<Long> cIdsList = wbsTreePrivatesEqual.stream().map(WbsTreePrivate::getId).distinct().collect(Collectors.toList());
@@ -441,12 +449,15 @@ public class TextdictInfoController extends BladeController {
                 .eq(WbsTreeContract::getProjectId, wbsTreePrivate.getProjectId())
                 .eq(WbsTreeContract::getExcelId, wbsTreePrivate.getExcelId())
                 .eq(WbsTreeContract::getStatus, 1)
-                .in(WbsTreeContract::getId, cIdsList)
-        ).stream().map(WbsTreeContract::getPKeyId).collect(Collectors.toList());
-
+                .in(WbsTreeContract::getId, cIdsList)).stream().map(WbsTreeContract::getPKeyId).collect(Collectors.toList());
         String cPkeyIdsStr = StringUtils.join(cPkeyIds, ",");
-        String updateSqlC = "update m_wbs_tree_contract set html_url = '" + replace + "' where p_key_id in (" + cPkeyIdsStr + ")";
-        jdbcTemplate.execute(updateSqlC);
+        if (StringUtils.isNotEmpty(cPkeyIdsStr)) {
+            String updateSqlC = "update m_wbs_tree_contract set html_url = '" + replace + "' where p_key_id in (" + cPkeyIdsStr + ")";
+            jdbcTemplate.execute(updateSqlC);
+        }
+
+        bladeRedis.set("save-eVis-lock:" + SecureUtil.getUserId(), "1");
+        bladeRedis.expire("save-eVis-lock:" + SecureUtil.getUserId(), 3);
 
         return R.success("操作成功");
     }
@@ -458,6 +469,7 @@ public class TextdictInfoController extends BladeController {
     @ApiOperationSupport(order = 7)
     @ApiOperation(value = "保存默认值", notes = "保存默认值")
     public R<String> saveDefaulVal(@Valid @RequestBody TextdictBy345VO textdictInfo) throws IOException, ClassNotFoundException {
+
         //当前清表信息
         WbsTreePrivate wbsTreePrivate = wbsTreePrivateMapper.getByPKeyId(textdictInfo.getTableId());
 
@@ -549,10 +561,11 @@ public class TextdictInfoController extends BladeController {
 
         String str1 = wbsTreePrivate.getHtmlUrl().replace("Desktop//privateUrl", "Desktop/privateUrl");
         String replace = str1.replace("\\", "\\\\");
-
-        //修改所有节点的htmlUrl
-        String updateSqlP = "update m_wbs_tree_private set html_url = '" + replace + "' where p_key_id in (" + ids + ")";
-        jdbcTemplate.execute(updateSqlP);
+        if (StringUtils.isNotEmpty(ids)) {
+            //修改所有节点的htmlUrl
+            String updateSqlP = "update m_wbs_tree_private set html_url = '" + replace + "' where p_key_id in (" + ids + ")";
+            jdbcTemplate.execute(updateSqlP);
+        }
 
         //修改对应合同段的htmlUrl,当前项目下对应合同段的节点
         List<Long> cIdsList = wbsTreePrivatesEqual.stream().map(WbsTreePrivate::getId).distinct().collect(Collectors.toList());
@@ -564,8 +577,11 @@ public class TextdictInfoController extends BladeController {
         ).stream().map(WbsTreeContract::getPKeyId).collect(Collectors.toList());
 
         String cPkeyIdsStr = StringUtils.join(cPkeyIds, ",");
-        String updateSqlC = "update m_wbs_tree_contract set html_url = '" + replace + "' where p_key_id in (" + cPkeyIdsStr + ")";
-        jdbcTemplate.execute(updateSqlC);
+        if (StringUtils.isNotEmpty(cPkeyIdsStr)) {
+            String updateSqlC = "update m_wbs_tree_contract set html_url = '" + replace + "' where p_key_id in (" + cPkeyIdsStr + ")";
+            jdbcTemplate.execute(updateSqlC);
+        }
+
 
         return R.success("操作成功");
     }

+ 7 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsFormElementController.java

@@ -220,6 +220,13 @@ public class WbsFormElementController extends BladeController {
     public R<List<WbsNodeTableVO>> searchNodeTables(String nodeId, String excelTabId) {
         List<WbsNodeTableVO> list = wbsFormElementService.searchNodeTables(nodeId, excelTabId);
         if (list.size() > 0) {
+            list.forEach(l->{
+                if (l.getInitTableName() != null){
+                    if (!l.getInitTableName().contains("m_")) {
+                        l.setIsLinkTable(2);
+                    }
+                }
+            });
             return R.data(list, "查询成功");
         }
         return R.fail(200, "操作失败");

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

@@ -317,9 +317,9 @@ public class WbsTreePrivateController extends BladeController {
         List<WbsNodeTableVO> rs = wbsTreePrivateService.selectByNodeTable(parentId, wbsId, projectId);
         if (rs.size() > 0) {
             for (WbsNodeTableVO r : rs) {
-                if (StringUtil.isBlank(r.getInitTableId())){
+                if (StringUtil.isBlank(r.getInitTableId())) {
                     WbsTree wbsTree = wbsTreeService.getById(r.getId());
-                    if (wbsTree != null){
+                    if (wbsTree != null) {
                         r.setInitTableId(wbsTree.getInitTableId().toString());
                         r.setElementTotal(Math.toIntExact(wbsFormElementService.count(
                                 new LambdaQueryWrapper<WbsFormElement>().eq(WbsFormElement::getFId, r.getInitTableId()))));
@@ -609,5 +609,15 @@ public class WbsTreePrivateController extends BladeController {
         return wbsTreePrivateService.getExcelHtml(primaryKeyId);
     }
 
+    /**
+     * 解決项目电签信息重复问题接口
+     * @param pid 当前项目id
+     * @return
+     */
+    @PostMapping("/eVisInfoRepeatDel")
+    public R eVisInfoRepeatDel(String pid) {
+        wbsTreePrivateService.eVisInfoRepeatDel(pid);
+        return R.status(true);
+    }
 
 }

+ 1 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/feign/ArchiveTreeClientImpl.java

@@ -41,6 +41,6 @@ public class ArchiveTreeClientImpl implements ArchiveTreeClient {
 
     @Override
     public R<List<ArchiveTreeVO2>> tree(Long projectId,Integer disPlayTree, Integer nodeType) {
-        return R.data(this.archiveTreeService.tree2(AuthUtil.getTenantId(),projectId, disPlayTree, nodeType));
+        return R.data(this.archiveTreeService.tree2(AuthUtil.getTenantId(),projectId, disPlayTree, nodeType,null,false));
     }
 }

+ 11 - 26
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeContractMapper.java

@@ -19,7 +19,6 @@ package org.springblade.manager.mapper;
 
 import org.apache.ibatis.annotations.Param;
 import org.springblade.manager.entity.ArchiveTreeContract;
-import org.springblade.manager.vo.ArchiveTreeContractAutoRuleVO;
 import org.springblade.manager.vo.ArchiveTreeContractVO;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -44,36 +43,22 @@ public interface ArchiveTreeContractMapper extends BaseMapper<ArchiveTreeContrac
 	 * @return
 	 */
 	List<ArchiveTreeContractVO> selectArchiveTreeContractPage(IPage page, ArchiveTreeContractVO archiveTreeContract);
+	List<ArchiveTreeContractVO> tree(@Param("tenantId") String tenantId, @Param("disPlayTree") Integer disPlayTree, @Param("nodeType") Integer nodeType, @Param("projectId") Long projectId);
+
 	List<ArchiveTreeContractVO> lazyTree(@Param("tenantId") String tenantId, @Param("parentId") Long parentId, @Param("projectId") Long projectId);
 
-	List<ArchiveTreeContractVO> tree(@Param("tenantId") String tenantId, @Param("disPlayTree") Integer disPlayTree, @Param("nodeType") Integer nodeType, @Param("projectId") Long projectId);
 
-	List<ArchiveTreeContractVO2> lazyTree2(@Param("tenantId") String tenantId, @Param("parentId") Long parentId, @Param("projectId") Long projectId);
 
-	List<ArchiveTreeContractVO2> tree2(@Param("tenantId") String tenantId, @Param("disPlayTree") Integer disPlayTree, @Param("nodeType") Integer nodeType, @Param("projectId") Long projectId);
-	/**
-	 * 自动组卷规则设置节点下所有子节点
-	 * @param treeContract
-	 * @return
-	 */
-	int updateAllSonNodeIdsForArchiveAutoRule(@Param("treeContract") ArchiveTreeContract treeContract);
+	List<ArchiveTreeContractVO2> lazyTree2(@Param("tenantId") String tenantId, @Param("parentId") Long parentId, @Param("projectId") Long projectId
+			, @Param("code") String code, @Param("contractId") String contractId);
+
+	List<ArchiveTreeContractVO2> tree2(@Param("tenantId") String tenantId, @Param("disPlayTree") Integer disPlayTree, @Param("nodeType") Integer nodeType, @Param("projectId") Long projectId
+			, @Param("code") String code, @Param("contractId") String contractId);
+
+	List<ArchiveTreeContractVO2> lazyTree3(@Param("tenantId") String tenantId, @Param("parentId") Long parentId, @Param("projectId") Long projectId, @Param("treeCode") Long treeCode);
+
+	List<ArchiveTreeContractVO2> tree3(@Param("tenantId") String tenantId, @Param("disPlayTree") Integer disPlayTree, @Param("nodeType") Integer nodeType, @Param("projectId") Long projectId, @Param("treeCode") Long treeCode);
 
-	/**
-	 * 删除立卷规则设置
-	 * @param treeContract
-	 * @return
-	 */
-	int removeAllSonNodeIdsForArchiveAutoRule_1(@Param("treeContract") ArchiveTreeContract treeContract);
-	int removeAllSonNodeIdsForArchiveAutoRule_2(@Param("treeContract") ArchiveTreeContract treeContract);
-	int removeAllSonNodeIdsForArchiveAutoRule_3(@Param("treeContract") ArchiveTreeContract treeContract);
-	int removeNodeForArchiveAutoRule_Group(@Param("archiveAutoGroupId") Long archiveAutoGroupId);
-	/**
-	 * 查看分类并卷规则-获取大类所有节点
-	 * @param ancestors
-	 * @param groupId
-	 * @return
-	 */
-	List<ArchiveTreeContractAutoRuleVO> getAllSonNodeforGroupView(@Param("ancestors")String ancestors, @Param("groupId")Long groupId);
 
 	int updateBatch(@Param("diffRent") List<String> diffRent);
 

+ 16 - 113
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeContractMapper.xml

@@ -35,6 +35,7 @@
         <result column="ext_type" property="extType"/>
         <result column="ext_id" property="extId"/>
         <result column="exp_data_type" property="expDataType"/>
+        <result column="from_id" property="fromId"/>
         <result column="archive_auto_type" property="archiveAutoType"/>
         <result column="archive_auto_node_id" property="archiveAutoNodeId"/>
         <result column="archive_auto_group_select" property="archiveAutoGroupSelect"/>
@@ -89,20 +90,15 @@
         <result column="ext_type" property="extType"/>
         <result column="ext_id" property="extId"/>
         <result column="exp_data_type" property="expDataType"/>
+        <result column="from_id" property="fromId"/>
         <result column="archive_auto_type" property="archiveAutoType"/>
         <result column="archive_auto_node_id" property="archiveAutoNodeId"/>
-    </resultMap>
-
-    <resultMap id="getAllSonNodeforGroupViewResultMap" type="org.springblade.manager.vo.ArchiveTreeContractAutoRuleVO">
-        <id column="id" property="nodeId"/>
-        <result column="parent_id" property="parentId"/>
-        <result column="node_name" property="nodeName"/>
-        <result column="archive_auto_type" property="archiveAutoType"/>
-        <result column="archive_auto_node_id" property="archiveAutoNodeId"/>
-        <result column="archive_auto_group_id" property="archiveAutoGroupId"/>
         <result column="archive_auto_group_select" property="archiveAutoGroupSelect"/>
+        <result column="archive_auto_group_id" property="archiveAutoGroupId"/>
     </resultMap>
 
+
+
     <select id="lazyTree" resultMap="treeNodeResultMap">
         SELECT
         d.id,
@@ -186,6 +182,8 @@
         d.exp_data_type,
         d.archive_auto_type,
         d.archive_auto_node_id,
+        d.archive_auto_group_select,
+        d.archive_auto_group_id,
         (SELECT CASE WHEN count(1) > 0 THEN 1 ELSE 0 END FROM m_archive_tree_contract WHERE parent_id = d.id and is_deleted = 0 and project_id = #{projectId})
         AS "has_children"
         FROM
@@ -195,6 +193,9 @@
         <if test="tenantId!=null and tenantId!=''">
             AND d.tenant_id = #{tenantId}
         </if>
+        <if test="code!=null and code!=''">
+            AND (d.tree_code = #{code} or d.tree_code = #{contractId} or d.parent_id = 0)
+        </if>
         ORDER BY d.sort
     </select>
 
@@ -218,7 +219,9 @@
         ext_id,
         exp_data_type,
         archive_auto_type,
-        archive_auto_node_id
+        archive_auto_node_id,
+        archive_auto_group_select,
+        archive_auto_group_id
         FROM m_archive_tree_contract
         WHERE is_deleted = 0 and project_id = #{projectId}
         <if test=" tenantId!=null and tenantId!='' ">
@@ -231,114 +234,14 @@
             /*根节点=0 关联电子原生文件=1 数字化上传文件=2*/
             AND node_type in (0,#{nodeType})
         </if>
+        <if test="code!=null and code!=''">
+            AND (d.tree_code = #{code} or d.tree_code = #{contractId} or d.parent_id = 0)
+        </if>
         OR ( parent_id = 0 AND project_id = #{projectId} )
         ORDER BY sort
     </select>
 
-    <update id="updateAllSonNodeIdsForArchiveAutoRule">
 
-        <if test="treeContract.archiveAutoType ==1 ">
-            update m_archive_tree_contract
-            set
-            archive_auto_node_id = #{treeContract.archiveAutoNodeId}
-            where
-            is_deleted = 0 and ancestors like concat('', #{treeContract.ancestors}, '%');
-        </if>
-
-        update m_archive_tree_contract
-        set
-            archive_auto_type= #{treeContract.archiveAutoType},
-            <if test="treeContract.archiveAutoType ==2 ">
-                archive_auto_group_id=#{treeContract.archiveAutoGroupId},
-                archive_auto_group_select=0
-            </if>
-        where
-            is_deleted = 0 and ancestors like concat('', #{treeContract.ancestors}, '%')
-            /*最高并卷规则不能覆盖 分类并卷规则,单独组卷规则*/
-            <if test="treeContract.archiveAutoType ==1 ">
-                and archive_auto_type != 2 and archive_auto_type != 3
-            </if>
-            /*分类并卷规则不能覆盖单独组卷规则*/
-            <if test="treeContract.archiveAutoType ==2 ">
-                and archive_auto_type != 3
-            </if>
-    </update>
-
-    <update id="removeAllSonNodeIdsForArchiveAutoRule_1">
-        update m_archive_tree_contract
-        set
-        archive_auto_node_id = NULL
-        where
-        is_deleted = 0
-        and ancestors like concat('', #{treeContract.ancestors}, '%');
-
-
-        update m_archive_tree_contract
-        set
-            archive_auto_type = NULL
-        where
-        is_deleted = 0
-        and ancestors like concat('', #{treeContract.ancestors}, '%')
-        /*取消规则 只取消规则与自己一致的*/
-        and archive_auto_type = #{treeContract.archiveAutoType} ;
-    </update>
-
-    <update id="removeAllSonNodeIdsForArchiveAutoRule_3">
-        update m_archive_tree_contract
-        set
-            /*取消规则 恢复默认规则 不需要设置为null,如果最高并卷节点取消规则,archive_auto_node_id会为空,相当于无规则不会进到自动组卷流程*/
-            archive_auto_type = 1
-        where
-        is_deleted = 0
-        and ancestors like concat('', #{treeContract.ancestors}, '%')
-        /*取消规则 只取消规则与自己一致的*/
-        and archive_auto_type = #{treeContract.archiveAutoType}
-    </update>
-    <update id="removeAllSonNodeIdsForArchiveAutoRule_2">
-        /*取消单个节点的分类并卷规则*/
-        update m_archive_tree_contract
-        set
-            /*取消规则 恢复默认规则 不需要设置为null,如果最高并卷节点取消规则,archive_auto_node_id会为空,相当于无规则不会进到自动组卷流程*/
-            archive_auto_type = 1 ,
-            archive_auto_group_id = NULL,
-            archive_auto_group_select =NULL
-        where
-          is_deleted = 0
-          and ancestors like concat('', #{treeContract.ancestors}, '%')
-            /*取消规则 只取消规则与自己一致的*/
-          and archive_auto_type = #{treeContract.archiveAutoType}
-    </update>
-
-    <update id="removeNodeForArchiveAutoRule_Group">
-        /**取消同一组的分类并卷规则*/
-        update m_archive_tree_contract
-        set
-            archive_auto_type = 1 ,
-            archive_auto_group_id = NULL,
-            archive_auto_group_select =NULL
-        where
-            is_deleted = 0
-            and archive_auto_group_id = #{archiveAutoGroupId}
-    </update>
-
-    <select id="getAllSonNodeforGroupView" resultMap="getAllSonNodeforGroupViewResultMap">
-        SELECT
-            id,
-            parent_id,
-            node_name,
-            archive_auto_type,
-            archive_auto_node_id,
-            archive_auto_group_id,
-            archive_auto_group_select
-        FROM m_archive_tree_contract
-        where is_deleted = 0
-          and ancestors like concat('', #{ancestors}, '%')
-          and archive_auto_type !=3
-          and id not in (
-                select id from m_archive_tree_contract where archive_auto_type=2 and archive_auto_group_id != #{groupId}
-          )
-        order by ancestors asc,sort asc
-    </select>
 
     <update id="updateBatch">
         UPDATE m_archive_tree_contract

+ 25 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeMapper.java

@@ -2,9 +2,9 @@ package org.springblade.manager.mapper;
 
 import feign.Param;
 import org.springblade.manager.entity.ArchiveTree;
+import org.springblade.manager.vo.ArchiveTreeAutoRuleVO;
 import org.springblade.manager.vo.ArchiveTreeVO;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.springblade.manager.vo.ArchiveTreeVO2;
 
 import java.util.List;
@@ -23,4 +23,28 @@ public interface ArchiveTreeMapper extends BaseMapper<ArchiveTree> {
 
     int updateBatch3();
 
+    /**
+     * 自动组卷规则设置节点下所有子节点
+     * @param tree
+     * @return
+     */
+    int updateAllSonNodeIdsForArchiveAutoRule(@Param("treeContract") ArchiveTree tree);
+
+    /**
+     * 删除立卷规则设置
+     * @param tree
+     * @return
+     */
+    int removeAllSonNodeIdsForArchiveAutoRule_1(@Param("tree") ArchiveTree tree);
+    int removeAllSonNodeIdsForArchiveAutoRule_2(@Param("tree") ArchiveTree tree);
+    int removeAllSonNodeIdsForArchiveAutoRule_3(@Param("tree") ArchiveTree tree);
+    int removeNodeForArchiveAutoRule_Group(@Param("archiveAutoGroupId") Long archiveAutoGroupId);
+    /**
+     * 查看分类并卷规则-获取大类所有节点
+     * @param ancestors
+     * @param groupId
+     * @return
+     */
+    List<ArchiveTreeAutoRuleVO> getAllSonNodeforGroupView(@Param("ancestors")String ancestors, @Param("groupId")Long groupId);
+
 }

+ 118 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeMapper.xml

@@ -94,6 +94,16 @@
         <result column="postType" property="postType"/>
     </resultMap>
 
+    <resultMap id="getAllSonNodeforGroupViewResultMap" type="org.springblade.manager.vo.ArchiveTreeAutoRuleVO">
+        <id column="id" property="nodeId"/>
+        <result column="parent_id" property="parentId"/>
+        <result column="node_name" property="nodeName"/>
+        <result column="archive_auto_type" property="archiveAutoType"/>
+        <result column="archive_auto_node_id" property="archiveAutoNodeId"/>
+        <result column="archive_auto_group_id" property="archiveAutoGroupId"/>
+        <result column="archive_auto_group_select" property="archiveAutoGroupSelect"/>
+    </resultMap>
+
     <update id="updateBatch">
         UPDATE m_archive_tree
         SET is_upload_file_display_configuration_tree = 1
@@ -203,6 +213,7 @@
         d.node_type AS nodeType,
         d.project_type,
         d.storage_type,
+        d.association_type,
         d.ext_type,
         d.ext_id,
         d.exp_data_type,
@@ -242,6 +253,8 @@
         node_type AS nodeType,
         project_type,
         storage_type,
+        association_type,
+        from_id,
         ext_type,
         ext_id,
         exp_data_type,
@@ -268,4 +281,109 @@
         ORDER BY sort
     </select>
 
+    <update id="updateAllSonNodeIdsForArchiveAutoRule">
+
+        <if test="tree.archiveAutoType ==1 ">
+            update m_archive_tree
+            set
+            archive_auto_node_id = #{tree.archiveAutoNodeId}
+            where
+            is_deleted = 0 and ancestors like concat('', #{tree.ancestors}, '%');
+        </if>
+
+        update m_archive_tree
+        set
+        archive_auto_type= #{tree.archiveAutoType},
+        <if test="tree.archiveAutoType ==2 ">
+            archive_auto_group_id=#{tree.archiveAutoGroupId},
+            archive_auto_group_select=0
+        </if>
+        where
+        is_deleted = 0 and ancestors like concat('', #{tree.ancestors}, '%')
+        /*最高并卷规则不能覆盖 分类并卷规则,单独组卷规则*/
+        <if test="tree.archiveAutoType ==1 ">
+            and archive_auto_type != 2 and archive_auto_type != 3
+        </if>
+        /*分类并卷规则不能覆盖单独组卷规则*/
+        <if test="tree.archiveAutoType ==2 ">
+            and archive_auto_type != 3
+        </if>
+    </update>
+
+    <update id="removeAllSonNodeIdsForArchiveAutoRule_1">
+        update m_archive_tree
+        set
+            archive_auto_node_id = NULL
+        where
+            is_deleted = 0
+          and ancestors like concat('', #{tree.ancestors}, '%');
+
+
+        update m_archive_tree
+        set
+            archive_auto_type = NULL
+        where
+            is_deleted = 0
+          and ancestors like concat('', #{tree.ancestors}, '%')
+            /*取消规则 只取消规则与自己一致的*/
+          and archive_auto_type = #{tree.archiveAutoType} ;
+    </update>
+
+    <update id="removeAllSonNodeIdsForArchiveAutoRule_3">
+        update m_archive_tree
+        set
+            /*取消规则 恢复默认规则 不需要设置为null,如果最高并卷节点取消规则,archive_auto_node_id会为空,相当于无规则不会进到自动组卷流程*/
+            archive_auto_type = 1
+        where
+            is_deleted = 0
+          and ancestors like concat('', #{tree.ancestors}, '%')
+            /*取消规则 只取消规则与自己一致的*/
+          and archive_auto_type = #{tree.archiveAutoType}
+    </update>
+    <update id="removeAllSonNodeIdsForArchiveAutoRule_2">
+        /*取消单个节点的分类并卷规则*/
+        update m_archive_tree
+        set
+            /*取消规则 恢复默认规则 不需要设置为null,如果最高并卷节点取消规则,archive_auto_node_id会为空,相当于无规则不会进到自动组卷流程*/
+            archive_auto_type = 1 ,
+            archive_auto_group_id = NULL,
+            archive_auto_group_select =NULL
+        where
+            is_deleted = 0
+          and ancestors like concat('', #{tree.ancestors}, '%')
+            /*取消规则 只取消规则与自己一致的*/
+          and archive_auto_type = #{tree.archiveAutoType}
+    </update>
+
+    <update id="removeNodeForArchiveAutoRule_Group">
+        /**取消同一组的分类并卷规则*/
+        update m_archive_tree
+        set
+            archive_auto_type = 1 ,
+            archive_auto_group_id = NULL,
+            archive_auto_group_select =NULL
+        where
+            is_deleted = 0
+          and archive_auto_group_id = #{archiveAutoGroupId}
+    </update>
+
+    <select id="getAllSonNodeforGroupView" resultMap="getAllSonNodeforGroupViewResultMap">
+        SELECT
+            id,
+            parent_id,
+            node_name,
+            archive_auto_type,
+            archive_auto_node_id,
+            archive_auto_group_id,
+            archive_auto_group_select
+        FROM m_archive_tree
+        where is_deleted = 0
+          and ancestors like concat('', #{ancestors}, '%')
+          and archive_auto_type !=3
+          and id not in (
+                select id from m_archive_tree where archive_auto_type=2 and archive_auto_group_id != #{groupId}
+            )
+        order by ancestors asc,sort asc
+    </select>
+
 </mapper>

+ 2 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreeMapper.xml

@@ -57,6 +57,7 @@
         <result column="value" property="value"/>
         <result column="key" property="key"/>
         <result column="has_children" property="hasChildren"/>
+        <result column="major_data_type" property="majorDataType"/>
         <result column="type" property="type"/>
         <result column="nodeType" property="nodeType"/>
         <result column="wbsType" property="wbsType"/>
@@ -266,6 +267,7 @@
             d.type AS "type",
             d.id AS "value",
             d.id AS "key",
+            d.major_data_type,
             d.node_type AS "nodeType",
             d.is_exist_form AS "isExistForm",
             a.wbs_type AS "wbsType"

+ 5 - 3
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreePrivateMapper.xml

@@ -48,11 +48,12 @@
 
     <resultMap id="WbsTreeResultMap2" type="org.springblade.manager.vo.WbsTreeVO2">
         <id column="id" property="id"/>
-        <result column="parentId" property="parentId"/>
+        <result column="parent_id" property="parentId"/>
         <result column="title" property="title"/>
         <result column="value" property="value"/>
         <result column="key" property="key"/>
         <result column="has_children" property="hasChildren"/>
+        <result column="major_data_type" property="majorDataType"/>
         <result column="type" property="type"/>
         <result column="nodeType" property="nodeType"/>
         <result column="wbsType" property="wbsType"/>
@@ -393,8 +394,8 @@
 
     <select id="tree2" resultMap="WbsTreeResultMap2">
         select
-        id, parent_id, node_name as title,type as "type", id as "value", id as "key" ,
-        node_type AS "nodeType", is_exist_form AS "isExistForm",
+        id, parent_id , node_name as title,type as "type", id as "value", id as "key" ,
+        node_type AS "nodeType", is_exist_form AS "isExistForm",major_data_type,
         wbs_type as "wbsType"
         from m_wbs_tree_private
         where
@@ -403,6 +404,7 @@
         and `type` = 1
         and project_id = #{projectId}
         and wbs_id = #{wbsId}
+        and parent_id is not null
         <if test="wbsType != null and wbsType != ''">
             and wbs_type = #{wbsType}
         </if>

+ 2 - 18
blade-service/blade-manager/src/main/java/org/springblade/manager/service/IArchiveTreeContractService.java

@@ -22,7 +22,6 @@ import org.springblade.manager.dto.ArchiveTreeContractDTO;
 import org.springblade.manager.dto.ArchiveTreeDTO;
 import org.springblade.manager.entity.ArchiveTree;
 import org.springblade.manager.entity.ArchiveTreeContract;
-import org.springblade.manager.vo.ArchiveTreeContractAutoRuleVO;
 import org.springblade.manager.vo.ArchiveTreeContractVO;
 import org.springblade.core.mp.base.BaseService;
 import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -55,9 +54,8 @@ public interface IArchiveTreeContractService extends BaseService<ArchiveTreeCont
 	 * 初始化项目级归档树
 	 * @param tenantId
 	 * @param projectId
-	 * @return
-	 */
-	boolean initTree(String tenantId, Long projectId, List<ArchiveTree> trees);
+	 * @return*/
+
 
 	boolean initTree2(String tenantId, Long projectId);
 
@@ -69,21 +67,7 @@ public interface IArchiveTreeContractService extends BaseService<ArchiveTreeCont
 
 	List<ArchiveTreeContractVO2> tree2(String tenantI,Integer disPlayTree,Integer nodeType,Long projectId);
 
-	/**
-	 *项目级立卷规则新增
-	 * @return
-	 */
-	boolean saveArchiveAutoRule(Integer archiveAutoType,String nodeIds);
-
-
-
-	Map<String,Object> getArchiveAutoRule(Long id);
 
-	/**
-	 *项目级立卷规则更新
-	 * @return
-	 */
-	boolean updateArchiveAutoRule(ArchiveTreeContractAutoRuleMapDTO dto);
 
 	List<ArchiveTreeContract> selectByParentIdOrId(String id);
 

+ 20 - 4
blade-service/blade-manager/src/main/java/org/springblade/manager/service/IArchiveTreeService.java

@@ -1,5 +1,6 @@
 package org.springblade.manager.service;
 
+import org.springblade.manager.dto.ArchiveTreeContractAutoRuleMapDTO;
 import org.springblade.manager.dto.ArchiveTreeDTO;
 import org.springblade.manager.dto.ArchiveTreeSortDTO;
 import org.springblade.manager.entity.ArchiveTree;
@@ -9,6 +10,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.springblade.manager.vo.ArchiveTreeVO2;
 
 import java.util.List;
+import java.util.Map;
 
 public interface IArchiveTreeService extends BaseService<ArchiveTree> {
 
@@ -20,7 +22,7 @@ public interface IArchiveTreeService extends BaseService<ArchiveTree> {
 //	List<ArchiveTreeVO> tree(String tenantI, Integer disPlayTree, Integer nodeType);
 
 	List<ArchiveTreeVO2> lazyTree2(String tenantId, Long projectId, Long parentId, Long extId,Long level);
-	List<ArchiveTreeVO2> tree2(String tenantI, Long projectId, Integer disPlayTree, Integer nodeType);
+	List<ArchiveTreeVO2> tree2(String tenantI, Long projectId, Integer disPlayTree, Integer nodeType,String wbsId,boolean bgetExtNodes);
 
 	List<ArchiveTree> selectByParentIdOrId(String id);
 
@@ -31,10 +33,24 @@ public interface IArchiveTreeService extends BaseService<ArchiveTree> {
 	boolean submitArchiveTreeSort(List<ArchiveTreeSortDTO> listSort);
 
 	List<ArchiveTree> treeList(String tenantId,Long projectId, Integer disPlayTree,Integer nodeType);
-	
 
 
-	boolean saveAechiveAutoRule(Integer archiveAutoType,String nodeIds);
-
 	boolean initArchiveProjectTree(Long projectId);
+
+
+	/**
+	 *项目级立卷规则新增
+	 * @return
+	 */
+	boolean saveArchiveAutoRule(Integer archiveAutoType,String nodeIds);
+
+
+
+	Map<String,Object> getArchiveAutoRule(Long id);
+
+	/**
+	 *项目级立卷规则更新
+	 * @return
+	 */
+	boolean updateArchiveAutoRule(ArchiveTreeContractAutoRuleMapDTO dto);
 }

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

@@ -76,4 +76,6 @@ public interface IWbsTreePrivateService extends BaseService<WbsTreePrivate> {
 
     boolean syncProjectEVisa(String projectId);
 
+    void eVisInfoRepeatDel(String pid);
+
 }

+ 15 - 3
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArTreeContractInitServiceImpl.java

@@ -68,7 +68,17 @@ public class ArTreeContractInitServiceImpl {
         //拷贝第一层
         copyChild(tenantId,projectId,null,archiveTreeContract.getId(),tree.getChildren(),archiveTreeContracts,oldNewMap);
 
-        //拷贝
+        //遍历打
+        for (ArchiveTreeContract ar:archiveTreeContracts) {
+            if (ar.getNodeName().indexOf("施工") >= 0) {
+                ar.setTreeCode("C");
+            }else if (ar.getNodeName().indexOf("监理") >= 0) {
+                ar.setTreeCode("S");
+            }
+        }
+
+
+        //拷贝建设,施工,监理下的树
         for (ArchiveTreeVO2 child: tree.getChildren()) {
             if (child.getTitle().indexOf("施工") >= 0 && bHasCon) {
                 for (ContractInfo contractInfo:contracts) {
@@ -89,11 +99,10 @@ public class ArTreeContractInitServiceImpl {
             }
         }
 
+
         //设置祖先id
         InitAncestors(archiveTreeContracts);
 
-        //todo 复制组卷信息
-
         return;
 
     }
@@ -121,6 +130,8 @@ public class ArTreeContractInitServiceImpl {
         contractNode.setParentId(newRootId);
         contractNode.setProjectId(projectId);
         contractNode.setContractId(contractInfo.getId());
+        //设置权限编码
+        contractNode.setTreeCode(contractInfo.getId().toString());
         contractNode.setIsDeleted(0);
         archiveTreeContracts.add(contractNode);
 
@@ -200,6 +211,7 @@ public class ArTreeContractInitServiceImpl {
 
             if (contractId != null ) {
                 archiveTreeContract.setContractId(contractId);
+                archiveTreeContract.setTreeCode(contractId.toString());
             }
 
             archiveTreeContracts.add(archiveTreeContract);

+ 27 - 278
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeContractServiceImpl.java

@@ -23,6 +23,7 @@ import com.mixsmart.utils.StringUtils;
 import lombok.AllArgsConstructor;
 import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.log.exception.ServiceException;
+import org.springblade.core.secure.BladeUser;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.constant.BladeConstant;
 import org.springblade.core.tool.node.ForestNodeMerger;
@@ -76,95 +77,11 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 	public IPage<ArchiveTreeContractVO> selectArchiveTreeContractPage(IPage<ArchiveTreeContractVO> page, ArchiveTreeContractVO archiveTreeContract) {
 		return page.setRecords(baseMapper.selectArchiveTreeContractPage(page, archiveTreeContract));
 	}
-	@Override
-	public boolean initTree(String tenantId, Long projectId, List<ArchiveTree> trees){
-		boolean bCreate = false;
-		QueryWrapper<ArchiveTreeContract> queryWrapper = new QueryWrapper<>();
-		queryWrapper.eq("parent_id", 0);
-		queryWrapper.eq("ancestors", 0);
-		queryWrapper.eq("tenant_id", tenantId);
-		queryWrapper.eq("project_id", projectId);
-
-		queryWrapper.eq("status", 1);
-		queryWrapper.eq("is_deleted", 0);
-		ArchiveTreeContract archiveTreeContract = archiveTreeContractMapper.selectOne(queryWrapper);
-		if (archiveTreeContract == null) {
-			bCreate = true;
-		}
-
-
-		//todo 同步新增节点
-
-
-
-		//系统模板的
-		List<ArchiveTreeContract> archiveTreeContracts = new ArrayList<>();
-		Map<Long,Long> oldNewMap = new LinkedHashMap<>();
-
-		Map<Long,ArchiveTree> archiveMap = new LinkedHashMap<>();
-
-		for (ArchiveTree archiveTreeVO :trees) {
-			oldNewMap.put(archiveTreeVO.getId(), SnowFlakeUtil.getId());
-			archiveMap.put(archiveTreeVO.getId(), archiveTreeVO);
-		}
-		oldNewMap.put(0L,0L);
-
-		for (ArchiveTree archiveTreeVO :trees) {
-
-			ArchiveTreeContract archiveTree = new ArchiveTreeContract(archiveTreeVO);
-			archiveTree.setId(oldNewMap.get(archiveTreeVO.getId()));
-			archiveTree.setParentId(oldNewMap.get(archiveTreeVO.getParentId()));
-			archiveTree.setCreateUser(AuthUtil.getUserId());
-			archiveTree.setProjectId(projectId);
-
-			String anCenstors = archiveTreeVO.getAncestors();
-			if (StringUtils.isNotEmpty(anCenstors)) {
-				String newAnCenstors = "";
-				String arrAnCenstor[] = anCenstors.split(",");
-				if (arrAnCenstor.length > 0) {
-
-					for (String anCenstor: arrAnCenstor) {
-						Long anCenstorId = Long.parseLong(anCenstor);
-						Long newAnCenstorId = oldNewMap.get(anCenstorId);
-						if (newAnCenstorId!= null) {
-							if (newAnCenstors.length() == 0) {
-								newAnCenstors += newAnCenstorId;
-							}else {
-								newAnCenstors += (","+ newAnCenstorId);
-							}
-						}
-					}
-				}
-				archiveTree.setAncestors(newAnCenstors);
-			}
-
-			archiveTreeContracts.add(archiveTree);
-		}
-
-		//todo 同步合同划分
-
-		//todo 生成动态节点
-		List<ArchiveTreeContractVO2> archiveTreeContractVO2List = this.tree2(tenantId,1,null,projectId);
-
-		//todo 遍历找到关联质检资料的节点,取出合同段
-
-		//todo 处理文件提名
-
-		//todo 立卷规则
-
-		//todo 同步划分树节点到案卷列表
-
-
-
-		this.saveBatch(archiveTreeContracts);
-		return true;
-	}
-
 
 	@Override
 	public boolean initTree2(String tenantId, Long projectId){
 
-		List<ArchiveTreeVO2> tree = archiveTreeService.tree2(AuthUtil.getTenantId(), projectId,null, null);
+		List<ArchiveTreeVO2> tree = archiveTreeService.tree2(AuthUtil.getTenantId(), projectId,null, null,null,false);
 		if (tree == null || tree.size() == 0) {
 			return false;
 		}
@@ -178,13 +95,9 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 
 		arTreeContractInitService.copyTree(tenantId,projectId,projectInfo.getProjectName(),tree.get(0),archiveTreeContracts,contractInfoVOS);
 
-	    //todo 同步动态节点
+	    //todo 同步质检资料动态节点,处理文件提名
 
-		//todo 遍历找到关联质检资料的节点,取出合同段
-
-		//todo 处理文件提名
-
-		//todo 立卷规则
+		//todo 同步立卷规则
 
 		//todo 同步划分树节点到案卷列表
 
@@ -211,201 +124,16 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 		if (AuthUtil.isAdministrator()) {
 			tenantId = StringPool.EMPTY;
 		}
-		return ForestNodeMerger.merge(baseMapper.lazyTree2(tenantId, parentId,projectId));
+		return ForestNodeMerger.merge(baseMapper.lazyTree2(tenantId, parentId,projectId,getAuthCode(),getAuthContractId()));
 	}
 
 	@Override
 	public List<ArchiveTreeContractVO2> tree2(String tenantId, Integer disPlayTree, Integer nodeType, Long projectId) {
-		return ForestNodeMerger.merge(baseMapper.tree2(tenantId, disPlayTree, nodeType,projectId));
-	}
-
-	/**
-	 * 保存组卷规则设置
-	 * @param archiveAutoType
-	 * @param nodeIds
-	 * @return
-	 */
-	@Override
-	public boolean saveArchiveAutoRule(Integer archiveAutoType, String nodeIds) {
-		//项目级不需要考虑是否为wbs节点,已经同步出来了都属于归档树节点,直接按归档树节点处理
-		try{
-			//步骤1保存选择节点的立卷规则。
-			String[] ids = nodeIds.split(",");
-
-			Long archiveAutoGroupId=null;
-
-			//分类并卷规则的需要生成个随机数,作为同一个分类赋值archiveAutoNodeId
-			if(archiveAutoType==2){
-				double ran=(Math.random()*100000000) + 1;
-				archiveAutoGroupId=Long.parseLong(System.currentTimeMillis()+""+ran);
-			}
-			for(String nodeId:ids){
-				long nodeIdLong = Long.parseLong(nodeId);
-				ArchiveTreeContract archiveTreeContract = baseMapper.selectById(nodeIdLong);
-				archiveTreeContract.setArchiveAutoType(archiveAutoType);
-				if(archiveAutoType==1){
-					//最高并卷规则 选择节点的ID
-					archiveTreeContract.setArchiveAutoNodeId(nodeIdLong);
-				}
-				if(archiveAutoType==2){
-					//分类并卷规则 提交都是一个分类类型
-					archiveTreeContract.setArchiveAutoGroupId(archiveAutoGroupId);
-					archiveTreeContract.setArchiveAutoGroupSelect(1);
-				}
-				baseMapper.updateById(archiveTreeContract);
-
-				//步骤2保存选择节点下所有子节点的立卷规则。注意立卷规则优先级覆盖原则。(单独组卷>分类并卷>最高并卷)
-				baseMapper.updateAllSonNodeIdsForArchiveAutoRule(archiveTreeContract);
-			}
-
-			return true;
-
-		}catch (Exception e){
-			e.printStackTrace();
-			return false;
-		}
-	}
 
-
-	/**
-	 * 获取节点规则查看
-	 * @param id
-	 * @return
-	 */
-	@Override
-	public Map<String,Object> getArchiveAutoRule(Long id) {
-
-		Map<String,Object> map= new HashMap<>();
-
-		ArchiveTreeContract archiveTreeContract = baseMapper.selectById(id);
-		Integer archiveAutoType = archiveTreeContract.getArchiveAutoType();
-		if(archiveAutoType!=null){
-			if(archiveAutoType==1){
-				//最高并卷层级 默认规则的节点 显示最高并卷层级节点
-				Long archiveAutoNodeId = archiveTreeContract.getArchiveAutoNodeId();
-				ArchiveTreeContract archiveAutoNode = baseMapper.selectById(archiveAutoNodeId);
-				StringBuffer allName= new StringBuffer();
-				String ancestors = archiveAutoNode.getAncestors();
-				String[] ancestorssplit = ancestors.split(",");//全路径ID
-				for(String pId:ancestorssplit){
-					long pIdLong = Long.parseLong(pId);
-					ArchiveTreeContract pIdNode = baseMapper.selectById(pIdLong);
-					allName.append(pIdNode.getNodeName()+"/");
-				}
-				allName.append(archiveAutoNode.getNodeName());
-				ArchiveTreeContractAutoRuleVO vo= new ArchiveTreeContractAutoRuleVO();
-				vo.setAllName(allName.toString());
-				vo.setNodeId(archiveAutoNode.getId());
-				vo.setArchiveAutoType(archiveAutoType);
-				map.put("type",archiveAutoType);
-				map.put("data",vo);
-				return map;
-			}
-			if(archiveAutoType==2){
-				//分类并卷显示所在大类下树结构,过滤单独规则,其他分类并卷规则组节点 本节点分类组显示打钩
-				//找出当前节点大类
-				String ancestors = archiveTreeContract.getAncestors();
-				String[] ancestorssplit = ancestors.split(",");//全路径ID
-				String nodeAncestors = ancestorssplit[0]+","+ancestorssplit[1]; //大类的ancestors
-				//获取大类下所有节点,过滤单独规则,其他分类并卷规则组节点
-				List<ArchiveTreeContractAutoRuleVO> nodetree = ForestNodeMerger.merge(baseMapper.getAllSonNodeforGroupView(nodeAncestors, archiveTreeContract.getArchiveAutoNodeId()));
-				//获取与当前节点同一分类的节点
-				List<ArchiveTreeContract> listGroup= baseMapper.selectList(Wrappers.<ArchiveTreeContract>lambdaQuery()
-						.eq(ArchiveTreeContract::getArchiveAutoGroupId, archiveTreeContract.getArchiveAutoGroupId())
-						.orderByAsc(ArchiveTreeContract::getSort));
-				StringBuffer nodeSelect = new StringBuffer();
-
-				for(ArchiveTreeContract node:listGroup){
-					nodeSelect.append(node.getId()+",");
-				}
-				map.put("type",archiveAutoType);
-				map.put("tree",nodetree);
-				map.put("data",nodeSelect.toString());
-				return map;
-			}
-			if(archiveAutoType==3){
-				//单独组卷规则 显示当前节点
-				StringBuffer allName= new StringBuffer();
-				String ancestors = archiveTreeContract.getAncestors();
-				String[] ancestorssplit = ancestors.split(",");//全路径ID
-				for(String pId:ancestorssplit){
-					long pIdLong = Long.parseLong(pId);
-					ArchiveTreeContract pIdNode = baseMapper.selectById(pIdLong);
-					allName.append(pIdNode.getNodeName()+"/");
-				}
-				allName.append(archiveTreeContract.getNodeName());
-				ArchiveTreeContractAutoRuleVO vo= new ArchiveTreeContractAutoRuleVO();
-				vo.setAllName(allName.toString());
-				vo.setNodeId(archiveTreeContract.getId());
-				vo.setArchiveAutoType(archiveAutoType);
-				map.put("type",archiveAutoType);
-				map.put("data",vo);
-				return map;
-			}
-		}
-		return map;
+		return ForestNodeMerger.merge(baseMapper.tree2(tenantId, disPlayTree, nodeType,projectId,getAuthCode(),getAuthContractId()));
 	}
 
 
-	public void removeArchiveAutoRule(Long nodeId){
-		ArchiveTreeContract node = baseMapper.selectById(nodeId);
-		Integer archiveAutoType = node.getArchiveAutoType();
-		if(archiveAutoType!=null){
-			//删除默认规则
-			if(archiveAutoType==1){
-				baseMapper.removeAllSonNodeIdsForArchiveAutoRule_1(node);
-			}
-			//删除节点及所有子节点 分类并卷规则
-			if(archiveAutoType==2){
-				//删除规则
-				baseMapper.removeAllSonNodeIdsForArchiveAutoRule_2(node);
-				//TODO 验证节点的父节点是否为分类并卷规则,如是则取消。若无其他兄弟节点,继续往上验证。
-			}
-			//删除节点及所有子节点 单独并卷规则
-			if(archiveAutoType==3){
-				baseMapper.removeAllSonNodeIdsForArchiveAutoRule_3(node);
-			}
-		}
-
-	}
-
-
-	@Override
-	public boolean updateArchiveAutoRule(ArchiveTreeContractAutoRuleMapDTO dto) {
-		//项目级不需要考虑是否为wbs节点,已经同步出来了都属于归档树节点,直接按归档树节点处理
-
-		Integer archiveAutoType = dto.getArchiveAutoType();
-		if(archiveAutoType!=null){
-			if(archiveAutoType==2){
-				Long groupId = dto.getArchiveAutoGroupId();
-				String selectNodeIds = dto.getSelectNodeIds();
-				List<String> selectNodeIdlist = Arrays.asList(selectNodeIds);
-				//先将同一分类的节点删除配置,。
-				baseMapper.removeNodeForArchiveAutoRule_Group(groupId);
-				//然后再按照选择节点保存新的设置
-				for(String nodeId:selectNodeIdlist){
-					long nodeIdLong = Long.parseLong(nodeId);
-					ArchiveTreeContract archiveTreeContract = baseMapper.selectById(nodeIdLong);
-					archiveTreeContract.setArchiveAutoType(archiveAutoType);
-					//分类并卷规则 提交都是一个分类类型
-					archiveTreeContract.setArchiveAutoGroupId(groupId);
-					archiveTreeContract.setArchiveAutoGroupSelect(1);
-					baseMapper.updateById(archiveTreeContract);
-					//保存选择节点下所有子节点的立卷规则。注意立卷规则优先级覆盖原则。(单独组卷>分类并卷>最高并卷)
-					baseMapper.updateAllSonNodeIdsForArchiveAutoRule(archiveTreeContract);
-				}
-			}
-			if(archiveAutoType==1){
-
-			}
-			if(archiveAutoType==3){
-
-			}
-
-		}
-
-		return false;
-	}
 
 	@Override
 	public List<ArchiveTreeContract> selectByParentIdOrId(String id) {
@@ -509,4 +237,25 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 		}
 	}
 
+	/**
+	 * 返回所属的合同段,没有则范围“”
+	 * @return
+	 */
+	public String getAuthContractId() {
+		String contractId ="";
+		BladeUser bladeUser = AuthUtil.getUser();
+
+		return contractId;
+	}
+
+	/**
+	 * 施工则返回“C”,监理则返回“S”,其他返回“”
+	 * @return
+	 */
+	public String getAuthCode() {
+		String code ="";
+		BladeUser bladeUser = AuthUtil.getUser();
+		return code;
+	}
+
 }

+ 232 - 34
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeServiceImpl.java

@@ -11,21 +11,21 @@ import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.constant.BladeConstant;
 
 import org.springblade.core.tool.utils.Func;
+import org.springblade.manager.dto.ArchiveTreeContractAutoRuleMapDTO;
 import org.springblade.manager.dto.ArchiveTreeDTO;
 import org.springblade.manager.dto.ArchiveTreeSortDTO;
 import org.springblade.manager.entity.ArchiveTree;
 import org.springblade.manager.entity.ArchiveTreeContract;
+import org.springblade.manager.entity.ProjectInfo;
+import org.springblade.manager.service.IProjectInfoService;
 import org.springblade.manager.service.IWbsTreePrivateService;
 import org.springblade.manager.service.IWbsTreeService;
 import org.springblade.manager.utils.DiffListUtil;
 import org.springblade.manager.utils.ForestNodeMerger;
-import org.springblade.manager.vo.ArchiveTreeContractVO2;
-import org.springblade.manager.vo.ArchiveTreeVO;
+import org.springblade.manager.vo.*;
 import org.springblade.manager.mapper.ArchiveTreeMapper;
 import org.springblade.manager.service.IArchiveTreeService;
 import org.springblade.core.mp.base.BaseServiceImpl;
-import org.springblade.manager.vo.ArchiveTreeVO2;
-import org.springblade.manager.vo.WbsTreeVO2;
 import org.springframework.stereotype.Service;
 
 import java.util.*;
@@ -39,6 +39,7 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
     private final ArTreeContractInitServiceImpl archiveTreeContractInitService;
     private final IWbsTreeService wbsTreeService;
     private final IWbsTreePrivateService wbsTreePrivateService;
+    private final IProjectInfoService projectInfoService;
 
     @Override
     public boolean initArchiveTree() {
@@ -128,6 +129,8 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
             archiveTrees.add(archiveTree);
         }
 
+        //todo 同步立卷规则
+
         this.saveBatch(archiveTrees);
 
         return true;
@@ -144,7 +147,7 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
             throw new ServiceException("根节点已存在,请先删除后再进行初始化");
         }
 
-        List<ArchiveTreeVO2> sysTrees = this.tree2(AuthUtil.getTenantId(), projectId,null, null);
+        List<ArchiveTreeVO2> sysTrees = this.tree2(AuthUtil.getTenantId(), projectId,null, null,null,false);
         if (sysTrees == null || sysTrees.size() == 0) {
             return false;
         }
@@ -227,24 +230,36 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
 //    }
 
     @Override
-    public List<ArchiveTreeVO2> tree2(String tenantId,Long projectId, Integer disPlayTree, Integer nodeType) {
+    public List<ArchiveTreeVO2> tree2(String tenantId,Long projectId, Integer disPlayTree, Integer nodeType,String wbsId,boolean bgetExtNodes) {
         List<ArchiveTreeVO2> archiveTreeVOList = baseMapper.tree2(tenantId, projectId,disPlayTree, nodeType);
         List<ArchiveTreeVO2> treeVO2s = ForestNodeMerger.merge(archiveTreeVOList);
         //todo 遍历树,找到质检节点,调用getWbsArchiveTree,根据关联层级,拼接上去
-        //待传入wbsId,把child 加入ar的childred
-//        String wbsId = "";
-//        if (com.mixsmart.utils.StringUtils.isNotEmpty(wbsId)) {
-//            for (ArchiveTreeVO2 ar : archiveTreeVOList) {
-//                if (ar.getAssociationType() == 1) {
-//                    ArchiveTreeVO2 child = getWbsArchiveTree(tenantId,projectId,ar.getId(),
-//                            wbsId,"1",Long.parseLong(ar.getDisplayHierarchy()));
-//                    if (child!= null) {
-//
-//                    }
-//                }
-//            }
-//        }
+        //是否获取扩展的wbs节点
+        if (StringUtils.isEmpty(wbsId) && projectId != 0 && bgetExtNodes) {
+            ProjectInfo projectInfo = projectInfoService.getOne(projectId);
+            if (projectInfo!= null) {
+                Long lWbsId = projectInfo.getReferenceWbsTemplateId();
+                if (lWbsId != null) {
+                    wbsId = projectInfo.getReferenceWbsTemplateId().toString();
+                }
+            }
+        }
 
+        if (StringUtils.isNotEmpty(wbsId)) {
+            for (ArchiveTreeVO2 ar : archiveTreeVOList) {
+                //关联质检资料
+                if (ar.getAssociationType()!= null
+                        &&  ar.getAssociationType() == 1
+                        && ar.getDisplayHierarchy() != null ) {
+                    ArchiveTreeVO2 child = getWbsArchiveTree(tenantId,projectId,ar.getId(),
+                            wbsId,"1",Long.parseLong(ar.getDisplayHierarchy()));
+
+                    if (child!= null) {
+                        ar.getChildren().add(child);
+                    }
+                }
+            }
+        }
         return treeVO2s;
     }
 
@@ -377,16 +392,25 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
             wbsTreeVO2s = wbsTreePrivateService.tree2(wbsId, projectId.toString());
         }
 
+        List<WbsTreeVO2> wbsTreeVO2List = new ArrayList<>();
+        ForestNodeMerger.getTreeList(wbsTreeVO2s.get(0),wbsTreeVO2List);
+
         //遍历构建
-        for (WbsTreeVO2 wbsTreeVO2:wbsTreeVO2s) {
+        for (WbsTreeVO2 wbsTreeVO2:wbsTreeVO2List) {
             //只展示指定层级之上的
+            if (wbsTreeVO2.getMajorDataType() != null ) {
+                if (wbsTreeVO2.getMajorDataType() == 1
+                    || wbsTreeVO2.getMajorDataType() == 2
+                    || wbsTreeVO2.getMajorDataType() == 3){
+                    continue;
+                }
+            }
             if (wbsTreeVO2.getNodeType() > level){
                 continue;
             }
-
             ArchiveTreeVO2 archiveTree = new ArchiveTreeVO2();
-            archiveTree.setId(SnowFlakeUtil.getId());
-            archiveTree.setParentId(parentId);
+            archiveTree.setId(wbsTreeVO2.getId());
+            archiveTree.setParentId(wbsTreeVO2.getParentId());
             archiveTree.setTitle(wbsTreeVO2.getTitle());
             archiveTree.setExtId(wbsTreeVO2.getId());
             archiveTree.setDisplayHierarchy(level.toString());
@@ -402,18 +426,192 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
     }
 
 
+    /**
+     * 保存组卷规则设置
+     * @param archiveAutoType
+     * @param nodeIds
+     * @return
+     */
     @Override
-    public boolean saveAechiveAutoRule(Integer archiveAutoType, String nodeIds) {
-        //步骤1:判断选择节点是否为wbs节点。
-        //步骤2:归档树原始节点,
-            //2.1保存选择节点的立卷规则。
-                //2.1.1 最高并卷规则的需要将选择节点的ID赋值archiveAutoNodeId
-                //2.1.2 分类并卷规则的需要生成个随机数,作为同一个分类赋值archiveAutoNodeId
-            //2.2保存选择节点下所有子节点的立卷规则。注意立卷规则优先级覆盖原则。(单独组卷>分类并卷>最高并卷)
-        //步骤3:归档树关联wbs节点
-            //TODO 关联wbs节点的立卷规则保存,涉及到能否正确同步出来。再议
-            //3.1保存选择节点的立卷规则。
-            //3.2保存选择节点下所有子节点的立卷规则。注意立卷规则优先级覆盖原则。(单独组卷>分类并卷>最高并卷)
+    public boolean saveArchiveAutoRule(Integer archiveAutoType, String nodeIds) {
+        //项目级不需要考虑是否为wbs节点,已经同步出来了都属于归档树节点,直接按归档树节点处理
+        try{
+            //步骤1保存选择节点的立卷规则。
+            String[] ids = nodeIds.split(",");
+
+            Long archiveAutoGroupId=null;
+
+            //分类并卷规则的需要生成个随机数,作为同一个分类赋值archiveAutoNodeId
+            if(archiveAutoType==2){
+                double ran=(Math.random()*100000000) + 1;
+                archiveAutoGroupId=Long.parseLong(System.currentTimeMillis()+""+ran);
+            }
+            for(String nodeId:ids){
+                long nodeIdLong = Long.parseLong(nodeId);
+                ArchiveTree archiveTree = baseMapper.selectById(nodeIdLong);
+                archiveTree.setArchiveAutoType(archiveAutoType);
+                if(archiveAutoType==1){
+                    //最高并卷规则 选择节点的ID
+                    archiveTree.setArchiveAutoNodeId(nodeIdLong);
+                }
+                if(archiveAutoType==2){
+                    //分类并卷规则 提交都是一个分类类型
+                    archiveTree.setArchiveAutoGroupId(archiveAutoGroupId);
+                    archiveTree.setArchiveAutoGroupSelect(1);
+                }
+                baseMapper.updateById(archiveTree);
+
+                //步骤2保存选择节点下所有子节点的立卷规则。注意立卷规则优先级覆盖原则。(单独组卷>分类并卷>最高并卷)
+                baseMapper.updateAllSonNodeIdsForArchiveAutoRule(archiveTree);
+            }
+
+            return true;
+
+        }catch (Exception e){
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+
+    /**
+     * 获取节点规则查看
+     * @param id
+     * @return
+     */
+    @Override
+    public Map<String,Object> getArchiveAutoRule(Long id) {
+
+        Map<String,Object> map= new HashMap<>();
+
+        ArchiveTree archiveTree = baseMapper.selectById(id);
+        Integer archiveAutoType = archiveTree.getArchiveAutoType();
+        if(archiveAutoType!=null){
+            if(archiveAutoType==1){
+                //最高并卷层级 默认规则的节点 显示最高并卷层级节点
+                Long archiveAutoNodeId = archiveTree.getArchiveAutoNodeId();
+                ArchiveTree archiveAutoNode = baseMapper.selectById(archiveAutoNodeId);
+                StringBuffer allName= new StringBuffer();
+                String ancestors = archiveAutoNode.getAncestors();
+                String[] ancestorssplit = ancestors.split(",");//全路径ID
+                for(String pId:ancestorssplit){
+                    long pIdLong = Long.parseLong(pId);
+                    ArchiveTree pIdNode = baseMapper.selectById(pIdLong);
+                    allName.append(pIdNode.getNodeName()+"/");
+                }
+                allName.append(archiveAutoNode.getNodeName());
+                ArchiveTreeAutoRuleVO vo= new ArchiveTreeAutoRuleVO();
+                vo.setAllName(allName.toString());
+                vo.setNodeId(archiveAutoNode.getId());
+                vo.setArchiveAutoType(archiveAutoType);
+                map.put("type",archiveAutoType);
+                map.put("data",vo);
+                return map;
+            }
+            if(archiveAutoType==2){
+                //分类并卷显示所在大类下树结构,过滤单独规则,其他分类并卷规则组节点 本节点分类组显示打钩
+                //找出当前节点大类
+                String ancestors = archiveTree.getAncestors();
+                String[] ancestorssplit = ancestors.split(",");//全路径ID
+                String nodeAncestors = ancestorssplit[0]+","+ancestorssplit[1]; //大类的ancestors
+                //获取大类下所有节点,过滤单独规则,其他分类并卷规则组节点
+                List<ArchiveTreeAutoRuleVO> nodetree = ForestNodeMerger.merge(baseMapper.getAllSonNodeforGroupView(nodeAncestors, archiveTree.getArchiveAutoNodeId()));
+                //获取与当前节点同一分类的节点
+                List<ArchiveTree> listGroup= baseMapper.selectList(Wrappers.<ArchiveTree>lambdaQuery()
+                        .eq(ArchiveTree::getArchiveAutoGroupId, archiveTree.getArchiveAutoGroupId())
+                        .orderByAsc(ArchiveTree::getSort));
+                StringBuffer nodeSelect = new StringBuffer();
+
+                for(ArchiveTree node:listGroup){
+                    nodeSelect.append(node.getId()+",");
+                }
+                map.put("type",archiveAutoType);
+                map.put("tree",nodetree);
+                map.put("data",nodeSelect.toString());
+                return map;
+            }
+            if(archiveAutoType==3){
+                //单独组卷规则 显示当前节点
+                StringBuffer allName= new StringBuffer();
+                String ancestors = archiveTree.getAncestors();
+                String[] ancestorssplit = ancestors.split(",");//全路径ID
+                for(String pId:ancestorssplit){
+                    long pIdLong = Long.parseLong(pId);
+                    ArchiveTree pIdNode = baseMapper.selectById(pIdLong);
+                    allName.append(pIdNode.getNodeName()+"/");
+                }
+                allName.append(archiveTree.getNodeName());
+                ArchiveTreeAutoRuleVO vo= new ArchiveTreeAutoRuleVO();
+                vo.setAllName(allName.toString());
+                vo.setNodeId(archiveTree.getId());
+                vo.setArchiveAutoType(archiveAutoType);
+                map.put("type",archiveAutoType);
+                map.put("data",vo);
+                return map;
+            }
+        }
+        return map;
+    }
+
+
+    public void removeArchiveAutoRule(Long nodeId){
+        ArchiveTree node = baseMapper.selectById(nodeId);
+        Integer archiveAutoType = node.getArchiveAutoType();
+        if(archiveAutoType!=null){
+            //删除默认规则
+            if(archiveAutoType==1){
+                baseMapper.removeAllSonNodeIdsForArchiveAutoRule_1(node);
+            }
+            //删除节点及所有子节点 分类并卷规则
+            if(archiveAutoType==2){
+                //删除规则
+                baseMapper.removeAllSonNodeIdsForArchiveAutoRule_2(node);
+                //TODO 验证节点的父节点是否为分类并卷规则,如是则取消。若无其他兄弟节点,继续往上验证。
+            }
+            //删除节点及所有子节点 单独并卷规则
+            if(archiveAutoType==3){
+                baseMapper.removeAllSonNodeIdsForArchiveAutoRule_3(node);
+            }
+        }
+
+    }
+
+
+    @Override
+    public boolean updateArchiveAutoRule(ArchiveTreeContractAutoRuleMapDTO dto) {
+        //项目级不需要考虑是否为wbs节点,已经同步出来了都属于归档树节点,直接按归档树节点处理
+
+        Integer archiveAutoType = dto.getArchiveAutoType();
+        if(archiveAutoType!=null){
+            if(archiveAutoType==2){
+                Long groupId = dto.getArchiveAutoGroupId();
+                String selectNodeIds = dto.getSelectNodeIds();
+                List<String> selectNodeIdlist = Arrays.asList(selectNodeIds);
+                //先将同一分类的节点删除配置,。
+                baseMapper.removeNodeForArchiveAutoRule_Group(groupId);
+                //然后再按照选择节点保存新的设置
+                for(String nodeId:selectNodeIdlist){
+                    long nodeIdLong = Long.parseLong(nodeId);
+                    ArchiveTree archiveTree = baseMapper.selectById(nodeIdLong);
+                    archiveTree.setArchiveAutoType(archiveAutoType);
+                    //分类并卷规则 提交都是一个分类类型
+                    archiveTree.setArchiveAutoGroupId(groupId);
+                    archiveTree.setArchiveAutoGroupSelect(1);
+                    baseMapper.updateById(archiveTree);
+                    //保存选择节点下所有子节点的立卷规则。注意立卷规则优先级覆盖原则。(单独组卷>分类并卷>最高并卷)
+                    baseMapper.updateAllSonNodeIdsForArchiveAutoRule(archiveTree);
+                }
+            }
+            if(archiveAutoType==1){
+
+            }
+            if(archiveAutoType==3){
+
+            }
+
+        }
+
         return false;
     }
+
 }

+ 87 - 31
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreePrivateServiceImpl.java

@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.google.common.collect.Lists;
 import lombok.AllArgsConstructor;
 import org.jsoup.Jsoup;
 import org.jsoup.nodes.Document;
@@ -20,7 +21,6 @@ import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.constant.BladeConstant;
 import org.springblade.core.tool.node.ForestNodeMerger;
 import org.springblade.core.tool.utils.*;
-import org.springblade.manager.dto.WbsTreeContractDTO;
 import org.springblade.manager.dto.WbsTreePrivateDTO2;
 import org.springblade.manager.dto.WbsTreePrivateDTO3;
 import org.springblade.manager.entity.*;
@@ -34,10 +34,16 @@ import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import javax.annotation.Resource;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.util.*;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Future;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 @Service
@@ -46,8 +52,6 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
 
     private final WbsTreeContractMapper wbsTreeContractMapper;
     private final WbsTreeContractServiceImpl wbsTreeContractService;
-
-    // 表单主表信息
     private final ITableInfoService tableInfoService;
     private final WbsTreeMapper wbsTreeMapper;
     private final ContractInfoMapper contractInfoMapper;
@@ -59,6 +63,9 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
     private final JdbcTemplate jdbcTemplate;
     private final TextdictInfoServiceImpl textDictInfoService;
 
+    @Resource(name = "taskExecutor1")
+    private ThreadPoolExecutor executor;
+
     @Override
     public List<WbsTreePrivateVO> tree(String wbsId, String projectId) {
         WbsInfo wbsInfo = wbsInfoMapper.selectOne(Wrappers.<WbsInfo>query().lambda().eq(WbsInfo::getId, wbsId));
@@ -1631,34 +1638,41 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
                 WbsTreePrivate oneRecordRoot = this.getOne(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getPKeyId, projectInfo.getReferenceWbsTemplateId()));
 
                 //获取当前项目下节点树所有节点、表、独立表
-                List<WbsTreePrivate> wbsTreePrivatesNodeAndTabNow = wbsTreePrivateMapper.selectList(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getProjectId, projectId).eq(WbsTreePrivate::getWbsType, 1).eq(WbsTreePrivate::getStatus, 1).and(obj -> obj.eq(WbsTreePrivate::getType, 1).or().eq(WbsTreePrivate::getType, 2)));
-                List<WbsTreePrivate> wbsTreePrivatesTableDL = wbsTreePrivateMapper.selectList(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getProjectId, projectId).eq(WbsTreePrivate::getType, 10).eq(WbsTreePrivate::getParentId, -10).eq(WbsTreePrivate::getStatus, 1));
-                wbsTreePrivatesNodeAndTabNow.addAll(wbsTreePrivatesTableDL);
-                //获取当前项目节点树的所有id
-                List<Long> saveIds = wbsTreePrivatesNodeAndTabNow.stream().filter(f -> f.getType().equals(1)).collect(Collectors.toList()).stream().map(WbsTreePrivate::getId).collect(Collectors.toList());
+                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));
+                List<WbsTreePrivate> wbsTreePrivatesTableDL = wbsTreePrivatesNodeAndTabNow.stream().filter(f -> f.getType().equals(10) && f.getParentId().equals(-10L)).collect(Collectors.toList());
+
+                //获取当前项目节点树
+                Map<Long, WbsTreePrivate> nowNodeTreeAll = wbsTreePrivatesNodeAndTabNow.stream().filter(f -> f.getType().equals(1)).collect(Collectors.toList()).stream()
+                        .collect(Collectors.toMap(WbsTreePrivate::getId, Function.identity()));
 
                 //获取当前引用的节点树下所有节点、表、独立表
-                List<WbsTreePrivate> wbsTreePrivatesNodeAndTab = wbsTreePrivateMapper.selectList(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getProjectId, oneRecordRoot.getProjectId()).eq(WbsTreePrivate::getWbsId, oneRecordRoot.getWbsId()).eq(WbsTreePrivate::getStatus, 1).and(obj -> obj.eq(WbsTreePrivate::getType, 1).or().eq(WbsTreePrivate::getType, 2)));
-                List<WbsTreePrivate> wbsTreePrivatesTableDLOld = wbsTreePrivateMapper.selectList(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getProjectId, oneRecordRoot.getProjectId()).eq(WbsTreePrivate::getType, 10).eq(WbsTreePrivate::getStatus, 1).eq(WbsTreePrivate::getParentId, -10).isNull(WbsTreePrivate::getWbsId));
-                wbsTreePrivatesNodeAndTab.addAll(wbsTreePrivatesTableDLOld);
+                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<Long> pIdsDL = wbsTreePrivatesNodeAndTab.stream().filter(f -> f.getType().equals(10) || f.getType().equals(2)).collect(Collectors.toList()).stream().map(WbsTreePrivate::getPKeyId).collect(Collectors.toList());
-                String sql = "select * from m_textdict_info where tab_id in (" + org.apache.commons.lang.StringUtils.join(pIdsDL, ",") + ") and is_deleted = 0";
-                List<TextdictInfo> textDictInfosAll = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(TextdictInfo.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<String, List<TextdictInfo>> collect3 = textDictInfosAll.stream().collect(Collectors.groupingBy(TextdictInfo::getTabId));
 
                 //构造原始电签信息
-                for (WbsTreePrivate wbsTreePrivate : wbsTreePrivatesNodeAndTab) {
+                for (WbsTreePrivate wbsTreePrivate : collect1) {
                     if (wbsTreePrivate.getType() == 2) {
-                        for (Long id : saveIds) {
-                            if (id.equals(wbsTreePrivate.getParentId())) {
-                                //根据元素表pKeyId,获取电签位置匹配信息、编辑默认信息
-                                List<TextdictInfo> textDictInfos = textDictInfosAll.stream().filter(f ->
-                                        ObjectUtils.isNotEmpty(f.getTabId()) && f.getTabId().equals(String.valueOf(wbsTreePrivate.getPKeyId()))).collect(Collectors.toList());
-                                if (textDictInfos.size() > 0) {
-                                    textDictInfoData.put(wbsTreePrivate.getPKeyId() + "," + wbsTreePrivate.getId(), textDictInfos);
-                                }
-                            }
+                        WbsTreePrivate obj = nowNodeTreeAll.get(wbsTreePrivate.getParentId());
+                        assert obj != null;
+                        List<TextdictInfo> textDictInfos = collect3.get(String.valueOf(wbsTreePrivate.getPKeyId()));
+                        if (textDictInfos != null && textDictInfos.size() > 0) {
+                            textDictInfoData.put(wbsTreePrivate.getPKeyId() + "," + wbsTreePrivate.getId(), textDictInfos);
                         }
                     }
 
@@ -1667,9 +1681,8 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
                         List<WbsTreePrivate> collect = wbsTreePrivatesTableDL.stream().filter(f -> f.getId().equals(wbsTreePrivate.getId())).collect(Collectors.toList());
                         if (collect.size() == 0) {
                             //根据元素表pKeyId,获取电签位置匹配信息、编辑默认信息
-                            List<TextdictInfo> textDictInfos = textDictInfosAll.stream().filter(f -> ObjectUtils.isNotEmpty(f.getTabId())
-                                    && f.getTabId().equals(String.valueOf(wbsTreePrivate.getPKeyId()))).collect(Collectors.toList());
-                            if (textDictInfos.size() > 0) {
+                            List<TextdictInfo> textDictInfos = collect3.get(String.valueOf(wbsTreePrivate.getPKeyId()));
+                            if (textDictInfos != null && textDictInfos.size() > 0) {
                                 textDictInfoData.put(wbsTreePrivate.getPKeyId() + "," + wbsTreePrivate.getId(), textDictInfos);
                             }
                         }
@@ -1686,7 +1699,7 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
                             for (TextdictInfo textdictInfo : v) {
                                 TextdictInfo obj = BeanUtil.copyProperties(textdictInfo, TextdictInfo.class);
                                 assert obj != null;
-                                obj.setTabId(String.valueOf(tree.getPKeyId()));
+                                obj.setTabId(String.valueOf(tree.getPKeyId())); //重新赋值绑定到对应的表上
                                 obj.setId(SnowFlakeUtil.getId());
                                 insertData.add(obj);
                             }
@@ -1695,8 +1708,10 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
                 });
 
                 //去重,删除当前表的电签信息
-                for (TextdictInfo insertDatum : insertData) {
-                    String delSql = "delete from m_textdict_info where tab_id = " + insertDatum.getTabId();
+                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);
                 }
 
@@ -1705,12 +1720,53 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
 
                 return true;
             } else {
-                throw new ServiceException("未获取到项目的关联的私有wbs树信息");
+                throw new ServiceException("当前项目关联的wbs树不是私有关联");
             }
         }
         return false;
     }
 
+    @Override
+    public void eVisInfoRepeatDel(String pid) {
+        //获取当前项目下节点树所有节点、表、独立表
+        String sqlNodeTreeAllNow = "SELECT p_key_id,id,type,parent_id,html_url FROM m_wbs_tree_private WHERE project_id = " + pid + " 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));
+
+        //获取当前对应电签位置配置信息
+        List<WbsTreePrivate> collect1 = wbsTreePrivatesNodeAndTabNow.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,tab_id,col_key,col_name,sig_role_id,sig_role_name 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);
+        }
+
+        //去重,解决之前由于删除接口重复保存,导致数据重复问题
+        List<TextdictInfo> list = textDictInfosAll.stream().collect(
+                Collectors.collectingAndThen(
+                        Collectors.toCollection(() -> new TreeSet<>(
+                                Comparator.comparing(o -> o.getTabId() + ";" + o.getSigRoleId() + ";" + o.getColKey() + ";" + o.getSigRoleName() + ";" + o.getColName()
+                                )
+                        )), ArrayList::new));
+
+        List<Long> idsAll = textDictInfosAll.stream().map(TextdictInfo::getId).collect(Collectors.toList());
+
+        List<Long> saveIds = list.stream().map(TextdictInfo::getId).collect(Collectors.toList());
+
+        List<Long> delIds = idsAll.stream().filter(f -> !saveIds.contains(f)).collect(Collectors.toList());
+
+        List<List<Long>> partition1 = Lists.partition(delIds, 1000);
+        for (List<Long> ids : partition1) {
+            String delSql = "delete from m_textdict_info where id in (" + org.apache.commons.lang.StringUtils.join(ids, ",") + ")";
+            jdbcTemplate.execute(delSql);
+        }
+
+    }
+
     @Transactional(rollbackFor = Exception.class)
     public boolean insertBatch(Collection<WbsTreePrivate> entityList, int batchSize) {
         try {

+ 46 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/utils/AsyncConfigurer.java

@@ -0,0 +1,46 @@
+package org.springblade.manager.utils;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableAsync;
+
+import java.util.concurrent.*;
+
+@Slf4j
+@Configuration
+@EnableAsync
+public class AsyncConfigurer {
+
+    /**
+     * cpu 核心数量
+     */
+    public static final int cpuNum = Runtime.getRuntime().availableProcessors();
+
+    /**
+     * 线程池配置
+     *
+     * @return
+     */
+    @Bean("taskExecutor1")
+    public ThreadPoolExecutor getAsyncExecutor() {
+        return new ThreadPoolMonitor(cpuNum
+                , cpuNum * 2
+                , 60
+                , TimeUnit.SECONDS
+                , new LinkedBlockingQueue<>(2000)
+                , new ThreadPoolExecutor.DiscardOldestPolicy(), "manager-thread-pool");
+    }
+
+    /**
+     * 线程池配置
+     *
+     * @return
+     */
+    @Bean("singleExecutor")
+    public ExecutorService getSingleExecutor() {
+        log.info("线程池初始化......");
+        return Executors.newSingleThreadExecutor();
+    }
+
+}

+ 1 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/utils/ForestNodeMerger.java

@@ -9,7 +9,7 @@ public class ForestNodeMerger {
     public static <T extends INode<T>> List<T> merge(List<T> items) {
         ForestNodeManager<T> forestNodeManager = new ForestNodeManager(items);
         items.forEach((forestNode) -> {
-            if (forestNode.getParentId() != 0L) {
+            if (forestNode.getParentId()!= null && forestNode.getParentId() != 0L) {
                 INode<T> node = forestNodeManager.getTreeNodeAt(forestNode.getParentId());
                 if (node != null) {
                     node.getChildren().add(forestNode);

+ 191 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/utils/ThreadPoolMonitor.java

@@ -0,0 +1,191 @@
+package org.springblade.manager.utils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+public class ThreadPoolMonitor extends ThreadPoolExecutor {
+    private final Logger logger = LoggerFactory.getLogger(getClass());
+
+    /**
+     * ActiveCount
+     */
+    int ac = 0;
+
+    /**
+     * 当前所有线程消耗的时间
+     */
+    private AtomicLong totalCostTime = new AtomicLong();
+
+    /**
+     * 当前执行的线程总数
+     */
+    private AtomicLong totalTasks = new AtomicLong();
+
+    /**
+     * 线程池名称
+     */
+    private String poolName;
+
+    /**
+     * 最短 执行时间
+     */
+    private long minCostTime;
+
+    /**
+     * 最长执行时间
+     */
+    private long maxCostTime;
+
+
+    /**
+     * 保存任务开始执行的时间
+     */
+    private ThreadLocal<Long> startTime = new ThreadLocal<>();
+
+    public ThreadPoolMonitor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
+                             TimeUnit unit, BlockingQueue<Runnable> workQueue, String poolName) {
+        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
+                Executors.defaultThreadFactory(), poolName);
+    }
+
+    public ThreadPoolMonitor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
+                             TimeUnit unit, BlockingQueue<Runnable> workQueue,
+                             ThreadFactory threadFactory, String poolName) {
+        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
+        this.poolName = poolName;
+    }
+
+    public ThreadPoolMonitor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler, String poolName) {
+        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
+        this.poolName = poolName;
+    }
+
+    /**
+     * 线程池延迟关闭时(等待线程池里的任务都执行完毕),统计线程池情况
+     */
+    @Override
+    public void shutdown() {
+        // 统计已执行任务、正在执行任务、未执行任务数量
+        logger.info("{} Going to shutdown. Executed tasks: {}, Running tasks: {}, Pending tasks: {}",
+                this.poolName, this.getCompletedTaskCount(), this.getActiveCount(), this.getQueue().size());
+        super.shutdown();
+    }
+
+    @Override
+    public List<Runnable> shutdownNow() {
+        // 统计已执行任务、正在执行任务、未执行任务数量
+        logger.info("{} Going to immediately shutdown. Executed tasks: {}, Running tasks: {}, Pending tasks: {}",
+                this.poolName, this.getCompletedTaskCount(), this.getActiveCount(), this.getQueue().size());
+        return super.shutdownNow();
+    }
+
+    /**
+     * 任务执行之前,记录任务开始时间
+     */
+    @Override
+    protected void beforeExecute(Thread t, Runnable r) {
+        logger.info("{}-before: " +
+                        " PoolSize: {}, CorePoolSize: {}, ActiveCount: {}, " +
+                        "Completed: {}, Task: {}, Queue: {}, LargestPoolSize: {}, " +
+                        "MaximumPoolSize: {},  KeepAliveTime: {}, isShutdown: {}, isTerminated: {}",
+                this.poolName,
+                this.getPoolSize(), this.getCorePoolSize(), super.getActiveCount(),
+                this.getCompletedTaskCount(), this.getTaskCount(), this.getQueue().size(), this.getLargestPoolSize(),
+                this.getMaximumPoolSize(), this.getKeepAliveTime(TimeUnit.MILLISECONDS), this.isShutdown(), this.isTerminated());
+        startTime.set(System.currentTimeMillis());
+    }
+
+    /**
+     * 任务执行之后,计算任务结束时间
+     */
+    @Override
+    protected void afterExecute(Runnable r, Throwable t) {
+        long costTime = System.currentTimeMillis() - startTime.get();
+        startTime.remove();  //删除,避免占用太多内存
+        //设置最大最小执行时间
+        maxCostTime = maxCostTime > costTime ? maxCostTime : costTime;
+        if (totalTasks.get() == 0) {
+            minCostTime = costTime;
+        }
+        minCostTime = minCostTime < costTime ? minCostTime : costTime;
+        totalCostTime.addAndGet(costTime);
+        totalTasks.incrementAndGet();
+        ac = this.getActiveCount();  //获取ActiveCount的值
+
+        logger.info("{}-after: " +
+                        "Duration: {} ms, PoolSize: {}, CorePoolSize: {}, ActiveCount: {}, " +
+                        "Completed: {}, Task: {}, Queue: {}, LargestPoolSize: {}, " +
+                        "MaximumPoolSize: {},  KeepAliveTime: {}, isShutdown: {}, isTerminated: {}",
+                this.poolName,
+                costTime, this.getPoolSize(), this.getCorePoolSize(), super.getActiveCount(),
+                this.getCompletedTaskCount(), this.getTaskCount(), this.getQueue().size(), this.getLargestPoolSize(),
+                this.getMaximumPoolSize(), this.getKeepAliveTime(TimeUnit.MILLISECONDS), this.isShutdown(), this.isTerminated());
+    }
+
+    public int getAc() {
+        return ac;
+    }
+
+    /**
+     * 线程平均耗时
+     *
+     * @return
+     */
+    public float getAverageCostTime() {
+        return totalCostTime.get() / totalTasks.get();
+    }
+
+    /**
+     * 线程最大耗时
+     */
+    public long getMaxCostTime() {
+        return maxCostTime;
+    }
+
+    /**
+     * 线程最小耗时
+     */
+    public long getMinCostTime() {
+        return minCostTime;
+    }
+
+    /**
+     * 生成线程池所用的线程,改写了线程池默认的线程工厂
+     */
+    static class EventThreadFactory implements ThreadFactory {
+        private static final AtomicInteger poolNumber = new AtomicInteger(1);
+        private final ThreadGroup group;
+        private final AtomicInteger threadNumber = new AtomicInteger(1);
+        private final String namePrefix;
+
+        /**
+         * 初始化线程工厂
+         *
+         * @param poolName 线程池名称
+         */
+        EventThreadFactory(String poolName) {
+            SecurityManager s = System.getSecurityManager();
+            group = Objects.nonNull(s) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
+            namePrefix = poolName + "-pool-" + poolNumber.getAndIncrement() + "-thread-";
+        }
+
+        @Override
+        public Thread newThread(Runnable r) {
+            Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
+
+            if (t.isDaemon()) {
+                t.setDaemon(false);
+            }
+            if (t.getPriority() != Thread.NORM_PRIORITY) {
+                t.setPriority(Thread.NORM_PRIORITY);
+            }
+            return t;
+        }
+    }
+}