Browse Source

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

# Conflicts:
#	blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchivesAutoController.java
#	blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.java
#	blade-service/blade-archive/src/main/java/org/springblade/archive/service/IArchivesAutoService.java
cr 4 weeks ago
parent
commit
780b6bd6f8
50 changed files with 1166 additions and 296 deletions
  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. 8 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/ArchivesAuto.java
  6. 65 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/ArchivesSortRule.java
  7. 5 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/vo/ArchivesAutoVO.java
  8. 23 10
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/ArchiveFile.java
  9. 10 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ParameterElement.java
  10. 3 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/WbsTreeContract.java
  11. 4 5
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveFileTaskController.java
  12. 17 3
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchivesAutoController.java
  13. 2 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/external/impl/ExternalDataArchiveAutoService.java
  14. 9 1
      blade-service/blade-archive/src/main/java/org/springblade/archive/external/impl/ExternalDataArchiveFileService.java
  15. 2 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/external/impl/ExternalDataArchiveMetaService.java
  16. 47 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/external/utils/TransUtil.java
  17. 6 1
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.java
  18. 143 33
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.xml
  19. 18 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesSortRuleMapper.java
  20. 21 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesSortRuleMapper.xml
  21. 13 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/ArchivesSortRuleService.java
  22. 2 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/IArchivesAutoService.java
  23. 64 2
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchiveAutoPdfServiceImpl.java
  24. 83 39
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java
  25. 22 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesSortRuleServiceImpl.java
  26. 1 1
      blade-service/blade-business/pom.xml
  27. 1 0
      blade-service/blade-business/src/main/java/org/springblade/business/feignClient/ArchiveFileClientImpl.java
  28. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/feignClient/InformationQueryClientImpl.java
  29. 5 1
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/ArchiveFileServiceImpl.java
  30. 40 13
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TaskServiceImpl.java
  31. 58 0
      blade-service/blade-business/src/main/java/org/springblade/business/sync/TaskSync.java
  32. 1 1
      blade-service/blade-control/pom.xml
  33. 4 0
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/EVDataServiceImpl.java
  34. 1 1
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/EVisaServiceImpl.java
  35. 4 2
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/utils/PDFUtils.java
  36. 1 1
      blade-service/blade-manager/pom.xml
  37. 7 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java
  38. 2 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/NodeBaseInfoController.java
  39. 3 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/TextdictInfoController.java
  40. 9 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/TableElementConverter.java
  41. 2 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeContractMapper.xml
  42. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/INodeBaseInfoService.java
  43. 9 11
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeContractServiceImpl.java
  44. 16 10
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java
  45. 63 45
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java
  46. 106 26
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/NodeBaseInfoServiceImpl.java
  47. 6 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsSynchronousEViSaServiceImpl.java
  48. 7 7
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsSynchronousServiceImpl.java
  49. 12 5
      blade-service/blade-manager/src/main/java/org/springblade/manager/utils/TableCoordinates.java
  50. 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();
+    }
+
+}

+ 8 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/ArchivesAuto.java

@@ -24,6 +24,7 @@ import java.time.ZoneId;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
 import io.swagger.annotations.ApiModelProperty;
+import org.apache.commons.lang.StringUtils;
 import org.springblade.archive.trans.ArchiveAutoVo;
 import org.springblade.archive.trans.ArchiveTreeVo;
 import org.springblade.core.mp.base.BaseEntity;
@@ -270,6 +271,13 @@ public class ArchivesAuto extends BaseEntity {
 
         // 4. 设置默认值(根据业务需求)
         this.setIsAutoFile(0);
+        //没生成封面并且文件数量为1的,就是上传的案卷文件
+        if (StringUtils.isEmpty(this.getOutUrl())
+                && (this.getFileN() != null && this.getFileN() == 1)) {
+            this.setIsAutoFile(1);
+        }
+
+
         this.setIsArchive(1);
         this.setIsDeleted(0);
     }

+ 65 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/ArchivesSortRule.java

@@ -0,0 +1,65 @@
+package org.springblade.archive.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.util.Date;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * 档案案卷排序规则
+ * @author LHB
+ * @TableName u_archives_sort_rule
+ */
+@TableName(value ="u_archives_sort_rule")
+@Data
+public class ArchivesSortRule {
+    /**
+     * 
+     */
+    @ApiModelProperty(value = "主键id")
+    @TableId(type = IdType.INPUT)
+    private Long id;
+
+    /**
+     * 项目id
+     */
+    @ApiModelProperty(value = "项目id")
+    private Long projectId;
+
+    /**
+     *  类型(1-节点配许,2-流水号排序)
+     */
+    @ApiModelProperty(value = "类型(1-节点配许,2-流水号排序)")
+    private Integer type;
+
+    /**
+     *  创建时间
+     */
+    @org.springframework.format.annotation.DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @com.fasterxml.jackson.annotation.JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "创建时间")
+    private Date createTime;
+
+    /**
+     *  创建人
+     */
+    @ApiModelProperty(value = "创建人")
+    private Long createUser;
+
+    /**
+     *  修改时间
+     */
+    @org.springframework.format.annotation.DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @com.fasterxml.jackson.annotation.JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "修改时间")
+    private Date updateTime;
+
+    /**
+     *  修改人
+     */
+    @ApiModelProperty(value = "修改人")
+    private Long updateUser;
+}

+ 5 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/vo/ArchivesAutoVO.java

