Преглед на файлове

Merge remote-tracking branch 'origin/test-merge' into test-merge

LHB преди 3 седмици
родител
ревизия
62451b8411
променени са 15 файла, в които са добавени 533 реда и са изтрити 220 реда
  1. 46 20
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchivesAutoController.java
  2. 2 2
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.java
  3. 1 1
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java
  4. 2 2
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialDetectionController.java
  5. 17 7
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialNumberRuleServiceImpl.java
  6. 102 61
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/EVDataServiceImpl.java
  7. 19 14
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/utils/PDFUtils.java
  8. 28 14
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java
  9. 5 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/TextdictInfoMapper.java
  10. 12 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/TextdictInfoMapper.xml
  11. 2 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreeContractMapper.xml
  12. 2 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/ISignConfigService.java
  13. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/SignConfigServiceImpl.java
  14. 115 28
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/TextdictInfoServiceImpl.java
  15. 179 67
      blade-service/blade-user/src/main/java/org/springblade/system/user/service/impl/UserServiceImpl.java

+ 46 - 20
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchivesAutoController.java

@@ -31,9 +31,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang.StringUtils;
 import org.apache.http.message.BasicNameValuePair;
 import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.WorkbookFactory;
+import org.apache.poi.ss.usermodel.*;
 import org.springblade.archive.dto.ArchiveWarningDTO;
 import org.springblade.archive.dto.FindAndReplaceDto;
 import org.springblade.archive.dto.SaveApplyDTO;
