浏览代码

Merge branch 'dev' of http://219.151.181.73:3000/zhuwei/bladex into dev

laibulaizheli 3 周之前
父节点
当前提交
fe529d9565
共有 31 个文件被更改,包括 663 次插入279 次删除
  1. 0 6
      blade-common/pom.xml
  2. 0 11
      blade-common/src/main/java/org/springblade/common/utils/AsyncConfigurer.java
  3. 12 6
      blade-common/src/main/java/org/springblade/common/utils/DeepSeekClient.java
  4. 28 0
      blade-common/src/main/java/org/springblade/common/utils/singleEexConfigurer.java
  5. 10 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ParameterElement.java
  6. 3 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/WbsTreeContract.java
  7. 4 5
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveFileTaskController.java
  8. 1 3
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchivesAutoController.java
  9. 2 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/external/impl/ExternalDataArchiveMetaService.java
  10. 119 68
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java
  11. 1 1
      blade-service/blade-business/pom.xml
  12. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/feignClient/InformationQueryClientImpl.java
  13. 5 1
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/ArchiveFileServiceImpl.java
  14. 2 1
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialNumberRuleServiceImpl.java
  15. 1 1
      blade-service/blade-control/pom.xml
  16. 4 0
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/EVDataServiceImpl.java
  17. 1 1
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/EVisaServiceImpl.java
  18. 4 2
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/utils/PDFUtils.java
  19. 1 1
      blade-service/blade-manager/pom.xml
  20. 42 17
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java
  21. 2 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/NodeBaseInfoController.java
  22. 9 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/TableElementConverter.java
  23. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreeContractMapper.xml
  24. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/INodeBaseInfoService.java
  25. 9 11
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeContractServiceImpl.java
  26. 8 7
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java
  27. 63 45
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java
  28. 106 26
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/NodeBaseInfoServiceImpl.java
  29. 12 12
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeContractServiceImpl.java
  30. 12 5
      blade-service/blade-manager/src/main/java/org/springblade/manager/utils/TableCoordinates.java
  31. 199 44
      blade-service/blade-user/src/main/java/org/springblade/system/user/service/impl/UserServiceImpl.java

+ 0 - 6
blade-common/pom.xml

@@ -64,12 +64,6 @@
             <scope>compile</scope>
         </dependency>
 
-<!--        <dependency>-->
-<!--            <groupId>com.google.collections</groupId>-->
-<!--            <artifactId>google-collections</artifactId>-->
-<!--            <version>1.0-rc2</version>-->
-<!--        </dependency>-->
-
         <dependency>
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>

+ 0 - 11
blade-common/src/main/java/org/springblade/common/utils/AsyncConfigurer.java

@@ -31,15 +31,4 @@ public class AsyncConfigurer {
                 , new ThreadPoolExecutor.DiscardOldestPolicy(), "manager-thread-pool");
     }
 
-    /**
-     * 线程池配置
-     *
-     * @return
-     */
-    /*@Bean("singleExecutor")
-    public ExecutorService getSingleExecutor() {
-        log.info("线程池初始化......");
-        return Executors.newSingleThreadExecutor();
-    }*/
-
 }

+ 12 - 6
blade-common/src/main/java/org/springblade/common/utils/DeepSeekClient.java

@@ -1,14 +1,15 @@
-package org.springblade.common.utils;
 
+package org.springblade.common.utils;
 import com.google.gson.Gson;
+
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParser;
 import okhttp3.*;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Component;
 
+
 import java.io.IOException;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
@@ -32,9 +33,10 @@ public class DeepSeekClient {
                 .build();
     }
 
-    /**
+/**
      * 请求 DeepSeek API
      */
+
     public String callDeepSeek(String prompt) throws IOException {
         DeepSeekRequest request = new DeepSeekRequest(prompt, "deepseek-chat");
         String requestJson = gson.toJson(request);
@@ -59,9 +61,11 @@ public class DeepSeekClient {
         }
     }
 
-    /**
+
+/**
      * 解析响应获取结果
      */
+
     public String analysisResponse(String responseJson) {
         try {
             JsonObject jsonObject = JsonParser.parseString(responseJson).getAsJsonObject();
@@ -87,9 +91,11 @@ public class DeepSeekClient {
         }
     }
 
-    /**
+
+/**
      * 直接获取精简后的内容
      */
+
     public String getSimplifiedContent(String prompt) {
         try {
             String response = callDeepSeek(prompt);
@@ -235,4 +241,4 @@ public class DeepSeekClient {
             }
         }
     }
-}
+}

+ 28 - 0
blade-common/src/main/java/org/springblade/common/utils/singleEexConfigurer.java

@@ -0,0 +1,28 @@
+package org.springblade.common.utils;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.scheduling.annotation.EnableAsync;
+
+import java.util.concurrent.*;
+
+@Slf4j
+@Configuration
+@EnableAsync
+public class singleEexConfigurer {
+
+    /**
+     * 线程池配置
+     *
+     * @return
+     */
+    @Bean("singleExecutor")
+    @Primary
+    public ExecutorService getSingleExecutor() {
+        log.info("线程池初始化......");
+        return Executors.newSingleThreadExecutor();
+    }
+
+}

+ 10 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ParameterElement.java

@@ -58,6 +58,16 @@ public class ParameterElement extends BaseEntity {
 	*/
 		private String contractId;
 
+	private String nodeId;
 
+	/**
+	 * 参数类型
+	 */
+	private String paramType;
+
+	/**
+	 * 参数
+	 */
+	private String parameter;
 
 }

+ 3 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/WbsTreeContract.java