@@ -170,6 +170,11 @@ public class ArchivesAutoVO extends ArchivesAuto {
 	 */
 	private String innerSearch;
 
+	/**
+	 * 排序规则
+	 */
+	private Integer sortRuleType;
+
 	@ApiModelProperty("批量保存")
 	private List<ArchivesAutoVO> list;
 	/**

+ 23 - 10
blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/ArchiveFile.java

@@ -374,22 +374,35 @@ public class ArchiveFile extends BaseEntity {
         // eVisaFile 可能对应 Vo 的 approveType(根据业务逻辑调整)
         this.setEVisaFile(vo.getApproveType());
         // utime 对应 Vo 的 upTime(需转换)
+// utime 对应 Vo 的 upTime(需转换)
         if (vo.getUpTime() != null) {
-            String upTimeStr = vo.getUpTime();
-            LocalDateTime dateTime;
+            String upTimeStr = vo.getUpTime().trim(); // 去除前后空格
+            LocalDateTime dateTime = null;
+
             try {
-                // 首先尝试原始格式:yyyy-MM-dd HH:mm:ss
-                DateTimeFormatter originalFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
-                dateTime = LocalDateTime.parse(upTimeStr, originalFormatter);
-            } catch (DateTimeParseException e) {
+                // 首先尝试完整日期时间格式:yyyy-MM-dd HH:mm:ss
+                DateTimeFormatter fullFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+                dateTime = LocalDateTime.parse(upTimeStr, fullFormatter);
+            } catch (DateTimeParseException e1) {
                 try {
-                    // 尝试紧凑的日期格式:yyyyMMdd
-                    LocalDate date = LocalDate.parse(upTimeStr, DateTimeFormatter.BASIC_ISO_DATE);
-                        dateTime = date.atStartOfDay(); // 时间设为00:00:00
+                    // 其次尝试纯日期格式:yyyy-MM-dd
+                    LocalDate date = LocalDate.parse(upTimeStr, DateTimeFormatter.ISO_LOCAL_DATE);
+                    dateTime = date.atStartOfDay(); // 时间设为00:00:00
                 } catch (DateTimeParseException e2) {
-                    throw new IllegalArgumentException("无法解析的日期时间格式: " + upTimeStr, e2);
+                    try {
+                        // 最后尝试紧凑日期格式:yyyyMMdd(8位数字)
+                        if (upTimeStr.matches("\\d{8}")) {
+                            DateTimeFormatter compactFormatter = DateTimeFormatter.ofPattern("yyyyMMdd");
+                            LocalDate date = LocalDate.parse(upTimeStr, compactFormatter);
+                            dateTime = date.atStartOfDay();
+                        }
+                    } catch (DateTimeParseException e3) {
+                        // 所有格式尝试失败
+                        System.out.println("无法解析的日期时间格式: " + upTimeStr);
+                    }
                 }
             }
+
             this.setUtime(dateTime);
         }
 

+ 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("操作失败");
         }

+ 17 - 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;
@@ -1116,5 +1114,21 @@ public class ArchivesAutoController extends BladeController {
         return R.status(archivesAutoService.reBuildArchiveFrontPdfs(archiveIds,projectId));
     }
 
+    @GetMapping("/sortRule")
+    @ApiOperationSupport(order = 42)
+    @ApiModelProperty(value = "排序规则")
+	@ApiImplicitParams(value = {
+			@ApiImplicitParam(name = "projectId", value = "项目id", required = true),
+			@ApiImplicitParam(name = "type", value = "排序类型:1-节点排序,2-流水号排序", required = true)
+	})
+    public R sortRule(Long projectId,Integer type){
+		if(projectId == null){
+			return R.fail("项目id不能为空");
+		}
+		if(type == null || type < 1 || type > 2){
+			return R.fail("排序类型错误");
+		}
+        return R.status(archivesAutoService.sortRule(projectId,type));
+    }
 
 }

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

@@ -195,6 +195,7 @@ public class ExternalDataArchiveAutoService {
                     localArchive.setOutUrl(externalArchive.getOutUrl());
                     localArchive.setName(externalArchive.getName());
                     localArchive.setFileNumber(externalArchive.getFileNumber());
+                    localArchive.setNodeId(externalArchive.getNodeId());
                     upArchives.add(localArchive);
                 }
             }
@@ -206,6 +207,7 @@ public class ExternalDataArchiveAutoService {
         // 检查关键字段差异
         return !Objects.equals(external.getOutUrl(), local.getOutUrl())
                 || !Objects.equals(external.getName(), local.getName())
+                || !Objects.equals(external.getNodeId(), local.getNodeId())
                 || !Objects.equals(external.getFileNumber(), local.getFileNumber());
 
         // 扩展检查示例(如需其他字段比较,可追加条件):

+ 9 - 1
blade-service/blade-archive/src/main/java/org/springblade/archive/external/impl/ExternalDataArchiveFileService.java

@@ -191,7 +191,14 @@ public class ExternalDataArchiveFileService {
             boolean pdfUrlDifferent = external.getPdfPageUrl() != null &&
                     !Objects.equals(external.getPdfPageUrl(), local.getPdfPageUrl());
 
-            return !Objects.equals(extUtimeStr, localUtimeStr) || pdfUrlDifferent;
+            // 新增nodeId比较:当external的nodeId非空时,与local的nodeId比较
+            boolean nodeIdDifferent = external.getNodeId() != null &&
+                    !Objects.equals(external.getNodeId(), local.getNodeId());
+
+            // 任意字段不同即需要更新
+            return !Objects.equals(extUtimeStr, localUtimeStr)
+                    || pdfUrlDifferent
+                    || nodeIdDifferent; // 新增nodeId判断
         }
     }
 
@@ -210,6 +217,7 @@ public class ExternalDataArchiveFileService {
         local.setFilePage(external.getFilePage());
         local.setFileSize(external.getFileSize());
         local.setUtime(external.getUtime());
+        local.setNodeId(external.getNodeId());
         //local.setArchiveId(external.getArchiveId());
     }
 

+ 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;

+ 47 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/external/utils/TransUtil.java

@@ -238,12 +238,18 @@ public class TransUtil {
         //三、施工质量控制文件 (六)现场抽检试验检测报告
         put("426db97ebf1a4de9b28153335342", 1927992893465690138L);
 
+        //三、施工质量控制文件 (七)房建
+        put("dfa7997ffe3f4e11b46508a52063", 1927992893465690145L);
+
         //四、安全文明施工文件
         put("ff0f6b6962494df7b7b3f03539b2", 1927992893465690146L);
 
         //五、进度控制文件
         put("4fbcf1973adb481a89a36d8b9898", 1927992893465690147L);
 
+        //六、合同管理文件
+        put("9a7cb944123647f19637983fe144", 1927992893465690148L);
+
         //七、变更文件
         put("2e203ab2574640c2895ac5196204", 1927992893465690162L);
         //八、施工原始记录
@@ -302,12 +308,19 @@ public class TransUtil {
         //三、施工质量控制文件 (六)现场抽检试验检测报告
         put("020567726035400a971f95f5a585", 1927992893469884441L);
 
+        //三、施工质量控制文件 (七)房建
+        put("579b5421137641ca9c84b0b5018d", 1927992893469884448L);
+
+
         //四、安全文明施工文件
         put("e8e2af76849d4fe392fbfec50156", 1927992893469884449L);
 
         //五、进度控制文件
         put("9f7b03959db646f791a1b2581ed2", 1927992893469884450L);
 
+        //六、合同管理文件
+        put("0298983d7b8142778d88ab7c4d03", 1927992893469884451L);
+
         //七、变更文件
         put("e04b9db2c50749629bf8a01bf6f3", 1927992893469884465L);
         //八、施工原始记录
@@ -352,12 +365,18 @@ public class TransUtil {
         //三、施工质量控制文件 (六)现场抽检试验检测报告
         put("70dda230cbca40a4b34004aa03f5", 1927992893469884491L);
 
+        //三、施工质量控制文件 (七)房建
+        put("bb69232532ff4443952fb22d0d53", 1927992893469884498L);
+
         //四、安全文明施工文件
         put("a5f598023ed4402ba1859ff8d1fa", 1927992893469884499L);
 
         //五、进度控制文件
         put("9f3d46f37d194604925ab6bf1f30", 1927992893469884500L);
 
+        //六、合同管理文件
+        put("9551483177b54c029dcaa443af4b", 1927992893469884501L);
+
         //七、变更文件
         put("7eccf837cfb649c69086427ef9e3", 1927992893469884515L);
         //八、施工原始记录
@@ -398,10 +417,17 @@ public class TransUtil {
         //(六)现场抽检试验检测报告
         put("d37d15a6893d4f26b7fa326cab98", 1927992893474078745L);
 
+        //三、施工质量控制文件 (七)房建
+        put("8488d944a78044f98ceb944c2785", 1927992893474078752L);
+
         //四、安全文明施工文件
         put("eecc8d374650469b87b04af099c3", 1927992893474078753L);
         //五、进度控制文件
         put("74a3f78dff114518b3ebd1800562", 1927992893474078754L);
+
+        //六、合同管理文件
+        put("75a5781d00f94b98abe2ee47d175", 1927992893474078755L);
+
         //七、变更文件
         put("c37db7bb196b411ca59b99fad259", 1927992893474078769L);
         //八、施工原始记录
@@ -436,6 +462,27 @@ public class TransUtil {
 
         //施工工序资料
         put("8a0aa647278548fa9edba59b78c4", 1927992893474078792L);
+
+
+        //二工程管理文件
+        put("89f84f2c49d84dce96a67a1cc99b", 1927992893474078772L);
+
+        //二、工程管理文件
+        //(一)工程质量管理文件
+        put("25a04127ab9341d491f5982ac9e8", 1927992893474078775L);
+
+
+        // (八)缺陷责任期资料
+        put("1d4c9460a9954d9d8ffcccc39f78", 1945023416096522240L);
+
+        // 四、施工安全及文明施工文件
+        put("fbca27defd5e48c1b08527154f87", 1927992893478273030L);
+
+        // 五、进度控制文件
+        put("c034b7bf1f4a44b78d422821337d", 1927992893478273031L);
+
+        // 八、施工原始记录
+        put("c52cf546b94d4099b0701a023caa", 1927992893478273037L);
         //二工程管理文件
         //施工准备文件 -1.施工项目部组建、印章启用、人员任命文件,进场人员资质报审文件,施工设备仪器进场报审文件、设备仪器校验、率定文件
         //put("0b0ac82851d7484bba414bb1ccbd", 1892759789415432263L);

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

@@ -230,5 +230,10 @@ public interface ArchivesAutoMapper extends BaseMapper<ArchivesAuto> {
     List<ArchivesAutoVO4> selectAllArchiveAuto(@Param("projectId")Long projectId, @Param("contractId") Long contractId, @Param("nodeIds") List<String> nodeIds,@Param("isArchive")Integer isArchive);
 
 
-	List<ArchivesAutoVO5> selectArchivesAutoFileFormDownload(@Param("projectId") Long projectId, @Param("ids") List<String> ids);
+
+
+	void deleteIsElementFileByProjectId(@Param("projectId") Long projectId);
+
+	void deleteIsElementFileByNode(@Param("projectId") Long projectId,@Param("ancestors") String ancestors,@Param("nodeId") String nodeId);
+	List<ArchivesAutoVO5> selectArchivesAutoFileFormDownload(@Param("projectId") Long projectId,  @Param("ids") List<String> ids);
 }

+ 143 - 33
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.xml

@@ -216,6 +216,35 @@
         <result column="out_id" property="outId"/>
         <result column="sort_num" property="sortNum"/>
     </resultMap>
+    <update id="deleteIsElementFileByProjectId">
+        UPDATE u_archive_file set is_deleted = 1 WHERE archive_id in (
+            select id
+            from u_archives_auto
+            where project_id = #{projectId}
+              and is_auto_file!=1
+              and is_deleted=0
+              and is_lock!=1
+        ) and is_element = 1
+    </update>
+    <update id="deleteIsElementFileByNode">
+        UPDATE u_archive_file set is_deleted = 1 WHERE archive_id in (
+            select id
+            from u_archives_auto
+            where project_id = #{projectId}
+              AND is_auto_file != 1
+              AND is_deleted = 0
+              AND is_lock != 1
+              AND node_id IN (
+                SELECT id FROM m_archive_tree_contract
+                WHERE project_id = #{projectId}
+                    AND ancestors IS NOT NULL
+                    AND ancestors LIKE concat(''
+                        , #{ancestors}
+                        , '%')
+                   OR id = #{nodeId}
+            )
+        ) and is_element = 1
+    </update>
 
 
     <select id="approvalFile" resultType="org.springblade.archive.vo.ArchivesAutoVO$ApprovalFile">
@@ -233,16 +262,13 @@
 
 
     <select id="selectArchivesAutoFileCount" resultType="java.lang.Integer">
-        select count(id) from u_archives_auto u where u.is_deleted = 0
+        select count(0) from u_archives_auto u LEFT JOIN m_archive_tree_contract m ON u.node_id = m.id where u.is_deleted = 0
         <if test="vo.projectId != null and vo.projectId != ''">
             and u.project_id = #{vo.projectId}
         </if>
         <if test="vo.queryValue != null and vo.queryValue != ''">
             and (u.name like concat('%',#{vo.queryValue},'%') or u.file_number like concat('%',#{vo.queryValue},'%'))
         </if>
-        <if test="vo.isAutoFile != null and vo.isAutoFile != ''">
-            and u.is_auto_file = #{vo.isAutoFile}
-        </if>
         <choose>
             <when test="vo.isArchive != null and vo.isArchive != ''">
                 and u.is_archive = #{vo.isArchive}
@@ -260,6 +286,22 @@
                 #{nodeId}
             </foreach>
         </if>
+        <if test="vo.queryValueSize != null and vo.queryValueSize != ''">
+            <choose>
+                <when test="vo.queryValueSize == 1">
+                    and CHAR_LENGTH(u.name) <![CDATA[ < ]]> 80
+                </when>
+                <when test="vo.queryValueSize == 2">
+                    and CHAR_LENGTH(u.name) >= 80 and CHAR_LENGTH(u.name) <![CDATA[ < ]]> 120
+                </when>
+                <when test="vo.queryValueSize == 3">
+                    and CHAR_LENGTH(u.name) >= 120 and CHAR_LENGTH(u.name) <![CDATA[ < ]]> 150
+                </when>
+                <when test="vo.queryValueSize == 4">
+                    and CHAR_LENGTH(u.name) >= 150
+                </when>
+            </choose>
+        </if>
     </select>
 
     <select id="selectArchivesAutoFilePage" resultMap="archivesAutoResultMap">
@@ -303,8 +345,23 @@
                 </when>
             </choose>
         </if>
-        order by m.tree_sort,u.auto_file_sort is null ,u.auto_file_sort,u.file_number is null,
-        SUBSTRING_INDEX(u.file_number, '_', 1), SUBSTRING_INDEX(u.file_number, '_', -1) + 0 ,u.create_time asc
+        <choose>
+            <when test="vo.sortRuleType != null and vo.sortRuleType == 1 and vo.isArchive != null and vo.isArchive != ''">
+                ORDER BY
+                    m.tree_sort,
+                    CASE WHEN u.file_number IS NULL THEN 1 ELSE 0 END,
+                    CAST(SUBSTRING_INDEX(file_number, '_', -1) AS SIGNED)
+            </when>
+            <when test="vo.sortRuleType != null and vo.sortRuleType == 2 and vo.isArchive != null and vo.isArchive != ''">
+                order by
+                    CASE WHEN u.file_number IS NULL THEN 1 ELSE 0 END,
+                    CAST(SUBSTRING_INDEX(file_number, '_', -1) AS SIGNED)
+            </when>
+            <otherwise>
+                order by m.tree_sort,u.auto_file_sort is null ,u.auto_file_sort,u.file_number is null,
+                SUBSTRING_INDEX(u.file_number, '_', 1), SUBSTRING_INDEX(u.file_number, '_', -1) + 0 ,u.create_time asc
+            </otherwise>
+        </choose>
         limit #{current}, #{size}
     </select>
 
@@ -598,7 +655,15 @@
         <if test="vo.storageTimes != null and vo.storageTimes != ''">
             and uaa.storage_time in
             <foreach collection="vo.storageTimes" item="storageTime" open="(" separator="," close=")">
-                #{storageTime}
+                <choose>
+                    <when test="storageTime == 3">
+                        #{storageTime},30
+                    </when>
+                    <otherwise>
+                        #{storageTime}
+                    </otherwise>
+                </choose>
+
             </foreach>
         </if>
         <if test="vo.secretLevels != null and vo.secretLevels != ''">
@@ -626,7 +691,23 @@
             </foreach>
         </if>
         GROUP BY uaa.id
-        order by uaa.tree_sort,uaa.auto_file_sort,uaa.file_number asc
+
+        <choose>
+            <when test="vo.sortRuleType != null and vo.sortRuleType == 1">
+                ORDER BY
+                matc.tree_sort,
+                CASE WHEN uaa.file_number IS NULL THEN 1 ELSE 0 END,
+                CAST(SUBSTRING_INDEX(uaa.file_number, '_', -1) AS SIGNED)
+            </when>
+            <when test="vo.sortRuleType != null and vo.sortRuleType == 2">
+                ORDER BY
+                CASE WHEN uaa.file_number IS NULL THEN 1 ELSE 0 END,
+                CAST(SUBSTRING_INDEX(uaa.file_number, '_', -1) AS SIGNED)
+            </when>
+            <otherwise>
+                order by uaa.tree_sort,uaa.auto_file_sort,uaa.file_number asc
+            </otherwise>
+        </choose>
     </select>
 
     <select id="pageByArchivesAuto11" resultMap="archivesAutoResultMap">
@@ -650,7 +731,14 @@
         <if test="vo.storageTimes != null and vo.storageTimes != ''">
             and uaa.storage_time in
             <foreach collection="vo.storageTimes" item="storageTime" open="(" separator="," close=")">
-                #{storageTime}
+                <choose>
+                    <when test="storageTime == 3">
+                        #{storageTime},30
+                    </when>
+                    <otherwise>
+                        #{storageTime}
+                    </otherwise>
+                </choose>
             </foreach>
         </if>
         <if test="vo.secretLevels != null and vo.secretLevels != ''">
@@ -678,7 +766,22 @@
             </foreach>
         </if>
         GROUP BY uaa.id
-        order by uaa.tree_sort,uaa.auto_file_sort,uaa.file_number asc
+        <choose>
+            <when test="vo.sortRuleType != null and vo.sortRuleType == 1">
+                ORDER BY
+                matc.tree_sort,
+                CASE WHEN uaa.file_number IS NULL THEN 1 ELSE 0 END,
+                CAST(SUBSTRING_INDEX(uaa.file_number, '_', -1) AS SIGNED)
+            </when>
+            <when test="vo.sortRuleType != null and vo.sortRuleType == 2">
+                ORDER BY
+                CASE WHEN uaa.file_number IS NULL THEN 1 ELSE 0 END,
+                CAST(SUBSTRING_INDEX(uaa.file_number, '_', -1) AS SIGNED)
+            </when>
+            <otherwise>
+                order by uaa.tree_sort,uaa.auto_file_sort,uaa.file_number asc
+            </otherwise>
+        </choose>
     </select>
 
     <select id="pageByArchivesAuto2" resultMap="archivesAutoResultMap">
@@ -1018,12 +1121,19 @@
           and uaa.is_destroy = #{type}
     </select>
     <select id="getAllArchiveAgeByContractType" resultType="java.util.Map">
-        SELECT CASE uaa.storage_time WHEN '1' THEN '10年' WHEN '2' THEN '30年' ELSE '永久' END as name,
-               COUNT(uaa.storage_time) as value
-        FROM m_archive_tree_contract matc left join u_archives_auto uaa
-        on uaa.node_id =matc.id
-        WHERE matc.project_id =#{projectId} and uaa.is_deleted =0
-        GROUP BY uaa.storage_time
+        select a.name, sum(a.VALUE) value
+        from (SELECT CASE uaa.storage_time WHEN '1' THEN '10年' WHEN '2' THEN '30年' ELSE '永久' END as name,
+                     COUNT(uaa.storage_time)                                                         as value
+              FROM m_archive_tree_contract matc
+                       left join u_archives_auto uaa
+                                 on uaa.node_id = matc.id
+              WHERE matc.project_id = #{projectId}
+                and matc.is_deleted = 0
+                and uaa.is_deleted = 0
+                and uaa.is_archive = 1
+              GROUP BY uaa.storage_time) a
+        GROUP BY a.name
+
     </select>
     <!--    档案鉴定,档案查询-->
     <select id="pageByAuthenticate" resultType="org.springblade.archive.vo.ArchivesAutoVO">
@@ -1357,7 +1467,6 @@
         select *
         from u_archives_auto
         where project_id = #{projectId}
-        and is_auto_file!=1
         and is_deleted=0
         and
         out_id in
@@ -1403,22 +1512,23 @@
     </select>
     <select id="getAllArchiveByContractTypeSummary" resultType="java.util.Map">
         select sum(a.key1 + a.key11) key1,sum(a.key2 + a.key12) key2,sum(a.key3 +a.key13) key3  from (
-         SELECT
-             sum( matc.tree_code IS NULL ) key3,
-             sum( matc.tree_code = 'S' ) key2,
-             sum( matc.tree_code = 'C' ) key1,
-             sum( mci.contract_type = 1 ) key11,
-             sum( mci.contract_type = 2 ) key12,
-             sum( mci.contract_type NOT IN ( 1, 2 )) key13
-         FROM
-             m_archive_tree_contract matc
-                 LEFT JOIN u_archives_auto uaa ON uaa.node_id = matc.id
-                 LEFT JOIN m_contract_info mci ON matc.tree_code = mci.id  and mci.is_deleted = 0
-         WHERE
-             uaa.project_id = #{projectId}
-           AND uaa.is_deleted = #{type}
-           AND uaa.is_destroy = #{type}
-        )a
+             SELECT
+                 IFNULL(sum( matc.tree_code IS NULL ),0) key3,
+                 IFNULL(sum( matc.tree_code = 'S' ),0) key2,
+                 IFNULL(sum( matc.tree_code = 'C' ),0) key1,
+                 IFNULL(sum( mci.contract_type = 1 ),0) key11,
+                 IFNULL(sum( mci.contract_type = 2 ),0) key12,
+                 IFNULL(sum( mci.contract_type NOT IN ( 1, 2 )),0) key13
+             FROM
+                 u_archives_auto uaa
+                     inner JOIN m_archive_tree_contract matc ON uaa.node_id = matc.id and matc.is_deleted = 0
+                     LEFT JOIN m_contract_info mci ON matc.tree_code = mci.id  and mci.is_deleted = 0
+             WHERE
+                 uaa.project_id = #{projectId}
+               AND uaa.is_deleted = #{type}
+               AND uaa.is_destroy = #{type}
+               AND uaa.is_archive = 1
+         )a
     </select>
     <select id="selectAllArchiveAuto" resultType="org.springblade.archive.vo.ArchivesAutoVO4">
         select uaa.id ,uaa.file_number,uaa.node_id,uatc.parent_Id,uatc.file_number_prefix from u_archives_auto uaa left join m_archive_tree_contract uatc on uaa.node_id=uatc.id where uaa.is_deleted = 0 and uaa.project_id=#{projectId}

+ 18 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesSortRuleMapper.java

@@ -0,0 +1,18 @@
+package org.springblade.archive.mapper;
+
+import org.springblade.archive.entity.ArchivesSortRule;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+* @author LHB
+* @description 针对表【u_archives_sort_rule(档案案卷排序规则)】的数据库操作Mapper
+* @createDate 2025-07-15 11:37:52
+* @Entity generator.domain.UArchivesSortRule
+*/
+public interface ArchivesSortRuleMapper extends BaseMapper<ArchivesSortRule> {
+
+}
+
+
+
+

+ 21 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesSortRuleMapper.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.springblade.archive.mapper.ArchivesSortRuleMapper">
+
+    <resultMap id="BaseResultMap" type="org.springblade.archive.entity.ArchivesSortRule">
+            <id property="id" column="id" />
+            <result property="projectId" column="project_id" />
+            <result property="type" column="type" />
+            <result property="createTime" column="create_time" />
+            <result property="createUser" column="create_user" />
+            <result property="updateTime" column="update_time" />
+            <result property="updateUser" column="update_user" />
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,project_id,type,create_time,create_user,update_time,
+        update_user
+    </sql>
+</mapper>

+ 13 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/service/ArchivesSortRuleService.java

@@ -0,0 +1,13 @@
+package org.springblade.archive.service;
+
+import org.springblade.archive.entity.ArchivesSortRule;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+* @author LHB
+* @description 针对表【u_archives_sort_rule(档案案卷排序规则)】的数据库操作Service
+* @createDate 2025-07-15 11:37:52
+*/
+public interface ArchivesSortRuleService extends IService<ArchivesSortRule> {
+
+}

+ 2 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/service/IArchivesAutoService.java

@@ -171,4 +171,6 @@ public interface IArchivesAutoService extends BaseService<ArchivesAuto> {
 	boolean creatFileNameFormAI(String ids, Long projectId, Long contractId) throws IOException;
 
 	List<ArchivesAutoVO5> selectArchivesAutoFileFormDownload(Long projectId, Long contractId, List<String> ids);
+
+	boolean sortRule(Long projectId, Integer type);
 }

+ 64 - 2
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchiveAutoPdfServiceImpl.java

@@ -26,6 +26,7 @@ import org.springblade.common.utils.SystemUtils;
 import org.springblade.common.vo.DataVO;
 import org.springblade.common.vo.FileSize;
 import org.springblade.core.oss.model.BladeFile;
+import org.springblade.core.tool.utils.BeanUtil;
 import org.springblade.core.tool.utils.ObjectUtil;
 import org.springblade.core.tool.utils.ResourceUtil;
 import org.springblade.core.tool.utils.StringUtil;
@@ -277,12 +278,70 @@ public class ArchiveAutoPdfServiceImpl implements IArchiveAutoPdfService {
 
         //统计文件大小
         RefreshFileSize(archivesAuto, archiveFileList, frontUrls);
-
+        // todo 四要素持久化
+        saveElementFiles(archivesAuto, archiveFileList.get(0), frontUrls);
         String joinedUrls = String.join(", ", frontUrls);
         archivesAuto.setOutUrl(joinedUrls);
         archivesAuto.setSecretLevel(secretLevel);
         archivesAuto.setStorageTime(storageTime);
     }
+    private void saveElementFiles(ArchivesAuto archivesAuto, ArchiveFile archiveFile, List<String> frontUrls) {
+        List<ArchiveFile> archiveFiles = new ArrayList<>();
+        if (frontUrls != null && !frontUrls.isEmpty()) {
+            try {
+                for (String frontUrl : frontUrls) {
+                    // 封面(原r_Archives_front)增加中文"封面"匹配
+                    ArchiveFile file = new ArchiveFile();
+                    String fileName = null;
+                    String fileUrl;
+                    int sort = 0;
+                    if (frontUrl.contains(ArchiveAutoPdfServiceImpl.ARCHIVE_NUMBER[0])
+                            || frontUrl.contains("封面")) {
+                        fileName = "封面";
+                        sort = -4;
+                    }
+                    // 卷内目录(原r_Archives_catalog)增加中文匹配
+                    else if (frontUrl.contains(ArchiveAutoPdfServiceImpl.ARCHIVE_NUMBER[1])
+                            || frontUrl.contains("卷内目录")) {
+                        fileName = "卷内目录";
+                        sort = -3;
+                    }
+                    // 备考表(原r_Archives_spare)增加中文匹配
+                    else if (frontUrl.contains(ArchiveAutoPdfServiceImpl.ARCHIVE_NUMBER[2])
+                            || frontUrl.contains("备考表")) {
+                        fileName = "备考表";
+                        sort = (int)(archivesAuto.getFileSize() + 100);
+                    }
+                    // 背脊(原r_Archives_back)增加中文匹配
+                    else if (frontUrl.contains(ArchiveAutoPdfServiceImpl.ARCHIVE_NUMBER[3])
+                            || frontUrl.contains("背脊")) {
+                        fileName = "背脊";
+                        sort = (int)(archivesAuto.getFileSize() + 101);
+                    }
+                    if(frontUrl.contains("@@@")){
+                        fileUrl = frontUrl.substring(0,frontUrl.indexOf("@@@"));
+                    }else {
+                        fileUrl = frontUrl;
+                    }
+                    if (fileName == null || fileUrl == null) {
+                        continue;
+                    }
+                    BeanUtil.copy(archiveFile, file);
+                    file.setFileName(fileName);
+                    file.setFileUrl(fileUrl);
+                    file.setPdfFileUrl(fileUrl);
+                    file.setIsElement(1);
+                    file.setSort(sort);
+                    archiveFiles.add(file);
+                }
+                if (!archiveFiles.isEmpty()) {
+                    archiveFileClient.addArchiveFile(archiveFiles);
+                }
+            } catch (Exception e) {
+                log.error("保存档案四要素失败:" + e);
+            }
+        }
+    }
 
     /**
      * 打码
@@ -558,6 +617,9 @@ public class ArchiveAutoPdfServiceImpl implements IArchiveAutoPdfService {
             }else {
                 object = "";
             }
+
+            //秘级用空
+            object = "";
         }
 
         dataInfo.put(key, object);
@@ -759,7 +821,7 @@ public class ArchiveAutoPdfServiceImpl implements IArchiveAutoPdfService {
                 file.setFid(idx);
                 //设置文件编号
                 if (StringUtil.isEmpty(file.getFileNumber())) {
-                    file.setFileNumber("\\");
+                    //file.setFileNumber("\\");
                 }
                 //设置页数
                 file.setPageNum(iStartPage.toString());

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

@@ -24,7 +24,8 @@ 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;
 import com.itextpdf.text.*;
@@ -82,9 +83,10 @@ import org.springframework.scheduling.annotation.Async;
 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.multipart.MultipartFile;
 
+import javax.annotation.Resource;
 import javax.servlet.http.HttpServletResponse;
 import java.io.*;
 import java.math.BigDecimal;
@@ -123,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<>(); //按立卷位区分和生成流水号
@@ -160,6 +162,8 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 
 	private final IArchiveAiNameService aiNameService;
 
+	private final ArchivesSortRuleService archivesSortRuleService;
+
 
 	@Override
 	public IPage<ArchivesAutoVO> selectArchivesAutoPage(IPage<ArchivesAutoVO> page, ArchivesAutoVO archivesAuto) {
@@ -216,6 +220,15 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 				vo.setContractId(null);
 			}
 		}
+		//添加排序规则
+		if(vo.getProjectId() != null){
+			ArchivesSortRule one = archivesSortRuleService.getOne(Wrappers.<ArchivesSortRule>lambdaQuery()
+					.eq(ArchivesSortRule::getProjectId, vo.getProjectId()));
+			if(one != null){
+				//添加排序类型
+				vo.setSortRuleType(one.getType());
+			}
+		}
 		if (StringUtils.isNotBlank(vo.getNodeIds())) {
 			vo.setNodeIdArray(Arrays.asList(vo.getNodeIds().split(",")));
 			//如果搜索类型不为文件,就不连接文件表
@@ -244,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()) ? "绝密" : "秘密"));
 				}
 			});
 		}
@@ -426,17 +437,30 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 			ArchiveProjectConfig config = archiveProjectConfigService.getByProjectIdOrNew(vo.getProjectId());
 			String[] frontUrls = outUrl.split(",");
 			for (String frontUrl : frontUrls) {
+				String fileUrl;
+				String fileId;
+				if(frontUrl.contains("@@@")){
+					fileUrl = frontUrl.substring(0,frontUrl.indexOf("@@@"));
+				}else {
+					fileUrl = frontUrl;
+				}
+				if (fileUrl.contains("$$$")) {
+					fileUrl = fileUrl.substring(0, fileUrl.indexOf("$$$"));
+				}
+				if (frontUrl.contains("$$$")) {
+					fileId = frontUrl.substring(frontUrl.indexOf("$$$") + 3);
+				} else {
+					fileId = SnowFlakeUtil.getId() + "";
+					outUrl = outUrl.replace(frontUrl, frontUrl + "$$$" + fileId);
+				}
 				// 封面(原r_Archives_front)增加中文"封面"匹配
 				if (front == null && (frontUrl.contains(ArchiveAutoPdfServiceImpl.ARCHIVE_NUMBER[0])
 						|| frontUrl.contains("封面"))
 						&& config.getFactorType().contains("1")) {
 					front = new ArchivesAutoVO.ApprovalFile();
 					front.setFileName("封面");
-					if(frontUrl.contains("@@@")){
-						front.setFileUrl(frontUrl.substring(0,frontUrl.indexOf("@@@")));
-					}else {
-						front.setFileUrl(frontUrl);
-					}
+					front.setFileUrl(fileUrl);
+					front.setId(fileId);
 				}
 				// 卷内目录(原r_Archives_catalog)增加中文匹配
 				else if (cataLog == null && (frontUrl.contains(ArchiveAutoPdfServiceImpl.ARCHIVE_NUMBER[1])
@@ -444,11 +468,8 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 						&& config.getFactorType().contains("2")) {
 					cataLog = new ArchivesAutoVO.ApprovalFile();
 					cataLog.setFileName("卷内目录");
-					if(frontUrl.contains("@@@")){
-						cataLog.setFileUrl(frontUrl.substring(0,frontUrl.indexOf("@@@")));
-					}else {
-						cataLog.setFileUrl(frontUrl);
-					}
+					cataLog.setFileUrl(fileUrl);
+					cataLog.setId(fileId);
 				}
 				// 备考表(原r_Archives_spare)增加中文匹配
 				else if (spare == null && (frontUrl.contains(ArchiveAutoPdfServiceImpl.ARCHIVE_NUMBER[2])
@@ -456,11 +477,8 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 						&& config.getFactorType().contains("3")) {
 					spare = new ArchivesAutoVO.ApprovalFile();
 					spare.setFileName("备考表");
-					if(frontUrl.contains("@@@")){
-						spare.setFileUrl(frontUrl.substring(0,frontUrl.indexOf("@@@")));
-					}else {
-						spare.setFileUrl(frontUrl);
-					}
+					spare.setFileUrl(fileUrl);
+					spare.setId(fileId);
 				}
 				// 背脊(原r_Archives_back)增加中文匹配
 				else if (back == null && (frontUrl.contains(ArchiveAutoPdfServiceImpl.ARCHIVE_NUMBER[3])
@@ -468,23 +486,19 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 						&& config.getFactorType().contains("4")) {
 					back = new ArchivesAutoVO.ApprovalFile();
 					back.setFileName("背脊");
-					if(frontUrl.contains("@@@")){
-						back.setFileUrl(frontUrl.substring(0,frontUrl.indexOf("@@@")));
-					}else {
-						back.setFileUrl(frontUrl);
-					}
+					back.setFileUrl(fileUrl);
+					back.setId(fileId);
 				}
 			}
+			if (!outUrl.equals(vo.getOutUrl())) {
+				this.update(Wrappers.<ArchivesAuto>lambdaUpdate().eq(ArchivesAuto::getId, vo.getId()).set(ArchivesAuto::getOutUrl, outUrl));
+			}
 		}
 		List<ArchivesAutoVO.ApprovalFile> files = vo.getApprovalFileList();;
 		if (files != null) {
-			String tempId = null;
-			if (!files.isEmpty()) {
-				tempId = files.get(0).getId();
-			}
 			if (front != null && front.getFileUrl() != null) {
-				if (front.getId() == null && tempId != null) {
-					front.setId(tempId + "_1");
+				if (front.getId() == null) {
+					front.setId(SnowFlakeUtil.getId() + "");
 				}
 				if (front.getId() != null) {
 					front.setPdfFileUrl(front.getFileUrl());
@@ -492,8 +506,8 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 				}
 			}
 			if (cataLog != null && cataLog.getFileUrl() != null) {
-				if (cataLog.getId() == null && tempId != null) {
-					cataLog.setId(tempId  + "_2");
+				if (cataLog.getId() == null) {
+					cataLog.setId(SnowFlakeUtil.getId() + "");
 				}
 				if (cataLog.getId() != null) {
 					cataLog.setPdfFileUrl(cataLog.getFileUrl());
@@ -505,8 +519,8 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 				}
 			}
 			if (spare != null && spare.getFileUrl() != null) {
-				if (spare.getId() == null && tempId != null) {
-					spare.setId(tempId  + "_3");
+				if (spare.getId() == null) {
+					spare.setId(SnowFlakeUtil.getId() + "");
 				}
 				if (spare.getId() != null) {
 					spare.setPdfFileUrl(spare.getFileUrl());
@@ -514,8 +528,8 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 				}
 			}
 			if (back != null && back.getFileUrl() != null) {
-				if (back.getId() == null && tempId != null) {
-					back.setId(tempId  + "_4");
+				if (back.getId() == null) {
+					back.setId(SnowFlakeUtil.getId() + "");
 				}
 				if (back.getId() != null) {
 					back.setPdfFileUrl(back.getFileUrl());
@@ -637,6 +651,15 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 			fixArchivesAutoFile(vo);
 		}
 
+		//添加排序规则
+		if(vo.getProjectId() != null){
+			ArchivesSortRule one = archivesSortRuleService.getOne(Wrappers.<ArchivesSortRule>lambdaQuery()
+					.eq(ArchivesSortRule::getProjectId, vo.getProjectId()));
+			if(one != null){
+				//添加排序类型
+				vo.setSortRuleType(one.getType());
+			}
+		}
 		List<ArchivesAuto> pageList = this.baseMapper.selectArchivesAutoFilePage(current, vo.getSize(), vo);
 		//设置分页信息
 		iPage.setTotal(total);
@@ -760,6 +783,8 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 						}
 					}
 				}
+				// 删除四要素文件记录
+				baseMapper.deleteIsElementFileByProjectId(projectId);
 			}
 			//清除文件页面pdf
 			List<String> filePageUrlList = baseMapper.getFilePageUrlList(projectId);
@@ -800,6 +825,8 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 							}
 						}
 					}
+					// 删除四要素文件记录
+					baseMapper.deleteIsElementFileByNode(projectId, ancestors, strNodeId);
 				}
 				//清除文件页面pdf
 				List<String> filePageUrlList = baseMapper.getFilePageUrlListByNode(projectId, ancestors, strNodeId);
@@ -2730,10 +2757,10 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 					}
 				}
 
-				String fileNumber = fileNumberPrefix + "_" + index;
+				String fileNumber = fileNumberPrefix + "-" + index;
 				if (indexType == 1) {
 					String formattedIndex = String.format("%0" + indexNum + "d", index);
-					fileNumber = fileNumberPrefix + "_" + formattedIndex;
+					fileNumber = fileNumberPrefix + "-" + formattedIndex;
 				}
 				if (bforce) {
 					if (archiveAutoPdfService.refreshFileNumberForce(archivesAuto, fileNumber)) {
@@ -4961,4 +4988,21 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		}
 	}
 
+	@Override
+	public boolean sortRule(Long projectId, Integer type) {
+		//根据项目id查询如果没有就新增,如果有就修改
+		ArchivesSortRule one = archivesSortRuleService.getOne(Wrappers.<ArchivesSortRule>lambdaQuery()
+				.eq(ArchivesSortRule::getProjectId, projectId));
+		if (one == null) {
+			one = new ArchivesSortRule();
+			one.setId(SnowFlakeUtil.getId());
+			one.setProjectId(projectId);
+			one.setCreateUser(AuthUtil.getUserId());
+		} else {
+			one.setUpdateUser(AuthUtil.getUserId());
+		}
+		one.setType(type);
+		archivesSortRuleService.saveOrUpdate(one);
+		return true;
+	}
 }

+ 22 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesSortRuleServiceImpl.java

@@ -0,0 +1,22 @@
+package org.springblade.archive.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springblade.archive.entity.ArchivesSortRule;
+import org.springblade.archive.mapper.ArchivesSortRuleMapper;
+import org.springblade.archive.service.ArchivesSortRuleService;
+import org.springframework.stereotype.Service;
+
+/**
+* @author LHB
+* @description 针对表【u_archives_sort_rule(档案案卷排序规则)】的数据库操作Service实现
+* @createDate 2025-07-15 11:37:52
+*/
+@Service
+public class ArchivesSortRuleServiceImpl extends ServiceImpl<ArchivesSortRuleMapper, ArchivesSortRule>
+    implements ArchivesSortRuleService {
+
+}
+
+
+
+

+ 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 - 0
blade-service/blade-business/src/main/java/org/springblade/business/feignClient/ArchiveFileClientImpl.java

@@ -330,6 +330,7 @@ public class ArchiveFileClientImpl implements ArchiveFileClient {
                         local.setFilePage(external.getFilePage());
                         local.setFileSize(external.getFileSize());
                         local.setUtime(external.getUtime());
+                        local.setNodeId(external.getNodeId());
                     }
                     return local;
                 })