@@ -162,38 +160,56 @@ public class ArchivesAutoController extends BladeController {
 	@PostMapping ("/downloadArchiveAutoExcel")
 	@ApiOperationSupport(order = 13)
 	@ApiOperation(value = "档案下载案卷excel")
-	public ResponseEntity<Resource> downloadArchiveAutoExcel(HttpServletResponse response,Long nodeId,Long projectId,Long contractId) throws IOException, InvalidFormatException {
-		List<ArchiveTreeContract> archiveTreeContracts = this.archiveTreeContractClient.queryAllChildByAncestors(nodeId+"",contractId);
-		List<String> ids=new ArrayList<>();
-		if(archiveTreeContracts != null && archiveTreeContracts.size() > 0){
-			ids = JSONArray.parseArray(JSONObject.toJSONString(archiveTreeContracts.stream().map(ArchiveTreeContract::getId).distinct().collect(Collectors.toList())), String.class);
+	public ResponseEntity<Resource> downloadArchiveAutoExcel(HttpServletResponse response, Long nodeId, Long projectId, Long contractId) throws IOException, InvalidFormatException {
+		// 获取数据
+		List<ArchiveTreeContract> archiveTreeContracts = this.archiveTreeContractClient.queryAllChildByAncestors(nodeId+"", contractId);
+		List<String> ids = new ArrayList<>();
+		if(archiveTreeContracts != null && !archiveTreeContracts.isEmpty()) {
+			ids = JSONArray.parseArray(JSONObject.toJSONString(archiveTreeContracts.stream()
+					.map(ArchiveTreeContract::getId)
+					.distinct()
+					.collect(Collectors.toList())), String.class);
 			ids.add(nodeId+"");
 		}
-	    List<ArchivesAutoVO5> list=	archivesAutoService.selectArchivesAutoFileFormDownload(projectId,contractId,ids);
-		String templatePath="/mnt/sdc/Users/hongchuangyanfa/Desktop/excel/archiveTemplate.xlsx";
+		List<ArchivesAutoVO5> list = archivesAutoService.selectArchivesAutoFileFormDownload(projectId, contractId, ids);
+
+		// 加载模板
+		String templatePath = "/mnt/sdc/Users/hongchuangyanfa/Desktop/excel/archiveTemplate.xlsx";
 		//String templatePath="C:\\Users\\hc01\\Desktop\\archiveTemplate.xlsx";
 		InputStream templateStream = new FileInputStream(new File(templatePath));
 		org.apache.poi.ss.usermodel.Workbook workbook = WorkbookFactory.create(templateStream);
 		Sheet sheet = workbook.getSheetAt(0);
-		// 3. 填充数据(假设数据从第2行开始填充)
-		int startRow = 1; // 第2行开始填充数据
+
+		// 创建带边框的单元格样式
+		CellStyle borderedCellStyle = workbook.createCellStyle();
+		borderedCellStyle.setBorderTop(BorderStyle.THIN);  // 上边框
+		borderedCellStyle.setBorderBottom(BorderStyle.THIN);  // 下边框
+		borderedCellStyle.setBorderLeft(BorderStyle.THIN);  // 左边框
+		borderedCellStyle.setBorderRight(BorderStyle.THIN);  // 右边框
+
+		// 填充数据(从第2行开始)
+		int startRow = 1;
 		for (int i = 0; i < list.size(); i++) {
 			Row row = sheet.createRow(startRow + i);
 			ArchivesAutoVO5 vo1 = list.get(i);
-			// 填充各列数据
-			row.createCell(0).setCellValue(i + 1); // 序号
-			row.createCell(1).setCellValue(StringUtils.isNotEmpty(vo1.getFileNumber())?vo1.getFileNumber():""); // 档号
-			row.createCell(2).setCellValue(StringUtils.isNotEmpty(vo1.getName())?vo1.getName():""); // 案卷题名
-			row.createCell(3).setCellValue(StringUtils.isNotEmpty(vo1.getStorageTimeValue())?vo1.getStorageTimeValue():""); // 保管期限
-			row.createCell(4).setCellValue(vo1.getPageN()+""); // 总页数
-			row.createCell(5).setCellValue(StringUtils.isNotEmpty(vo1.getUnit())?vo1.getUnit():""); // 立卷单位
-			row.createCell(6).setCellValue(StringUtils.isNotEmpty(vo1.getRemark())?vo1.getRemark():""); // 备注
+
+			// 创建单元格并设置值和样式
+			createCellWithBorder(row, 0, i + 1, borderedCellStyle); // 序号
+			createCellWithBorder(row, 1, StringUtils.isNotEmpty(vo1.getFileNumber()) ? vo1.getFileNumber() : "", borderedCellStyle); // 档号
+			createCellWithBorder(row, 2, StringUtils.isNotEmpty(vo1.getName()) ? vo1.getName() : "", borderedCellStyle); // 案卷题名
+			createCellWithBorder(row, 3, StringUtils.isNotEmpty(vo1.getStorageTimeValue()) ? vo1.getStorageTimeValue() : "", borderedCellStyle); // 保管期限
+			createCellWithBorder(row, 4, vo1.getPageN() + "", borderedCellStyle); // 总页数
+			createCellWithBorder(row, 5, StringUtils.isNotEmpty(vo1.getUnit()) ? vo1.getUnit() : "", borderedCellStyle); // 立卷单位
+			createCellWithBorder(row, 6, StringUtils.isNotEmpty(vo1.getRemark()) ? vo1.getRemark() : "", borderedCellStyle); // 备注
 		}
+
+		// 输出Excel文件
 		ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
 		workbook.write(outputStream);
 		workbook.close();
 		ByteArrayResource resource = new ByteArrayResource(outputStream.toByteArray());
 
+		// 设置响应头
 		String fileName = "案卷目录.xlsx";
 		String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.toString())
 				.replaceAll("\\+", "%20");
@@ -202,7 +218,17 @@ public class ArchivesAutoController extends BladeController {
 				.contentType(MediaType.APPLICATION_OCTET_STREAM)
 				.contentLength(resource.contentLength())
 				.body(resource);
+	}
 
+	// 辅助方法:创建带边框的单元格
+	private void createCellWithBorder(Row row, int columnIndex, Object value, CellStyle style) {
+		Cell cell = row.createCell(columnIndex);
+		if (value instanceof Number) {
+			cell.setCellValue(((Number) value).doubleValue());
+		} else {
+			cell.setCellValue(value.toString());
+		}
+		cell.setCellStyle(style);
 	}
 
     @GetMapping("/fileNumberFlush")

+ 2 - 2
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.java

@@ -235,6 +235,6 @@ public interface ArchivesAutoMapper extends BaseMapper<ArchivesAuto> {
 	void deleteIsElementFileByProjectId(@Param("projectId") Long projectId);
 
 	void deleteIsElementFileByNode(@Param("projectId") Long projectId,@Param("ancestors") String ancestors,@Param("nodeId") String nodeId);
-	List<ArchivesAutoVO5> selectArchivesAutoFileFormDownload(@Param("projectId") Long projectId, @Param("contractId") Long contractId, @Param("ids") List<String> ids);
-	List<ArchivesAutoVO5> selectArchivesAutoFileFormDownload(@Param("projectId") Long projectId, @Param("ids") List<String> ids);
+	List<ArchivesAutoVO5> selectArchivesAutoFileFormDownload(@Param("projectId") Long projectId,  @Param("ids") List<String> ids);
+
 }

+ 1 - 1
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java

@@ -1602,7 +1602,7 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 
 	@Override
 	public List<ArchivesAutoVO5> selectArchivesAutoFileFormDownload(Long projectId, Long contractId, List<String> ids) {
-		List<ArchivesAutoVO5> list = this.baseMapper.selectArchivesAutoFileFormDownload(projectId, contractId, ids);
+		List<ArchivesAutoVO5> list = this.baseMapper.selectArchivesAutoFileFormDownload(projectId, ids);
 		List<DictBiz> sheetSourceList1 = this.iDictBizClient.getList("storage_period", "notRoot").getData();
 		list.forEach(vos -> {
 			if (StringUtils.isNotEmpty(vos.getStorageTime())) {

+ 2 - 2
blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialDetectionController.java

@@ -683,12 +683,12 @@ public class TrialDetectionController extends BladeController {
         if (vo.getRecordNo() == null) {
             Map<String, String> map = trialNumberRuleService.getTrialNumber(projectId, contractId, 4, nodeId, true);
             vo.setRecordNo(map.get("trialNumber"));
-            vo.setRecordAutoNumber(map.get("trialAutoNumber"));
+            vo.setRecordAutoNumber(map.get("autoIncrementNumber"));
         }
         if (vo.getReportNo() == null) {
             Map<String, String> map = trialNumberRuleService.getTrialNumber(projectId, contractId, 5, nodeId, true);
             vo.setReportNo(map.get("trialNumber"));
-            vo.setReportAutoNumber(map.get("trialAutoNumber"));
+            vo.setReportAutoNumber(map.get("autoIncrementNumber"));
         }
         List<TrialSeleInspectionRecordInfoDTO.StandardVo> mapList = jdbcTemplate.query("SELECT id,name from u_wbs_private_standard WHERE type = 2 and is_deleted = 0  and private_id = " + nodeId,
                 new BeanPropertyRowMapper<>(TrialSeleInspectionRecordInfoDTO.StandardVo.class));

+ 17 - 7
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialNumberRuleServiceImpl.java

@@ -90,7 +90,13 @@ public class TrialNumberRuleServiceImpl extends BaseServiceImpl<TrialNumberRuleM
              rules = baseMapper.selectList(Wrappers.<TrialNumberRule>query().lambda().eq(TrialNumberRule::getContractId, contractId).eq(TrialNumberRule::getType, type).eq(TrialNumberRule::getStatus,2).orderByAsc(TrialNumberRule::getSort));
         }
         boolean flag=true;
+        boolean flag1=true;
         int i=1;
+        if(rules.isEmpty()){
+            map.put("trialNumber","");
+            map.put("autoIncrementNumber","");
+            return map;
+        }
         do {
             for (TrialNumberRule rule : rules) {
                 if(rule.getRule()==1){
@@ -139,6 +145,7 @@ public class TrialNumberRuleServiceImpl extends BaseServiceImpl<TrialNumberRuleM
                     if(!isSaveRedis){
                         trialNumber.append(rule.getData());
                         map.put("autoIncrementNumber",rule.getData());
+                        continue;
                     }
                     if(rule.getIsAutoIncrement()!=null&&rule.getIsAutoIncrement()==1){
                         String autoIncrementNumber="";
@@ -151,9 +158,12 @@ public class TrialNumberRuleServiceImpl extends BaseServiceImpl<TrialNumberRuleM
                                 return null;
                             }
                         });
-                        if(StringUtils.isEmpty(maxNumber)){
+                        if(StringUtils.isEmpty(maxNumber)&&i==1){
                             autoIncrementNumber=rule.getData();
                         }else {
+                            if(maxNumber==null){
+                                maxNumber=rule.getData();
+                            }
                             autoIncrementNumber=incrementFormattedNumberWithCheck(maxNumber,i);
                         }
 //
@@ -202,12 +212,12 @@ public class TrialNumberRuleServiceImpl extends BaseServiceImpl<TrialNumberRuleM
                     }
                 }
             }
-            if(isSaveRedis){
-                flag=checkTrialNumberIsExist(trialNumber.toString(),type,contractId);
-                i++;
-                if(!flag){
-                    trialNumber.setLength(0);
-                }
+            if(isSaveRedis&&rules.stream().anyMatch(r->r.getRule()==6&&r.getIsAutoIncrement()==1)){
+                    flag=checkTrialNumberIsExist(trialNumber.toString(),type,contractId);
+                    i++;
+                    if(!flag){
+                        trialNumber.setLength(0);
+                    }
             }
         }while (!flag);
         map.put("trialNumber",trialNumber.toString());

+ 102 - 61
blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/EVDataServiceImpl.java

@@ -87,8 +87,8 @@ public class EVDataServiceImpl implements EVDataService {
             this.addSignatureTaskBatch(taskApp);
             //for循环 pdfUrl分割
             String fileUrl = CommonUtil.replaceOssUrl(taskApp.getSignPdfUrl());
-            List<String> eVisaConfigList = PDFUtils.getPdfSignIds(fileUrl, taskApp);
-            if (eVisaConfigList == null || eVisaConfigList.size() == 0) {
+            Map<String, Integer> eVisaConfigMap = PDFUtils.getPdfSignIds(fileUrl, taskApp);
+            if (eVisaConfigMap == null || eVisaConfigMap.size() == 0) {
                 //没有电签配置,默认当前任务为不签字审批,返回成功
                 taskApp.setSigState(2);
                 taskApp.setSignSmg("pdf未获取到关键字Id");
@@ -96,7 +96,7 @@ public class EVDataServiceImpl implements EVDataService {
                 return;
             }
             // 获取pdf上的电签Ids
-            String ids = String.join(",", eVisaConfigList);
+            String ids = String.join(",", eVisaConfigMap.keySet());
             if (taskApp.getRemarkType().equals("1")) { //安心签
                 //添加电签策略
                 List<SealStrategyVO> strategyListByAXQ = getStrategyListByAXQ(taskApp, ids);
@@ -118,6 +118,26 @@ public class EVDataServiceImpl implements EVDataService {
                     }
                     SignBackPdfInfo(taskApp);
                     return;
+                } else {
+                    // 一个位置只留一个签字
+                    Map<Integer, SealStrategyVO> map = new HashMap<>();
+                    strategyListByAXQ.forEach(item -> {
+                        String keyword = item.getKeyword();
+                        Integer lineNum = eVisaConfigMap.get(keyword);
+                        if (lineNum ==  null) {
+                            return;
+                        }
+                        SealStrategyVO vo = map.get(lineNum);
+                        if (vo == null) {
+                            map.put(lineNum, item);
+                        } else {
+                            String keyword1 = vo.getKeyword();
+                            if (keyword1 != null && keyword1.contains("✹") && !keyword.contains("✹")) {
+                                map.put(lineNum, item);
+                            }
+                        }
+                    });
+                    strategyListByAXQ = new ArrayList<>(map.values());
                 }
 
                 //调用签字逻辑
@@ -133,6 +153,27 @@ public class EVDataServiceImpl implements EVDataService {
             } else if (taskApp.getRemarkType().equals("2") || taskApp.getRemarkType().equals("3")) { //东方中讯
                 //添加电签策略
                 List<Map<String, Object>> strategyListByDFZX = getStrategyListByDFZX(taskApp, ids);
+                if (strategyListByDFZX != null && !strategyListByDFZX.isEmpty()) {
+                    // 一个位置只留一个签字
+                    Map<Integer, Map<String, Object>> map = new HashMap<>();
+                    strategyListByDFZX.forEach(item -> {
+                        String keyword = item.get("keyword") + "";
+                        Integer lineNum = eVisaConfigMap.get(keyword);
+                        if (lineNum ==  null) {
+                            return;
+                        }
+                        Map<String, Object> vo = map.get(lineNum);
+                        if (vo == null) {
+                            map.put(lineNum, item);
+                        } else {
+                            String keyword1 = vo.get("keyword") + "";
+                            if (!keyword1.equals("null") && keyword1.contains("✹") && !keyword.contains("✹")) {
+                                map.put(lineNum, item);
+                            }
+                        }
+                    });
+                    strategyListByDFZX = new ArrayList<>(map.values());
+                }
                 //调用签字逻辑
                 String s = signTaskBatchByDFZX(strategyListByDFZX, fileUrl, taskApp.getSigType(),taskApp.getRemarkType(),taskApp.getContractId());
                 if (s.contains("sucess")) {
@@ -624,8 +665,8 @@ public class EVDataServiceImpl implements EVDataService {
                     }
                     maps2 = jdbcTemplate.queryForList(sqlinfo);
                 }
+                List<Map<String, Object>> maps = new ArrayList<>();
                 if (maps2 != null && maps2.size() > 0) {
-                    List<Map<String, Object>> maps = new ArrayList<>();
                     Map<String, List<Map<String, Object>>> peopleByAge = maps2.stream()
                             .collect(Collectors.groupingBy(hada -> (Func.toStr(hada.get("id")))));
 
@@ -647,68 +688,68 @@ public class EVDataServiceImpl implements EVDataService {
                             maps.add(keyList.get(0));
                         }
                     }
-                    if (signIds.length() > 0 && task.getSigType() != 2) {
-                        String sql = "SELECT * from ( SELECT DISTINCT a.conf_id as id,0.0 as pyzbx ,0.0 as pyzby,(SELECT signature_file_url from m_sign_pfx_file where is_register=1 and certificate_user_id='"
-                                + userId + "' and is_deleted=0  ) as signature_file_url, (SELECT wide from m_sign_pfx_file where is_register=1 and certificate_user_id='"
-                                + userId + "' and is_deleted=0  ) as wide ,(SELECT high from m_sign_pfx_file where is_register=1 and certificate_user_id='"
-                                + userId + "' and is_deleted=0  ) as high from m_sign_config_relation a where a.type = 1 and a.is_deleted = 0 and a.conf_id in (" + signIds + ") and a.relation_id in (SELECT DISTINCT c.role_id from m_project_assignment_user c  where c.contract_id="
-                                + task.getContractId() + " and user_id=" + userId + " and c.is_deleted=0 ) ) x where x.signature_file_url is not null ";
-                        List<Map<String, Object>> maps3 = jdbcTemplate.queryForList(sql);
-                        System.out.println("安心签--签章--key =" + sql);
-                        if (!maps3.isEmpty()) {
-                            Map<String, List<Map<String, Object>>> peopleByAges = maps3.stream()
-                                    .collect(Collectors.groupingBy(hada -> (Func.toStr(hada.get("id")))));
-                            for (String keyId : peopleByAges.keySet()) {
-                                List<Map<String, Object>> keyList = peopleByAges.get(keyId);
-                                if (keyList != null && !keyList.isEmpty()) {
-                                    Map<String, Object> map = keyList.get(0);
-                                    map.put("id", "✹" + map.get("id"));
-                                    maps.add(map);
-                                }
+                }
+                if (signIds.length() > 0 && task.getSigType() != 2) {
+                    String sql = "SELECT * from ( SELECT DISTINCT a.conf_id as id,0.0 as pyzbx ,0.0 as pyzby,(SELECT signature_file_url from m_sign_pfx_file where is_register=1 and certificate_user_id='"
+                            + userId + "' and is_deleted=0  ) as signature_file_url, (SELECT wide from m_sign_pfx_file where is_register=1 and certificate_user_id='"
+                            + userId + "' and is_deleted=0  ) as wide ,(SELECT high from m_sign_pfx_file where is_register=1 and certificate_user_id='"
+                            + userId + "' and is_deleted=0  ) as high from m_sign_config_relation a where a.type = 1 and a.is_deleted = 0 and a.conf_id in (" + signIds + ") and a.relation_id in (SELECT DISTINCT c.role_id from m_project_assignment_user c  where c.contract_id="
+                            + task.getContractId() + " and user_id=" + userId + " and c.is_deleted=0 ) ) x where x.signature_file_url is not null ";
+                    List<Map<String, Object>> maps3 = jdbcTemplate.queryForList(sql);
+                    System.out.println("安心签--签章--key =" + sql);
+                    if (!maps3.isEmpty()) {
+                        Map<String, List<Map<String, Object>>> peopleByAges = maps3.stream()
+                                .collect(Collectors.groupingBy(hada -> (Func.toStr(hada.get("id")))));
+                        for (String keyId : peopleByAges.keySet()) {
+                            List<Map<String, Object>> keyList = peopleByAges.get(keyId);
+                            if (keyList != null && !keyList.isEmpty()) {
+                                Map<String, Object> map = keyList.get(0);
+                                map.put("id", "✹" + map.get("id"));
+                                maps.add(map);
                             }
                         }
                     }
-                    if (maps == null || maps.size() <= 0) {
-                        break;
-                    }
-                    //准备签章策略
-                    for (Map<String, Object> eVisaConfig : maps) {
-                        //设置签章策略
-                        SealStrategyVO vo = new SealStrategyVO();
-                        if (task.getSigType() == 1) {
-                            vo.setSealCode(EVisaConstant.SIGN_SEAL_CODE + userId);
-                            if (userId.length() <= EVisaConstant.USER_ID_SUB) {
-                                vo.setSealPassword(userId.toString());
-                            } else {
-                                vo.setSealPassword(userId.substring(0, EVisaConstant.USER_ID_SUB));
-                            }
-                            vo.setSealPerson(userNames[i]);
-                            //设置签字文件
-                            vo.setImageUrl(eVisaConfig.get("signature_file_url") + "");
-                            vo.setSealType("3");
-                            vo.setKeyword(eVisaConfig.get("id") + "");
-                            vo.setOffSetX(eVisaConfig.get("pyzbx") + "");
-                            vo.setOffSetY(eVisaConfig.get("pyzby") + "");
-                            vo.setHeight(eVisaConfig.get("high") + "");
-                            vo.setWidth(eVisaConfig.get("wide") + "");
-                            vo.setProjectId(eVisaConfig.get("project_id") + "");
-                        } else if (task.getSigType() == 2) {
-                            vo.setSealCode(EVisaConstant.SIGN_SEAL_CODE + eVisaConfig.get("sfId"));
-                            vo.setSealPassword(eVisaConfig.get("certificate_password") + "");
-                            vo.setSealPerson(eVisaConfig.get("certificate_user_name") + "" + System.currentTimeMillis());
-                            //设置签字文件
-                            vo.setImageUrl(eVisaConfig.get("signature_file_url") + "");
-                            vo.setSealType("3");
-                            vo.setCompanySeal(true);
-                            vo.setKeyword(eVisaConfig.get("id") + "");
-                            vo.setOffSetX(eVisaConfig.get("pyzbx") + "");
-                            vo.setOffSetY(eVisaConfig.get("pyzby") + "");
-                            vo.setHeight(eVisaConfig.get("high") + "");
-                            vo.setWidth(eVisaConfig.get("wide") + "");
-                            vo.setProjectId(eVisaConfig.get("project_id") + "");
+                }
+                if (maps.size() <= 0) {
+                    break;
+                }
+                //准备签章策略
+                for (Map<String, Object> eVisaConfig : maps) {
+                    //设置签章策略
+                    SealStrategyVO vo = new SealStrategyVO();
+                    if (task.getSigType() == 1) {
+                        vo.setSealCode(EVisaConstant.SIGN_SEAL_CODE + userId);
+                        if (userId.length() <= EVisaConstant.USER_ID_SUB) {
+                            vo.setSealPassword(userId.toString());
+                        } else {
+                            vo.setSealPassword(userId.substring(0, EVisaConstant.USER_ID_SUB));
                         }
-                        sealStrategyVOS.add(vo);
+                        vo.setSealPerson(userNames[i]);
+                        //设置签字文件
+                        vo.setImageUrl(eVisaConfig.get("signature_file_url") + "");
+                        vo.setSealType("3");
+                        vo.setKeyword(eVisaConfig.get("id") + "");
+                        vo.setOffSetX(eVisaConfig.get("pyzbx") + "");
+                        vo.setOffSetY(eVisaConfig.get("pyzby") + "");
+                        vo.setHeight(eVisaConfig.get("high") + "");
+                        vo.setWidth(eVisaConfig.get("wide") + "");
+                        vo.setProjectId(eVisaConfig.get("project_id") + "");
+                    } else if (task.getSigType() == 2) {
+                        vo.setSealCode(EVisaConstant.SIGN_SEAL_CODE + eVisaConfig.get("sfId"));
+                        vo.setSealPassword(eVisaConfig.get("certificate_password") + "");
+                        vo.setSealPerson(eVisaConfig.get("certificate_user_name") + "" + System.currentTimeMillis());
+                        //设置签字文件
+                        vo.setImageUrl(eVisaConfig.get("signature_file_url") + "");
+                        vo.setSealType("3");
+                        vo.setCompanySeal(true);
+                        vo.setKeyword(eVisaConfig.get("id") + "");
+                        vo.setOffSetX(eVisaConfig.get("pyzbx") + "");
+                        vo.setOffSetY(eVisaConfig.get("pyzby") + "");
+                        vo.setHeight(eVisaConfig.get("high") + "");
+                        vo.setWidth(eVisaConfig.get("wide") + "");
+                        vo.setProjectId(eVisaConfig.get("project_id") + "");
                     }
+                    sealStrategyVOS.add(vo);
                 }
             }
         }

+ 19 - 14
blade-service/blade-e-visa/src/main/java/org/springblade/evisa/utils/PDFUtils.java

@@ -8,16 +8,15 @@ import org.springblade.common.utils.CommonUtil;
 import org.springblade.core.tool.utils.Func;
 
 import java.io.*;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
+import java.util.*;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
 public class PDFUtils {
-    public static List<String>  getPdfSignIds(String pdfUrl, TaskSignInfoVO taskApp) {
-        List<String> eVisaConfigList = new ArrayList<>();
+    public static Map<String, Integer>  getPdfSignIds(String pdfUrl, TaskSignInfoVO taskApp) {
+//        List<String> eVisaConfigList = new ArrayList<>();
+        Map<String, Integer> eVisaConfigMap = new HashMap<>();
         try  {
             InputStream inputStream = CommonUtil.getOSSInputStream(pdfUrl);
             PDDocument document = PDDocument.load(inputStream);
@@ -43,7 +42,8 @@ public class PDFUtils {
                         }
                     }
                     if (txt.length() >= 15 && Func.isNumeric(txt)||(Func.isNumeric(txt)&&txt.length()==8&&txt.startsWith("123"))) {
-                        eVisaConfigList.add(txt);
+//                        eVisaConfigList.add(txt);
+                        eVisaConfigMap.put(txt,k);
                     }
                 }
                 if (taskApp.getPdfDate() == null || taskApp.getPdfDate().isEmpty()) {
@@ -60,7 +60,8 @@ public class PDFUtils {
                         }
                     }
                     if (txt.length() >= 15 && Func.isNumeric(txt)||(Func.isNumeric(txt)&&txt.length()==8&&txt.startsWith("123"))) {
-                        eVisaConfigList.add(txt);
+//                        eVisaConfigList.add(txt);
+                        eVisaConfigMap.put(txt,k);
                     }
                 }
 
@@ -74,7 +75,8 @@ public class PDFUtils {
                     }
                     if (txt.length() >= 15 && Func.isNumeric(txt)||(Func.isNumeric(txt)&&txt.length()==8&&txt.startsWith("123"))) {
                         System.out.println(txt);
-                        eVisaConfigList.add(txt);
+//                        eVisaConfigList.add(txt);
+                        eVisaConfigMap.put(txt,k);
                     }
                 }
                 if (textStr.contains("✹")) {
@@ -88,7 +90,8 @@ public class PDFUtils {
                                 }
                             }
                             if (txt.length() >= 15 && Func.isNumeric(txt)||(Func.isNumeric(txt)&&txt.length()==8&&txt.startsWith("123"))) {
-                                eVisaConfigList.add("✹" + txt);
+//                                eVisaConfigList.add("✹" + txt);
+                                eVisaConfigMap.put("✹" + txt,k);
                             }
                         }
                     }
@@ -101,7 +104,8 @@ public class PDFUtils {
                                 }
                             }
                             if (txt.length() >= 15 && Func.isNumeric(txt)||(Func.isNumeric(txt)&&txt.length()==8&&txt.startsWith("123"))) {
-                                eVisaConfigList.add("✹" + txt);
+//                                eVisaConfigList.add("✹" + txt);
+                                eVisaConfigMap.put("✹" + txt,k);
                             }
                         }
                     }
@@ -112,20 +116,21 @@ public class PDFUtils {
                             }
                         }
                         if (textString.length() >= 15 && Func.isNumeric(textString)||(Func.isNumeric(textString)&&textString.length()==8&&textString.startsWith("123"))) {
-                            eVisaConfigList.add("✹" + textString);
+//                            eVisaConfigList.add("✹" + textString);
+                            eVisaConfigMap.put("✹" + textString,k);
                         }
                     }
                 }
             }
 
 
-            List<String> unique = eVisaConfigList.stream().distinct().collect(Collectors.toList());
+//            List<String> unique = eVisaConfigList.stream().distinct().collect(Collectors.toList());
             document.close();
-            return unique;
+            return eVisaConfigMap;
         }catch (Exception e){
             e.printStackTrace();
             System.out.println("pdf大小为0");
-            return eVisaConfigList;
+            return eVisaConfigMap;
         }
     }
 

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

@@ -4825,32 +4825,46 @@ public class ExcelTabController extends BladeController {
         List<WbsTreeContract>list= wbsTreeContractMapper.selectListForcheckAllNodeDate(projectId,contractId);
         //将表单通过pid分组
         Map<Long, List<WbsTreeContract>> map = list.stream().collect(Collectors.groupingBy(WbsTreeContract::getPId));
+        int i=map.size();
+        System.out.println("当前项目合同段有:"+i+"个节点");
         for (Map.Entry<Long, List<WbsTreeContract>> entry : map.entrySet()) {
             Long pId = entry.getKey();
             WbsTreeContract parent = wbsTreeContractMapper.selectOne(new LambdaQueryWrapper<>(WbsTreeContract.class).eq(WbsTreeContract::getPKeyId, pId));
+            String informationSql="select * from u_information_query where wbs_id="+parent.getPKeyId()+" and contract_id="+contractId+" and is_deleted=0";
+            List<InformationQuery> query = jdbcTemplate.query(informationSql, new BeanPropertyRowMapper<>(InformationQuery.class));
+            if(query.isEmpty()||query.get(0).getStatus()!=0){
+                i--;
+                System.out.println("剩余:"+i+"个节点未检查");
+                continue;
+            }
             List<WbsTreeContract> wbsTreeContractList = entry.getValue();
             for (WbsTreeContract contract : wbsTreeContractList) {
                 Map<String, Object> dataInfo = excelTabService.getBussDataInfo(contract.getPKeyId(), 0, true);
-                InputStream inputStreamByUrl = FileUtils.getInputStreamByUrl(contract.getHtmlUrl());
-                String htmlString = IoUtil.readToString(inputStreamByUrl);
-                Document doc = Jsoup.parse(htmlString);
-                Elements dateElements = doc.select("el-date-picker");
-                if(!dateElements.isEmpty()){
-                    Boolean dateFlag=true;
-                    for (Element element : dateElements) {
-                        String keyname = element.attr("keyname");
-                        if(!dataInfo.containsKey(keyname)||(StringUtils.isEmpty(dataInfo.get(keyname).toString()))){
-                            dateFlag=false;
-                            break;
+                if(dataInfo!=null){
+                    InputStream inputStreamByUrl = FileUtils.getInputStreamByUrl(contract.getHtmlUrl());
+                    String htmlString = IoUtil.readToString(inputStreamByUrl);
+                    Document doc = Jsoup.parse(htmlString);
+                    Elements dateElements = doc.select("el-date-picker");
+                    if(!dateElements.isEmpty()){
+                        Boolean dateFlag=true;
+                        for (Element element : dateElements) {
+                            String keyname = element.attr("keyname");
+                            if(!dataInfo.containsKey(keyname)||(StringUtils.isEmpty(dataInfo.get(keyname).toString()))){
+                                dateFlag=false;
+                                break;
+                            }
+                        }
+                        if(!dateFlag){
+                            wbsTreeContractMapper.update(null,new LambdaUpdateWrapper<WbsTreeContract>().eq(WbsTreeContract::getPKeyId,contract.getPKeyId()).set(WbsTreeContract::getDateIsComplete,2));
                         }
-                    }
-                    if(!dateFlag){
-                        wbsTreeContractMapper.update(contract,new LambdaUpdateWrapper<WbsTreeContract>().eq(WbsTreeContract::getPKeyId,contract.getPKeyId()).set(WbsTreeContract::getDateIsComplete,2));
                     }
                 }
             }
             wbsTreeContractService.checkNodeAllDate(parent);
+            i--;
+            System.out.println("剩余:"+i+"个节点未检查");
         }
+        System.out.println("检查完毕");
         return R.status(true);
     }
 }

+ 5 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/TextdictInfoMapper.java

@@ -24,6 +24,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.springframework.data.repository.query.Param;
 
+import java.util.Collection;
 import java.util.List;
 
 /**
@@ -52,4 +53,8 @@ public interface TextdictInfoMapper extends EasyBaseMapper<TextdictInfo> {
     TextdictInfo selectTextdictInfoOne(@Param("id") String id,@Param("sigRoleId") String sigRoleId,@Param("projectId") String projectId);
 
     void updateHtmlUrl(@Param("htmlUrl") String htmlUrl,@Param("projectId") String projectId, @Param("excelId") Long pKeyId);
+
+    List<TextdictInfoVO> selectTextdictInfoByExcelIdAndColKey(@Param("excelId") String excelId, @Param("colKeys") Collection<String> colKeys);
+
+    List<TextdictInfoVO> selectTextDictInfoByIdAndColKeyAndColName(@Param("list") List<TextdictInfo> textdictInfos);
 }

+ 12 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/TextdictInfoMapper.xml

@@ -65,6 +65,18 @@
             and sig_role_id = #{sigRoleId}
             and project_id= #{projectId}
     </select>
+    <select id="selectTextdictInfoByExcelIdAndColKey" resultMap="textdictInfoVoResultMap">
+        SELECT * from m_textdict_info where is_deleted = 0 and type in('2','6') and excel_id = #{excelId} and is_deleted = 0
+        <foreach collection="colKeys" item="key" separator="," open=" and col_key in ( " close=" )" >
+            #{key}
+        </foreach>
+    </select>
+    <select id="selectTextDictInfoByIdAndColKeyAndColName" resultMap="textdictInfoVoResultMap">
+        select * from m_textdict_info where is_deleted = 0
+        <foreach collection="list" item="item" separator="," open=" and (id,col_key,col_name) in ( " close=")">
+            (#{item.id},#{item.colKey},#{item.colName})
+        </foreach>
+    </select>
     <update id="updateHtmlUrl">
         update m_wbs_tree_contract set html_url = #{htmlUrl} where type = 2 and project_id = #{projectId} and is_type_private_pid = #{pKeyId};
     </update>

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

@@ -990,8 +990,8 @@
         <if test="contractId!=null and contractId!=''">
           and  contract_id=#{contractId}
         </if>
-        and is_deleted=0 and is_buss_show !=2 and init_table_name !=null and html_url !=null and LENGTH(init_table_name) > 10 and LENGTH(html_url) > 10
-        and p_id !=null
+        and is_deleted=0 and is_buss_show !=2 and init_table_name is not null and html_url is not null and LENGTH(init_table_name) > 10 and LENGTH(html_url) > 10
+        and p_id is not null
     </select>
 
 </mapper>

+ 2 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/service/ISignConfigService.java

@@ -12,6 +12,7 @@ import org.springblade.manager.vo.WbsFormElementVO3;
 import org.springblade.system.vo.RoleVO;
 import org.springblade.system.vo.RoleVO2;
 
+import java.util.Collection;
 import java.util.List;
 
 public interface ISignConfigService extends BaseService<SignConfig> {
@@ -30,5 +31,5 @@ public interface ISignConfigService extends BaseService<SignConfig> {
 
     List<TableInfo> tableList(Integer tableType, String name);
 
-    List<TextdictInfoVO> hasSignConfig(String initTableName, List<String> keys, TextdictInfoVO vo);
+    List<TextdictInfoVO> hasSignConfig(String initTableName, Collection<String> keys, TextdictInfoVO vo);
 }

+ 1 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/SignConfigServiceImpl.java

@@ -293,7 +293,7 @@ public class SignConfigServiceImpl extends BaseServiceImpl<SignConfigMapper, Sig
     }
 
     @Override
-    public List<TextdictInfoVO> hasSignConfig(String initTableName, List<String> keyNames, TextdictInfoVO vo) {
+    public List<TextdictInfoVO> hasSignConfig(String initTableName, Collection<String> keyNames, TextdictInfoVO vo) {
         List<TextdictInfoVO> textdictInfoVOS = new ArrayList<>();
         if (keyNames == null || keyNames.isEmpty()) {
             return textdictInfoVOS;

+ 115 - 28
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/TextdictInfoServiceImpl.java

@@ -22,6 +22,8 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import org.apache.commons.lang.StringUtils;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.jsoup.Jsoup;
 import org.jsoup.nodes.Document;
 import org.jsoup.nodes.Element;
@@ -76,46 +78,35 @@ public class TextdictInfoServiceImpl extends ServiceImpl<TextdictInfoMapper, Tex
                 Document doc = Jsoup.parse(htmlString);
                 Elements table = doc.getElementsByAttribute("dqid");
                 List<String> dqid = new ArrayList<>();
-                List<String> keys = new ArrayList<>();
+                Map<String, String> dqIdMap = new HashMap<>();
+                Map<String, String> keys = new HashMap<>();
                 for(Element ek:table){
-                    dqid.addAll(Func.toStrList("\\|\\|",ek.attr("dqid")));
+                    List<String> list = Func.toStrList("\\|\\|", ek.attr("dqid"));
+                    dqid.addAll(list);
+                    Elements keyname = ek.getElementsByAttributeValueStarting("keyname", "key_");
+                    if (keyname != null && !keyname.isEmpty()) {
+                        String key = keyname.get(0).attr("keyname");
+                        for (String s : list) {
+                            dqIdMap.put(s, key);
+                        }
+                    }
                 }
                 Elements keyNames = doc.getElementsByAttribute("keyname");
                 if(Func.isNotEmpty(keyNames)){
                     for(Element keyName:keyNames){
-                        keys.add(keyName.attr("keyname"));
+                        keys.put(keyName.attr("keyname"), keyName.attr("placeholder"));
                     }
                 }
                 if(Func.isNotEmpty(textdictInfo.getShowType()) && textdictInfo.getShowType() == 1){
+                    List<TextdictInfo> textdictInfos = new ArrayList<>();
                     if(Func.isNotEmpty(dqid) && dqid.size() > 0){
                         textdict = baseMapper.selectTextdictBYIds(dqid,privateInfo.getProjectId());
+                        textdict = getTextdictInfoByDqIdAndKeyName(textdict, dqIdMap, keys, textdictInfos);
                     }else {
                         textdict = new ArrayList<>();
                     }
-                    List<TextdictInfoVO> textdictList= baseMapper.selectTextdictInfoByExcelId(page, textdictInfo);
-                    if (textdict == null || textdict.isEmpty()) {
-                        textdict = textdictList;
-                        if (textdict != null) {
-                            textdict.forEach(textdictInfoVO -> textdictInfoVO.setIsSystem(2));
-                        }
-                        addSign(textdict, doc, privateInfo, dqid, textdict);
-                    } else if (textdictList != null && !textdictList.isEmpty()) {
-                        Map<String, Map<String, TextdictInfoVO>> map = textdict.stream().filter(vo -> vo.getColKey() != null && vo.getColKey().contains("__")).collect(Collectors.groupingBy(vo -> vo.getColKey().split("__")[1], Collectors.toMap(TextdictInfoVO::getSigRoleId, v -> v, (v1, v2) -> v1)));
-                        List<TextdictInfoVO> collect = textdictList.stream().filter(textdictInfoVO -> {
-                            if (textdictInfoVO.getColKey() == null || !textdictInfoVO.getColKey().contains("__")) {
-                                return true;
-                            }
-                            Map<String, TextdictInfoVO> voMap = map.get(textdictInfoVO.getColKey().split("__")[1]);
-                            textdictInfoVO.setIsSystem(2);
-                            if (voMap != null && !voMap.isEmpty() ) {
-                                return voMap.get(textdictInfoVO.getSigRoleId()) == null;
-                            }
-                            return true;
-                        }).collect(Collectors.toList());
-                        textdict.addAll(collect);
-                        addSign(collect, doc, privateInfo, dqid,textdict);
-                    }
                     if (!keys.isEmpty()) {
+                        textdict = getTextDictInfoBySystem(textdictInfo, keys, textdictInfos, textdict, doc, privateInfo, dqid);
                         TextdictInfoVO temp = null;
                         if (textdict != null && !textdict.isEmpty()) {
                             temp = textdict.get(0);
@@ -128,7 +119,7 @@ public class TextdictInfoServiceImpl extends ServiceImpl<TextdictInfoMapper, Tex
                             temp.setType(2);
                         }
                         // 查询电签库配置
-                        List<TextdictInfoVO> textdictConfigList = iSignConfigService.hasSignConfig(privateInfo.getInitTableName(), keys, temp);
+                        List<TextdictInfoVO> textdictConfigList = iSignConfigService.hasSignConfig(privateInfo.getInitTableName(), keys.keySet(), temp);
                         if (textdict == null || textdict.isEmpty()) {
                             textdict = textdictConfigList;
                         } else {
@@ -147,7 +138,15 @@ public class TextdictInfoServiceImpl extends ServiceImpl<TextdictInfoMapper, Tex
                         }
                     }
                 }else{
-                    textdict = baseMapper.selectTextdictInfoByExcelId(page, textdictInfo);
+                    if (!keys.isEmpty()) {
+                        // 根据excel_id 和col_key 查询
+                        List<TextdictInfoVO> textdictList= baseMapper.selectTextdictInfoByExcelIdAndColKey(textdictInfo.getExcelId(),keys.keySet());
+                        if (textdictList != null) {
+                            Map<String, TextdictInfoVO> map = textdictList.stream().filter(vo -> vo.getColName() != null && vo.getColName().equals(keys.get(vo.getColKey())))
+                                    .collect(Collectors.toMap(vo -> vo.getColKey() + vo.getSigRoleId(), v -> v, (v1, v2) -> v1));
+                            textdict = new ArrayList<>(map.values());
+                        }
+                    }
                 }
             } catch (Exception e) {
                 throw new RuntimeException(e);
@@ -157,6 +156,94 @@ public class TextdictInfoServiceImpl extends ServiceImpl<TextdictInfoMapper, Tex
         }
         return page.setRecords(textdict);
     }
+
+    /**
+     * 系统推荐
+     */
+    @Nullable
+    private List<TextdictInfoVO> getTextDictInfoBySystem(TextdictInfoVO textdictInfo, Map<String, String> keys, List<TextdictInfo> textdictInfos, List<TextdictInfoVO> textdict, Document doc, WbsTreePrivate privateInfo, List<String> dqid) {
+        // 根据excel_id 和col_key 查询
+        List<TextdictInfoVO> textdictList= baseMapper.selectTextdictInfoByExcelIdAndColKey(textdictInfo.getExcelId(), keys.keySet());
+        if (textdictList != null) {
+            Map<String, TextdictInfoVO> map = textdictList.stream().filter(vo -> vo.getColName() != null && vo.getColName().equals(keys.get(vo.getColKey()))).collect(Collectors.toMap(vo -> vo.getColKey() + vo.getSigRoleId(), v -> v, (v1, v2) -> v1));
+            textdictList = new ArrayList<>(map.values());
+            if (!textdictInfos.isEmpty()) {
+                // 保存到数据库,从系统推荐中获取roleId
+                Map<String, TextdictInfo> collect = textdictInfos.stream().collect(Collectors.toMap(info -> info.getColKey() + info.getColName(), v -> v, (v1, v2) -> v1));
+                for (TextdictInfoVO vo : textdictList) {
+                    TextdictInfo info = collect.get(vo.getColKey() + vo.getColName());
+                    if (info != null) {
+                        vo.setId(info.getId());
+                        vo.setProjectId("0");
+                        BeanUtil.copyProperties(vo, info);
+                    }
+                }
+                List<TextdictInfo> list = textdictInfos.stream().filter(info -> StringUtil.hasText(info.getSigRoleId())).collect(Collectors.toList());
+                this.saveBatch( list);
+            }
+        }
+        if (textdict.isEmpty()) {
+            textdict = textdictList;
+            if (textdict != null) {
+                textdict.forEach(textdictInfoVO -> textdictInfoVO.setIsSystem(2));
+            }
+            addSign(textdict, doc, privateInfo, dqid, textdict);
+        } else if (textdictList != null && !textdictList.isEmpty()) {
+            Map<String, Map<String, TextdictInfoVO>> map = textdict.stream().filter(vo -> vo.getColKey() != null && vo.getColKey().contains("__")).collect(Collectors.groupingBy(vo -> vo.getColKey().split("__")[1], Collectors.toMap(TextdictInfoVO::getSigRoleId, v -> v, (v1, v2) -> v1)));
+            List<TextdictInfoVO> collect = textdictList.stream().filter(textdictInfoVO -> {
+                if (textdictInfoVO.getColKey() == null || !textdictInfoVO.getColKey().contains("__")) {
+                    return true;
+                }
+                Map<String, TextdictInfoVO> voMap = map.get(textdictInfoVO.getColKey().split("__")[1]);
+                textdictInfoVO.setIsSystem(2);
+                if (voMap != null && !voMap.isEmpty() ) {
+                    return voMap.get(textdictInfoVO.getSigRoleId()) == null;
+                }
+                return true;
+            }).collect(Collectors.toList());
+            textdict.addAll(collect);
+            addSign(collect, doc, privateInfo, dqid, textdict);
+        }
+        return textdict;
+    }
+
+    @NotNull
+    private List<TextdictInfoVO> getTextdictInfoByDqIdAndKeyName(List<TextdictInfoVO> textdict, Map<String, String> dqIdMap, Map<String, String> keys, List<TextdictInfo> textdictInfos) {
+        if (textdict == null) {
+            textdict = new ArrayList<>();
+        }
+        Map<String, TextdictInfoVO> map = textdict.stream().collect(Collectors.toMap(item -> item.getId() + "", v -> v, (v1, v2) -> v2));
+        dqIdMap.forEach((k, v) -> {
+            if (map.containsKey(k)) {
+                return;
+            }
+            Long id = null;
+            try {
+                id = Long.parseLong(k);
+            } catch (Exception e) {
+                log.warn(e.getMessage());
+            }
+            String colName = keys.get(v);
+            if (id == null || v == null || colName == null) {
+                return;
+            }
+            TextdictInfo info = new TextdictInfo();
+            info.setId(id);
+            info.setColKey(v);
+            info.setColName(colName);
+            textdictInfos.add(info);
+        });
+        if (!textdictInfos.isEmpty()) {
+            List<TextdictInfoVO> list = baseMapper.selectTextDictInfoByIdAndColKeyAndColName(textdictInfos);
+            Map<String, TextdictInfoVO> voMap = list.stream().collect(Collectors.toMap(item -> item.getId() + item.getColKey() + item.getColName(), item -> item, (v1, v2) -> v1));
+            Collection<TextdictInfoVO> values = voMap.values();
+            values.forEach(item -> item.setIsSystem(2));
+            textdict.addAll(values);
+            textdictInfos.removeIf(item -> voMap.containsKey(item.getId() + item.getColKey() + item.getColName()));
+        }
+        return textdict;
+    }
+
     private void addSign(List<TextdictInfoVO> collect, Document doc, WbsTreePrivate privateInfo, List<String> dqid,List<TextdictInfoVO> allTextdict) {
         if (collect == null || collect.isEmpty()) {
             return;

+ 179 - 67
blade-service/blade-user/src/main/java/org/springblade/system/user/service/impl/UserServiceImpl.java

@@ -82,6 +82,8 @@ import java.io.File;
 import java.io.FileNotFoundException;
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.function.Function;
 import java.util.stream.Collectors;
@@ -806,11 +808,12 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
                                         Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(WbsTreeContractLazyVO::getPKeyId))),
                                         ArrayList::new
                                 ));
+
                         /*获取当前合同段节点对应的资料填报QueryInfo本地缓存信息*/
                         List<WbsTreeContractLazyQueryInfoVO> queryInfoList = this.getQueryInfoList(contractId, tableOwner);
                         Map<Long, Integer> queryInfoMaps = queryInfoList.stream().filter(f -> Func.isNotEmpty(f.getWbsId())&&Func.isNotEmpty(f.getStatus()))
                                 .collect(Collectors.toMap(WbsTreeContractLazyQueryInfoVO::getWbsId, WbsTreeContractLazyQueryInfoVO::getStatus, (existingValue, newValue) -> existingValue));
-                        List<Long> pKeyIdList = new ArrayList<>(queryInfoMaps.keySet());
+//                        List<Long> pKeyIdList = new ArrayList<>(queryInfoMaps.keySet());
 
                         /* ================ 处理数量 ================ */
                         List<WbsTreeContractLazyVO> lowestNodesTB = distinctLowestNodesAll.parallelStream().filter(f -> queryInfoMaps.containsKey(f.getPKeyId())).collect(Collectors.toList());
@@ -830,11 +833,12 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
                         long startTime = System.currentTimeMillis();
 //                        List<NodeVO> nodeVOList = distinctNodesAll.stream().map(this::convertToNodeVO).collect(Collectors.toList());
 //                        Map<Long, NodeVO> nodeVOMap = nodeVOList.stream().collect(Collectors.toMap(NodeVO::getId, vo -> vo, (existing, replacement) -> existing));
-                        List<NodeVO> treeNodeVOList = this.buildNodeTreeByStream1(distinctNodesAll, lowestNodesMap);
+//                        List<NodeVO> treeNodeVOList = this.buildNodeTreeByStream1(distinctNodesAll, lowestNodesMap);
 //                        NodeVO.calculateStatusToDFS(treeNodeVOList, nodeVOMap);
                         Map<Long, Integer> nodeColorStatusMap = new HashMap<>();
-                        NodeVO.calculateStatusToDFS1(treeNodeVOList, nodeColorStatusMap);
+//                        NodeVO.calculateStatusToDFS1(treeNodeVOList, nodeColorStatusMap);
 //                        buildNodeTreeByStream(distinctNodesAll, lowestNodesMap, nodeColorStatusMap);
+                        buildNodeTreeAndCalculateStatus(distinctNodesAll, lowestNodesMap, nodeColorStatusMap);
                         // 将树形结构展开成列表
 //                        List<NodeVO> nodeVOS = this.flattenTree(treeNodeVOList);
 //                        Map<Long, Integer> nodeColorStatusMap = nodeVOS.stream().collect(Collectors.toMap(NodeVO::getPKeyId, NodeVO::getStatus, (existing, replacement) -> existing));
@@ -955,9 +959,9 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
 
                                 Map<Long, Integer> queryInfoMaps = queryInfoList.stream().filter(f -> cn.hutool.core.util.ObjectUtil.isNotEmpty(f.getWbsId()))
                                         .collect(Collectors.toMap(WbsTreeContractLazyQueryInfoVO::getWbsId, WbsTreeContractLazyQueryInfoVO::getStatus, (existingValue, newValue) -> existingValue));
-                                List<Long> pKeyIdList = new ArrayList<>(queryInfoMaps.keySet());
+//                                List<Long> pKeyIdList = new ArrayList<>(queryInfoMaps.keySet());
 
-                                List<WbsTreeContractLazyVO> lowestNodesTB = distinctLowestNodesAll.parallelStream().filter(f -> pKeyIdList.contains(f.getPKeyId())).collect(Collectors.toList());
+                                List<WbsTreeContractLazyVO> lowestNodesTB = distinctLowestNodesAll.parallelStream().filter(f -> queryInfoMaps.containsKey(f.getPKeyId())).collect(Collectors.toList());
                                 List<Long> lowestNodeParentIdsTB = lowestNodesTB.parallelStream().map(WbsTreeContractLazyVO::getParentId).collect(Collectors.toList());
                                 List<WbsTreeContractLazyVO> resultParentNodesTB = this.getCachedParentCountNodes(sgContractId, lowestNodeParentIdsTB, nodesAll, tableOwner);
                                 Map<Long, WbsTreeContractLazyVO> lowestNodesMap = lowestNodesTB.stream()
@@ -972,13 +976,14 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
 
 //                                List<NodeVO> nodeVOList = distinctNodesAll.stream().map(this::convertToNodeVO).collect(Collectors.toList());
 //                                Map<Long, NodeVO> nodeVOMap = nodeVOList.stream().collect(Collectors.toMap(NodeVO::getId, vo -> vo, (existing, replacement) -> existing));
-                                List<NodeVO> treeNodeVOList = this.buildNodeTreeByStream1(distinctNodesAll, lowestNodesMap);
+//                                List<NodeVO> treeNodeVOList = this.buildNodeTreeByStream1(distinctNodesAll, lowestNodesMap);
 //                                NodeVO.calculateStatusToDFS(treeNodeVOList, nodeVOMap);
 //                                List<NodeVO> nodeVOS = this.flattenTree(treeNodeVOList);
 //                                Map<Long, Integer> nodeColorStatusMap = nodeVOS.stream().collect(Collectors.toMap(NodeVO::getPKeyId, NodeVO::getStatus, (existing, replacement) -> existing));
                                 Map<Long, Integer> nodeColorStatusMap = new HashMap<>();
-                                NodeVO.calculateStatusToDFS1(treeNodeVOList, nodeColorStatusMap);
+//                                NodeVO.calculateStatusToDFS1(treeNodeVOList, nodeColorStatusMap);
 //                                buildNodeTreeByStream(distinctNodesAll, lowestNodesMap, nodeColorStatusMap);
+                                buildNodeTreeAndCalculateStatus(distinctNodesAll, lowestNodesMap, nodeColorStatusMap);
                                 if (lazyNodes.size() > 0) {
                                     Map<Long, Integer> countMap = new HashMap<>();
                                     for (WbsTreeContractLazyVO node : resultParentNodesTB) {
@@ -1301,6 +1306,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
     }
 
 
+
     private List<PrivateTreeVO> buildTree(List<WbsTreePrivate> wbsTreePrivatesNodes, String projectId) {
         List<PrivateTreeVO> privateTreeVOS = BeanUtil.copyProperties(wbsTreePrivatesNodes, PrivateTreeVO.class);
         if (!privateTreeVOS.isEmpty()) {
@@ -1349,34 +1355,68 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
             long startTime = System.currentTimeMillis();
 
             /*分页查询,每次5000条*/
-            int pageSize = 5000;
+            int pageSize = 10000;
             int pageNumber = 1;
-            int offset;
-
-            nodesAll = new ArrayList<>();
-            List<WbsTreeContractLazyVO> nodesAllPage;
-            do {
-                offset = (pageNumber - 1) * pageSize;
-                nodesAllPage = jdbcTemplate.query(
-                        "SELECT p_key_id,id,parent_id " +
-                                ",sort,create_time,IFNULL(if(LENGTH (trim(full_name)) > 0, full_name, node_name), node_name) AS fullName " +
-                                "FROM m_wbs_tree_contract " +
-                                "WHERE type = 1 " +
-                                "AND status = 1 " +
-                                "AND is_deleted = 0 " +
-                                "AND contract_id = ? " +
-                                "LIMIT ? OFFSET ?",
-                        new Object[]{contractId, pageSize, offset},
-                        new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class)
-                );
-                nodesAll.addAll(nodesAllPage);
-                pageNumber++;
-            } while (nodesAllPage.size() == pageSize);
+//            int offset;
+
+            List<WbsTreeContractLazyVO> nodes = new CopyOnWriteArrayList<>();
+//            List<WbsTreeContractLazyVO> nodesAllPage;
+            Integer count = jdbcTemplate.queryForObject("select count(1) FROM m_wbs_tree_contract where type = 1 and status = 1 and is_deleted = 0 and contract_id = " + contractId, Integer.class);
+            if (count != null && count > 0) {
+                int pageCount = count % pageSize == 0 ? count / pageSize : count / pageSize + 1;
+                CountDownLatch countDownLatch = new CountDownLatch(pageCount);
+                for (int i = 1; i <= pageCount; i++) {
+                    int offset = (i - 1) * pageSize;
+                    new Thread(() -> {
+                        try {
+                            List<WbsTreeContractLazyVO> query = jdbcTemplate.query(
+                                    "SELECT p_key_id,id,parent_id " +
+                                            ",sort,create_time,IFNULL(if(LENGTH (trim(full_name)) > 0, full_name, node_name), node_name) AS fullName " +
+                                            "FROM m_wbs_tree_contract " +
+                                            "WHERE type = 1 " +
+                                            "AND status = 1 " +
+                                            "AND is_deleted = 0 " +
+                                            "AND contract_id = ? " +
+                                            "LIMIT ? OFFSET ?",
+                                    new Object[]{contractId, pageSize, offset},
+                                    new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
+                            nodes.addAll(query);
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                        }
+                        countDownLatch.countDown();
+                    }).start();
+                }
+                try {
+                    countDownLatch.await();
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+            }
+//            do {
+//                offset = (pageNumber - 1) * pageSize;
+//                nodesAllPage = jdbcTemplate.query(
+//                        "SELECT p_key_id,id,parent_id " +
+//                                ",sort,create_time,IFNULL(if(LENGTH (trim(full_name)) > 0, full_name, node_name), node_name) AS fullName " +
+//                                "FROM m_wbs_tree_contract " +
+//                                "WHERE type = 1 " +
+//                                "AND status = 1 " +
+//                                "AND is_deleted = 0 " +
+//                                "AND contract_id = ? " +
+//                                "LIMIT ? OFFSET ?",
+//                        new Object[]{contractId, pageSize, offset},
+////                        new Object[]{contractId},
+//                        new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class)
+//                );
+//                nodesAll.addAll(nodesAllPage);
+//            nodesAll = nodesAllPage;
+//                pageNumber++;
+//            } while (nodesAllPage.size() == pageSize);
 
             long endTime = System.currentTimeMillis();
             long executionTime = endTime - startTime;
             _logger.info("合同段 " + contractId + " 查询所有wbs节点树 执行时间:" + executionTime + " ms");
-
+            nodesAll = nodes;
             if (nodesAll.size() > 0) {
                 //判断是否有子级,赋值
                 Map<Long, List<WbsTreeContractLazyVO>> groupedByParentId = nodesAll.stream()
@@ -1394,7 +1434,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
                     }
                 }
                 //更新本地缓存
-//                localCacheNodes.put(contractId, nodesAll);
+                localCacheNodes.put(contractId, nodesAll);
             }
         }
         return nodesAll;
@@ -1422,21 +1462,22 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
         long startTime = System.currentTimeMillis();
 
         /*分页查询,每次5000条*/
-        int pageSize = 5000;
-        int pageNumber = 1;
-        int offset;
+//        int pageSize = 5000;
+//        int pageNumber = 1;
+//        int offset;
 
         List<WbsTreeContractLazyQueryInfoVO> queryInfoListPage;
 
-        do {
-            offset = (pageNumber - 1) * pageSize;
+//        do {
+//            offset = (pageNumber - 1) * pageSize;
             queryInfoListPage = jdbcTemplate.query(
-                    "SELECT wbs_id, `status` FROM u_information_query WHERE id in (SELECT id from (SELECT max(id) as id FROM u_information_query WHERE type = 1 AND contract_id = ? AND classify = ? GROUP BY wbs_id LIMIT ? offset ?) as a)",
-                    new Object[]{contractId, tableOwner, pageSize, offset},
+                    "SELECT wbs_id, `status` FROM u_information_query WHERE id in (SELECT id from (SELECT max(id) as id FROM u_information_query WHERE is_deleted = 0 AND type = 1 AND contract_id = ? AND classify = ? GROUP BY wbs_id) as a)",
+                    new Object[]{contractId, tableOwner},
+//                    new Object[]{contractId, tableOwner, pageSize, offset},
                     new BeanPropertyRowMapper<>(WbsTreeContractLazyQueryInfoVO.class));
             queryInfoList.addAll(queryInfoListPage);
-            pageNumber++;
-        } while (queryInfoListPage.size() == pageSize);
+//            pageNumber++;
+//        } while (queryInfoListPage.size() == pageSize);
 
         long endTime = System.currentTimeMillis();
         long executionTime = endTime - startTime;
@@ -1444,7 +1485,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
 
         if (queryInfoList.size() > 0) {
             //更新本地缓存
-//            localCacheQueryInfos.put(cacheKey, queryInfoList);
+            localCacheQueryInfos.put(cacheKey, queryInfoList);
         }
         return queryInfoList;
     }
@@ -1471,15 +1512,16 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
             /*重新计算,进行递归获取父节点计数统计*/
 //            this.recursiveGetParentNodes(resultParentNodesTB, lowestNodeParentIdsTB, nodesAll);
             Map<Long, List<WbsTreeContractLazyVO>> map = nodesAll.stream().collect(Collectors.groupingBy(WbsTreeContractLazyVO::getId));
-            recursiveGetParentNodes(resultParentNodesTB, lowestNodeParentIdsTB, map);
+//            recursiveGetParentNodes(resultParentNodesTB, lowestNodeParentIdsTB, map);
+            queueGetParentNodes(resultParentNodesTB, lowestNodeParentIdsTB, map);
             long endTime = System.currentTimeMillis();
             long executionTime = endTime - startTime;
             _logger.info("合同段 " + contractId + " wbs节点树 数量计算 执行时间:" + executionTime + " ms");
 
-//            if (resultParentNodesTB.size() > 0) {
-//                //更新本地缓存
-//                localCacheParentCountNodes.put(cacheKey, resultParentNodesTB);
-//            }
+            if (resultParentNodesTB.size() > 0) {
+                //更新本地缓存
+                localCacheParentCountNodes.put(cacheKey, resultParentNodesTB);
+            }
         }
         return resultParentNodesTB;
     }