@@ -216,6 +216,9 @@ public class WbsTreeContract extends BaseEntity {
     @ApiModelProperty(value = "原id,如果当前字段有数据则说明这条数据是复制节点")
     private String oldId;
 
+    @ApiModelProperty(value = "被复制节点p_key_id")
+    private String copyPkId;
+
     /**
      * 表单是否上传附件1否
      */

+ 4 - 5
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveFileTaskController.java

@@ -67,7 +67,8 @@ public class ArchiveFileTaskController extends BladeController {
             List<ArchiveFile> archiveFileList = jdbcTemplate.query("select * from u_archive_file where id in(" + ids + ")", new BeanPropertyRowMapper<>(ArchiveFile.class));
             if (archiveFileList.size() > 0) {
                 //固定水印图片章
-                String pngQzUrl = "https://blade-oss-chongqing.oss-cn-shenzhen.aliyuncs.com//upload/20250221/7686a428dd1fe2cc7086dae94f0b3a9d.png";
+                String pngQzUrl = "https://xinan1.zos.ctyun.cn/blade-oss-chongqing/upload/20250221/7686a428dd1fe2cc7086dae94f0b3a9d.png";
+                String reData = "";
                 for (ArchiveFile archiveFile : archiveFileList) {
                     if (Arrays.asList(1, 2).contains(archiveFile.getStatus())) {
                         throw new ServiceException("只有【未上报 或 已废除】状态的业务数据才能认证!");
@@ -110,13 +111,11 @@ public class ArchiveFileTaskController extends BladeController {
                         //TODO ============= 电签认证 =============
                         String resultMsg = this.eVisaClient.eVisaCustom(eVISATaskArchiveDTO);
                         if (StringUtils.isEmpty(resultMsg) || ("500").equals(resultMsg)) {
-                            throw new ServiceException("电签服务发生异常,请联系管理员!");
-                        }
-                        if (resultMsg.contains("success@@@@")) {
-                            return R.data(true);
+                            reData = reData+archiveFile.getFileName()+"认证失败";
                         }
                     }
                 }
+                return R.success(reData);
             }
             return R.fail("操作失败");
         }

+ 1 - 3
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchivesAutoController.java

@@ -44,7 +44,7 @@ import org.springblade.archive.vo.*;
 import org.springblade.business.entity.ArchiveFile;
 import org.springblade.business.feign.ArchiveFileClient;
 import org.springblade.business.vo.NeiYeLedgerVO1;
-import org.springblade.common.utils.DeepSeekClient;
+//import org.springblade.common.utils.DeepSeekClient;
 import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
@@ -101,8 +101,6 @@ public class ArchivesAutoController extends BladeController {
 
 	private final ProjectClient projectClient;
 
-	@Autowired
-	private ExecutorService executorService;
 	@Autowired
 	private ITraceLogService iTraceLogService;
     private final JdbcTemplate jdbcTemplate;

+ 2 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/external/impl/ExternalDataArchiveMetaService.java

@@ -14,6 +14,7 @@ import org.springframework.dao.DataAccessException;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Service;
 
+import javax.annotation.Resource;
 import java.util.*;
 import java.util.concurrent.ExecutorService;
 import java.util.stream.Collectors;
@@ -24,6 +25,7 @@ public class ExternalDataArchiveMetaService {
 
     private final JdbcTemplate jdbcTemplate;
 
+    @Resource(name = "singleExecutor")
     private ExecutorService executorService;
 
     private ArchivesAutoMapper autoMapper;

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

@@ -24,7 +24,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
-import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -86,10 +86,12 @@ import org.springframework.transaction.annotation.Transactional;
 
 import org.springframework.web.multipart.MultipartFile;
 
+import javax.annotation.Resource;
 import javax.servlet.http.HttpServletResponse;
 import java.io.*;
 import java.math.BigDecimal;
 import java.net.URL;
+import java.net.URLEncoder;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
@@ -101,6 +103,9 @@ import java.util.concurrent.ExecutorService;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Collectors;
+import java.util.zip.Deflater;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
 
 /**
  *  服务实现类
@@ -120,7 +125,7 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 	private ProjectClient projectClient;
 	private final ArchivesAutoMapper autoMapper;
 
-	@Autowired
+	@Resource(name = "singleExecutor")
 	private ExecutorService executorService;
 
 	private Map<String, Integer> indexMap = new HashMap<>(); //按立卷位区分和生成流水号
@@ -252,9 +257,7 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 					secretLevelMap.put("2", "绝密");
 					secretLevelMap.put("3", "秘密");
 					secretLevelMap.put("4", "公开");
-
 					aa.setSecretLevelValue(secretLevelMap.getOrDefault(aa.getSecretLevel(), "秘密"));
-					//aa.setSecretLevelValue("1".equals(aa.getSecretLevel()) ? "机密" : ("2".equals(aa.getSecretLevel()) ? "绝密" : "秘密"));
 				}
 			});
 		}
@@ -441,6 +444,9 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 				}else {
 					fileUrl = frontUrl;
 				}
+				if (fileUrl.contains("$$$")) {
+					fileUrl = fileUrl.substring(0, fileUrl.indexOf("$$$"));
+				}
 				if (frontUrl.contains("$$$")) {
 					fileId = frontUrl.substring(frontUrl.indexOf("$$$") + 3);
 				} else {
@@ -3699,82 +3705,127 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 	@Override
 	public void batchDownloadFileToZip(String ids, HttpServletResponse response) {
 		List<Long> longs = Func.toLongList(ids);
-		//获取档案下的文件
+		// 获取档案下的文件
 		List<ArchiveFile> result = baseMapper.batchSearchArchiveFile(longs);
-		//判断是否存在文件
-		if (result != null && result.size() > 0) {
-			//获取选择的案卷,只要id和文件提名字段
-			Map<Long, String> nameMap = baseMapper.getArchives(longs).stream().filter(l -> StringUtils.isNotBlank(l.getName())).collect(Collectors.toMap(l -> l.getId(), l -> l.getName()));
-			//默认下载地址
-			String defaultDir = "/www/wwwroot/Users/hongchuangyanfa/Desktop/archiveDownload";
-			//项目下地址
-			String projectDir = defaultDir + "/" + result.get(0).getProjectId();
-			File file = new File(projectDir);
-			//获取项目名称
-			ProjectInfo projectInfo = projectClient.getById(result.get(0).getProjectId());
-			//判断文件夹是否存在,存在则该项目正在下载打包,不存在则生成
-			if (file.exists()) {
-				throw new ServiceException("当前项目正在下载档案,请稍后再试");
-			} else {
-				file.mkdir();
+
+		if (CollectionUtils.isEmpty(result)) {
+			throw new ServiceException("未找到可下载的文件");
+		}
+
+		// 获取选择的案卷名称映射
+		Map<Long, String> nameMap = baseMapper.getArchives(longs).stream()
+				.filter(l -> StringUtils.isNotBlank(l.getName()))
+				.collect(Collectors.toMap(l -> l.getId(), l -> l.getName()));
+
+		// 使用临时目录而不是固定目录,避免并发问题
+		String tempDir = System.getProperty("java.io.tmpdir") + "/archive_download_" + UUID.randomUUID();
+		String projectDir = tempDir + "/" + result.get(0).getProjectId();
+		File projectDirFile = new File(projectDir);
+
+		try {
+			// 创建项目目录
+			if (!projectDirFile.mkdirs()) {
+				throw new ServiceException("无法创建临时目录");
 			}
-			//删除掉pdfUrl为空的数据
+
+			// 获取项目信息
+			ProjectInfo projectInfo = projectClient.getById(result.get(0).getProjectId());
+			String zipFileName = projectInfo.getId() + ".zip";
+
+			// 过滤掉无PDF的文件
 			result.removeIf(query -> StringUtils.isEmpty(query.getPdfFileUrl()));
-			//按照档案id分组
-			Map<Long, List<ArchiveFile>> map = result.stream().collect(Collectors.groupingBy(ArchiveFile::getArchiveId));
-			try {
-				//为每个档案分别设置
-				for (Long archiveId : map.keySet()) {
-					String initName = nameMap.get(archiveId);
-					String[] split = initName.split(")");
-					String name = split[split.length - 1];
-					String archiveDir = projectDir + "/" + name;
-					//创建档案文件夹
-					File file2 = new File(archiveDir);
-					file2.mkdir();
-					//组卷,下载PDF
+
+			// 按照档案id分组
+			Map<Long, List<ArchiveFile>> archiveFilesMap = result.stream()
+					.collect(Collectors.groupingBy(ArchiveFile::getArchiveId));
+
+			// 设置响应头 - 提前设置以便流式传输
+			response.setContentType("application/zip");
+			response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(zipFileName, "UTF-8"));
+
+			// 使用ZipOutputStream直接流式写入响应,避免生成临时zip文件
+			try (ZipOutputStream zos = new ZipOutputStream(response.getOutputStream())) {
+				// 设置压缩级别
+				zos.setLevel(Deflater.BEST_SPEED);
+
+				// 为每个档案处理文件
+				for (Map.Entry<Long, List<ArchiveFile>> entry : archiveFilesMap.entrySet()) {
+					Long archiveId = entry.getKey();
+					List<ArchiveFile> files = entry.getValue();
+					String archiveName = getArchiveName(nameMap.get(archiveId));
+
+					// 处理合并的档案PDF
 					String mergeArchivesFile = this.getMergeArchivesFile(archiveId);
-					InputStream file_out2 = CommonUtil.getOSSInputStream(mergeArchivesFile);
-					if (file_out2 != null) {
-						CommonUtil.inputStreamToFile(file_out2, new File(archiveDir + "/" + name + ".pdf"));
-						file_out2.close();
+					if (StringUtils.isNotBlank(mergeArchivesFile)) {
+						addFileToZip(zos, archiveName + "/" + archiveName + ".pdf", mergeArchivesFile);
 					}
 
-					//下载卷内文件
-					String archiveFileDir = archiveDir + "/" + "卷内文件";
-					File file3 = new File(archiveFileDir);
-					file3.mkdir();
-					List<ArchiveFile> files = map.get(archiveId);
+					// 处理卷内文件
+					String innerDir = archiveName + "/卷内文件/";
 					for (ArchiveFile archiveFile : files) {
-						String fileUrl = archiveFile.getPdfFileUrl();
-						String initFileName = archiveFile.getFileName();
-						if (initFileName.length() > 100) {
-							initFileName = initFileName.substring(0, 100);
-						}
-						String fileName = "/" + initFileName + ".pdf";
-						InputStream file_out = CommonUtil.getOSSInputStream(fileUrl);
-						if (file_out != null) {
-							CommonUtil.inputStreamToFile(file_out, new File(archiveFileDir + fileName));
-							file_out.close();
-						}
+						String fileName = getSafeFileName(archiveFile.getFileName()) + ".pdf";
+						addFileToZip(zos, innerDir + fileName, archiveFile.getPdfFileUrl());
 					}
 				}
-				//下载完成,打包文件
-				this.packageZip2(defaultDir, projectDir, projectInfo.getId());
-				String zipFile = defaultDir + "/" + projectInfo.getId() + ".zip";
-				Path path = Paths.get(zipFile);
-				response.setContentType("application/zip");
-				response.setHeader("Content-Disposition", "attachment;filename=" + projectInfo.getId() + "2.zip");
-				// 获取文件内容流并写入响应
-				Files.copy(path, response.getOutputStream());
+			}
+		} catch (Exception e) {
+			throw new ServiceException("文件下载失败: " + e.getMessage());
+		} finally {
+			// 清理临时目录
+			deleteDirectory(new File(tempDir));
+		}
+	}
 
-			} catch (Exception e) {
-				throw new ServiceException(e.getMessage());
-			} finally {
-				//删除文件与zip文件
-				this.deleteFile(defaultDir, projectInfo.getId());
+	// 辅助方法:添加文件到zip流(分片下载)
+	private void addFileToZip(ZipOutputStream zos, String entryName, String fileUrl) throws IOException {
+		if (StringUtils.isBlank(fileUrl)) return;
+
+		ZipEntry zipEntry = new ZipEntry(entryName);
+		zos.putNextEntry(zipEntry);
+
+		try (InputStream in = CommonUtil.getOSSInputStream(fileUrl)) {
+			if (in == null) return;
+
+			byte[] buffer = new byte[8192]; // 8KB缓冲区
+			int len;
+			while ((len = in.read(buffer)) > 0) {
+				zos.write(buffer, 0, len);
+			}
+		} finally {
+			zos.closeEntry();
+		}
+	}
+
+	// 辅助方法:安全获取档案名称
+	private String getArchiveName(String initName) {
+		if (StringUtils.isBlank(initName)) return "未命名档案";
+		String[] split = initName.split(")");
+		return split[split.length - 1];
+	}
+
+	// 辅助方法:安全文件名
+	private String getSafeFileName(String fileName) {
+		if (StringUtils.isBlank(fileName)) return "未命名文件";
+		// 限制文件名长度并移除非法字符
+		return fileName.substring(0, Math.min(100, fileName.length()))
+				.replaceAll("[\\\\/:*?\"<>|]", "");
+	}
+
+	// 辅助方法:递归删除目录
+	private void deleteDirectory(File directory) {
+		if (directory == null || !directory.exists()) return;
+
+		File[] files = directory.listFiles();
+		if (files != null) {
+			for (File file : files) {
+				if (file.isDirectory()) {
+					deleteDirectory(file);
+				} else {
+					file.delete();
+				}
 			}
 		}
+		directory.delete();
 	}
 
 	@Override

+ 1 - 1
blade-service/blade-business/pom.xml

@@ -194,7 +194,7 @@
                     <target>${java.version}</target>
                     <encoding>${project.build.sourceEncoding}</encoding>
                     <compilerArguments>
-                        <bootclasspath>${java.home}/lib/rt.jar:${java.home}/lib/jce.jar:${java.home}/lib/jsse.jar
+                        <bootclasspath>${java.home}/lib/rt.jar${path.separator}${java.home}/lib/jce.jar${path.separator}${java.home}/lib/jsse.jar
                         </bootclasspath>
                     </compilerArguments>
                 </configuration>

+ 1 - 1
blade-service/blade-business/src/main/java/org/springblade/business/feignClient/InformationQueryClientImpl.java

@@ -128,7 +128,7 @@ public class InformationQueryClientImpl implements InformationQueryClient {
 
     @Override
     public InformationQuery getInfoByWbsId(Long wbsId,Integer classify) {
-        return informationQueryMapper.selectOne(new QueryWrapper<InformationQuery>().eq("wbs_id",wbsId).eq("classify",classify));
+        return informationQueryMapper.selectOne(new QueryWrapper<InformationQuery>().eq("wbs_id",wbsId).eq("classify",classify).in("status",0,1,2));
     }
 
 

+ 5 - 1
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/ArchiveFileServiceImpl.java

@@ -18,11 +18,13 @@ import org.springblade.core.tool.utils.Func;
 import org.springblade.resource.feign.NewIOSSClient;
 import org.springblade.system.entity.DictBiz;
 import org.springblade.system.feign.IDictBizClient;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 
+import javax.annotation.Resource;
 import java.util.*;
 import java.util.concurrent.ExecutorService;
 import java.util.stream.Collectors;
@@ -40,9 +42,11 @@ public class ArchiveFileServiceImpl extends BaseServiceImpl<ArchiveFileMapper, A
     private final IDictBizClient dictBizClient;
     private final NewIOSSClient iossClient;
 
+    @Resource(name = "singleExecutor")
     private ExecutorService executorService;
+
     private final ArchiveInspectionInfoClient archiveInspectionInfoClient;
-    private final JdbcTemplate   jdbcTemplate;
+    private final JdbcTemplate jdbcTemplate;
 
 
     @Override

+ 2 - 1
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialNumberRuleServiceImpl.java

@@ -145,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="";
@@ -211,7 +212,7 @@ public class TrialNumberRuleServiceImpl extends BaseServiceImpl<TrialNumberRuleM
                     }
                 }
             }
-            if(isSaveRedis){
+            if(isSaveRedis&&rules.stream().anyMatch(r->r.getRule()==6&&r.getIsAutoIncrement()==1)){
                     flag=checkTrialNumberIsExist(trialNumber.toString(),type,contractId);
                     i++;
                     if(!flag){

+ 1 - 1
blade-service/blade-control/pom.xml

@@ -100,7 +100,7 @@
                     <target>${java.version}</target>
                     <encoding>${project.build.sourceEncoding}</encoding>
                     <compilerArguments>
-                        <bootclasspath>${java.home}/lib/rt.jar;${java.home}/lib/jce.jar;${java.home}/lib/jsse.jar
+                        <bootclasspath>${java.home}/lib/rt.jar${path.separator}${java.home}/lib/jce.jar${path.separator}${java.home}/lib/jsse.jar
                         </bootclasspath>
                     </compilerArguments>
                 </configuration>

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

@@ -100,6 +100,8 @@ public class EVDataServiceImpl implements EVDataService {
             if (taskApp.getRemarkType().equals("1")) { //安心签
                 //添加电签策略
                 List<SealStrategyVO> strategyListByAXQ = getStrategyListByAXQ(taskApp, ids);
+
+                ids = ids.replaceAll("\\✹", "");
                 if (strategyListByAXQ == null || Func.isEmpty(strategyListByAXQ) || strategyListByAXQ.size() == 0) {
                     ids = ids.replaceAll("✹", "");
                     List<Map<String, Object>> mapList = jdbcTemplate.queryForList("SELECT * from m_textdict_info where type=6  and is_deleted=0 and id in(" + ids + ")");
@@ -335,6 +337,8 @@ public class EVDataServiceImpl implements EVDataService {
                 } else if (taskApp.getApprovalType() == 8) {
                     if (taskApp.getSigType() == 2) {
                         this.jdbcTemplate.execute("update u_entrust_info set sample_status=2,status=" + (taskApp.getSigType() + 1) + ",entrust_e_pdf='" + taskApp.getLastFilePdfUrl() + "' where id=(SELECT wbs_id from u_information_query where id='" + taskApp.getFormDataId() + "')");
+                    }else{
+                        this.jdbcTemplate.execute("update u_entrust_info set entrust_e_pdf='" + taskApp.getLastFilePdfUrl() + "' where id=(SELECT wbs_id from u_information_query where id='" + taskApp.getFormDataId() + "' and status in(0,1,2) ) ");
                     }
                     updateSql = "update u_information_query set e_visa_pdf_url='" + taskApp.getLastFilePdfUrl() + "',status=" + taskApp.getSigType() + ",business_time='" + taskApp.getPdfDate() + "' where id='" + taskApp.getFormDataId() + "'";
                 }

+ 1 - 1
blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/EVisaServiceImpl.java

@@ -798,7 +798,7 @@ public class EVisaServiceImpl implements EVisaService {
             url = "http://219.151.181.73:9125/FrontSys/SealServicezx/FileSignByKeyWord";
         }
         if(signPdfByDFZX.equals("3")){
-            url = "http://113.250.191.72:9125/FrontSys/SealServicezx/FileSignByKeyWord";
+            url = "http://10.0.0.4:9125/FrontSys/SealServicezx/FileSignByKeyWord";
         }
 
 

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

@@ -16,6 +16,8 @@ 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<>();
         try  {
@@ -119,8 +121,8 @@ public class PDFUtils {
         }
     }
 
-    public static void mai123n(String[] args) {
-        String pdfUrl = "/Users/hongchuangyanfa/Desktop/22222/1278页.pdf";
+    public static void mai11n(String[] args) {
+        String pdfUrl = "/Users/hongchuangyanfa/Downloads/cb1e0971f9ae3ab53ab2866b3471aaee.pdf";
         getPdfSignIds(pdfUrl);
     }
 

+ 1 - 1
blade-service/blade-manager/pom.xml

@@ -240,7 +240,7 @@
                     <target>${java.version}</target>
                     <encoding>${project.build.sourceEncoding}</encoding>
                     <compilerArguments>
-                        <bootclasspath>${java.home}/lib/rt.jar;${java.home}/lib/jce.jar;${java.home}/lib/jsse.jar
+                        <bootclasspath>${java.home}/lib/rt.jar${path.separator}${java.home}/lib/jce.jar${path.separator}${java.home}/lib/jsse.jar
                         </bootclasspath>
                     </compilerArguments>
                 </configuration>

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

@@ -1675,6 +1675,7 @@ public class ExcelTabController extends BladeController {
         wbsTreeContract.setPKeyId(newPkId);
         wbsTreeContract.setCreateTime(new Date());
         wbsTreeContract.setTabGroupId(tabGroupId);
+        wbsTreeContract.setCopyPkId(wbsInfo.getCopyPkId() == null ? pkeyId + "" : wbsInfo.getCopyPkId());
         String nodeName;
         nodeName = wbsTreeContractList2.get(wbsTreeContractList2.size() - 1).getNodeName();
         if (nodeName.indexOf("__") >= 0) {
@@ -3765,7 +3766,7 @@ public class ExcelTabController extends BladeController {
     @ApiImplicitParam(name = "fileId", value = "fileId")
     public void downGongChengExcelFile(HttpServletResponse response) throws Exception {
         String fileName = URLEncoder.encode("工程划分导入模版", Charsets.UTF_8.name());
-        String filePath="https://xinan1.zos.ctyun.cn/blade-oss-chongqing/upload/20250508/bf69e3bd5a3fd3a216099238591948d9.xlsx";
+        String filePath="https://xinan1.zos.ctyun.cn/blade-oss-chongqing/upload/20250717/780f2392e0c15810de10cde98217ad36.xlsx";
         InputStream redio = CommonUtil.getOSSInputStream(filePath);
         byte[] buffer = IoUtil.readToByteArray(redio);
         OutputStream toClient = new BufferedOutputStream(response.getOutputStream());
@@ -4634,12 +4635,12 @@ public class ExcelTabController extends BladeController {
             for (String noId : nodeId) {
                 JSONObject js = new JSONObject();
                 JSONObject js2 = new JSONObject();
+             //   InformationQuery infoB = informationQueryClient.getInfoByWbsId(Func.toLong(noId), Func.toInt(classify));
                 List<AppWbsTreeContractVO> tableAll = wbsTreeContractService.searchNodeAllTable(noId, classify, contractId, projectId, null);
                 JSONArray array = new JSONArray();
                 if (tableAll != null && tableAll.size() >= 1) {
                     /*只需加载第一张即可,生效会自动补全*/
                     for (AppWbsTreeContractVO tab : tableAll) {
-                        //  AppWbsTreeContractVO tab = tableAll.get(0);
                         Map<String, Object> jo = excelTabService.getBussDataInfo(tab.getPKeyId(), 0,true);
                         String s = new Gson().toJson(jo);
                         //字符串转jsonobject
@@ -4657,7 +4658,10 @@ public class ExcelTabController extends BladeController {
                 }
                 js2.put("orderList", array);
                 js.put("dataInfo", js2);
-                js.put("signType", "1");
+                /*if(infoB!=null && (infoB.getStatus()==1 || infoB.getStatus()==2)){
+                    js.put("signType", "1");
+                }*/
+
                 this.saveBussData2(js);
             }
         } catch (Exception e) {
@@ -4810,34 +4814,55 @@ 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));
+            if(parent==null){
+                i--;
+                System.out.println("剩余:"+i+"个节点未检查");
+                continue;
+            }
+            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);
                 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;
+                    try {
+                        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));
-                        }
+                    }catch (Exception e){
+
                     }
                 }
             }
             wbsTreeContractService.checkNodeAllDate(parent);