+ 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

+ 40 - 13
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TaskServiceImpl.java

@@ -3,6 +3,7 @@ package org.springblade.business.service.impl;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.AllArgsConstructor;
@@ -18,6 +19,7 @@ import org.springblade.business.entity.*;
 import org.springblade.business.mapper.TaskMapper;
 import org.springblade.business.mapper.TrialSelfInspectionRecordMapper;
 import org.springblade.business.service.*;
+import org.springblade.business.sync.TaskSync;
 import org.springblade.business.utils.FileUtils;
 import org.springblade.business.vo.*;
 import org.springblade.common.constant.CommonConstant;
@@ -26,6 +28,7 @@ import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.mp.base.BaseServiceImpl;
 import org.springblade.core.oss.model.BladeFile;
+import org.springblade.core.redis.cache.BladeRedis;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.secure.utils.SecureUtil;
 import org.springblade.core.tool.api.R;
@@ -61,6 +64,7 @@ import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.SingleColumnRowMapper;
+import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -134,6 +138,13 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
 
     @Autowired
     StringRedisTemplate RedisTemplate;
+    @Autowired
+    private BladeRedis bladeRedis;
+    //异步类
+    @Autowired
+    private TaskSync taskSync;
+
+
 
     private final ITrialSelfInspectionRecordService iTrialSelfInspectionRecordService;
 