@@ -1556,6 +1598,40 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
             this.recursiveGetParentNodes(result, collect, nodeMap);
         }
     }
+    public void queueGetParentNodes(List<WbsTreeContractLazyVO> result, List<Long> lowestNodeParentIds, Map<Long, List<WbsTreeContractLazyVO>> nodeMap) {
+        if (lowestNodeParentIds == null || lowestNodeParentIds.isEmpty()) {
+            return;
+        }
+        Queue<Long> nodeIdQueue = new LinkedList<>(lowestNodeParentIds);
+        while (!nodeIdQueue.isEmpty()) {
+            Map<Long, Long> parentIdGroup = nodeIdQueue.stream()
+                .collect(Collectors.groupingByConcurrent(Function.identity(), Collectors.counting()));
+
+            List<WbsTreeContractLazyVO> collectedNodes = parentIdGroup.entrySet().stream()
+                .flatMap(entry -> {
+                    List<WbsTreeContractLazyVO> nodes = nodeMap.get(entry.getKey());
+                    if (nodes == null || nodes.isEmpty()) {
+                        return Stream.empty();
+                    }
+                    if (entry.getValue() > 1L) {
+                        nodes = nodes.stream().limit(1)
+                            .flatMap(node -> Collections.nCopies(entry.getValue().intValue(), node).stream())
+                            .collect(Collectors.toList());
+                    }
+                    return nodes.stream();
+                })
+                .collect(Collectors.toList());
+            List<Long> collect = collectedNodes.stream()
+                .map(WbsTreeContractLazyVO::getParentId).filter(Objects::nonNull)
+                .collect(Collectors.toList());
+            if (!collect.isEmpty()) {
+                result.addAll(collectedNodes);
+                nodeIdQueue = new LinkedList<>(collect);
+            } else {
+                nodeIdQueue.clear();
+            }
+        }
+    }
 
 
     /**
@@ -1612,24 +1688,11 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
         return result;
     }
 
-    /**
-     * 构造树形结构数据 (解决节点颜色问题)
-     *
-     * @param distinctNodesAll 去重后所有节点数据
-     * @return
-     */
-    public List<NodeVO> buildNodeTreeByStream1(List<WbsTreeContractLazyVO> distinctNodesAll,
-                                              Map<Long, WbsTreeContractLazyVO> lowestNodesMap) {
-        List<WbsTreeContractLazyVO> list = distinctNodesAll.stream().filter(f->f.getParentId()!=null).filter(f -> f.getParentId().equals(0L)).collect(Collectors.toList());
-        Map<Long, List<WbsTreeContractLazyVO>> map = distinctNodesAll.stream().filter(f->f.getParentId()!=null).collect(Collectors.groupingBy(WbsTreeContractLazyVO::getParentId));
-        Map<Long, NodeVO> nodeVOMap = new HashMap<>();
-        return recursionFnNodeTree(list, map, lowestNodesMap,nodeVOMap);
-    }
 
