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

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

# Conflicts:
#	blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java
#	blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsFormElementServiceImpl.java
cr преди 1 месец
родител
ревизия
a2d3e4218a
променени са 65 файла, в които са добавени 2605 реда и са изтрити 747 реда
  1. 1 1
      blade-common/src/main/java/org/springblade/common/utils/AsyncConfig.java
  2. 1 1
      blade-ops/blade-resource/src/main/java/org/springblade/resource/builder/oss/OssBuilder.java
  3. 10 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/ArchiveProjectConfig.java
  4. 29 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/dto/WbsTreeContractStatisticsDTO.java
  5. 6 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/InformationQuery.java
  6. 6 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/StandardInfo.java
  7. 211 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/WbsTreeContractStatistics.java
  8. 48 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/feign/WbsTreeContractStatisticsClient.java
  9. 79 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/DqOperationLog.java
  10. 2 1
      blade-service-api/blade-user-api/src/main/java/org/springblade/system/user/feign/IUserClient.java
  11. 2 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveProjectConfigController.java
  12. 31 3
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchivesAutoController.java
  13. 12 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/TaskSplitController.java
  14. 1 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/external/impl/ExternalDataArchiveFileService.java
  15. 14 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/external/utils/TransUtil.java
  16. 3 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/ITaskSplitService.java
  17. 3 1
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchiveAutoPdfServiceImpl.java
  18. 212 257
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java
  19. 38 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/TaskSplitServiceImpl.java
  20. 33 3
      blade-service/blade-archive/src/main/java/org/springblade/archive/utils/FileUtils.java
  21. 4 0
      blade-service/blade-business/pom.xml
  22. 24 3
      blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java
  23. 4 0
      blade-service/blade-business/src/main/java/org/springblade/business/controller/RecycleBinController.java
  24. 43 40
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TaskController.java
  25. 163 0
      blade-service/blade-business/src/main/java/org/springblade/business/feignClient/WbsTreeContractStatisticsClientImpl.java
  26. 4 4
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/ArchiveFileMapper.xml
  27. 2 2
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/InformationQueryMapper.xml
  28. 54 4
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/StandardInfoMapper.xml
  29. 23 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/WbsTreeContractStatisticsMapper.java
  30. 43 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/WbsTreeContractStatisticsMapper.xml
  31. 16 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/IWbsTreeContractStatisticsService.java
  32. 2 2
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/ArchiveFileServiceImpl.java
  33. 2 2
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/InformationQueryServiceImpl.java
  34. 8 35
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TaskServiceImpl.java
  35. 33 4
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/UStandardInfoServiceImpl.java
  36. 643 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/WbsTreeContractStatisticsServiceImpl.java
  37. 133 25
      blade-service/blade-business/src/main/java/org/springblade/business/sync/TaskSync.java
  38. 2 2
      blade-service/blade-business/src/main/java/org/springblade/business/utils/PDFUtil.java
  39. 2 1
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/EVDataServiceImpl.java
  40. 4 4
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/utils/PDFUtils.java
  41. 3 1
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/EqualNode.java
  42. 6 1
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/GtNode.java
  43. 6 1
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/LtEqNode.java
  44. 6 1
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/LtNode.java
  45. 3 1
      blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/NotEqualNode.java
  46. 1 0
      blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/NumberParser.java
  47. 3 2
      blade-service/blade-manager/src/main/java/com/mixsmart/utils/CustomFunction.java
  48. 10 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java
  49. 25 6
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/TextdictInfoController.java
  50. 3 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/TurnPoint.java
  51. 2 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeContractMapper.xml
  52. 8 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/DqOperationLogMapper.java
  53. 25 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/DqOperationLogMapper.xml
  54. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreePrivateMapper.xml
  55. 12 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IDqOperationLogService.java
  56. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeContractSyncImpl.java
  57. 13 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/DqOperationLogServiceImpl.java
  58. 28 24
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java
  59. 57 13
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java
  60. 40 29
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsFormElementServiceImpl.java
  61. 89 69
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeContractServiceImpl.java
  62. 64 0
      blade-service/blade-user/src/main/java/org/springblade/system/user/controller/UserController.java
  63. 20 20
      blade-service/blade-user/src/main/java/org/springblade/system/user/controller/WbsTreeController.java
  64. 14 0
      blade-service/blade-user/src/main/java/org/springblade/system/user/feign/UserClient.java
  65. 214 180
      blade-service/blade-user/src/main/java/org/springblade/system/user/service/impl/UserServiceImpl.java

+ 1 - 1
blade-common/src/main/java/org/springblade/common/utils/AsyncConfig.java

@@ -20,7 +20,7 @@ public class AsyncConfig {
     public ThreadPoolExecutor getAsyncExecutor() {
         return new ThreadPoolMonitor(cpuNum
                 , 15
-                , 180
+                , 600
                 , TimeUnit.SECONDS
                 , new LinkedBlockingQueue<>(2000)
                 , new ThreadPoolExecutor.DiscardOldestPolicy(), "manager-thread-pool");

+ 1 - 1
blade-ops/blade-resource/src/main/java/org/springblade/resource/builder/oss/OssBuilder.java

@@ -98,7 +98,7 @@ public class OssBuilder {
                 oss.setEndpoint("https://xinan1.zos.ctyun.cn");
             }
         }
-		oss.setEndpoint("https://xinan1.zos.ctyun.cn");
+		//oss.setEndpoint("https://xinan1.zos.ctyun.cn");
 		System.out.println("oss111="+oss.getEndpoint());
 		Oss ossCached = ossPool.get(tenantId);
 		OssTemplate template = templatePool.get(tenantId);

+ 10 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/ArchiveProjectConfig.java

@@ -48,6 +48,16 @@ public class ArchiveProjectConfig extends BaseEntity {
      */
     private Integer indexNum;
 
+    /**
+     *  页码流水号类型,0 默认,无虚数, 1 3位虚数
+     */
+    private Integer pageType;
+
+    /**
+     *  页码序号位数,默认为0
+     */
+    private Integer pageLen;
+
     //是否打页码
     public boolean isPage() {
         return getFactorType().contains("5");

+ 29 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/dto/WbsTreeContractStatisticsDTO.java

@@ -0,0 +1,29 @@
+package org.springblade.business.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springblade.business.entity.InformationQuery;
+
+import java.io.Serializable;
+
+@Data
+@AllArgsConstructor
+public class WbsTreeContractStatisticsDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+    private Long contractId;
+    private Long pKeyId;
+    private Integer classify;
+
+
+    public WbsTreeContractStatisticsDTO() {
+    }
+
+    public WbsTreeContractStatisticsDTO(InformationQuery  query) {
+        if (query != null) {
+            this.contractId = query.getContractId();
+            this.pKeyId = query.getWbsId();
+            this.classify = query.getClassify();
+        }
+    }
+}

+ 6 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/InformationQuery.java

@@ -137,4 +137,10 @@ public class InformationQuery extends BaseEntity {
 
     @ApiModelProperty("节点pdf")
     private String nodePdfUrl;
+
+    @ApiModelProperty("重刷状态 0-待重刷,1-正在重刷,2-重刷成功,3-重刷失败")
+    private Integer saveAgain;
+
+    @ApiModelProperty("重刷次数:如果次数大于5次 每次都是3,就停止重刷")
+    private Integer saveAgainCount;
 }

+ 6 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/StandardInfo.java

@@ -104,4 +104,10 @@ public class StandardInfo {
      */
     @TableField(exist = false)
     private String parentName;
+
+    /**
+     * 父级名称
+     */
+    @TableField(exist = false)
+    private String nameEnd;
 }

+ 211 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/WbsTreeContractStatistics.java

@@ -0,0 +1,211 @@
+package org.springblade.business.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+@TableName("m_wbs_tree_contract_statistics")
+@AllArgsConstructor
+public class WbsTreeContractStatistics implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "主键id")
+    @TableId(
+            value = "id",
+            type = IdType.ASSIGN_ID
+    )
+    private Long id;
+
+    /**
+     * 项目Id
+     */
+    @JsonProperty(value = "projectId")
+    @ApiModelProperty(name = "projectId", value = "项目Id", required = true)
+    private String projectId;
+
+    /**
+     * 合同Id
+     */
+    @JsonProperty(value = "contractId")
+    @ApiModelProperty(name = "contractId", value = "合同Id", required = true)
+    private String contractId;
+
+    /**
+     * 父主键
+     */
+    @ApiModelProperty(value = "父主键id")
+    private Long parentId;
+
+    /**
+     * 祖级列表
+     */
+    @ApiModelProperty(value = "祖级id列表")
+    private String ancestors;
+
+    /**
+     * 是否是叶子节点, 1 是 0 不是
+     */
+    @ApiModelProperty(value = "是否是叶子节点, 1 是 0 不是")
+    private Integer isLeaf;
+
+    /**
+     * 叶子节点数量
+     */
+    @ApiModelProperty(value = "叶子节点数量")
+    private Integer leafNum = 0;
+
+    /**
+     * 已填报数量
+     */
+    @ApiModelProperty(value = "已填报数量")
+    private Integer fillNum = 0;
+    /**
+     * 待审批数量
+     */
+    @ApiModelProperty(value = "待审批数量")
+    private Integer approveNum = 0;
+    /**
+     * 已审批数量
+     */
+    @ApiModelProperty(value = "已审批数量")
+    private Integer completeNum = 0;
+    /**
+     * 已填报数量(监理)
+     */
+    @ApiModelProperty(value = "已填报数量(监理)")
+    private Integer jlFillNum = 0;
+    /**
+     * 待审批数量(监理)
+     */
+    @ApiModelProperty(value = "待审批数量(监理)")
+    private Integer jlApproveNum = 0;
+    /**
+     * 已审批数量(监理)
+     */
+    @ApiModelProperty(value = "已审批数量(监理)")
+    private Integer jlCompleteNum = 0;
+
+    @DateTimeFormat(
+            pattern = "yyyy-MM-dd HH:mm:ss"
+    )
+    @JsonFormat(
+            pattern = "yyyy-MM-dd HH:mm:ss"
+    )
+    @ApiModelProperty("创建时间")
+    private Date createTime;
+
+    @DateTimeFormat(
+            pattern = "yyyy-MM-dd HH:mm:ss"
+    )
+    @JsonFormat(
+            pattern = "yyyy-MM-dd HH:mm:ss"
+    )
+    @ApiModelProperty("更新时间")
+    private Date updateTime = new Date();
+
+    @ApiModelProperty("业务状态")
+    private Integer status = 1;
+    @TableLogic
+    @ApiModelProperty("是否已删除")
+    private Integer isDeleted = 0;
+
+
+    public WbsTreeContractStatistics() {
+
+    }
+    public WbsTreeContractStatistics(Long pKeyId, String projectId, String contractId, Long pId, String ancestors) {
+        if (pKeyId != null) {
+            this.id =pKeyId;
+            this.projectId = projectId;
+            this.contractId = contractId;
+            this.parentId = pId == null ? 0L : pId;
+            this.ancestors = ancestors == null ? "" : ancestors;
+            this.status = 1;
+            this.isLeaf = 1;
+        }
+    }
+
+    public WbsTreeContractStatistics(Long pKeyId, String projectId, String contractId, Long pId, String ancestors, Integer isLeaf) {
+        this(pKeyId, projectId, contractId, pId, ancestors);
+        this.isLeaf = isLeaf;
+    }
+
+    public Integer calculateSgSubmitNums() {
+        this.fillNum = this.fillNum == null ? 0 : this.fillNum;
+        this.approveNum = this.approveNum == null ? 0 : this.approveNum;
+        this.completeNum = this.completeNum == null ? 0 : this.completeNum;
+        return this.approveNum + this.completeNum + this.fillNum;
+    }
+
+    public Integer calculateSgColorStatus() {
+        this.fillNum = this.fillNum == null ? 0 : this.fillNum;
+        this.approveNum = this.approveNum == null ? 0 : this.approveNum;
+        this.completeNum = this.completeNum == null ? 0 : this.completeNum;
+        return calculateStatus(this.fillNum, this.approveNum, this.completeNum, this.leafNum);
+    }
+
+    public Integer calculateJlSubmitNums() {
+        this.jlApproveNum = this.jlApproveNum == null ? 0 : this.jlApproveNum;
+        this.jlCompleteNum = this.jlCompleteNum == null ? 0 : this.jlCompleteNum;
+        this.jlFillNum = this.jlFillNum == null ? 0 : this.jlFillNum;
+        return this.jlApproveNum + this.jlCompleteNum + this.jlFillNum;
+    }
+
+    public Integer calculateJlColorStatus() {
+        this.jlApproveNum = this.jlApproveNum == null ? 0 : this.jlApproveNum;
+        this.jlCompleteNum = this.jlCompleteNum == null ? 0 : this.jlCompleteNum;
+        this.jlFillNum = this.jlFillNum == null ? 0 : this.jlFillNum;
+        return calculateStatus(this.jlFillNum, this.jlApproveNum, this.jlCompleteNum, this.leafNum);
+    }
+
+    // 1 未填报 2已填报 3待审批 4 已审批
+    public int calculateStatus(int fillNum, int approveNum, int completeNum, int leafNum) {
+        // 叶子节点只有一种情况的
+        if (fillNum == 0 && approveNum == 0 && completeNum == 0) {
+            return 1;
+        }
+        if ((leafNum == 0 || leafNum == completeNum) && completeNum > 0 && approveNum == 0 && fillNum == 0) {
+            return 4;
+        }
+        if ((leafNum == 0 || leafNum == approveNum) && completeNum == 0 && approveNum > 0 && fillNum == 0) {
+            return 3;
+        }
+        if ((leafNum == 0 || leafNum == fillNum) && completeNum == 0 && approveNum == 0 && fillNum > 0) {
+            return 2;
+        }
+        int unApproveNum = Math.max(leafNum - approveNum - completeNum - fillNum, 0);
+        if (unApproveNum == 0 && fillNum == 0 && approveNum > 0 && completeNum > 0) {
+            return 3;
+        }
+        return 2;
+    }
+
+    public Integer calculateSubmitNums(String tableOwner) {
+        if ("1".equals(tableOwner)) {
+            return calculateSgSubmitNums();
+        } else if ("2".equals(tableOwner)) {
+            return calculateJlSubmitNums();
+        }
+        return null;
+    }
+
+    public Integer calculateColorStatus(String tableOwner) {
+        if ("1".equals(tableOwner)) {
+            return calculateSgColorStatus();
+        } else if ("2".equals(tableOwner)) {
+            return calculateJlColorStatus();
+        }
+        return null;
+    }
+}

+ 48 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/feign/WbsTreeContractStatisticsClient.java

@@ -0,0 +1,48 @@
+package org.springblade.business.feign;
+
+
+import org.springblade.business.dto.WbsTreeContractStatisticsDTO;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.util.List;
+
+import static org.springblade.core.launch.constant.AppConstant.APPLICATION_NAME_PREFIX;
+
+@FeignClient(value = APPLICATION_NAME_PREFIX + "business")
+public interface WbsTreeContractStatisticsClient {
+
+    /**
+     * 接口前缀
+     */
+    String API_PREFIX = "/api/business/WbsTreeContractStatistics";
+
+    /**
+     * 更新统计表节点信息
+     * WbsTreeContractStatisticsDTO
+     */
+    @PostMapping(API_PREFIX + "/updateInformationQuery")
+    void updateInformationQueryStatus(@RequestBody List<WbsTreeContractStatisticsDTO> wbsTreeContractStatisticsDTOs);
+
+    @GetMapping(API_PREFIX + "/updateInformationQueryStatusByTaskId")
+    void updateInformationQueryStatusByTaskId(@RequestParam String taskIds);
+
+    /**
+     * 更新统计表节点
+     */
+    @GetMapping(API_PREFIX + "/updateWbsTreeContractNodes")
+    void updateWbsTreeContractNodes(@RequestParam String nodeIds);
+
+    @GetMapping(API_PREFIX + "/delWbsTreeContractNodes")
+    void delWbsTreeContractNodes(@RequestParam String nodeIds);
+
+    @GetMapping(API_PREFIX + "/recycleWbsTreeContractNodes")
+    void recycleWbsTreeContractNodes(@RequestParam String nodeIds);
+
+    @GetMapping(API_PREFIX + "/statisticsContract")
+    void statisticsContract(@RequestParam Long contractId);
+
+}

+ 79 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/DqOperationLog.java

@@ -0,0 +1,79 @@
+package org.springblade.manager.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+
+import io.swagger.annotations.ApiModelProperty;
+import org.springblade.core.mp.base.BaseEntity;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.core.secure.BladeUser;
+import org.springblade.core.secure.utils.AuthUtil;
+
+import java.util.Date;
+
+
+@Data
+@TableName("u_dq_operation_log")
+@EqualsAndHashCode(callSuper = true)
+public class DqOperationLog extends BaseEntity {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty("项目id")
+    private Long projectId;
+
+    @ApiModelProperty("节点pKeyId")
+    private Long nodeId;
+
+    /**
+     * 操作类型
+     */
+    @ApiModelProperty("操作类型, 1:保存,2:删除")
+    private Integer operationType;
+
+    /**
+     * 参数
+     */
+    @ApiModelProperty("参数")
+    private String operationContent;
+
+    /**
+     * 旧内容
+     */
+    @ApiModelProperty("旧内容")
+    private String oldContent;
+
+    /**
+     * 新内容
+     */
+    @ApiModelProperty("新内容")
+    private String newContent;
+
+    /**
+     * textdict_info ids
+     */
+    @ApiModelProperty("textdict_info ids")
+    private String businessId;
+
+    @ApiModelProperty("操作人")
+    private String createUserName;
+
+
+
+    public DqOperationLog() {
+    }
+
+    public DqOperationLog(WbsTreePrivate wbsTreePrivate, BladeUser user, String businessId, Integer type, String param, String oldContent, String newContent) {
+        this.projectId = Long.parseLong(wbsTreePrivate.getProjectId());
+        this.nodeId = wbsTreePrivate.getPKeyId();
+        this.operationType = type;
+        this.operationContent = param;
+        this.createUserName = user.getUserName();
+        this.businessId = businessId;
+        this.oldContent = oldContent;
+        this.newContent = newContent;
+        this.setCreateTime(new Date());
+        this.setCreateUser(user.getUserId());
+        this.setCreateUserName(user.getUserName());
+    }
+}

+ 2 - 1
blade-service-api/blade-user-api/src/main/java/org/springblade/system/user/feign/IUserClient.java

@@ -185,5 +185,6 @@ public interface IUserClient {
     @GetMapping(API_PREFIX + "/clearContractLocalCacheAndRedisCache")
     void clearContractLocalCacheAndRedisCache();
 
-
+    @GetMapping(API_PREFIX + "/getTokenByUser")
+    String getTokenByUser(@RequestParam String account);
 }

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

@@ -38,6 +38,8 @@ public class ArchiveProjectConfigController {
         archiveProjectConfig.setIndexType(config.getIndexType());
         archiveProjectConfig.setDirType(config.getDirType());
         archiveProjectConfig.setIndexNum(config.getIndexNum());
+        archiveProjectConfig.setPageType(config.getPageType());
+        archiveProjectConfig.setPageLen(config.getPageLen());
         boolean result = archiveProjectConfigService.updateById(archiveProjectConfig);
         return R.status(result);
     }

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