@@ -1969,19 +1980,35 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
         public R reSigningEVisaStatus0(List<reSigningEVisaStatus> dtos, String header) throws Exception {
          R result= new R();
          if(dtos.size()>0){
-            for (reSigningEVisaStatus dto : dtos) {
-                InformationQuery iq = informationQueryService.getById(dto.getId());
-                if(iq!=null){
-                    informationQueryService.update(new LambdaUpdateWrapper<InformationQuery>()
-                        .eq(InformationQuery::getId, dto.getId())
-                        .set(InformationQuery::getEVisaPdfUrl, null)
-                        .set(InformationQuery::getPdfUrl, null));
-                    result = this.saveNodePdf(iq.getClassify()+"", iq.getWbsId()+"", dto.getContractId()+"", dto.getProjectId()+"", header);
-                    if(result==null||(result!=null&&result.getCode()!=200)){
-                        return R.fail(iq.getName()+"重新保存PDF信息失败");
-                    }
-                }
-            }
+
+             //添加缓存
+             Set<Long> newIds = dtos.stream().map(reSigningEVisaStatus::getId).collect(Collectors.toSet());
+
+             //随机id
+             String s = "sign-reSigningEVisaStatus0:" + SnowFlakeUtil.getId();
+
+             //数据效验
+             Set<Long> oldIds = new HashSet<>();
+             Set<String> keys = bladeRedis.keys("sign-reSigningEVisaStatus0*");
+             for (String key : keys) {
+                 Set<Long> ids = bladeRedis.get(key);
+                 if(ids !=null ){
+                     oldIds.addAll(ids);
+                 }
+             }
+
+             if(CollectionUtils.isNotEmpty(oldIds)){
+                 //如果旧的id中存在新的id,则不允许添加
+                 long count = oldIds.stream().filter(f -> newIds.contains(f)).count();
+                 if(count > 0){
+                     return R.fail("当前提交数据中存在正在保存的数据,请勿重复提交");
+                 }
+             }
+             //10分钟过期
+             bladeRedis.setEx(s,newIds, 600L);
+
+             //执行异步
+             taskSync.reSigningEVisaStatusSync(dtos,header,s);
         }
          return R.success("操作成功");
     }