-    public List<NodeVO> recursionFnNodeTree
+    public Set<Integer> buildNodeTreeAndCalculateStatus
             (List<WbsTreeContractLazyVO> list, Map<Long, List<WbsTreeContractLazyVO>> map,
-             Map<Long, WbsTreeContractLazyVO> lowestNodesMap, Map<Long, NodeVO> nodeVOMap) {
-        List<NodeVO> result = new ArrayList<>();
+             Map<Long, WbsTreeContractLazyVO> lowestNodesMap, Map<Long, Integer> nodeVOMap, Map<Long, Integer> nodeColorStatusMap) {
+        Set<Integer> result = new HashSet<>();
         for (WbsTreeContractLazyVO vo : list) {
             if (vo.getHasChildren().equals(0)) {
                 WbsTreeContractLazyVO lowestNodeVO = lowestNodesMap.getOrDefault(vo.getPKeyId(), null);
@@ -1641,21 +1704,70 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
                 //非最底层节点,颜色默认=1黑色
                 vo.setColorStatus(1);
             }
-            //转换为NodeVO
-            NodeVO nodeVO = convertToNodeVO(vo);
-            nodeVOMap.put(nodeVO.getPKeyId(), nodeVO);
+            Integer status = vo.getColorStatus() != null ? vo.getColorStatus() : 1;
+            nodeVOMap.put(vo.getPKeyId(), status);
             List<WbsTreeContractLazyVO> childrenList = map.get(vo.getId());
             if (childrenList != null && !childrenList.isEmpty()) {
                 List<WbsTreeContractLazyVO> collect = childrenList.stream().filter(child -> !nodeVOMap.containsKey(child.getPKeyId()))
                         .collect(Collectors.toList());
                 if (!collect.isEmpty()) {
-                    nodeVO.setChildren(recursionFnNodeTree(collect, map, lowestNodesMap, nodeVOMap));
+                    Set<Integer> nodeVOS = buildNodeTreeAndCalculateStatus(collect, map, lowestNodesMap, nodeVOMap, nodeColorStatusMap);
+                    Integer status1 = calculateNodeStatus(nodeVOS);
+                    if (status1 != null) {
+                        status = status1;
+                    }
+                    nodeColorStatusMap.put(vo.getPKeyId(), status);
                 }
             }
-            result.add(nodeVO);
+            result.add(status);
         }
         return result;
     }