+            i--;
+            System.out.println("剩余:"+i+"个节点未检查");
         }
+        System.out.println("检查完毕");
         return R.status(true);
     }
 }

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

@@ -247,8 +247,8 @@ public class NodeBaseInfoController extends BladeController {
     @GetMapping("/getNodeBaseInfoByPkeyId")
     @ApiOperationSupport(order = 9)
     @ApiOperation(value = "设置自动获取", notes = "pkeyId表单Id,nodeId节点Id")
-    public R getNodeBaseInfoByPkeyId(@RequestParam Long pkeyId, @RequestParam Long nodeId, @RequestParam String autoType,@RequestParam(required = false) BigDecimal min,@RequestParam(required = false)BigDecimal max){
-        return R.data(nodeBaseInfoService.getNodeBaseInfoByPkeyId(pkeyId,nodeId,autoType,min,max));
+    public R getNodeBaseInfoByPkeyId(@RequestParam Long pkeyId, @RequestParam Long nodeId, @RequestParam String autoType, @RequestParam(required = false) String paramName,@RequestParam(required = false) BigDecimal min,@RequestParam(required = false)BigDecimal max){
+        return R.data(nodeBaseInfoService.getNodeBaseInfoByPkeyId(pkeyId,nodeId,autoType, paramName,min,max));
     }
 
 	@GetMapping("/getAllNodeBaseInfoByPkeyId")

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

@@ -458,6 +458,15 @@ public class TableElementConverter implements ITableElementConverter {
                                 info.setToBeUpdated(true);
                                 info.getDataMap().put(fd.getKey(), FormulaUtils.recovery(p));
                                 }
+
+                                //单独处理 重复表单的数据
+                                if(elementDataList.size() == 1 && pages.size() == 1){
+                                    for (TableInfo table : tables) {
+                                        table.setToBeUpdated(true);
+                                        table.getDataMap().put(fd.getKey(), FormulaUtils.recovery(pages.get(0)));
+                                    }
+                                }
+
                             }
                         } catch (Exception e) {
                             StaticLog.error("元素{}回写报错", fd.getCode());

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

@@ -982,7 +982,7 @@
           and  contract_id=#{contractId}
         </if>
         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
+        and p_id is not null and type=2
     </select>
 
 </mapper>

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

@@ -43,7 +43,7 @@ public interface INodeBaseInfoService extends BaseService<NodeBaseInfo> {
 
     NodeBaseInfo getOrSaveNodeBaseInfo(Long pKeyId);
 
-    Object getNodeBaseInfoByPkeyId(Long pkeyId, Long nodeId, String autoType, BigDecimal min,BigDecimal max);
+    Object getNodeBaseInfoByPkeyId(Long pkeyId, Long nodeId, String autoType, String paramName, BigDecimal min, BigDecimal max);
 
 	Map<String,Object> getAllNodeBaseInfoByPkeyId(Long pkeyId,Long nodeId) throws Exception;
 }

+ 9 - 11
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeContractServiceImpl.java

@@ -48,14 +48,11 @@ import org.springblade.manager.vo.*;
 import org.springblade.manager.mapper.ArchiveTreeContractMapper;
 import org.springblade.core.mp.base.BaseServiceImpl;
 import org.springframework.beans.BeanUtils;
-import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.springframework.transaction.annotation.Transactional;
-import org.springframework.util.CollectionUtils;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestParam;
 
+import javax.annotation.Resource;
 import java.util.*;
 import java.util.concurrent.ExecutorService;
 import java.util.stream.Collectors;
@@ -71,6 +68,7 @@ import java.util.stream.Collectors;
 public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeContractMapper, ArchiveTreeContract> implements IArchiveTreeContractService {
 
 	private final ArchiveTreeContractMapper archiveTreeContractMapper;
+
 	private final ArchiveTreeMapper archiveTreeMapper;
 
 	private final IArchiveTreeService archiveTreeService;
@@ -87,14 +85,12 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 
 	private final ArchiveFileClient archiveFileClient;
 
-	private final IWbsTreeContractService wbsTreeContractService;
 
 	private final ArchiveAutoRuleWbsMapper archiveAutoRuleWbsMapper;
 
 	private final ArchiveAutoClient archiveAutoClient;
 
-	private final JdbcTemplate jdbcTemplate;
-
+	@Resource(name = "singleExecutor")
 	private ExecutorService executorService;
 
 
@@ -656,10 +652,12 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 							|| dstScopeTree.getId().equals(contractNode.getParentId())) {
 
 						ArchiveTreeVO2 tmpSubTree = srcTree;
+						ArchiveTreeContractVO2 temp = contractNode;
 						Long dstNodeId = dstNode.getId();
-						if (dstNode.getParentId() == 0 ||  dstScopeTree.getId().equals(contractNode.getParentId()) ) {
+						if ((dstNode.getParentId() == 0 ||  dstScopeTree.getId().equals(contractNode.getParentId())) && !contractNode.getId().equals(dstNode.getId())) {
 							tmpSubTree = ForestNodeMergerEx.getSubTree(srcTree,ar.getFromId());
-							dstNodeId = contractNode.getId();
+							dstNodeId = ar.getId();
+							temp = ar;
 						}
 						if (tmpSubTree == null) {
 							continue;
@@ -668,12 +666,12 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 						//getNormalSaveList 接口除了同步新增节点,还会同步已有节点的属性。
 						//因为关联工序的位置是固定的,先不考虑新增一个关联工序节点,且一次同步完成情况
 						tmpSaveList = archiveTreeContractSync.getNormalSaveListEx(tmpSubTree.getId(),
-								tmpSubTree,dstNodeId,contractNode);
+								tmpSubTree,dstNodeId,temp);
 						saveList.addAll(tmpSaveList);
 
 						//获取工序节点
 						List<ArchiveTreeContract> extSaveList = archiveTreeContractSync.getExtSaveList(dstNodeId,
-								contractNode,dstNode.getProjectId(),classify);
+								temp,dstNode.getProjectId(),classify);
 						saveList.addAll(extSaveList);
 
 

+ 8 - 7
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java

@@ -1282,14 +1282,15 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                         sb.append(tableInfo.getPkeyId());sb.append(",");sb.append(user.getUserId());
                         sb.append(","); sb.append("SYSDATE()");sb.append(",\"");sb.append(sqlInfoNew);
                         sb.append("\")");
-
-                        if(sigType.equals("1") && wbsTreeContract.getProjectId().equals("1630011899725201410") && (tableInfo.getIsTypePrivatePid().equals("1559714325173080065") || tableInfo.getIsTypePrivatePid().equals("1559479719236702210") )){
+                        //由于当时 电签重刷 不想改变着两张表值 后来(监理不愿意,所以需要放开)
+                        /*if(sigType.equals("1") && wbsTreeContract.getProjectId().equals("1630011899725201410") && (tableInfo.getIsTypePrivatePid().equals("1559714325173080065") || tableInfo.getIsTypePrivatePid().equals("1559479719236702210") )){
                             System.out.println("123");
-                        }else{
-                            jdbcTemplate.execute(delSql);
-                            jdbcTemplate.execute(sqlInfo);
-                            jdbcTemplate.execute(sb.toString());
-                        }
+                        }else{*///}
+
+                        jdbcTemplate.execute(delSql);
+                        jdbcTemplate.execute(sqlInfo);
+                        jdbcTemplate.execute(sb.toString());
+
                         transactionManager1.commit(transactionStatus);
                     } catch (Exception e) {
                         transactionManager1.rollback(transactionStatus);

+ 63 - 45
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java

@@ -84,6 +84,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.BiFunction;
 import java.util.function.BinaryOperator;
+import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -5771,59 +5772,21 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                     if (FB02.TABLE_NAME.equals(wtcEva.getInitTableName())) {
                         FB02 fb02 = new FB02(processFds);
                         if (fb02.checked()) {
-                            /*swId是分项评定的父节点Id*/
-
-                          ///  List<FormulaDataBlock> formulaDataBlocks = this.getSqlList("select DISTINCT a.id,a.type,a.sw_id swId,a.contract_id contractId,a.val from m_formula_data_block a,m_wbs_tree_contract b where a.sw_id=b.parent_id and b.contract_id ="+wtcEva.getContractId()+" and b.major_data_type=2 and b.is_deleted=0 and b.ancestors_p_id like '%"+wtcEva.getPId()+"%' ORDER BY b.sort ", FormulaDataBlock.class);
-
-                            // 每次需要依赖于treeCode值
-                            // List<FormulaDataBlock> formulaDataBlocks = this.getSqlList("select DISTINCT a.id,a.type,a.sw_id swId,a.contract_id contractId,a.val from m_formula_data_block a join (select parent_id from m_wbs_tree_contract where tree_code like '" + treeCode.getLast() + "%' and contract_id =" + wtcEva.getContractId() + " and major_data_type=2 and is_deleted=0 ORDER BY tree_code)b on a.sw_id=b.parent_id ", FormulaDataBlock.class);
-                            /*if (formulaDataBlocks != null && formulaDataBlocks.size() > 0) {
-                                *//*就是分项工程节点的父节点名称*//*
-                                String swIds = formulaDataBlocks.stream().map(FormulaDataBlock::getSwId).map(Objects::toString).collect(Collectors.joining(","));
-                                List<Map<String, Object>> listMaps = this.jdbcTemplate.queryForList("select id ,node_name nodeName,full_name fullName  from m_wbs_tree_contract where is_deleted =0 and contract_id=" + wtcEva.getContractId() + " and id in(" + swIds + ")");
-                                Map<String, String> swNameMap = new HashMap<>();
-                                if (listMaps.size() > 0) {
-                                    swNameMap.putAll(listMaps.stream().collect(Collectors.toMap(m -> m.get("id").toString(), m -> m.get("fullName").toString(), (v1, v2) -> v2)));
-                                }
-                                fb02.source(formulaDataBlocks, swNameMap);
-
-                                if (fb02.getDatas().size() > 0) {
-                                    Map<String, String> tableKeysCoordsMap = FormulaUtils.getElementCell(wtcEva.getHtmlUrl());
-                                    if (fb02.initFdCoords(tableKeysCoordsMap)) {
-                                        *//*根据数据长度,增减页数*//*
-                                        List<WbsTreeContract> wtcList = this.adjustPageSize(fb02.getPageNum(), wtcEva, processFds);
-                                        if (fb02.flush(wtcList)) {
-                                            this.jdbcTemplate.batchUpdate(fb02.getSql(), fb02.getParams());
-                                            return R.success("成功");
-                                        }
-                                    }
-                                }
-                            }*/
-
-                            // 重新优化
-                           // String contSql = "SELECT p_key_id as pKeyId,node_name as fullName,init_table_name as initTableName,html_url as htmlUrl from m_wbs_tree_contract a where a.p_id in( select p_key_id  from m_wbs_tree_contract b where  b.contract_id ="+wtcEva.getContractId()+"  and b.major_data_type=2 and b.is_deleted=0 and b.ancestors_p_id like '%"+wtcEva.getPId()+"%' ) and a.type=2 and node_name not like '%附表%' and LENGTH(a.html_url)>=10 and init_table_name is not null ";
                             String contSql = "SELECT p_key_id as pKeyId,p_id as pId,IFNULL(if(length(trim(full_name))>0, full_name, node_name), node_name) AS fullName,init_table_name as partitionCode,html_url as oldId,type,major_data_type as majorDataType from m_wbs_tree_contract where is_deleted=0 and ancestors_p_id like '%"+wtcEva.getPId()+"%' and contract_id ="+wtcEva.getContractId()+"  ORDER BY sort ,full_name ";
                             List<WbsTreeContractLazyVO> allNode = this.getSqlList(contSql, WbsTreeContractLazyVO.class);
                             List<WbsTreeContractLazyVO> conNode= getAllChildNodesWithStream(wtcEva.getPId()+"",allNode);
                             //将conNode 转成Map对象
                             Map<Long, WbsTreeContractLazyVO> map = conNode.stream().collect(Collectors.toMap(WbsTreeContractLazyVO::getPKeyId, WbsTreeContractLazyVO -> WbsTreeContractLazyVO));
                             List<WbsTreeContractLazyVO> tableInfo = new ArrayList<>();
-                           // String nodeName = "";
                             for (WbsTreeContractLazyVO info : conNode) {
-                                /*if(info.getType()==1 && (info.getPId()+"").equals(wtcEva.getPId()+"") ){
-                                    nodeName=info.getFullName();
-                                }*/
                                 if(info.getType()==2){
                                     WbsTreeContractLazyVO wbsTreeContractLazyVO = map.get(info.getPId());
-                                  //  if(wbsTreeContractLazyVO!=null && wbsTreeContractLazyVO.getMajorDataType()!=null && wbsTreeContractLazyVO.getMajorDataType()==2 && info.getFullName().indexOf("附表")<0 && (info.getPKeyId()+"").equals("1861674943318589443")){
                                     if(wbsTreeContractLazyVO!=null && wbsTreeContractLazyVO.getMajorDataType()!=null && wbsTreeContractLazyVO.getMajorDataType()==2 && info.getFullName().indexOf("附表")<0 ){
                                         WbsTreeContractLazyVO wbsTreeC = map.get(wbsTreeContractLazyVO.getPId());
                                         info.setTitle(wbsTreeC.getFullName());
                                         tableInfo.add(info);
-                                      //  System.out.println("---------"+nodeName+"   "+info.getFullName());
                                     }
                                 }
-                              //  System.out.println(info.getFullName());
                             }
                             System.out.println("tableInfo:"+tableInfo);
                             for (WbsTreeContractLazyVO info : tableInfo) {
@@ -5981,7 +5944,7 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                             for (FormData e : fbFds) {
                                 if (e.getEName().startsWith("分部工程名称")) {
                                     fbName = e;
-                                } else if (e.getEName().startsWith("分部工程实测得分计算")) {
+                                } else if (e.getEName().startsWith("分部工程评分") ) { //分部工程实测得分计算
                                     passRate = e;
                                 } else if (e.getEName().startsWith("质量等级")) {
                                     fbLevel = e;
@@ -5990,10 +5953,38 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                             if (!(fbName != null && passRate != null && fbLevel != null)) {
                                 return R.fail("未能匹配分部评定节点");
                             }
+
                             String keys = Stream.of(fbName, passRate, fbLevel).map(FormData::getKey).map(StringUtils::handleNull).collect(Collectors.joining(",c.", "c.", ""));
-                            List<Map<String, Object>> mapList = jdbcTemplate.queryForList("select " + keys + " , a.tree_code from (select id,tree_code from m_wbs_tree_contract where tree_code like '" + treeCode.getLast() + "%' and contract_id =" + wtcEva.getContractId() + " and major_data_type=2 and is_deleted=0 and node_type=3 ORDER BY tree_code)a join m_wbs_tree_contract b on a.id=b.parent_id" +
-                                    " join " + FB02.TABLE_NAME + " c on b.p_key_id=c.p_key_id where b.contract_id =" + wtcEva.getContractId() + " and b.is_deleted=0 and b.init_table_name='" + FB02.TABLE_NAME + "'" +
-                                    "ORDER BY a.tree_code");
+                           // String contSql = "SELECT p_key_id as pKeyId,p_id as pId,IFNULL(if(length(trim(full_name))>0, full_name, node_name), node_name) AS fullName,init_table_name as partitionCode,html_url as oldId,type,major_data_type as majorDataType from m_wbs_tree_contract where is_deleted=0 and (ancestors_p_id like '%"+wtcEva.getPId()+"%' or p_key_id="+wtcEva.getPId()+") and contract_id ="+wtcEva.getContractId()+"  ORDER BY sort ,full_name ";
+                            String contSql = " SELECT DISTINCT c.p_key_id as pKeyId,c.p_id as pId, CASE WHEN c.type =1 then c.full_name when c.type =2 then c.node_name END AS fullName,c.type,c.major_data_type as majorDataType  from m_wbs_tree_contract c , "+
+                                             " (SELECT a.* from m_wbs_tree_contract a ,m_wbs_tree_contract b where  b.p_key_id=a.p_id and a.table_owner in(1,2,3) and  a.is_deleted=0 and  b.is_deleted=0 and b.ancestors_p_id like '%"+wtcEva.getPId()+"%' and b.contract_id ="+wtcEva.getContractId()+" and b.major_data_type=8 and a.node_name  NOT LIKE '%\\__%' ) d "+
+                                             " where (FIND_IN_SET(c.p_key_id,d.ancestors_p_id) or c.p_key_id=d.p_key_id) and  c.ancestors_p_id like '%"+wtcEva.getPId()+"%' and c.contract_id ="+wtcEva.getContractId()+" and c.is_deleted=0 "+
+                                             " ORDER BY c.sort ,c.full_name ";
+
+                            List<WbsTreeContractLazyVO> allNode = this.getSqlList(contSql, WbsTreeContractLazyVO.class);
+                            List<WbsTreeContractLazyVO> conNode= getAllChildNodesWithStream(wtcEva.getPId()+"",allNode);
+                            //将conNode 转成Map对象
+                            Map<Long, WbsTreeContractLazyVO> DataMap = conNode.stream().collect(Collectors.toMap(WbsTreeContractLazyVO::getPKeyId, WbsTreeContractLazyVO -> WbsTreeContractLazyVO));
+                            List<WbsTreeContractLazyVO> tableInfo = new ArrayList<>();
+                            StringBuffer sb = new StringBuffer();
+                            for (WbsTreeContractLazyVO info : conNode) {
+                                System.out.println(info.getFullName()+""+info.getPKeyId());
+                                if(info.getType()==2){
+                                    WbsTreeContractLazyVO wbsTreeContractLazyVO = DataMap.get(info.getPId());
+                                    if(wbsTreeContractLazyVO!=null && wbsTreeContractLazyVO.getMajorDataType()!=null && wbsTreeContractLazyVO.getMajorDataType()==8 && info.getFullName().indexOf("__")<0 ){
+                                        tableInfo.add(info);
+                                        sb.append(info.getPKeyId());
+                                    }
+                                }
+                            }
+
+                           System.out.println("123");
+                            String pkeyIds = tableInfo.stream().map(WbsTreeContractLazyVO::getPKeyId).map(Object::toString).collect(Collectors.joining(","));
+
+                            String sqlInfo = "select " +keys +",p_key_id from "+  FB02.TABLE_NAME +" c where p_key_id in("+pkeyIds+") ORDER BY FIND_IN_SET(p_key_id,'"+pkeyIds+"')";
+                            System.out.println("1231");
+
+                            List<Map<String, Object>> mapList = jdbcTemplate.queryForList(sqlInfo);
                             if (mapList.size() > 0) {
                                 List<Item02> abList = new ArrayList<>();
                                 for (Map<String, Object> map : mapList) {
@@ -6001,17 +5992,17 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                                     item.setName(StringUtils.handleNull(map.get(fbName.getKey())).split("_\\^_")[0]);
                                     item.setPassRate(BaseUtils.obj2DoubleZero(StringUtils.handleNull(map.get(passRate.getKey())).split("_\\^_")[0]));
                                     item.setLevel(StringUtils.handleNull(map.get(fbLevel.getKey())).split("_\\^_")[0]);
-                                    item.setTreeCode(StringUtils.handleNull(map.get("tree_code")));
+                                    item.setTreeCode(StringUtils.handleNull(map.get("p_key_id")));
                                     abList.add(item);
                                 }
                                 /*合并相同分部评定*/
-                                BinaryOperator<Item02> biOp = (v1, v2) -> {
+                              /*  BinaryOperator<Item02> biOp = (v1, v2) -> {
                                     if (v1.getScores() >= v2.getScores()) {
                                         return v1;
                                     }
                                     return v2;
                                 };
-                                abList = new ArrayList<>(abList.stream().collect(Collectors.toMap(Item02::getTreeCode, f -> f, biOp)).values());
+                                abList = new ArrayList<>(abList.stream().collect(Collectors.toMap(Item02::getTreeCode, f -> f, biOp)).values());*/
                                 dw02.source(abList);
                                 if (dw02.getDatas().size() > 0) {
                                     Map<String, String> tableKeysCoordsMap = FormulaUtils.getElementCell(wtcEva.getHtmlUrl());
@@ -6037,6 +6028,33 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
     }
 
 
+    // 批量加载+内存计算
+/*    public List<WbsTreeContractLazyVO> getAllChildNodesWithStream(Long parentId, List<WbsTreeContractLazyVO> allNodes) {
+
+        // 2. 构建内存索引
+        Map<Long, WbsTreeContractLazyVO> nodeMap = allNodes.stream()
+                .collect(Collectors.toMap(WbsTreeContractLazyVO::getPKeyId, Function.identity()));
+
+        Map<Long, List<WbsTreeContractLazyVO>> childrenMap = allNodes.stream()
+                .filter(node -> node.getPId() != null)
+                .collect(Collectors.groupingBy(WbsTreeContractLazyVO::getPId));
+
+        // 3. 递归查找子节点
+        List<WbsTreeContractLazyVO> result = new ArrayList<>();
+        Deque<Long> stack = new ArrayDeque<>();
+        stack.push(Func.toLong(parentId));
+
+        while (!stack.isEmpty()) {
+            Long currentId = stack.pop();
+            WbsTreeContractLazyVO node = nodeMap.get(currentId);
+            if (node != null) {
+                result.add(node);
+                childrenMap.getOrDefault(currentId, Collections.emptyList())
+                        .forEach(child -> stack.push(child.getPKeyId()));
+            }
+        }
+        return result;
+    }*/
     // 获取所有子节点
     public List<WbsTreeContractLazyVO> getAllChildNodesWithStream(String parentId, List<WbsTreeContractLazyVO> allNodes) {
         List<WbsTreeContractLazyVO> children = new ArrayList<>();

+ 106 - 26
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/NodeBaseInfoServiceImpl.java

@@ -16,28 +16,30 @@
  */
 package org.springblade.manager.service.impl;
 
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import org.jsoup.Jsoup;
 import org.jsoup.nodes.Document;
 import org.jsoup.nodes.Element;
 import org.jsoup.select.Elements;
 import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.log.exception.ServiceException;
+import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.utils.IoUtil;
-import org.springblade.core.tool.utils.ObjectUtil;
 import org.springblade.core.tool.utils.StringUtil;
 import org.springblade.manager.entity.NodeBaseInfo;
 import org.springblade.manager.entity.Parameter;
 import org.springblade.manager.entity.ParameterElement;
 import org.springblade.manager.entity.WbsTreeContract;
+import org.springblade.manager.service.IParameterElementService;
 import org.springblade.manager.service.IWbsTreeContractService;
 import org.springblade.manager.utils.FileUtils;
 import org.springblade.manager.vo.NodeBaseInfoVO;
 import org.springblade.manager.mapper.NodeBaseInfoMapper;
 import org.springblade.manager.service.INodeBaseInfoService;
 import org.springblade.core.mp.base.BaseServiceImpl;
-import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
@@ -49,7 +51,6 @@ import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.util.*;
 import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 /**
  *  服务实现类
@@ -64,6 +65,8 @@ public class NodeBaseInfoServiceImpl extends BaseServiceImpl<NodeBaseInfoMapper,
     private  IWbsTreeContractService iWbsTreeContractService;
     @Autowired
     private  JdbcTemplate jdbcTemplate;
+    @Autowired
+    private IParameterElementService parameterElementService;
 	@Override
 	public IPage<NodeBaseInfoVO> selectNodeBaseInfoPage(IPage<NodeBaseInfoVO> page, NodeBaseInfoVO nodeBaseInfo) {
 		return page.setRecords(baseMapper.selectNodeBaseInfoPage(page, nodeBaseInfo));
@@ -162,7 +165,7 @@ public class NodeBaseInfoServiceImpl extends BaseServiceImpl<NodeBaseInfoMapper,
 
 
     @Override
-    public Object getNodeBaseInfoByPkeyId(Long pkeyId, Long nodeId, String autoType, BigDecimal min, BigDecimal max) {
+    public Object getNodeBaseInfoByPkeyId(Long pkeyId, Long nodeId, String autoType, String paramName, BigDecimal min, BigDecimal max) {
         String result="";
         String[] strings = autoType.split(",");
         List<String> types = Arrays.asList(strings);
@@ -195,6 +198,7 @@ public class NodeBaseInfoServiceImpl extends BaseServiceImpl<NodeBaseInfoMapper,
                 }
             }
         }
+        String parameter = null;
         if(types.size()==1&&types.contains("8")) {
             if (min.compareTo(max) >= 0) {
                 throw new IllegalArgumentException("max must be greater than min");
@@ -209,6 +213,41 @@ public class NodeBaseInfoServiceImpl extends BaseServiceImpl<NodeBaseInfoMapper,
 
             // 设置精度和舍入模式 保留两位小数
             result= randomValue.setScale(2, RoundingMode.HALF_UP).toString();
+            Map<String, BigDecimal> map = new HashMap<>();
+            map.put("min", min);
+            map.put("max", max);
+            parameter = JSONObject.toJSONString( map);
+        }
+        if (paramName != null && !paramName.isEmpty()) {
+            try {
+                WbsTreeContract wbsTreeContract = iWbsTreeContractService.getBaseMapper().selectOne(new QueryWrapper<WbsTreeContract>().eq("p_key_id", pkeyId));
+                if (wbsTreeContract.getCopyPkId() ==  null) {
+                    wbsTreeContract.setCopyPkId(wbsTreeContract.getPKeyId() + "");
+                    iWbsTreeContractService.update(Wrappers.<WbsTreeContract>lambdaUpdate().set(WbsTreeContract::getCopyPkId, wbsTreeContract.getPKeyId()).eq(WbsTreeContract::getPKeyId, wbsTreeContract.getPKeyId()));
+                }
+                ParameterElement element = parameterElementService.getOne(Wrappers.<ParameterElement>lambdaQuery().eq(ParameterElement::getProjectId, wbsTreeContract.getProjectId())
+                        .eq(ParameterElement::getContractId, wbsTreeContract.getContractId()).eq(ParameterElement::getType, 3)
+                        .eq(ParameterElement::getElementName, paramName).eq(ParameterElement::getNodeId, wbsTreeContract.getCopyPkId()));
+                if (element == null) {
+                    element = new ParameterElement();
+                    element.setProjectId(Long.valueOf(wbsTreeContract.getProjectId()));
+                    element.setContractId(wbsTreeContract.getContractId());
+                    element.setNodeId(wbsTreeContract.getCopyPkId() == null ? wbsTreeContract.getPKeyId() + "" : wbsTreeContract.getCopyPkId());
+                    element.setType(3);
+                    element.setElementName(paramName);
+                    element.setParameter(parameter);
+                    element.setParamType(autoType);
+                    element.setCreateUser(AuthUtil.getUserId());
+                    element.setCreateDept(Long.valueOf(AuthUtil.getDeptId()));
+                    parameterElementService.save(element);
+                } else {
+                    element.setParameter(parameter);
+                    element.setParamType(autoType);
+                    parameterElementService.updateById(element);
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
         }
         return result;
     }
@@ -228,9 +267,19 @@ public class NodeBaseInfoServiceImpl extends BaseServiceImpl<NodeBaseInfoMapper,
             htmlString = htmlString.replaceAll("placeholder", "placeholderxx");
             Document doc = Jsoup.parse(htmlString);
             //拿到参数库所有元素与参数库的元素比较
-            String sql="select * from m_parameter_element where is_deleted =0";
+            // 全局参数
+            String sql="select * from m_parameter_element where is_deleted =0 and type = 1";
             List<ParameterElement> ParameterElementList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(ParameterElement.class));
-
+            // 私有参数
+            List<ParameterElement> parameterElements = parameterElementService.list(Wrappers.<ParameterElement>lambdaQuery().eq(ParameterElement::getProjectId, wbsTreeContract.getProjectId())
+                    .eq(ParameterElement::getType, 3).eq(ParameterElement::getContractId, wbsTreeContract.getContractId())
+                    .eq(ParameterElement::getNodeId, wbsTreeContract.getCopyPkId() == null ? wbsTreeContract.getPKeyId() : wbsTreeContract.getCopyPkId()));
+            if (!parameterElements.isEmpty()) {
+                // 去重
+                Set<String> set = parameterElements.stream().map(ParameterElement::getElementName).collect(Collectors.toSet());
+                ParameterElementList.removeIf(parameterElement -> set.contains(parameterElement.getElementName()));
+            }
+            ParameterElementList.addAll(parameterElements);
             String nodeSql="Select * from m_node_base_info where node_id="+nodeId+" and is_deleted=0 limit 1";
             NodeBaseInfo nodeBaseInfo;
             try {
@@ -240,33 +289,48 @@ public class NodeBaseInfoServiceImpl extends BaseServiceImpl<NodeBaseInfoMapper,
             }
             List<WbsTreeContract> ancestorsNodes = iWbsTreeContractService.getBaseMapper().selectList(new QueryWrapper<WbsTreeContract>().in("p_key_id", Arrays.stream(wbsTreeContractNode.getAncestors().split(",")).toArray()).eq("contract_id", wbsTreeContractNode.getContractId()));
             for (ParameterElement parameterElement : ParameterElementList) {
-                Elements selects = doc.select("[placeholderxx='" + parameterElement.getElementName() + "']");
+                Elements selects;
+                if (parameterElement.getType() == 3) {
+                    selects = doc.getElementsByAttributeValue("keyname",parameterElement.getElementName());
+                } else {
+                    selects = doc.select("[placeholderxx='" + parameterElement.getElementName() + "']");
+                }
                 //元素库里存在表单的元素
                 if(selects.size()>0){
-                    //用元素查出参数库
-                    String sql1="Select * from m_parameter where id="+parameterElement.getParameterId();
-                    Parameter parameter = jdbcTemplate.queryForObject(sql1, new BeanPropertyRowMapper<>(Parameter.class));
-                    //不需要获取的情况
-                    //如果参数要区分项目
-                    if(parameter.getType()==1){
-                        //并且元素不是全局参数
-                        if(parameterElement.getType()!=1){
-                            //并且元素对应的项目ID不等于表单的项目ID
-                            if(parameterElement.getProjectId()!=null&&!wbsTreeContract.getProjectId().equals(parameterElement.getProjectId().toString())){
-                                System.out.println(parameter.getParamName()+" 参数库的"+parameterElement.getElementName()+"元素不是全局参数,并且项目Id对应不上");
-                                continue;
-                            }else {
-                                if(parameterElement.getContractId()!=null&&!wbsTreeContract.getContractId().equals(parameterElement.getContractId())){
-                                    System.out.println(parameter.getParamName()+" 参数库的"+parameterElement.getElementName()+"元素不是全局参数,项目ID能对应上但是合同段Id对应不上");
+                    String[] paramTypes;
+                    if (parameterElement.getParameterId() != null) {
+                        //用元素查出参数库
+                        String sql1="Select * from m_parameter where id="+parameterElement.getParameterId();
+                        Parameter parameter = jdbcTemplate.queryForObject(sql1, new BeanPropertyRowMapper<>(Parameter.class));
+                        //不需要获取的情况
+                        //如果参数要区分项目
+                        if(parameter.getType()==1){
+                            //并且元素不是全局参数
+                            if(parameterElement.getType()!=1){
+                                //并且元素对应的项目ID不等于表单的项目ID
+                                if(parameterElement.getProjectId()!=null&&!wbsTreeContract.getProjectId().equals(parameterElement.getProjectId().toString())){
+                                    System.out.println(parameter.getParamName()+" 参数库的"+parameterElement.getElementName()+"元素不是全局参数,并且项目Id对应不上");
                                     continue;
+                                }else {
+                                    if(parameterElement.getContractId()!=null&&!wbsTreeContract.getContractId().equals(parameterElement.getContractId())){
+                                        System.out.println(parameter.getParamName()+" 参数库的"+parameterElement.getElementName()+"元素不是全局参数,项目ID能对应上但是合同段Id对应不上");
+                                        continue;
+                                    }
                                 }
                             }
                         }
+                        //需要获取的情况
+                        //拿到参数库的类型
+                        String paramType = parameter.getParamType();
+                        paramTypes = paramType.split(",");
+                    } else {
+                        String paramType = parameterElement.getParamType();
+                        if (paramType == null || paramType.isEmpty()) {
+                            continue;
+                        }
+                        paramTypes = paramType.split(",");
                     }
-                    //需要获取的情况
-                    //拿到参数库的类型
-                    String paramType = parameter.getParamType();
-                    String[] paramTypes = paramType.split(",");
+
                     //根据参数的类型值,来获取不同的值 1-7是获取单位工程名称这些 8是获取划分编号 9是获取范围随机数
                     for (Element select : selects) {
                         StringBuilder result=new StringBuilder();
@@ -362,6 +426,22 @@ public class NodeBaseInfoServiceImpl extends BaseServiceImpl<NodeBaseInfoMapper,
                                     s=s+wbsTreeContract.getPartitionCode();
                                 }
                                 result.append(s);
+                            }else if(type.equals("9")) {
+                                String parameter = parameterElement.getParameter();
+                                if (parameter != null) {
+                                    JSONObject json = JSONObject.parseObject(parameter);
+                                    BigDecimal min = json.getBigDecimal("min");
+                                    BigDecimal max = json.getBigDecimal("max");
+                                    // 计算区间范围
+                                    BigDecimal range = max.subtract(min);
+
+                                    // 生成随机数并调整范围
+                                    BigDecimal randomFactor = new BigDecimal(Math.random());
+                                    BigDecimal randomValue = min.add(range.multiply(randomFactor));
+
+                                    // 设置精度和舍入模式 保留两位小数
+                                    result.append(randomValue.setScale(2, RoundingMode.HALF_UP));
+                                }
                             }
                         }
                         map.put(select.attr("keyname"),result.toString());

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

@@ -2346,18 +2346,18 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
             Row row = sheet.getRow(i);
             if (row == null) continue;
             // 获取每一列的值
-            String unitName = getCellValue(row.getCell(0)); // A列:单位工程名称
-            String unitCode = getCellValue(row.getCell(1)); // B列:单位工程编号
-            String subUnitName = getCellValue(row.getCell(2)); // C列:子单位工程名称
-            String subUnitCode = getCellValue(row.getCell(3)); // D列:子单位工程编号
-            String divisionName = getCellValue(row.getCell(4)); // E列:分部工程名称
-            String divisionCode = getCellValue(row.getCell(5)); // F列:分部工程编号
-            String subDivisionName = getCellValue(row.getCell(6)); // G列:子分部工程名称
-            String subDivisionCode = getCellValue(row.getCell(7)); // H列:子分部工程编号
-            String itemName = getCellValue(row.getCell(8)); // I列:分项工程名称
-            String itemCode = getCellValue(row.getCell(9)); // J列:分项工程编号
-            String subItemName = getCellValue(row.getCell(10)); // K列:子分项工程名称
-            String subItemCode = getCellValue(row.getCell(11));// L列:子分项工程编号
+            String unitCode = getCellValue(row.getCell(0)); // A列:单位工程编号
+            String unitName = getCellValue(row.getCell(1)); // B列:单位工程名称
+            String subUnitCode = getCellValue(row.getCell(2)); // C列:子单位工程编号
+            String subUnitName = getCellValue(row.getCell(3)); // D列:子单位工程名称
+            String divisionCode = getCellValue(row.getCell(4)); // E列:分部工程编号
+            String divisionName = getCellValue(row.getCell(5)); // F列:分部工程名称
+            String subDivisionCode = getCellValue(row.getCell(6)); // G列:子分部工程编号
+            String subDivisionName = getCellValue(row.getCell(7)); // H列:子分部工程名称
+            String itemCode = getCellValue(row.getCell(8)); // I列:分项工程编号
+            String itemName = getCellValue(row.getCell(9)); // J列:分项工程名称
+            String subItemCode = getCellValue(row.getCell(10));// K列:子分项工程编号
+            String subItemName = getCellValue(row.getCell(11)); // L列:子分项工程名称
             ImportTreeDto dto=new ImportTreeDto(unitName,unitCode,1,StringUtils.isEmpty(unitName) ,subUnitName,subUnitCode,18,StringUtils.isEmpty(subUnitName),divisionName,divisionCode,2,StringUtils.isEmpty(divisionName), subDivisionName,subDivisionCode,3,StringUtils.isEmpty(subDivisionName),itemName,itemCode,4,StringUtils.isEmpty(itemName),subItemName,subItemCode,5,StringUtils.isEmpty(subItemName));
                 list.add(dto);
         }

+ 12 - 5
blade-service/blade-manager/src/main/java/org/springblade/manager/utils/TableCoordinates.java

@@ -4,6 +4,7 @@ import org.jsoup.Jsoup;
 import org.jsoup.nodes.Document;
 import org.jsoup.nodes.Element;
 import org.jsoup.select.Elements;
+import org.springblade.common.utils.CommonUtil;
 import org.springblade.core.tool.utils.IoUtil;
 
 import java.io.File;
@@ -14,16 +15,19 @@ import java.util.*;
 
 public class TableCoordinates {
     static Map<Integer, Set<Integer>> occupiedCells = new HashMap<>();
-    public static void main12(String[] args) throws Exception {
-        String htmlUrl = "/Users/hongchuangyanfa/fsdownload/1582300079941746688.html";
+    public static void mai1ßn(String[] args) throws Exception {
+        String htmlUrl = "http://fileinfo.hczcxx.cn:9295/privateUrlCopy/1630011899725201410/1940382551554129920.html";
        // String htmlUrl = "/mnt/sdc/Users/hongchuangyanfa/Desktop/privateUrlCopy/1630011899725201410/1582300079941746688.html";
         getHtmlDataInfo(htmlUrl);
     }
 
     public static List<String> getHtmlDataInfo(String htmlUrl) throws Exception {
+        System.out.println(htmlUrl);
         occupiedCells.clear();
         List<String> redata = new ArrayList<>();
-        InputStream fileInputStream = FileUtils.getInputStreamByUrl(htmlUrl);
+        InputStream fileInputStream = FileUtils.getInputStreamByUrl(htmlUrl);//CommonUtil.getOSSInputStream(htmlUrl); //FileUtils.getOSSInputStream();//
+       // InputStream fileInputStream = CommonUtil.getOSSInputStream(htmlUrl); //FileUtils.getOSSInputStream();//
+        // FileUtils.getInputStreamByUrl(htmlUrl);
         try {
             String htmlString = IoUtil.readToString(fileInputStream);
             Document doc = Jsoup.parse(htmlString, "UTF-8");
@@ -55,6 +59,7 @@ public class TableCoordinates {
                     // 计算绝对坐标
                     Map<String, Object> coord = new HashMap<>();
                     String cellName = cell.text().replaceAll("\\s+", "");
+                    System.out.println("cellName:"+cellName);
                     coord.put("name", cellName);
                     coord.put("x1", x);
                     coord.put("y1", y);
@@ -67,11 +72,11 @@ public class TableCoordinates {
                         scX2 = x + colspan - 1;
                         scY1 = y;
                         scY2 = y + rowspan - 1;
-                    } else if (cellName != null && cellName.indexOf("合格判定") >= 0) {
+                    } else if (cellName != null && (cellName.indexOf("合格判定") >= 0 || cellName.indexOf("判定合格") >= 0)) {
                         tableKeys.put("合格判定", coord);
                     } else if (cellName != null && cellName.indexOf("实测值或实测偏差值") >= 0) {
                         tableKeys.put("实测值或实测偏差值", coord);
-                    } else if (cellName != null && cellName.indexOf("项次") >= 0) {
+                    } else if (cellName != null && cellName.indexOf("项次") >= 0 || cellName.indexOf("次项") >= 0) {
                         tableKeys.put("项次", coord);
                     } else if (cellName != null && cellName.indexOf("检查项目") >= 0) {
                         tableKeys.put("检查项目", coord);
@@ -176,6 +181,8 @@ public class TableCoordinates {
                   System.out.println(reVal);
                 redata.add(reVal);
             }
+        } catch (Exception e) {
+            throw new RuntimeException(e);
         }finally {
             fileInputStream.close();
         }

+ 199 - 44
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;
@@ -811,10 +813,10 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
                         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 -> 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(contractId, lowestNodeParentIdsTB, nodesAll, tableOwner);
                         Map<Long, WbsTreeContractLazyVO> lowestNodesMap = lowestNodesTB.stream()
@@ -831,18 +833,18 @@ 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.buildNodeTreeByStream(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));
                         long endTime = System.currentTimeMillis();
                         long executionTime = endTime - startTime;
                         _logger.info("合同段 " + contractId + " 处理颜色 执行时间:" + executionTime + " ms");
-
                         /* ================ 处理最终结果集 ================ */
                         if (lazyNodes.size() > 0) {
                             Map<Long, Integer> countMap = new HashMap<>();
@@ -957,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()
@@ -974,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.buildNodeTreeByStream(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) {
@@ -1303,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()) {
@@ -1351,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()
@@ -1424,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;
@@ -1471,9 +1510,10 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
             long startTime = System.currentTimeMillis();
 
             /*重新计算,进行递归获取父节点计数统计*/
-            this.recursiveGetParentNodes(resultParentNodesTB, lowestNodeParentIdsTB, nodesAll);
-//            Map<Long, List<WbsTreeContractLazyVO>> map = nodesAll.stream().collect(Collectors.groupingBy(WbsTreeContractLazyVO::getId));
+//            this.recursiveGetParentNodes(resultParentNodesTB, lowestNodeParentIdsTB, nodesAll);
+            Map<Long, List<WbsTreeContractLazyVO>> map = nodesAll.stream().collect(Collectors.groupingBy(WbsTreeContractLazyVO::getId));
 //            recursiveGetParentNodes(resultParentNodesTB, lowestNodeParentIdsTB, map);
+            queueGetParentNodes(resultParentNodesTB, lowestNodeParentIdsTB, map);
             long endTime = System.currentTimeMillis();
             long executionTime = endTime - startTime;
             _logger.info("合同段 " + contractId + " wbs节点树 数量计算 执行时间:" + executionTime + " ms");
@@ -1551,13 +1591,47 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
                 })
                 .collect(Collectors.toList());
         List<Long> collect = collectedNodes.stream()
-                .map(WbsTreeContractLazyVO::getParentId).filter(Objects::nonNull).distinct()
+                .map(WbsTreeContractLazyVO::getParentId).filter(Objects::nonNull)
                 .collect(Collectors.toList());
         if (!collect.isEmpty()) {
             result.addAll(collectedNodes);
             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();
+            }
+        }
+    }
 
 
     /**
@@ -1614,6 +1688,87 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
         return result;
     }
 
+
+    public Set<Integer> buildNodeTreeAndCalculateStatus
+            (List<WbsTreeContractLazyVO> list, Map<Long, List<WbsTreeContractLazyVO>> map,
+             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);
+                if (lowestNodeVO != null && lowestNodeVO.getColorStatus() != null) {
+                    //最底层颜色初始化
+                    vo.setColorStatus(lowestNodeVO.getColorStatus());
+                }
+            } else {
+                //非最底层节点,颜色默认=1黑色
+                vo.setColorStatus(1);
+            }
+            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()) {
+                    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(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
      *