+ 58 - 0
blade-service/blade-business/src/main/java/org/springblade/business/sync/TaskSync.java

@@ -0,0 +1,58 @@
+package org.springblade.business.sync;
+
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import lombok.AllArgsConstructor;
+import org.springblade.business.dto.reSigningEVisaStatus;
+import org.springblade.business.entity.InformationQuery;
+import org.springblade.business.service.IInformationQueryFileService;
+import org.springblade.business.service.IInformationQueryService;
+import org.springblade.core.redis.cache.BladeRedis;
+import org.springblade.core.tool.api.R;
+import org.springblade.manager.feign.ExcelTabClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * @author LHB
+ */
+@Component
+@AllArgsConstructor
+public class TaskSync {
+
+    private final IInformationQueryService informationQueryService;
+
+    private final ExcelTabClient excelTabClient;
+    @Autowired
+    private BladeRedis bladeRedis;
+    @Async("taskExecutor1")
+    public void reSigningEVisaStatusSync(List<reSigningEVisaStatus> dtos, String header,String s) {
+        R result= null;
+        try {
+            for (reSigningEVisaStatus dto : dtos) {
+                InformationQuery iq = informationQueryService.getById(dto.getId());
+                if(iq!=null){
+                    informationQueryService.update(new LambdaUpdateWrapper<InformationQuery>()
+                            .eq(InformationQuery::getId, dto.getId())
+                            .set(InformationQuery::getEVisaPdfUrl, null)
+                            .set(InformationQuery::getPdfUrl, null));
+                    result = this.saveNodePdf(iq.getClassify()+"", iq.getWbsId()+"", dto.getContractId()+"", dto.getProjectId()+"", header);
+                    if(result==null||(result!=null&&result.getCode()!=200)){
+                        System.out.println(iq.getName()+"重新保存PDF信息失败");
+                    }
+                }
+            }
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }finally {
+            //删除缓f存
+            bladeRedis.del(s);
+        }
+    }
+
+    R saveNodePdf(String classify, String nodePKeyIds, String contractId, String projectId, String header) throws Exception {
+        return excelTabClient.synPDFInfo(contractId, nodePKeyIds, classify, projectId, header);
+    }
+}