+    // 1 未填报 2已填报 3待审批 4 已审批
+    public Integer calculateNodeStatus(Set<Integer> childStatusList) {
+        //最底层节点直接返回
+        if (childStatusList ==  null || childStatusList.isEmpty()) {
+            return null;
+        }
+        //判断子级
+        //如果子节点都是相同的状态,则父节点状态也为该状态
+        if (childStatusList.size() == 1) {
+            return childStatusList.iterator().next();
+        }
+        //判断是否存在同时只存在1、3的情况
+        if (childStatusList.contains(1) && childStatusList.contains(3) && !childStatusList.contains(2)) {
+            return 2;
+        }
+        //判断是否存在同时只存在3、4的情况
+        if (childStatusList.contains(3) && childStatusList.contains(4) && !childStatusList.contains(1) && !childStatusList.contains(2)) {
+            return 3;
+        }
+        //判断是否存在只有1但不全是1的情况
+        if (childStatusList.contains(1) && !childStatusList.contains(2) && !childStatusList.contains(3) && !childStatusList.contains(4)) {
+            return 2;
+        }
+
+        //判断是否存在只有2但不全是2的情况
+        if (childStatusList.contains(2) && !childStatusList.contains(1) && !childStatusList.contains(3) && !childStatusList.contains(4)) {
+            return 2;
+        }
+
+        //判断是否存在只有3但不全是3的情况
+        if (childStatusList.contains(3) && !childStatusList.contains(1) && !childStatusList.contains(2) && !childStatusList.contains(4)) {
+            return 3;
+        }
+
+        //其他情况,父节点状态默认为2
+        return 2;
+    }
+
+    public void buildNodeTreeAndCalculateStatus(List<WbsTreeContractLazyVO> distinctNodesAll,
+                                                        Map<Long, WbsTreeContractLazyVO> lowestNodesMap,Map<Long, Integer> nodeColorStatusMap) {
+        List<WbsTreeContractLazyVO> list = distinctNodesAll.stream().filter(f->f.getParentId()!=null).filter(f -> f.getParentId().equals(0L)).collect(Collectors.toList());
+        Map<Long, List<WbsTreeContractLazyVO>> map = distinctNodesAll.stream().filter(f->f.getParentId()!=null).collect(Collectors.groupingBy(WbsTreeContractLazyVO::getParentId));
+        Map<Long, Integer> nodeVOMap = new HashMap<>();
+        buildNodeTreeAndCalculateStatus(list, map, lowestNodesMap,nodeVOMap, nodeColorStatusMap);
+    }
 
     /**
      * 树形层级结构转为普通List