@@ -158,6 +158,16 @@ public class ArchivesAutoController extends BladeController {
 		int test = 0;
 		//todo 后续去掉
 		if (test > 1) {
+
+			List<ArchiveTreeContract> archiveTreeContracts = this.archiveTreeContractClient.queryAllChildByAncestors(queryVo.getNodeIds(),queryVo.getContractId());
+
+			List<String> ids = JSONArray.parseArray(JSONObject.toJSONString(archiveTreeContracts.stream().map(ArchiveTreeContract::getId).distinct().collect(Collectors.toList())), String.class);
+			ids.add(queryVo.getNodeIds());
+
+	        String result = String.join(",", ids);
+
+			System.out.println("nodeid (" + result + ")");
+
 			List<String> nodeIdArray = queryVo.getNodeIdArray();
 			// 注意:在设置nodeIdArray的条件分支外,nodeIdArray可能为null
 			if (nodeIdArray != null) {
@@ -200,7 +210,7 @@ public class ArchivesAutoController extends BladeController {
 		String templatePath = "/mnt/sdc/Users/hongchuangyanfa/Desktop/excel/archiveTemplate.xlsx";
 		//String templatePath="C:\\Users\\hc01\\Desktop\\archiveTemplate.xlsx";
 		InputStream templateStream = new FileInputStream(new File(templatePath));
-		org.apache.poi.ss.usermodel.Workbook workbook = WorkbookFactory.create(templateStream);
+		Workbook workbook = WorkbookFactory.create(templateStream);
 		Sheet sheet = workbook.getSheetAt(0);
 
 		// 创建带边框的单元格样式
@@ -622,8 +632,26 @@ public class ArchivesAutoController extends BladeController {
 			return R.fail("请选择多个案卷进行合并");
 		}
 		archivesAutoList.sort(Comparator.comparingInt(a -> {
-			String[] parts = a.getFileNumber().split("_");
-			return Integer.parseInt(parts[parts.length - 1]); // 取最后一个部分作为数字
+			String fileNumber = a.getFileNumber();
+			if (fileNumber == null || fileNumber.isEmpty()) {
+				return Integer.MAX_VALUE;
+			}
+			String[] parts;
+			if (fileNumber.indexOf("_") > 0) {
+				parts = fileNumber.split("_");
+			} else if (fileNumber.indexOf("-") > 0) {
+				parts = fileNumber.split("-");
+			} else {
+				return Integer.MAX_VALUE;
+			}
+			if (parts.length > 0) {
+				try {
+					return Integer.parseInt(parts[parts.length - 1]);
+				} catch (NumberFormatException e) {
+					return Integer.MAX_VALUE;
+				}
+			}
+			return Integer.MAX_VALUE;
 		}));
 		//根据档号后缀排序 拿到第一个
 		ArchivesAuto auto = archivesAutoList.get(0);

+ 12 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/TaskSplitController.java

@@ -34,6 +34,8 @@ import org.springblade.archive.entity.TaskSplit;
 import org.springblade.archive.service.ITaskSplitService;
 import org.springblade.core.boot.ctrl.BladeController;
 
+import java.util.Map;
+
 /**
  * 解析主标任务 控制器
  *
@@ -92,6 +94,16 @@ public class TaskSplitController extends BladeController {
 		return taskSplitService.saveTaskSplit(taskSplit);
 	}
 
+	/**
+	 * 查询 解析主标任务
+	 */
+	@PostMapping("/getSaveInfo")
+	@ApiOperationSupport(order = 2)
+	@ApiOperation(value = "查询 解析主标任务", notes = "传入taskSplit")
+	public R<Map<String, Object>> getSaveInfo(@Valid @RequestBody TaskSplit taskSplit) {
+		return taskSplitService.getSaveInfo(taskSplit);
+	}
+
 /*
 	*/
 /**

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

@@ -218,6 +218,7 @@ public class ExternalDataArchiveFileService {
         local.setFileSize(external.getFileSize());
         local.setUtime(external.getUtime());
         local.setNodeId(external.getNodeId());
+        local.setSort(external.getSort());
         //local.setArchiveId(external.getArchiveId());
     }
 

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

@@ -51,6 +51,20 @@ public class TransUtil {
         //建设单位数字化扫描档案(第二部分 决算和审计文件) 一、支付报表及计算单
         put("c3073682882249cb83fb87ef83d4", 1945670728317665296L);
 
+
+        //==========特殊
+        //建设单位数字化扫描档案(第一部分 综合文件)-二、建设依据及上级有关指示-立项
+        put("0284c9f77242489d93da723584ce", 1945670728317665287L);
+        //建设单位数字化扫描档案(第一部分 综合文件)-二、建设依据及上级有关指示-勘察
+        put("3ae2565bad2b498182b8077f03ed", 1945670728317665288L);
+        //建设单位数字化扫描档案(第一部分 综合文件)-二、建设依据及上级有关指示-许可批准
+        put("e9eea9a2ef34469c8fb1c935499a", 1945670728317665289L);
+
+        //建设单位数字化扫描档案(第一部分 综合文件)-二、工程管理文件-工程招标
+        put("d41e35addf2f49a8aa3cd552c3ba", 1945670728317665293L);
+        //建设单位数字化扫描档案(第一部分 综合文件)-二、工程管理文件-其他文件和资料
+        put("39afe1a44c664f23a4dc8b3a817f", 1945670728317665294L);
+
         //====监理
         //====================【第一总监】
 

+ 3 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/service/ITaskSplitService.java

@@ -22,6 +22,8 @@ import org.springblade.core.mp.base.BaseService;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.springblade.core.tool.api.R;
 
+import java.util.Map;
+
 /**
  * 解析主标任务 服务类
  *
@@ -41,4 +43,5 @@ public interface ITaskSplitService extends BaseService<TaskSplit> {
 
 	R saveTaskSplit(TaskSplit taskSplit);
 
+	R<Map<String, Object>> getSaveInfo(TaskSplit taskSplit);
 }

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

@@ -378,7 +378,9 @@ public class ArchiveAutoPdfServiceImpl implements IArchiveAutoPdfService {
             }
         }
         String localPath = FileUtils.getSysLocalFileUrl();
-        List<String> pageUrls = FileUtils.doForPageNumberUseItextpdf(urls, localPath, newIOSSClient, archivesAuto.getProjectId());
+        // 传递页码配置参数
+        List<String> pageUrls = FileUtils.doForPageNumberUseItextpdf(urls, localPath, newIOSSClient,
+                archivesAuto.getProjectId(), config.getPageType(), config.getPageLen());
         for (int i = 0; i < waitArchiveFiles.size(); i++) {
             waitArchiveFiles.get(i).setPdfPageUrl(pageUrls.get(i));
         }

Файловите разлики са ограничени, защото са твърде много
+ 212 - 257
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java


+ 38 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/TaskSplitServiceImpl.java

@@ -28,6 +28,7 @@ import org.springblade.core.tool.utils.DateUtil;
 import org.springblade.core.tool.utils.Func;
 import org.springframework.stereotype.Service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.springframework.util.StringUtils;
 
 import javax.annotation.Resource;
 import java.time.LocalDateTime;
@@ -111,4 +112,41 @@ public class TaskSplitServiceImpl extends BaseServiceImpl<TaskSplitMapper, TaskS
 		return R.data(200,data,"操作成功");
 	}
 
+    @Override
+    public R<Map<String, Object>> getSaveInfo(TaskSplit taskSplit) {
+        Random random = new Random();
+        // 数据校验区
+        Map<String, Object> data = new HashMap<>();
+        String contractId = taskSplit.getContractId();
+        String splitIds = taskSplit.getIds();
+        if (StringUtils.isEmpty(contractId)) {
+            return R.fail("合同段Id为空");
+        }
+        // 代表整个合同解析
+        if (StringUtils.isEmpty(splitIds) || Func.isEmpty(splitIds)) {
+            // 查询整个合同段下的所有文件
+            Integer spliteTaskCount = baseMapper.getSpliteTaskCount(contractId);
+            if (spliteTaskCount >= 1) {
+                return R.fail("该合同已经添加任务,无需重复操作");
+            }
+            // 生成10到20之间的随机数
+            int randomNumber = random.nextInt(30) + 150;
+            int i = (int) Math.ceil(randomNumber * spliteTaskCount / 60.0);
+
+            Integer archiveCount = baseMapper.getArchiveCount(contractId);
+            data.put("fileCount", archiveCount);
+            data.put("taskTime", i);
+
+        } else {
+            // 指定文件解析
+            List<String> split = Func.toStrList(splitIds);
+            // 生成10到20之间的随机数
+            int randomNumber = random.nextInt(30) + 150;
+            int i = (int) Math.ceil(randomNumber * split.size() / 60.0);
+            data.put("fileCount", split.size());
+            data.put("taskTime", i);
+        }
+
+        return R.data(200, data, "操作成功");
+    }
 }

+ 33 - 3
blade-service/blade-archive/src/main/java/org/springblade/archive/utils/FileUtils.java

@@ -495,6 +495,10 @@ public class FileUtils {
      * @Date 2021.12.17 14:21
      **/
     public static List<String> doForPageNumberUseItextpdf(List<String> uris, String localPath, NewIOSSClient newIOSSClient, Long projectId) {
+        return doForPageNumberUseItextpdf(uris, localPath, newIOSSClient, projectId, 0, 0);
+    }
+
+    public static List<String> doForPageNumberUseItextpdf(List<String> uris, String localPath, NewIOSSClient newIOSSClient, Long projectId, Integer pageType, Integer pageLen) {
         List<String> result = new ArrayList<>();
         if (uris != null && uris.size() > 0) {
             int cursor = 0;
@@ -563,19 +567,22 @@ public class FileUtils {
 //                                heigh = temp;
 //                            }
 
+                            // 格式化页码
+                            String pageNumber = formatPageNumber(cursor + index, pageType, pageLen);
+                            
                             if (width > heigh && heigh != 0) {
                                 //横表旋转270
                                 pdfReader.getPageN(index).put(PdfName.ROTATE, new PdfNumber(270)); // 顺时针旋转270°
                                 //横表旋转后打页码坐标不一样
-                                over.showTextAligned(Element.ALIGN_LEFT, String.valueOf(cursor + index), heigh - 35, 20, 0);
+                                over.showTextAligned(Element.ALIGN_LEFT, pageNumber, heigh - 35, 20, 0);
                             } else {
                                 if (rotate!= null && rotate.intValue() == 270) {
                                     //交换width和height
                                     pdfReader.getPageN(index).put(PdfName.ROTATE, new PdfNumber(0)); // 顺时针旋转270°
                                     //横表旋转后打页码坐标不一样
-                                    over.showTextAligned(Element.ALIGN_LEFT, String.valueOf(cursor + index), width - 35, 20, 0);
+                                    over.showTextAligned(Element.ALIGN_LEFT, pageNumber, width - 35, 20, 0);
                                 }else {
-                                    over.showTextAligned(Element.ALIGN_LEFT, String.valueOf(cursor + index), width - 35, 20, 0);
+                                    over.showTextAligned(Element.ALIGN_LEFT, pageNumber, width - 35, 20, 0);
                                 }
                             }
                             over.endText();
@@ -838,4 +845,27 @@ public class FileUtils {
         return cleaned.length() > 8 ? cleaned.substring(0, 8) : cleaned;
     }
 
+    /**
+     * 格式化页码
+     * @param pageNumber 原始页码
+     * @param pageType 页码类型,0-默认无虚数,1-有虚数
+     * @param pageLen 页码位数
+     * @return 格式化后的页码
+     */
+    private static String formatPageNumber(int pageNumber, Integer pageType, Integer pageLen) {
+        if (pageType == null || pageType == 0) {
+            // 默认情况,直接返回页码
+            return String.valueOf(pageNumber);
+        }
+        
+        if (pageType == 1 && pageLen != null && pageLen > 0) {
+            // 需要补齐虚数
+            String format = "%0" + pageLen + "d";
+            return String.format(format, pageNumber);
+        }
+        
+        // 其他情况返回默认页码
+        return String.valueOf(pageNumber);
+    }
+
 }

+ 4 - 0
blade-service/blade-business/pom.xml

@@ -31,6 +31,10 @@
             <groupId>org.springblade</groupId>
             <artifactId>blade-core-boot</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.springblade</groupId>
+            <artifactId>blade-core-test</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.springblade</groupId>
             <artifactId>blade-starter-swagger</artifactId>

+ 24 - 3
blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java

@@ -21,11 +21,18 @@ import org.springblade.business.dto.CustomAddContractNodeDTO;
 import org.springblade.business.dto.FlushQueryNameDTO;
 import org.springblade.business.dto.PreviewNodeNameDTO;
 import org.springblade.business.dto.PreviewNodeNameDTO1;
+import org.springblade.business.dto.ImportTreeDto;
+import org.springblade.business.dto.WbsTreeContractStatisticsDTO;
+import org.springblade.business.dto.FlushQueryNameDTO;
+import org.springblade.business.dto.FlushQueryNameDTO;
+import org.springblade.business.dto.PreviewNodeNameDTO;
+import org.springblade.business.dto.PreviewNodeNameDTO1;
 import org.springblade.business.entity.*;
 import org.springblade.business.feign.MessageWarningClient;
 import org.springblade.business.feign.OperationLogClient;
 import org.springblade.business.feign.RecycleBinClient;
 import org.springblade.business.feign.TaskClient;
+import org.springblade.business.feignClient.WbsTreeContractStatisticsClientImpl;
 import org.springblade.business.mapper.InformationQueryMapper;
 import org.springblade.business.service.*;
 import org.springblade.business.utils.FileUtils;
@@ -137,6 +144,7 @@ public class InformationWriteQueryController extends BladeController {
     private final ExcelTabClient excelTabClient;
 
     private final IRecycleBinService recycleBinService;
+    private final WbsTreeContractStatisticsClientImpl wbsTreeContractStatisticsClient;
 
 
     @Autowired
@@ -1568,6 +1576,10 @@ public R<String> batchDownloadFileToZip(String ids, HttpServletResponse response
                         for (Long contractId1 : contractIds) {
                             informationQueryService.delAsyncWbsTree(contractId1 + "");
                         }
+                        if (!queries.isEmpty()) {
+                            List<WbsTreeContractStatisticsDTO> collect1 = queries.stream().filter(query -> query.getType() == 1).map(WbsTreeContractStatisticsDTO::new).collect(Collectors.toList());
+                            wbsTreeContractStatisticsClient.updateInformationQueryStatus(collect1);
+                        }
                     }
 
                     try {
@@ -1838,7 +1850,10 @@ public R<Object> batchTask(@RequestBody StartTaskVO startTaskVO) {
             }
 
             informationQueryService.delAsyncWbsTree(startTaskVO.getContractId());
-
+            if (queries != null && !queries.isEmpty()) {
+                List<WbsTreeContractStatisticsDTO> collect1 = queries.stream().filter(query -> query.getType() == 1).map(WbsTreeContractStatisticsDTO::new).collect(Collectors.toList());
+                wbsTreeContractStatisticsClient.updateInformationQueryStatus(collect1);
+            }
             return R.data(200, aopParamsSet, "操作成功");
         }
     }
@@ -2036,7 +2051,9 @@ public R<Boolean> copyContractTreeNode(@RequestBody CopyContractTreeNodeVO vo) {
                     //TODO 20250414-lhb-新增
                     newData.setTreePId(oldToNewIdMap.containsKey(nodeOld.getId()) ? oldToNewIdMap.get(nodeOld.getId()) : SnowFlakeUtil.getId());
                     //新节点设置规划编号
-                    newData.setPartitionCode(StringUtils.isNotEmpty(vo.getPartitionCode()) ? vo.getPartitionCode() : null);
+                    if (vo.getNeedCopyPrimaryKeyId().equals(nodeOld.getPKeyId().toString())) {
+                        newData.setPartitionCode(StringUtils.isNotEmpty(vo.getPartitionCode()) ? vo.getPartitionCode() : null);
+                    }
                 }
                 //如果当前节点是选中节点
                 if (vo.getNeedCopyPrimaryKeyId().equals(nodeOld.getPKeyId().toString())) {
@@ -2177,7 +2194,7 @@ public R<Boolean> copyContractTreeNode(@RequestBody CopyContractTreeNodeVO vo) {
 
         /*更新缓存*/
         informationQueryService.delAsyncWbsTree(needCopyNode.getContractId());
-
+        wbsTreeContractStatisticsClient.updateWbsTreeContractNodes(saveList.stream().map(item -> item.getPKeyId() + "").collect(Collectors.joining(",")));
         return booleanR;
 
     } else if (("2").equals(vo.getCopyType())) {
@@ -2397,6 +2414,7 @@ public R<Boolean> copyContractTreeNode(@RequestBody CopyContractTreeNodeVO vo) {
                 if (row) {
                     //更新redis缓存
                     informationQueryService.delAsyncWbsTree(contractId);
+                    wbsTreeContractStatisticsClient.updateWbsTreeContractNodes(nodes.stream().map(item -> item.getPKeyId() + "").collect(Collectors.joining(",")));
                 }
 
                 //拼接操作记录
@@ -3677,6 +3695,7 @@ public R removeContractTreeNodeJudge(@RequestParam String ids) {
             this.wbsTreeContractClient.removeContractTreeNode(idArray);
             //更新redis
             this.informationQueryService.delAsyncWbsTree(removeWbsTreeContracts.get(0).getContractId());
+            this.wbsTreeContractStatisticsClient.delWbsTreeContractNodes(String.join(",", idArray));
         }
         return R.data(true);
     }
@@ -4185,6 +4204,7 @@ public R<Boolean> saveContractTreeNode(@RequestBody AddContractTreeNodeVO vo) {
 
         List<WbsTreeContract> nowTabs = saveList.stream().filter(f -> new Integer(2).equals(f.getType())).collect(Collectors.toList());
         this.updateTextDictInfos(nowTabs, oldTabIds, vo.getProjectId());//获取电签信息、默认信息
+        wbsTreeContractStatisticsClient.updateWbsTreeContractNodes(saveList.stream().map(item -> item.getPKeyId() + "").collect(Collectors.joining(",")));
         iUserClient.clearContractLocalCacheAndRedisCache();
         flag=booleanR.getData();
         if(!flag){
@@ -5073,6 +5093,7 @@ public R<Object> customAddContractNode(@RequestBody CustomAddContractNodeDTO dto
         }
         if (wbsTreeContractClient.saveBatch(Collections.singletonList(obj))) {
             informationQueryService.delAsyncWbsTree(parentNode.getContractId());
+            wbsTreeContractStatisticsClient.updateWbsTreeContractNodes(obj.getPKeyId() + "");
             return R.success("操作成功");
         }
 

+ 4 - 0
blade-service/blade-business/src/main/java/org/springblade/business/controller/RecycleBinController.java

@@ -13,6 +13,7 @@ import org.apache.commons.lang.StringUtils;
 import org.springblade.business.entity.ArchiveFile;
 import org.springblade.business.entity.ImageClassificationFile;
 import org.springblade.business.feign.InformationQueryClient;
+import org.springblade.business.feignClient.WbsTreeContractStatisticsClientImpl;
 import org.springblade.business.service.IArchiveFileService;
 import org.springblade.business.service.IImageClassificationFileService;
 import org.springblade.business.vo.RecycleBinVO;
@@ -53,6 +54,8 @@ public class RecycleBinController extends BladeController {
 
     private final InformationQueryClient informationQueryClient;
 
+    private final WbsTreeContractStatisticsClientImpl wbsTreeContractStatisticsClient;
+
     /**
      * 恢复
      */
@@ -83,6 +86,7 @@ public class RecycleBinController extends BladeController {
                     e.printStackTrace();
                 }
                 informationQueryClient.delAsyncWbsTree(nodeTypeList.get(0).getContractId() + "");
+                wbsTreeContractStatisticsClient.recycleWbsTreeContractNodes(String.join(",", processNodeList));
             }
             //文件类型
             List<RecycleBin> fileTypeList = recycleBinList.stream().filter(recycleBin -> new Integer("1").equals(recycleBin.getDelType())).distinct().collect(Collectors.toList());

+ 43 - 40
blade-service/blade-business/src/main/java/org/springblade/business/controller/TaskController.java

@@ -1527,48 +1527,51 @@ public class TaskController extends BladeController {
                             Task::getId,
                             task -> task));
         }
-        //所有满足条件的日志 转map
-        String logQuery = "select business_id,create_user_name ,create_time, operation_type, save_data from u_operation_log where operation_type in (6,9,12,15,18,21,24,26,61,62)";
-        List<OperationLog> operationLogs = jdbcTemplate.query(logQuery, new BeanPropertyRowMapper<>(OperationLog.class));
-        if(ObjectUtil.isNotEmpty(operationLogs)){
-             operationLogMap = operationLogs.stream().collect(Collectors.groupingBy(OperationLog::getBusinessId));
-        }
-        for (BusinessTaskPageVO businessTaskPageVO : pageList) {
-            if("已废除".equals(businessTaskPageVO.getTaskStatusName())){
-                Long taskId = businessTaskPageVO.getTaskId();
-                Task task = taskMap.get(taskId);
-                if (ObjectUtil.isEmpty(task)){
-                    continue;
-                }
-                //任务创建时间
-                Date createTime = task.getCreateTime();
-                //废除时间肯定在任务创建时间之后  选择距离当前任务创建时间最近的一条数据
-                List<OperationLog> operationLogsF = operationLogMap.get(task.getFormDataId());
-
-                if(ObjectUtil.isNotEmpty(operationLogsF)){
-                    Optional<OperationLog> min = operationLogsF.stream().filter(o -> o.getCreateTime().compareTo(createTime) >= 0)
-                            .min(Comparator.comparing(t -> t.getCreateTime().getTime() - createTime.getTime()));
-                    if (min.isPresent()){
-                        OperationLog operationLog = min.get();
-                        String createUserName = operationLog.getCreateUserName();
-                        String date = DateUtil.formatDateTime(operationLog.getCreateTime());
-                        if (operationLog.getOperationType() != null && operationLog.getOperationType() == 61) {
-                            businessTaskPageVO.setEVisaStatus("驳回成功:"+ createUserName +"-"+ date);
-                            String saveData = operationLog.getSaveData();
-                            if (saveData != null && !saveData.isEmpty()) {
-                                try  {
-                                    JSONObject data = JSONObject.parseObject(saveData);
-                                    if (data != null && data.containsKey("comment")) {
-                                        businessTaskPageVO.setEVisaStatus("驳回成功:"+ createUserName +"-"+ date + ";驳回原因:"+data.getString("comment"));
+        if(CollectionUtil.isNotEmpty(pageList)){
+            //所有满足条件的日志 转map
+            Set<String> collect = pageList.stream().map(BusinessTaskPageVO::getFormDataId).collect(Collectors.toSet());
+            String logQuery = "select business_id,create_user_name ,create_time, operation_type, save_data from u_operation_log where business_id in (" + StringUtil.join(collect) + ") and operation_type in (6,9,12,15,18,21,24,26,61,62)";
+            List<OperationLog> operationLogs = jdbcTemplate.query(logQuery, new BeanPropertyRowMapper<>(OperationLog.class));
+            if(ObjectUtil.isNotEmpty(operationLogs)){
+                operationLogMap = operationLogs.stream().collect(Collectors.groupingBy(OperationLog::getBusinessId));
+            }
+            for (BusinessTaskPageVO businessTaskPageVO : pageList) {
+                if("已废除".equals(businessTaskPageVO.getTaskStatusName())){
+                    Long taskId = businessTaskPageVO.getTaskId();
+                    Task task = taskMap.get(taskId);
+                    if (ObjectUtil.isEmpty(task)){
+                        continue;
+                    }
+                    //任务创建时间
+                    Date createTime = task.getCreateTime();
+                    //废除时间肯定在任务创建时间之后  选择距离当前任务创建时间最近的一条数据
+                    List<OperationLog> operationLogsF = operationLogMap.get(task.getFormDataId());
+
+                    if(ObjectUtil.isNotEmpty(operationLogsF)){
+                        Optional<OperationLog> min = operationLogsF.stream().filter(o -> o.getCreateTime().compareTo(createTime) >= 0)
+                                .min(Comparator.comparing(t -> t.getCreateTime().getTime() - createTime.getTime()));
+                        if (min.isPresent()){
+                            OperationLog operationLog = min.get();
+                            String createUserName = operationLog.getCreateUserName();
+                            String date = DateUtil.formatDateTime(operationLog.getCreateTime());
+                            if (operationLog.getOperationType() != null && operationLog.getOperationType() == 61) {
+                                businessTaskPageVO.setEVisaStatus("驳回成功:"+ createUserName +"-"+ date);
+                                String saveData = operationLog.getSaveData();
+                                if (saveData != null && !saveData.isEmpty()) {
+                                    try  {
+                                        JSONObject data = JSONObject.parseObject(saveData);
+                                        if (data != null && data.containsKey("comment")) {
+                                            businessTaskPageVO.setEVisaStatus("驳回成功:"+ createUserName +"-"+ date + ";驳回原因:"+data.getString("comment"));
+                                        }
+                                    } catch (Exception e) {
+                                        e.printStackTrace();
                                     }
-                                } catch (Exception e) {
-                                    e.printStackTrace();
                                 }
+                            } else if (operationLog.getOperationType() != null && operationLog.getOperationType() == 62) {
+                                businessTaskPageVO.setEVisaStatus("撤回成功:"+ createUserName +"-"+ date);
+                            } else {
+                                businessTaskPageVO.setEVisaStatus(businessTaskPageVO.getEVisaStatus()+":"+ createUserName +"-"+ date);
                             }
-                        } else if (operationLog.getOperationType() != null && operationLog.getOperationType() == 62) {
-                            businessTaskPageVO.setEVisaStatus("撤回成功:"+ createUserName +"-"+ date);
-                        } else {
-                            businessTaskPageVO.setEVisaStatus(businessTaskPageVO.getEVisaStatus()+":"+ createUserName +"-"+ date);
                         }
                     }
                 }
@@ -2126,7 +2129,7 @@ public class TaskController extends BladeController {
     /**
      * 任务超时提示信息
      */
-    @Scheduled(cron = "0 0 3 * * ?")
+//    @Scheduled(cron = "0 0 3 * * ?")
     public void TaskTimeoutTips() {
         String key = "task.time.out";
         String value = ParamCache.getValue(key);

+ 163 - 0
blade-service/blade-business/src/main/java/org/springblade/business/feignClient/WbsTreeContractStatisticsClientImpl.java

@@ -0,0 +1,163 @@
+package org.springblade.business.feignClient;
+
+import lombok.AllArgsConstructor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springblade.business.dto.WbsTreeContractStatisticsDTO;
+import org.springblade.business.entity.InformationQuery;
+import org.springblade.business.feign.WbsTreeContractStatisticsClient;
+import org.springblade.business.mapper.InformationQueryMapper;
+import org.springblade.business.service.IWbsTreeContractStatisticsService;
+import org.springblade.business.service.impl.WbsTreeContractStatisticsServiceImpl;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.time.LocalDateTime;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+
+@RestController
+@AllArgsConstructor
+public class WbsTreeContractStatisticsClientImpl implements WbsTreeContractStatisticsClient {
+
+    private final IWbsTreeContractStatisticsService wbsTreeContractStatisticsService;
+    private final JdbcTemplate jdbcTemplate;
+    private final StringRedisTemplate redisTemplate;
+    private static final Logger log = LoggerFactory.getLogger(WbsTreeContractStatisticsClientImpl.class);
+    private static final String INFORMATION_QUERY_STATUS_STATISTICS_KEY = "blade:statistics:information_query_statistics_key";
+
+    @Scheduled(cron = "0/30 * * * * ?")
+    public void updateInformationQueryStatus() {
+        Map<String, String> map = new HashMap<>();
+        List<String> queryIds = redisTemplate.opsForList().range(INFORMATION_QUERY_STATUS_STATISTICS_KEY, 0, 100);
+        if (queryIds != null && !queryIds.isEmpty()) {
+            String ids = queryIds.stream().distinct().collect(Collectors.joining(","));
+            List<InformationQuery> queryList = jdbcTemplate.query("select wbs_id, classify, contract_id from u_information_query where id in ( " + ids +" ) and is_deleted = 0 group by contract_id,wbs_id,classify",
+                    new BeanPropertyRowMapper<>(InformationQuery.class));
+            if (!queryList.isEmpty()) {
+                for (InformationQuery query : queryList) {
+                    if (map.containsKey(query.getWbsId() + "," + query.getContractId() + "," + query.getClassify())) {
+                        continue;
+                    }
+                    try {
+                        wbsTreeContractStatisticsService.updateInformationNumber(query.getWbsId(), query.getClassify(), query.getContractId());
+                        map.put(query.getWbsId() + "," + query.getContractId() + "," + query.getClassify(), "");
+                    } catch (Exception e) {
+                        redisTemplate.opsForList().rightPush("blade:statistics:information_query_statistics_key", query.getId() + "");
+                        log.error("updateInformationQueryStatus wbsId = {}, contractId = {}, classify = {}", query.getWbsId(), query.getContractId(), query.getClassify() , e);
+                    }
+                }
+                for (String queryId : queryIds) {
+                    redisTemplate.opsForList().remove("blade:statistics:information_query_statistics_key", 1, queryId);
+                }
+            }
+        }
+    }
+
+    /**
+     * 定时任务 每天四点执行
+     */
+    @Scheduled(cron = "0 0 4 * * ?")
+    public void scheduledSync() {
+        log.info("WbsTreeContractStatistics.scheduledSync 定时任务开始执行, 时间:" + LocalDateTime.now());
+        try {
+            wbsTreeContractStatisticsService.sync();
+        } catch (Exception e) {
+            log.error("WbsTreeContractStatistics.scheduledSync 定时任务执行报错, 原因:"+e.getMessage());
+        }
+        log.info("WbsTreeContractStatistics.scheduledSync 定时任务结束执行, 时间:" + LocalDateTime.now());
+    }
+
+    @Override
+    @Async
+    public void updateInformationQueryStatus(List<WbsTreeContractStatisticsDTO> wbsTreeContractStatisticsDTOs) {
+        if (wbsTreeContractStatisticsDTOs == null || wbsTreeContractStatisticsDTOs.isEmpty()) {
+            return;
+        }
+        for (WbsTreeContractStatisticsDTO dto : wbsTreeContractStatisticsDTOs) {
+            try {
+                wbsTreeContractStatisticsService.updateInformationNumber(dto.getPKeyId(), dto.getClassify(), dto.getContractId());
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    @Override
+    @Async
+    public void updateInformationQueryStatusByTaskId(String taskIds) {
+        if (taskIds != null && !taskIds.isEmpty()) {
+            String[] taskIdList = taskIds.split(",");
+            List<InformationQuery> queryList = jdbcTemplate.query("select wbs_id, classify, contract_id from u_information_query where id in (select form_data_id from u_task where  id in (?) and is_deleted = 0) and is_deleted = 0 group by contract_id,wbs_id,classify",
+                    new Object[]{String.join(",", taskIdList)}, new BeanPropertyRowMapper<>(InformationQuery.class));
+            if (!queryList.isEmpty()) {
+                for (InformationQuery query : queryList) {
+                    try {
+                        wbsTreeContractStatisticsService.updateInformationNumber(query.getWbsId(), query.getClassify(), query.getContractId());
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    @Async
+    public void updateWbsTreeContractNodes(String nodeIds) {
+        if (nodeIds != null && !nodeIds.isEmpty()) {
+            String[] pKeyIds = nodeIds.split(",");
+            for (String pKeyId : pKeyIds) {
+                try {
+                    wbsTreeContractStatisticsService.insertWbsTreeContractStatistics(Long.parseLong(pKeyId), 0);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    @Override
+    @Async
+    public void delWbsTreeContractNodes(String nodeIds) {
+        if (nodeIds != null && !nodeIds.isEmpty()) {
+            String[] pKeyIds = nodeIds.split(",");
+            for (String pKeyId : pKeyIds) {
+                try {
+                    wbsTreeContractStatisticsService.updateIsDeleted(Long.parseLong(pKeyId), 1);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    @Async
+    @Override
+    public void recycleWbsTreeContractNodes(String nodeIds) {
+        if (nodeIds != null && !nodeIds.isEmpty()) {
+            String[] pKeyIds = nodeIds.split(",");
+            for (String pKeyId : pKeyIds) {
+                try {
+                    wbsTreeContractStatisticsService.updateIsDeleted(Long.parseLong(pKeyId), 0);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    @Override
+    @Async
+    public void statisticsContract(Long contractId) {
+        wbsTreeContractStatisticsService.statisticsContract(contractId);
+    }
+}

+ 4 - 4
blade-service/blade-business/src/main/java/org/springblade/business/mapper/ArchiveFileMapper.xml

@@ -73,9 +73,9 @@
     <select id="selectArchiveFileCount" resultType="java.lang.Integer">
         select count(u.id) from u_archive_file u
         <if test="vo.nodeIds != null and vo.nodeIds != ''">
-            left join m_archive_tree_contract t on t.id = u.node_id
+            left join m_archive_tree_contract t on t.id = u.node_id and t.is_deleted= 0
             <if test="vo.extType != null">
-                LEFT JOIN m_archive_tree_contract m ON m.id = u.node_ext_id
+                LEFT JOIN m_archive_tree_contract m ON m.id = u.node_ext_id and m.is_deleted= 0
             </if>
         </if>
         where u.is_deleted = 0
@@ -158,9 +158,9 @@
     <select id="selectArchiveFilePage" resultMap="archiveFileResultMap">
         select u.* from u_archive_file u
         <if test="vo.nodeIds != null and vo.nodeIds != ''">
-            left join m_archive_tree_contract t on t.id = u.node_id
+            left join m_archive_tree_contract t on t.id = u.node_id and t.is_deleted= 0
             <if test="vo.extType != null">
-                LEFT JOIN m_archive_tree_contract m ON m.id = u.node_ext_id
+                LEFT JOIN m_archive_tree_contract m ON m.id = u.node_ext_id and m.is_deleted= 0
             </if>
         </if>
         where u.is_deleted = 0

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

@@ -198,8 +198,8 @@
         CASE (select count(tcf.id) from u_tree_contract_first AS tcf where tcf.is_deleted = 0 and tcf.wbs_node_id =
         wtc.p_key_id) WHEN 0 THEN 'false' ELSE 'true'
         END AS isFirst,
-        ( SELECT count(1) from m_wbs_tree_contract where id in(SELECT parent_id from m_wbs_tree_contract a where
-        a.is_deleted=0 and a.type=2 and table_owner in(1,2,3)) and contract_id=wtc.contract_id and type =1 and
+        ( SELECT count(1) from m_wbs_tree_contract where id in(SELECT DISTINCT parent_id from m_wbs_tree_contract a where
+        a.is_deleted=0 and a.type=2 and a.contract_id = #{contractId} and table_owner in(1,2,3)) and contract_id=wtc.contract_id and type =1 and
         is_deleted=0 and (FIND_IN_SET(wtc.id,ancestors) or wtc.p_key_id=p_key_id)
         ) as allCount,
         (SELECT count(1) from u_information_query b where b.wbs_id in(SELECT p_key_id from m_wbs_tree_contract a

+ 54 - 4
blade-service/blade-business/src/main/java/org/springblade/business/mapper/StandardInfoMapper.xml

@@ -71,7 +71,29 @@
     </select>
     <select id="findByParentId" resultType="org.springblade.business.entity.StandardInfo">
         select
-            <include refid="Base_Column_List"/>,concat(symbol,name) symbolName
+            case
+                when
+                    symbol = '~'
+                then
+                    SUBSTRING_INDEX(name, '~', 1)
+                else
+                    name
+            end `name`,
+            <include refid="Base_Column_List"/>,
+            case
+                when
+                    symbol = '~'
+                then
+                    SUBSTRING_INDEX(name, '~', -1)
+            end nameEnd,
+            case
+                when
+                    symbol = '~'
+                then
+                    name
+                else
+                    concat(symbol,name)
+            end symbolName
         FROM
             u_standard_info
         WHERE
@@ -110,7 +132,17 @@
 
     <select id="getConditionSet" resultMap="BaseResultConditionSet">
         select
-            <include refid="Base_Column_Join_List"/>, concat(a.symbol,a.name) symbolName,b.group_id
+            <include refid="Base_Column_Join_List"/>,
+            case
+                when
+                    a.symbol = '~'
+                then
+                    a.name
+                else
+                    concat(a.symbol,a.name)
+            end symbolName,
+
+            b.group_id
         from
             u_standard_info a
             INNER join u_standard_info p on a.parent_id = p.id and a.is_deleted = p.is_deleted
@@ -211,7 +243,16 @@
     </sql>
     <select id="getElementJoin" resultMap="BaseResultElementJoin">
         select
-            <include refid="Base_Column_Join_List"/>, concat(a.symbol,a.name) symbolName,b.group_id
+            <include refid="Base_Column_Join_List"/>,
+            case
+                when
+                    a.symbol = '~'
+                then
+                    a.name
+                else
+                    concat(a.symbol,a.name)
+            end symbolName,
+            b.group_id
         from
             u_standard_info a
             INNER JOIN u_standard_info c on a.parent_id = c.id and a.is_deleted = c.is_deleted
@@ -285,7 +326,16 @@
 
     <select id="effectPreview" resultMap="BaseResultElementJoin">
         SELECT
-            a.*, concat(a.symbol,a.name) symbolName,null group_id
+            a.*,
+            case
+                when
+                    a.symbol = '~'
+                then
+                    a.name
+                else
+                concat(a.symbol,a.name)
+            end symbolName,
+            null group_id
         FROM
             u_standard_info a
                 INNER JOIN u_standard_info_join b ON a.id = b.standard_info_left_id

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

@@ -0,0 +1,23 @@
+package org.springblade.business.mapper;
+
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
+import org.springblade.business.entity.WbsTreeContractStatistics;
+
+import java.util.Collection;
+
+public interface WbsTreeContractStatisticsMapper extends BaseMapper<WbsTreeContractStatistics> {
+
+    WbsTreeContractStatistics getByIdOnLock(Long id);
+
+    @Select("select id, project_id, contract_id, is_deleted, `status`, create_time,  update_time, parent_id, ancestors, leaf_num, fill_num, approve_num, complete_num, jl_fill_num, jl_approve_num, jl_complete_num, is_leaf from wbs_tree_contract_statistics where id = #{id}")
+    WbsTreeContractStatistics getByIdOnIgnoreDeleted(Long id);
+
+
+    @Update("update wbs_tree_contract_statistics set is_deleted = 0 where id = #{pKeyId}")
+    Boolean updateDeleteStatus(Long pKeyId);
+
+    Boolean updateLeafNum(Collection<Long> ids);
+}

+ 43 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/WbsTreeContractStatisticsMapper.xml

@@ -0,0 +1,43 @@
+<?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.business.mapper.WbsTreeContractStatisticsMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="ResultMap" type="org.springblade.business.entity.WbsTreeContractStatistics">
+        <result column="id" property="id"/>
+        <result column="project_id" property="projectId"/>
+        <result column="contract_id" property="contractId"/>
+        <result column="is_deleted" property="isDeleted"/>
+        <result column="status" property="status"/>
+        <result column="create_time" property="createTime"/>
+        <result column="update_time" property="updateTime"/>
+        <result column="parent_id" property="parentId"/>
+        <result column="ancestors" property="ancestors"/>
+        <result column="leaf_num" property="leafNum"/>
+        <result column="fill_num" property="fillNum"/>
+        <result column="is_leaf" property="isLeaf"/>
+        <result column="approve_num" property="approveNum"/>
+        <result column="complete_num" property="completeNum"/>
+        <result column="jl_fill_num" property="jlFillNum"/>
+        <result column="jl_approve_num" property="jlApproveNum"/>
+        <result column="jl_complete_num" property="jlCompleteNum"/>
+    </resultMap>
+    <sql id="includeSql">
+        id, project_id, contract_id, is_deleted, `status`, create_time,  update_time, parent_id, ancestors, leaf_num, fill_num, approve_num, complete_num, jl_fill_num, jl_approve_num, jl_complete_num, is_leaf
+    </sql>
+    <update id="updateLeafNum">
+        UPDATE m_wbs_tree_contract_statistics a INNER JOIN (
+                select  b.id, COUNT(c.id) AS leaf_num, sum(c.fill_num) as fill_num, sum(c.approve_num) as approve_num, sum(c.complete_num) as complete_num, sum(c.jl_fill_num) as jl_fill_num, sum(c.jl_approve_num) as jl_approve_num, sum(c.jl_complete_num) as jl_complete_num
+                FROM m_wbs_tree_contract_statistics b INNER JOIN m_wbs_tree_contract_statistics c  ON c.contract_id = b.contract_id AND c.is_leaf = 1 AND c.is_deleted = 0  AND c.status = 1 AND c.ancestors LIKE CONCAT(b.ancestors, ',', b.id, '%')
+                WHERE b.id IN (
+                    <foreach collection="ids" item="item" separator=",">
+                        #{item}
+                    </foreach>
+                    ) GROUP BY b.id
+            ) AS t ON a.id = t.id
+        SET a.leaf_num = t.leaf_num, a.fill_num = t.fill_num,a.approve_num = t.approve_num, a.complete_num = t.complete_num, a.jl_fill_num =t.jl_fill_num, a.jl_approve_num = t.jl_approve_num, a.jl_complete_num = t.jl_complete_num;
+    </update>
+    <select id="getByIdOnLock" resultMap="ResultMap">
+        select <include refid="includeSql"/> from m_wbs_tree_contract_statistics where id = #{id} for update
+    </select>
+</mapper>

+ 16 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/IWbsTreeContractStatisticsService.java

@@ -0,0 +1,16 @@
+package org.springblade.business.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import org.springblade.business.entity.WbsTreeContractStatistics;
+
+public interface IWbsTreeContractStatisticsService extends IService<WbsTreeContractStatistics> {
+
+    Boolean updateInformationNumber(Long wbsId, Integer classify, Long contractId);
+
+    Boolean insertWbsTreeContractStatistics(Long wbsTreeContractPkeyId, Integer isDelete);
+
+    Boolean updateIsDeleted(Long id, Integer isDeleted);
+    void statisticsContract(Long contractId);
+
+    void sync();
+}

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

@@ -177,10 +177,10 @@ public class ArchiveFileServiceImpl extends BaseServiceImpl<ArchiveFileMapper, A
                 }
             }
             //循环查看是否把需要审批改为不需要审批,  不可能把不需要审批改为需要审批 ,0不需要,1需要
-            if (vo.getStatus() == 0 && vo.getIsApproval() == 0) {
+            if (vo.getStatus() != null && vo.getStatus() == 0 && vo.getIsApproval() != null &&  vo.getIsApproval() == 0) {
                 vo.setStatus(2);
             }
-            if(vo.getIsApproval() == 1){
+            if(vo.getIsApproval() != null && vo.getIsApproval() == 1){
                 Set<String> aopParamsSet = new HashSet<>();
                 //判断现在的数据是否是待审批数据,只有上报状态、未认证状态的数据才能撤销
                 ArchiveFile archiveFile = jdbcTemplate.queryForObject("select * from u_archive_file where id = " + vo.getId(), new BeanPropertyRowMapper<>(ArchiveFile.class));

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

@@ -392,7 +392,7 @@ public class InformationQueryServiceImpl extends BaseServiceImpl<InformationQuer
             if(type>=3 || type<=0){
                 type = 1;
             }
-            if (DistributedRedisLock.acquire("saveOrUpdateInformationQueryData:" + primaryKeyId + ":" + contractTree.getContractId() + ":" + classify + ":" + type,5)) {
+            if (DistributedRedisLock.acquire("saveOrUpdateInformationQueryData:" + primaryKeyId + ":" + contractTree.getContractId() + ":" + classify + ":" + type,20)) {
                 try {
                     //判断当前填报节点下是否已经存在相应数据
                     InformationQuery oldData = this.baseMapper.getInformationQueryByWbsId(contractTree.getPKeyId(), classify,contractTree.getContractId());
@@ -1071,7 +1071,7 @@ public class InformationQueryServiceImpl extends BaseServiceImpl<InformationQuer
         List<InformationQuery> informationQueries = this.getBaseMapper().selectBatchIds(ids);
         if (informationQueries != null && !informationQueries.isEmpty()) {
             for (InformationQuery informationQuery : informationQueries) {
-                if (DistributedRedisLock.acquire("informationQueryLock_" + informationQuery.getWbsId() + "_" + informationQuery.getContractId() + "_" + informationQuery.getClassify() + "_" + informationQuery.getType(),5)) {
+                if (DistributedRedisLock.acquire("informationQueryLock_" + informationQuery.getWbsId() + "_" + informationQuery.getContractId() + "_" + informationQuery.getClassify() + "_" + informationQuery.getType(),20)) {
                     try {
                         List<InformationQuery> queryList = this.list(Wrappers.<InformationQuery>lambdaQuery().select(InformationQuery::getId, InformationQuery::getStatus)
                                 .eq(InformationQuery::getWbsId, informationQuery.getWbsId())

+ 8 - 35
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TaskServiceImpl.java

@@ -16,6 +16,7 @@ import org.springblade.archive.entity.ArchiveProjectConfig;
 import org.springblade.archive.feign.ArchiveAutoClient;
 import org.springblade.business.dto.*;
 import org.springblade.business.entity.*;
+import org.springblade.business.feignClient.WbsTreeContractStatisticsClientImpl;
 import org.springblade.business.mapper.TaskMapper;
 import org.springblade.business.mapper.TrialSelfInspectionRecordMapper;
 import org.springblade.business.service.*;
@@ -131,6 +132,7 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
     private final NewIOSSClient newIOSSClient;
     private final WbsTreePrivateClient wbsTreePrivateClient;
     private final TrialSelfInspectionRecordMapper trialSelfInspectionRecordMapper;
+    private final WbsTreeContractStatisticsClientImpl wbsTreeContractStatisticsClient;
     //超级管理员的角色id
     private final String SUPER_ADMIN_ROLE_ID ="1123598816738675201";
     //泓创智诚公司的部门id
@@ -138,12 +140,6 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
 
     @Autowired
     StringRedisTemplate RedisTemplate;
-    @Autowired
-    private BladeRedis bladeRedis;
-    //异步类
-    @Autowired
-    private TaskSync taskSync;
-
 
 
     private final ITrialSelfInspectionRecordService iTrialSelfInspectionRecordService;
@@ -766,6 +762,7 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                         }
                     }
                 }
+                wbsTreeContractStatisticsClient.updateInformationQueryStatusByTaskId(String.join(",", taskIds));
             }
         }
     }
@@ -1978,37 +1975,13 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
     }*/
         @Override
         public R reSigningEVisaStatus0(List<reSigningEVisaStatus> dtos, String header) throws Exception {
-         R result= new R();
          if(dtos.size()>0){
-
-             //添加缓存
              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);
+             //正在重刷的不允许再次重刷
+             informationQueryService.update(Wrappers.<InformationQuery>update().lambda()
+                     .set(InformationQuery::getSaveAgain, 0)
+                     .ne(InformationQuery::getSaveAgain, 1)
+                     .in(InformationQuery::getId, newIds));
         }
          return R.success("操作成功");
     }

+ 33 - 4
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/UStandardInfoServiceImpl.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.apache.commons.lang.math.NumberUtils;
 import org.springblade.business.dto.StandardInfoJoinDTO;
 import org.springblade.business.dto.StandardInfoPrivateJoinDTO;
 import org.springblade.business.dto.StandardInfoDTO;
@@ -81,6 +82,20 @@ public class UStandardInfoServiceImpl extends ServiceImpl<StandardInfoMapper, St
                 item.setParentId(uStandardInfo.getId());
                 item.setStandardId(uStandardInfo.getStandardId());
                 item.setCreateUser(user.getUserId());
+
+                //判断符号之后的数据是否为数字
+                if (StringUtils.isNotEmpty(item.getSymbol())) {
+                    if(item.getName().startsWith("+")){
+                        item.setName(item.getName().substring(1));
+                    }
+                    //如果是范围符号 则单独处理数据
+                    if(StringUtils.equals(item.getSymbol(),"~")){
+                        if(item.getNameEnd().startsWith("+")){
+                            item.setNameEnd(item.getNameEnd().substring(1));
+                        }
+                        item.setName(item.getName() + "~" + item.getNameEnd());
+                    }
+                }
             });
 
             //把父级对象转出来单独保存
@@ -92,7 +107,7 @@ public class UStandardInfoServiceImpl extends ServiceImpl<StandardInfoMapper, St
             return true;
         } catch (BeansException e) {
             e.printStackTrace();
-            throw new ServiceException("添加失败");
+            throw new ServiceException(e.getMessage());
         }
     }
 
@@ -116,6 +131,20 @@ public class UStandardInfoServiceImpl extends ServiceImpl<StandardInfoMapper, St
                     //更新的子集合 添加更新人
                     item.setUpdateUser(user.getUserId());
                 }
+
+                //判断符号之后的数据是否为数字
+                if (StringUtils.isNotEmpty(item.getSymbol())) {
+                    if(item.getName().startsWith("+")){
+                        item.setName(item.getName().substring(1));
+                    }
+                    //如果是范围符号 则单独处理数据
+                    if(StringUtils.equals(item.getSymbol(),"~")){
+                        if(item.getNameEnd().startsWith("+")){
+                            item.setNameEnd(item.getNameEnd().substring(1));
+                        }
+                        item.setName(item.getName() + "~" + item.getNameEnd());
+                    }
+                }
             });
             //更新父级对象
             StandardInfo parent = BeanUtil.copyProperties(uStandardInfo, StandardInfo.class);
@@ -125,7 +154,7 @@ public class UStandardInfoServiceImpl extends ServiceImpl<StandardInfoMapper, St
             return true;
         } catch (Exception e) {
             e.printStackTrace();
-            throw new ServiceException("更新失败");
+            throw new ServiceException(e.getMessage());
         }
     }
 
@@ -206,7 +235,7 @@ public class UStandardInfoServiceImpl extends ServiceImpl<StandardInfoMapper, St
                 Collections.sort(newRightIds);
 
                 String newRightIdsStr = String.join(",", newRightIds.stream().map(String::valueOf).collect(Collectors.toList()));
-                if(CollectionUtil.isNotEmpty(newRightIds)){
+                if (CollectionUtil.isNotEmpty(newRightIds)) {
                     //把左Id加进来 确保只有在左id相同的情况下才进行判断
                     newRightIdsStr = newRightIdsStr + "," + leftId;
                 }
@@ -356,7 +385,7 @@ public class UStandardInfoServiceImpl extends ServiceImpl<StandardInfoMapper, St
     @Override
     public List<StandardInfoPrivateJoinVO> effectPreview(String ids) {
         List<Long> collect = Arrays.stream(ids.split(",")).map(Long::parseLong).collect(Collectors.toList());
-        return baseMapper.effectPreview(collect,collect.size());
+        return baseMapper.effectPreview(collect, collect.size());
     }
 }
 

+ 643 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/WbsTreeContractStatisticsServiceImpl.java

@@ -0,0 +1,643 @@
+package org.springblade.business.service.impl;
+
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springblade.business.entity.InformationQuery;
+import org.springblade.business.entity.WbsTreeContractStatistics;
+import org.springblade.business.mapper.WbsTreeContractStatisticsMapper;
+import org.springblade.business.service.IWbsTreeContractStatisticsService;
+import org.springblade.core.tool.utils.BeanUtil;
+import org.springblade.core.tool.utils.ObjectUtil;
+import org.springblade.core.tool.utils.StringUtil;
+import org.springblade.manager.entity.ContractInfo;
+import org.springblade.manager.entity.WbsTreeContract;
+import org.springblade.manager.vo.WbsTreeContractLazyQueryInfoVO;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.support.TransactionTemplate;
+
+import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+
+
+@Service
+@AllArgsConstructor
+public class WbsTreeContractStatisticsServiceImpl extends ServiceImpl<WbsTreeContractStatisticsMapper, WbsTreeContractStatistics> implements IWbsTreeContractStatisticsService {
+
+    private final JdbcTemplate jdbcTemplate;
+    private final TransactionTemplate transactionTemplate;
+    private static final Logger log = LoggerFactory.getLogger(WbsTreeContractStatisticsServiceImpl.class);
+
+
+
+
+    @Override
+    public Boolean updateInformationNumber(Long wbsId, Integer classify, Long contractId) {
+        WbsTreeContract wbsTreeContract = getWbsTreeContractByPKeyId(wbsId);
+        if (wbsTreeContract == null || wbsTreeContract.getIsDeleted() == 1) {
+            return false;
+        }
+        InformationQuery query = getInformationQueryByWbsId(wbsId, classify, Long.parseLong(wbsTreeContract.getContractId()));
+        if (query == null || query.getStatus() == null) {
+            return false;
+        }
+        Integer status = query.getStatus();
+        WbsTreeContractStatistics contractStatistics = this.getById(wbsId);
+        if (contractStatistics == null) {
+            insertWbsTreeContractStatistics(wbsId, 0);
+        }
+        return transactionTemplate.execute(transactionStatus -> {
+            WbsTreeContractStatistics lock = this.baseMapper.getByIdOnLock(wbsId);
+            if (lock == null) {
+                return false;
+            }
+            String ancestors = lock.getAncestors();
+            if (ancestors == null || ancestors.isEmpty()) {
+                return false;
+            }
+            String[] ids = ancestors.split(",");
+            List<Long> collect = Arrays.stream(ids).filter(item -> !item.equals("0") && StringUtil.isNumeric(item)).map(Long::parseLong).collect(Collectors.toList());
+            if (classify == 1) {
+                // 施工
+                if (status == 0 || status == 3) {
+                    //  fill_num == 0 && approve_num == 0 && complete_num == 0 更新当前节点 set fill_num = 1, approve_num = 0, complete_num = 0  并更新父级节点 set fill_num = fill_num + 1
+                    //  fill_num == 1 && approve_num == 0 && complete_num == 0 不更新
+                    //  fill_num == 0 && approve_num == 1 && complete_num == 0 更新当前节点 set fill_num = 1, approve_num = 0, complete_num = 0  并更新父级节点 set fill_num = fill_num + 1, approve_num = approve_num - 1
+                    //  fill_num == 0 && approve_num == 0 && complete_num == 1 更新当前节点 set fill_num = 1, approve_num = 0, complete_num = 0 并更新父级节点 set fill_num = fill_num + 1, complete_num = complete_num - 1
+                    this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().eq(WbsTreeContractStatistics::getId, wbsId)
+                            .set(WbsTreeContractStatistics::getFillNum, 1).set(WbsTreeContractStatistics::getApproveNum, 0).set(WbsTreeContractStatistics::getCompleteNum, 0));
+                    if (lock.getFillNum() == 0 && lock.getApproveNum() == 0 && lock.getCompleteNum() == 0) {
+                        this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().in(WbsTreeContractStatistics::getId, collect).setSql("fill_num = fill_num + 1"));
+                    } else if (lock.getFillNum() == 0 && lock.getApproveNum() == 1 && lock.getCompleteNum() == 0) {
+                        this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().in(WbsTreeContractStatistics::getId, collect).setSql("fill_num = fill_num + 1, approve_num = approve_num - 1"));
+                    } else if (lock.getFillNum() == 0 && lock.getApproveNum() == 0 && lock.getCompleteNum() == 1) {
+                        this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().in(WbsTreeContractStatistics::getId, collect).setSql("fill_num = fill_num + 1, complete_num = complete_num - 1"));
+                    }
+                } else if (status == 1) {
+                    this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().eq(WbsTreeContractStatistics::getId, wbsId)
+                            .set(WbsTreeContractStatistics::getFillNum, 0).set(WbsTreeContractStatistics::getApproveNum, 1).set(WbsTreeContractStatistics::getCompleteNum, 0));
+                    if (lock.getFillNum() == 0 && lock.getApproveNum() == 0 && lock.getCompleteNum() == 0) {
+                        this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().in(WbsTreeContractStatistics::getId, collect).setSql("approve_num = approve_num + 1"));
+                    } else if (lock.getFillNum() == 1 && lock.getApproveNum() == 0 && lock.getCompleteNum() == 0) {
+                        this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().in(WbsTreeContractStatistics::getId, collect).setSql("fill_num = fill_num - 1, approve_num = approve_num + 1"));
+                    } else if (lock.getFillNum() == 0 && lock.getApproveNum() == 0 && lock.getCompleteNum() == 1) {
+                        this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().in(WbsTreeContractStatistics::getId, collect).setSql("fill_num = fill_num + 1, complete_num = complete_num - 1"));
+                    }
+                } else if (status == 2) {
+                    this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().eq(WbsTreeContractStatistics::getId, wbsId)
+                            .set(WbsTreeContractStatistics::getFillNum, 0).set(WbsTreeContractStatistics::getApproveNum, 0).set(WbsTreeContractStatistics::getCompleteNum, 1));
+                    if (lock.getFillNum() == 0 && lock.getApproveNum() == 0 && lock.getCompleteNum() == 0) {
+                        this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().in(WbsTreeContractStatistics::getId, collect).setSql("complete_num = complete_num + 1"));
+                    } else if (lock.getFillNum() == 1 && lock.getApproveNum() == 0 && lock.getCompleteNum() == 0) {
+                        this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().in(WbsTreeContractStatistics::getId, collect).setSql("fill_num = fill_num - 1, complete_num = complete_num + 1"));
+                    } else if (lock.getFillNum() == 0 && lock.getApproveNum() == 1 && lock.getCompleteNum() == 0) {
+                        this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().in(WbsTreeContractStatistics::getId, collect).setSql("approve_num = approve_num - 1, complete_num = complete_num + 1"));
+                    }
+                }
+            } else if (classify == 2) {
+                // 监理
+                if (status == 0 || status == 3) {
+                    this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().eq(WbsTreeContractStatistics::getId, wbsId)
+                            .set(WbsTreeContractStatistics::getJlFillNum, 1).set(WbsTreeContractStatistics::getJlApproveNum, 0).set(WbsTreeContractStatistics::getJlCompleteNum, 0));
+                    if (lock.getJlFillNum() == 0 && lock.getJlApproveNum() == 0 && lock.getJlCompleteNum() == 0) {
+                        this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().in(WbsTreeContractStatistics::getId, collect).setSql("jl_fill_num = jl_fill_num + 1"));
+                    } else if (lock.getJlFillNum() == 0 && lock.getJlApproveNum() == 1 && lock.getJlCompleteNum() == 0) {
+                        this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().in(WbsTreeContractStatistics::getId, collect).setSql("jl_fill_num = jl_fill_num + 1, jl_approve_num = jl_approve_num - 1"));
+                    } else if (lock.getJlFillNum() == 0 && lock.getJlApproveNum() == 0 && lock.getJlCompleteNum() == 1) {
+                        this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().in(WbsTreeContractStatistics::getId, collect).setSql("jl_fill_num = jl_fill_num + 1, jl_complete_num = jl_complete_num - 1"));
+                    }
+                } else if (status == 1) {
+                    this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().eq(WbsTreeContractStatistics::getId, wbsId)
+                            .set(WbsTreeContractStatistics::getJlFillNum, 0).set(WbsTreeContractStatistics::getJlApproveNum, 1).set(WbsTreeContractStatistics::getJlCompleteNum, 0));
+                    if (lock.getJlFillNum() == 0 && lock.getJlApproveNum() == 0 && lock.getJlCompleteNum() == 0) {
+                        this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().in(WbsTreeContractStatistics::getId, collect).setSql("jl_approve_num = jl_approve_num + 1"));
+                    } else if (lock.getJlFillNum() == 1 && lock.getJlApproveNum() == 0 && lock.getJlCompleteNum() == 0) {
+                        this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().in(WbsTreeContractStatistics::getId, collect).setSql("jl_fill_num = jl_fill_num - 1, jl_approve_num = jl_approve_num + 1"));
+                    } else if (lock.getJlFillNum() == 0 && lock.getJlApproveNum() == 0 && lock.getJlCompleteNum() == 1) {
+                        this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().in(WbsTreeContractStatistics::getId, collect).setSql("jl_approve_num = jl_approve_num - 1, jl_complete_num = jl_complete_num + 1"));
+                    }
+                } else if (status == 2) {
+                    this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().eq(WbsTreeContractStatistics::getId, wbsId)
+                            .set(WbsTreeContractStatistics::getJlFillNum, 0).set(WbsTreeContractStatistics::getJlApproveNum, 0).set(WbsTreeContractStatistics::getJlCompleteNum, 1));
+                    if (lock.getJlFillNum() == 0 && lock.getJlApproveNum() == 0 && lock.getJlCompleteNum() == 0) {
+                        this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().in(WbsTreeContractStatistics::getId, collect).setSql("jl_complete_num = jl_complete_num + 1"));
+                    } else if (lock.getJlFillNum() == 1 && lock.getJlApproveNum() == 0 && lock.getJlCompleteNum() == 0) {
+                        this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().in(WbsTreeContractStatistics::getId, collect).setSql("jl_fill_num = jl_fill_num - 1, jl_complete_num = jl_complete_num + 1"));
+                    } else if (lock.getJlFillNum() == 0 && lock.getJlApproveNum() == 1 && lock.getJlCompleteNum() == 0) {
+                        this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().in(WbsTreeContractStatistics::getId, collect).setSql("jl_approve_num = jl_approve_num - 1, jl_complete_num = jl_complete_num + 1"));
+                    }
+                }
+            }
+            return true;
+        });
+    }
+    @Override
+    public Boolean insertWbsTreeContractStatistics(Long wbsTreeContractPkeyId, Integer isDelete) {
+        if (isDelete == 1) {
+            return this.updateIsDeleted(wbsTreeContractPkeyId, isDelete);
+        }
+        WbsTreeContract wbsTreeContract = getWbsTreeContractByPKeyId(wbsTreeContractPkeyId);
+        if (wbsTreeContract == null || wbsTreeContract.getIsDeleted() != 0 || wbsTreeContract.getStatus() != 1 || wbsTreeContract.getType() != 1) {
+            return false;
+        }
+        WbsTreeContractStatistics wbsTreeContractStatistics = this.getById(wbsTreeContractPkeyId);
+        if (wbsTreeContractStatistics != null) {
+            return true;
+        }
+        wbsTreeContractStatistics = createWbsTreeContractStatistics(wbsTreeContract);
+        // 查询父级节点存不存在,不存在则创建
+        List<WbsTreeContractStatistics> parentList = new ArrayList<>();
+        createWbsTreeContractStatisticsParent(wbsTreeContract, wbsTreeContractStatistics, parentList);
+        if (!parentList.isEmpty()) {
+            for (int i = 1; i < parentList.size(); i++) {
+                WbsTreeContractStatistics statistics = parentList.get(i);
+                WbsTreeContractStatistics parent = parentList.get(i - 1);
+                if (parent != null && StringUtil.hasText(parent.getAncestors())) {
+                    statistics.setAncestors(parent.getAncestors() + "," + parent.getId());
+                    statistics.setParentId(parent.getId());
+                }
+            }
+        }
+        // 查询有没有子节点,子节点是否存在
+        createWbsTreeContractStatisticsChildren(wbsTreeContract, wbsTreeContractStatistics, parentList);
+        parentList.add(wbsTreeContractStatistics);
+        saveBatch(parentList);
+        Set<Long> ancestors = new HashSet<>();
+        for (WbsTreeContractStatistics statistics : parentList) {
+            if (statistics.getAncestors() != null) {
+                String[] split = statistics.getAncestors().split(",");
+                for (String s : split) {
+                    if (!StringUtil.isNumeric(s) && s.equals("0")) {
+                        continue;
+                    }
+                    ancestors.add(Long.parseLong(s));
+                }
+            }
+        }
+        if (!ancestors.isEmpty()) {
+            this.baseMapper.updateLeafNum(ancestors);
+        }
+        return true;
+    }
+
+    @Override
+    public Boolean updateIsDeleted(Long id, Integer isDeleted) {
+        if (isDeleted == null || isDeleted == 0) {
+            // 恢复
+            WbsTreeContractStatistics statistics = this.baseMapper.getByIdOnIgnoreDeleted(id);
+            if (statistics == null) {
+                return insertWbsTreeContractStatistics(id, 0);
+            }
+            return transactionTemplate.execute(status -> {
+                this.baseMapper.updateDeleteStatus(id);
+                if (statistics.getIsLeaf() == 1) {
+                    this.updateLeafNum(statistics.getAncestors());
+                }
+                return true;
+            });
+        } else {
+            // 删除
+            WbsTreeContractStatistics statistics = this.getById(id);
+            if (statistics != null) {
+                // 删除当前节点及其子节点
+                List<WbsTreeContractStatistics> list = this.list(Wrappers.<WbsTreeContractStatistics>lambdaQuery().eq(WbsTreeContractStatistics::getContractId, statistics.getContractId())
+                        .likeRight(WbsTreeContractStatistics::getAncestors, statistics.getAncestors() + "," + statistics.getId()));
+                list.add( statistics);
+                Set<Long> ids = list.stream().map(WbsTreeContractStatistics::getId).collect(Collectors.toSet());
+                return transactionTemplate.execute( status -> {
+                    this.update(Wrappers.<WbsTreeContractStatistics>lambdaUpdate().set(WbsTreeContractStatistics::getIsDeleted, 1).in(WbsTreeContractStatistics::getId, ids));
+                    // 2 更新父节点的子节点数
+                    return updateLeafNum(statistics.getAncestors());
+                });
+            }
+        }
+        return true;
+    }
+
+    public Boolean updateLeafNum(String ids) {
+        if (ids != null && !ids.isEmpty()) {
+            String[] split = ids.split(",");
+            Set<Long> ids1 = Arrays.stream(split).filter(StringUtil::isNumeric).map(Long::parseLong).filter(id -> id > 0).collect(Collectors.toSet());
+            return this.baseMapper.updateLeafNum(ids1);
+        }
+        return true;
+    }
+
+    public void createWbsTreeContractStatisticsParent(WbsTreeContract wbsTreeContract, WbsTreeContractStatistics wbsTreeContractStatistics, List<WbsTreeContractStatistics> wbsTreeContractStatisticsList) {
+        if (wbsTreeContract.getParentId() == null || wbsTreeContract.getParentId() <= 0) {
+            wbsTreeContractStatistics.setParentId(0L);
+            wbsTreeContractStatistics.setAncestors("");
+            return;
+        }
+        WbsTreeContractStatistics parent = this.getById(wbsTreeContractStatistics.getParentId());
+        if (parent == null) {
+            WbsTreeContract wbsTreeContractParent = getWbsTreeContractByPKeyId(wbsTreeContractStatistics.getParentId());
+            if (wbsTreeContractParent == null || wbsTreeContractParent.getIsDeleted() != 0 || wbsTreeContractParent.getStatus() != 1) {
+                return;
+            }
+            parent = createWbsTreeContractStatistics(wbsTreeContractParent);
+            createWbsTreeContractStatisticsParent(wbsTreeContractParent, parent, wbsTreeContractStatisticsList);
+            wbsTreeContractStatisticsList.add(parent);
+        } else {
+            if (StringUtil.hasText(wbsTreeContract.getAncestors())) {
+                wbsTreeContractStatistics.setParentId(parent.getId());
+                wbsTreeContractStatistics.setAncestors(parent.getAncestors() + "," + parent.getId());
+            }
+        }
+    }
+
+    public void createWbsTreeContractStatisticsChildren(WbsTreeContract wbsTreeContract, WbsTreeContractStatistics wbsTreeContractStatistics, List<WbsTreeContractStatistics> wbsTreeContractStatisticsList) {
+        List<WbsTreeContract> wbsTreeContracts =  jdbcTemplate.query("select * from m_wbs_tree_contract where is_deleted = 0 and type = 1 and contract_id = ? and p_id = ?",
+                new Object[]{wbsTreeContract.getContractId(), wbsTreeContract.getPKeyId()}, new BeanPropertyRowMapper<>(WbsTreeContract.class));
+        if (wbsTreeContracts == null || wbsTreeContracts.isEmpty()) {
+            wbsTreeContractStatistics.setIsLeaf(1);
+            wbsTreeContractStatistics.setLeafNum(0);
+            return;
+        }
+        wbsTreeContracts.forEach(item -> {
+            WbsTreeContractStatistics statistics = createWbsTreeContractStatistics(item);
+            createWbsTreeContractStatisticsChildren(item, wbsTreeContractStatistics, wbsTreeContractStatisticsList);
+            statistics.setAncestors(wbsTreeContractStatistics.getAncestors() + "," + wbsTreeContractStatistics.getId());
+            statistics.setParentId(wbsTreeContractStatistics.getId());
+            wbsTreeContractStatisticsList.add(statistics);
+            int num = wbsTreeContractStatistics.getLeafNum() == null ? 0 : wbsTreeContractStatistics.getLeafNum();
+            int i = statistics.getLeafNum() == 0 ? 1 : statistics.getLeafNum();
+            wbsTreeContractStatistics.setLeafNum(num + i);
+        });
+    }
+
+    /**
+     * 同步
+     */
+    public void sync() {
+        List<ContractInfo> contractInfos = jdbcTemplate.query("select id from m_contract_info where is_deleted = 0 and p_id in (select id from m_project_info where is_deleted = 0)", new BeanPropertyRowMapper<>(ContractInfo.class));
+        if (contractInfos.isEmpty()) {
+            return;
+        }
+        for (ContractInfo contractInfo : contractInfos) {
+            statisticsContract(contractInfo.getId());
+        }
+    }
+
+    @Override
+    public void statisticsContract(Long contractId) {
+        try {
+            List<WbsTreeContract> wbsTreeContracts =  jdbcTemplate.query("select * from m_wbs_tree_contract where is_deleted = 0 and type = 1 and status = 1 and contract_id = ? ",
+                    new Object[]{contractId}, new BeanPropertyRowMapper<>(WbsTreeContract.class));
+
+            List<WbsTreeContractStatistics> addWbsTreeContractStatistics = new ArrayList<>(wbsTreeContracts.size());
+            {
+                List<WbsTreeContractDto> contractDtoList = chickTreeAncestors(wbsTreeContracts);
+                for (WbsTreeContractDto dto : contractDtoList) {
+                    addWbsTreeContractStatistics.add(createWbsTreeContractStatistics(dto));
+                }
+            }
+            // 统计叶子节点数量
+//            countLeafNum(addWbsTreeContractStatistics);
+            useIsLeafFieldCountLeafNum(addWbsTreeContractStatistics);
+            countInformationNumber(addWbsTreeContractStatistics, contractId);
+            List<WbsTreeContractStatistics> updateWbsTreeContractStatistics = new ArrayList<>();
+            List<WbsTreeContractStatistics> wbsTreeContractStatistics = this.list(Wrappers.<WbsTreeContractStatistics>lambdaQuery().eq(WbsTreeContractStatistics::getContractId, contractId).eq(WbsTreeContractStatistics::getIsDeleted, 0));
+            Map<Long, WbsTreeContractStatistics> map = wbsTreeContractStatistics.stream().collect(Collectors.toMap(WbsTreeContractStatistics::getId, v -> v));
+            addWbsTreeContractStatistics.removeIf(item -> {
+                WbsTreeContractStatistics statistics = map.get(item.getId());
+                if (statistics == null) {
+                    return false;
+                }
+                if (updateWbsTreeContractStatisticsFields(statistics, item)) {
+                    updateWbsTreeContractStatistics.add(item);
+                }
+                return true;
+            });
+            if (!addWbsTreeContractStatistics.isEmpty()) {
+                saveBatch(addWbsTreeContractStatistics);
+            }
+            if (!updateWbsTreeContractStatistics.isEmpty()) {
+                updateBatchById(updateWbsTreeContractStatistics);
+            }
+        } catch (Exception e) {
+            log.error("更新合同段wbs树统计信息异常", e);
+        }
+    }
+
+    private boolean updateWbsTreeContractStatisticsFields(WbsTreeContractStatistics old, WbsTreeContractStatistics newObj) {
+        boolean result = false;
+        if (ObjectUtil.nullSafeEquals(old.getParentId(), newObj.getParentId())) {
+            newObj.setParentId(null);
+        } else {
+            result = true;
+        }
+        if (ObjectUtil.nullSafeEquals(old.getAncestors(), newObj.getAncestors())) {
+            newObj.setAncestors(null);
+        } else {
+            result = true;
+        }
+        if (ObjectUtil.nullSafeEquals(old.getIsLeaf(), newObj.getIsLeaf())) {
+            newObj.setIsLeaf(null);
+        } else {
+            result = true;
+        }
+        if (ObjectUtil.nullSafeEquals(old.getLeafNum(), newObj.getLeafNum())) {
+            newObj.setLeafNum(null);
+        } else {
+            result = true;
+        }
+        if (ObjectUtil.nullSafeEquals(old.getFillNum(), newObj.getFillNum())) {
+            newObj.setFillNum(null);
+        } else {
+            result = true;
+        }
+        if (ObjectUtil.nullSafeEquals(old.getApproveNum(), newObj.getApproveNum())) {
+            newObj.setApproveNum(null);
+        } else {
+            result = true;
+        }
+        if (ObjectUtil.nullSafeEquals(old.getCompleteNum(), newObj.getCompleteNum())) {
+            newObj.setCompleteNum(null);
+        } else {
+            result = true;
+        }
+        if (ObjectUtil.nullSafeEquals(old.getJlFillNum(), newObj.getJlFillNum())) {
+            newObj.setJlFillNum(null);
+        } else {
+            result = true;
+        }
+        if (ObjectUtil.nullSafeEquals(old.getJlApproveNum(), newObj.getJlApproveNum())) {
+            newObj.setJlApproveNum(null);
+        } else {
+            result = true;
+        }
+        if (ObjectUtil.nullSafeEquals(old.getJlCompleteNum(), newObj.getJlCompleteNum())) {
+            newObj.setJlCompleteNum(null);
+        } else {
+            result = true;
+        }
+        newObj.setStatus(null);
+        newObj.setIsDeleted(null);
+        newObj.setCreateTime(null);
+        newObj.setUpdateTime(null);
+        newObj.setProjectId( null);
+        newObj.setContractId( null);
+        return result;
+    }
+    private void countInformationNumber(List<WbsTreeContractStatistics> wbsTreeContractStatistics, Long contractId) {
+        if (wbsTreeContractStatistics == null || wbsTreeContractStatistics.isEmpty()) {
+            return;
+        }
+        // 统计已填报,待审批,已审批数量
+        List<WbsTreeContractLazyQueryInfoVO> sgQueryInfoList = 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 is_deleted = 0 AND type = 1 AND contract_id = ? AND classify = ? GROUP BY wbs_id) as a)",
+                    new Object[]{contractId, 1},
+                    new BeanPropertyRowMapper<>(WbsTreeContractLazyQueryInfoVO.class));
+        List<WbsTreeContractLazyQueryInfoVO> jlQueryInfoList = 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 is_deleted = 0 AND type = 1 AND contract_id = ? AND classify = ? GROUP BY wbs_id) as a)",
+                new Object[]{contractId, 2},
+                new BeanPropertyRowMapper<>(WbsTreeContractLazyQueryInfoVO.class));
+        if (sgQueryInfoList.isEmpty() && jlQueryInfoList.isEmpty()) {
+            return;
+        }
+        Map<Long, WbsTreeContractStatistics> map = wbsTreeContractStatistics.stream().collect(Collectors.toMap(WbsTreeContractStatistics::getId, item -> item, (k1, k2) -> k1));
+        Map<Long, Map<Integer, AtomicInteger>> sgStatisticsMap = countInformation(sgQueryInfoList, map);
+        Map<Long, Map<Integer, AtomicInteger>> jlStatisticsMap = countInformation(jlQueryInfoList, map);
+        wbsTreeContractStatistics.forEach(item -> {
+            Map<Integer, AtomicInteger> sgStatusMap = sgStatisticsMap.get(item.getId());
+            if (sgStatusMap != null && !sgStatusMap.isEmpty()) {
+                AtomicInteger integer = sgStatusMap.get(0);
+                if (integer != null) {
+                    item.setFillNum(integer.get());
+                }
+                integer = sgStatusMap.get(1);
+                if (integer != null) {
+                    item.setApproveNum(integer.get());
+                }
+                integer = sgStatusMap.get(2);
+                if (integer != null) {
+                    item.setCompleteNum(integer.get());
+                }
+            }
+            Map<Integer, AtomicInteger> jlStatusMap = jlStatisticsMap.get(item.getId());
+            if (jlStatusMap != null && !jlStatusMap.isEmpty()) {
+                AtomicInteger integer = jlStatusMap.get(0);
+                if (integer != null) {
+                    item.setJlFillNum(integer.get());
+                }
+                integer = jlStatusMap.get(1);
+                if (integer != null) {
+                    item.setJlApproveNum(integer.get());
+                }
+                integer = jlStatusMap.get(2);
+                if (integer != null) {
+                    item.setJlCompleteNum(integer.get());
+                }
+            }
+        });
+    }
+
+    private static Map<Long, Map<Integer, AtomicInteger>> countInformation(List<WbsTreeContractLazyQueryInfoVO> queryInfoList, Map<Long, WbsTreeContractStatistics> map) {
+        if (queryInfoList == null || queryInfoList.isEmpty()) {
+            return new HashMap<>();
+        }
+        Map<Long, Map<Integer, AtomicInteger>> statisticsMap = new HashMap<>();
+        Map<Long, Integer> sgStatusMap = queryInfoList.stream().peek(item -> {
+            if (item.getStatus() == null || item.getStatus() == 3) {
+                item.setStatus(0);
+            }
+        }).collect(Collectors.toMap(WbsTreeContractLazyQueryInfoVO::getWbsId, WbsTreeContractLazyQueryInfoVO::getStatus));
+        sgStatusMap.forEach((wbsId, status) -> {
+            put(wbsId, status, statisticsMap);
+            WbsTreeContractStatistics statistics = map.get(wbsId);
+            if (statistics == null || statistics.getAncestors() == null || statistics.getAncestors().isEmpty()) {
+                return;
+            }
+            String[] split = statistics.getAncestors().split(",");
+            for (String s : split) {
+                if (!StringUtil.isNumeric(s)) {
+                    continue;
+                }
+                Long id = Long.parseLong(s);
+                put(id, status, statisticsMap);
+            }
+        });
+        return statisticsMap;
+    }
+
+    private static void put(Long wbsId, Integer status, Map<Long, Map<Integer, AtomicInteger>> statisticsMap) {
+        Map<Integer, AtomicInteger> map = statisticsMap.get(wbsId);
+        if (map == null) {
+            map = new HashMap<>();
+        }
+        AtomicInteger count = map.get(status);
+        if (count == null) {
+            count = new AtomicInteger(0);
+        }
+        count.incrementAndGet();
+        map.put(status, count);
+        statisticsMap.put(wbsId, map);
+    }
+
+    /**
+     * 统计叶子节点数量 - 全量
+     */
+    public void countLeafNum(List<WbsTreeContractStatistics> wbsTreeContractStatistics) {
+        Map<Long, List<WbsTreeContractStatistics>> map = wbsTreeContractStatistics.stream().peek(item -> {
+            if (item.getParentId() == null) {
+                item.setParentId(0L);
+            }
+        }).collect(Collectors.groupingBy(WbsTreeContractStatistics::getParentId));
+        List<WbsTreeContractStatistics> list = map.get(0L);
+        if (list != null && !list.isEmpty()) {
+            list.forEach(item -> item.setLeafNum(countLeafNum(map.get(item.getId()), map)));
+        }
+    }
+    public Integer countLeafNum(List<WbsTreeContractStatistics> wbsTreeContracts, Map<Long, List<WbsTreeContractStatistics>> map) {
+        if (wbsTreeContracts == null || wbsTreeContracts.isEmpty()) {
+            return 0;
+        }
+        wbsTreeContracts.forEach(item -> item.setLeafNum(countLeafNum(map.get(item.getId()), map)));
+        return wbsTreeContracts.stream().mapToInt(item -> item.getLeafNum() == null || item.getLeafNum() == 0 ? 1 :item.getLeafNum()).sum();
+    }
+    /**
+     * 统计叶子节点数量 - 全量
+     */
+    public void useIsLeafFieldCountLeafNum(List<WbsTreeContractStatistics> wbsTreeContractStatistics) {
+        Map<Long, AtomicInteger> countMap = new HashMap<>();
+        Map<Long, WbsTreeContractStatistics> map = wbsTreeContractStatistics.stream().peek(item -> {
+            if (item.getIsLeaf() != null && item.getIsLeaf() == 1 && StringUtil.hasText(item.getAncestors())) {
+                String[] split = item.getAncestors().split(",");
+                for (String s : split) {
+                    if (s != null && !s.isEmpty()) {
+                        long id = Long.parseLong(s);
+                        if (id == 0) continue;
+                        AtomicInteger num = countMap.get(id);
+                        if (num == null) {
+                            num = new AtomicInteger(0);
+                        }
+                        num.incrementAndGet();
+                        countMap.put(id, num);
+                    }
+                }
+            }
+        }).collect(Collectors.toMap(WbsTreeContractStatistics::getId, item -> item, (k1, k2) -> k1));
+        countMap.forEach((k, v) -> {
+            WbsTreeContractStatistics statistics = map.get(k);
+            if (statistics != null) {
+                statistics.setLeafNum(v.get());
+            }
+        });
+    }
+
+    private  List<WbsTreeContractDto> chickTreeAncestors(List<WbsTreeContract> wbsTreeContracts) {
+        if (wbsTreeContracts == null || wbsTreeContracts.isEmpty()) {
+            return new ArrayList<>();
+        }
+        List<WbsTreeContractDto> contractNodes = wbsTreeContracts.stream().map(item -> BeanUtil.copyProperties(item, WbsTreeContractDto.class)).collect(Collectors.toList());
+        {
+            Map<Long, List<WbsTreeContractDto>> mapByParentId = contractNodes.stream().peek(item -> {
+                if (item.getParentId() == null) {
+                    item.setParentId(0L);
+                }
+                if (item.getPId() == null) {
+                    item.setPId(0L);
+                }
+            }).collect(Collectors.groupingBy(WbsTreeContractDto::getParentId));
+            List<WbsTreeContractDto> list = mapByParentId.get(0L);
+            list.forEach(item -> item.setAncestorsByParentId("0"));
+            Queue<WbsTreeContractDto> queue = new LinkedList<>(list);
+            while (!queue.isEmpty()) {
+                WbsTreeContractDto poll = queue.poll();
+                List<WbsTreeContractDto> children = mapByParentId.get(poll.getId());
+                if (children != null && !children.isEmpty()) {
+                    for (WbsTreeContractDto child : children) {
+                        child.setAncestorsByParentId(poll.getAncestorsByParentId() + "," + poll.getPKeyId());
+                        child.setTempPId(poll.getPKeyId());
+                        queue.offer(child);
+                    }
+                } else {
+                    poll.setIsLeaf(1);
+                }
+            }
+        }
+//        {
+//            Map<Long, List<WbsTreeContractDto>> mapByParentId = contractNodes.stream().collect(Collectors.groupingBy(WbsTreeContractDto::getPId));
+//            List<WbsTreeContractDto> list = mapByParentId.get(0L);
+//            list.forEach(item -> item.setAncestorsByPid("0"));
+//            Queue<WbsTreeContractDto> queue = new LinkedList<>(list);
+//            while (!queue.isEmpty()) {
+//                WbsTreeContractDto poll = queue.poll();
+//                List<WbsTreeContractDto> children = mapByParentId.get(poll.getPKeyId());
+//                if (children != null && !children.isEmpty()) {
+//                    for (WbsTreeContractDto child : children) {
+//                        child.setAncestorsByPid(poll.getAncestorsByPid() + "," + poll.getPKeyId());
+//                        queue.offer(child);
+//                    }
+//                }else {
+//                    poll.setIsLeaf(1);
+//                }
+//            }
+//        }
+//        for (WbsTreeContractDto node : contractNodes) {
+//            if (!StringUtil.equals(node.getAncestorsByParentId(), node.getAncestorsByPid())) {
+//                log.error("数据错误:" + node);
+//            } else if (!StringUtil.equals(node.getAncestorsByParentId(), node.getAncestors())){
+//                log.error("数据错误:" + node + " ancestorsPid=" + node.getAncestorsPId());
+//            }
+//        }
+        return contractNodes;
+    }
+
+    private WbsTreeContract getWbsTreeContractByPKeyId(Long pKeyId) {
+        List<WbsTreeContract> query = jdbcTemplate.query("select * from m_wbs_tree_contract where p_key_id = ?", new Object[]{pKeyId}, new BeanPropertyRowMapper<>(WbsTreeContract.class));
+        if (!query.isEmpty()) {
+            return query.get(0);
+        }
+        return null;
+    }
+
+    private WbsTreeContractStatistics createWbsTreeContractStatistics(WbsTreeContract wbsTreeContract) {
+        return new WbsTreeContractStatistics(wbsTreeContract.getPKeyId(), wbsTreeContract.getProjectId(), wbsTreeContract.getContractId(), wbsTreeContract.getPId(), wbsTreeContract.getAncestorsPId());
+    }
+    private WbsTreeContractStatistics createWbsTreeContractStatistics(WbsTreeContractDto wbsTreeContract) {
+        return new WbsTreeContractStatistics(wbsTreeContract.getPKeyId(), wbsTreeContract.getProjectId(), wbsTreeContract.getContractId(), wbsTreeContract.getTempPId(), wbsTreeContract.getAncestorsByParentId(), wbsTreeContract.getIsLeaf());
+    }
+
+    private InformationQuery getInformationQueryByWbsId(Long wbsId, Integer classify, Long contractId) {
+        List<InformationQuery> queryList = jdbcTemplate.query(
+                "SELECT wbs_id, classify, `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 = ? and wbs_id = ?) as a)",
+                new Object[]{contractId, classify, wbsId},
+                new BeanPropertyRowMapper<>(InformationQuery.class));
+        if (!queryList.isEmpty()) {
+            return queryList.get(0);
+        }
+        return null;
+    }
+
+    @Data
+    private static class WbsTreeContractDto extends WbsTreeContract {
+        private List<WbsTreeContractDto> children;
+        private String ancestorsByParentId;
+        private String ancestorsByPid;
+        private Long tempPId;
+        // 1 是叶子节点, 0 不是叶子节点
+        private Integer isLeaf = 0;
+
+        @Override
+        public String toString() {
+            return "WbsTreeContractDto{" +
+                    "pKeyId=" + super.getPKeyId() +
+                    ", pId=" + super.getPId() +
+                    ", parentId=" + super.getParentId() +
+                    ", id=" + super.getId() +
+                    ", ancestorsByParentId='" + ancestorsByParentId + '\'' +
+                    ", ancestorsByPid='" + ancestorsByPid + '\'' +
+                    '}';
+        }
+    }
+
+}

+ 133 - 25
blade-service/blade-business/src/main/java/org/springblade/business/sync/TaskSync.java

@@ -1,58 +1,166 @@
 package org.springblade.business.sync;
 
+import cn.hutool.core.date.DateTime;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.google.common.collect.Lists;
 import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
 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.common.utils.SystemUtils;
+import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.redis.cache.BladeRedis;
 import org.springblade.core.tool.api.R;
+import org.springblade.manager.entity.WbsTreeSynchronousRecord;
 import org.springblade.manager.feign.ExcelTabClient;
+import org.springblade.system.user.feign.IUserClient;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Component;
 
+import javax.annotation.Resource;
+import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.stream.Collectors;
 
 /**
  * @author LHB
  */
 @Component
 @AllArgsConstructor
+@Slf4j
 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信息失败");
+    // 线程池
+    @Resource(name = "taskExecutor1")
+    private ThreadPoolExecutor executor;
+
+    //用户
+    @Resource
+    private IUserClient userClient;
+
+
+    public void reSigningEVisaStatusSync(InformationQuery dto, String header) {
+        log.info("数据正在重刷,线程名称:{}", Thread.currentThread().getName());
+
+        informationQueryService.update(new LambdaUpdateWrapper<InformationQuery>()
+                .eq(InformationQuery::getId, dto.getId())
+                .set(InformationQuery::getEVisaPdfUrl, null)
+                .set(InformationQuery::getUpdateTime, DateTime.now())
+
+                .set(InformationQuery::getPdfUrl, null));
+        R result = this.saveNodePdf(dto.getClassify() + "", dto.getWbsId() + "", dto.getContractId() + "", dto.getProjectId() + "", header);
+
+        LambdaUpdateWrapper<InformationQuery> lambda = Wrappers.<InformationQuery>update().lambda();
+        if (result == null || result.getCode() != 200) {
+            //重签失败
+            lambda.set(InformationQuery::getSaveAgain, 3)
+                    .set(InformationQuery::getEVisaPdfUrl, dto.getEVisaPdfUrl())
+                    .setSql("save_again_count = save_again_count + 1")
+                    .set(InformationQuery::getPdfUrl, dto.getPdfUrl());
+        } else {
+            //成功重签
+            lambda.set(InformationQuery::getSaveAgain, 2);
+            lambda.set(InformationQuery::getSaveAgainCount, 0);
+        }
+        lambda.set(InformationQuery::getUpdateTime, DateTime.now());
+        lambda.eq(InformationQuery::getId, dto.getId());
+
+        informationQueryService.update(lambda);
+        log.info("数据重刷完毕,线程名称:{}", Thread.currentThread().getName());
+    }
+
+
+    /**
+     * 定时检查save-again = 1 的数据 查看更新时间与当前时间是否超过30分钟,如果超过 30分钟,则修改状态为0
+     * 一个小时检查一次
+     */
+    @Scheduled(cron = "0 0 * * * ?")
+    public void updateStuckTask() {
+        List<InformationQuery> list = informationQueryService.list(Wrappers.<InformationQuery>lambdaQuery()
+                .eq(InformationQuery::getSaveAgain, 1)
+                .eq(InformationQuery::getIsDeleted, 0));
+
+        List<Long> ids = new ArrayList<>();
+        for (InformationQuery informationQuery : list) {
+            //更新时间 + 半个小时 < 当前时间
+            if (informationQuery.getUpdateTime().getTime() + 1800000 < System.currentTimeMillis()) {
+                ids.add(informationQuery.getId());
+            }
+        }
+        if (CollectionUtils.isNotEmpty(ids)) {
+            informationQueryService.update(null, Wrappers.<InformationQuery>lambdaUpdate()
+                    .set(InformationQuery::getSaveAgain, 0)
+                    .in(InformationQuery::getId, ids));
+        }
+    }
+
+
+    /**
+     * 重刷定时任务 使用多线程的方式去跑
+     */
+    @Scheduled(fixedDelay = 60000)
+    public void saveAgainTask() {
+        if (!SystemUtils.isLinux()) {
+            return;
+        }
+        //获取token
+        String header = userClient.getTokenByUser("admin");
+
+        List<InformationQuery> list = informationQueryService.list(Wrappers.<InformationQuery>lambdaQuery()
+                .in(InformationQuery::getSaveAgain, 0, 3)
+                .eq(InformationQuery::getIsDeleted, 0)
+                //失败重刷次数小于2次
+                .lt(InformationQuery::getSaveAgainCount, 2)
+                .last("limit 50"));
+        if (CollectionUtils.isEmpty(list)) {
+            return;
+        }
+
+        for (InformationQuery informationQueries : list) {
+            //修改状态之后开始重刷
+            boolean update = informationQueryService.update(Wrappers.<InformationQuery>update().lambda()
+                    .set(InformationQuery::getSaveAgain, 1)
+                    .set(InformationQuery::getUpdateTime, DateTime.now())
+                    .eq(InformationQuery::getId, informationQueries.getId()));
+            if (update) {
+                CompletableFuture.runAsync(() -> {
+                    try {
+                        /*===============执行批量任务===============*/
+                        this.reSigningEVisaStatusSync(informationQueries, header);
+                    } catch (Exception e) {
+                        log.error("执行重刷任务失败,任务ID列表:{}", informationQueries.getId(), e);
+                        // 可选:回滚状态或标记为失败
                     }
-                }
+                }, executor).exceptionally(throwable -> {
+                    log.error("异步任务执行异常,任务ID列表:{}", informationQueries.getId(), throwable);
+                    return null;
+                });
             }
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }finally {
-            //删除缓f存
-            bladeRedis.del(s);
         }
+        log.info("队列数量{}", executor.getQueue().size());
+        log.info("活跃数量{}", executor.getActiveCount());
+        log.info("总共数量{}", executor.getTaskCount());
+        log.info("完成数量{}", executor.getCompletedTaskCount());
     }
 
-    R saveNodePdf(String classify, String nodePKeyIds, String contractId, String projectId, String header) throws Exception {
-        return excelTabClient.synPDFInfo(contractId, nodePKeyIds, classify, projectId, header);
+
+    R saveNodePdf(String classify, String nodePKeyIds, String contractId, String projectId, String header) {
+        try {
+            return excelTabClient.synPDFInfo(contractId, nodePKeyIds, classify, projectId, header);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
     }
 }

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

@@ -105,7 +105,7 @@ public class PDFUtil {
             for(int k=0;k<lines.length;k++){
                 String textStr = lines[k];
                 int index = textStr.indexOf("*");
-                if(index>=0 && textStr.charAt(index+1) != '✹'){
+                if(index>=0 && textStr.lastIndexOf("*")+1 < textStr.length() && textStr.charAt(index+1) != '✹'){
                     textStr = textStr.substring(textStr.lastIndexOf("*")+1,textStr.length());
                 }
 
@@ -140,7 +140,7 @@ public class PDFUtil {
                         eVisaConfigList.add(txt);
                     }
                 }
-                if (textStr.contains("✹")) {
+                if (textStr.contains("✹") && textStr.indexOf("✹") + 1 < textStr.length()) {
                     String textString = textStr.substring(textStr.indexOf("✹") + 1);
                     if (textString.contains("||✹")) {
                         String[] textS1 = Func.toStrArray("\\|\\|✹",textString);

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

@@ -220,7 +220,7 @@ public class EVDataServiceImpl implements EVDataService {
                     Long pdfSize = 0L;
                     String nodePdfUrl = "";
 
-                    List<Map<String, Object>> mapList = jdbcTemplate.queryForList("select *,domain_url as url from m_table_file where is_deleted = 0 and type in (10,11,12) and tab_id = (select wbs_id from u_information_query WHERE id = + " + taskApp.getFormDataId() + ")");
+                    List<Map<String, Object>> mapList = jdbcTemplate.queryForList("select *,domain_url as url from m_table_file where is_deleted = 0 and type in (10,11,12) and (tab_id,classify) in (select wbs_id, classify from u_information_query WHERE id = + " + taskApp.getFormDataId() + ")");
                     if (Func.isNotEmpty(mapList) && mapList.size() >= 1) {
                         String file_path = FileUtils.getSysLocalFileUrl();
                         List<String> datainfo = new ArrayList<>();
@@ -356,6 +356,7 @@ public class EVDataServiceImpl implements EVDataService {
                 }
             }
             RedisTemplate.delete("sign-" + taskApp.getFormDataId());
+            RedisTemplate.opsForList().rightPush("blade:statistics:information_query_statistics_key", taskApp.getFormDataId());
             Thread.sleep(1000);
         } catch (Exception e) {
             RedisTemplate.delete("sign-" + taskApp.getFormDataId());

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

@@ -33,7 +33,7 @@ public class PDFUtils {
             for(int k=0;k<lines.length;k++){
                 String textStr = lines[k];
                 int index = textStr.indexOf("*");
-                if(index>=0 && textStr.charAt(index+1) != '✹'){
+                if(index>=0 && textStr.lastIndexOf("*")+1 < textStr.length() && textStr.charAt(index+1) != '✹'){
                     textStr = textStr.substring(textStr.lastIndexOf("*")+1,textStr.length());
                 }
 
@@ -74,7 +74,7 @@ public class PDFUtils {
                         eVisaConfigList.add(txt);
                     }
                 }
-                if (textStr.contains("✹")) {
+                if (textStr.contains("✹") && textStr.indexOf("✹") + 1 < textStr.length()) {
                     String textString = textStr.substring(textStr.indexOf("✹") + 1);
                     if (textString.contains("||✹")) {
                         String[] textS1 = Func.toStrArray("\\|\\|✹",textString);
@@ -137,7 +137,7 @@ public class PDFUtils {
             for(int k=0;k<lines.length;k++){
                 String textStr = lines[k];
                 int index = textStr.indexOf("*");
-                if(index>=0 && textStr.charAt(index+1) != '✹'){
+                if(index>=0 && textStr.lastIndexOf("*")+1 < textStr.length() && textStr.charAt(index+1) != '✹'){
                     textStr = textStr.substring(textStr.lastIndexOf("*")+1,textStr.length());
                 }
 
@@ -172,7 +172,7 @@ public class PDFUtils {
                         eVisaConfigList.add(txt);
                     }
                 }
-                if (textStr.contains("✹")) {
+                if (textStr.contains("✹") && textStr.indexOf("✹") + 1 < textStr.length()) {
                     String textString = textStr.substring(textStr.indexOf("✹") + 1);
                     if (textString.contains("||✹")) {
                         String[] textS1 = Func.toStrArray("\\|\\|✹",textString);

+ 3 - 1
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/EqualNode.java

@@ -31,12 +31,14 @@ public class EqualNode extends OperatorResultNode {
                 Object[] leftAndRight = ValueUtil.obtain(leftOperand.calculate(variables), rightOperand.calculate(variables));
 
                 //如果是数字类型 第一个是float  第二个是整数所以不能使用equals
-                if(leftAndRight[0] instanceof Number && leftAndRight[1] instanceof Number){
+                if (leftAndRight[0] instanceof Number && leftAndRight[1] instanceof Number) {
                     return EqUtil.calculate((Number) leftAndRight[0], (Number) leftAndRight[1]);
                 }
 
                 boolean equals = StringUtils.isEquals(leftAndRight[0], leftAndRight[1]);
                 return leftAndRight == null ? null : equals;
+            } else if (leftValue instanceof Boolean || rightValue instanceof Boolean) {
+                return leftValue instanceof Boolean ? leftValue : rightValue;
             } else {
                 return leftValue.equals(rightValue);
             }

+ 6 - 1
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/GtNode.java

@@ -21,7 +21,12 @@ public class GtNode extends OperatorResultNode {
 //		if (rightValue == null) {
 //			return null;
 //		}
-        Object[] leftAndRight = ValueUtil.obtain(leftOperand.calculate(variables), rightOperand.calculate(variables));
+        Object calculate = leftOperand.calculate(variables);
+        if(calculate instanceof Boolean && !(Boolean) calculate){
+            return calculate;
+        }
+        Object calculate1 = rightOperand.calculate(variables);
+        Object[] leftAndRight = ValueUtil.obtain(calculate, calculate1);
         return leftAndRight == null ? null : GtUtil.calculate((Number) leftAndRight[0], (Number) leftAndRight[1]);
     }
 

+ 6 - 1
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/LtEqNode.java

@@ -21,7 +21,12 @@ public class LtEqNode extends OperatorResultNode {
 //		if (rightValue == null) {
 //			return null;
 //		}
-        Object[] leftAndRight = ValueUtil.obtain(leftOperand.calculate(variables), rightOperand.calculate(variables));
+        Object calculate = leftOperand.calculate(variables);
+        if(calculate instanceof Boolean && !(Boolean) calculate){
+            return calculate;
+        }
+        Object calculate1 = rightOperand.calculate(variables);
+        Object[] leftAndRight = ValueUtil.obtain(calculate, calculate1);
         return leftAndRight == null ? null : !((Boolean) GtUtil.calculate((Number) leftAndRight[0], (Number) leftAndRight[1]));
     }
 

+ 6 - 1
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/LtNode.java

@@ -22,7 +22,12 @@ public class LtNode extends OperatorResultNode {
 //		if (rightValue == null) {
 //			return null;
 //		}
-        Object[] leftAndRight = ValueUtil.obtain(leftOperand.calculate(variables), rightOperand.calculate(variables));
+        Object calculate = leftOperand.calculate(variables);
+        if(calculate instanceof Boolean && !(Boolean) calculate){
+            return calculate;
+        }
+        Object calculate1 = rightOperand.calculate(variables);
+        Object[] leftAndRight = ValueUtil.obtain(calculate, calculate1);
         return leftAndRight == null ? null : LtUtil.calculate((Number) leftAndRight[0], (Number) leftAndRight[1]);
     }
 

+ 3 - 1
blade-service/blade-manager/src/main/java/com/jfireel/expression/node/impl/NotEqualNode.java

@@ -31,12 +31,14 @@ public class NotEqualNode extends OperatorResultNode {
                 Object[] leftAndRight = ValueUtil.obtain(leftOperand.calculate(variables), rightOperand.calculate(variables));
 
                 //如果是数字类型 第一个是float  第二个是整数所以不能使用equals
-                if(leftAndRight[0] instanceof Number && leftAndRight[1] instanceof Number){
+                if (leftAndRight[0] instanceof Number && leftAndRight[1] instanceof Number) {
                     return !EqUtil.calculate((Number) leftAndRight[0], (Number) leftAndRight[1]);
                 }
 
                 boolean equals = !StringUtils.isEquals(leftAndRight[0], leftAndRight[1]);
                 return leftAndRight == null ? null : equals;
+            } else if (leftValue instanceof Boolean || rightValue instanceof Boolean) {
+                return leftValue instanceof Boolean ? leftValue : rightValue;
             } else {
                 return leftValue.equals(rightValue) == false;
             }

+ 1 - 0
blade-service/blade-manager/src/main/java/com/jfireel/expression/parse/impl/NumberParser.java

@@ -7,6 +7,7 @@ import com.jfireel.expression.parse.Invoker;
 import com.jfireel.expression.token.Operator;
 import com.jfireel.expression.token.Symbol;
 import com.jfireel.expression.token.Token;
+import com.jfireel.expression.token.TokenType;
 import com.jfireel.expression.util.CharType;
 
 import java.util.Deque;

+ 3 - 2
blade-service/blade-manager/src/main/java/com/mixsmart/utils/CustomFunction.java

@@ -18,6 +18,7 @@ import org.springblade.manager.entity.WbsTreeContract;
 import org.springblade.manager.utils.RandomNumberHolder;
 
 import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.time.LocalDate;
@@ -1775,13 +1776,13 @@ public class CustomFunction {
             for (Object obj : l1) {
                 String[] arr = obj.toString().split("[×xX*/]");
                 if (Arrays.stream(Arrays.stream(arr).toArray()).allMatch(StringUtils::isNumber)) {
-                    if (Arrays.stream(Arrays.stream(arr).toArray()).map(StringUtils::handleNull).map(Double::parseDouble).noneMatch(e -> e > finalMax || e < finalMin)) {
+                    if (Arrays.stream(Arrays.stream(arr).toArray()).map(StringUtils::handleNull).map(item -> new BigDecimal(item).setScale(8, RoundingMode.HALF_UP).doubleValue()).noneMatch(e -> e > finalMax || e < finalMin)) {
                         result.add(obj);
                     }
                 }
             }
         }
-        List<Object> l2 = datas.stream().filter(StringUtils::isNumber).map(StringUtils::handleNull).map(Double::parseDouble).filter(e -> e <= finalMax && e >= finalMin).collect(Collectors.toList());
+        List<Object> l2 = datas.stream().filter(StringUtils::isNumber).map(StringUtils::handleNull).map(item -> new BigDecimal(item).setScale(8, RoundingMode.HALF_UP).doubleValue()).filter(e -> e <= finalMax && e >= finalMin).collect(Collectors.toList());
         if (ListUtils.isNotEmpty(l2)) {
             result.addAll(l2);
         }

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

@@ -32,10 +32,12 @@ import org.jsoup.nodes.Document;
 import org.jsoup.nodes.Element;
 import org.jsoup.nodes.Node;
 import org.jsoup.select.Elements;
+import org.springblade.business.dto.WbsTreeContractStatisticsDTO;
 import org.springblade.business.entity.ContractLog;
 import org.springblade.business.entity.InformationQuery;
 import org.springblade.business.feign.ContractLogClient;
 import org.springblade.business.feign.InformationQueryClient;
+import org.springblade.business.feign.WbsTreeContractStatisticsClient;
 import org.springblade.business.vo.SaveContractLogVO;
 import org.springblade.common.constant.CommonConstant;
 import org.springblade.common.utils.*;
@@ -164,6 +166,8 @@ public class ExcelTabController extends BladeController {
 
     private final WbsTreeContractMapper wbsTreeContractMapper;
 
+    private final WbsTreeContractStatisticsClient wbsTreeContractStatisticsClient;
+
 
     @Autowired
     StringRedisTemplate RedisTemplate;
@@ -2103,6 +2107,12 @@ public class ExcelTabController extends BladeController {
         executionTime.info("---PDF合并耗时---");
         //更新缓存
         informationQueryClient.delAsyncWbsTree(contractId);
+        try {
+            WbsTreeContractStatisticsDTO dto = new WbsTreeContractStatisticsDTO(Long.parseLong(contractId), Long.parseLong(nodeId), Integer.parseInt(classify));
+            wbsTreeContractStatisticsClient.updateInformationQueryStatus(Collections.singletonList(dto));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
         executionTime.info("缓存删除耗时");
         executionTime.brief();
         return R.data(result.getMsg());

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

@@ -35,14 +35,19 @@ import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
 import org.springblade.core.redis.cache.BladeRedis;
+import org.springblade.core.secure.BladeUser;
+import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.secure.utils.SecureUtil;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.*;
+import org.springblade.manager.entity.DqOperationLog;
 import org.springblade.manager.entity.TextdictInfo;
 import org.springblade.manager.entity.WbsTreeContract;
 import org.springblade.manager.entity.WbsTreePrivate;
 import org.springblade.manager.mapper.WbsTreePrivateMapper;
+import org.springblade.manager.service.IDqOperationLogService;
 import org.springblade.manager.service.ITextdictInfoService;
+import org.springblade.manager.service.impl.DqOperationLogServiceImpl;
 import org.springblade.manager.service.impl.WbsTreeContractServiceImpl;
 import org.springblade.manager.utils.ExcelInfoUtils;
 import org.springblade.manager.utils.FileUtils;
@@ -58,10 +63,7 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -81,6 +83,7 @@ public class TextdictInfoController extends BladeController {
     private final WbsTreeContractServiceImpl wbsTreeContractService;
     private final BladeRedis bladeRedis;
     private final JdbcTemplate jdbcTemplate;
+    private final IDqOperationLogService dqOperationLogService;
 
     /**
      * 详情
@@ -237,9 +240,14 @@ public class TextdictInfoController extends BladeController {
             File writeFile = new File(wbsTreePrivate.getHtmlUrl());
             FileUtil.writeToFile(writeFile, doc.html(), Boolean.parseBoolean("UTF-8"));
         }
-
         //批量删除
         delIds.add(ids);
+        if (textdictInfo.getType() == 6 || textdictInfo.getType() == 2) {
+            JSONObject param = new JSONObject();
+            param.put("ids", ids);
+            param.put("tabId", tabId);
+            dqOperationLogService.save(new DqOperationLog(wbsTreePrivate, AuthUtil.getUser(), String.join( ",", delIds), 2,param.toJSONString(), JSON.toJSONString(query), ""));
+        }
         textdictInfoService.getBaseMapper().deleteBatchIds(delIds);
 
         return R.success("删除成功");
@@ -461,6 +469,8 @@ public class TextdictInfoController extends BladeController {
         String ids = StringUtils.join(pKeyIds, ",");
 
         //删除历史数据
+        String querySql = "select * from m_textdict_info where (tab_id in(SELECT p_key_id from m_wbs_tree_private where project_id='"+wbsTreePrivate.getProjectId()+"' and excel_id='"+wbsTreePrivate.getExcelId()+"' and type=2 and is_deleted=0) or (excel_id="+wbsTreePrivate.getExcelId()+" AND project_id='"+wbsTreePrivate.getProjectId()+"')) and project_id="+wbsTreePrivate.getProjectId()+" and type in(2,6) ";
+        List<TextdictInfo> oldTextdictInfos = jdbcTemplate.query(querySql, new BeanPropertyRowMapper<>(TextdictInfo.class));
         String delSql = "delete from m_textdict_info where (tab_id in(SELECT p_key_id from m_wbs_tree_private where project_id='"+wbsTreePrivate.getProjectId()+"' and excel_id='"+wbsTreePrivate.getExcelId()+"' and type=2 and is_deleted=0) or (excel_id="+wbsTreePrivate.getExcelId()+" AND project_id='"+wbsTreePrivate.getProjectId()+"')) and project_id="+wbsTreePrivate.getProjectId()+" and type in(2,6) ";
         jdbcTemplate.execute(delSql);
 
@@ -468,6 +478,8 @@ public class TextdictInfoController extends BladeController {
         Map<String,String> keyMap = new HashMap<>();
 
         // ------- 查询数据库是否存在 该该电签信息 ---------
+        StringBuilder dqIds = new StringBuilder();
+        List<TextdictInfo> newTextDictInfos = new ArrayList<>();
         for (int i = 0; i < jsonArray.size(); i++) {
             JSONObject jsonObject = jsonArray.getJSONObject(i);
             TextdictInfo textdictInfo = new TextdictInfo();
@@ -514,6 +526,8 @@ public class TextdictInfoController extends BladeController {
             }else{
                 textdictInfoService.save(textdictInfo);
             }
+            newTextDictInfos.add(textdictInfo);
+            dqIds.append(textdictInfo.getId()).append( ",");
             String dqId = "";
             if(keyMap.containsKey(keky)){
                 dqId = keyMap.get(keky)+"||"+textdictInfo.getId();
@@ -557,7 +571,12 @@ public class TextdictInfoController extends BladeController {
             String updateSqlC = "update m_wbs_tree_contract set html_url = '" + replace + "' where p_key_id in (" + cPkeyIdsStr + ") and project_id="+wbsTreePrivate.getProjectId()+"";
             jdbcTemplate.execute(updateSqlC);
         }
-
+        BladeUser user = AuthUtil.getUser();
+        DqOperationLog log = new DqOperationLog(wbsTreePrivate, user, "", 1, dataInfo.toJSONString(), JSON.toJSONString(oldTextdictInfos), JSON.toJSONString(newTextDictInfos));
+        if (dqIds.length() > 1) {
+            log.setBusinessId(dqIds.deleteCharAt(dqIds.length() - 1).toString());
+        }
+        dqOperationLogService.save(log);
         bladeRedis.set("save-eVis-lock:" + SecureUtil.getUserId(), "1");
         bladeRedis.expire("save-eVis-lock:" + SecureUtil.getUserId(), 3);
 

+ 3 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/TurnPoint.java

@@ -173,6 +173,9 @@ public class TurnPoint implements Serializable {
     }
 
     public String getSj() {
+        if(StringUtils.isEmpty(sj)){
+            sj = null;
+        }
         return sj;
     }
 

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

@@ -337,13 +337,13 @@
 
     <!-- 文件收集 归档树的文件数量 -->
     <select id="selectFileNumber" resultType="java.lang.Integer">
-        SELECT  count(1)  FROM m_archive_tree_contract a
+        SELECT  count(0)  FROM m_archive_tree_contract a
         inner join u_archive_file b on b.node_id = a.id and b.is_deleted = a.is_deleted and b.project_id = a.project_id and (b.is_auto_file is null or b.is_auto_file != 1)
         WHERE  a.is_deleted = 0
         and a.project_id = #{projectId}
         <choose>
             <when test="extType != null and extType == 1">
-                and ( 	b.node_id in( select id from  m_archive_tree_contract where FIND_IN_SET(#{id},ancestors) or a.id = #{id}) OR
+                and (b.node_id in( select id from  m_archive_tree_contract where FIND_IN_SET(#{id},ancestors) or a.id = #{id}) OR
                 b.node_ext_id in(  select id from  m_archive_tree_contract where FIND_IN_SET(#{id},ancestors) or a.id = #{id}))
             </when>
             <otherwise>

+ 8 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/DqOperationLogMapper.java

@@ -0,0 +1,8 @@
+package org.springblade.manager.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.springblade.manager.entity.DqOperationLog;
+import org.springblade.manager.entity.FormulaBase;
+
+public interface DqOperationLogMapper extends BaseMapper<DqOperationLog> {
+}

+ 25 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/DqOperationLogMapper.xml

@@ -0,0 +1,25 @@
+<?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.manager.mapper.DqOperationLogMapper">
+
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="resultMap" type="org.springblade.manager.entity.DqOperationLog">
+        <result column="id" property="id"/>
+        <result column="create_time" property="createTime"/>
+        <result column="create_user" property="createUser"/>
+        <result column="create_dept" property="createDept"/>
+        <result column="update_user" property="updateUser"/>
+        <result column="update_time" property="updateTime"/>
+        <result column="status" property="status"/>
+        <result column="is_deleted" property="isDeleted"/>
+        <result column="project_id" property="projectId"/>
+        <result column="node_id" property="nodeId"/>
+        <result column="operation_type" property="operationType"/>
+        <result column="operation_content" property="operationContent"/>
+        <result column="business_id" property="businessId"/>
+        <result column="old_content" property="oldContent"/>
+        <result column="new_content" property="newContent"/>
+    </resultMap>
+
+</mapper>

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

@@ -956,6 +956,6 @@
                (select node_type from m_wbs_tree_private where p_key_id = ucl.wbs_node_id) as logType,
                (select node_name from m_wbs_tree_private where p_key_id = ucl.wbs_node_id) as logName
         from u_contract_log ucl
-        where contract_id = #{contractId} and is_deleted = 0
+        where contract_id = #{contractId} and is_deleted = 0 and pdf_url IS NOT NULL order by record_time
     </select>
 </mapper>

+ 12 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/IDqOperationLogService.java

@@ -0,0 +1,12 @@
+package org.springblade.manager.service;
+
+import org.springblade.core.mp.base.BaseService;
+import org.springblade.manager.entity.*;
+
+
+/**
+ * @author yangyj
+ */
+public interface IDqOperationLogService extends BaseService<DqOperationLog> {
+
+}

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

@@ -1148,7 +1148,7 @@ public class ArchiveTreeContractSyncImpl {
         if (StringUtils.isBlank(contractLogType)){
             throw new ServiceException("当前节点未配置同步日志资料类型");
         }
-        List<Integer> logType = Arrays.stream(contractLogType.split(","))
+        List<Integer> logType = Arrays.stream(contractLogType.split(",")).filter(l -> StringUtils.isNotBlank(l))
                 .map(Integer::parseInt) // 将每个字符串转换为Integer
                 .collect(Collectors.toList());
         //获取日志类型字典

+ 13 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/DqOperationLogServiceImpl.java

@@ -0,0 +1,13 @@
+package org.springblade.manager.service.impl;
+
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.manager.entity.DqOperationLog;
+import org.springblade.manager.mapper.DqOperationLogMapper;
+import org.springblade.manager.service.IDqOperationLogService;
+import org.springframework.stereotype.Service;
+
+
+@Service
+public class DqOperationLogServiceImpl extends BaseServiceImpl<DqOperationLogMapper, DqOperationLog> implements IDqOperationLogService {
+
+}

+ 28 - 24
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java

@@ -736,6 +736,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
 
             //参数
             LinkedHashMap<String, String> dataMap2 = tableInfo.getDataMap();
+            updateFieldLength(tabName, dataMap2);
             for (String key : dataMap2.keySet()) {
                 keySql.append(", ").append(key);
                 valSql.append(", '").append(dataMap2.get(key)).append("'");
@@ -1105,7 +1106,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                         for (TableInfo tableInfo : tableInfoList) {
                             //获取字段信息
                             LinkedHashMap<String, String> dataMap2 = tableInfo.getDataMap();
-
+                            updateFieldLength(table.getTabEnName(),dataMap2);
                             //拼接SQL
                             StringBuilder sql = new StringBuilder("INSERT INTO " + table.getTabEnName()),
                                     keySql = new StringBuilder("id, group_id"),
@@ -1233,9 +1234,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                     String delSql = "delete from " + tabName + " where p_key_id=" + tableInfo.getPkeyId();
                     String sqlInfo = "";
                     LinkedHashMap<String, String> dataMap2 = tableInfo.getDataMap();
-                    if (!updateFieldLength(tabName, dataMap2)) {
-                        throw new ServiceException("字段长度超出限制, 系统无法进行自增,请前往后台管理系统手动设置");
-                    }
+                    updateFieldLength(tabName, dataMap2);
                     /*检查发现有p_key_id缺失的情况,导致表单数据丢失,所以强制覆盖*/
                     dataMap2.put("p_key_id", tableInfo.getPkeyId());
                     //统计保存的字段
@@ -1346,17 +1345,14 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
        // return R.success(fileName1);
     }
 
-    public boolean updateFieldLength(String tableName, Map<String, String> fieldNameAndLengthMap) {
+    public void updateFieldLength(String tableName, Map<String, String> fieldNameAndLengthMap) {
         if (fieldNameAndLengthMap == null || fieldNameAndLengthMap.isEmpty()) {
-            return true;
+            return;
         }
-        fieldNameAndLengthMap.remove("id");
-        fieldNameAndLengthMap.remove("p_key_id");
-        fieldNameAndLengthMap.remove("group_id");
-        if (fieldNameAndLengthMap.isEmpty()) {
-            return true;
+        String fields = fieldNameAndLengthMap.keySet().stream().filter(key -> !key.equals("id") && !key.equals("p_key_id") && !key.equals("group_id")).map(key -> "'" + key + "'").collect(Collectors.joining(","));
+        if (fields.isEmpty()) {
+            return;
         }
-        String fields = fieldNameAndLengthMap.keySet().stream().map(key -> "'" + key + "'").collect(Collectors.joining(","));
         List<Map<String, Object>> fieldMap = jdbcTemplate.queryForList("select distinct COLUMN_NAME as fieldName, CHARACTER_MAXIMUM_LENGTH as fieldLength from information_schema.COLUMNS where  TABLE_NAME = '" + tableName +
                 "' and COLUMN_NAME in (" + fields + ")");
         Map<String, Integer> map = fieldMap.stream().collect(toMap(k -> k.get("fieldName") + "", v -> {
@@ -1397,10 +1393,9 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
             } catch (Exception e) {
                 transactionManager1.rollback(transactionStatus);
                 log.error("更新字段长度失败, error: " + e.getMessage());
-                return false;
+                throw new ServiceException("字段长度超出限制, 系统无法进行扩容,请尝试缩小字段长度或者联系系统管理员处理");
             }
         }
-        return true;
     }
 
     public String reason(String log) {
@@ -3163,19 +3158,27 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
             List<Map<String, Object>> formulas = null;
             if (wbsTreePrivate != null) {
                 if (wbsTreePrivate.getInitTableId() != null) {
-                    formulas = jdbcTemplate.queryForList("SELECT a.e_name,b.rely FROM m_wbs_form_element a, m_formula b WHERE  b.id in ( SELECT formula_id FROM m_element_formula_mapping WHERE scope = 0 AND element_id = a.id) and a.f_id = " +
+                    formulas = jdbcTemplate.queryForList("SELECT a.e_name, b.rely, c.scope from m_wbs_form_element a , m_formula b, m_element_formula_mapping c WHERE b.id = c.formula_id and c.element_id = a.id and a.f_id = " +
                             wbsTreePrivate.getInitTableId() + " and b.rely like '%TBInfo:%'");
-                }
-                if (wbsTreePrivate.getInitTableName() != null) {
+                } else if (wbsTreePrivate.getInitTableName() != null) {
                     List<org.springblade.manager.entity.TableInfo> tableInfos = tableInfoService.list(Wrappers.<org.springblade.manager.entity.TableInfo>lambdaQuery().eq(org.springblade.manager.entity.TableInfo::getTabEnName, wbsTreePrivate.getInitTableName()));
                     if (!tableInfos.isEmpty()) {
-                        formulas = jdbcTemplate.queryForList("SELECT a.e_name,b.rely FROM m_wbs_form_element a, m_formula b WHERE  b.id in ( SELECT formula_id FROM m_element_formula_mapping WHERE scope = 0 AND element_id = a.id) and a.f_id = " +
+                        formulas = jdbcTemplate.queryForList("SELECT a.e_name, b.rely, c.scope from m_wbs_form_element a , m_formula b, m_element_formula_mapping c WHERE b.id = c.formula_id and c.element_id = a.id and a.f_id = " +
                                 tableInfos.get(0).getId() + " and b.rely like '%TBInfo:%'");
                     }
                 }
             }
             if (!ObjectUtil.isEmpty(formulas)) {
-                for (Map<String, Object> formula : formulas) {
+                Map<Object, Map<String, Object>> collect = formulas.stream().peek(formula -> formula.putIfAbsent("scope", -1)).filter(formula -> formula.get("rely") != null && formula.get("e_name") != null)
+                        .collect(toMap(k -> k.get("e_name"), v -> v, (v1, v2) -> {
+                            Object o1 = v1.get("scope");
+                            Object o2 = v2.get("scope");
+                            if (o1 instanceof Integer && o2 instanceof Integer) {
+                                return (Integer) o1 > (Integer) o2 ? v1 : v2;
+                            }
+                            return o1 instanceof Integer ? v1 : o2 instanceof Integer ? v2 : v1;
+                        }));
+                for (Map<String, Object> formula : collect.values()) {
                     Object relyObj = formula.get("rely");
                     if (relyObj == null) {
                         continue;
@@ -3192,7 +3195,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                         if (!rely.contains("TBInfo:")) {
                             continue;
                         }
-                        keyMap.put(rely, map.toString());
+                        keyMap.put(map.toString(), rely);
                     }
                 }
             }
@@ -3942,6 +3945,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                 //新增SQL
                 String sqlInfo = "";
                 LinkedHashMap<String, String> dataMap2 = tableInfo.getDataMap();
+                updateFieldLength(wbsTreePrivate.getInitTableName() ,dataMap2);
                 if(!dataMap2.containsKey("p_key_id")){
                     if(tableInfo.getPkeyId()!=null&&!tableInfo.getPkeyId().equals("")){
                         dataMap2.put("p_key_id",tableInfo.getPkeyId());
@@ -5197,7 +5201,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
         }
         setFirstData(doc,"批号",sampleInfo.getBatchNumber(),reData,isCancelList);
         setFirstData(doc,"生产批号",sampleInfo.getBatchNumber(),reData,isCancelList);
-        setFirstData(doc,"生产厂家",sampleInfo.getSamplingLocation(),reData,isCancelList);
+        setFirstData(doc,"生产厂家",sampleInfo.getSupplierUnit(),reData,isCancelList);
         setFirstData(doc,"样品编号",sampleInfo.getSpecificationNumber(),reData,isCancelList);
         setFirstData(doc,"取样地点",sampleInfo.getSamplingLocation(),reData,isCancelList);
         setFirstData(doc,"样品描述",sampleInfo.getSampleDescription(),reData,isCancelList);
@@ -5232,7 +5236,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
             setFirstData(doc,"本批材料数量",entrustInfo.getExpCount()+calculationUnit,reData,isCancelList);
         }
         if(trialMaterialMobilization != null){
-            setFirstData(doc,"生产厂家",trialMaterialMobilization.getPlaceOfProduction(),reData,isCancelList);
+//            setFirstData(doc,"生产厂家",trialMaterialMobilization.getPlaceOfProduction(),reData,isCancelList);
             setFirstData(doc,"供应商",trialMaterialMobilization.getPlaceOfProduction(),reData,isCancelList);
         }
         return isCancelList;
@@ -5243,13 +5247,13 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
         TrialBaseInfo baseInfo = buildTrialBaseInfo(sampleInfo, entrustInfo, record, baseInfoDTO);
         Map<String, String> keyMap = formulaTrialData(wbsTreePrivate);
         keyMap.forEach((key, value) -> {
-            setFirstData(doc,value,baseInfo.getValueByKey(key),reData,isCancelList);
+            setFirstData(doc,key,baseInfo.getValueByKey(value),reData,isCancelList);
         });
         if (record != null && record.getStandardId() != null && record.getStandardInfoIds() != null) {
             String[] split = record.getStandardInfoIds().split(",");
             if (split.length > 0) {
                 // 技术指标
-                List<Map<String, Object>> mapList = jdbcTemplate.queryForList("SELECT concat(a.symbol,a.name) symbolName,b.col_key,b.col_name from u_standard_info a, u_standard_info_private_join b WHERE a.id = b.standard_info_id and " +
+                List<Map<String, Object>> mapList = jdbcTemplate.queryForList("SELECT  case when a.symbol = '~' then  a.name else concat(a.symbol,a.name) end symbolName,b.col_key,b.col_name from u_standard_info a, u_standard_info_private_join b WHERE a.id = b.standard_info_id and " +
                                 "a.standard_id = ? and b.private_id = ? and a.is_deleted = 0 and b.is_deleted = 0 " +
                                 "and (SELECT count(1) from u_standard_info_join WHERE standard_info_right_id in ( "+ record.getStandardInfoIds() +" ) and standard_info_left_id = a.id and is_deleted = 0) = ?"
                         , record.getStandardId() , wbsTreePrivate.getPKeyId(), split.length);

+ 57 - 13
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java

@@ -5112,6 +5112,32 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                                         f = f.replace(el, "缺少数据无法匹配");
                                         break;
                                     }
+                                    //生成比较公式的时候是否使用或者
+                                    Boolean isOr = false;
+                                    //如果是范围
+                                    if (list1.get(0).contains("~") || list2.get(0).contains("~")) {
+                                        if(list1.get(0).contains("~")){
+                                            String[] split2 = list1.get(0).split("~");
+                                            list1.set(0, ">" + split2[0] + " <" + split2[1]);
+                                        }else{
+                                            String[] split2 = list2.get(0).split("~");
+                                            list2.set(0, ">" + split2[0] + " <" + split2[1]);
+                                        }
+
+
+                                    } else if (list1.get(0).startsWith("±") || list2.get(0).startsWith("±")) {
+                                        isOr = true;
+                                        //如果是正负值
+                                        if(list1.get(0).startsWith("±")){
+                                            String value = list1.get(0).substring(1);
+
+                                            list1.set(0, "=" + value + " =-" + value);
+                                        }else{
+                                            String value = list2.get(0).substring(1);
+                                            list2.set(0, "=" + value + " =-" + value);
+                                        }
+                                    }
+
                                     //带后缀的数据去掉留纯数据
                                     String strings1 = extractPureNumbers(list1.get(0));
                                     String strings2 = extractPureNumbers(list2.get(0));
@@ -5149,10 +5175,15 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                                                 }
 
                                                 operator = strReplace(operator);
-                                                String str = split1[1] + operator + extractPureNumbers(number);
+                                                number = extractPureNumbers(number);
+                                                String str = split1[1] + operator + (number != null && number.startsWith("-") ? "(" + number + ")" : number);
                                                 list.add(str);
                                             }
-                                            formulaData = String.join("&&",list);
+                                            if(isOr){
+                                                formulaData = String.join("||",list);
+                                            }else{
+                                                formulaData = String.join("&&",list);
+                                            }
                                         }else{
                                             String number = null;
                                             //获取比较符
@@ -5164,8 +5195,8 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                                                 number = s3.substring(1);
                                             }
                                             operator = strReplace(operator);
-
-                                            formulaData = split1[1] + operator + extractPureNumbers(number);
+                                            number = extractPureNumbers(number);
+                                            formulaData = split1[1] + operator + (number !=null && number.startsWith("-") ? "(" + number + ")" : number);
                                         }
                                     }else if (pattern.matcher(s3).matches() && !pattern.matcher(s4).matches()){
                                         list1.set(0,s3);
@@ -5183,10 +5214,15 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                                                     number = string.substring(1);
                                                 }
                                                 operator = strReplace(operator);
-                                                String str = split1[0] + operator + extractPureNumbers(number);
+                                                number = extractPureNumbers(number);
+                                                String str = split1[0] + operator + (number !=null && number.startsWith("-") ? "(" + number + ")" : number);
                                                 list.add(str);
                                             }
-                                            formulaData = String.join("&&",list);
+                                            if(isOr){
+                                                formulaData = String.join("||",list);
+                                            }else{
+                                                formulaData = String.join("&&",list);
+                                            }
                                         }else{
                                             String number = null;
                                             //获取比较符
@@ -5198,7 +5234,9 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                                                 number = s4.substring(1);
                                             }
                                             operator = strReplace(operator);
-                                            formulaData = split1[0] + operator + extractPureNumbers(number);
+                                            //新值
+                                            number = extractPureNumbers(number);
+                                            formulaData = split1[0] + operator + (number !=null && number.startsWith("-") ? "(" + number + ")" : number);
                                         }
                                     } else{
                                         f = f.replace(el, "数据错误,无法比较");
@@ -5319,17 +5357,23 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
             return null;
         }
 
-        // 检查第一个字符是否为数字
-        if (Character.isDigit(input.charAt(0))) {
+        // 处理负数情况:以 '-' 开头且后跟数字
+        if (input.startsWith("-") && input.length() > 1 && Character.isDigit(input.charAt(1))) {
+            int endIndex = 2;  // 从 '-' 后开始检查数字
+            while (endIndex < input.length() && Character.isDigit(input.charAt(endIndex))) {
+                endIndex++;
+            }
+            return input.substring(0, endIndex);  // 返回 "-" + 连续数字
+        }
+        // 处理正数情况:以数字开头
+        else if (Character.isDigit(input.charAt(0))) {
             int endIndex = 1;
-            // 遍历后续字符,直到遇到非数字或字符串结束
             while (endIndex < input.length() && Character.isDigit(input.charAt(endIndex))) {
                 endIndex++;
             }
-            // 返回开头的连续数字子串
-            return input.substring(0, endIndex);
+            return input.substring(0, endIndex);  // 返回连续数字
         }
-        // 如果开头不是数字,返回空字符串
+        // 其他情况返回 null
         return null;
     }
 

+ 40 - 29
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsFormElementServiceImpl.java

@@ -322,25 +322,10 @@ public class WbsFormElementServiceImpl extends BaseServiceImpl<WbsFormElementMap
         //修改之前的值
         String fId1 = wbsFormElementList.get(0).getFId();
         List<WbsFormElement> beforeUpdateWbsFormElements = baseMapper.selectList(Wrappers.<WbsFormElement>query().lambda().eq(WbsFormElement::getFId, fId1));
+        Map<Long, Integer> eLengthMap = beforeUpdateWbsFormElements.stream().collect(Collectors.toMap(WbsFormElement::getId, WbsFormElement::getELength, (v1, v2) -> v1 > v2 ? v1 : v2));
         //修改元素基础信息
         wbsFormElementList.forEach(obj -> obj.setStatus(1));
         boolean b = this.updateBatchById(wbsFormElementList);
-
-
-        //当前设置的字段总长度
-        Integer nowTotalLength = 0;
-        for (WbsFormElement wbsFormElement : wbsFormElementList) {
-            // + 10 预留字段长度,用来保存在excel中的位置信息,比如:xx_^_12_12, 不适合一个字段存储多个位置
-            nowTotalLength += wbsFormElement.getELength() + 10;
-        }
-        //当前表总字段长度
-        int sumLength = baseMapper.selectSumColumnLength(jdbcTemplate.queryForObject("SELECT DATABASE()", String.class), initTableName);
-        if (nowTotalLength > MYSQL_MAX_COLUMN_LENGTH) {
-            //修改元素字段长度
-            throw new ServiceException("无法添加字段,可用长度:" + (MYSQL_MAX_COLUMN_LENGTH - sumLength));
-        }
-
-
         //修改实体表信息
         if (b) {
             String fId = "";
@@ -379,22 +364,48 @@ public class WbsFormElementServiceImpl extends BaseServiceImpl<WbsFormElementMap
 //                } else if (eLength >= 0 && eLength <= 65) {
 //                    eLength = DEFAULT_ELEMENT_LENGTH_NUMBER;
 //                }
+                Integer length = eLengthMap.get(wbsFormElement.getId());
+                if (length == null || !length.equals(eLength)) {
+                    //判断是否存在该Key字段
+                    int row1 = wbsTreeMapper.isThereAField(initTableName, eKey);
+                    if (row1 > 0) {
+                        try {
+                            baseMapper.updateFiledType(initTableName, eKey, "varchar", eLength);
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                            this.updateBatchById(beforeUpdateWbsFormElements);
+                            return R.fail(eName + "长度范围超出总最大限制,请尝试缩小当前字段与其他字段长度或者联系系统管理员处理");
+                        }
+                    }
+                }
+            }
 
-                //判断是否存在该Key字段
-                int row1 = wbsTreeMapper.isThereAField(initTableName, eKey);
-                if (row1 > 0) {
-                    try {
-                        // + 10 预留字段长度,用来保存在excel中的位置信息,比如:xx_^_12_12, 不适合一个字段存储多个位置
-                        baseMapper.updateFiledType(initTableName, eKey, "varchar", eLength + 10);
-                    } catch (Exception e) {
-                        // 数据库字段长度大于修改长度,则忽略
-                        if (e.getMessage().contains("Data truncated for column '" + eKey + "' at row 1")) {
-                            continue;
+            //元素库修改元素的同时要去修改html上面的元素
+            String sql="select DISTINCT html_url from m_wbs_tree_private where init_table_name='"+initTableName+"' and is_deleted=0 and html_url is not null";
+            List<String> htmlurls = jdbcTemplate.query(sql, new SingleColumnRowMapper<>(String.class));
+            if(!htmlurls.isEmpty()){
+                for (String htmlurl : htmlurls) {
+                    InputStream inputStream = FileUtils.getInputStreamByUrl(htmlurl);
+                    if(inputStream==null){
+                        continue;
+                    }
+                    String htmlString = IoUtil.readToString(inputStream);
+                    Document doc = Jsoup.parse(htmlString);
+                    for (WbsFormElement wbsFormElement : wbsFormElements) {
+                        Elements elements = doc.select("[keyname^=" + wbsFormElement.getEKey() + "__]");;
+                        for (Element element : elements) {
+                            element.attr("placeholder", wbsFormElement.getEName());
                         }
-                        e.printStackTrace();
-                        this.updateBatchById(beforeUpdateWbsFormElements);
-                        throw new RuntimeException("字段长度范围超出总最大限制,请尝试缩小当前字段长度或其他字段长度");
                     }
+                    try {
+                        File writefile = new File(htmlurl);
+                        FileUtil.writeToFile(writefile, doc.html(), Boolean.parseBoolean("UTF-8"));
+                    }catch (Exception e){
+                        System.out.println("修改html文件异常:"+ htmlurl);
+                    }finally {
+                        inputStream.close();
+                    }
+
                 }
             }
 

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

@@ -34,6 +34,7 @@ import org.springblade.business.entity.ConstructionLedger;
 import org.springblade.business.entity.InformationQuery;
 import org.springblade.business.feign.ConstructionLedgerFeignClient;
 import org.springblade.business.feign.InformationQueryClient;
+import org.springblade.business.feign.WbsTreeContractStatisticsClient;
 import org.springblade.business.vo.QueryProcessDataVO;
 import org.springblade.common.constant.CommonConstant;
 import org.springblade.common.utils.Colour;
@@ -114,6 +115,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
     private final ITableFileService tableFileService;
     private final TableInfoMapper  tableInfoMapper;
     private final WbsFormElementMapper wbsFormElementMapper;
+    private final WbsTreeContractStatisticsClient wbsTreeContractStatisticsClient;
 
 
     @Autowired
@@ -432,6 +434,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
 
         //更新Redis缓存
         informationQueryClient.delAsyncWbsTree(pawDTO.getContractId());
+        wbsTreeContractStatisticsClient.statisticsContract(Long.parseLong(pawDTO.getContractId()));
         return true;
     }
 
@@ -609,21 +612,36 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
 //        InformationQuery info = informationQueryClient.getInfoByWbsId(Long.valueOf(primaryKeyId));
 //        if(info!=null){
 //            resultTabs.forEach(tab->tab.setFileName(info.getName()));
-//        }
-
-
-//        if (Optional.ofNullable(wbsTreeContract.getIsUseSort()).orElse(0) == 0) {
-//            //表单排序
-//            if (resultTabs.size() > 0) {
-//               List<AppWbsTreeContractVO> resultTabsToCopy = this.sortTabs(resultTabs, "__"); //复制表排序
-//                return this.sortTabs(resultTabsToCopy, "_PL_"); //频率表排序
-//            }
 //        }
         // 使用自定义 Comparator 进行排序
         resultTabs.sort(new WbsTreeContractComparator());
+        if (Optional.ofNullable(wbsTreeContract.getIsUseSort()).orElse(0) == 0) {
+            //表单排序
+            if (resultTabs.size() > 0) {
+                sortTabsByIsTypePrivatePid(resultTabs);
+               List<AppWbsTreeContractVO> resultTabsToCopy = this.sortTabs(resultTabs, "__"); //复制表排序
+                return this.sortTabs(resultTabsToCopy, "_PL_"); //频率表排序
+            }
+        }
         return resultTabs;
     }
 
+    private void sortTabsByIsTypePrivatePid(List<AppWbsTreeContractVO> resultTabs) {
+        if(!resultTabs.isEmpty()){
+            for (AppWbsTreeContractVO resultTab : resultTabs) {
+                if(resultTab.getIsTypePrivatePid()!=null){
+                    String sql="select IFNULL(sort,1000) from m_wbs_tree_private where p_key_id="+resultTab.getIsTypePrivatePid()+" and is_deleted=0";
+                    Integer sort = jdbcTemplate.queryForObject(sql,Integer.class);
+                    if(sort!=null&&sort!=1000&&!Objects.equals(sort, resultTab.getSort())){
+                        resultTab.setSort(sort);
+                        String sql1="update m_wbs_tree_contract set sort="+sort+" where p_key_id="+resultTab.getPKeyId();
+                        jdbcTemplate.update(sql1);
+                    }
+                }
+            }
+        }
+    }
+
 
     public static class WbsTreeContractComparator implements Comparator<AppWbsTreeContractVO> {
 
@@ -1899,38 +1917,42 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                     values.set(i, String.join("☆",heightDeviationList));
                                 }
                             }
-                            if(rowMin==null){
-                                continue;
-                            }
-                            List<String> list = new ArrayList<>();
+                            if(rowMin!=null){
+                                List<String> list = new ArrayList<>();
 
-                            //获取当前key对应的坐标
-                            Set<String> strings = coordinateMap.get(initTabName);
-                            String index = null;
-                            for (String string : strings) {
-                                String[] split = string.split("__");
-                                if(Objects.equals(split[0],actualElevationNew)){
-                                    index = split[1];
+                                //获取当前key对应的坐标
+                                Set<String> strings = coordinateMap.get(initTabName);
+                                String index = null;
+                                for (String string : strings) {
+                                    String[] split = string.split("__");
+                                    if(Objects.equals(split[0],actualElevationNew)){
+                                        index = split[1];
+                                    }
                                 }
-                            }
-                            //按照最小行数来计算
-                            for (int i = rowMin; i <= rowMax; i++) {
-                                BigDecimal designed = designedElevationNewMap.get(i);
-                                BigDecimal height = heightDeviationNewMap.get(i);
+                                //按照最小行数来计算
+                                for (int i = rowMin; i <= rowMax; i++) {
+                                    BigDecimal designed = designedElevationNewMap.get(i);
+                                    BigDecimal height = heightDeviationNewMap.get(i);
 
-                                if(designed == null || height == null){
-                                    continue;
+                                    if(designed == null || height == null){
+                                        continue;
+                                    }
+                                    BigDecimal v = designed.add(height.divide(new BigDecimal(1000)));
+                                    //第5列,索引为4
+                                    list.add(v.doubleValue() + "_^_"+ i + "_" + index);
+                                }
+                                //未获取到当前key的坐标就不设置值
+                                if(index != null){
+                                    //设置实际标高的值
+                                    if(keys.indexOf(actualElevationNew) > -1){
+                                        values.set(keys.indexOf(actualElevationNew), String.join("☆",list));
+                                    }else{
+                                        keys.add(actualElevationNew);
+                                        values.add(String.join("☆",list));
+                                    }
                                 }
-                                BigDecimal v = designed.add(height.divide(new BigDecimal(1000)));
-                                //第5列,索引为4
-                                list.add(v.doubleValue() + "_^_"+ i + "_" + index);
-                            }
-                            //未获取到当前key的坐标就不设置值
-                            if(index == null){
-                                continue;
                             }
-                            //设置实际标高的值
-                            values.set(keys.indexOf(actualElevationNew), String.join("☆",list));
+
                         }else if(planePositionTableName.equals(initTabName)){
                             //CL10平面位置检测记录表(监理)
                             //差值
@@ -1993,42 +2015,40 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                 }
                                 values.set(i, String.join("☆",list));
                             }
-                            if(rowMin==null){
-                                continue;
-                            }
-                            List<String> list = new ArrayList<>();
-                            //获取当前key对应的坐标
-                            Set<String> strings = coordinateMap.get(initTabName);
-                            String index = null;
-                            for (String string : strings) {
-                                String[] split = string.split("__");
-                                if(Objects.equals(split[0],deviationNew)){
-                                    index = split[1];
+                            if(rowMin!=null){
+                                List<String> list = new ArrayList<>();
+                                //获取当前key对应的坐标
+                                Set<String> strings = coordinateMap.get(initTabName);
+                                String index = null;
+                                for (String string : strings) {
+                                    String[] split = string.split("__");
+                                    if(Objects.equals(split[0],deviationNew)){
+                                        index = split[1];
+                                    }
                                 }
-                            }
-                            //按照最小行数来计算
-                            for (int i = rowMin; i <= rowMax; i++) {
-                                BigDecimal x = differenceNewXMap.get(i);
-                                BigDecimal y = differenceNewYMap.get(i);
+                                //按照最小行数来计算
+                                for (int i = rowMin; i <= rowMax; i++) {
+                                    BigDecimal x = differenceNewXMap.get(i);
+                                    BigDecimal y = differenceNewYMap.get(i);
 
-                                if(x == null || y == null){
-                                    continue;
-                                }
-                                BigDecimal sqrt = sqrt(x.multiply(x).add(y.multiply(y)), 0);
+                                    if(x == null || y == null){
+                                        continue;
+                                    }
+                                    BigDecimal sqrt = sqrt(x.multiply(x).add(y.multiply(y)), 0);
 
-                                //第9列,索引为8
-                                list.add(sqrt.intValue() + "_^_"+ i + "_" + index);
-                            }
-                            //未获取到当前key的坐标就不设置值
-                            if(index == null){
-                                continue;
-                            }
-                            //设置实际标高的值
-                            if(keys.indexOf(deviationNew) > -1){
-                                values.set(keys.indexOf(deviationNew), String.join("☆",list));
-                            }else{
-                                keys.add(deviationNew);
-                                values.add(String.join("☆",list));
+                                    //第9列,索引为8
+                                    list.add(sqrt.intValue() + "_^_"+ i + "_" + index);
+                                }
+                                //未获取到当前key的坐标就不设置值
+                                if(index != null){
+                                    //设置实际标高的值
+                                    if(keys.indexOf(deviationNew) > -1){
+                                        values.set(keys.indexOf(deviationNew), String.join("☆",list));
+                                    }else{
+                                        keys.add(deviationNew);
+                                        values.add(String.join("☆",list));
+                                    }
+                                }
                             }
                         }
 

+ 64 - 0
blade-service/blade-user/src/main/java/org/springblade/system/user/controller/UserController.java

@@ -751,4 +751,68 @@ public class UserController {
         }
         return this.getLoginInfo(Authorization, userInfo);
     }
+
+
+    /**
+     * 项目内部获取用户接口
+     * @param account
+     * @param type
+     * @param tenantId
+     * @param request
+     * @return
+     */
+    @PostMapping("/loginByToken4")
+    @ApiOperationSupport(order = 20)
+    @ApiOperation(value = "token验证加密", notes = "token验证登录")
+    public R loginByToken4(String account,Integer type, String tenantId, HttpServletRequest request) {
+        if(account==null || Func.isNull(account) || Func.isEmpty(account)){
+            return R.fail("account值不能为空");
+        }
+        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
+        queryWrapper.eq("account", account);
+        queryWrapper.eq("sys_type", type == null ? 2 : type);
+        if(StringUtil.isNotBlank(tenantId)){
+            queryWrapper.eq("tenant_id", tenantId);
+        }
+        queryWrapper.last("limit 1");
+        User userInfo = userService.getOne(queryWrapper);
+        if (userInfo == null) {
+            return R.fail("用户名或密码错误");
+        }
+
+        String Authorization = request == null ? null : request.getHeader("Authorization");
+
+        if (Authorization == null || StringUtil.isEmpty(Authorization)) {
+            String useType = userInfo.getUserType();
+            List<String> strList = Func.toStrList(useType);
+            for(String sys_id:strList){
+                String dataInfo = "";
+                if(sys_id.equals("1")){ //质量/试验平台
+                    dataInfo ="client:client_secret";
+                }else if(sys_id.equals("2")){ //APP端
+                    dataInfo ="uni-app:app_secret";
+                }else if(sys_id.equals("3")){ //档案平台"
+                    dataInfo ="archives:archives_secret";
+                }else if(sys_id.equals("4")){ //后台管理端"
+                    dataInfo ="saber:saber_secret";
+                }else if(sys_id.equals("5")){ //成本管控系统"
+                    dataInfo ="hac:hac_secret";
+                }else if(sys_id.equals("6")){ //征拆系统"
+                    dataInfo ="lar:lar_secret";
+                }else if(sys_id.equals("7")){ //计量系统"
+                    dataInfo ="measure:measure_secret";
+                }else if(sys_id.equals("8")){ //安全系统"
+                    dataInfo ="measure:measure_secret";
+                }
+                Authorization = "Basic "+Func.encodeBase64(dataInfo);
+                //Basic bWVhc3VyZTptZWFzdXJlX3NlY3JldA==
+                //Basic bWVhc3VyZTptZWFzdXJlX3NlY3JldA==
+                R loginInfo = this.getLoginInfo(Authorization, userInfo);
+                if(loginInfo.getCode()==200){
+                    return loginInfo;
+                }
+            }
+        }
+        return this.getLoginInfo(Authorization,userInfo);
+    }
 }

+ 20 - 20
blade-service/blade-user/src/main/java/org/springblade/system/user/controller/WbsTreeController.java

@@ -79,18 +79,18 @@ public class WbsTreeController extends BladeController {
         } else if (("2").equals(classifyType)) {
             dataInfoId = contractIdRelation + "_" + parentId + "_" + "1" + "_" + tableOwner;
         }
-        Object data = null;
-        if (ObjectUtil.isNotEmpty(dataInfoId)) {
-            if (("2").equals(classifyType) && ObjectUtil.isNotEmpty(contractIdRelation)) {
-                data = redisTemplate.opsForValue().get("blade-manager::contract:wbstree:" + dataInfoId);
-            } else if (("1").equals(classifyType)) {
-                data = redisTemplate.opsForValue().get("blade-manager::contract:wbstree:" + dataInfoId);
-                redisTemplate.delete("blade-manager::contract:wbstree:" + dataInfoId);
-            }
-        }
-        if (data != null) {
-            vos = JSON.parseArray(data.toString(), WbsTreeContractLazyVO.class);
-        } else {
+//        Object data = null;
+//        if (ObjectUtil.isNotEmpty(dataInfoId)) {
+//            if (("2").equals(classifyType) && ObjectUtil.isNotEmpty(contractIdRelation)) {
+//                data = redisTemplate.opsForValue().get("blade-manager::contract:wbstree:" + dataInfoId);
+//            } else if (("1").equals(classifyType)) {
+//                data = redisTemplate.opsForValue().get("blade-manager::contract:wbstree:" + dataInfoId);
+//                redisTemplate.delete("blade-manager::contract:wbstree:" + dataInfoId);
+//            }
+//        }
+//        if (data != null) {
+//            vos = JSON.parseArray(data.toString(), WbsTreeContractLazyVO.class);
+//        } else {
             vos = iUserService.lazyQueryContractWbsTree(parentId, contractId, contractIdRelation, tableOwner,description);
             if (vos != null && ObjectUtil.isNotEmpty(dataInfoId)) {
 
@@ -106,14 +106,14 @@ public class WbsTreeController extends BladeController {
                 //对结果进行排序
                 vos.sort(safeComparator);
 
-                if (("2").equals(classifyType) && ObjectUtil.isNotEmpty(contractIdRelation)) {
-                    JSONArray array = JSONArray.parseArray(JSON.toJSONString(vos));
-                    redisTemplate.opsForValue().set("blade-manager::contract:wbstree:" + dataInfoId, JSON.toJSON(array).toString());
-                } else if (("1").equals(classifyType)) {
-                    JSONArray array = JSONArray.parseArray(JSON.toJSONString(vos));
-                    redisTemplate.opsForValue().set("blade-manager::contract:wbstree:" + dataInfoId, JSON.toJSON(array).toString());
-                }
-            }
+//                if (("2").equals(classifyType) && ObjectUtil.isNotEmpty(contractIdRelation)) {
+//                    JSONArray array = JSONArray.parseArray(JSON.toJSONString(vos));
+//                    redisTemplate.opsForValue().set("blade-manager::contract:wbstree:" + dataInfoId, JSON.toJSON(array).toString());
+//                } else if (("1").equals(classifyType)) {
+//                    JSONArray array = JSONArray.parseArray(JSON.toJSONString(vos));
+//                    redisTemplate.opsForValue().set("blade-manager::contract:wbstree:" + dataInfoId, JSON.toJSON(array).toString());
+//                }
+//            }
         }
         return R.data(vos);
     }

+ 14 - 0
blade-service/blade-user/src/main/java/org/springblade/system/user/feign/UserClient.java

@@ -16,12 +16,15 @@
  */
 package org.springblade.system.user.feign;
 
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.AllArgsConstructor;
 import org.springblade.core.tenant.annotation.NonDS;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.manager.dto.SaveUserInfoByProjectDTO;
+import org.springblade.system.user.bean.ResultCYData;
+import org.springblade.system.user.controller.UserController;
 import org.springblade.system.user.dto.UserDTO;
 import org.springblade.system.user.entity.User;
 import org.springblade.system.user.entity.UserInfo;
@@ -46,6 +49,7 @@ import java.util.List;
 public class UserClient implements IUserClient {
 
     private final IUserService service;
+    private final UserController userController;
 
     @Override
     public List<User> findUserInfoList() {
@@ -149,5 +153,15 @@ public class UserClient implements IUserClient {
         service.clearContractLocalCacheAndRedisCache();
     }
 
+    @Override
+    public String getTokenByUser(String account) {
+        R r = userController.loginByToken4(account, 1,"000000",null);
+        if(r.isSuccess()){
+            JSONObject data = (JSONObject) r.getData();
+            return (String) data.get("access_token");
+        } else {
 
+            return null;
+        }
+    }
 }

+ 214 - 180
blade-service/blade-user/src/main/java/org/springblade/system/user/service/impl/UserServiceImpl.java

@@ -13,10 +13,7 @@ import lombok.AllArgsConstructor;
 import org.apache.http.client.utils.DateUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springblade.business.entity.InformationQuery;
-import org.springblade.business.entity.Task;
-import org.springblade.business.entity.TaskParallel;
-import org.springblade.business.entity.TreeContractFirst;
+import org.springblade.business.entity.*;
 import org.springblade.business.vo.InformationQueryVO;
 import org.springblade.business.vo.QueryProcessDataVO;
 import org.springblade.common.constant.CommonConstant;
@@ -797,84 +794,73 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
                     }
                     if (lazyNodes.size() > 0) {
                         /*获取当前合同段节点本地缓存信息*/
-                        List<WbsTreeContractLazyVO> nodesAll = this.getNodeAll(contractId);
-                        List<WbsTreeContractLazyVO> distinctNodesAll = nodesAll.stream()
-                                .collect(Collectors.collectingAndThen(
-                                        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(WbsTreeContractLazyVO::getPKeyId))),
-                                        ArrayList::new
-                                ));
-                        List<WbsTreeContractLazyVO> distinctLowestNodesAll = distinctNodesAll.stream().filter(f -> f.getHasChildren().equals(0))
-                                .collect(Collectors.collectingAndThen(
-                                        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(WbsTreeContractLazyVO::getPKeyId))),
-                                        ArrayList::new
-                                ));
-
-                        /*获取当前合同段节点对应的资料填报QueryInfo本地缓存信息*/
-                        List<WbsTreeContractLazyQueryInfoVO> queryInfoList = this.getQueryInfoList(contractId, tableOwner);
-                        Map<Long, Integer> queryInfoMaps = queryInfoList.stream().filter(f -> Func.isNotEmpty(f.getWbsId())&&Func.isNotEmpty(f.getStatus()))
-                                .collect(Collectors.toMap(WbsTreeContractLazyQueryInfoVO::getWbsId, WbsTreeContractLazyQueryInfoVO::getStatus, (existingValue, newValue) -> existingValue));
-//                        List<Long> pKeyIdList = new ArrayList<>(queryInfoMaps.keySet());
-
-                        /* ================ 处理数量 ================ */
-                        List<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()
-                                .peek(vo -> {
-                                    Integer colorStatus = queryInfoMaps.get(vo.getPKeyId());
-                                    if (colorStatus != null) {
-                                        vo.setColorStatus(colorStatus == 0 ? 2 : (colorStatus == 1 ? 3 : (colorStatus == 2 ? 4 : 2)));
-                                    } else {
-                                        vo.setColorStatus(1);
-                                    }
-                                }).collect(Collectors.toMap(WbsTreeContractLazyVO::getPKeyId, Function.identity()));
-
-                        /* ================ 处理颜色 ================ */
-                        long startTime = System.currentTimeMillis();
-//                        List<NodeVO> nodeVOList = distinctNodesAll.stream().map(this::convertToNodeVO).collect(Collectors.toList());
-//                        Map<Long, NodeVO> nodeVOMap = nodeVOList.stream().collect(Collectors.toMap(NodeVO::getId, vo -> vo, (existing, replacement) -> existing));
-//                        List<NodeVO> treeNodeVOList = this.buildNodeTreeByStream1(distinctNodesAll, lowestNodesMap);
-//                        NodeVO.calculateStatusToDFS(treeNodeVOList, nodeVOMap);
-                        Map<Long, Integer> nodeColorStatusMap = new HashMap<>();
-//                        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");
+//                        List<WbsTreeContractLazyVO> nodesAll = this.getNodeAll(contractId);
+//                        List<WbsTreeContractLazyVO> distinctNodesAll = nodesAll.stream()
+//                                .collect(Collectors.collectingAndThen(
+//                                        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(WbsTreeContractLazyVO::getPKeyId))),
+//                                        ArrayList::new
+//                                ));
+//                        List<WbsTreeContractLazyVO> distinctLowestNodesAll = distinctNodesAll.stream().filter(f -> f.getHasChildren().equals(0))
+//                                .collect(Collectors.collectingAndThen(
+//                                        Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(WbsTreeContractLazyVO::getPKeyId))),
+//                                        ArrayList::new
+//                                ));
+//
+//                        /*获取当前合同段节点对应的资料填报QueryInfo本地缓存信息*/
+//                        List<WbsTreeContractLazyQueryInfoVO> queryInfoList = this.getQueryInfoList(contractId, tableOwner);
+//                        Map<Long, Integer> queryInfoMaps = queryInfoList.stream().filter(f -> Func.isNotEmpty(f.getWbsId())&&Func.isNotEmpty(f.getStatus()))
+//                                .collect(Collectors.toMap(WbsTreeContractLazyQueryInfoVO::getWbsId, WbsTreeContractLazyQueryInfoVO::getStatus, (existingValue, newValue) -> existingValue));
+////                        List<Long> pKeyIdList = new ArrayList<>(queryInfoMaps.keySet());
+//
+//                        /* ================ 处理数量 ================ */
+//                        List<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()
+//                                .peek(vo -> {
+//                                    Integer colorStatus = queryInfoMaps.get(vo.getPKeyId());
+//                                    if (colorStatus != null) {
+//                                        vo.setColorStatus(colorStatus == 0 ? 2 : (colorStatus == 1 ? 3 : (colorStatus == 2 ? 4 : 2)));
+//                                    } else {
+//                                        vo.setColorStatus(1);
+//                                    }
+//                                }).collect(Collectors.toMap(WbsTreeContractLazyVO::getPKeyId, Function.identity()));
+//
+//                        /* ================ 处理颜色 ================ */
+//                        long startTime = System.currentTimeMillis();
+////                        List<NodeVO> nodeVOList = distinctNodesAll.stream().map(this::convertToNodeVO).collect(Collectors.toList());
+////                        Map<Long, NodeVO> nodeVOMap = nodeVOList.stream().collect(Collectors.toMap(NodeVO::getId, vo -> vo, (existing, replacement) -> existing));
+////                        List<NodeVO> treeNodeVOList = this.buildNodeTreeByStream1(distinctNodesAll, lowestNodesMap);
+////                        NodeVO.calculateStatusToDFS(treeNodeVOList, nodeVOMap);
+//                        Map<Long, Integer> nodeColorStatusMap = new HashMap<>();
+////                        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<>();
-                            for (WbsTreeContractLazyVO node : resultParentNodesTB) {
-                                Long key = node.getPKeyId();
-                                if (countMap.containsKey(key)) {
-                                    countMap.put(key, countMap.get(key) + 1);
-                                } else {
-                                    countMap.put(key, 1);
-                                }
-                            }
-                            for (WbsTreeContractLazyVO lazyNodeVO : lazyNodes) {
+//                        if (lazyNodes.size() > 0) {
+//                            Map<Long, Integer> countMap = new HashMap<>();
+//                            for (WbsTreeContractLazyVO node : resultParentNodesTB) {
+//                                Long key = node.getPKeyId();
+//                                if (countMap.containsKey(key)) {
+//                                    countMap.put(key, countMap.get(key) + 1);
+//                                } else {
+//                                    countMap.put(key, 1);
+//                                }
+//                            }
+                        String pKeyIds = lazyNodes.stream().map(item -> item.getPKeyId() + "").collect(Collectors.joining(","));
+                        List<WbsTreeContractStatistics> wbsTreeContractStatisticsList = jdbcTemplate.query("select id, leaf_num, fill_num, approve_num, complete_num,jl_fill_num, jl_approve_num, jl_complete_num from m_wbs_tree_contract_statistics where id in (" + pKeyIds + ")",
+                                new BeanPropertyRowMapper<>(WbsTreeContractStatistics.class));
+                        Map<Long, WbsTreeContractStatistics> wbsTreeContractStatisticsMap = wbsTreeContractStatisticsList.stream().collect(Collectors.toMap(WbsTreeContractStatistics::getId, item -> item));
+                        setPrivateTemplate(lazyNodes);
+                        for (WbsTreeContractLazyVO lazyNodeVO : lazyNodes) {
                                 if(lazyNodeVO.getIsCustom()!=null&&lazyNodeVO.getIsCustom()==1){
                                     lazyNodeVO.setPrivateTemplate("当前节点为自定义节点,无法定位后管位置");
-                                }else {
-                                    try {
-                                        if(lazyNodeVO.getIsTypePrivatePid()!=null){
-                                            String privateSql="select p_key_id, ancestors_p_id from m_wbs_tree_private where p_key_id="+lazyNodeVO.getIsTypePrivatePid()+" and is_deleted=0";
-                                            WbsTreePrivate ancestor = jdbcTemplate.queryForObject(privateSql,new BeanPropertyRowMapper<>(WbsTreePrivate.class));
-                                            String ancestorsPId=ancestor.getAncestorsPId()+","+ancestor.getPKeyId();
-                                            String privateNodeNameSql="select node_name from m_wbs_tree_private where p_key_id in ("+ancestorsPId+")";
-                                            List<String> wbsTreePrivates = jdbcTemplate.query(privateNodeNameSql,new SingleColumnRowMapper<>(String.class));
-                                            if(wbsTreePrivates.size()>0){
-                                                String result = wbsTreePrivates.stream().collect(Collectors.joining("/"));
-                                                lazyNodeVO.setPrivateTemplate(result);
-                                            }
-                                        }
-                                    } catch (Exception e) {
-                                        lazyNodeVO.setPrivateTemplate("");
-                                    }
                                 }
                                 lazyNodeVO.setNotExsitChild(!lazyNodeVO.getHasChildren().equals(1));
                                 lazyNodeVO.setPrimaryKeyId(lazyNodeVO.getPKeyId());
@@ -883,25 +869,32 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
                                         lazyNodeVO.setTitle(contractInfo.getContractName());
                                     }
                                 }
-
-                                lazyNodeVO.setSubmitCounts(cn.hutool.core.util.ObjectUtil.isNotEmpty(countMap.get(lazyNodeVO.getPKeyId())) ? countMap.get(lazyNodeVO.getPKeyId()) : (cn.hutool.core.util.ObjectUtil.isNotEmpty(queryInfoMaps.get(lazyNodeVO.getPKeyId())) ? 1 : 0));
-
-                                if (lazyNodeVO.getSubmitCounts().equals(0)) {
-                                    lazyNodeVO.setColorStatus(1);
-                                    continue;
-                                }
-
-                                Integer parentColorStatus = nodeColorStatusMap.get(lazyNodeVO.getPKeyId());
-                                if (parentColorStatus != null) {
-                                    lazyNodeVO.setColorStatus(parentColorStatus);
+                                WbsTreeContractStatistics statistics = wbsTreeContractStatisticsMap.get(lazyNodeVO.getPKeyId());
+                                if (statistics != null) {
+                                    lazyNodeVO.setSubmitCounts(statistics.calculateSubmitNums(tableOwner));
+                                    lazyNodeVO.setColorStatus(statistics.calculateColorStatus(tableOwner));
                                 } else {
-                                    WbsTreeContractLazyVO lowestNode = lowestNodesMap.get(lazyNodeVO.getPKeyId());
-                                    if (lowestNode != null) {
-                                        lazyNodeVO.setColorStatus(lowestNode.getColorStatus());
-                                    }
+                                    lazyNodeVO.setSubmitCounts(0);
+                                    lazyNodeVO.setColorStatus(1);
                                 }
-
-                            }
+//                                lazyNodeVO.setSubmitCounts(cn.hutool.core.util.ObjectUtil.isNotEmpty(countMap.get(lazyNodeVO.getPKeyId())) ? countMap.get(lazyNodeVO.getPKeyId()) : (cn.hutool.core.util.ObjectUtil.isNotEmpty(queryInfoMaps.get(lazyNodeVO.getPKeyId())) ? 1 : 0));
+
+//                                if (lazyNodeVO.getSubmitCounts().equals(0)) {
+//                                    lazyNodeVO.setColorStatus(1);
+//                                    continue;
+//                                }
+//
+//                                Integer parentColorStatus = nodeColorStatusMap.get(lazyNodeVO.getPKeyId());
+//                                if (parentColorStatus != null) {
+//                                    lazyNodeVO.setColorStatus(parentColorStatus);
+//                                } else {
+//                                    WbsTreeContractLazyVO lowestNode = lowestNodesMap.get(lazyNodeVO.getPKeyId());
+//                                    if (lowestNode != null) {
+//                                        lazyNodeVO.setColorStatus(lowestNode.getColorStatus());
+//                                    }
+//                                }
+
+//                            }
                         }
                         return lazyNodes;
                     }
@@ -943,77 +936,65 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
 //                                    " ORDER BY a.sort,title,a.create_time";
                             List<WbsTreeContractLazyVO> lazyNodes = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
                             if (lazyNodes.size() > 0) {
-                                List<WbsTreeContractLazyVO> nodesAll = this.getNodeAll(sgContractId);
-                                List<WbsTreeContractLazyVO> distinctNodesAll = nodesAll.stream()
-                                        .collect(Collectors.collectingAndThen(
-                                                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(WbsTreeContractLazyVO::getPKeyId))),
-                                                ArrayList::new
-                                        ));
-                                List<WbsTreeContractLazyVO> distinctLowestNodesAll = distinctNodesAll.stream().filter(f -> f.getHasChildren().equals(0))
-                                        .collect(Collectors.collectingAndThen(
-                                                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(WbsTreeContractLazyVO::getPKeyId))),
-                                                ArrayList::new
-                                        ));
-
-                                List<WbsTreeContractLazyQueryInfoVO> queryInfoList = this.getQueryInfoList(sgContractId, tableOwner);
-
-                                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<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()
-                                        .peek(vo -> {
-                                            Integer colorStatus = queryInfoMaps.get(vo.getPKeyId());
-                                            if (colorStatus != null) {
-                                                vo.setColorStatus(colorStatus == 0 ? 2 : (colorStatus == 1 ? 3 : (colorStatus == 2 ? 4 : 2)));
-                                            } else {
-                                                vo.setColorStatus(1);
-                                            }
-                                        }).collect(Collectors.toMap(WbsTreeContractLazyVO::getPKeyId, Function.identity()));
-
-//                                List<NodeVO> nodeVOList = distinctNodesAll.stream().map(this::convertToNodeVO).collect(Collectors.toList());
-//                                Map<Long, NodeVO> nodeVOMap = nodeVOList.stream().collect(Collectors.toMap(NodeVO::getId, vo -> vo, (existing, replacement) -> existing));
-//                                List<NodeVO> treeNodeVOList = this.buildNodeTreeByStream1(distinctNodesAll, lowestNodesMap);
-//                                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);
-//                                buildNodeTreeByStream(distinctNodesAll, lowestNodesMap, nodeColorStatusMap);
-                                buildNodeTreeAndCalculateStatus(distinctNodesAll, lowestNodesMap, nodeColorStatusMap);
-                                if (lazyNodes.size() > 0) {
-                                    Map<Long, Integer> countMap = new HashMap<>();
-                                    for (WbsTreeContractLazyVO node : resultParentNodesTB) {
-                                        Long key = node.getPKeyId();
-                                        if (countMap.containsKey(key)) {
-                                            countMap.put(key, countMap.get(key) + 1);
-                                        } else {
-                                            countMap.put(key, 1);
-                                        }
-                                    }
-
+//                                List<WbsTreeContractLazyVO> nodesAll = this.getNodeAll(sgContractId);
+//                                List<WbsTreeContractLazyVO> distinctNodesAll = nodesAll.stream()
+//                                        .collect(Collectors.collectingAndThen(
+//                                                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(WbsTreeContractLazyVO::getPKeyId))),
+//                                                ArrayList::new
+//                                        ));
+//                                List<WbsTreeContractLazyVO> distinctLowestNodesAll = distinctNodesAll.stream().filter(f -> f.getHasChildren().equals(0))
+//                                        .collect(Collectors.collectingAndThen(
+//                                                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(WbsTreeContractLazyVO::getPKeyId))),
+//                                                ArrayList::new
+//                                        ));
+//
+//                                List<WbsTreeContractLazyQueryInfoVO> queryInfoList = this.getQueryInfoList(sgContractId, tableOwner);
+//
+//                                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<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()
+//                                        .peek(vo -> {
+//                                            Integer colorStatus = queryInfoMaps.get(vo.getPKeyId());
+//                                            if (colorStatus != null) {
+//                                                vo.setColorStatus(colorStatus == 0 ? 2 : (colorStatus == 1 ? 3 : (colorStatus == 2 ? 4 : 2)));
+//                                            } else {
+//                                                vo.setColorStatus(1);
+//                                            }
+//                                        }).collect(Collectors.toMap(WbsTreeContractLazyVO::getPKeyId, Function.identity()));
+//
+////                                List<NodeVO> nodeVOList = distinctNodesAll.stream().map(this::convertToNodeVO).collect(Collectors.toList());
+////                                Map<Long, NodeVO> nodeVOMap = nodeVOList.stream().collect(Collectors.toMap(NodeVO::getId, vo -> vo, (existing, replacement) -> existing));
+////                                List<NodeVO> treeNodeVOList = this.buildNodeTreeByStream1(distinctNodesAll, lowestNodesMap);
+////                                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);
+////                                buildNodeTreeByStream(distinctNodesAll, lowestNodesMap, nodeColorStatusMap);
+//                                buildNodeTreeAndCalculateStatus(distinctNodesAll, lowestNodesMap, nodeColorStatusMap);
+//                                if (lazyNodes.size() > 0) {
+//                                    Map<Long, Integer> countMap = new HashMap<>();
+//                                    for (WbsTreeContractLazyVO node : resultParentNodesTB) {
+//                                        Long key = node.getPKeyId();
+//                                        if (countMap.containsKey(key)) {
+//                                            countMap.put(key, countMap.get(key) + 1);
+//                                        } else {
+//                                            countMap.put(key, 1);
+//                                        }
+//                                    }
+                                String pKeyIds = lazyNodes.stream().map(item -> item.getPKeyId() + "").collect(Collectors.joining(","));
+                                List<WbsTreeContractStatistics> wbsTreeContractStatisticsList = jdbcTemplate.query("select id, leaf_num, fill_num, approve_num, complete_num,jl_fill_num, jl_approve_num, jl_complete_num  from m_wbs_tree_contract_statistics where id in (" + pKeyIds + ")",
+                                        new BeanPropertyRowMapper<>(WbsTreeContractStatistics.class));
+                                Map<Long, WbsTreeContractStatistics> wbsTreeContractStatisticsMap = wbsTreeContractStatisticsList.stream().collect(Collectors.toMap(WbsTreeContractStatistics::getId, item -> item));
+                                setPrivateTemplate(lazyNodes);
                                     for (WbsTreeContractLazyVO lazyNodeVO : lazyNodes) {
                                         if(lazyNodeVO.getIsCustom()!=null&&lazyNodeVO.getIsCustom()==1){
                                             lazyNodeVO.setPrivateTemplate("当前节点为自定义节点,无法定位后管位置");
-                                        }else {
-                                            try {
-                                                if(lazyNodeVO.getIsTypePrivatePid()!=null){
-                                                    String privateSql="select p_key_id, ancestors_p_id from m_wbs_tree_private where p_key_id="+lazyNodeVO.getIsTypePrivatePid()+" and is_deleted=0";
-                                                    WbsTreePrivate ancestor = jdbcTemplate.queryForObject(privateSql,new BeanPropertyRowMapper<>(WbsTreePrivate.class));
-                                                    String ancestorsPId=ancestor.getAncestorsPId()+","+ancestor.getPKeyId();
-                                                    String privateNodeNameSql="select node_name from m_wbs_tree_private where p_key_id in ("+ancestorsPId+")";
-                                                    List<String> wbsTreePrivates = jdbcTemplate.query(privateNodeNameSql,new SingleColumnRowMapper<>(String.class));
-                                                    if(wbsTreePrivates.size()>0){
-                                                        String result = wbsTreePrivates.stream().collect(Collectors.joining("/"));
-                                                        lazyNodeVO.setPrivateTemplate(result);
-                                                    }
-                                                }
-                                            } catch (Exception e) {
-                                                lazyNodeVO.setPrivateTemplate("");
-                                            }
                                         }
                                         lazyNodeVO.setType(lazyNodeVO.getNodeType());
                                         lazyNodeVO.setNotExsitChild(!lazyNodeVO.getHasChildren().equals(1));
@@ -1024,24 +1005,31 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
                                                 lazyNodeVO.setTitle(sgContractInfo.getContractName());
                                             }
                                         }
-
-                                        lazyNodeVO.setSubmitCounts(cn.hutool.core.util.ObjectUtil.isNotEmpty(countMap.get(lazyNodeVO.getPKeyId())) ? countMap.get(lazyNodeVO.getPKeyId()) : (cn.hutool.core.util.ObjectUtil.isNotEmpty(queryInfoMaps.get(lazyNodeVO.getPKeyId())) ? 1 : 0));
-                                        if (lazyNodeVO.getSubmitCounts().equals(0)) {
-                                            lazyNodeVO.setColorStatus(1);
-                                            continue;
-                                        }
-
-                                        Integer parentColorStatus = nodeColorStatusMap.get(lazyNodeVO.getPKeyId());
-                                        if (parentColorStatus != null) {
-                                            lazyNodeVO.setColorStatus(parentColorStatus);
+                                        WbsTreeContractStatistics statistics = wbsTreeContractStatisticsMap.get(lazyNodeVO.getPKeyId());
+                                        if (statistics != null) {
+                                            lazyNodeVO.setSubmitCounts(statistics.calculateSubmitNums(tableOwner));
+                                            lazyNodeVO.setColorStatus(statistics.calculateColorStatus(tableOwner));
                                         } else {
-                                            WbsTreeContractLazyVO lowestNode = lowestNodesMap.get(lazyNodeVO.getPKeyId());
-                                            if (lowestNode != null) {
-                                                lazyNodeVO.setColorStatus(lowestNode.getColorStatus());
-                                            }
+                                            lazyNodeVO.setSubmitCounts(0);
+                                            lazyNodeVO.setColorStatus(1);
                                         }
-
-                                    }
+//                                        lazyNodeVO.setSubmitCounts(cn.hutool.core.util.ObjectUtil.isNotEmpty(countMap.get(lazyNodeVO.getPKeyId())) ? countMap.get(lazyNodeVO.getPKeyId()) : (cn.hutool.core.util.ObjectUtil.isNotEmpty(queryInfoMaps.get(lazyNodeVO.getPKeyId())) ? 1 : 0));
+//                                        if (lazyNodeVO.getSubmitCounts().equals(0)) {
+//                                            lazyNodeVO.setColorStatus(1);
+//                                            continue;
+//                                        }
+//
+//                                        Integer parentColorStatus = nodeColorStatusMap.get(lazyNodeVO.getPKeyId());
+//                                        if (parentColorStatus != null) {
+//                                            lazyNodeVO.setColorStatus(parentColorStatus);
+//                                        } else {
+//                                            WbsTreeContractLazyVO lowestNode = lowestNodesMap.get(lazyNodeVO.getPKeyId());
+//                                            if (lowestNode != null) {
+//                                                lazyNodeVO.setColorStatus(lowestNode.getColorStatus());
+//                                            }
+//                                        }
+
+//                                    }
                                 }
                                 lazyNodesAll.addAll(lazyNodes);
                             }
@@ -1053,6 +1041,52 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
         }
         return null;
     }
+    private void setPrivateTemplate(List<WbsTreeContractLazyVO> lazyNodes) {
+        if (lazyNodes != null && !lazyNodes.isEmpty()) {
+            try {
+                String privateIds = lazyNodes.stream().filter(vo -> vo.getIsTypePrivatePid() != null).map(vo -> vo.getIsTypePrivatePid() + "").distinct().collect(Collectors.joining(","));
+                List<WbsTreePrivate> query = new ArrayList<>();
+                if (!privateIds.isEmpty()) {
+                    String privateSql="select p_key_id, ancestors_p_id, node_name from m_wbs_tree_private where p_key_id in ("+privateIds+") and is_deleted=0";
+                    query = jdbcTemplate.query(privateSql, new BeanPropertyRowMapper<>(WbsTreePrivate.class));
+                    if (!query.isEmpty()) {
+                        Set<String> privateIdSet = new HashSet<>();
+                        query.forEach(wbsTreePrivate -> {
+                            String[] split = wbsTreePrivate.getAncestorsPId().split(",");
+                            for (String s : split) {
+                                if (StringUtils.isNotEmpty(s)) {
+                                    privateIdSet.add(s);
+                                }
+                            }
+                        });
+                        String privateNodeNameSql="select p_key_id, node_name from m_wbs_tree_private where p_key_id in ("+String.join(",",privateIdSet)+")";
+                        List<WbsTreePrivate> wbsTreePrivates = jdbcTemplate.query(privateNodeNameSql,new BeanPropertyRowMapper<>(WbsTreePrivate.class));
+                        query.addAll(wbsTreePrivates);
+                    }
+                }
+                Map<Long, WbsTreePrivate> map = query.stream().collect(Collectors.toMap(WbsTreePrivate::getPKeyId, v -> v, (v1, v2) -> v2));
+                lazyNodes.forEach(lazyNodeVO -> {
+                    WbsTreePrivate treePrivate = map.get(lazyNodeVO.getPKeyId());
+                    if (treePrivate == null || treePrivate.getAncestorsPId() == null) {
+                        lazyNodeVO.setPrivateTemplate("");
+                        return;
+                    }
+                    StringBuilder sb = new StringBuilder();
+                    String[] split = treePrivate.getAncestorsPId().split(",");
+                    for (String s : split) {
+                        WbsTreePrivate temp = map.get(Long.parseLong(s));
+                        if (temp == null || temp.getNodeName() == null) {
+                            continue;
+                        }
+                        sb.append(temp.getNodeName()).append("/");
+                    }
+                    lazyNodeVO.setPrivateTemplate(sb.deleteCharAt(sb.length() - 1).toString());
+                });
+            } catch (Exception e) {
+                lazyNodes.forEach(lazyNodeVO -> lazyNodeVO.setPrivateTemplate(""));
+            }
+        }
+    }
 
     /**
      * 非批量电签时,主动清理本地缓存,如资料填报保存、任务上报等

Някои файлове не бяха показани, защото твърде много файлове са промени