+ 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>

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

@@ -1679,6 +1679,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) {
@@ -1864,7 +1865,7 @@ public class ExcelTabController extends BladeController {
                         String contractsIdsStr = contractsIds.stream()
                             .map(id -> "'" + id + "'")
                             .collect(Collectors.joining(", "));;
-                        String sql1 = "select pdf_url,e_visa_pdf_url,pdf_trial_url,pdf_trial_url_position,status from u_information_query where classify='" + classify + "' and wbs_id='" + nodeId + "' and contract_id in(" + contractsIdsStr + ")";
+                        String sql1 = "select pdf_url,e_visa_pdf_url,pdf_trial_url,pdf_trial_url_position,status from u_information_query where classify='" + classify + "' and wbs_id='" + nodeId + "' and contract_id in(" + contractsIdsStr + ") and status in(0,1,2)";
                         maps = jdbcTemplate.queryForList(sql1);
                     }
                 }
@@ -4638,12 +4639,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
@@ -4661,7 +4662,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) {

+ 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")

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

@@ -336,6 +336,9 @@ public class TextdictInfoController extends BladeController {
                         dataf = dateForm.get("format");
                         dateType = dateForm.get("type");
                     }
+                    if (dateType == null) {
+                        dateType = "date";
+                    }
                     if (dateType.equals("datetime")) {
                         element.empty().append("<el-date-picker @keyDowns='dateKeydown()' v-model=" + vmode + " type='" + dateType + "' format='" + dataf + "' value-format='" + dataf + "' placeholder=" + placeholder + " keyname=" + keyname + " weighing=" + weighing + "  @contextmenu.prevent.native='contextmenuClick(" + parm + ")'  @mouseup.right='RightClick(" + parm + ")' trIndex=" + trindex + " tdIndex=" + tdindex + "  x1=" + x1 + " x2=" + x2 + " y1=" + y1 + " y2=" + y2 + " style='width:100%;height:100%'   placeholder='" + placeholder + "'> </el-date-picker>");
                     } else if (dateType.equals("date")) {

+ 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());

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

@@ -522,12 +522,12 @@
             (SELECT COUNT(*)
              FROM u_archives_auto uaa1
              WHERE  uaa1.is_destroy =0 and uaa1.is_deleted =0 and uaa1.is_archive = 1 and (uaa1.node_id in
-                 (select id from m_archive_tree_contract matc2 WHERE matc2.project_id = #{projectId} and matc2.ancestors like CONCAT('%',matc1.id,'%')) or uaa1.node_id = matc1.id)
+                 (select id from m_archive_tree_contract matc2 WHERE matc2.project_id = #{projectId} and matc2.is_deleted = 0 and matc2.ancestors like CONCAT('%',matc1.id,'%')) or uaa1.node_id = matc1.id)
             ) as 'auto',
             (SELECT COUNT(*)
              FROM u_archives_auto uaa1
              WHERE  uaa1.is_destroy =1 and uaa1.is_deleted =1 and uaa1.is_archive = 1 and (uaa1.node_id in
-                (select id from m_archive_tree_contract matc2 WHERE matc2.project_id = #{projectId} and matc2.ancestors like CONCAT('%',matc1.id,'%')) or uaa1.node_id = matc1.id)
+                (select id from m_archive_tree_contract matc2 WHERE matc2.project_id = #{projectId} and matc2.is_deleted = 0 and matc2.ancestors like CONCAT('%',matc1.id,'%')) or uaa1.node_id = matc1.id)
             ) as 'deleted',
             if((SELECT COUNT(*) from m_archive_tree_contract matc WHERE parent_id = matc1.id)=0,false,true) as hasChildren
         FROM m_archive_tree_contract matc1 WHERE matc1.project_id =#{projectId} and matc1.parent_id = #{nodeId} and matc1.is_deleted = 0

+ 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);
 
 

+ 16 - 10
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);
@@ -2355,15 +2356,20 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
             Elements dqids = table.getElementsByAttribute("dqid");
             // 电签组装2
             String tableName = wbsTreeContract.getInitTableName();
-            String dqSql = "select * from u_sign_key_role_info where tab_en_name='"+tableName+"'";
+//            String dqSql = "select * from u_sign_key_role_info where tab_en_name='"+tableName+"'";
+            String dqSql = "select e_key,GROUP_CONCAT(DISTINCT concat('*✹',id)) ids from u_sign_key_role_info where tab_en_name='" + tableName + "' GROUP BY e_key";
+
             List<Map<String, Object>> mapList = jdbcTemplate.queryForList(dqSql);
 
             if(mapList!=null && mapList.size()>0){
                 for(Map<String, Object> map : mapList) {
-                    Elements elementsBy = table.getElementsByAttributeValueStarting("keyname", map.get("e_key") + "");
+                    Elements elementsBy = table.getElementsByAttributeValueStarting("keyname", map.get("e_key") + "_");
                     if(elementsBy!=null && elementsBy.size()>0){
                         for(Element element : elementsBy){
-                            element.attr("sign_type", "✹"+map.get("id"));
+                            String ids = (String) map.get("ids");
+                            ids = ids.replace(",","");
+                            ids = ids.substring(1);
+                            element.attr("sign_type", ids);
                             dqids.add(element);
                         }
                     }

+ 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());

+ 6 - 2
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsSynchronousEViSaServiceImpl.java

@@ -51,7 +51,7 @@ public class WbsSynchronousEViSaServiceImpl {
     }
 
     @Transactional(rollbackFor = Exception.class)
-    public void updateSyncPrivateForm(WbsTreePrivate wbsTreePrivate, List<WbsTreePrivate> collect, Long id,String errorMsg) {
+    public void updateSyncPrivateForm(WbsTreePrivate wbsTreePrivate, List<WbsTreePrivate> collect,Long createUserId, Long id,String errorMsg) {
         List<Long> ids = collect.stream().map(WbsTreePrivate::getPKeyId).collect(Collectors.toList());
         List<Long> parentIds = collect.stream().map(WbsTreePrivate::getParentId).collect(Collectors.toList());
         //节点公式同步
@@ -65,6 +65,8 @@ public class WbsSynchronousEViSaServiceImpl {
                 .set(WbsTreePrivate::getHtmlUrl, wbsTreePrivate.getHtmlUrl())
                 .set(wbsTreePrivate.getExcelId()!=null,WbsTreePrivate::getIsLinkTable, 2)
                 .set(WbsTreePrivate::getExcelId, wbsTreePrivate.getExcelId())
+                .set(WbsTreePrivate::getUpdateTime, DateTime.now())
+                .set(WbsTreePrivate::getUpdateUser, createUserId)
                 .in(WbsTreePrivate::getPKeyId, ids)
         );
         synchronousRecordMapper.update(null, Wrappers.<WbsTreeSynchronousRecord>lambdaUpdate()
@@ -76,7 +78,7 @@ public class WbsSynchronousEViSaServiceImpl {
     }
 
     @Transactional(rollbackFor = Exception.class)
-    public void syncPrivateForceForm(WbsTreePrivate wbsTreePrivate, String nodeId, Long id) {
+    public void syncPrivateForceForm(WbsTreePrivate wbsTreePrivate,Long createUserId, String nodeId, Long id) {
         WbsTreePrivate wbsTreePrivate1 = wbsTreePrivateMapper.selectById(nodeId);
 
         wbsTreePrivateMapper.update(null, Wrappers.<WbsTreePrivate>lambdaUpdate()
@@ -86,6 +88,8 @@ public class WbsSynchronousEViSaServiceImpl {
                 .set(WbsTreePrivate::getHtmlUrl, wbsTreePrivate.getHtmlUrl())
                 .set(StringUtils.isBlank(wbsTreePrivate.getFullName()),WbsTreePrivate::getFullName, wbsTreePrivate1.getNodeName())
                 .set(WbsTreePrivate::getNodeName, wbsTreePrivate.getNodeName())
+                .set(WbsTreePrivate::getUpdateTime, DateTime.now())
+                .set(WbsTreePrivate::getUpdateUser, createUserId)
                 .in(WbsTreePrivate::getPKeyId, nodeId)
         );
         synchronousRecordMapper.update(null, Wrappers.<WbsTreeSynchronousRecord>lambdaUpdate()

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

@@ -140,7 +140,7 @@ public class WbsSynchronousServiceImpl {
                 .ne(WbsTree::getId, wbsTree.getId())
                 .eq(WbsTree::getInitTableName, wbsTree.getInitTableName())
                 .eq(WbsTree::getIsDeleted, 0));
-        if(CollectionUtil.isEmpty(wbsTrees)){
+        if (CollectionUtil.isEmpty(wbsTrees)) {
             throw new ServiceException("当前项目没有相同实体表的其他表单");
         }
 
@@ -166,11 +166,11 @@ public class WbsSynchronousServiceImpl {
                 Objects.equals(f.getExcelId(), wbsTreePrivate.getExcelId())
         ).collect(Collectors.toList());
 
-        if(CollectionUtil.isNotEmpty(collect1)){
+        if (CollectionUtil.isNotEmpty(collect1)) {
             collect.addAll(collect1);
         }
         //清表不同的数据
-        List<WbsTreePrivate> noExcelIdEq = wbsTreePrivates.stream().filter(f -> f.getExcelId()!=null && !Objects.equals(f.getExcelId(), wbsTreePrivate.getExcelId())).collect(Collectors.toList());
+        List<WbsTreePrivate> noExcelIdEq = wbsTreePrivates.stream().filter(f -> f.getExcelId() != null && !Objects.equals(f.getExcelId(), wbsTreePrivate.getExcelId())).collect(Collectors.toList());
         StringBuilder sb = new StringBuilder();
         if (CollectionUtil.isNotEmpty(noExcelIdEq)) {
             for (WbsTreePrivate treePrivate : noExcelIdEq) {
@@ -183,7 +183,7 @@ public class WbsSynchronousServiceImpl {
         }
 
         //修改数据
-        wbsSynchronousEViSaService.updateSyncPrivateForm(wbsTreePrivate, collect, wbsTreeSynchronousRecord.getId(),sb.toString());
+        wbsSynchronousEViSaService.updateSyncPrivateForm(wbsTreePrivate, collect, wbsTreeSynchronousRecord.getCreateUserId(), wbsTreeSynchronousRecord.getId(), sb.toString());
     }
 
     /**
@@ -205,7 +205,7 @@ public class WbsSynchronousServiceImpl {
         if (wbsTreePrivate == null) {
             throw new ServiceException("表单不存在");
         }
-        wbsSynchronousEViSaService.syncPrivateForceForm(wbsTreePrivate, nodeId, wbsTreeSynchronousRecord.getId());
+        wbsSynchronousEViSaService.syncPrivateForceForm(wbsTreePrivate, wbsTreeSynchronousRecord.getCreateUserId(), nodeId, wbsTreeSynchronousRecord.getId());
     }
 
     /**
@@ -982,7 +982,7 @@ public class WbsSynchronousServiceImpl {
                         List<Long> collect1 = addData.stream().map(WbsTreePrivate::getPKeyId).collect(Collectors.toList());
                         //这里可以保存到数据库指定错误日志表
                         throw new ServiceException("添加失败:" + StringUtil.join(collect1, ","));
-                    }else{
+                    } else {
                         //排序调整-连续排序
                         if (wbsTreeSynchronousRecord.getType().contains("7")) {
                             //获取节点下的当前表单
@@ -1128,7 +1128,7 @@ public class WbsSynchronousServiceImpl {
                     //这里可以保存到数据库指定错误日志表
                     //这里可以保存到数据库指定错误日志表
                     throw new ServiceException("添加失败:" + StringUtil.join(collect1, ","));
-                }else{
+                } else {
                     //排序调整
                     if (wbsTreeSynchronousRecord.getType().contains("7")) {
                         //获取节点下的当前表单

+ 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
      *