Prechádzať zdrojové kódy

Merge branch 'master' of http://121.41.40.202:3000/zhuwei/bladex

huangtf 1 rok pred
rodič
commit
7c53eb63c5
70 zmenil súbory, kde vykonal 2563 pridanie a 746 odobranie
  1. 5 0
      blade-ops-api/blade-resource-api/src/main/java/org/springblade/resource/feign/NewIOSSClient.java
  2. 10 0
      blade-ops/blade-resource/src/main/java/org/springblade/resource/feign/NewIOSSClientImpl.java
  3. 40 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/ArchiveConclusion.java
  4. 6 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/ArchivesAuto.java
  5. 46 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/ExpertInspection.java
  6. 6 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/feign/ArchiveAutoClient.java
  7. 22 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/vo/ArchiveInspectVO.java
  8. 19 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/vo/ArchivesAutoVO3.java
  9. 2 1
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/vo/CheckoutVO.java
  10. 24 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/vo/ExpertInspectionVO.java
  11. 53 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/vo/ProjectInspectStatVO.java
  12. 2 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/OperationLogVO.java
  13. 6 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ArchiveTreeContract.java
  14. 2 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ExcelEditCallback.java
  15. 7 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/SaveUserInfoByProjectClient.java
  16. 6 1
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/WbsTreeContractClient.java
  17. 7 8
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/FB02.java
  18. 68 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/InspectTreeVO.java
  19. 21 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/MyInspectTreeVO.java
  20. 1 1
      blade-service-api/blade-user-api/src/main/java/org/springblade/system/user/feign/IUserClient.java
  21. 149 3
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchivesAutoController.java
  22. 23 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/feign/ArchiveAutoClientImpl.java
  23. 16 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchiveConclusionMapper.java
  24. 16 2
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.java
  25. 54 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.xml
  26. 21 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ExpertInspectionMapper.java
  27. 9 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ExpertInspectionMapper.xml
  28. 24 3
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/IArchivesAutoService.java
  29. 15 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/IExpertInspectionService.java
  30. 408 12
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java
  31. 22 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ExpertInspectionServiceImpl.java
  32. 15 18
      blade-service/blade-business/src/main/java/org/springblade/business/controller/ContractTreeDrawingsController.java
  33. 7 2
      blade-service/blade-business/src/main/java/org/springblade/business/controller/OperationLogController.java
  34. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TaskController.java
  35. 1 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/ContractTreeDrawingsMapper.java
  36. 4 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/ContractTreeDrawingsMapper.xml
  37. 4 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/OperationLogMapper.java
  38. 6 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/OperationLogMapper.xml
  39. 2 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/UserOpinionFlowMapper.java
  40. 26 1
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/UserOpinionFlowMapper.xml
  41. 2 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/IContractTreeDrawingsService.java
  42. 2 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/IUserOpinionFlowService.java
  43. 35 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/ContractTreeDrawingsServiceImpl.java
  44. 73 16
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/InformationQueryServiceImpl.java
  45. 11 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/UserOpinionFlowServiceImpl.java
  46. 53 6
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/UserOpinionServiceImpl.java
  47. 63 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ArchiveTreeContractController.java
  48. 189 175
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java
  49. 28 57
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsParamController.java
  50. 3 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreeContractController.java
  51. 45 4
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreePrivateController.java
  52. 8 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/feign/SaveUserInfoByProjectClientImpl.java
  53. 7 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/feign/WbsTreeContractClientImpl.java
  54. 11 4
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeContractMapper.java
  55. 109 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeContractMapper.xml
  56. 20 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ProjectInfoMapper.xml
  57. 5 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreeContractMapper.java
  58. 88 66
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreeContractMapper.xml
  59. 9 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IArchiveTreeContractService.java
  60. 3 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IExcelTabService.java
  61. 3 4
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IFormulaService.java
  62. 2 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IWbsTreeContractService.java
  63. 109 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeContractServiceImpl.java
  64. 2 34
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ContractInfoServiceImpl.java
  65. 111 24
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java
  66. 50 27
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java
  67. 34 4
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ProjectInfoServiceImpl.java
  68. 308 252
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeContractServiceImpl.java
  69. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/utils/FileUtils.java
  70. 3 3
      blade-service/blade-manager/src/main/resources/application-dev.yml

+ 5 - 0
blade-ops-api/blade-resource-api/src/main/java/org/springblade/resource/feign/NewIOSSClient.java

@@ -9,6 +9,7 @@ import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.multipart.MultipartFile;
 
+import java.io.InputStream;
 import java.util.List;
 
 @FeignClient(value = AppConstant.APPLICATION_RESOURCE_NAME)
@@ -18,6 +19,7 @@ public interface NewIOSSClient {
     String UPLOAD_FILE_INFO = API_PREFIX + "/uploadFileInfo";
     String UPLOAD_FILE_INFO_BYTE = API_PREFIX + "/uploadFileInfoByte";
     String UPLOAD_FILE_INFO_INPUT_STREAM = API_PREFIX + "/uploadFileInfoInputStream";
+    String UPLOAD_FILE_INFO_INPUT_STREAM2 = API_PREFIX + "/uploadFileInfoInputStream2";
     String REMOVE_PDF_FILE = API_PREFIX + "/remove-file";
     String REMOVE_PDF_FILES = API_PREFIX + "/remove-files";
     String UPLOAD_FILE_INFO_WITH_PATH = API_PREFIX + "/uploadFileInfoWithPath";
@@ -25,6 +27,9 @@ public interface NewIOSSClient {
     @PostMapping(value = UPLOAD_FILE_INFO_INPUT_STREAM, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
     BladeFile uploadFileByInputStream(MultipartFile file);
 
+    @PostMapping(value = UPLOAD_FILE_INFO_INPUT_STREAM2)
+    BladeFile uploadFileByInputStream2(@RequestParam String OriginalFilename,@RequestParam InputStream inputStream);
+
     @PostMapping(UPLOAD_FILE_INFO)
     BladeFile uploadFile(@RequestParam String fileName, @RequestParam String localFileUrl);
 

+ 10 - 0
blade-ops/blade-resource/src/main/java/org/springblade/resource/feign/NewIOSSClientImpl.java

@@ -38,6 +38,16 @@ public class NewIOSSClientImpl implements NewIOSSClient {
         return null;
     }
 
+    @Override
+    public BladeFile uploadFileByInputStream2(String OriginalFilename, InputStream inputStream) {
+        try {
+            return this.ossBuilder.template().putFile(OriginalFilename, inputStream);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
     @Override
     public BladeFile updateFile(byte[] fileByte, String fileName) {
         try {

+ 40 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/ArchiveConclusion.java

@@ -0,0 +1,40 @@
+package org.springblade.archive.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @Param   档案结论表
+ * @Author wangwl
+ * @Date 2023/11/22 11:15
+ **/
+@Data
+@TableName("u_archive_conclusion")
+public class ArchiveConclusion implements Serializable {
+
+    @ApiModelProperty("主键id")
+    @TableId(
+            value = "id",
+            type = IdType.ASSIGN_ID
+    )
+    private Long id;
+
+    @ApiModelProperty("项目id")
+    private Long projectId;
+
+    @ApiModelProperty("专家id")
+    private Long expertId;
+
+    @ApiModelProperty("文档地址")
+    private String worldUrl;
+
+    @ApiModelProperty("文档PDF地址")
+    private String worldPdfUrl;
+
+
+}

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

@@ -172,6 +172,12 @@ public class ArchivesAuto extends BaseEntity {
     private Integer isReviewed;
     @ApiModelProperty("申请验收状态,0未申请或已申请1验收中")
     private Integer isApply;
+    @ApiModelProperty("整改状态 0默认1整改2合格")
+    private Integer updateStatus;
+    @ApiModelProperty(value = "专家id,逗号分隔")
+    private String expertId;
+    @ApiModelProperty("是否抽检,0未抽检1已抽检")
+    private Integer isInspect;
 
     //是否是影音
     public boolean isMedia() {

+ 46 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/ExpertInspection.java

@@ -0,0 +1,46 @@
+package org.springblade.archive.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.core.mp.base.BaseEntity;
+
+/**
+ * @Param   档案专家意见表
+ * @Author wangwl
+ * @Date 2023/11/16 14:49
+ **/
+@Data
+@TableName("u_archive_expert_inspection")
+@EqualsAndHashCode(callSuper = true)
+public class ExpertInspection extends BaseEntity {
+
+    @ApiModelProperty("项目id")
+    private Long projectId;
+
+    @ApiModelProperty("单位类型:1施工2监理3业主")
+    private Integer UnitType;
+
+    @ApiModelProperty("档案id")
+    private Long archiveId;
+
+    @ApiModelProperty("文件id")
+    private Long fileId;
+
+    @ApiModelProperty("抽检意见")
+    private String opinion;
+
+    @ApiModelProperty("专家id")
+    private Long expertId;
+
+    @ApiModelProperty("专家名称")
+    private String expertName;
+
+    @ApiModelProperty("案卷名称")
+    private String archiveName;
+
+    @ApiModelProperty("是否合格,0不合格1合格")
+    private Integer isPass;
+
+}

+ 6 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/feign/ArchiveAutoClient.java

@@ -37,4 +37,10 @@ public interface ArchiveAutoClient {
      */
     @PostMapping(API_PREFIX + "/batchUpdateIsApply")
     R<Boolean> batchUpdateIsApply(@RequestParam Integer isApply,@RequestParam List<Long> ids);
+
+    /**
+     * 批量修改档案专家,参数为节点集合
+     */
+    @PostMapping(API_PREFIX + "/batchUpdateExpertId")
+    R<Boolean> batchUpdateExpertId(@RequestParam String userId,@RequestParam List<Long> ids);
 }

+ 22 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/vo/ArchiveInspectVO.java

@@ -0,0 +1,22 @@
+package org.springblade.archive.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.archive.entity.ArchivesAuto;
+
+/**
+ * @Param
+ * @Author wangwl
+ * @Date 2023/11/15 16:04
+ **/
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class ArchiveInspectVO extends ArchivesAuto {
+    @ApiModelProperty("是否查阅名称")
+    private String inspectStatusName;
+
+    @ApiModelProperty("整改状态名称")
+    private String updateStatusName;
+
+}

+ 19 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/vo/ArchivesAutoVO3.java

@@ -0,0 +1,19 @@
+package org.springblade.archive.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.archive.entity.ArchivesAuto;
+
+/**
+ * @author wangwl 档案初检总统计,带档案单位
+ * @Date 2023/2/17 10:40
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class ArchivesAutoVO3 extends ArchivesAuto {
+
+    @ApiModelProperty("主节点")
+    private Integer unitType;
+
+}

+ 2 - 1
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/vo/CheckoutVO.java

@@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import org.springblade.archive.entity.ArchivesAuto;
 
+import java.io.Serializable;
 import java.util.List;
 
 /**
@@ -12,7 +13,7 @@ import java.util.List;
  * @Date 2023/8/23 14:52
  **/
 @Data
-public class CheckoutVO {
+public class CheckoutVO implements Serializable {
 
     @ApiModelProperty("节点名称")
     private String nodeName;

+ 24 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/vo/ExpertInspectionVO.java

@@ -0,0 +1,24 @@
+package org.springblade.archive.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.archive.entity.ExpertInspection;
+
+/**
+ * @Param   用于显示当前专家抽检记录
+ * @Author wangwl
+ * @Date 2023/11/17 11:57
+ **/
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class ExpertInspectionVO extends ExpertInspection {
+    @ApiModelProperty("抽检所属")
+    private String unitName;
+
+    @ApiModelProperty("所有意见")
+    private String allOpinion;
+
+    @ApiModelProperty("文件PDF")
+    private String filePdf;
+}

+ 53 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/vo/ProjectInspectStatVO.java

@@ -0,0 +1,53 @@
+package org.springblade.archive.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @Param   项目抽检统计返回
+ * @Author wangwl
+ * @Date 2023/11/17 14:31
+ **/
+@Data
+public class ProjectInspectStatVO implements Serializable {
+    @ApiModelProperty("预警提示")
+    private String tips;
+
+    @ApiModelProperty("总抽检率")
+    private String totalInspectRatio;
+
+    @ApiModelProperty("整改状态名称")
+    private List<ProjectInspectStatVO.UnitGroup> list;
+
+    @Data
+    public static class UnitGroup {
+        @ApiModelProperty("分组")
+        private String name;
+
+        @ApiModelProperty("总案卷")
+        private Integer total;
+
+        @ApiModelProperty("已抽检")
+        private Integer endInspect;
+
+        @ApiModelProperty("需整改")
+        private Integer needUpdate;
+
+        @ApiModelProperty("抽检率")
+        private String inspectRatio;
+
+        public UnitGroup() {
+        }
+
+        public UnitGroup(Integer total, Integer endInspect, Integer needUpdate, String inspectRatio) {
+            this.total = total;
+            this.endInspect = endInspect;
+            this.needUpdate = needUpdate;
+            this.inspectRatio = inspectRatio;
+        }
+    }
+
+}

+ 2 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/OperationLogVO.java

@@ -47,4 +47,6 @@ public class OperationLogVO extends OperationLog {
     @ApiModelProperty("结束时间")
     private String endTime;
 
+    private Long contractId;
+
 }

+ 6 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ArchiveTreeContract.java

@@ -227,6 +227,12 @@ public class ArchiveTreeContract extends BaseEntity {
      */
     private Integer classify;
 
+    @ApiModelProperty(value = "专家id,逗号分隔")
+    private String expertId;
+
+    @ApiModelProperty(value = "专家名称,逗号分隔")
+    private String expertName;
+
 
     public ArchiveTreeContract() {
     }

+ 2 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ExcelEditCallback.java

@@ -20,4 +20,6 @@ public class ExcelEditCallback {
     // 返回码
     private Integer error;
 
+    private Long projectId;
+
 }

+ 7 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/SaveUserInfoByProjectClient.java

@@ -20,6 +20,7 @@ public interface SaveUserInfoByProjectClient {
      */
     String SEARCH_USER_INFO_AND_PROJECT = "/api/manager/searchUserInfoAndProject";
     String SEARCH_USER_INFO_AND_PROJECT2 = "/api/manager/searchUserInfoAndProject2";
+    String SEARCH_USER_INFO_AND_PROJECT_BY_USER_IDS = "/api/manager/searchUserInfoAndProjectByUserIds";
     String QUERY_USER_CONTRACT_ROLE = "/api/manager/queryUserContractRole";
     String SAVE_INFO_RELATION = "/api/manager/saveInfoRelation";
 
@@ -38,6 +39,12 @@ public interface SaveUserInfoByProjectClient {
     @GetMapping(SEARCH_USER_INFO_AND_PROJECT2)
     List<SaveUserInfoByProjectDTO> searchUserInfoAndProject2(@RequestParam("userId") String userId);
 
+    /**
+     * 获取用户引用项目合同角色信息
+     */
+    @PostMapping(SEARCH_USER_INFO_AND_PROJECT_BY_USER_IDS)
+    List<SaveUserInfoByProjectDTO> searchUserInfoAndProjectByUserIds(@RequestBody List<Long> userIds);
+
     /**
      * 保存用户项目角色关联信息
      */

+ 6 - 1
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/WbsTreeContractClient.java

@@ -181,5 +181,10 @@ public interface WbsTreeContractClient {
 
     //获取 节点下表单
     @GetMapping(API_PREFIX + "/searchNodeAllTableInfo")
-    List<AppWbsTreeContractVO> searchNodeAllTableInfo(@RequestParam String primaryKeyId, @RequestParam String type, @RequestParam String contractId, @RequestParam String projectId,@RequestParam Long userId);
+    List<AppWbsTreeContractVO> searchNodeAllTableInfo(@RequestParam String primaryKeyId, @RequestParam String type, @RequestParam String contractId, @RequestParam String projectId, @RequestParam Long userId);
+
+    /*删除合同段本地缓存*/
+    @GetMapping(API_PREFIX + "/deleteContractLocalCache")
+    void deleteContractLocalCache(@RequestParam String contractId);
+
 }

+ 7 - 8
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/FB02.java

@@ -28,7 +28,7 @@ public class FB02 {
     private Integer  rowSize=20;
     private List<FormData> fds = new ArrayList<>();
     private List<Item> datas = new ArrayList<>();
-    private Map<FormData, BiFunction<List<Item>,Integer,List<Object>>> fm = new HashMap<>();
+    private Map<String, BiFunction<List<Item>,Integer,List<Object>>> fm = new HashMap<>();
     private List<String> sqlList = new ArrayList<>();
 
 
@@ -70,19 +70,19 @@ public class FB02 {
          for(FormData fd:processFds){
               if(fd.getEName().contains("分项工程名称")){
                   this.subItem=fd;
-                  this.fm.put(fd,(List<Item> l,Integer pn)->l.stream().map(Item::getSubItem).collect(Collectors.toList()));
+                  this.fm.put(fd.getCode(),(List<Item> l,Integer pn)->l.stream().map(Item::getSubItem).collect(Collectors.toList()));
               }else if(fd.getEName().contains("序号")){
                   this.sn=fd;
-                  this.fm.put(fd,(List<Item> l,Integer pn)->IntStream.range(0, l.size()).boxed().map(i->i+pn*l.size()).collect(Collectors.toList()));
+                  this.fm.put(fd.getCode(),(List<Item> l,Integer pn)->IntStream.range(0, l.size()).boxed().map(i->i+pn*l.size()).collect(Collectors.toList()));
               }else if(fd.getEName().contains("实测项目")){
                   this.name=fd;
-                  this.fm.put(fd,(List<Item> l,Integer pn)->l.stream().map(Item::getName).collect(Collectors.toList()));
+                  this.fm.put(fd.getCode(),(List<Item> l,Integer pn)->l.stream().map(Item::getName).collect(Collectors.toList()));
               }else if(fd.getEName().contains("实测合格率")){
                   this.passRate=fd;
-                  this.fm.put(fd,(List<Item> l,Integer pn)->l.stream().map(Item::getPassRate).collect(Collectors.toList()));
+                  this.fm.put(fd.getCode(),(List<Item> l,Integer pn)->l.stream().map(Item::getPassRate).collect(Collectors.toList()));
               }else if(fd.getEName().trim().equals("权值")){
                   this.weight=fd;
-                  this.fm.put(fd,(List<Item> l,Integer pn)->l.stream().map(Item::getWeight).collect(Collectors.toList()));
+                  this.fm.put(fd.getCode(),(List<Item> l,Integer pn)->l.stream().map(Item::getWeight).collect(Collectors.toList()));
               }
               if(this.subItem!=null&&this.name!=null&&this.passRate!=null&&this.weight!=null&&this.sn!=null){
                   /*匹配完成*/
@@ -131,7 +131,6 @@ public class FB02 {
                     sb.append(putEd(k,v,fd,w)).append(StringPool.COMMA);
                 });
                 String template="update "+w.getInitTableName()+" set "+sb.deleteCharAt(sb.length()-1)+" where id ="+w.getPKeyId();
-                System.out.println("EUV:"+template);
                 sqlList.add(template);
             }
 
@@ -142,7 +141,7 @@ public class FB02 {
 
    /**把数据放到对应元素*/
     private String putEd(int pn,List<Item> items, FormData fd,WbsTreeContract w){
-        BiFunction<List<Item>,Integer,List<Object>> fc = this.fm.get(fd);
+        BiFunction<List<Item>,Integer,List<Object>> fc = this.fm.get(fd.getCode());
         if(fc!=null) {
             List<Object> data = fc.apply(items,pn);
             List<ElementData> list = new ArrayList<>();

+ 68 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/InspectTreeVO.java

@@ -0,0 +1,68 @@
+package org.springblade.manager.vo;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springblade.core.tool.node.INode;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @Param
+ * @Author wangwl
+ * @Date 2023/11/9 18:05
+ **/
+@Data
+public class InspectTreeVO implements INode<InspectTreeVO> {
+
+    /**
+     * 主键ID
+     */
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long id;
+
+    /**
+     * 父节点ID
+     */
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long parentId;
+
+    /**
+     * 子孙节点
+     */
+    @JsonInclude(JsonInclude.Include.NON_EMPTY)
+    private List<InspectTreeVO> children;
+
+    /**
+     * 是否有子孙节点
+     */
+    @JsonInclude(JsonInclude.Include.NON_EMPTY)
+    @ApiModelProperty(value = "false没有子节点,true有子节点")
+    private Boolean hasChildren;
+
+    @Override
+    public List<InspectTreeVO> getChildren() {
+        if (this.children == null) {
+            this.children = new ArrayList<>();
+        }
+        return this.children;
+    }
+
+    @ApiModelProperty(value = "是否选择0否1是")
+    private Integer isSelect;
+
+    @ApiModelProperty(value = "节点名称")
+    private String nodeName;
+
+
+    @ApiModelProperty(value = "分属专家")
+    private String nodeInfo;
+
+    @ApiModelProperty(value = "false没有子节点,true有子节点")
+    private Boolean isChildren;
+
+
+}

+ 21 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/MyInspectTreeVO.java

@@ -0,0 +1,21 @@
+package org.springblade.manager.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.manager.entity.ArchiveTreeContract;
+
+/**
+ * @Param
+ * @Author wangwl
+ * @Date 2023/11/15 15:35
+ **/
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class MyInspectTreeVO extends ArchiveTreeContract {
+    @ApiModelProperty(value = "节点名称")
+    private String title;
+
+    @ApiModelProperty(value = "false没有子节点,true有子节点")
+    private Boolean hasChildren;
+}

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

@@ -171,7 +171,7 @@ public interface IUserClient {
     @GetMapping(USER_INFO_ALL)
     List<User> selectUserAll();
 
-    @GetMapping(USER_LIST_INFO_BY_IDS)
+    @PostMapping(USER_LIST_INFO_BY_IDS)
     List<User> userInfoByIds(@RequestBody List<Long> userIds);
 
     @PostMapping(SAVE_USER_DTO)

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

@@ -25,6 +25,7 @@ import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import lombok.AllArgsConstructor;
 
 import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.validation.Valid;
 
@@ -33,11 +34,12 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang.StringUtils;
 import org.apache.http.message.BasicNameValuePair;
 import org.springblade.archive.dto.SaveApplyDTO;
+import org.springblade.archive.entity.ArchiveConclusion;
+import org.springblade.archive.entity.ExpertInspection;
 import org.springblade.archive.service.IArchiveAutoPdfService;
 import org.springblade.archive.utils.CallBgrsjk;
 import org.springblade.archive.utils.FileUtils;
-import org.springblade.archive.vo.ArchiveInspectPreviewVO;
-import org.springblade.archive.vo.CheckoutVO;
+import org.springblade.archive.vo.*;
 import org.springblade.business.entity.ArchiveFile;
 import org.springblade.business.entity.InformationQuery;
 import org.springblade.common.constant.CommonConstant;
@@ -49,10 +51,12 @@ import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.manager.entity.ArchiveTreeContract;
 import org.springblade.manager.entity.ContractInfo;
+import org.springblade.manager.entity.ExcelEditCallback;
 import org.springblade.manager.entity.ProjectInfo;
 import org.springblade.manager.feign.ArchiveTreeContractClient;
 import org.springblade.manager.feign.ContractClient;
 import org.springblade.manager.feign.ProjectClient;
+import org.springblade.manager.vo.MyInspectTreeVO;
 import org.springblade.system.cache.ParamCache;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.MediaType;
@@ -60,7 +64,6 @@ import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.RequestParam;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.springblade.archive.entity.ArchivesAuto;
-import org.springblade.archive.vo.ArchivesAutoVO;
 import org.springblade.archive.wrapper.ArchivesAutoWrapper;
 import org.springblade.archive.service.IArchivesAutoService;
 import org.springblade.core.boot.ctrl.BladeController;
@@ -764,4 +767,147 @@ public class ArchivesAutoController extends BladeController {
 		ArchiveInspectPreviewVO vo = archivesAutoService.getArchivesAutoViewByUnit(unitType,projectId,1);
 		return R.data(vo);
 	}
+
+	/**
+	 * 在线验收-查询节点已经上报的档案
+	 */
+	@GetMapping("/getNodeArchives")
+	@ApiOperationSupport(order = 31)
+	@ApiOperation(value = "档案在线验收-查询节点已经上报的档案", notes = "分页查询,传入当前节点id,搜索值,返回档案集合")
+	@ApiImplicitParams(value = {
+			@ApiImplicitParam(name = "projectId", value = "项目id", required = true),
+			@ApiImplicitParam(name = "nodeId", value = "当前节点id", required = true),
+			@ApiImplicitParam(name = "searchType", value = "搜索类型1档案名称2文件名称", required = true),
+			@ApiImplicitParam(name = "searchValue", value = "搜索值", required = false),
+			@ApiImplicitParam(name = "current", value = "当前页", required = true),
+			@ApiImplicitParam(name = "size", value = "每页的数量", required = true),
+			@ApiImplicitParam(name = "type", value = "树类型,所有案卷1,我验收的案卷2", required = true)
+	})
+	public R<IPage<ArchiveInspectVO>> getNodeArchives(Query query,@RequestParam Long nodeId,@RequestParam Long projectId,@RequestParam Integer searchType,@RequestParam String searchValue,@RequestParam Integer type) {
+		IPage<ArchiveInspectVO> list = archivesAutoService.getNodeArchives(query,nodeId,projectId,searchType,searchValue,type);
+		return R.data(list);
+	}
+
+	/**
+	 * 在线验收-专家抽检统计
+	 */
+	@GetMapping("/userInspectStats")
+	@ApiOperationSupport(order = 32)
+	@ApiOperation(value = "在线验收-专家抽检统计", notes = "传入项目id")
+	@ApiImplicitParams(value = {
+			@ApiImplicitParam(name = "projectId", value = "项目id", required = true)
+	})
+	public R<Map<String,String>> userInspectStats(@RequestParam Long projectId) {
+		Map<String, String> map = archivesAutoService.userInspectStats(projectId);
+		return R.data(map);
+	}
+
+	/**
+	 * 在线验收-修改抽检状态
+	 */
+	@GetMapping("/updateInspectStatus")
+	@ApiOperationSupport(order = 33)
+	@ApiOperation(value = "在线验收-修改抽检状态", notes = "在当前页面停留30秒再调接口:传入档案id,返回查阅完成,可以显示到页面")
+	@ApiImplicitParams(value = {
+			@ApiImplicitParam(name = "projectId", value = "项目id", required = true),
+			@ApiImplicitParam(name = "archiveId", value = "档案id", required = true)
+	})
+	public R updateInspectStatus(@RequestParam Long archiveId,@RequestParam Long projectId) {
+		archivesAutoService.updateInspectStatus(archiveId,projectId);
+		return R.data("当前案卷查阅完成");
+	}
+
+	/**
+	 * 在线验收-获取档案文件抽检意见
+	 */
+	@GetMapping("/getArchiveFileOpinion")
+	@ApiOperationSupport(order = 33)
+	@ApiOperation(value = "在线验收-获取档案文件抽检意见", notes = "传入项目id,文件id")
+	@ApiImplicitParams(value = {
+			@ApiImplicitParam(name = "projectId", value = "项目id", required = true),
+			@ApiImplicitParam(name = "fileId", value = "文件id", required = true)
+	})
+	public R<ExpertInspectionVO> getArchiveFileOpinion(@RequestParam Long fileId,@RequestParam Long projectId) {
+		ExpertInspectionVO vo = archivesAutoService.getArchiveFileOpinion(fileId, projectId);
+		return R.data(vo);
+	}
+
+	/**
+	 * 在线验收-保存抽检意见
+	 */
+	@PostMapping("/saveInspect")
+	@ApiOperationSupport(order = 34)
+	@ApiOperation(value = "在线验收-保存抽检意见", notes = "传入档案id,文件id,抽检意见")
+	@ApiImplicitParams(value = {
+			@ApiImplicitParam(name = "projectId", value = "项目id", required = true),
+			@ApiImplicitParam(name = "archiveId", value = "档案id", required = true),
+			@ApiImplicitParam(name = "fileId", value = "文件id", required = false),
+			@ApiImplicitParam(name = "opinion", value = "抽检意见", required = false)
+	})
+	public R saveInspect(@RequestBody ExpertInspection inspection) {
+		archivesAutoService.saveInspect(inspection);
+		return R.data("保存成功");
+	}
+
+	/**
+	 * 在线验收-专家抽检记录
+	 */
+	@GetMapping("/getUserInspectInfo")
+	@ApiOperationSupport(order = 35)
+	@ApiOperation(value = "在线验收-专家抽检记录", notes = "分页返回当前专家抽检记录:传入项目id")
+	@ApiImplicitParams(value = {
+			@ApiImplicitParam(name = "current", value = "当前页", required = true),
+			@ApiImplicitParam(name = "size", value = "每页的数量", required = true),
+			@ApiImplicitParam(name = "projectId", value = "项目id", required = true)
+	})
+	public R<IPage<ExpertInspectionVO>> getUserInspectInfo(Query query,@RequestParam Long projectId) {
+		IPage<ExpertInspectionVO> page = archivesAutoService.getUserInspectInfo(query, projectId);
+		return R.data(page);
+	}
+
+
+
+	/**
+	 * 在线验收-项目抽检统计
+	 */
+	@GetMapping("/projectInspectStat")
+	@ApiOperationSupport(order = 35)
+	@ApiOperation(value = "在线验收-项目抽检统计", notes = "传入项目id")
+	@ApiImplicitParams(value = {
+			@ApiImplicitParam(name = "projectId", value = "项目id", required = true)
+	})
+	public R<ProjectInspectStatVO> projectInspectStat(@RequestParam Long projectId) {
+		ProjectInspectStatVO vo = archivesAutoService.projectInspectStat(projectId);
+		return R.data(vo);
+	}
+
+	/**
+	 * 在线验收-编写报告
+	 */
+	@GetMapping("/getArchiveConclusion")
+	@ApiOperationSupport(order = 36)
+	@ApiOperation(value = "在线验收-编写报告", notes = "当前专家存在草稿则返回草稿,不存在则返回模板")
+	@ApiImplicitParams(value = {
+			@ApiImplicitParam(name = "projectId", value = "项目id", required = true)
+	})
+	public R<ArchiveConclusion> getArchiveConclusion(@RequestParam Long projectId) {
+		ArchiveConclusion vo = archivesAutoService.getArchiveConclusion(projectId);
+		return R.data(vo);
+	}
+
+	/**
+	 * 在线excel 档案修改回调
+	 */
+	@PostMapping(value = "/callbackSave")
+	@ApiOperation(value = "onlyOffice保存回调", notes = "onlyOffice保存回调")
+	@ApiOperationSupport(order = 37)
+	@ResponseBody
+	public ExcelEditCallback callbackSave(@RequestBody ExcelEditCallback callback, HttpServletRequest request) {
+		String projectId = request.getParameter("projectId");
+		callback.setProjectId(Long.parseLong(projectId));
+		return archivesAutoService.callbackSave(callback);
+	}
+
+
+
 }

+ 23 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/feign/ArchiveAutoClientImpl.java

@@ -1,8 +1,10 @@
 package org.springblade.archive.feign;
 
 import lombok.AllArgsConstructor;
+import org.apache.commons.lang.StringUtils;
 import org.springblade.archive.entity.ArchiveProjectConfig;
 import org.springblade.archive.entity.ArchivesAuto;
+import org.springblade.archive.mapper.ArchivesAutoMapper;
 import org.springblade.archive.service.IArchiveProjectConfigService;
 import org.springblade.archive.service.IArchivesAutoService;
 import org.springblade.archive.vo.ArchivesAutoVO;
@@ -18,6 +20,8 @@ import java.util.List;
 @AllArgsConstructor
 public class ArchiveAutoClientImpl implements ArchiveAutoClient {
 
+    private ArchivesAutoMapper autoMapper;
+
     private IArchivesAutoService archivesAutoService;
 
     private final IArchiveProjectConfigService archiveProjectConfigService;
@@ -43,4 +47,23 @@ public class ArchiveAutoClientImpl implements ArchiveAutoClient {
     public R<Boolean> batchUpdateIsApply(Integer isApply, List<Long> ids) {
         return archivesAutoService.batchUpdateIsApply(isApply,ids);
     }
+
+    @Override
+    public R<Boolean> batchUpdateExpertId(String userId, List<Long> ids) {
+        List<ArchivesAuto> list = autoMapper.getNodeAllArchive(ids);
+        //循环判断是否已经存在专家,存在则追加
+        list.stream().forEach(l->{
+            if (StringUtils.isBlank(l.getExpertId())){
+                //为空
+                l.setExpertId(userId);
+            }else {
+                //不为空
+                String expertId = l.getExpertId();
+                l.setExpertId(expertId+","+userId);
+            }
+        });
+        //保存所有节点
+        archivesAutoService.updateBatchById(list);
+        return R.data(true);
+    }
 }

+ 16 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchiveConclusionMapper.java

@@ -0,0 +1,16 @@
+package org.springblade.archive.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.springblade.archive.entity.ArchiveConclusion;
+import org.springblade.archive.entity.ArchiveProjectConfig;
+
+/**
+ * <p>
+ * Mapper 接口
+ * </p>
+ *
+ * @since 2023-04-09
+ */
+public interface ArchiveConclusionMapper extends BaseMapper<ArchiveConclusion> {
+
+}

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

@@ -20,11 +20,11 @@ import org.apache.ibatis.annotations.MapKey;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 import org.springblade.archive.dto.ArchivesAutoDTO;
+import org.springblade.archive.entity.ArchiveConclusion;
 import org.springblade.archive.entity.ArchivesAuto;
-import org.springblade.archive.vo.ArchivesAutoVO;
+import org.springblade.archive.vo.*;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import org.springblade.archive.vo.ArchivesAutoVO2;
 import org.springblade.business.entity.ArchiveFile;
 import org.springblade.manager.entity.ArchiveTreeContract;
 import org.springblade.system.entity.DictBiz;
@@ -173,4 +173,18 @@ public interface ArchivesAutoMapper extends BaseMapper<ArchivesAuto> {
 	//用于档案巡检查询单位下档案
 	List<ArchivesAutoVO2> getUnitAllArchive2(@Param("firstNode") Long firstNode,@Param("grade") Integer grade,@Param("isApply") Integer isApply);
 
+	IPage<ArchiveInspectVO> getNodeArchives(IPage<ArchiveInspectVO> page,@Param("id") Long nodeId,@Param("projectId") Long projectId,@Param("searchType") Integer searchType,@Param("searchValue") String searchValue,@Param("userId") Long userId);
+
+    List<ArchivesAuto> getNodeAllArchive(@Param("ids") List<Long> ids);
+
+    Integer getUserArchiveTotal(@Param("projectId") Long projectId,@Param("userId") Long userId);
+
+	Integer getUserReviewedTotal(@Param("projectId") Long projectId,@Param("userId") Long userId);
+
+	IPage<ExpertInspectionVO> getUserInspectInfo(IPage<ExpertInspectionVO> page,@Param("projectId") Long projectId,@Param("userId") Long userId);
+
+    List<ArchivesAutoVO3> getAllInspectArchive(@Param("projectId")Long projectId);
+
+    ArchiveConclusion getArchiveConclusion(@Param("projectId") Long projectId,@Param("userId") Long userId);
+
 }

+ 54 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.xml

@@ -1001,6 +1001,60 @@
         WHERE uaa.is_deleted = 0 and matc.is_deleted = 0 and uaa.is_apply = #{isApply} and matc.ancestors like concat("%",#{firstNode},"%")
         order by uaa.tree_sort
     </select>
+    <select id="getNodeArchives" resultType="org.springblade.archive.vo.ArchiveInspectVO">
+        select uaa.id ,uaa.file_number,uaa.name ,uaa.unit,
+               (CASE when uaa.is_inspect = 0 then '未抽检' else '已抽检' end) as inspectStatusName,
+               (CASE when uaa.update_status = 1 then '整改' when uaa.update_status = 2 then '合格' else null end) as updateStatusName
+        from m_archive_tree_contract atc right join u_archives_auto uaa on atc.id = uaa.node_id
+        WHERE uaa.is_apply = 1 and uaa.project_id = #{projectId} and atc.project_id = #{projectId} and atc.is_deleted = 0 and uaa.is_deleted =0
+          and FIND_IN_SET(#{id}, atc.ancestors)
+        <if test="userId != null">
+            and FIND_IN_SET(#{userId}, uaa.expert_id)
+        </if>
+        <if test="searchValue != null and searchValue != ''">
+            <if test="searchType == 1">
+                and uaa.name like concat('%',#{searchValue},'%')
+            </if>
+            <if test="searchType == 2">
+                and (select COUNT(1) from u_archive_file uaf WHERE uaf.archive_id = uaa.id and uaf.file_name like concat('%',#{searchValue},'%'))
+            </if>
+        </if>
+    </select>
+    <select id="getNodeAllArchive" resultType="org.springblade.archive.entity.ArchivesAuto">
+        select id,expert_id
+        from u_archives_auto where is_deleted = 0 and node_id in
+        <foreach collection="ids" item="id" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </select>
+    <select id="getUserArchiveTotal" resultType="java.lang.Integer">
+        SELECT COUNT(1) from u_archives_auto
+        WHERE project_id = #{projectId} and is_deleted = 0 and FIND_IN_SET(#{userId},expert_id)
+    </select>
+    <select id="getUserReviewedTotal" resultType="java.lang.Integer">
+        SELECT COUNT(1) from u_archives_auto
+        WHERE project_id = #{projectId} and is_deleted = 0 and is_inspect = 1 and FIND_IN_SET(#{userId},expert_id)
+    </select>
+    <select id="getUserInspectInfo" resultType="org.springblade.archive.vo.ExpertInspectionVO">
+        select aei.id,aei.archive_name ,aei.opinion , aei.archive_id,expert_name,
+               (case when unit_type = 1 then '施工' when unit_type = 2 then '监理' else '业主' end) as unitName,
+               (select uaf.pdf_file_url from u_archive_file uaf where uaf.id = aei.file_id) as filePdf
+        from u_archive_expert_inspection aei
+        WHERE project_id = #{projectId} and is_deleted = 0
+        <if test="userId != null">
+            and expert_id = #{userId}
+        </if>
+        order BY update_time DESC
+    </select>
+    <select id="getAllInspectArchive" resultType="org.springblade.archive.vo.ArchivesAutoVO3">
+        SELECT (case when contract_id is null then '3' when contract_id = -1 then '3' else (SELECT contract_type from m_contract_info mci WHERE mci.id = uaa.contract_id) end) as unitType,
+               uaa.*
+        from u_archives_auto uaa WHERE project_id = #{projectId} and is_deleted = 0 and is_apply = 1
+    </select>
+    <select id="getArchiveConclusion" resultType="org.springblade.archive.entity.ArchiveConclusion">
+        select * from u_archive_conclusion where project_id = #{projectId} and expert_id = #{userId}
+    </select>
+
 
 
     <update id="splitFiles">

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

@@ -0,0 +1,21 @@
+package org.springblade.archive.mapper;
+
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
+import org.springblade.archive.entity.ExpertInspection;
+import org.springblade.archive.vo.ExpertInspectionVO;
+
+import java.util.List;
+
+/**
+ * <p>
+ * Mapper 接口
+ * </p>
+ *
+ * @since 2023-04-09
+ */
+public interface ExpertInspectionMapper extends BaseMapper<ExpertInspection> {
+
+    List<ExpertInspection> getListByFileId(@Param("fileId") Long fileId,@Param("projectId") Long projectId);
+}

+ 9 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ExpertInspectionMapper.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.springblade.archive.mapper.ExpertInspectionMapper">
+
+    <select id="getListByFileId" resultType="org.springblade.archive.entity.ExpertInspection">
+        select * from u_archive_expert_inspection
+        where project_id = #{projectId} and file_id = #{fileId} and is_deleted = 0 and is_pass = 0
+    </select>
+</mapper>

+ 24 - 3
blade-service/blade-archive/src/main/java/org/springblade/archive/service/IArchivesAutoService.java

@@ -17,15 +17,17 @@
 package org.springblade.archive.service;
 
 import org.springblade.archive.dto.SaveApplyDTO;
+import org.springblade.archive.entity.ArchiveConclusion;
 import org.springblade.archive.entity.ArchivesAuto;
-import org.springblade.archive.vo.ArchiveInspectPreviewVO;
-import org.springblade.archive.vo.ArchivesAutoVO;
-import org.springblade.archive.vo.CheckoutVO;
+import org.springblade.archive.entity.ExpertInspection;
+import org.springblade.archive.vo.*;
 import org.springblade.business.entity.ArchiveFile;
 import org.springblade.core.mp.base.BaseService;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.springblade.core.mp.support.Query;
 import org.springblade.core.tool.api.R;
 import org.springblade.manager.entity.ArchiveTreeContract;
+import org.springblade.manager.entity.ExcelEditCallback;
 import org.springblade.system.entity.DictBiz;
 import org.springblade.system.user.entity.User;
 import org.springframework.web.multipart.MultipartFile;
@@ -121,4 +123,23 @@ public interface IArchivesAutoService extends BaseService<ArchivesAuto> {
 	Boolean getApplyStatus(Long projectId);
 
 	void annulApply(Long projectId);
+
+	IPage<ArchiveInspectVO> getNodeArchives(Query query,Long nodeId, Long projectId,Integer searchType,String searchValue,Integer type);
+
+	Map<String,String> userInspectStats(Long projectId);
+
+	void updateInspectStatus(Long archiveId,Long projectId);
+
+	void saveInspect(ExpertInspection inspection);
+
+	IPage<ExpertInspectionVO> getUserInspectInfo(Query query, Long projectId);
+
+    ProjectInspectStatVO projectInspectStat(Long projectId);
+
+	ExpertInspectionVO getArchiveFileOpinion(Long fileId, Long projectId);
+
+
+    ArchiveConclusion getArchiveConclusion(Long projectId);
+
+	ExcelEditCallback callbackSave(ExcelEditCallback callback);
 }

+ 15 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/service/IExpertInspectionService.java

@@ -0,0 +1,15 @@
+package org.springblade.archive.service;
+
+import org.springblade.archive.entity.ArchiveProjectConfig;
+import org.springblade.archive.entity.ExpertInspection;
+import org.springblade.archive.vo.ExpertInspectionVO;
+import org.springblade.core.mp.base.BaseService;
+
+import java.util.List;
+
+
+public interface IExpertInspectionService extends BaseService<ExpertInspection> {
+
+
+    List<ExpertInspection> getListByFileId(Long fileId, Long projectId);
+}

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

@@ -25,26 +25,24 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang.StringUtils;
 import org.springblade.archive.dto.SaveApplyDTO;
+import org.springblade.archive.entity.ArchiveConclusion;
 import org.springblade.archive.entity.ArchiveProjectConfig;
 import org.springblade.archive.entity.ArchivesAuto;
-import org.springblade.archive.service.IArchiveAutoPdfService;
-import org.springblade.archive.service.IArchiveOfflineVersionInfoService;
-import org.springblade.archive.service.IArchiveProjectConfigService;
+import org.springblade.archive.entity.ExpertInspection;
+import org.springblade.archive.mapper.ArchiveConclusionMapper;
+import org.springblade.archive.service.*;
 import org.springblade.archive.utils.ArchiveTreeUtil;
 import org.springblade.archive.utils.FileTransJavaDemo;
 import org.springblade.archive.utils.FileUtils;
-import org.springblade.archive.vo.ArchiveInspectPreviewVO;
-import org.springblade.archive.vo.ArchivesAutoVO;
+import org.springblade.archive.vo.*;
 import org.springblade.archive.mapper.ArchivesAutoMapper;
-import org.springblade.archive.service.IArchivesAutoService;
-import org.springblade.archive.vo.ArchivesAutoVO2;
-import org.springblade.archive.vo.CheckoutVO;
 import org.springblade.business.entity.ArchiveFile;
 import org.springblade.business.entity.Task;
 import org.springblade.business.entity.TaskParallel;
@@ -67,9 +65,7 @@ import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.FileUtil;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.core.tool.utils.StringUtil;
-import org.springblade.manager.entity.ArchiveTreeContract;
-import org.springblade.manager.entity.ContractInfo;
-import org.springblade.manager.entity.ProjectInfo;
+import org.springblade.manager.entity.*;
 import org.springblade.manager.feign.ArchiveTreeContractClient;
 import org.springblade.manager.feign.ContractClient;
 import org.springblade.manager.feign.ProjectClient;
@@ -96,6 +92,8 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.math.BigDecimal;
+import java.net.URL;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
@@ -138,6 +136,10 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 
 	private final TaskClient taskClient;
 
+	private final IExpertInspectionService inspectionService;
+
+	private final ArchiveConclusionMapper conclusionMapper;
+
 
 
 
@@ -2630,7 +2632,7 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		task.setContractId(contractInfos.get(0).getId()+"");
 		task.setStartTime(dto.getStartDate().toString());
 		task.setReportUser(AuthUtil.getUserId().toString());
-		task.setReportUserName(AuthUtil.getUserName());
+		task.setReportUserName(AuthUtil.getNickName());
 		task.setTaskName(dto.getTaskName());
 		task.setTaskContent(dto.getTaskContent());
 		//数据指向设置为专家信息
@@ -2694,6 +2696,400 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		}
 	}
 
+	/**
+	 * 在线验收-查询节点已经上报的档案,id为节点id
+	 */
+	@Override
+	public IPage<ArchiveInspectVO> getNodeArchives(Query query,Long nodeId,Long projectId,Integer searchType,String searchValue,Integer type) {
+		IPage<ArchiveInspectVO> page = new Page<>(query.getCurrent(),query.getSize());
+		if (type == 1){
+			return baseMapper.getNodeArchives(page,nodeId,projectId,searchType,searchValue,null);
+		}else {
+			return baseMapper.getNodeArchives(page,nodeId,projectId,searchType,searchValue,AuthUtil.getUserId());
+		}
+	}
+
+	/**
+	 * 在线验收-抽检统计
+	 */
+	@Override
+	public Map<String, String> userInspectStats(Long projectId) {
+		Map<String, String> map = new HashMap<>();
+		Long userId = AuthUtil.getUserId();
+		//获取用户归属档案总数
+		Integer t1 = baseMapper.getUserArchiveTotal(projectId, userId);
+		if (t1 == 0){
+			return null;
+		}
+		map.put("total",t1+"");
+		//获取用户归属档案所有已阅总数
+		Integer t2 = baseMapper.getUserReviewedTotal(projectId, userId);
+		if (t2 > t1){
+			throw new ServiceException("数据错误,已阅比总数多");
+		}
+		map.put("reviewed",t2+"");
+		if (t2 == 0){
+			map.put("ratio","0%");
+		}else {
+			map.put("ratio", new BigDecimal(t2).divide(new BigDecimal(t1), 3, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(1) + "%");
+		}
+		return map;
+	}
+
+	/**
+	 * 在线验收-修改抽检状态
+	 */
+	@Override
+	@Transactional
+	public void updateInspectStatus(Long archiveId,Long projectId) {
+		//查看当前档案是否存在有意见的数据,存在则什么都不修改,不存在则修改已抽检,合格
+		long count2 = inspectionService.count(new LambdaQueryWrapper<ExpertInspection>()
+				.eq(ExpertInspection::getIsPass, 0)
+				.eq(ExpertInspection::getArchiveId, archiveId));
+		//修改档案抽检状态
+		if (count2 == 0) {
+			this.update(new LambdaUpdateWrapper<ArchivesAuto>()
+					.set(ArchivesAuto::getIsInspect, 1)
+					.set(ArchivesAuto::getUpdateStatus,2)
+					.eq(ArchivesAuto::getId, archiveId));
+		}
+		//查看当前专家在意见表中是否对当前案卷有数据,如果存在数据则证明抽检过,直接跳过
+		Long userId = AuthUtil.getUserId();
+		long count = inspectionService.count(new LambdaQueryWrapper<ExpertInspection>()
+						.eq(ExpertInspection::getExpertId, userId)
+						.eq(ExpertInspection::getArchiveId, archiveId));
+		if (count == 0){
+			String userName = AuthUtil.getNickName();
+			//获取档案信息,如果状态未未查阅则修改
+			ArchivesAuto archive = this.getById(archiveId);
+			//查询当前案卷节点的合同段类型
+			Integer unitType;
+			if (archive.getContractId() == null || archive.getContractId() == -1){
+				unitType = 3;
+			}else {
+				ContractInfo contract = contractClient.getContractById(archive.getContractId());
+				unitType = contract.getContractType();
+			}
+			ExpertInspection inspection = new ExpertInspection();
+			inspection.setProjectId(projectId);
+			inspection.setExpertId(userId);
+			inspection.setExpertName(userName);
+			inspection.setIsPass(1);
+			inspection.setUnitType(unitType);
+			inspection.setArchiveId(archiveId);
+			inspection.setArchiveName(archive.getName());
+			inspectionService.save(inspection);
+		}
+
+	}
+
+	/**
+	 * 在线验收-保存抽检意见
+	 */
+	@Override
+	@Transactional
+	public void saveInspect(ExpertInspection inspection) {
+		//判断是否存在文件id
+		if (inspection.getFileId() == null){
+			throw new ServiceException("未获取到当前的文件id");
+		}
+		//专家基本信息
+		Long userId = AuthUtil.getUserId();
+		String userName = AuthUtil.getNickName();
+		//获取档案信息,如果状态未未查阅则修改
+		ArchivesAuto archive = this.getById(inspection.getArchiveId());
+		archive.setIsInspect(1);
+		//查询当前案卷节点的合同段类型
+		Integer unitType;
+		if (archive.getContractId() == null || archive.getContractId() == -1){
+			unitType = 3;
+		}else {
+			ContractInfo contract = contractClient.getContractById(archive.getContractId());
+			unitType = contract.getContractType();
+		}
+		//判断是否存在意见
+		Integer isPass = 1;
+		if (StringUtils.isNotBlank(inspection.getOpinion())){
+			isPass = 0;
+		}
+		inspection.setArchiveName(archive.getName());
+		inspection.setExpertId(userId);
+		inspection.setExpertName(userName);
+		inspection.setIsPass(isPass);
+		inspection.setUnitType(unitType);
+		//如果专家对案卷没有意见
+		if (isPass == 1){
+			//判断是否有合格意见,有则直接跳过
+			long count3 = inspectionService.count(new LambdaQueryWrapper<ExpertInspection>()
+					.eq(ExpertInspection::getExpertId, userId)
+					.eq(ExpertInspection::getArchiveId, archive.getId())
+					.eq(ExpertInspection::getIsPass, 1));
+			if (count3 == 0){
+				//先删除当前专家对当前案卷当前文件的意见
+				inspectionService.remove(new LambdaQueryWrapper<ExpertInspection>()
+						.eq(ExpertInspection::getExpertId, userId)
+						.eq(ExpertInspection::getArchiveId, inspection.getArchiveId())
+						.eq(ExpertInspection::getFileId, inspection.getFileId()));
+				//再查看当前专家是否对当前档案有意见
+				long count2 = inspectionService.count(new LambdaQueryWrapper<ExpertInspection>()
+						.eq(ExpertInspection::getExpertId, userId)
+						.eq(ExpertInspection::getArchiveId, archive.getId())
+						.eq(ExpertInspection::getIsPass, 0));
+				//没有就直接保存合格
+				if (count2 == 0) {
+					inspection.setFileId(null);
+					inspectionService.save(inspection);
+				}
+			}
+		}else {
+			//如果专家对案卷有意见,先删除当前专家在意见表对当前档案合格的意见
+			inspectionService.remove(new LambdaQueryWrapper<ExpertInspection>()
+					.eq(ExpertInspection::getExpertId, userId)
+					.eq(ExpertInspection::getArchiveId, inspection.getArchiveId())
+					.eq(ExpertInspection::getIsPass, 1));
+			//再去查看意见表是否存在对当前档案当前文件的意见
+			ExpertInspection one = inspectionService.getOne(new LambdaQueryWrapper<ExpertInspection>()
+					.eq(ExpertInspection::getExpertId, userId)
+					.eq(ExpertInspection::getArchiveId, inspection.getArchiveId())
+					.eq(ExpertInspection::getFileId, inspection.getFileId()));
+			//如果不存在数据,然后保存
+			if (one == null) {
+				inspectionService.save(inspection);
+			} else {
+				//如果存在数据,则判断是否存在意见,然后修改
+				one.setIsPass(isPass);
+				one.setOpinion(inspection.getOpinion());
+				inspectionService.updateById(one);
+			}
+		}
+		//查询当前档案的所有不合格专家意见
+		long count = inspectionService.count(new LambdaQueryWrapper<ExpertInspection>()
+				.eq(ExpertInspection::getArchiveId, archive.getId())
+				.eq(ExpertInspection::getIsPass, 0));
+		if (count > 0){
+			//如果有则修改档案不合格
+			archive.setUpdateStatus(1);
+		}else {
+			//如果没有则修改档案为合格
+			archive.setUpdateStatus(2);
+		}
+		this.updateById(archive);
+	}
+
+	/**
+	 * 在线验收-抽检记录
+	 */
+	@Override
+	public IPage<ExpertInspectionVO> getUserInspectInfo(Query query, Long projectId) {
+		Long userId = AuthUtil.getUserId();
+		//判断当前用户职位是否为专家组长,专家组长查看所有
+		String userRole = AuthUtil.getUserRole();
+		if ("1656191696348082177".equals(userRole)){
+			userId = null;
+		}
+		IPage<ExpertInspectionVO> page = new Page<>(query.getCurrent(),query.getSize());
+		return baseMapper.getUserInspectInfo(page,projectId,userId);
+	}
+
+	/**
+	 * 在线验收-项目抽检统计
+	 */
+	@Override
+	public ProjectInspectStatVO projectInspectStat(Long projectId) {
+		//获取当前项目下所有已经申请抽检的案卷
+		List<ArchivesAutoVO3> list = baseMapper.getAllInspectArchive(projectId);
+		if (list == null || list.size() == 0){
+			return null;
+		}
+		ProjectInspectStatVO vo = new ProjectInspectStatVO();
+		List<ProjectInspectStatVO.UnitGroup> groupList = new ArrayList<>();
+		//总抽检率
+		BigDecimal totalRatio = new BigDecimal(0) ;
+		//根据单位类型分组
+		Map<Integer, List<ArchivesAutoVO3>> listMap = list.stream().collect(Collectors.groupingBy(ArchivesAutoVO3::getUnitType));
+		//统计业主
+		List<ArchivesAutoVO3> list1 = listMap.get(3);
+		if (list1 != null && list1.size() > 0){
+			ProjectInspectStatVO.UnitGroup unitGroup = new ProjectInspectStatVO.UnitGroup();
+			unitGroup.setTotal(list1.size());
+			list1.removeIf(l-> l.getIsInspect() == 0);
+			unitGroup.setEndInspect(list1.size());
+			list1.removeIf(l->l.getUpdateStatus() == 2);
+			unitGroup.setNeedUpdate(list1.size());
+			BigDecimal bigDecimal = new BigDecimal(unitGroup.getEndInspect()).divide(new BigDecimal(unitGroup.getTotal()), 3, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(1);
+			unitGroup.setInspectRatio(bigDecimal.toString()+"%");
+			unitGroup.setName("业主组");
+			groupList.add(unitGroup);
+			totalRatio = totalRatio.add(bigDecimal);
+
+		}else {
+			ProjectInspectStatVO.UnitGroup unitGroup = new ProjectInspectStatVO.UnitGroup(0,0,0,"0%");
+			unitGroup.setName("业主组");
+			groupList.add(unitGroup);
+		}
+		//统计监理
+		List<ArchivesAutoVO3> list2 = listMap.get(2);
+		if (list2 != null && list2.size() > 0){
+			ProjectInspectStatVO.UnitGroup unitGroup = new ProjectInspectStatVO.UnitGroup();
+			unitGroup.setTotal(list2.size());
+			list2.removeIf(l-> l.getIsInspect() == 0);
+			unitGroup.setEndInspect(list2.size());
+			list2.removeIf(l->l.getUpdateStatus() == 2);
+			unitGroup.setNeedUpdate(list2.size());
+			BigDecimal bigDecimal = new BigDecimal(unitGroup.getEndInspect()).divide(new BigDecimal(unitGroup.getTotal()), 3, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(1);
+			unitGroup.setInspectRatio(bigDecimal.toString()+"%");
+			unitGroup.setName("监理组");
+			groupList.add(unitGroup);
+			totalRatio = totalRatio.add(bigDecimal);
+
+		}else {
+			ProjectInspectStatVO.UnitGroup unitGroup = new ProjectInspectStatVO.UnitGroup(0,0,0,"0%");
+			unitGroup.setName("监理组");
+			groupList.add(unitGroup);
+		}
+		//统计施工
+		List<ArchivesAutoVO3> list3 = listMap.get(1);
+		if (list3 != null && list3.size() > 0){
+			ProjectInspectStatVO.UnitGroup unitGroup = new ProjectInspectStatVO.UnitGroup();
+			unitGroup.setTotal(list3.size());
+			list3.removeIf(l-> l.getIsInspect() == 0);
+			unitGroup.setEndInspect(list3.size());
+			list3.removeIf(l->l.getUpdateStatus() == 2);
+			unitGroup.setNeedUpdate(list3.size());
+			BigDecimal bigDecimal = new BigDecimal(unitGroup.getEndInspect()).divide(new BigDecimal(unitGroup.getTotal()), 3, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(1);
+			unitGroup.setInspectRatio(bigDecimal.toString()+"%");
+			unitGroup.setName("施工组");
+			groupList.add(unitGroup);
+			totalRatio = totalRatio.add(bigDecimal);
+
+		}else {
+			ProjectInspectStatVO.UnitGroup unitGroup = new ProjectInspectStatVO.UnitGroup(0,0,0,"0%");
+			unitGroup.setName("施工组");
+			groupList.add(unitGroup);
+		}
+		ProjectInspectStatVO.UnitGroup unitGroup2 = new ProjectInspectStatVO.UnitGroup(0,0,0,"0%");
+		unitGroup2.setName("声像组");
+		groupList.add(unitGroup2);
+		ProjectInspectStatVO.UnitGroup unitGroup3 = new ProjectInspectStatVO.UnitGroup(0,0,0,"0%");
+		unitGroup3.setName("竣工图组");
+		groupList.add(unitGroup3);
+		vo.setList(groupList);
+		vo.setTotalInspectRatio(totalRatio.toString());
+		//案卷低于100卷,则需要全部抽检完,抽检率必须达到100%,否则则提示抽检率不达标,未达到100%;
+		//案卷高于100卷,所有抽检案卷加起来的抽检率不足10%,则提示抽检率未达到10%
+		if (list.size() <= 100){
+			if (new BigDecimal(100).compareTo(totalRatio) != 0){
+				vo.setTips("预警提示:抽检率未达到验收要求,目前只抽检了"+totalRatio+"%");
+			}
+		}else {
+			if (new BigDecimal(10).compareTo(totalRatio) != -1){
+				vo.setTips("预警提示:抽检率未达到验收要求,目前只抽检了"+totalRatio+"%");
+			}
+		}
+		return vo;
+	}
+
+	/**
+	 * 在线验收-获取档案文件抽检意见
+	 */
+	@Override
+	public ExpertInspectionVO getArchiveFileOpinion(Long fileId, Long projectId) {
+		Long userId = AuthUtil.getUserId();
+		String userName = AuthUtil.getNickName();
+		ExpertInspectionVO vo = new ExpertInspectionVO();
+		//获取意见表里当前文件相关意见
+		List<ExpertInspection> list = inspectionService.getListByFileId(fileId,projectId);
+		if (list != null && list.size() > 0){
+			StringBuilder str = new StringBuilder();
+			for (ExpertInspection inspection : list) {
+				str.append(inspection.getExpertName()+":"+inspection.getOpinion()+";");
+				if (userId.equals(inspection.getExpertId())){
+					vo.setOpinion(inspection.getOpinion());
+				}
+			}
+			vo.setAllOpinion(str.toString());
+		}
+		return vo;
+	}
+
+	/**
+	 * 在线验收-编写报告
+	 */
+	@Override
+	public ArchiveConclusion getArchiveConclusion(Long projectId) {
+		Long userId = AuthUtil.getUserId();
+		ArchiveConclusion conclusion = baseMapper.getArchiveConclusion(projectId, userId);
+		//如果为空返回模板
+		if (conclusion == null){
+			//当保存的时候发现key为5代表是模板
+			ArchiveConclusion archiveConclusion = new ArchiveConclusion();
+			Long id = SnowFlakeUtil.getId();
+			archiveConclusion.setId(id);
+			archiveConclusion.setWorldUrl("https://bladex-chongqing-info.oss-cn-hangzhou.aliyuncs.com//upload/20231122/377ab5022240b55f9b63e2f4e3aae437.docx");
+			return archiveConclusion;
+		}
+		//否则返回草稿
+		return conclusion;
+	}
+
+	/**
+	 * 在线excel 档案修改回调
+	 */
+	@Override
+	public ExcelEditCallback callbackSave(ExcelEditCallback callback) {
+		ExcelEditCallback editCallback = new ExcelEditCallback();
+		editCallback.setError(0); //初始化返回值
+		int status = callback.getStatus();
+		//status=6,表示点击保存按钮
+		if (status == 3 || status == 6)
+		{
+			//获取url
+			String downloadUri = callback.getUrl();
+			downloadUri = downloadUri.replaceAll("amp;", "");
+			try {
+				//获取onlyOffice缓存中的文件流
+				URL url = new URL(downloadUri);
+				java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
+				connection.setRequestMethod("GET");
+				connection.setConnectTimeout(5 * 1000);
+				InputStream inputStream = connection.getInputStream();
+				if (inputStream == null) {
+					throw new Exception("文件为空");
+				}
+				//判断当前key是否存在,不存在则新增,存在则修改
+				String id = callback.getKey();
+				if (StringUtils.isBlank(id)){
+					throw new Exception("key不能为null");
+				}
+//				id = id.substring(0, id.lastIndexOf("_"));
+//				ArchiveConclusion conclusion = conclusionMapper.selectById(id);
+				ArchiveConclusion conclusion = conclusionMapper.selectOne(new LambdaQueryWrapper<ArchiveConclusion>().eq(ArchiveConclusion::getExpertId,AuthUtil.getUserId()));
+				//上传新文件到文件服务器
+				BladeFile bladeFile = iossClient.uploadFileByInputStream2("结论.docx",inputStream);
+				if (bladeFile == null || StringUtils.isBlank(bladeFile.getLink())){
+					throw new Exception("文件上传失败");
+				}
+				if (conclusion == null){
+					ArchiveConclusion archiveConclusion = new ArchiveConclusion();
+					archiveConclusion.setWorldUrl(bladeFile.getLink());
+					archiveConclusion.setId(SnowFlakeUtil.getId());
+					archiveConclusion.setExpertId(AuthUtil.getUserId());
+					archiveConclusion.setProjectId(callback.getProjectId());
+					conclusionMapper.insert(archiveConclusion);
+				}else {
+					conclusion.setWorldUrl(bladeFile.getLink());
+					conclusionMapper.updateById(conclusion);
+				}
+				inputStream.close();
+			} catch (Exception e) {
+				editCallback.setError(1);
+				e.printStackTrace();
+			}
+		}
+		return editCallback;
+	}
+
+
 	public void deleteFile(String defaultDir,Long id){
 		String dir = defaultDir+"/"+id;
 		String file = defaultDir+"/"+id+".zip";

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

@@ -0,0 +1,22 @@
+package org.springblade.archive.service.impl;
+
+
+import org.springblade.archive.entity.ExpertInspection;
+import org.springblade.archive.mapper.ExpertInspectionMapper;
+import org.springblade.archive.service.IExpertInspectionService;
+import org.springblade.archive.vo.ExpertInspectionVO;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public class ExpertInspectionServiceImpl extends BaseServiceImpl<ExpertInspectionMapper, ExpertInspection> implements IExpertInspectionService {
+
+
+    @Override
+    public List<ExpertInspection> getListByFileId(Long fileId, Long projectId) {
+        return baseMapper.getListByFileId(fileId,projectId);
+    }
+}
+

+ 15 - 18
blade-service/blade-business/src/main/java/org/springblade/business/controller/ContractTreeDrawingsController.java

@@ -25,10 +25,13 @@ import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import lombok.AllArgsConstructor;
 import org.apache.commons.lang.StringUtils;
 import org.springblade.business.entity.ContractTreeDrawings;
+import org.springblade.business.service.IInformationQueryService;
 import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.secure.BladeUser;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.api.R;
+import org.springblade.manager.entity.WbsTreeContract;
+import org.springblade.manager.feign.WbsTreeContractClient;
 import org.springframework.web.bind.annotation.*;
 import org.springblade.business.service.IContractTreeDrawingsService;
 import org.springblade.core.boot.ctrl.BladeController;
@@ -48,6 +51,9 @@ public class ContractTreeDrawingsController extends BladeController {
 
     private final IContractTreeDrawingsService contractTreeDrawingsService;
 
+
+
+
     /**
      * 保存或修改节点上传的图纸记录
      *
@@ -63,25 +69,10 @@ public class ContractTreeDrawingsController extends BladeController {
             @ApiImplicitParam(name = "fileUrl", value = "文件url", required = true),
             @ApiImplicitParam(name = "id", value = "节点的drawingsId")
     })
-    public R<String> saveOrUpdateContractTreeDrawings(@RequestParam String primaryKeyId, @RequestParam String fileUrl,String id) {
-        //当前提交用户
-        BladeUser user = AuthUtil.getUser();
-        if (!"-1".equals(id) && StringUtils.isNotEmpty(id)) {
-            //修改
-            this.contractTreeDrawingsService.update(Wrappers.<ContractTreeDrawings>lambdaUpdate()
-                    .set(ContractTreeDrawings::getFileUrl, fileUrl).set(ContractTreeDrawings::getUpdateUser, user.getUserId())
-                    .set(ContractTreeDrawings::getUpdateTime, new Date())
-                    .eq(ContractTreeDrawings::getId, id));
+    public R<Long> saveOrUpdateContractTreeDrawings(@RequestParam String primaryKeyId, @RequestParam String fileUrl,Long id) {
 
-            return R.data(id);
-        } else {
-            //新增
-            ContractTreeDrawings drawings = new ContractTreeDrawings(primaryKeyId, fileUrl, user.getUserId(), user.getDeptId());
-            drawings.setId(SnowFlakeUtil.getId());
-            this.contractTreeDrawingsService.save(drawings);
 
-            return R.data(drawings.getId().toString());
-        }
+        return contractTreeDrawingsService.saveOrUpdateContractTreeDrawings(primaryKeyId,fileUrl,id);
     }
 
     /**
@@ -94,8 +85,14 @@ public class ContractTreeDrawingsController extends BladeController {
             @ApiImplicitParam(name = "primaryKeyId", value = "节点primaryKeyId", required = true)
     })
     public R<String> getTreeDrawings(Long primaryKeyId){
+        if (primaryKeyId == null || primaryKeyId == -1){
+            return R.fail("图纸id错误");
+        }
         ContractTreeDrawings one = contractTreeDrawingsService.getOne(new LambdaQueryWrapper<ContractTreeDrawings>()
-                .eq(ContractTreeDrawings::getProcessId, primaryKeyId));
+                .eq(ContractTreeDrawings::getId, primaryKeyId));
+        if (one == null || StringUtils.isBlank(one.getFileUrl())){
+            return R.fail("暂未查询到当前节点下图纸");
+        }
         return R.data(one.getFileUrl());
     }
 

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

@@ -17,6 +17,7 @@
 package org.springblade.business.controller;
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
@@ -25,6 +26,7 @@ import lombok.AllArgsConstructor;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang.time.DateUtils;
 import org.jetbrains.annotations.NotNull;
+import org.springblade.business.mapper.OperationLogMapper;
 import org.springblade.business.wrapper.OperationLogWrapper;
 import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
@@ -60,6 +62,8 @@ public class OperationLogController extends BladeController {
 
     private final IDictBizClient dictBizClient;
 
+    private final OperationLogMapper logMapper;
+
 
 
     /**
@@ -156,8 +160,9 @@ public class OperationLogController extends BladeController {
         }
 
 
-
-        IPage<OperationLog> pages = operationLogService.page(Condition.getPage(query), wrapper.lambda().orderBy(true, false, OperationLog::getCreateTime));
+        IPage<OperationLog> pages = new Page<>(query.getCurrent(),query.getSize());
+//        IPage<OperationLog> pages = operationLogService.page(Condition.getPage(query), wrapper.lambda().orderBy(true, false, OperationLog::getCreateTime));
+        pages = logMapper.getPage(pages,operationLog);
 
         //获取业务字典
         List<DictBiz> dictBizList = this.dictBizClient.getList("operation_type", "notRoot").getData();

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

@@ -685,7 +685,7 @@ public class TaskController extends BladeController {
                                     dto.setTenantId(AuthUtil.getTenantId());
                                     dto.setAccount("expert"+phone);
                                     StringSPUtils stringSPUtils = new StringSPUtils();
-                                    dto.setPassword(stringSPUtils.getStringSP(name)+phone);
+                                    dto.setPassword(stringSPUtils.getStringSP(name).toLowerCase(Locale.ROOT)+phone);
                                     dto.setUserType("3");
                                     dto.setRealName(name);
                                     dto.setPhone(phone);

+ 1 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/ContractTreeDrawingsMapper.java

@@ -39,4 +39,5 @@ public interface ContractTreeDrawingsMapper extends BaseMapper<ContractTreeDrawi
      */
     List<ContractTreeDrawingsVO> selectContractTreeDrawingsPage(IPage page, ContractTreeDrawingsVO contractTreeDrawings);
 
+    void deleteByNodeId(@Param("id") String primaryKeyId);
 }

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

@@ -15,6 +15,10 @@
         <result column="process_id" property="processId"/>
         <result column="file_url" property="fileUrl"/>
     </resultMap>
+    <delete id="deleteByNodeId">
+        DELETE FROM u_contract_tree_drawings
+        WHERE process_id = #{id}
+    </delete>
 
     <select id="queryCurrentNodeDrawings" resultMap="contractTreeDrawingsResultMap">
         select id, file_url from u_contract_tree_drawings where is_deleted = 0 and process_id = #{primaryKeyId}

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

@@ -16,9 +16,11 @@
  */
 package org.springblade.business.mapper;
 
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.apache.ibatis.annotations.Param;
 import org.springblade.business.entity.OperationLog;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.springblade.business.vo.OperationLogVO;
 
 import java.util.List;
 
@@ -37,4 +39,6 @@ public interface OperationLogMapper extends BaseMapper<OperationLog> {
     List<String> queryBusinessModule(@Param("userId") Long userId);
 
     Long getAdminId();
+
+    IPage<OperationLog> getPage(IPage<OperationLog> pages,@Param("vo") OperationLogVO operationLog);
 }

+ 6 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/OperationLogMapper.xml

@@ -52,5 +52,11 @@
     <select id="getAdminId" resultType="java.lang.Long">
         select id from blade_role WHERE role_name = '超级管理员'
     </select>
+    <select id="getPage" resultType="org.springblade.business.entity.OperationLog">
+        select *
+        from u_operation_log uol where is_deleted = 0
+        and (SELECT contract_id from m_wbs_tree_contract WHERE p_key_id = SUBSTRING_INDEX(uol.business_id,",",1)) = #{vo.contractId}
+        order by uol.create_time desc
+    </select>
 
 </mapper>

+ 2 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/UserOpinionFlowMapper.java

@@ -48,4 +48,6 @@ public interface UserOpinionFlowMapper extends BaseMapper<UserOpinionFlow> {
      */
     List<UserOpinionFlowVO> selectUserOpinionFlowPage(IPage page, UserOpinionFlowVO userOpinionFlow);
 
+    List<UserOpinionFlow> queryUserOpinionFlowsByConcatenatedIds(List<String> list);
+
 }

+ 26 - 1
blade-service/blade-business/src/main/java/org/springblade/business/mapper/UserOpinionFlowMapper.xml

@@ -123,7 +123,8 @@
                manage_time,
                reply_name,
                reply_content,
-               is_current
+               is_current,
+               number
         from u_user_opinion_flow
         where is_deleted = 0
           and user_opinion_id = #{key}
@@ -145,4 +146,28 @@
         select * from u_user_opinion_flow where is_deleted = 0
     </select>
 
+    <select id="queryUserOpinionFlowsByConcatenatedIds" resultMap="userOpinionFlowResultMap">
+        SELECT  id,
+                user_opinion_id,
+                evaluation,
+                manage_user,
+                manage_user_name,
+                manage_user_phone,
+                sort,
+                manage_time,
+                reply_name,
+                reply_content,
+                is_current,
+                number
+        FROM u_user_opinion_flow
+        WHERE is_deleted = 0
+        AND (
+                <foreach collection="list" item="item" separator=" OR " open="" close="">
+                    CONCAT(user_opinion_id, '___', number) = #{item}
+                </foreach>
+             )
+        ORDER BY sort ASC
+    </select>
+
+
 </mapper>

+ 2 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/IContractTreeDrawingsService.java

@@ -20,6 +20,7 @@ import org.springblade.business.entity.ContractTreeDrawings;
 import org.springblade.business.vo.ContractTreeDrawingsVO;
 import org.springblade.core.mp.base.BaseService;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.springblade.core.tool.api.R;
 
 /**
  * 服务类
@@ -42,4 +43,5 @@ public interface IContractTreeDrawingsService extends BaseService<ContractTreeDr
      */
     IPage<ContractTreeDrawingsVO> selectContractTreeDrawingsPage(IPage<ContractTreeDrawingsVO> page, ContractTreeDrawingsVO contractTreeDrawings);
 
+    R<Long> saveOrUpdateContractTreeDrawings(String primaryKeyId, String fileUrl, Long id);
 }

+ 2 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/IUserOpinionFlowService.java

@@ -53,4 +53,6 @@ public interface IUserOpinionFlowService extends BaseService<UserOpinionFlow> {
 
     Integer selectIsSolveByUserOpinionKey(Long userOpinionKey);
 
+    List<UserOpinionFlowVO> queryUserOpinionFlowsByConcatenatedIds(List<String> concatenatedList);
+
 }

+ 35 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/ContractTreeDrawingsServiceImpl.java

@@ -16,11 +16,20 @@
  */
 package org.springblade.business.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import lombok.AllArgsConstructor;
 import org.springblade.business.entity.ContractTreeDrawings;
+import org.springblade.business.service.IInformationQueryService;
 import org.springblade.business.vo.ContractTreeDrawingsVO;
 import org.springblade.business.mapper.ContractTreeDrawingsMapper;
 import org.springblade.business.service.IContractTreeDrawingsService;
+import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.core.secure.BladeUser;
+import org.springblade.core.secure.utils.AuthUtil;
+import org.springblade.core.tool.api.R;
+import org.springblade.manager.entity.WbsTreeContract;
+import org.springblade.manager.feign.WbsTreeContractClient;
 import org.springframework.stereotype.Service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 
@@ -31,8 +40,13 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
  * @since 2022-06-14
  */
 @Service
+@AllArgsConstructor
 public class ContractTreeDrawingsServiceImpl extends BaseServiceImpl<ContractTreeDrawingsMapper, ContractTreeDrawings> implements IContractTreeDrawingsService {
 
+    private final IInformationQueryService queryService;
+
+    private final WbsTreeContractClient contractClient;
+
     @Override
     public ContractTreeDrawings queryCurrentNodeDrawings(String primaryKeyId) {
         return this.baseMapper.queryCurrentNodeDrawings(primaryKeyId);
@@ -43,4 +57,25 @@ public class ContractTreeDrawingsServiceImpl extends BaseServiceImpl<ContractTre
         return page.setRecords(baseMapper.selectContractTreeDrawingsPage(page, contractTreeDrawings));
     }
 
+    @Override
+    public R<Long> saveOrUpdateContractTreeDrawings(String primaryKeyId, String fileUrl, Long id) {
+        //当前提交用户
+        BladeUser user = AuthUtil.getUser();
+        if (id != null && id != -1) {
+            //如果存在图纸,则删除当前节点下所有图纸
+            baseMapper.deleteByNodeId(primaryKeyId);
+        }
+        //新增
+        ContractTreeDrawings drawings = new ContractTreeDrawings(primaryKeyId, fileUrl, user.getUserId(), user.getDeptId());
+        drawings.setId(SnowFlakeUtil.getId());
+        id = drawings.getId();
+        this.save(drawings);
+        WbsTreeContract Contract = contractClient.getContractWbsTreeByPrimaryKeyId(Long.parseLong(primaryKeyId));
+        if (Contract == null){
+            return R.fail("未找到当前节点信息");
+        }
+        queryService.delAsyncWbsTree(Contract.getContractId());
+        return R.data(id);
+    }
+
 }

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

@@ -23,8 +23,10 @@ import org.springblade.core.mp.base.BaseServiceImpl;
 import org.springblade.core.oss.model.BladeFile;
 import org.springblade.core.secure.BladeUser;
 import org.springblade.core.secure.utils.AuthUtil;
+import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.*;
 import org.springblade.manager.entity.ContractInfo;
+import org.springblade.manager.entity.ContractRelationJlyz;
 import org.springblade.manager.entity.TabBusstimeInfo;
 import org.springblade.manager.entity.WbsTreeContract;
 import org.springblade.manager.feign.ContractClient;
@@ -358,7 +360,20 @@ public class InformationQueryServiceImpl extends BaseServiceImpl<InformationQuer
                                                    Integer classify, Integer sourceType,
                                                    String isFirst, String sourceUrl,
                                                    String pdfUrl, String firstFileName, List<JSONObject> linkDataList) {
-        BladeUser user = AuthUtil.getUser();
+        Long userId = 0L ;
+        String userNmae ="";
+
+        if(primaryKeyId.indexOf(":")>=0){
+           String prdata[] = primaryKeyId.split(":");
+            primaryKeyId = prdata[0];
+            userId = Long.parseLong(prdata[1]);
+            R<User> userR = userClient.userInfoById(userId);
+            userNmae = userR.getData().getName();
+        }else{
+            BladeUser user = AuthUtil.getUser();
+            userId = user.getUserId();
+            userNmae = user.getNickName();
+        }
 
         if (StringUtils.isNotEmpty(isFirst) && "true".equals(isFirst)) {
             return this.saveOrUpdateFirstInformationQueryData(primaryKeyId, tableId, businessId, fileName, classify, sourceType, sourceUrl, pdfUrl, firstFileName, linkDataList);
@@ -376,9 +391,9 @@ public class InformationQueryServiceImpl extends BaseServiceImpl<InformationQuer
                 }
 
                 //拼接填报人信息
-                String fileUser = user.getUserId() + "-" + user.getNickName();
+                String fileUser = userId + "-" + userNmae;
                 if (StringUtils.isNotEmpty(oldData.getFileUserIdAndName())) {
-                    if (!oldData.getFileUserIdAndName().contains(user.getUserId().toString())) {
+                    if (!oldData.getFileUserIdAndName().contains(userId.toString())) {
                         //不包含,拼接
                         oldData.setFileUserIdAndName(oldData.getFileUserIdAndName() + "," + fileUser);
                     }
@@ -387,7 +402,7 @@ public class InformationQueryServiceImpl extends BaseServiceImpl<InformationQuer
                 }
 
                 oldData.setUpdateTime(new Date());
-                oldData.setUpdateUser(user.getUserId());
+                oldData.setUpdateUser(userId);
 
                 List<String> linkIds = linkDataList.stream().map(json -> json.getString("id")).distinct().collect(Collectors.toList());
                 if (linkIds.size() > 0) {
@@ -418,17 +433,16 @@ public class InformationQueryServiceImpl extends BaseServiceImpl<InformationQuer
                 //流程状态,默认未上报
                 newData.setStatus(0);
                 //填报人ID及姓名
-                newData.setFileUserIdAndName(user.getUserId() + "-" + user.getNickName());
+                newData.setFileUserIdAndName(userId + "-" + userNmae);
                 //数据源类型
                 newData.setSourceType(sourceType);
-                newData.setCreateUser(user.getUserId());
+                newData.setCreateUser(userId);
                 newData.setCreateTime(new Date());
 
                 List<String> linkIds = linkDataList.stream().map(json -> json.getString("id")).distinct().collect(Collectors.toList());
                 if (linkIds.size() > 0) {
                     newData.setSjRecordIds(StringUtils.join(linkIds, ","));
                 }
-
                 //保存数据
                 this.baseMapper.insert(newData);
             }
@@ -908,16 +922,59 @@ public class InformationQueryServiceImpl extends BaseServiceImpl<InformationQuer
 
     @Override
     public void delAsyncWbsTree(String contractId) {
-        //模糊匹配所有以contractId开头的所有合同段节点key值
-        Set<String> keysByNodes = RedisTemplate.keys("blade-manager::contract:wbstree:" + contractId + "*");
-        if (keysByNodes != null) {
-            RedisTemplate.delete(keysByNodes);
-        }
+        ContractInfo contractInfo = jdbcTemplate.query("select id,contract_type from m_contract_info where id = " + contractId, new BeanPropertyRowMapper<>(ContractInfo.class)).stream().findAny().orElse(null);
+
+        /*================ 监理合同段 ================*/
+        if (contractInfo != null && (new Integer("2").equals(contractInfo.getContractType()) || new Integer("3").equals(contractInfo.getContractType()))) {
+            String sql = "select * from m_contract_relation_jlyz where contract_id_jlyz = " + contractInfo.getId();
+            List<Long> record_SG = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(ContractRelationJlyz.class)).stream().map(ContractRelationJlyz::getContractIdSg).collect(Collectors.toList());
+            if (record_SG.size() > 0) {
+                for (Long sgId : record_SG) {
+                    //模糊匹配所有以contractId开头的所有合同段节点key值
+                    Set<String> keysByNodes = RedisTemplate.keys("blade-manager::contract:wbstree:" + sgId + "*");
+                    if (keysByNodes != null) {
+                        RedisTemplate.delete(keysByNodes);
+                    }
+
+                    //模糊匹配所有以contractId开头的所有资料填报key值
+                    Set<String> keysByInformationQuery = RedisTemplate.keys("blade-manager::contract:wbstree:byInformationQuery:" + sgId + "*");
+                    if (keysByInformationQuery != null) {
+                        RedisTemplate.delete(keysByInformationQuery);
+                    }
+
+                    //模糊匹配所有以contractId开头的所有节点计算统计key值
+                    Set<String> keysParentCount = RedisTemplate.keys("blade-manager::contract:wbstree:byParentCountNodes:" + sgId + "*");
+                    if (keysParentCount != null) {
+                        RedisTemplate.delete(keysParentCount);
+                    }
+
+                    //删除合同段本地缓存
+                    wbsTreeContractClient.deleteContractLocalCache(String.valueOf(sgId));
+                }
+            }
+
+            /*================ 施工合同段 ================*/
+        } else if (contractInfo != null && new Integer("1").equals(contractInfo.getContractType())) {
+            //模糊匹配所有以contractId开头的所有合同段节点key值
+            Set<String> keysByNodes = RedisTemplate.keys("blade-manager::contract:wbstree:" + contractId + "*");
+            if (keysByNodes != null) {
+                RedisTemplate.delete(keysByNodes);
+            }
+
+            //模糊匹配所有以contractId开头的所有资料填报key值
+            Set<String> keysByInformationQuery = RedisTemplate.keys("blade-manager::contract:wbstree:byInformationQuery:" + contractId + "*");
+            if (keysByInformationQuery != null) {
+                RedisTemplate.delete(keysByInformationQuery);
+            }
+
+            //模糊匹配所有以contractId开头的所有节点计算统计key值
+            Set<String> keysParentCount = RedisTemplate.keys("blade-manager::contract:wbstree:byParentCountNodes:" + contractId + "*");
+            if (keysParentCount != null) {
+                RedisTemplate.delete(keysParentCount);
+            }
 
-        //模糊匹配所有以contractId开头的所有资料填报key值
-        Set<String> keysByInformationQuery = RedisTemplate.keys("blade-manager::contract:wbstree:byInformationQuery:" + contractId + "*");
-        if (keysByInformationQuery != null) {
-            RedisTemplate.delete(keysByInformationQuery);
+            //删除合同段本地缓存
+            wbsTreeContractClient.deleteContractLocalCache(contractId);
         }
     }
 

+ 11 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/UserOpinionFlowServiceImpl.java

@@ -69,4 +69,15 @@ public class UserOpinionFlowServiceImpl extends BaseServiceImpl<UserOpinionFlowM
         return this.baseMapper.selectIsSolveByUserOpinionKey(userOpinionKey);
     }
 
+    @Override
+    public List<UserOpinionFlowVO> queryUserOpinionFlowsByConcatenatedIds(List<String> concatenatedList) {
+        List<UserOpinionFlow> result = this.baseMapper.queryUserOpinionFlowsByConcatenatedIds(concatenatedList);
+        List<UserOpinionFlowVO> resultVo = JSONArray.parseArray(JSONObject.toJSONString(result), UserOpinionFlowVO.class);
+        resultVo.forEach(vo -> {
+            vo.setCurrent(new Integer("1").equals(vo.getIsCurrent()));
+            vo.setCurrentBol(new Integer("2").equals(vo.getIsCurrent()));
+        });
+        return resultVo;
+    }
+
 }

+ 53 - 6
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/UserOpinionServiceImpl.java

@@ -1,6 +1,7 @@
 package org.springblade.business.service.impl;
 
 import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@@ -23,13 +24,17 @@ import org.springblade.core.secure.BladeUser;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.manager.dto.SaveUserInfoByProjectDTO;
 import org.springblade.manager.feign.SaveUserInfoByProjectClient;
+import org.springblade.system.entity.Role;
 import org.springblade.system.feign.ISysClient;
 import org.springblade.system.user.entity.User;
 import org.springblade.system.user.feign.IUserClient;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 
 import java.util.*;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 /**
@@ -56,6 +61,8 @@ public class UserOpinionServiceImpl extends BaseServiceImpl<UserOpinionMapper, U
 
     private final SaveUserInfoByProjectClient saveUserInfoByProjectClient;
 
+    private final JdbcTemplate jdbcTemplate;
+
     @Override
     public Integer getOpinionNumber(String userId) {
         return this.baseMapper.getOpinionNumber(userId);
@@ -85,6 +92,34 @@ public class UserOpinionServiceImpl extends BaseServiceImpl<UserOpinionMapper, U
             List<Long> userOpinionKeys = finalResult.stream().map(BusinessUserOpinionVO::getUserOpinionId).distinct().collect(Collectors.toList());
             List<UserOpinionFile> allFile = this.userOpinionFileService.selectUserOpinionFileByUserOpinionKeys(userOpinionKeys);
 
+            /*所有工单最新状态userOpinionFlowGroupMap*/
+            List<String> concatenatedList = finalResult.stream()
+                    .filter(obj -> ObjectUtil.isNotEmpty(obj.getUserOpinionId()) && ObjectUtil.isNotEmpty(obj.getNewNumber()))
+                    .map(obj -> obj.getUserOpinionId() + "___" + obj.getNewNumber())
+                    .map(String::valueOf)
+                    .collect(Collectors.toList());
+            List<UserOpinionFlowVO> UserOpinionFlowVOList = this.userOpinionFlowService.queryUserOpinionFlowsByConcatenatedIds(concatenatedList);
+            Map<String, List<UserOpinionFlowVO>> userOpinionFlowGroupMap = UserOpinionFlowVOList.stream()
+                    .filter(vo -> Objects.nonNull(vo.getUserOpinionId()) && Objects.nonNull(vo.getNumber()))
+                    .collect(Collectors.groupingBy(
+                            vo -> vo.getUserOpinionId() + vo.getNumber() + ""
+                    ));
+
+            /*获取所有提交人userOpinionMap*/
+            List<UserOpinion> userOpinionList = this.getBaseMapper().selectBatchIds(userOpinionKeys);
+            Map<Long, UserOpinion> userOpinionMap = userOpinionList.stream().collect(Collectors.toMap(UserOpinion::getId, Function.identity()));
+
+            /*获取创建人信息userMap*/
+            List<Long> createUserIds = userOpinionList.stream().map(UserOpinion::getCreateUser).collect(Collectors.toList());
+            List<User> userList = this.userClient.userInfoByIds(createUserIds);
+            Map<Long, User> userMap = userList.stream().distinct().collect(Collectors.toMap(User::getId, Function.identity()));
+
+            /*获取用户与项目关系信息saveUserInfoByProjectGroupMap*/
+            Map<String, List<SaveUserInfoByProjectDTO>> saveUserInfoByProjectGroupMap = this.saveUserInfoByProjectClient.searchUserInfoAndProjectByUserIds(createUserIds).stream().collect(Collectors.groupingBy(SaveUserInfoByProjectDTO::getUserId));
+
+            /*获取角色信息roleMap*/
+            Map<Long, Role> roleMap = jdbcTemplate.query("SELECT id,role_name FROM blade_role WHERE is_deleted = 0", new BeanPropertyRowMapper<>(Role.class)).stream().collect(Collectors.toMap(Role::getId, Function.identity()));
+
             //设置附件信息
             finalResult.forEach(vo -> {
                 List<String> imageUrls = new ArrayList<>();
@@ -103,7 +138,8 @@ public class UserOpinionServiceImpl extends BaseServiceImpl<UserOpinionMapper, U
                 vo.setImageUrl(imageUrls);
 
                 //获取当前工单最新状态
-                List<UserOpinionFlowVO> newFlow = this.userOpinionFlowService.queryCurrentUserOpinionFlowByUserOpinionId(String.valueOf(vo.getUserOpinionId()), vo.getNewNumber());
+                /*List<UserOpinionFlowVO> newFlow = this.userOpinionFlowService.queryCurrentUserOpinionFlowByUserOpinionId(String.valueOf(vo.getUserOpinionId()), vo.getNewNumber());*/
+                List<UserOpinionFlowVO> newFlow = userOpinionFlowGroupMap.getOrDefault(vo.getUserOpinionId() + vo.getNewNumber() + "", null);
                 if (newFlow != null && newFlow.size() > 0) {
                     //获取退后阶段
                     UserOpinionFlowVO flow = newFlow.get(3);
@@ -156,13 +192,16 @@ public class UserOpinionServiceImpl extends BaseServiceImpl<UserOpinionMapper, U
                 }
 
                 //获取提交人
-                UserOpinion opinion = this.getById(vo.getUserOpinionId());
+                //UserOpinion opinion = this.getById(vo.getUserOpinionId());
+                UserOpinion opinion = userOpinionMap.getOrDefault(vo.getUserOpinionId(), null);
                 if (opinion != null) {
                     vo.setSubmitUserName(opinion.getCreateUserName());
-                    User user = this.userClient.userInfoById(opinion.getCreateUser()).getData();
+                    //User user = this.userClient.userInfoById(opinion.getCreateUser()).getData();
+                    User user = userMap.getOrDefault(opinion.getCreateUser(), null);
                     if (user != null) {
                         vo.setSubmitPhone(user.getPhone());
-                        List<SaveUserInfoByProjectDTO> userRoleList = this.saveUserInfoByProjectClient.searchUserInfoAndProject2(opinion.getCreateUser().toString());
+                        //List<SaveUserInfoByProjectDTO> userRoleList = this.saveUserInfoByProjectClient.searchUserInfoAndProject2(opinion.getCreateUser().toString());
+                        List<SaveUserInfoByProjectDTO> userRoleList = saveUserInfoByProjectGroupMap.getOrDefault(opinion.getCreateUser().toString(), null);
                         //用户角色
                         String roleIds = user.getRoleId();
                         if (userRoleList != null && userRoleList.size() > 0) {
@@ -172,8 +211,16 @@ public class UserOpinionServiceImpl extends BaseServiceImpl<UserOpinionMapper, U
                                 roleIds = userRoleList.stream().map(SaveUserInfoByProjectDTO::getRoleId).distinct().collect(Collectors.joining(","));
                             }
                         }
-                        List<String> roleNames = this.sysClient.getRoleNames(roleIds).getData();
-                        if (roleNames != null && roleNames.size() > 0) {
+
+                        List<String> roleNames = new ArrayList<>();
+                        for (String roleId : roleIds.split(",")) {
+                            Role role = roleMap.getOrDefault(Long.parseLong(roleId), null);
+                            if (role != null) {
+                                roleNames.add(role.getRoleName());
+                            }
+                        }
+                        //List<String> roleNames = this.sysClient.getRoleNames(roleIds).getData();
+                        if (/*roleNames != null &&*/ roleNames.size() > 0) {
                             vo.setSubmitUserRole(String.join(",", roleNames));
                         }
                     }

+ 63 - 3
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ArchiveTreeContractController.java

@@ -21,10 +21,12 @@ import io.swagger.annotations.*;
 import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import lombok.AllArgsConstructor;
 
+import javax.servlet.http.HttpServletRequest;
 import javax.validation.Valid;
 
 import lombok.extern.slf4j.Slf4j;
 import org.checkerframework.checker.units.qual.A;
+import org.springblade.archive.entity.ArchivesAuto;
 import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.cache.utils.CacheUtil;
 import org.springblade.core.log.exception.ServiceException;
@@ -43,14 +45,12 @@ import org.springblade.manager.feign.ContractClient;
 import org.springblade.manager.service.IArchiveTreeService;
 import org.springblade.manager.service.IContractInfoService;
 import org.springblade.manager.service.impl.ArchiveTreeContractSyncImpl;
-import org.springblade.manager.vo.ArchiveTreeContractVO2;
+import org.springblade.manager.vo.*;
 
-import org.springblade.manager.vo.ArchiveTreeContractVO4;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.RequestParam;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.springblade.manager.entity.ArchiveTreeContract;
-import org.springblade.manager.vo.ArchiveTreeContractVO;
 import org.springblade.manager.wrapper.ArchiveTreeContractWrapper;
 import org.springblade.manager.service.IArchiveTreeContractService;
 import org.springblade.core.boot.ctrl.BladeController;
@@ -448,4 +448,64 @@ public class ArchiveTreeContractController extends BladeController {
 
         return R.success("开始同步合同段,请耐心等待" );
     }
+
+    /**
+     * 在线验收-确认抽检范围
+     */
+    @GetMapping("/getUnitAllNode")
+    @ApiOperationSupport(order = 20)
+    @ApiOperation(value = "档案在线验收-确认抽检范围", notes = "传入选择参数")
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "projectId", value = "项目id"),
+            @ApiImplicitParam(name = "types", value = "1业主2监理3施工4影像5竣工图")
+    })
+    public R<List<InspectTreeVO>> getUnitAllNode(@RequestParam Long projectId, @RequestParam String types) {
+        List<InspectTreeVO> list = archiveTreeContractService.getUnitAllNode(projectId,types);
+        return R.data(list);
+    }
+
+    /**
+     * 在线验收-确认并进入抽检
+     */
+    @PostMapping("/saveAllSelectNodes")
+    @ApiOperationSupport(order = 21)
+    @ApiOperation(value = "档案在线验收-确认并进入抽检", notes = "传入选择参数")
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "ids", value = "选择的节点,逗号拼接")
+    })
+    public R saveAllSelectNodes(@RequestBody Map<String, String> map) {
+        archiveTreeContractService.saveAllSelectNodes(map);
+        return R.data("分配成功");
+    }
+
+    /**
+     * 在线验收-我验收的案卷
+     */
+    @GetMapping("/lazyTree")
+    @ApiOperationSupport(order = 22)
+    @ApiOperation(value = "档案在线验收-我验收的案卷", notes = "懒加载树,传入父id和项目id,返回子集合")
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "parentId", value = "父id,首节点传0"),
+            @ApiImplicitParam(name = "projectId", value = "项目id")
+    })
+    public R<List<MyInspectTreeVO>> lazyTree(@RequestParam Long parentId, @RequestParam Long projectId) {
+        List<MyInspectTreeVO> list = archiveTreeContractService.lazyTree(parentId, projectId);
+        return R.data(list);
+    }
+
+    /**
+     * 在线验收-开始抽检
+     */
+    @GetMapping("/startInspect")
+    @ApiOperationSupport(order = 22)
+    @ApiOperation(value = "档案在线验收-开始抽检", notes = "返回true跳转初始化验收,返回false跳转档案初检")
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "projectId", value = "项目id")
+    })
+    public R<Boolean> startInspect(@RequestParam Long projectId) {
+        return R.data(archiveTreeContractService.startInspect(projectId));
+    }
+
+
+
 }

+ 189 - 175
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java

@@ -64,6 +64,8 @@ import org.springblade.resource.feign.IOSSClient;
 import org.springblade.resource.feign.NewIOSSClient;
 import org.springblade.resource.vo.NewBladeFile;
 import org.springblade.system.cache.ParamCache;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.transaction.annotation.Transactional;
@@ -117,15 +119,12 @@ public class ExcelTabController extends BladeController {
     // 元素信息表-
     private final IWbsTreeContractService wbsTreeContractService;
 
-    private final WbsTreeContractServiceImpl wbsTreeContractServiceImpl;
-
     private final WbsTreePrivateMapper wbsTreePrivateMapper;
 
     private final JdbcTemplate jdbcTemplate;
 
     private final ExcelTabMapper excelTabMapper;
 
-
     // 表单附件信息
     private final ITableFileService tableFileService;
 
@@ -148,6 +147,8 @@ public class ExcelTabController extends BladeController {
 
     private final IWbsParamService wbsParamService;
 
+    @Autowired
+    StringRedisTemplate RedisTemplate;
 
     /**
      * 详情
@@ -313,7 +314,7 @@ public class ExcelTabController extends BladeController {
         BladeFile bladeFile = newIOSSClient.uploadFile(file.getOriginalFilename(), exceUrl);
         // 解析原始excel
 
-      //  BladeFile bladeFileR = newIOSSClient.uploadFileByInputStream(file);
+        //  BladeFile bladeFileR = newIOSSClient.uploadFileByInputStream(file);
         detail.setExtension(file.getOriginalFilename());
         detail.setFileUrl(bladeFile.getLink());
         detail.setFileType(3); // 表示为清表信息  1 表示祖节点  2 表示为节点信息 3 表示清表
@@ -624,7 +625,7 @@ public class ExcelTabController extends BladeController {
     @ApiImplicitParams(value = {
             @ApiImplicitParam(name = "pkeyId", value = "pkeyId", required = true)
     })
-    public R getExcelHtmlByBuss(Long pkeyId) throws Exception {
+    public R getExcelHtmlByBuss(Long pkeyId){
 
         WbsTreeContract wbsTreeContract = wbsTreeContractService.getBaseMapper().selectOne(Wrappers.<WbsTreeContract>query().lambda()
                 .eq(WbsTreeContract::getPKeyId, pkeyId));
@@ -635,74 +636,75 @@ public class ExcelTabController extends BladeController {
             return R.fail("暂无表单!");
         }
 
-        String fileUrl = wbsTreeContract.getHtmlUrl();
-        InputStream fileInputStream = FileUtils.getInputStreamByUrl(fileUrl);
-
-        String htmlString = IoUtil.readToString(fileInputStream);
-        htmlString = htmlString.replaceAll("placeholder", "placeholderxx");
-        htmlString = htmlString.replaceAll("title", "titlexx");
-
-        // 远程搜索配置
-        Document doc = Jsoup.parse(htmlString);
-        int maxCol = doc.select("Col").size();
-        Element table = doc.select("table").first();
-        Elements hc = doc.select("hc-form-select-search");
-        if (hc.size() >= 1) {
-            for (int i = 0; i < hc.size(); i++) {
-                Element datax = hc.get(i);
-                datax.removeAttr("pkeyId");
-                datax.removeAttr("contractId");
-                datax.attr("pkeyId", pkeyId + "");
-                datax.attr("contractId", wbsTreeContract.getContractId());
+        try {
+            String fileUrl = wbsTreeContract.getHtmlUrl();
+            InputStream fileInputStream = FileUtils.getInputStreamByUrl(fileUrl);
+
+            String htmlString = IoUtil.readToString(fileInputStream);
+            htmlString = htmlString.replaceAll("placeholder", "placeholderxx");
+            htmlString = htmlString.replaceAll("title", "titlexx");
+
+            // 远程搜索配置
+            Document doc = Jsoup.parse(htmlString);
+            int maxCol = doc.select("Col").size();
+            Element table = doc.select("table").first();
+            Elements hc = doc.select("hc-form-select-search");
+            if (hc.size() >= 1) {
+                for (int i = 0; i < hc.size(); i++) {
+                    Element datax = hc.get(i);
+                    datax.removeAttr("pkeyId");
+                    datax.removeAttr("contractId");
+                    datax.attr("pkeyId", pkeyId + "");
+                    datax.attr("contractId", wbsTreeContract.getContractId());
+                }
             }
-        }
 
-        // 远程搜索配置2-设计强度搜索
-        Elements hc2 = doc.select("hc-form-select-search2");
-        if (hc2.size() >= 1) {
-            for (int i = 0; i < hc2.size(); i++) {
-                Element datax = hc2.get(i);
-                datax.removeAttr("contractId");
-                datax.attr("contractId", wbsTreeContract.getContractId());
+            // 远程搜索配置2-设计强度搜索
+            Elements hc2 = doc.select("hc-form-select-search2");
+            if (hc2.size() >= 1) {
+                for (int i = 0; i < hc2.size(); i++) {
+                    Element datax = hc2.get(i);
+                    datax.removeAttr("contractId");
+                    datax.attr("contractId", wbsTreeContract.getContractId());
+                }
             }
-        }
 
-        // 标题解决
-        ProjectInfo projectInfo = projectInfoService.getById(wbsTreeContract.getProjectId());
-        //判断是否是水利水电表,水利水电项目名14,表名12 。   其他表都是18
-        Boolean isWater = false;
-        ExcelTab tab = excelTabMapper.getWaterByTableId(wbsTreeContract.getExcelId());
-        if (tab != null) {
-            isWater = true;
-        }
+            // 标题解决
+            ProjectInfo projectInfo = projectInfoService.getById(wbsTreeContract.getProjectId());
+            //判断是否是水利水电表,水利水电项目名14,表名12 。   其他表都是18
+            Boolean isWater = false;
+            ExcelTab tab = excelTabMapper.getWaterByTableId(wbsTreeContract.getExcelId());
+            if (tab != null) {
+                isWater = true;
+            }
 
-        // 添加标题显示
-        Elements trs = table.select("tr");
-        for (int i = 1; i < 6; i++) {
-            Element tr = trs.get(i);
-            Elements tds = tr.select("td");
-            for (int j = 0; j < tds.size(); j++) {
-                Element data = tds.get(j);
-                int colspan = data.attr("COLSPAN").equals("") ? 0 : Integer.parseInt(data.attr("COLSPAN"));
-                String style = data.attr("style");
-                if (style.indexOf("font-size") >= 0) {
-                    int fontsize = Integer.parseInt(style.substring(style.indexOf("font-size:") + 10, style.indexOf(".0pt")));
-                    if (isWater) {
-                        if (StringUtils.isNotEmpty(data.text()) && fontsize >= 12) {
-                            trs.get(i - 1).select("td").get(0).text(projectInfo.getProjectName());
-                        }
-                    } else {
-                        if (StringUtils.isNotEmpty(data.text()) && fontsize >= 14) {
-                            trs.get(i - 1).select("td").get(0).text(projectInfo.getProjectName());
+            // 添加标题显示
+            Elements trs = table.select("tr");
+            for (int i = 1; i < 6; i++) {
+                Element tr = trs.get(i);
+                Elements tds = tr.select("td");
+                for (int j = 0; j < tds.size(); j++) {
+                    Element data = tds.get(j);
+                    int colspan = data.attr("COLSPAN").equals("") ? 0 : Integer.parseInt(data.attr("COLSPAN"));
+                    String style = data.attr("style");
+                    if (style.indexOf("font-size") >= 0) {
+                        int fontsize = Integer.parseInt(style.substring(style.indexOf("font-size:") + 10, style.indexOf(".0pt")));
+                        if (isWater) {
+                            if (StringUtils.isNotEmpty(data.text()) && fontsize >= 12) {
+                                trs.get(i - 1).select("td").get(0).text(projectInfo.getProjectName());
+                            }
+                        } else {
+                            if (StringUtils.isNotEmpty(data.text()) && fontsize >= 14) {
+                                trs.get(i - 1).select("td").get(0).text(projectInfo.getProjectName());
+                            }
                         }
                     }
                 }
             }
-        }
 
-        // 获取公式颜色
-        String tabName = wbsTreeContract.getInitTableName();
-        // 字段查询 获取公式字段
+            // 获取公式颜色
+            String tabName = wbsTreeContract.getInitTableName();
+            // 字段查询 获取公式字段
 //        String colkeys = "SELECT e_key from m_table_info a ,m_wbs_form_element b WHERE a.tab_en_name = '" + tabName + "' and a.id=b.f_id and b.id  in(SELECT element_id from m_element_formula_mapping c where c.is_deleted=0) ";
 //
 //        List<Map<String, Object>> maps = jdbcTemplate.queryForList(colkeys);
@@ -723,16 +725,19 @@ public class ExcelTabController extends BladeController {
 //                }
 //            }
 //        }
-        WbsTreeContract process = this.wbsTreeContractService.getOne(Wrappers.<WbsTreeContract>lambdaQuery()
-                .eq(WbsTreeContract::getId, wbsTreeContract.getParentId())
-                .eq(WbsTreeContract::getContractId, wbsTreeContract.getContractId())
-                .eq(WbsTreeContract::getWbsId, wbsTreeContract.getWbsId()).last("limit 1"));
-        if (process != null) {
-            this.excelTabService.gsColor(pkeyId, process.getPKeyId().toString(), wbsTreeContract.getProjectId(), doc);
+            WbsTreeContract process = this.wbsTreeContractService.getOne(Wrappers.<WbsTreeContract>lambdaQuery()
+                    .eq(WbsTreeContract::getId, wbsTreeContract.getParentId())
+                    .eq(WbsTreeContract::getContractId, wbsTreeContract.getContractId())
+                    .eq(WbsTreeContract::getWbsId, wbsTreeContract.getWbsId()).last("limit 1"));
+            if (process != null) {
+                this.excelTabService.gsColor(pkeyId, process.getPKeyId().toString(), wbsTreeContract.getProjectId(), doc);
+            }
+            doc.select("Col").remove();
+            fileInputStream.close();
+            return R.data(table + "");
+        }catch (Exception e){
+            return R.fail("暂无表单!");
         }
-        doc.select("Col").remove();
-        fileInputStream.close();
-        return R.data(table + "");
     }
 
 
@@ -1801,7 +1806,7 @@ public class ExcelTabController extends BladeController {
         // 解析 style
         Document doc = Jsoup.parse(htmlString);
         Element table = doc.select("table").first();
-        table.select("table").attr("min-width","-webkit-fill-available");
+        table.select("table").attr("min-width", "-webkit-fill-available");
         doc.select("Col").remove();
         fileInputStream.close();
         return R.data(table + "");
@@ -1815,7 +1820,7 @@ public class ExcelTabController extends BladeController {
             @ApiImplicitParam(name = "pkeyId", value = "pkeyId", required = true)
     })
     public R getBussDataInfo(Long pkeyId) throws FileNotFoundException {
-        return excelTabService.getBussDataInfo(pkeyId, 0);
+        return R.data(excelTabService.getBussDataInfo(pkeyId, 0,true));
     }
 
 
@@ -1960,7 +1965,7 @@ public class ExcelTabController extends BladeController {
         String sql = "select pdf_url,e_visa_pdf_url,pdf_trial_url,pdf_trial_url_position,status from u_information_query where classify='" + classify + "' and wbs_id='" + nodeId + "' and contract_id='" + contractId + "'";
         List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);
         if (maps == null || maps.size() == 0) {
-            WbsTreeContract contract = wbsTreeContractService.getOne(new LambdaQueryWrapper<WbsTreeContract>().eq(WbsTreeContract::getPKeyId,nodeId));
+            WbsTreeContract contract = wbsTreeContractService.getOne(new LambdaQueryWrapper<WbsTreeContract>().eq(WbsTreeContract::getPKeyId, nodeId));
             String fileName = this.wbsParamService.createFileTitle(contract);
             InformationQuery query = new InformationQuery();
             query.setId(SnowFlakeUtil.getId());
@@ -1972,7 +1977,7 @@ public class ExcelTabController extends BladeController {
             query.setType((contract.getIsExpernode() == null || contract.getIsExpernode() <= 0) ? 1 : 2);
             query.setName(fileName);
             query.setCreateTime(new Date());
-            query.setFileUserIdAndName(AuthUtil.getUserId()+"-"+AuthUtil.getUserName());
+            query.setFileUserIdAndName(AuthUtil.getUserId() + "-" + AuthUtil.getUserName());
             informationQueryClient.saveInfo(query);
         }
         excelTabService.getBussPdfs(nodeId, classify, contractId, projectId);
@@ -2011,6 +2016,12 @@ public class ExcelTabController extends BladeController {
     })
     public R getPdfS(String nodeId, String classify, String contractId) throws FileNotFoundException {
         String file_path = FileUtils.getSysLocalFileUrl();
+        Boolean aBoolean = RedisTemplate.hasKey("pdf-" + nodeId+"-"+classify);
+        if(aBoolean){
+            Long expire = RedisTemplate.getExpire("pdf-" + nodeId + "-" + classify);
+            return R.fail("pdf正在生成,还有"+expire+"秒");
+        }
+
         //获取节点下的所有表单,和附件,如果表单全是隐藏的,并且没有附件,则提示暂无数据
         String sql = "select pdf_url,e_visa_pdf_url,pdf_trial_url,pdf_trial_url_position,status from u_information_query where classify='" + classify + "' and wbs_id='" + nodeId + "' and contract_id='" + contractId + "'";
         List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);
@@ -2031,11 +2042,11 @@ public class ExcelTabController extends BladeController {
                 return R.fail("暂无PDF数据");
             } else {
                 // 由于独立附件 需要追加最后
-                List<TableFileVO> data = tableFileService.selectTableFileListByTen(Long.valueOf(nodeId+""));
+                List<TableFileVO> data = tableFileService.selectTableFileListByTen(Long.valueOf(nodeId + ""));
                 List<String> datainfo = new ArrayList<>();
                 datainfo.add(pdfUrl);
-                if(data!=null && data.size()>=1){
-                    for(TableFileVO tabsx :data){
+                if (data != null && data.size() >= 1) {
+                    for (TableFileVO tabsx : data) {
                         datainfo.add(tabsx.getUrl());
                     }
                     String listPdf = file_path + "/pdf/" + nodeId + ".pdf";
@@ -2046,7 +2057,7 @@ public class ExcelTabController extends BladeController {
                     FileUtils.mergePdfPublicMethods(datainfo, listPdf);
                     String netUrl = FileUtils.getNetUrl(listPdf);
                     return R.data(netUrl);
-                }else{
+                } else {
                     return R.data(pdfUrl);
                 }
             }
@@ -2106,10 +2117,7 @@ public class ExcelTabController extends BladeController {
     }
 
 
-
-
-
-    @PostMapping("/save_buss_data")
+    @PostMapping("/save_buss_data111")
     @ApiOperationSupport(order = 13)
     @ApiOperation(value = "填报页面数据保存", notes = "填报页面数据保存")
     public R saveBussData2(@Valid @RequestBody JSONObject dataInfo) throws Exception {
@@ -2131,16 +2139,14 @@ public class ExcelTabController extends BladeController {
         List<AppWbsTreeContractVO> tableAll = new ArrayList<>();
         List<TableInfo> tableInfoList = this.excelTabService.getTableInfoList(dataArray);
         if (tableInfoList != null) {
-            tableAll = wbsTreeContractService.searchNodeAllTable(nodeId, "1", contractId, projectId);
+            tableAll = wbsTreeContractService.searchNodeAllTable(nodeId, "1", contractId, projectId,null);
             List<Long> tableAllIds = tableAll.stream().map(AppWbsTreeContractVO::getPKeyId).collect(Collectors.toList());
             if (tableAll.size() > tableInfoList.size()) {
                 List<Long> exclude = tableInfoList.stream().map(TableInfo::getPkeyId).map(Long::parseLong).collect(Collectors.toList());
                 JSONArray extra = new JSONArray();
                 for (Long pk : tableAllIds) {
                     if (!exclude.contains(pk)) {
-                        R bussDataInfo = this.excelTabService.getBussDataInfo(pk, 1);
-                        @SuppressWarnings("unchecked")
-                        Map<String, Object> jo = (Map<String, Object>) bussDataInfo.getData();
+                        Map<String, Object> jo = this.excelTabService.getBussDataInfo(pk, 1);
                         if (ObjectUtils.isNotEmpty(jo)) {
                             jo.put("pkeyId", pk);
                             extra.add(jo);
@@ -2178,6 +2184,7 @@ public class ExcelTabController extends BladeController {
         if (tableInfoList != null) {
             for (TableInfo tableInfo : tableInfoList) {
                 R bussPdfInfo = excelTabService.getBussPdfInfo(Long.parseLong(tableInfo.getPkeyId()));
+
                 if (ObjectUtil.isEmpty(bussPdfInfo) || bussPdfInfo.getCode() != 200) {
                     //如果返回的单张pdfUrl为空,那么表示发生异常,返回异常信息
                     errorPKeyIds.add(tableInfo.getPkeyId());
@@ -2189,7 +2196,7 @@ public class ExcelTabController extends BladeController {
         if (errorPKeyIds.size() > 0) {
             List<AppWbsTreeContractVO> errorTabs = new LinkedList<>();
             for (AppWbsTreeContractVO appWbsTreeContractVO : tableAll) {
-                if (errorPKeyIds.contains(appWbsTreeContractVO.getPKeyId().toString())){
+                if (errorPKeyIds.contains(appWbsTreeContractVO.getPKeyId().toString())) {
                     errorTabs.add(appWbsTreeContractVO);
                 }
             }
@@ -2411,8 +2418,8 @@ public class ExcelTabController extends BladeController {
                                                 sheet.getCellRange(y1, x1).getStyle().setShrinkToFit(true);
 
                                             } else if (data.html().indexOf("hc-form-checkbox-group") >= 0) {
-                                                 CellRange cellRange = sheet.getCellRange(y1, x1);
-                                                 String exceVal = cellRange.getValue().replaceAll(" ", "");
+                                                CellRange cellRange = sheet.getCellRange(y1, x1);
+                                                String exceVal = cellRange.getValue().replaceAll(" ", "");
                                                 //如果有□ 代表 自动生成  如果没有 代表后期添加 需要显示html 中的值
                                                 if (exceVal.indexOf("□") >= 0) {
                                                     if (myData.equals("1")) {
@@ -2420,7 +2427,7 @@ public class ExcelTabController extends BladeController {
                                                     }
                                                 } else {
                                                     List<Node> nodes = data.childNodes();
-                                                    Node node = nodes.get(nodes.size() -1);
+                                                    Node node = nodes.get(nodes.size() - 1);
                                                     String dataJson = node.attr(":objs");
                                                     if (StringUtils.isNotEmpty(dataJson)) {
                                                         JSONArray jsonArray = JSONArray.parseArray(dataJson);
@@ -3544,7 +3551,7 @@ public class ExcelTabController extends BladeController {
     @ApiImplicitParams(value = {
             @ApiImplicitParam(name = "pkeyId", value = "pkeyId", required = true)
     })
-    public R getHtmlBussCols(Long pkeyId) throws Exception {
+    public R getHtmlBussCols(Long pkeyId)  {
         String file_path = ParamCache.getValue(CommonConstant.SYS_LOCAL_URL);
         String sys_file_net_url = ParamCache.getValue(CommonConstant.SYS_FILE_NET_URL);
         WbsTreeContract wbsTreeContract = wbsTreeContractService.getBaseMapper().selectOne(Wrappers.<WbsTreeContract>query().lambda()
@@ -3555,51 +3562,54 @@ public class ExcelTabController extends BladeController {
         if (wbsTreeContract.getHtmlUrl() == null) {
             return R.fail("暂无表单!");
         }
-
-        String fileUrl = wbsTreeContract.getHtmlUrl();
-        File file1 = ResourceUtil.getFile(fileUrl);
-        InputStream fileInputStream = null;
-        if (file1.exists()) {
-            fileInputStream = new FileInputStream(file1);
-        } else {
-            String path = sys_file_net_url + fileUrl.replaceAll("//", "/").replaceAll(file_path, "");
-            fileInputStream = CommonUtil.getOSSInputStream(path);
-        }
+        try {
+            String fileUrl = wbsTreeContract.getHtmlUrl();
+            File file1 = ResourceUtil.getFile(fileUrl);
+            InputStream fileInputStream = null;
+            if (file1.exists()) {
+                fileInputStream = new FileInputStream(file1);
+            } else {
+                String path = sys_file_net_url + fileUrl.replaceAll("//", "/").replaceAll(file_path, "");
+                fileInputStream = CommonUtil.getOSSInputStream(path);
+            }
 
 
-        String htmlString = IoUtil.readToString(fileInputStream);
-        // 解析 style
-        Document doc = Jsoup.parse(htmlString);
-        Element table = doc.select("table").first();
-        Elements trs = table.select("tr");
-
-        List<List<String>> redata = new ArrayList<>();
-        for (int i = 0; i < trs.size(); i++) {
-            Element tr = trs.get(i);
-            Elements tds = tr.select("td");
-            List<String> tdList = new ArrayList<>();
-            for (int j = 0; j < tds.size(); j++) {
-                Element element = tds.get(j);
-                if (element.html().indexOf("el-tooltip") >= 0) {
-                    element = element.children().get(0);
-                }
-                if (element.children().size() >= 1) {
-                    String keyname = element.children().get(0).attr("keyname");
-                    if (StringUtils.isNotEmpty(keyname)) {
-                        tdList.add(keyname);
+            String htmlString = IoUtil.readToString(fileInputStream);
+            // 解析 style
+            Document doc = Jsoup.parse(htmlString);
+            Element table = doc.select("table").first();
+            Elements trs = table.select("tr");
+
+            List<List<String>> redata = new ArrayList<>();
+            for (int i = 0; i < trs.size(); i++) {
+                Element tr = trs.get(i);
+                Elements tds = tr.select("td");
+                List<String> tdList = new ArrayList<>();
+                for (int j = 0; j < tds.size(); j++) {
+                    Element element = tds.get(j);
+                    if (element.html().indexOf("el-tooltip") >= 0) {
+                        element = element.children().get(0);
+                    }
+                    if (element.children().size() >= 1) {
+                        String keyname = element.children().get(0).attr("keyname");
+                        if (StringUtils.isNotEmpty(keyname)) {
+                            tdList.add(keyname);
+                        }
                     }
                 }
+                if (tdList != null && tdList.size() >= 1) {
+                    redata.add(tdList);
+                }
             }
-            if (tdList != null && tdList.size() >= 1) {
-                redata.add(tdList);
-            }
-        }
 
-        String[][] res = new String[redata.size()][]; // 存放转换结果的 二维数组
-        for (int i = 0; i < res.length; i++) { // 转换方法
-            res[i] = redata.get(i).toArray(new String[redata.get(i).size()]);
+            String[][] res = new String[redata.size()][]; // 存放转换结果的 二维数组
+            for (int i = 0; i < res.length; i++) { // 转换方法
+                res[i] = redata.get(i).toArray(new String[redata.get(i).size()]);
+            }
+            return R.data(res);
+        }catch (Exception e){
+            return R.fail("暂无表单!");
         }
-        return R.data(res);
     }
 
 
@@ -3800,52 +3810,53 @@ public class ExcelTabController extends BladeController {
     @PostMapping("/save_sigpdfInfo12313213")
     @ApiOperationSupport(order = 72)
     @ApiOperation(value = "pdf", notes = "pdf")
-    public void synPDFInfo(@RequestParam String contractid,@RequestParam String typeinfo){
-        String sqlInfo = "SELECT DISTINCT wbs_id,classify,contract_id,project_id,type from u_information_query where contract_id='"+contractid+"' and is_deleted=0 and type=1 and  classify='"+typeinfo+"' and wbs_id in(SELECT p_key_id from m_wbs_tree_contract where is_deleted=0 and contract_id='"+contractid+"')";
+    public void synPDFInfo(@RequestParam String contractid, @RequestParam String typeinfo) {
+        String sqlInfo = "SELECT DISTINCT wbs_id,classify,contract_id,project_id,type from u_information_query where contract_id='" + contractid + "' and is_deleted=0 and type=1 and  classify='" + typeinfo + "' and wbs_id in(SELECT p_key_id from m_wbs_tree_contract where is_deleted=0 and contract_id='" + contractid + "')";
         List<Map<String, Object>> maps = jdbcTemplate.queryForList(sqlInfo);
         System.out.println(maps.size());
 
-            int i=0;
-            if(maps!=null && maps.size()>=1){
-                for(Map<String, Object> dataMap:maps){
-                    String nodeId = dataMap.get("wbs_id")+"";
-                    String classify = dataMap.get("classify")+"";
-                    String contractId = dataMap.get("contract_id")+"";
-                    String projectId = dataMap.get("project_id")+"";
-                    List<AppWbsTreeContractVO> tableAll = wbsTreeContractService.searchNodeAllTable(nodeId, classify, contractId, projectId);
-                    if(tableAll!=null && tableAll.size()>=1){
-                        for(AppWbsTreeContractVO tab:tableAll){
-                            try {
-                                 excelTabService.getBussPdfInfo(Long.parseLong(tab.getPKeyId()+""));
-                            }catch (Exception e){
-                                e.printStackTrace();
-                            }finally {
-                                continue;
-                            }
+        int i = 0;
+        if (maps != null && maps.size() >= 1) {
+            for (Map<String, Object> dataMap : maps) {
+                String nodeId = dataMap.get("wbs_id") + "";
+                String classify = dataMap.get("classify") + "";
+                String contractId = dataMap.get("contract_id") + "";
+                String projectId = dataMap.get("project_id") + "";
+                List<AppWbsTreeContractVO> tableAll = wbsTreeContractService.searchNodeAllTable(nodeId, classify, contractId, projectId,null);
+                if (tableAll != null && tableAll.size() >= 1) {
+                    for (AppWbsTreeContractVO tab : tableAll) {
+                        try {
+                            excelTabService.getBussPdfInfo(Long.parseLong(tab.getPKeyId() + ""));
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                        } finally {
+                            continue;
                         }
                     }
-                    i=i+1;
-                    System.out.println("完成1---="+i);
-                    try {
-                        excelTabService.getBussPdfs(nodeId, classify, contractId, projectId);
-                    } catch (Exception e) {
-                        continue;
-                    }finally {
-                        continue;
-                    }
+                }
+                i = i + 1;
+                System.out.println("完成1---=" + i);
+                try {
+                    excelTabService.getBussPdfs(nodeId, classify, contractId, projectId);
+                } catch (Exception e) {
+                    continue;
+                } finally {
+                    continue;
                 }
             }
+        }
 
     }
 
 
     /**
      * 用户保存新接口
+     *
      * @param dataInfo
      * @return
      * @throws Exception
      */
-    @PostMapping("/save_buss_data2")
+    @PostMapping("/save_buss_data")
     @ApiOperationSupport(order = 13)
     @ApiOperation(value = "填报页面数据保存", notes = "填报页面数据保存")
     public R saveBussData(@Valid @RequestBody JSONObject dataInfo) throws Exception {
@@ -3856,13 +3867,18 @@ public class ExcelTabController extends BladeController {
         } else { //单个保存
             dataArray.add(dataInfo);
         }
-        this.excelTabService.formulaFillData2(dataArray,ExecuteType.INSPECTION);
-        return excelTabService.saveBussData(dataArray);
+        this.excelTabService.formulaFillData2(dataArray, ExecuteType.INSPECTION);
+        if(dataArray!=null && dataArray.size()>=1){
+            return excelTabService.saveBussData(dataArray);
+        }else{
+            return R.fail("公式报错,导致保存接口无入参数");
+        }
     }
 
 
     /**
      * 质检附件追加
+     *
      * @return ObjectStat
      */
     @SneakyThrows
@@ -3876,8 +3892,8 @@ public class ExcelTabController extends BladeController {
     })
     public R addBussFile(@RequestParam("file") MultipartFile[] file, String nodeId) {
         List<TableFile> fileList = new ArrayList<>();
-        if(file!=null && file.length>=1){
-            for (MultipartFile multipartFile:file){
+        if (file != null && file.length >= 1) {
+            for (MultipartFile multipartFile : file) {
                 R<BladeFile> bladeFile = iossClient.addFileInfo(multipartFile);
                 BladeFile bladeFile1 = bladeFile.getData();
 
@@ -3894,10 +3910,9 @@ public class ExcelTabController extends BladeController {
             }
             tableFileService.saveOrUpdateBatch(fileList);
             return R.data("操作成功");
-        }else{
+        } else {
             return R.data("请上传pdf");
         }
-
     }
 
 
@@ -3910,21 +3925,21 @@ public class ExcelTabController extends BladeController {
             @ApiImplicitParam(name = "classify", value = "classify", required = true),
             @ApiImplicitParam(name = "projectId", value = "projectId", required = true)
     })
-    public R synPDFInfo(String contractId,String nodeIds, String classify, String projectId) {
+    public R synPDFInfo(String contractId, String nodeIds, String classify, String projectId) {
 
-        if( contractId==null && StringUtils.isEmpty(contractId)){
+        if (contractId == null && StringUtils.isEmpty(contractId)) {
             return R.data("contractId不能为空");
         }
 
-        if(nodeIds==null && StringUtils.isEmpty(nodeIds)){
+        if (nodeIds == null && StringUtils.isEmpty(nodeIds)) {
             return R.data("nodeId不能为空");
         }
 
-        if(classify==null && StringUtils.isEmpty(classify)){
+        if (classify == null && StringUtils.isEmpty(classify)) {
             return R.data("classify不能为空");
         }
 
-        if(projectId==null && StringUtils.isEmpty(projectId)){
+        if (projectId == null && StringUtils.isEmpty(projectId)) {
             return R.data("projectId不能为空");
         }
 
@@ -3933,13 +3948,12 @@ public class ExcelTabController extends BladeController {
             for (String noId : nodeId) {
                 JSONObject js = new JSONObject();
                 JSONObject js2 = new JSONObject();
-                List<AppWbsTreeContractVO> tableAll = wbsTreeContractService.searchNodeAllTable(noId, classify, contractId, projectId);
+                List<AppWbsTreeContractVO> tableAll = wbsTreeContractService.searchNodeAllTable(noId, classify, contractId, projectId,null);
                 JSONArray array = new JSONArray();
                 if (tableAll != null && tableAll.size() >= 1) {
                     for (AppWbsTreeContractVO tab : tableAll) {
                         try {
-                            R bussDataInfo = excelTabService.getBussDataInfo(tab.getPKeyId(), 0);
-                            Map<String, Object> jo = (Map<String, Object>) bussDataInfo.getData();
+                            Map<String, Object> jo = excelTabService.getBussDataInfo(tab.getPKeyId(), 0);
                             String s = new Gson().toJson(jo);
                             //字符串转jsonobject
                             JSONObject obj = JSON.parseObject(s);
@@ -3962,7 +3976,7 @@ public class ExcelTabController extends BladeController {
                 js.put("dataInfo", js2);
                 this.saveBussData2(js);
             }
-        }catch (Exception e){
+        } catch (Exception e) {
             return null;
         }
         return R.data("成功");

+ 28 - 57
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsParamController.java

@@ -263,7 +263,7 @@ public class WbsParamController {
     @ApiOperation(value = "节点参数列表", notes = "节点参数列表")
     @GetMapping("/list")
     public R<List<WbsParamBean>> list3(@ApiParam(value = "节点id", required = true) Long wbsId) {
-        this.service.duplicate(wbsId);
+        /*this.service.duplicate(wbsId);*/
         List<WbsParam> data = this.service.list(Wrappers.<WbsParam>lambdaQuery()
                 .select(WbsParam::getId, WbsParam::getName, WbsParam::getK, WbsParam::getV, WbsParam::getRemark, WbsParam::getNodeId, WbsParam::getProjectId)
                 .eq(WbsParam::getNodeId, wbsId)
@@ -417,62 +417,7 @@ public class WbsParamController {
         return formula;
     }
 
-    /*private R<Object> duplicate() {删除重复节点参数配置,方法已经过时无法直接使用
-        try {
-            StopWatch stopWatch = new StopWatch();
-            stopWatch.start("节点参数查重及删除");
-            List<Map<String, Object>> mapList = this.jdbcTemplate.queryForList("select  node_id nodeId,k,count(*) num from m_wbs_param  where is_deleted=0 and type=1 GROUP BY node_id,k HAVING count(*)>1");
-            if (!mapList.isEmpty()) {
-                List<WbsParam> list = this.service.list(Wrappers.<WbsParam>lambdaQuery().in(WbsParam::getNodeId, mapList.stream().map(m -> m.get("nodeId")).collect(Collectors.toList())));
-                List<Long> removeWpIds = new ArrayList<>();
-                List<Long> removeMapingIds = new ArrayList<>();
-                List<Long> removeFormulaIds = new ArrayList<>();
-                Map<Long, Map<String, List<WbsParam>>> group = list.stream().collect(Collectors.groupingBy(WbsParam::getNodeId, LinkedHashMap::new, Collectors.groupingBy(WbsParam::getK)));
-                group.values().forEach(m -> {
-                    m.forEach((k, v) -> {
-                        List<Map<String, Object>> relationMap = this.jdbcTemplate.queryForList("select a.id paramId,b.id mappingId,b.formula_id formulaId from m_wbs_param a join m_element_formula_mapping b on a.id=b.param_id where b.scope=35 and a.id in(" + v.stream().map(WbsParam::getId).map(String::valueOf).collect(Collectors.joining("','", "'", "'")) + ") order by  b.update_time desc");
-                        if (!relationMap.isEmpty()) {
-                            Object id = relationMap.get(0).get("paramId");
-                            removeWpIds.addAll(v.stream().map(WbsParam::getId).filter(eId -> !StringUtils.isNotEquals(id, eId)).collect(Collectors.toList()));
-                            *//*同一道工序下,一个节点参数可能会关联多个元素,除了保留参数关联的以外全部添加到待删除列表*//*
-                            relationMap.stream().filter(x -> StringUtils.isNotEquals(x.get("paramId"), id)).forEach(e -> {
-                                removeMapingIds.add(Long.parseLong(e.get("mappingId").toString()));
-                                removeFormulaIds.add(Long.parseLong(e.get("formulaId").toString()));
-                            });
-                        } else {
-                            removeWpIds.addAll(v.stream().skip(1).map(WbsParam::getId).collect(Collectors.toList()));
-                        }
-                    });
-                });
-                System.out.println("查找到重复参数" + list.size() + "个");
-                System.out.println("待删除参数" + removeWpIds.size() + "个");
-                System.out.println("待删除中间关联" + removeMapingIds.size() + "个");
-                System.out.println("待删除公式" + removeFormulaIds.size() + "个");
-//                    batchDel(this.service,removeWpIds);
-//                    batchDel(this.elementFormulaMappingService,removeMapingIds);
-//                    batchDel(this.formulaService,removeFormulaIds);
-                Map<String, Integer> result = new HashMap<>();
-                result.put("查找到重复参数", list.size());
-                result.put("待删除参数", removeWpIds.size());
-                result.put("待删除中间关联", removeMapingIds.size());
-                result.put("待删除公式", removeFormulaIds.size());
-                stopWatch.stop();
-                Long totalTime = stopWatch.getTotalTimeMillis();
-                StaticLog.info("公式执行用时:{}", totalTime);
-                return R.data(result);
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        return R.fail("执行异常");
-    }*/
 
-    public <T> void  batchDel(BaseService<T> sv,List<Long> list){
-        if(sv!=null&&Func.isNotEmpty(list)) {
-            List<List<Long>> removeWpIdsList = BaseUtils.splitList(list, 1000);
-            removeWpIdsList.forEach(sv::deleteLogic);
-        }
-    }
 
     @GetMapping("/createFormulaForWp")
     public R<Object> createFormulaForWp() {
@@ -617,7 +562,33 @@ public class WbsParamController {
     }
 
 
-
+    @GetMapping("/remove-element-mapping")
+    public R<Object> removeMapping(){
+        long s = System.currentTimeMillis();
+        List<Map<String,Object>> listMap =this.jdbcTemplate.queryForList("select element_id elementId,param_id paramId,count(*) total,max(id) id  from m_element_formula_mapping  where is_deleted=0 and scope=35 GROUP BY element_id,param_id  HAVING count(*)>1 ORDER BY count(*) desc");
+        if(listMap.size()>0){
+            List<String> sqlList = new ArrayList<>();
+            for(Map<String,Object> map:listMap){
+                try {
+                    String sql = "update m_element_formula_mapping set is_deleted=1 ,update_time='2023-11-20 00:00:00' where element_id="+map.get("elementId")+" and param_id="+map.get("paramId")+" and id <>"+map.get("id");
+                    sqlList.add(sql);
+                }catch (Exception e){
+                    e.printStackTrace();
+                }
+            }
+            List<List<String>> segmentList = BaseUtils.splitList(sqlList,250);
+            segmentList.stream().map(l->String.join(";",l)).forEach(sl->{
+                try {
+                   // System.out.println(s);
+                    this.jdbcTemplate.execute(sl);
+                }catch (Exception e){
+                    e.printStackTrace();
+                }
+            });
+            return R.data("处理语句"+listMap.size()+"条,耗时"+(System.currentTimeMillis()-s)+"ms");
+        }
+        return R.data("无数据");
+    }
 
 
 

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

@@ -47,6 +47,7 @@ import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RestController;
 
 import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.*;
 import java.net.URLEncoder;
@@ -78,8 +79,8 @@ public class WbsTreeContractController extends BladeController {
     @GetMapping("/search-node-tables")
     @ApiOperationSupport(order = 1)
     @ApiOperation(value = "查询当前节点下所有元素表信息", notes = "传入节点primaryKeyId、type、合同段id、项目id")
-    public R searchNodeAllTable(String primaryKeyId, String type, String contractId, String projectId) {
-        List<AppWbsTreeContractVO> list = iWbsTreeContractService.searchNodeAllTable(primaryKeyId, type, contractId, projectId);
+    public R searchNodeAllTable(String primaryKeyId, String type, String contractId, String projectId, HttpServletRequest request) {
+        List<AppWbsTreeContractVO> list = iWbsTreeContractService.searchNodeAllTable(primaryKeyId, type, contractId, projectId, request);
         if (list.size() > 0) {
             list.forEach(l -> {
                 if (StringUtils.isNotBlank(l.getHtmlUrl())) {

+ 45 - 4
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreePrivateController.java

@@ -321,19 +321,60 @@ public class WbsTreePrivateController extends BladeController {
                                                             @RequestParam("projectId") String projectId) {
         List<WbsNodeTableVO> rs = wbsTreePrivateService.selectByNodeTable(parentId, wbsId, projectId);
         if (rs.size() > 0) {
+            /*表单对应的initTableIdMaps*/
+            Set<String> ids = rs.stream().map(WbsNodeTableVO::getId).collect(Collectors.toSet());
+            Map<Long, Long> initTableIdMaps = wbsTreeService.getBaseMapper().selectList(Wrappers.<WbsTree>lambdaQuery()
+                    .select(WbsTree::getInitTableId, WbsTree::getId)
+                    .in(WbsTree::getId, ids)).stream().collect(Collectors.toMap(WbsTree::getId, WbsTree::getInitTableId));
+
+            /*元素FidSet,统计数量*/
+            Set<Long> formElementFids = new HashSet<>();
+
+            /*initTabId赋值*/
             for (WbsNodeTableVO r : rs) {
                 if (StringUtil.isBlank(r.getHtmlUrl())) {
                     r.setIsLinkTable(1);
                 }
                 if (StringUtil.isBlank(r.getInitTableId())) {
-                    WbsTree wbsTree = wbsTreeService.getById(r.getId());
-                    if (wbsTree != null) {
-                        r.setInitTableId(com.baomidou.mybatisplus.core.toolkit.ObjectUtils.isNotEmpty(wbsTree.getInitTableId()) ? wbsTree.getInitTableId().toString() : "");
+
+                    /*提出去,不for循环查询
+                    WbsTree wbsTree = wbsTreeService.getById(r.getId());*/
+
+                    Long initTabId = initTableIdMaps.getOrDefault(Long.parseLong(r.getId()), null);
+
+                    if (initTabId != null) {
+                        r.setInitTableId(String.valueOf(initTabId));
+
+                        formElementFids.add(initTabId);
+
+                        /*提出去,不for循环查询
                         r.setElementTotal(Math.toIntExact(wbsFormElementService.count(
-                                new LambdaQueryWrapper<WbsFormElement>().eq(WbsFormElement::getFId, r.getInitTableId()))));
+                                new LambdaQueryWrapper<WbsFormElement>().eq(WbsFormElement::getFId, r.getInitTableId()))));*/
+
+                    } else {
+                        r.setInitTableId("");
                     }
                 }
             }
+
+            if (formElementFids.size() > 0) {
+                /*查询所有相关的元素记录*/
+                List<WbsFormElement> wbsFormElements = wbsFormElementService.getBaseMapper().selectList(Wrappers.<WbsFormElement>lambdaQuery()
+                        .select(WbsFormElement::getFId)
+                        .in(WbsFormElement::getFId, formElementFids));
+
+                /*elementCountMap分组*/
+                Map<String, Integer> elementCountMap = wbsFormElements.stream()
+                        .collect(Collectors.groupingBy(WbsFormElement::getFId, Collectors.collectingAndThen(Collectors.counting(), Long::intValue)));
+
+                /*元素数量赋值*/
+                for (WbsNodeTableVO r : rs) {
+                    if (StringUtil.isNotBlank(r.getInitTableId())) {
+                        r.setElementTotal(elementCountMap.getOrDefault(r.getInitTableId(), 0));
+                    }
+                }
+            }
+
             return R.data(rs);
         }
         return R.fail(200, "未查询到数据");

+ 8 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/feign/SaveUserInfoByProjectClientImpl.java

@@ -45,6 +45,14 @@ public class SaveUserInfoByProjectClientImpl implements SaveUserInfoByProjectCli
         );
     }
 
+    @Override
+    public List<SaveUserInfoByProjectDTO> searchUserInfoAndProjectByUserIds(List<Long> userIds) {
+        return saveUserInfoByProjectService.list(
+                Wrappers.<SaveUserInfoByProjectDTO>query().lambda()
+                        .in(SaveUserInfoByProjectDTO::getUserId, userIds)
+        );
+    }
+
     @Override
     public void saveInfoRelation(Long userId, Long projectId, Long contractId, Long roleId) {
         SaveUserInfoByProjectDTO obj = new SaveUserInfoByProjectDTO();

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

@@ -421,8 +421,14 @@ public class WbsTreeContractClientImpl implements WbsTreeContractClient {
 
     @Override
     public List<AppWbsTreeContractVO> searchNodeAllTableInfo(String primaryKeyId, String type, String contractId, String projectId,Long userId) {
-        List<AppWbsTreeContractVO> list = wbsTreeContractService.searchNodeAllTable(primaryKeyId+":"+userId, type, contractId, projectId);
+        List<AppWbsTreeContractVO> list = wbsTreeContractService.searchNodeAllTable(primaryKeyId+":"+userId, type, contractId, projectId,null);
         return list;
     }
 
+    /*删除合同段本地缓存*/
+    @Override
+    public void deleteContractLocalCache(String contractId) {
+        wbsTreeContractServiceImpl.deleteContractLocalCache(contractId);
+    }
+
 }

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

@@ -23,12 +23,9 @@ import org.springblade.business.entity.ArchiveFile;
 import org.springblade.business.entity.InformationQuery;
 import org.springblade.manager.entity.ArchiveTreeContract;
 import org.springblade.manager.entity.WbsTreePrivate;
-import org.springblade.manager.vo.ArchiveTreeContractVO;
+import org.springblade.manager.vo.*;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import org.springblade.manager.vo.ArchiveTreeContractVO2;
-import org.springblade.manager.vo.ArchiveTreeContractVO3;
-import org.springblade.manager.vo.ArchiveTreeVO;
 
 import java.util.List;
 import java.util.Map;
@@ -121,4 +118,14 @@ public interface ArchiveTreeContractMapper extends BaseMapper<ArchiveTreeContrac
 //     List<ArchiveFile> getListByContractId(@Param("contractId") Long contractId);
 //
 //    List<InformationQuery> getInformationByContractId(@Param("contractId") Long contractId);
+
+    List<InspectTreeVO> getUnitAllNode(@Param("projectId") Long project,@Param("ownerUnit")Long ownerUnit,@Param("supervisorUnit") Long supervisorUnit,@Param("buildUnit") Long buildUnit);
+
+    InspectTreeVO getFirstNode(@Param("projectId") Long projectId);
+
+    List<ArchiveTreeContract> getUnitFirstNode(@Param("id") Long id);
+
+    List<ArchiveTreeContract> getSelectNodes(@Param("ids") List<Long> longs);
+
+    List<MyInspectTreeVO> MyLazyTree(@Param("parentId") Long parentId,@Param("projectId") Long projectId,@Param("userId") Long userId);
 }

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

@@ -500,6 +500,115 @@
         order by ancestors
             limit 1
     </select>
+<!--    <select id="getUnitAllNode" resultType="org.springblade.manager.vo.InspectTreeVO">-->
+<!--        <if test="ownerUnit != null">-->
+<!--            select id,parent_id,node_name,-->
+<!--            (CASE when LENGTH(expert_id) > 0 then 0 else 1 end) as isSelect,-->
+<!--            (CASE when LENGTH(expert_id) > 0 then concat('该目录已分属', atc.expert_name , '专家') else '' end) as nodeInfo-->
+<!--            from m_archive_tree_contract atc-->
+<!--            WHERE is_deleted =0 and project_id = #{projectId}-->
+<!--            and (id = #{ownerUnit} or FIND_IN_SET(#{ownerUnit},ancestors))-->
+<!--        </if>-->
+<!--        <if test="ownerUnit != null and (supervisorUnit != null or buildUnit != null)">-->
+<!--            UNION all-->
+<!--        </if>-->
+<!--        <if test="supervisorUnit != null">-->
+<!--            select id,parent_id,node_name,-->
+<!--            (CASE when LENGTH(expert_id) > 0 then 0 else 1 end) as isSelect,-->
+<!--            (CASE when LENGTH(expert_id) > 0 then concat('该目录已分属', atc.expert_name , '专家') else '' end) as nodeInfo-->
+<!--            from m_archive_tree_contract atc-->
+<!--            WHERE is_deleted =0 and project_id = #{projectId}-->
+<!--            and  (id = #{supervisorUnit} or FIND_IN_SET(#{supervisorUnit},ancestors))-->
+<!--        </if>-->
+<!--        <if test="supervisorUnit != null and buildUnit != null">-->
+<!--            UNION all-->
+<!--        </if>-->
+<!--        <if test="buildUnit != null ">-->
+<!--        select id,parent_id,node_name,-->
+<!--        (CASE when LENGTH(expert_id) > 0 then 0 else 1 end) as isSelect,-->
+<!--        (CASE when LENGTH(expert_id) > 0 then concat('该目录已分属', atc.expert_name , '专家') else '' end) as nodeInfo-->
+<!--        from m_archive_tree_contract atc-->
+<!--        WHERE is_deleted =0 and project_id = #{projectId}-->
+<!--        and  (id = #{buildUnit} or FIND_IN_SET(#{buildUnit},ancestors))-->
+<!--        </if>-->
+<!--    </select>-->
+
+    <select id="getUnitAllNode" resultType="org.springblade.manager.vo.InspectTreeVO">
+        <if test="ownerUnit != null">
+            select id,parent_id,
+            (CASE when LENGTH(expert_id) > 0 then 0 else 1 end) as isSelect,
+            if((select COUNT(1) from m_archive_tree_contract WHERE is_deleted = 0 and parent_id = atc.id) > 0,true,false) as isChildren,
+            (CASE when LENGTH(expert_id) > 0 then concat('该目录已分属', atc.expert_name , '专家') else '' end) as nodeInfo,
+            (concat(atc.node_name,'(', (select COUNT(1) from u_archives_auto  WHERE  is_apply = 1 and is_deleted=0 and node_id in (select id from m_archive_tree_contract where is_deleted = 0 and project_id = #{projectId}
+            and (id = atc.id or FIND_IN_SET(atc.id,ancestors)))), '卷)')) as node_name
+            from m_archive_tree_contract atc
+            WHERE is_deleted =0 and project_id = #{projectId}
+            and (id = #{ownerUnit} or FIND_IN_SET(#{ownerUnit},ancestors))
+        </if>
+        <if test="ownerUnit != null and (supervisorUnit != null or buildUnit != null)">
+            UNION all
+        </if>
+        <if test="supervisorUnit != null">
+            select id,parent_id,
+            (CASE when LENGTH(expert_id) > 0 then 0 else 1 end) as isSelect,
+            if((select COUNT(1) from m_archive_tree_contract WHERE is_deleted = 0 and parent_id = atc.id) > 0,true,false) as isChildren,
+            (CASE when LENGTH(expert_id) > 0 then concat('该目录已分属', atc.expert_name , '专家') else '' end) as nodeInfo,
+            (concat(atc.node_name,'(', (select COUNT(1) from u_archives_auto  WHERE  is_apply = 1 and is_deleted=0 and node_id in (select id from m_archive_tree_contract where is_deleted = 0 and project_id = #{projectId}
+            and (id = atc.id or FIND_IN_SET(atc.id,ancestors)))), '卷)')) as node_name
+            from m_archive_tree_contract atc
+            WHERE is_deleted =0 and project_id = #{projectId}
+            and  (id = #{supervisorUnit} or FIND_IN_SET(#{supervisorUnit},ancestors))
+        </if>
+        <if test="supervisorUnit != null and buildUnit != null">
+            UNION all
+        </if>
+        <if test="buildUnit != null ">
+            select id,parent_id,
+            (CASE when LENGTH(expert_id) > 0 then 0 else 1 end) as isSelect,
+            if((select COUNT(1) from m_archive_tree_contract WHERE is_deleted = 0 and parent_id = atc.id) > 0,true,false) as isChildren,
+            (CASE when LENGTH(expert_id) > 0 then concat('该目录已分属', atc.expert_name , '专家') else '' end) as nodeInfo,
+            (concat(atc.node_name,'(', (select COUNT(1) from u_archives_auto  WHERE  is_apply = 1 and is_deleted=0 and node_id in (select id from m_archive_tree_contract where is_deleted = 0 and project_id = #{projectId}
+            and (id = atc.id or FIND_IN_SET(atc.id,ancestors)))), '卷)')) as node_name
+            from m_archive_tree_contract atc
+            WHERE is_deleted =0 and project_id = #{projectId}
+            and  (id = #{buildUnit} or FIND_IN_SET(#{buildUnit},ancestors))
+        </if>
+    </select>
+
+    <select id="getFirstNode" resultType="org.springblade.manager.vo.InspectTreeVO">
+        select id,parent_id,
+               (CASE when LENGTH(expert_id) > 0 then 0 else 1 end) as isSelect,
+               if((select COUNT(1) from m_archive_tree_contract WHERE is_deleted = 0 and parent_id = atc.id) > 0,true,false) as isChildren,
+--                (CASE when LENGTH(expert_id) > 0 then concat('该目录已分属', atc.expert_name , '专家') else '' end) as nodeInfo,
+               (concat(atc.node_name,'(', (select COUNT(1) from u_archives_auto  WHERE  is_apply = 1 and is_deleted=0 and node_id in (select id from m_archive_tree_contract where is_deleted = 0 and project_id = #{projectId}
+                and (id = atc.id or FIND_IN_SET(atc.id,ancestors)))), ')')) as node_name
+        from m_archive_tree_contract atc
+        WHERE atc.parent_id = 0 and atc.is_deleted = 0 and project_id =#{projectId}
+    </select>
+    <select id="getUnitFirstNode" resultType="org.springblade.manager.entity.ArchiveTreeContract">
+        SELECT id,
+               (CASE tree_code WHEN 'C' THEN 3 WHEN  's' THEN 2 ELSE 1 END) as tree_code
+        from m_archive_tree_contract
+        WHERE parent_id = #{id} and is_deleted = 0
+    </select>
+    <select id="getSelectNodes" resultType="org.springblade.manager.entity.ArchiveTreeContract">
+        select id,expert_id,expert_name
+        from m_archive_tree_contract where id in
+        <foreach collection="ids" item="id" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </select>
+    <select id="MyLazyTree" resultType="org.springblade.manager.vo.MyInspectTreeVO">
+        select *,node_name as title,
+               if((select COUNT(1) from m_archive_tree_contract WHERE is_deleted = 0 and parent_id = d.id) > 0,true,false) as hasChildren
+        FROM
+        m_archive_tree_contract d
+        WHERE
+        d.parent_id = #{parentId} AND d.is_deleted = 0 and project_id = #{projectId}
+        and FIND_IN_SET(#{userId},d.expert_id)
+        ORDER BY d.sort
+    </select>
+
 
     <update id="updateAllSonNodeIdsForArchiveAutoRule">
 

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

@@ -56,7 +56,7 @@
     </resultMap>
 
     <select id="queryProjectUserAmount" resultMap="projectUserAmount">
-        select mpi.project_alias,
+        /*select mpi.project_alias,
                (select COUNT(DISTINCT user_id) end
         from m_project_assignment_user
         where is_deleted = 0
@@ -87,7 +87,25 @@
            or parent_id =
             '1537246243393589249'))) as owner
         from
-            m_project_info as mpi
+            m_project_info as mpi*/
+
+        SELECT
+            mpi.project_alias,
+            mpi.create_time,
+            COUNT(DISTINCT CASE WHEN m.role_id = '1537247986361782274' OR r1.parent_id = '1537247986361782274' THEN m.user_id END) AS contractor,
+            COUNT(DISTINCT CASE WHEN m.role_id = '1537246384519335938' OR r2.parent_id = '1537246384519335938' THEN m.user_id END) AS supervision,
+            COUNT(DISTINCT CASE WHEN m.role_id = '1537246243393589249' OR r3.parent_id = '1537246243393589249' THEN m.user_id END) AS owner
+        FROM
+            m_project_info AS mpi
+                LEFT JOIN m_project_assignment_user AS m ON mpi.id = m.project_id AND m.is_deleted = 0
+                LEFT JOIN blade_role AS r1 ON m.role_id = r1.id AND r1.is_deleted = 0
+                LEFT JOIN blade_role AS r2 ON m.role_id = r2.id AND r2.is_deleted = 0
+                LEFT JOIN blade_role AS r3 ON m.role_id = r3.id AND r3.is_deleted = 0
+        GROUP BY
+            mpi.project_alias
+        ORDER BY
+            mpi.create_time;
+
     </select>
 
     <select id="singPfxManagementPage" resultMap="singPfxManagementResultMap">

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

@@ -8,8 +8,9 @@ import org.springblade.manager.injector.EasyBaseMapper;
 import org.springblade.manager.vo.*;
 
 import java.util.List;
+import java.util.Set;
 
-@CacheNamespace
+//@CacheNamespace
 public interface WbsTreeContractMapper extends EasyBaseMapper<WbsTreeContract> {
 
     int deleteByIds(@Param("ids") List<Long> ids);
@@ -58,7 +59,9 @@ public interface WbsTreeContractMapper extends EasyBaseMapper<WbsTreeContract> {
 
     List<WbsTableOwnerRole> selectWbsTableOwnerRoleList(String roleId);
 
-    List<AppWbsTreeContractVO> selectWbsTreeContractList(List<String> tableOwnerNumbers, String projectId, String wbsId, String contractId, Long parentId, String contractIdRelation, List<String> tableOwnerList);
+    List<AppWbsTreeContractVO> selectWbsTreeContractList(Set<String> roleTableOwnerSets, String projectId, String wbsId, String contractId, Long parentId, String contractIdRelation);
+
+    List<AppWbsTreeContractVO> selectWbsTreeContractListClient(Set<String> roleTableOwnerSets, String projectId, String wbsId, String contractId, Long parentId, String contractIdRelation);
 
     SaveUserInfoByProject selectRoleInfo(Long userId, String contractId, String projectId);
 

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

@@ -109,7 +109,6 @@
         </collection>
     </resultMap>
 
-
     <resultMap id="resultMap2" type="org.springblade.manager.vo.WbsTreeContractVO">
         <result column="id" property="id"/>
         <result column="wbs_id" property="wbsId"/>
@@ -416,6 +415,7 @@
         where role_id = #{roleId}
     </select>
 
+    <!--APP返回appResultMap(内部嵌套子查询(不清楚为什么要这样嵌套查询,导致一直递归))-->
     <select id="selectWbsTreeContractList" resultMap="appResultMap">
         SELECT * FROM
         m_wbs_tree_contract
@@ -423,25 +423,43 @@
         AND wbs_id = #{wbsId}
         AND contract_id = #{contractId}
         AND parent_id = #{parentId}
-        AND table_owner in
-        <foreach item="tableOwnerNumbers" collection="tableOwnerNumbers" open="(" close=")" separator=",">
-            #{tableOwnerNumbers}
-        </foreach>
         AND type = 2
         AND status = 1
         AND is_deleted = 0
         <if test="contractIdRelation != null and contractIdRelation!= ''">
             AND contract_id = #{contractIdRelation}
         </if>
-        <if test="tableOwnerList != null and tableOwnerList!= ''">
+        <if test="roleTableOwnerSets != null and roleTableOwnerSets!= ''">
             AND table_owner in
-            <foreach item="tableOwnerList" collection="tableOwnerList" open="(" close=")" separator=",">
-                #{tableOwnerList}
+            <foreach item="roleTableOwnerSets" collection="roleTableOwnerSets" open="(" close=")" separator=",">
+                #{roleTableOwnerSets}
             </foreach>
         </if>
         ORDER BY sort,full_name,create_time
     </select>
 
+    <!--客户端返回WbsTreeContract-->
+    <select id="selectWbsTreeContractListClient" resultType="org.springblade.manager.vo.AppWbsTreeContractVO">
+        SELECT * FROM
+        m_wbs_tree_contract
+        WHERE project_id = #{projectId}
+        AND wbs_id = #{wbsId}
+        AND contract_id = #{contractId}
+        AND parent_id = #{parentId}
+        AND type = 2
+        AND status = 1
+        AND is_deleted = 0
+        <if test="contractIdRelation != null and contractIdRelation!= ''">
+            AND contract_id = #{contractIdRelation}
+        </if>
+        <if test="roleTableOwnerSets != null and roleTableOwnerSets!= ''">
+            AND table_owner in
+            <foreach item="roleTableOwnerSets" collection="roleTableOwnerSets" open="(" close=")" separator=",">
+                #{roleTableOwnerSets}
+            </foreach>
+        </if>
+    </select>
+
     <select id="selectRoleInfo" resultType="org.springblade.manager.entity.SaveUserInfoByProject">
         SELECT role_id
         FROM m_project_assignment_user
@@ -566,25 +584,29 @@
     <update id="updateContractTablesInfo">
         UPDATE m_wbs_tree_contract
         SET
-            node_name =
-                CASE
-                    WHEN node_name LIKE '%_PL_%' THEN CONCAT(#{wbsTreePrivate.nodeName}, SUBSTRING(node_name FROM INSTR(node_name, '_PL_')))
-                    WHEN node_name LIKE '%__%' THEN CONCAT(#{wbsTreePrivate.nodeName}, SUBSTRING(node_name FROM INSTR(node_name, '__')))
-                ELSE #{wbsTreePrivate.nodeName}
-                END,
-            full_name =
-                CASE
-                    WHEN full_name LIKE '%_PL_%' THEN CONCAT(#{wbsTreePrivate.nodeName}, SUBSTRING(full_name FROM INSTR(full_name, '_PL_')))
-                    WHEN full_name LIKE '%__%' THEN CONCAT(#{wbsTreePrivate.nodeName}, SUBSTRING(full_name FROM INSTR(full_name, '__')))
-                    ELSE #{wbsTreePrivate.nodeName}
-                END,
-            table_type = #{wbsTreePrivate.tableType},
-            table_owner = #{wbsTreePrivate.tableOwner}
-            <if test="wbsTreePrivate.sort != null and wbsTreePrivate.sort != ''">
-                ,sort = #{wbsTreePrivate.sort}
-            </if>
+        node_name =
+        CASE
+        WHEN node_name LIKE '%_PL_%' THEN CONCAT(#{wbsTreePrivate.nodeName}, SUBSTRING(node_name FROM INSTR(node_name,
+        '_PL_')))
+        WHEN node_name LIKE '%__%' THEN CONCAT(#{wbsTreePrivate.nodeName}, SUBSTRING(node_name FROM INSTR(node_name,
+        '__')))
+        ELSE #{wbsTreePrivate.nodeName}
+        END,
+        full_name =
+        CASE
+        WHEN full_name LIKE '%_PL_%' THEN CONCAT(#{wbsTreePrivate.nodeName}, SUBSTRING(full_name FROM INSTR(full_name,
+        '_PL_')))
+        WHEN full_name LIKE '%__%' THEN CONCAT(#{wbsTreePrivate.nodeName}, SUBSTRING(full_name FROM INSTR(full_name,
+        '__')))
+        ELSE #{wbsTreePrivate.nodeName}
+        END,
+        table_type = #{wbsTreePrivate.tableType},
+        table_owner = #{wbsTreePrivate.tableOwner}
+        <if test="wbsTreePrivate.sort != null and wbsTreePrivate.sort != ''">
+            ,sort = #{wbsTreePrivate.sort}
+        </if>
         WHERE
-            p_key_id in
+        p_key_id in
         <foreach collection="pKeyIdsContracts" item="pKeyIds" open="(" close=")" separator=",">
             #{pKeyIds}
         </foreach>
@@ -595,47 +617,47 @@
             UPDATE m_wbs_tree_contract
             <set>
                 node_name =
-                    CASE
-                        WHEN node_name LIKE '%_PL_%'
-                            THEN CONCAT(
-                            <if test="item.nodeName != null and item.nodeName != ''">
-                                #{item.nodeName}
-                            </if>,
-                            SUBSTRING(node_name FROM INSTR(node_name, '_PL_'))
-                            )
-                        WHEN node_name LIKE '%__%'
-                            THEN CONCAT(
-                            <if test="item.nodeName != null and item.nodeName != ''">
-                                #{item.nodeName}
-                            </if>,
-                            SUBSTRING(node_name FROM INSTR(node_name, '__'))
-                            )
-                        ELSE
-                        <if test="item.nodeName != null and item.nodeName != ''">
-                            #{item.nodeName}
-                        </if>
-                    END,
+                CASE
+                WHEN node_name LIKE '%_PL_%'
+                THEN CONCAT(
+                <if test="item.nodeName != null and item.nodeName != ''">
+                    #{item.nodeName}
+                </if>,
+                SUBSTRING(node_name FROM INSTR(node_name, '_PL_'))
+                )
+                WHEN node_name LIKE '%__%'
+                THEN CONCAT(
+                <if test="item.nodeName != null and item.nodeName != ''">
+                    #{item.nodeName}
+                </if>,
+                SUBSTRING(node_name FROM INSTR(node_name, '__'))
+                )
+                ELSE
+                <if test="item.nodeName != null and item.nodeName != ''">
+                    #{item.nodeName}
+                </if>
+                END,
                 full_name =
-                    CASE
-                        WHEN full_name LIKE '%_PL_%'
-                            THEN CONCAT(
-                            <if test="item.nodeName != null and item.nodeName != ''">
-                                #{item.nodeName}
-                            </if>,
-                            SUBSTRING(full_name FROM INSTR(full_name, '_PL_'))
-                            )
-                        WHEN full_name LIKE '%__%'
-                            THEN CONCAT(
-                            <if test="item.nodeName != null and item.nodeName != ''">
-                                #{item.nodeName}
-                            </if>,
-                            SUBSTRING(full_name FROM INSTR(full_name, '__'))
-                            )
-                        ELSE
-                        <if test="item.nodeName != null and item.nodeName != ''">
-                            #{item.nodeName}
-                        </if>
-                    END,
+                CASE
+                WHEN full_name LIKE '%_PL_%'
+                THEN CONCAT(
+                <if test="item.nodeName != null and item.nodeName != ''">
+                    #{item.nodeName}
+                </if>,
+                SUBSTRING(full_name FROM INSTR(full_name, '_PL_'))
+                )
+                WHEN full_name LIKE '%__%'
+                THEN CONCAT(
+                <if test="item.nodeName != null and item.nodeName != ''">
+                    #{item.nodeName}
+                </if>,
+                SUBSTRING(full_name FROM INSTR(full_name, '__'))
+                )
+                ELSE
+                <if test="item.nodeName != null and item.nodeName != ''">
+                    #{item.nodeName}
+                </if>
+                END,
                 <if test="item.nodeType != null and item.nodeType != ''">
                     node_type = #{item.nodeType},
                 </if>

+ 9 - 3
blade-service/blade-manager/src/main/java/org/springblade/manager/service/IArchiveTreeContractService.java

@@ -24,11 +24,9 @@ import org.springblade.manager.dto.ArchiveTreeDTO;
 import org.springblade.manager.entity.ArchiveTree;
 import org.springblade.manager.entity.ArchiveTreeContract;
 
-import org.springblade.manager.vo.ArchiveTreeContractVO;
+import org.springblade.manager.vo.*;
 import org.springblade.core.mp.base.BaseService;
 import com.baomidou.mybatisplus.core.metadata.IPage;
-import org.springblade.manager.vo.ArchiveTreeContractVO2;
-import org.springblade.manager.vo.ArchiveTreeContractVO3;
 
 
 import java.util.ArrayList;
@@ -126,4 +124,12 @@ public interface IArchiveTreeContractService extends BaseService<ArchiveTreeCont
                                                  String periodName);
 
     public void updateWbsRuleNodes(Long projectId);
+
+    List<InspectTreeVO> getUnitAllNode(Long project, String types);
+
+    void saveAllSelectNodes(Map<String, String> map);
+
+    List<MyInspectTreeVO> lazyTree(Long parentId, Long projectId);
+
+    Boolean startInspect(Long projectId);
 }

+ 3 - 2
blade-service/blade-manager/src/main/java/org/springblade/manager/service/IExcelTabService.java

@@ -113,8 +113,9 @@ public interface IExcelTabService extends BaseService<ExcelTab> {
     Map<String, String> getTablbCols(String pkeyid, String colkey) throws FileNotFoundException;
 
     // 获取用户端 单个表单接口数据
-    R getBussDataInfo(Long pkeyId, int type);
-
+    Map<String,Object> getBussDataInfo(Long pkeyId, int type);
+    // 获取用户端 单个表单接口数据
+    Map<String,Object> getBussDataInfo(Long pkeyId, int type,Boolean isFormLoading);
     // 单个pdf 生成
     R getBussPdfInfo(Long pkeyId) throws Exception;
 

+ 3 - 4
blade-service/blade-manager/src/main/java/org/springblade/manager/service/IFormulaService.java

@@ -4,10 +4,7 @@ import org.jsoup.nodes.Document;
 import org.springblade.core.mp.base.BaseService;
 import org.springblade.core.tool.api.R;
 import org.springblade.manager.dto.FormData;
-import org.springblade.manager.entity.Formula;
-import org.springblade.manager.entity.WbsInfo;
-import org.springblade.manager.entity.WbsTreeContract;
-import org.springblade.manager.entity.WbsTreePrivate;
+import org.springblade.manager.entity.*;
 import org.springblade.manager.enums.ExecuteType;
 import org.springblade.manager.formula.KeyMapper;
 import org.springblade.manager.formula.impl.TableElementConverter;
@@ -113,4 +110,6 @@ public interface IFormulaService extends BaseService<Formula> {
 
     /**表单数据加载的时候执行节点参数*/
     R<Object> evaluate(Long pkeyId);
+    /**获取当前节点的参数wbsNodeId:WBS级id ,wtpPkeyId:项目级PkeyId*/
+    List<WbsParam> getNodeWps(Long wbsNodeId,Long wtpPkeyId);
 }

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

@@ -10,6 +10,7 @@ import org.springblade.manager.entity.WbsTreePrivate;
 import org.springblade.manager.vo.*;
 import org.springframework.web.multipart.MultipartFile;
 
+import javax.servlet.http.HttpServletRequest;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.util.List;
@@ -37,7 +38,7 @@ public interface IWbsTreeContractService extends BaseService<WbsTreeContract> {
 
     List<WbsTreeContractTreeVO3> lazyTreeThree(String contractIdRelation, Long parentId, String contractId);
 
-    List<AppWbsTreeContractVO> searchNodeAllTable(String primaryKeyId, String tableOwner, String contractId, String projectId);
+    List<AppWbsTreeContractVO> searchNodeAllTable(String primaryKeyId, String tableOwner, String contractId, String projectId, HttpServletRequest request);
 
     List<WbsTreeContract> searchParentAllNode(long primaryKeyId, Long contractId);
 

+ 109 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeContractServiceImpl.java

@@ -16,18 +16,22 @@
  */
 package org.springblade.manager.service.impl;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.mixsmart.utils.StringUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.core.toolkit.StringPool;
 import lombok.AllArgsConstructor;
+import org.springblade.archive.feign.ArchiveAutoClient;
 import org.springblade.business.feign.ArchiveFileClient;
 import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.secure.BladeUser;
 import org.springblade.core.secure.utils.AuthUtil;
+import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.constant.BladeConstant;
 import org.springblade.core.tool.node.ForestNodeMerger;
 import org.springblade.core.tool.utils.Func;
+import org.springblade.core.tool.utils.StringUtil;
 import org.springblade.manager.dto.ArchiveTreeContractDTO;
 import org.springblade.manager.entity.*;
 import org.springblade.manager.feign.WbsTreeContractClient;
@@ -42,6 +46,7 @@ import org.springblade.core.mp.base.BaseServiceImpl;
 import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.RequestParam;
 
 import java.util.*;
@@ -78,6 +83,8 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 
 	private final ArchiveAutoRuleWbsMapper archiveAutoRuleWbsMapper;
 
+	private final ArchiveAutoClient archiveAutoClient;
+
 
 
 
@@ -1339,5 +1346,107 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 		}
 	}
 
+	/**
+	 * 档案验收返回单位所有节点
+	 * @param projectId
+	 * @return
+	 */
+	@Override
+	public List<InspectTreeVO> getUnitAllNode(Long projectId,String types) {
+		/**
+		 *  1业主2监理3施工4影像5竣工图,根据勾选的类型,返回单位首节点集合,勾选哪个单位回显哪个
+		 *   如果勾选了施工,又勾选了影像和竣工图,则只返回施工,
+		 *   如果只勾选了影像和竣工图,则返回施工节点类型为声像、隐蔽、竣工图类型的节点
+		 *   如果当前目录下所有节点都属于某个专家,则显示该目录已分属XX专家
+		 *   每个节点下有多少卷档案也要标识
+		 */
+		//获取首节点
+		InspectTreeVO firstNode = baseMapper.getFirstNode(projectId);
+		//获取三个单位节点
+		List<ArchiveTreeContract> unitFirstNode = baseMapper.getUnitFirstNode(firstNode.getId());
+		Map<String, Long> unitMap = unitFirstNode.stream().collect(Collectors.toMap(l -> l.getTreeCode(), l -> l.getId()));
+		//根据选择单位选择
+		Long ownerUnit = null;
+		Long supervisorUnit = null;
+		Long buildUnit = null;
+		if (types.contains("1")){
+			ownerUnit = unitMap.get("1");
+		}
+		if (types.contains("2")){
+			supervisorUnit = unitMap.get("2");
+		}
+		if (types.contains("3")){
+			buildUnit = unitMap.get("3");
+		}else if(types.contains("4") || types.contains("5")){
+			buildUnit = unitMap.get("3");
+		}
+		//结果集
+		List<InspectTreeVO> unitAllNode = baseMapper.getUnitAllNode(projectId,ownerUnit,supervisorUnit,buildUnit);
+		unitAllNode.add(firstNode);
+		return org.springblade.manager.utils.ForestNodeMerger.merge(unitAllNode);
+	}
+
+	@Override
+	@Transactional
+	public void saveAllSelectNodes(Map<String, String> map) {
+		String ids = map.get("ids");
+		//获取当前用户id与名称
+		String userId = AuthUtil.getUserId()+"";
+		String userName = AuthUtil.getNickName();
+		//取出所有选择的节点,只获取专家名称和专家id字段
+		List<Long> longs = Func.toLongList(ids);
+		List<ArchiveTreeContract> list = baseMapper.getSelectNodes(longs);
+		//循环判断是否已经存在专家,存在则追加
+		list.stream().forEach(l->{
+			if (org.apache.commons.lang3.StringUtils.isBlank(l.getExpertId())){
+				//为空
+				l.setExpertId(userId);
+				l.setExpertName(userName);
+			}else {
+				//不为空
+				String expertId = l.getExpertId();
+				l.setExpertId(expertId+","+userId);
+				String expertName = l.getExpertName();
+				l.setExpertName(expertName+"/"+userName);
+			}
+		});
+		//保存所有节点
+		this.updateBatchById(list);
+		//修改节点下所有档案,并保存
+		R<Boolean> booleanR = archiveAutoClient.batchUpdateExpertId(userId, longs);
+		if (booleanR.getData() == null || booleanR.getData() != true){
+			throw new ServiceException("为档案绑定专家失败");
+		}
+	}
+
+	@Override
+	public List<MyInspectTreeVO> lazyTree(Long parentId, Long projectId) {
+		//获取当前用户id,用于获取分配给当前用户的树
+		Long userId = AuthUtil.getUserId();
+		List<MyInspectTreeVO> vos = baseMapper.MyLazyTree(parentId, projectId, userId);
+		return vos;
+	}
+
+	/**
+	 * 在线验收-开始抽检
+	 */
+	@Override
+	public Boolean startInspect(Long projectId) {
+		//获取当前项目首节点
+		ArchiveTreeContract one = this.getOne(new LambdaQueryWrapper<ArchiveTreeContract>()
+				.eq(ArchiveTreeContract::getProjectId, projectId)
+				.eq(ArchiveTreeContract::getParentId, 0));
+		if (one == null){
+			throw new ServiceException("未找到当前项目首节点");
+		}
+		Long userId = AuthUtil.getUserId();
+		//判断是否存在当前专家id
+		if (StringUtil.isNotBlank(one.getExpertId()) && one.getExpertId().contains(userId+"")){
+			return false;
+		}else {
+			return true;
+		}
+	}
+
 
 }

+ 2 - 34
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ContractInfoServiceImpl.java

@@ -336,18 +336,15 @@ public class ContractInfoServiceImpl extends BaseServiceImpl<ContractInfoMapper,
         if (StringUtils.isNotEmpty(queryValue) && StringUtils.isNotEmpty(contractId)) {
             ContractInfo contractInfo = contractInfoMapper.selectById(contractId);
             if (contractInfo != null) {
-                //TODO 质检
+                /*质检施工合同段*/
                 if (contractInfo.getContractType().equals(1)) {
-                    //获取查询有效节点信息
                     LambdaQueryWrapper<WbsTreeContract> queryWrapper = new LambdaQueryWrapper<>();
                     queryWrapper.select(WbsTreeContract::getParentId, WbsTreeContract::getId, WbsTreeContract::getPKeyId);
                     queryWrapper.like(WbsTreeContract::getFullName, queryValue);
                     queryWrapper.eq(WbsTreeContract::getContractId, contractId);
                     queryWrapper.eq(WbsTreeContract::getType, 1);
-                    //所有匹配节点
                     List<WbsTreeContract> nodes = wbsTreeContractMapper.selectList(queryWrapper);
                     if (nodes.size() > 0) {
-                        //获取当前合同段所有缓存节点信息
                         List<WbsTreeContractLazyVO> nodesAllTemp;
                         Object data = redisTemplate.opsForValue().get("blade-manager::contract:wbstree:" + contractId);
                         if (data != null) {
@@ -355,7 +352,6 @@ public class ContractInfoServiceImpl extends BaseServiceImpl<ContractInfoMapper,
                         } else {
                             nodesAllTemp = jdbcTemplate.query("select a.p_key_id,a.id,a.parent_id from m_wbs_tree_contract a where a.type = 1 and a.status = 1 and a.is_deleted = 0 and a.contract_id = " + contractId, new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
                             if (nodesAllTemp.size() > 0) {
-                                //判断是否有子级,赋值
                                 Map<Long, List<WbsTreeContractLazyVO>> groupedByParentId = nodesAllTemp.stream().collect(Collectors.groupingBy(WbsTreeContractLazyVO::getParentId));
                                 for (WbsTreeContractLazyVO vo : nodesAllTemp) {
                                     if (vo.getParentId() == 0) {
@@ -373,13 +369,11 @@ public class ContractInfoServiceImpl extends BaseServiceImpl<ContractInfoMapper,
                             }
                         }
 
-                        //去重
                         List<WbsTreeContractLazyVO> distinctNodesAll = nodesAllTemp.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
@@ -387,19 +381,13 @@ public class ContractInfoServiceImpl extends BaseServiceImpl<ContractInfoMapper,
 
                         List<Long> parentIds = nodes.stream().map(WbsTreeContract::getParentId).collect(Collectors.toList());
                         List<Long> ids = nodes.stream().map(WbsTreeContract::getId).collect(Collectors.toList());
-                        //所有匹配的PKeyIds
                         Set<Long> resultNodesPKeyIds = new LinkedHashSet<>();
-                        //获取所有匹配节点的父级
                         this.recursiveGetParentNodes(resultNodesPKeyIds, parentIds, nodesAllTemp);
-                        //获取所有匹配节点的子级
                         this.recursiveGetChildNodes(resultNodesPKeyIds, ids, nodesAllTemp);
 
-                        //获取结果集节点
                         resultNodesPKeyIds.addAll(nodes.stream().map(WbsTreeContract::getPKeyId).collect(Collectors.toList()));
                         List<WbsTreeContract> wbsTreeContractList = wbsTreeContractMapper.selectList(Wrappers.<WbsTreeContract>lambdaQuery().in(WbsTreeContract::getPKeyId, resultNodesPKeyIds));
 
-                        //获取当前合同段填报过的资料信息Map
-                        //获取当前合同段所有填报资料缓存信息
                         List<WbsTreeContractLazyQueryInfoVO> queryInfoList;
                         Object dataInformationQuery;
                         if (cn.hutool.core.util.ObjectUtil.isEmpty(tableOwner)) {
@@ -428,44 +416,29 @@ public class ContractInfoServiceImpl extends BaseServiceImpl<ContractInfoMapper,
                                 .collect(Collectors.toMap(WbsTreeContractLazyQueryInfoVO::getWbsId, WbsTreeContractLazyQueryInfoVO::getStatus, (existingValue, newValue) -> existingValue));
                         List<Long> pKeyIdList = new ArrayList<>(queryInfoMaps.keySet());
 
-                        //TODO 处理数量
-                        //填报过的所有最底层节点
                         List<WbsTreeContractLazyVO> lowestNodesTB = distinctLowestNodesAll.parallelStream().filter(f -> pKeyIdList.contains(f.getPKeyId()) && resultNodesPKeyIds.contains(f.getPKeyId())).collect(Collectors.toList());
                         List<Long> lowestNodeParentIdsTB = lowestNodesTB.parallelStream().map(WbsTreeContractLazyVO::getParentId).collect(Collectors.toList());
                         List<WbsTreeContractLazyVO> resultParentNodesTB = new ArrayList<>();
                         wbsTreeContractServiceImpl.recursiveGetParentNodes(resultParentNodesTB, lowestNodeParentIdsTB, nodesAllTemp);
 
-                        //最底层节点颜色构造后Map
                         Map<Long, WbsTreeContractLazyVO> lowestNodesMap = lowestNodesTB.stream()
                                 .peek(vo -> {
                                     Integer colorStatus = queryInfoMaps.get(vo.getPKeyId());
                                     if (colorStatus != null) {
-                                        //任务状态0=未上报=颜色2蓝色、任务状态1=待审批=颜色3橙色、任务状态2=已审批=颜色4绿色
-                                        ///*任务状态3=已废除=颜色1黑色*/(2023年10月16日13:59:00 已废除改为=颜色2蓝色)
                                         vo.setColorStatus(colorStatus == 0 ? 2 : (colorStatus == 1 ? 3 : (colorStatus == 2 ? 4 : 2)));
                                     } else {
-                                        //未填报的=颜色1黑色
                                         vo.setColorStatus(1);
                                     }
                                 }).collect(Collectors.toMap(WbsTreeContractLazyVO::getPKeyId, Function.identity()));
 
-                        //TODO 处理颜色
-                        //先将WbsTreeContractLazyVO转为NodeVO
                         List<NodeVO> nodeVOList = distinctNodesAll.stream().map(wbsTreeContractServiceImpl::convertToNodeVO).collect(Collectors.toList());
-                        //转为Map<Long, NodeVO>
                         Map<Long, NodeVO> nodeVOMap = nodeVOList.stream().collect(Collectors.toMap(NodeVO::getId, vo -> vo, (existing, replacement) -> existing));
-                        //把distinctNodesAll把所有节点转为树形结构,再转为List<NodeVO>对象
                         List<NodeVO> treeNodeVOList = wbsTreeContractServiceImpl.buildNodeTreeByStream(distinctNodesAll, lowestNodesMap);
-                        //处理节点颜色
                         NodeVO.calculateStatusToDFS(treeNodeVOList, nodeVOMap);
-                        //把树形结构转为普通List集合
                         List<NodeVO> nodeVOS = wbsTreeContractServiceImpl.flattenTree(treeNodeVOList);
-                        //获取所有节点颜色Map
                         Map<Long, Integer> nodeColorStatusMap = nodeVOS.stream().collect(Collectors.toMap(NodeVO::getPKeyId, NodeVO::getStatus, (existing, replacement) -> existing));
 
-                        //构造vo
                         if (wbsTreeContractList.size() > 0) {
-                            //处理填报数量
                             Map<Long, Long> countMap = new HashMap<>();
                             for (WbsTreeContractLazyVO node : resultParentNodesTB) {
                                 Long key = node.getPKeyId();
@@ -484,10 +457,8 @@ public class ContractInfoServiceImpl extends BaseServiceImpl<ContractInfoMapper,
                                             vo.setTitle(ObjectUtil.isNotEmpty(node.getFullName()) ? node.getFullName() : node.getNodeName());
                                             vo.setPrimaryKeyId(node.getPKeyId());
 
-                                            //设置数量
                                             vo.setSubmitCounts(ObjectUtil.isNotEmpty(countMap.get(vo.getPrimaryKeyId())) ? countMap.get(vo.getPrimaryKeyId()) : (ObjectUtil.isNotEmpty(queryInfoMaps.get(vo.getPrimaryKeyId())) ? 1L : 0L));
 
-                                            //设置颜色
                                             Integer parentColorStatus = nodeColorStatusMap.get(vo.getPrimaryKeyId());
                                             if (parentColorStatus != null) {
                                                 vo.setColorStatus(parentColorStatus);
@@ -504,8 +475,8 @@ public class ContractInfoServiceImpl extends BaseServiceImpl<ContractInfoMapper,
                         }
                     }
 
+                    /*监理、业主合同段*/
                 } else if (contractInfo.getContractType().equals(2) || contractInfo.getContractType().equals(3)) {
-                    //TODO 监理、指挥部
                     Map<Long, List<WbsTreeContractTreeAllVO>> resultMaps = new LinkedHashMap<>();
                     List<ContractRelationJlyz> relationJLYZList = jdbcTemplate.query("select * from m_contract_relation_jlyz where contract_id_jlyz = " + contractId, new BeanPropertyRowMapper<>(ContractRelationJlyz.class));
                     if (ObjectUtil.isEmpty(relationJLYZList) || relationJLYZList.size() <= 0) {
@@ -562,7 +533,6 @@ public class ContractInfoServiceImpl extends BaseServiceImpl<ContractInfoMapper,
                             resultNodesPKeyIds.addAll(nodes.stream().map(WbsTreeContract::getPKeyId).collect(Collectors.toList()));
                             List<WbsTreeContract> wbsTreeContractList = wbsTreeContractMapper.selectList(Wrappers.<WbsTreeContract>lambdaQuery().in(WbsTreeContract::getPKeyId, resultNodesPKeyIds));
 
-                            //资料信息缓存
                             List<WbsTreeContractLazyQueryInfoVO> queryInfoList;
                             Object dataInformationQuery;
                             if (cn.hutool.core.util.ObjectUtil.isEmpty(tableOwner)) {
@@ -601,14 +571,12 @@ public class ContractInfoServiceImpl extends BaseServiceImpl<ContractInfoMapper,
                                     .peek(vo -> {
                                         Integer colorStatus = queryInfoMaps.get(vo.getPKeyId());
                                         if (colorStatus != null) {
-                                            ///*任务状态3=已废除=颜色1黑色*/(2023年10月16日13:59:00 已废除改为=颜色2蓝色)
                                             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(wbsTreeContractServiceImpl::convertToNodeVO).collect(Collectors.toList());
                             Map<Long, NodeVO> nodeVOMap = nodeVOList.stream().collect(Collectors.toMap(NodeVO::getId, vo -> vo, (existing, replacement) -> existing));
                             List<NodeVO> treeNodeVOList = wbsTreeContractServiceImpl.buildNodeTreeByStream(distinctNodesAll, lowestNodesMap);

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

@@ -70,6 +70,7 @@ import org.springblade.manager.vo.*;
 import org.springblade.resource.feign.NewIOSSClient;
 import org.springblade.system.cache.ParamCache;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DataIntegrityViolationException;
 import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
@@ -86,6 +87,7 @@ import java.text.SimpleDateFormat;
 import java.util.List;
 import java.util.*;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 import java.util.function.Function;
 import java.util.regex.Matcher;
 import java.util.stream.Collectors;
@@ -325,7 +327,10 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                         }
                     }
                 }
-                dataMap2.put("p_key_id", tableInfo.getPkeyId());
+                dataInfo2.put("p_key_id", tableInfo.getPkeyId());
+                dataInfo2.put("classify",tableInfo.getClassify());
+                dataInfo2.put("contractId",tableInfo.getContractId());
+                dataInfo2.put("projectId",tableInfo.getProjectId());
                 tableInfo.setDataMap(dataMap2);
                 result.add(tableInfo);
             }
@@ -467,7 +472,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
     private List<NodeTable> createNodeTables(Long nodeId, String contractId, String projectId, ExecuteType type) {
         List<NodeTable> tableAll = new ArrayList<>();
         if (type.equals(ExecuteType.INSPECTION)) {
-            List<AppWbsTreeContractVO> treeNode = wbsTreeContractService.searchNodeAllTable(nodeId.toString(), "1", contractId, projectId);
+            List<AppWbsTreeContractVO> treeNode = wbsTreeContractService.searchNodeAllTable(nodeId.toString(), "1", contractId, projectId,null);
             tableAll = BeanUtil.copyProperties(treeNode, NodeTable.class);
         } else if (type.equals(ExecuteType.TESTING)) {
             List<WbsTreePrivateVO4> wbsTreePrivateVO4s = wbsTreePrivateService.searchNodeAllTable(nodeId.toString(), "1", "9", contractId, projectId, null, null);
@@ -515,10 +520,14 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
 
     private void updateFormulaLog(String log, Long pKeyId) {
         try {
-            String deleteSql = "DELETE FROM m_formula_log WHERE id = ?";
-            String insertSql = "INSERT INTO m_formula_log (id, content,update_time) VALUES (?, ?,?)";
-            jdbcTemplate.update(deleteSql, pKeyId);
-            jdbcTemplate.update(insertSql, pKeyId, log, DateTime.now());
+            if(log.length()<=2000) {
+                String deleteSql = "DELETE FROM m_formula_log WHERE id = ?";
+                String insertSql = "INSERT INTO m_formula_log (id, content,update_time) VALUES (?, ?,?)";
+                jdbcTemplate.update(deleteSql, pKeyId);
+                jdbcTemplate.update(insertSql, pKeyId, log, DateTime.now());
+            }else{
+                StaticLog.error(log);
+            }
         } catch (Exception e) {
             e.printStackTrace();
         }
@@ -1232,29 +1241,38 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
     }
 
     @Override
-    public R getBussDataInfo(Long pkeyId, int type) {
+    public Map<String,Object> getBussDataInfo(Long pkeyId, int type) {
+        /*只有默认不执行表单公式isFormLoading==false*/
+        return this.getBussDataInfo(pkeyId,type,false);
+    }
+    @Override
+    public Map<String,Object> getBussDataInfo(Long pkeyId, int type,Boolean isFormLoading) {
+        /*需要加载表单公式的时候isFormLoading==true*/
         Document document=null;
         Map<String, Object> reData = new HashMap<>();
 
         WbsTreeContract wbsTreeContract = wbsTreeContractService.getBaseMapper().selectOne(Wrappers.<WbsTreeContract>query().lambda()
                 .eq(WbsTreeContract::getPKeyId, pkeyId));
         if (wbsTreeContract == null) {
-            return R.data(reData);
+            return reData;
         }
 
         if (wbsTreeContract.getHtmlUrl() == null) {
-            return R.data(reData);
+            return reData;
         }
 
         //表单是否存储在
-        String tabName = wbsTreeContract.getInitTableName();
+    /*    String tabName = wbsTreeContract.getInitTableName();
         String isExitSql = " select * from information_schema.TABLES where TABLE_NAME='" + tabName + "'";
         List<Map<String, Object>> tabList = jdbcTemplate.queryForList(isExitSql);
         if (tabList == null || tabList.size() <= 0) {
-            return R.fail("无实体表对应");
+            return reData;
         }
 
-        String querySql = "select * from " + wbsTreeContract.getInitTableName() + " where p_key_id=" + pkeyId;
+        String querySql = "select * from " + wbsTreeContract.getInitTableName() + " where p_key_id=" + pkeyId;*/
+
+
+        String querySql = "select * from table_data_info where p_key_id=" + pkeyId;
         List<Map<String, Object>> dataIn = jdbcTemplate.queryForList(querySql);
 
         // 匹配关联
@@ -1387,6 +1405,12 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
         }
 
         if (dataIn != null && dataIn.size() >= 1) {
+            for (Map<String, Object>  data : dataIn) {
+                reData.put(data.get("tab_key")+"",data.get("key_val"));
+            }
+        }
+
+        /*if (dataIn != null && dataIn.size() >= 1) {
             Map<String, Object> mysqlData = dataIn.get(0);
             for (String key : mysqlData.keySet()) {
                 String tabVal = mysqlData.get(key) + "";
@@ -1451,7 +1475,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                     }
                 }
             }
-        }
+        }*/
 
         // 获取默认值
         QueryWrapper<TextdictInfo> queryWrapper = new QueryWrapper<>();
@@ -1482,8 +1506,10 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
         }
         reData.put("tabGroupId", wbsTreeContract.getTabGroupId());
         /*表单公式*/
-        this.formulaService.paramFormula(wbsTreeContract,reData,document);
-        return R.data(reData);
+        if(isFormLoading) {
+            this.formulaService.paramFormula(wbsTreeContract, reData, document);
+        }
+        return reData;
     }
 
     @Override
@@ -1514,7 +1540,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
             return R.fail("未获取到清表信息");
         }
 
-        Map<String, Object> DataInfo = (Map<String, Object>) getBussDataInfo(pkeyId, 0).getData();
+        Map<String, Object> DataInfo = getBussDataInfo(pkeyId, 0);
         //真实填报率
         Integer realFillRate = 0;
 
@@ -1620,6 +1646,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                     realFillRate = v.intValue();
                 }
             }
+
             Elements trs = table.select("tr");
             if (ObjectUtil.isNotEmpty(DataInfo)) {
                 for (String val : DataInfo.keySet()) {
@@ -1873,8 +1900,11 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
     public void getBussPdfs(String nodeId, String classify, String contractId, String projectId) throws Exception {
         String file_path = FileUtils.getSysLocalFileUrl();
         // 获取有权限的节点信息
-        List<AppWbsTreeContractVO> wbsTreeContractList = wbsTreeContractService.searchNodeAllTable(nodeId, classify, contractId, projectId);
+        List<AppWbsTreeContractVO> wbsTreeContractList = wbsTreeContractService.searchNodeAllTable(nodeId, classify, contractId, projectId,null);
         List<String> data = new ArrayList<>();
+        if(nodeId.indexOf(":")>=0){
+            nodeId = nodeId.split(":")[0];
+        }
         if (wbsTreeContractList != null && wbsTreeContractList.size() >= 1) {
             for (WbsTreeContract wbsInfo : wbsTreeContractList) {
                 // 隐藏的不生成pdf
@@ -2927,11 +2957,14 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
         String contractId = tableInfo1.getString("contractId");
         String projectId = tableInfo1.getString("projectId");
         String classify = tableInfo1.getString("classify");
+        String UserId = AuthUtil.getUserId()+"";
+        RedisTemplate.opsForValue().set("pdf-" + nodeId+"-"+classify, "1", 300, TimeUnit.SECONDS);
         //构造阻塞器
         CountDownLatch cdl = new CountDownLatch(dataArray.size());
         // 构造多线程保存用户数据到表中 并生成excel
         for (int i = 0; i < dataArray.size(); i++) {
             JSONObject jsonObject = dataArray.getJSONObject(i);
+            jsonObject.put("UserId",UserId);
             Thread countUserThread = new Thread(() -> {
                 try {
                     SaveOneTabInfo(jsonObject);
@@ -2942,18 +2975,34 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
                 }
             });
             countUserThread.start();
+
+            new Thread(() -> {
+                try {
+                    cdl.await();
+                    //合并pdf加载
+                    this.getBussPdfs(nodeId+":"+UserId, classify, contractId, projectId);
+                    //更新缓存
+                    informationQueryClient.delAsyncWbsTree(contractId);
+                    RedisTemplate.delete("pdf-" + nodeId+"-"+classify);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                } finally {
+                    cdl.countDown();//标记已经完成一个任务
+                }
+            }).start();
         }
-        //合并pdf加载
-        this.getBussPdfs(nodeId, classify, contractId, projectId);
-        //更新缓存
-        informationQueryClient.delAsyncWbsTree(contractId);
         return R.data("操作成功");
     }
 
     // 保存单表
     public void SaveOneTabInfo(JSONObject tableInfo) throws Exception {
         System.out.println("---------=" + new Date().toLocaleString());
-        String pKeyId = tableInfo.getString("pkeyId");
+        String pKeyId = tableInfo.getString("p_key_id");
+        String nodeId = tableInfo.getString("nodeId");
+        String classify = tableInfo.getString("classify");
+        String UserId = tableInfo.getString("UserId");
+        //真实填报率
+        Integer realFillRate = 0;
 
         tableInfo.fluentRemove("contractId")
                 .fluentRemove("pkeyId")
@@ -3007,6 +3056,31 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
             String htmlString = IoUtil.readToString(inputStreamByUrl);
             Document doc = Jsoup.parse(htmlString);
             Element table = doc.select("table").first();
+
+            //计算填报率
+            List<String> keyList = table.getElementsByAttribute("v-model").stream()
+                    .map(l -> {
+                        String attr = l.attr("v-model");
+                        System.out.println(attr);
+                        String[] split = attr.split("\\.");
+                        return split[1];
+                    })
+                    .collect(Collectors.toList());
+            Long sigSize = table.getElementsByAttribute(":readonly").stream().count();
+            int keySize = keyList.size();
+            List<String> fills = tableInfo.keySet().stream().filter(e -> StringUtils.isNotEmpty(tableInfo.getString(e)) && e.contains("__") && e.contains("key")).collect(Collectors.toList());
+            if (fills.size() != 0 && keyList != null && keyList.size() != 0){
+                if (keySize == sigSize){
+                    realFillRate = 100;
+                }else if (keySize > sigSize) {
+                    keySize = keySize - sigSize.intValue();
+                    keyList.retainAll(fills);
+                    Double v = new Double(keyList.size()) / new Double(keySize) * 100;
+                    realFillRate = v.intValue();
+                }
+            }
+
+
             if (ObjectUtil.isNotEmpty(tableInfo)) {
                 for (String key : tableInfo.keySet()) {
                     if (key.contains("key") && key.contains("__")) {
@@ -3209,8 +3283,20 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
             throw new RuntimeException("字段过长,新增失败");
         }
 
-        String file_path = FileUtils.getSysLocalFileUrl();
+        String fileName ="暂无文件提名1";
+        // 处理文件提名
+        try {
+            WbsTreeContract wbsTreeContractByP = this.wbsTreeContractService.getOne(Wrappers.<WbsTreeContract>lambdaQuery().eq(WbsTreeContract::getPKeyId, nodeId));
+            //处理文件提名
+            fileName = this.wbsParamService.createFileTitle(wbsTreeContractByP);
+        }catch (Exception exception){
+
+        }finally {
+            //huangjn 保存成功后调用生成资料查询列表数据
+            this.informationQueryClient.saveOrUpdateInformationQueryData(nodeId+":"+UserId, "首件使用字段", "业务ID(主要将来给首件使用)", fileName, Integer.parseInt(classify), 2, "false", "源文件(首件字段)", "pdf文件(首件字段)", "首件上传总结报告名称", new ArrayList<>());
+        }
 
+        String file_path = FileUtils.getSysLocalFileUrl();
         String pdfPath = file_path + "/pdf//" + pKeyId + ".pdf";
         String excelPath = file_path + "/pdf//" + pKeyId + ".xlsx";
 
@@ -3275,10 +3361,11 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
         UpdateWrapper<WbsTreeContract> updateWrapper = new UpdateWrapper<>();
         updateWrapper.in("p_key_id", pKeyId + "");
         updateWrapper.set("pdf_url", fileUrl);
+        updateWrapper.set("real_fill_rate", realFillRate);
+        updateWrapper.set("is_tab_pdf", 2);
         wbsTreeContractService.update(updateWrapper);
         tabPdf2.delete();
         tabPdf.delete();
-        ResourceUtil.getFile(excelPath);
         //关闭流
         IoUtil.closeQuietly(outputStream);
         IoUtil.closeQuietly(exceInp);

+ 50 - 27
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java

@@ -167,7 +167,7 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
             /*节点参数*/
             tec.constantMap.put(WP,getWpMap(one));
             /*表格名称*/
-            List<AppWbsTreeContractVO> tableList =wbsTreeContractService.searchNodeAllTable(one.getPkId().toString(), "1", tec.getContractId().toString(),tec.getProjectId().toString());
+            List<AppWbsTreeContractVO> tableList =wbsTreeContractService.searchNodeAllTable(one.getPkId().toString(), "1", tec.getContractId().toString(),tec.getProjectId().toString(),null);
             tec.constantMap.put(TABLE_LIST,tableList);
             /*监表质量附件,过滤掉隐藏表格*/
             tec.constantMap.put("tableNames",tableList.stream().filter(e->StringUtils.isEquals(e.getIsBussShow(),1)&&StringUtils.isNotEquals(e.getTableType(),4)).map(WbsTreeContract::getNodeName).collect(Collectors.toList()));
@@ -676,21 +676,24 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
             constantMap.put(e,e);
         });
     }
-
+    public Map<String,Object> getWpMap(CurrentNode currentNode){
+        return this.getWpMap(currentNode.getWbsNodeId(),currentNode.getWtpPkeyId());
+    }
     /**
      * @Description 获取节点参数
      **/
-    public Map<String,Object> getWpMap(CurrentNode currentNode){
+    public Map<String,Object> getWpMap(Long wbsNodeId,Long wtpPkeyId){
         Map<String,Object> result = new HashMap<>(100);
-        List<WbsParam> total = new ArrayList<>();
-        List<WbsParam> wpsPublic = this.wpService.list(Wrappers.<WbsParam>lambdaQuery().eq(WbsParam::getNodeId,currentNode.getWbsNodeId()).eq(WbsParam::getType,1));
+        List<WbsParam> total=this.getNodeWps(wbsNodeId,wtpPkeyId);
+    /*    List<WbsParam> total = new ArrayList<>();
+        List<WbsParam> wpsPublic = this.wpService.list(Wrappers.<WbsParam>lambdaQuery().eq(WbsParam::getNodeId,wbsNodeId).eq(WbsParam::getType,1));
         if(Func.isNotEmpty(wpsPublic)){
             total.addAll(wpsPublic);
         }
-        List<WbsParam> wpsPrivate = this.wpService.list(Wrappers.<WbsParam>lambdaQuery().eq(WbsParam::getNodeId,currentNode.getWtpPkeyId()).eq(WbsParam::getType,1));
+        List<WbsParam> wpsPrivate = this.wpService.list(Wrappers.<WbsParam>lambdaQuery().eq(WbsParam::getNodeId,wtpPkeyId).eq(WbsParam::getType,1));
         if(Func.isNotEmpty(wpsPrivate)){
             total.addAll(wpsPrivate);
-        }
+        }*/
         Map<String,String> logMap =new HashMap<>();
         if(CollectionUtil.isNotEmpty(total)){
             /*同名参数私有覆盖公用*/
@@ -702,10 +705,28 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
         this.tec.getLog().put(FormulaLog.PARAM,result.entrySet().stream().map(p->logMap.get(p.getKey())+":"+p.getValue()).collect(Collectors.joining(";")));
         /*元素动态绑定*/
         /*绑定节点参数公式*/
+      /*  total= new ArrayList<>(total.stream().collect(Collectors.toMap(WbsParam::getK, w -> w, (v1, v2) -> v2)).values());*/
         this.bindParamFormula(total);
         return result;
     }
 
+    @Override
+    public List<WbsParam> getNodeWps(Long wbsNodeId, Long wtpPkeyId) {
+        List<WbsParam> total = new ArrayList<>();
+        List<WbsParam> wpsPublic = this.wpService.list(Wrappers.<WbsParam>lambdaQuery().eq(WbsParam::getNodeId,wbsNodeId).eq(WbsParam::getType,1));
+        if(Func.isNotEmpty(wpsPublic)){
+            total.addAll(wpsPublic);
+        }
+        List<WbsParam> wpsPrivate = this.wpService.list(Wrappers.<WbsParam>lambdaQuery().eq(WbsParam::getNodeId,wtpPkeyId).eq(WbsParam::getType,1));
+        if(Func.isNotEmpty(wpsPrivate)){
+            total.addAll(wpsPrivate);
+        }
+        if(total.size()>0) {
+            total = new ArrayList<>(total.stream().collect(Collectors.toMap(WbsParam::getK, w -> w, (v1, v2) -> v2)).values());
+        }
+        return total;
+    }
+
     public void bindParamFormula(List<WbsParam> total){
         Map<String,Formula> formulaIdMap = this.wpService.formulaKeyMap(total.stream().map(WbsParam::getK).collect(Collectors.toList()));
         /*查找无绑定公式且单元格只有一个的当前表单元素*/
@@ -1165,9 +1186,7 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
         JSONArray dataArray = new JSONArray();
         for (NodeTable data : subTabList) {
             /*自动挂载附表情况下,装配TableInfo数据*/
-            R bussDataInfo = this.excelTabService.getBussDataInfo(data.getPKeyId(), 1);
-            @SuppressWarnings("unchecked")
-            Map<String, Object>  data1 = (Map<String, Object>) bussDataInfo.getData();
+            Map<String, Object>  data1 = this.excelTabService.getBussDataInfo(data.getPKeyId(), 1);
             data1.put("pkeyId",data.getPKeyId());
             dataArray.add(data1);
         }
@@ -1535,7 +1554,7 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                            WbsTreeContract target = FormulaUtils.copyPage(origin);
                            saveList.add(target);
                        }
-                       this.wbsTreeContractService.saveOrUpdateBatch(saveList);
+                       this.wbsTreeContractService.saveBatch(saveList);
                        list.addAll(saveList);
                        String sql="select * from "+origin.getInitTableName()+" where p_key_id ="+origin.getPKeyId();
                        @SuppressWarnings("unchecked")
@@ -1657,20 +1676,18 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
     public WbsTreePrivate getOriginWtp(Long pkeyId) {
         WbsTreePrivate wtp = this.wbsTreePrivateService.getOne(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getPKeyId,pkeyId));
         int i=10;
-        WbsTreePrivate publicWtp = null;
+        WbsTreePrivate publicWtp = wtp;
         while (i>0) {
-            WbsTreePrivate tmp=  this.wbsTreePrivateService.getOne(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getPKeyId, wtp.getWbsId()));
+            WbsTreePrivate tmp=  this.wbsTreePrivateService.getOne(Wrappers.<WbsTreePrivate>lambdaQuery().eq(WbsTreePrivate::getPKeyId, publicWtp.getWbsId()));
             if (tmp == null) {
                 break;
             }
             publicWtp = tmp;
             i--;
         }
-        if(publicWtp!=null){
-            /*私有引用项目的wbsId其实是被复制的项目的根节点p_key_id,只有溯源才能找到真正的wbsId*/
-            wtp.setWbsId(publicWtp.getWbsId());
-        }
-       return wtp;
+        /*私有引用项目的wbsId其实是被复制的项目的根节点p_key_id,只有溯源才能找到真正的wbsId*/
+        wtp.setWbsId(publicWtp.getWbsId());
+        return wtp;
     }
 
     @Override
@@ -2330,26 +2347,25 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
             WbsTreePrivate publicWtp = this.getOriginWtp(privatePkeyId);
 
             Map<String,Object> result = new HashMap<>(100);
-            List<WbsParam> total = new ArrayList<>();
-            List<WbsParam> wpsPublic = this.wpService.list(Wrappers.<WbsParam>lambdaQuery().eq(WbsParam::getNodeId,publicWtp.getId()).eq(WbsParam::getType,1));
+            List<WbsParam> total = this.getNodeWps(publicWtp.getId(),privatePkeyId);
+/*            List<WbsParam> wpsPublic = this.wpService.list(Wrappers.<WbsParam>lambdaQuery().eq(WbsParam::getNodeId,publicWtp.getId()).eq(WbsParam::getType,1));
             if(Func.isNotEmpty(wpsPublic)){
                 total.addAll(wpsPublic);
             }
             List<WbsParam> wpsPrivate = this.wpService.list(Wrappers.<WbsParam>lambdaQuery().eq(WbsParam::getNodeId,privatePkeyId).eq(WbsParam::getType,1));
             if(Func.isNotEmpty(wpsPrivate)){
                 total.addAll(wpsPrivate);
-            }
+            }*/
             if(CollectionUtil.isNotEmpty(total)){
-                /*同名参数私有覆盖公用*/
                 for(WbsParam p:total){
                     result.put(p.getK(),p.getV());
                 }
             }else{
                 return;
             }
-            /*元素动态绑定*/
+           /* total= new ArrayList<>(total.stream().collect(Collectors.toMap(WbsParam::getK, w -> w, (v1, v2) -> v2)).values());*/
             Map<String,Formula> formulaIdMap = this.wpService.formulaKeyMap(total.stream().map(WbsParam::getK).collect(Collectors.toList()));
-            /*获取已配置节点公式*/
+             //元素动态绑定  获取已配置节点公式   未查明的bug暂时关闭
             Map<Long,String> paramIdKeyMap=  total.stream().collect(Collectors.toMap(WbsParam::getId,WbsParam::getK));
             List<ElementFormulaMapping> mappingList =  this.elementFormulaMappingService.list(Wrappers.<ElementFormulaMapping>lambdaQuery().in(ElementFormulaMapping::getParamId,total.stream().map(WbsParam::getId).collect(Collectors.toList())));
             if(Func.isNotEmpty(mappingList)){
@@ -2364,12 +2380,14 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                     });
                 });
             }
-            /*检查是否可以自动绑定参数公式*/
+
+           // 检查是否可以自动绑定参数公式
             List<FormData> notFormulaFds=fds.stream().filter(f->f.getFormulaId()==null).collect(Collectors.toList());
             if(notFormulaFds.size()>0){
+                List<WbsParam> finalTotal = total;
                 notFormulaFds.forEach(e->{
-                    /*暂时用参数名称是否包含元素名称作为匹配规则*/
-                    total.stream().filter(p->e.getEName().contains(p.getName().replaceAll("【[\\u4E00-\\u9FFF]+】|\\s+",""))).findAny().ifPresent(d->{
+                    //暂时用参数名称是否包含元素名称作为匹配规则
+                    finalTotal.stream().filter(p->e.getEName().contains(p.getName().replaceAll("【[\\u4E00-\\u9FFF]+】|\\s+",""))).findAny().ifPresent(d->{
                         Formula tf= formulaIdMap.get(d.getK());
                         if(tf!=null&&e.getId()!=null) {
                             e.setFormula(tf);
@@ -2433,6 +2451,11 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                 LinkedList<String> treeCode = new LinkedList<>(FormulaUtils.treeCodeSplit(wtcEva.getTreeCode()));
                 List<FormulaDataBlock> formulaDataBlocks = this.getSqlList("select a.* from m_formula_data_block a join (select parent_id from m_wbs_tree_contract where tree_code like '" + treeCode.getLast() + "%' and contract_id =" + wtcEva.getContractId() + " and major_data_type=2 and is_deleted=0 ORDER BY tree_code)b on a.sw_id=b.parent_id ", FormulaDataBlock.class);
                 if (formulaDataBlocks!=null&&formulaDataBlocks.size() > 0) {
+                    /*获取分部工程名称*/
+                    WbsTreeContract node = this.wbsTreeContractService.getOne(Wrappers.<WbsTreeContract>lambdaQuery().eq(WbsTreeContract::getId, wtcEva.getParentId()).eq(WbsTreeContract::getContractId,wtcEva.getContractId()));
+                    WbsTreePrivate wtp = this.wtpId(node.getPKeyId());
+                    WbsTreePrivate publicWtp = this.getOriginWtp(wtp.getPKeyId());
+                    this.getWpMap(publicWtp.getId(),wtp.getPKeyId());
                     formulaDataBlocks.forEach(fdb -> {
                         List<ElementBlock> elementBlockList = JSON.parseArray(fdb.getVal(), ElementBlock.class);
                         elementBlockList.forEach(eb -> {

+ 34 - 4
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ProjectInfoServiceImpl.java

@@ -1,6 +1,9 @@
 package org.springblade.manager.service.impl;
 
+import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.Data;
+import org.apache.commons.lang.StringUtils;
 import org.springblade.manager.entity.ContractInfo;
 import org.springblade.manager.vo.*;
 import org.springblade.manager.entity.ProjectInfo;
@@ -9,11 +12,16 @@ import org.springblade.manager.entity.WbsTreePrivate;
 import org.springblade.manager.mapper.*;
 import org.springblade.manager.service.IProjectInfoService;
 import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.stereotype.Service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 
 import javax.annotation.Resource;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 @Service
 public class ProjectInfoServiceImpl extends BaseServiceImpl<ProjectInfoMapper, ProjectInfo> implements IProjectInfoService {
@@ -28,6 +36,9 @@ public class ProjectInfoServiceImpl extends BaseServiceImpl<ProjectInfoMapper, P
     @Resource
     private SignPfxFileMapper signPfxFileMapper;
 
+    @Resource
+    private JdbcTemplate jdbcTemplate;
+
     public List<ProjectUserAmountVO> queryProjectUserAmount() {
         return this.baseMapper.queryProjectUserAmount();
     }
@@ -37,16 +48,35 @@ public class ProjectInfoServiceImpl extends BaseServiceImpl<ProjectInfoMapper, P
         long current = (vo.getCurrent() - 1L) * vo.getSize();
         List<SingPfxManagementVO> result = this.baseMapper.singPfxManagementPage(current, vo.getSize(), vo, alias);
 
+        Set<Long> projectIds = result.stream().map(SingPfxManagementVO::getProjectId).collect(Collectors.toSet());
+
+        /*获取个人签章Map*/
+        String sql_1 = "select pau.project_id from m_sign_pfx_file AS spf left join m_project_assignment_user AS pau on spf.certificate_user_id = pau.user_id where spf.is_deleted = 0 and pau.is_deleted = 0 and pau.project_id in(" + StringUtils.join(projectIds, ",") + ") and spf.certificate_type = 1";
+        List<QueryPersonalOrEnterpriseCountResultVO> projectSelfCountList = jdbcTemplate.query(sql_1, new BeanPropertyRowMapper<>(QueryPersonalOrEnterpriseCountResultVO.class));
+        Map<Long, Long> projectSelfCountMap = projectSelfCountList.stream().collect(Collectors.groupingBy(QueryPersonalOrEnterpriseCountResultVO::getProjectId, Collectors.counting()));
+
+        /*获取企业签章Map*/
+        String sql_2 = "select spd.project_id from m_sign_pfx_file AS spf LEFT JOIN m_sign_pfx_deputy AS spd ON spf.id = spd.sign_pfx_file_id where spf.is_deleted = 0 and spd.is_deleted = 0 and spd.project_id in(" + StringUtils.join(projectIds, ",") + ") and spf.certificate_type = 2";
+        List<QueryPersonalOrEnterpriseCountResultVO> projectFirmCountList = jdbcTemplate.query(sql_2, new BeanPropertyRowMapper<>(QueryPersonalOrEnterpriseCountResultVO.class));
+        Map<Long, Long> projectFirmCountMap = projectFirmCountList.stream().collect(Collectors.groupingBy(QueryPersonalOrEnterpriseCountResultVO::getProjectId, Collectors.counting()));
+
         result.forEach(vos -> {
             //查询个人签章
-            vos.setPersonalCount(this.signPfxFileMapper.queryPersonalOrEnterpriseCount(vos.getProjectId(), 1).toString());
+            //vos.setPersonalCount(this.signPfxFileMapper.queryPersonalOrEnterpriseCount(vos.getProjectId(), 1).toString());
+            vos.setPersonalCount(ObjectUtil.isNotEmpty(projectSelfCountMap.get(vos.getProjectId())) ? projectSelfCountMap.get(vos.getProjectId()).toString() : null);
             //查询企业章
-            vos.setEnterpriseCount(this.signPfxFileMapper.queryPersonalOrEnterpriseCount(vos.getProjectId(), 2).toString());
+            //vos.setEnterpriseCount(this.signPfxFileMapper.queryPersonalOrEnterpriseCount(vos.getProjectId(), 2).toString());
+            vos.setEnterpriseCount(ObjectUtil.isNotEmpty(projectFirmCountMap.get(vos.getProjectId())) ? projectFirmCountMap.get(vos.getProjectId()).toString() : null);
         });
 
         return result;
     }
 
+    @Data
+    private static class QueryPersonalOrEnterpriseCountResultVO {
+        private Long projectId;
+    }
+
     @Override
     public List<ProjectInfo> selectProjectList(List<String> projectIds) {
         return this.baseMapper.selectProjectList(projectIds);
@@ -90,7 +120,7 @@ public class ProjectInfoServiceImpl extends BaseServiceImpl<ProjectInfoMapper, P
     }
 
     @Override
-    public Long getContractIdbyName(String projectName,String contractName) {
+    public Long getContractIdbyName(String projectName, String contractName) {
         Long contractId = null;
         List<ProjectInfo> projectInfos = baseMapper.selectList(Wrappers.<ProjectInfo>query().lambda()
                 .eq(ProjectInfo::getIsDeleted, 0)
@@ -110,7 +140,7 @@ public class ProjectInfoServiceImpl extends BaseServiceImpl<ProjectInfoMapper, P
             return contractId;
         }
 
-        return  contractInfos.get(0).getId();
+        return contractInfos.get(0).getId();
 
     }
 

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

@@ -14,6 +14,8 @@ import org.jsoup.Jsoup;
 import org.jsoup.nodes.Document;
 import org.jsoup.nodes.Element;
 import org.jsoup.select.Elements;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springblade.business.entity.ConstructionLedger;
 import org.springblade.business.feign.ConstructionLedgerFeignClient;
 import org.springblade.business.feign.InformationQueryClient;
@@ -25,7 +27,6 @@ import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.mp.base.BaseServiceImpl;
 import org.springblade.core.secure.utils.AuthUtil;
-import org.springblade.core.secure.utils.SecureUtil;
 import org.springblade.core.tool.node.ForestNodeMerger;
 import org.springblade.core.tool.utils.*;
 import org.springblade.manager.bean.NodeVO;
@@ -52,10 +53,8 @@ import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.LinkedCaseInsensitiveMap;
 import org.springframework.web.multipart.MultipartFile;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
+import javax.servlet.http.HttpServletRequest;
+import java.io.*;
 import java.math.BigInteger;
 import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
@@ -69,6 +68,7 @@ import java.util.stream.Stream;
 @AllArgsConstructor
 public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractMapper, WbsTreeContract> implements IWbsTreeContractService {
 
+    private static final Logger logger = LoggerFactory.getLogger(WbsTreeContractServiceImpl.class);
     private final ConstructionLedgerFeignClient constructionLedgerFeign;
     private final WbsTreePrivateMapper wbsTreePrivateMapper;
     private final ContractInfoMapper contractInfoMapper;
@@ -79,6 +79,12 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
     @Autowired
     StringRedisTemplate redisTemplate;
 
+    //存储当前合同段contractId对应的合同段树
+    private final Map<String, List<WbsTreeContractLazyVO>> localCacheNodes = new ConcurrentHashMap<>();
+    //存储当前合同段contractId_tableOwner对应的资料查询信息
+    private final Map<String, List<WbsTreeContractLazyQueryInfoVO>> localCacheQueryInfos = new ConcurrentHashMap<>();
+    //存储当前合同段contractId_tableOwner对应的节点数量统计缓存信息
+    private final Map<String, List<WbsTreeContractLazyVO>> localCacheParentCountNodes = new ConcurrentHashMap<>();
 
     @Override
     public List<WbsTreeContract> selectQueryCurrentNodeByAncestors(List<String> ids, String contractId) {
@@ -415,7 +421,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
     }
 
     @Override
-    public List<AppWbsTreeContractVO> searchNodeAllTable(String primaryKeyId, String tableOwner, String contractId, String projectId) {
+    public List<AppWbsTreeContractVO> searchNodeAllTable(String primaryKeyId, String tableOwner, String contractId, String projectId, HttpServletRequest request) {
         //由于Feign调用时,获取不到UserId
         Long userId;
         if (StringUtils.isNotEmpty(primaryKeyId) && primaryKeyId.contains(":")) {
@@ -428,7 +434,9 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
         } else {
             userId = AuthUtil.getUserId();
         }
+
         WbsTreeContract wbsTreeContract = baseMapper.selectOne(Wrappers.<WbsTreeContract>query().lambda()
+                .select(WbsTreeContract::getId, WbsTreeContract::getProjectId, WbsTreeContract::getContractId, WbsTreeContract::getContractIdRelation, WbsTreeContract::getWbsId)
                 .eq(WbsTreeContract::getPKeyId, primaryKeyId));
         if (wbsTreeContract == null) {
             return Collections.emptyList();
@@ -447,12 +455,15 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
             throw new ServiceException("当前用户角色未授权,请先分配角色查看元素表相对应的权限");
         }
 
-        List<String> tableOwnerNumbers = wbsTableOwnerRoleList.stream().map(WbsTableOwnerRole::getTableOwnerNumber).collect(Collectors.toList());
+        //角色表单权限(后管权限配置)
+        Set<String> roleTableOwnerSets = wbsTableOwnerRoleList.stream().map(WbsTableOwnerRole::getTableOwnerNumber).collect(Collectors.toSet());
+
+        //接口请求表单类型(施工质检 或 监理抽检)
+        Set<String> tabTableOwnerSets = new HashSet<>();
 
-        List<String> tableOwnerList = null;
+        /*tableOwner!=null,表示从资料填报查询,查权限数据,roleTableOwnerSets=取交集后*/
         if (StringUtils.isNotEmpty(tableOwner)) {
             String tableOwners;
-            //字典owner_type
             if (tableOwner.equals("1")) {
                 tableOwners = "1,2,3";
             } else if (tableOwner.equals("2")) {
@@ -460,14 +471,46 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
             } else {
                 tableOwners = "7,8,9";
             }
-            tableOwnerList = Func.toStrList(tableOwners);
+            tabTableOwnerSets.addAll(Func.toStrList(tableOwners));
+
+            //取交集
+            roleTableOwnerSets.retainAll(tabTableOwnerSets);
         }
 
-        List<AppWbsTreeContractVO> resultTabs = baseMapper.selectWbsTreeContractList(tableOwnerNumbers, wbsTreeContract.getProjectId(), wbsTreeContract.getWbsId(), wbsTreeContract.getContractId(), wbsTreeContract.getId(), wbsTreeContract.getContractIdRelation(), tableOwnerList);
+        /*tableOwner=null,表示从工程划分处查询,默认查询所有类型数据,roleTableOwnerSets=原始*/
+
+        //判断是客户端还是APP
+        List<AppWbsTreeContractVO> resultTabs;
+        if (ObjectUtil.isNotEmpty(request)) {
+            /*暂时通过获取请求头,不通过Auth获取clientId标识来判断是客户端或APP*/
+            String userAgent = request.getHeader("User-Agent");
+            if (userAgent != null && (userAgent.contains("Windows") || userAgent.contains("windows") || userAgent.contains("Mac") || userAgent.contains("mac"))) {
+                //客户端查询
+                resultTabs = baseMapper.selectWbsTreeContractListClient(roleTableOwnerSets,
+                        wbsTreeContract.getProjectId(), wbsTreeContract.getWbsId(),
+                        wbsTreeContract.getContractId(), wbsTreeContract.getId(),
+                        wbsTreeContract.getContractIdRelation());
+            } else {
+                //APP查询
+                resultTabs = baseMapper.selectWbsTreeContractList(roleTableOwnerSets,
+                        wbsTreeContract.getProjectId(), wbsTreeContract.getWbsId(),
+                        wbsTreeContract.getContractId(), wbsTreeContract.getId(),
+                        wbsTreeContract.getContractIdRelation());
+            }
+        } else {
+            //其他接口调用默认保持原始调用方式查询
+            resultTabs = baseMapper.selectWbsTreeContractList(roleTableOwnerSets,
+                    wbsTreeContract.getProjectId(), wbsTreeContract.getWbsId(),
+                    wbsTreeContract.getContractId(), wbsTreeContract.getId(),
+                    wbsTreeContract.getContractIdRelation());
+        }
 
         //表单排序
-        List<AppWbsTreeContractVO> resultTabsToCopy = this.sortTabs(resultTabs, "__"); //复制表排序
-        return this.sortTabs(resultTabsToCopy, "_PL_"); //频率表排序
+        if (resultTabs.size() > 0) {
+            List<AppWbsTreeContractVO> resultTabsToCopy = this.sortTabs(resultTabs, "__"); //复制表排序
+            return this.sortTabs(resultTabsToCopy, "_PL_"); //频率表排序
+        }
+        return resultTabs;
     }
 
     /**
@@ -681,58 +724,21 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
 
     @Override
     public List<WbsTreeContractLazyVO> lazyQueryContractWbsTree(String id, String contractId, String contractIdRelation, String tableOwner) {
+        if (StringUtils.isEmpty(tableOwner)) {
+            throw new ServiceException("tableOwner is not null");
+        }
         if (ObjectUtil.isNotEmpty(contractId)) {
-            ContractInfo contractInfo = jdbcTemplate.query("select contract_name,contract_type from m_contract_info where id = " + contractId, new BeanPropertyRowMapper<>(ContractInfo.class)).stream().findAny().orElse(null);
+            ContractInfo contractInfo = contractInfoMapper.selectOne(Wrappers.<ContractInfo>lambdaQuery().select(ContractInfo::getContractName, ContractInfo::getContractType).eq(ContractInfo::getId, contractId));
             if (contractInfo != null) {
-                //TODO ************ 施工合同段 ************
+                /*施工合同段*/
                 if (new Integer(1).equals(contractInfo.getContractType())) {
-                    //获取当前合同段所有缓存节点信息
-                    List<WbsTreeContractLazyVO> nodesAll;
-                    /*Object data = redisTemplate.opsForValue().get("blade-manager::contract:wbstree:" + contractId);
-                    if (data != null) {
-                        nodesAll = JSON.parseArray(data.toString(), WbsTreeContractLazyVO.class);
-                    } else {*/
-
-                    //long startTime1 = System.currentTimeMillis();
-
-                    /*开启mybatis-plus二级缓存*/
-                    List<WbsTreeContract> wbsTreeContracts = baseMapper.selectList(Wrappers.<WbsTreeContract>lambdaQuery()
-                            .select(WbsTreeContract::getId, WbsTreeContract::getPKeyId, WbsTreeContract::getParentId)
-                            .eq(WbsTreeContract::getType, 1)
-                            .eq(WbsTreeContract::getStatus, 1)
-                            .eq(WbsTreeContract::getContractId, contractId)
-                    );
-
-                    /*long endTime1 = System.currentTimeMillis();
-                    long executionTime1 = endTime1 - startTime1;
-                    System.out.println("1111111111111:" + executionTime1);*/
-
-                    nodesAll = BeanUtil.copyProperties(wbsTreeContracts, WbsTreeContractLazyVO.class);
-
-                    //nodesAll = jdbcTemplate.query("select a.p_key_id,a.id,a.parent_id from m_wbs_tree_contract a where a.type = 1 and a.status = 1 and a.is_deleted = 0 and a.contract_id = " + contractId, new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
-                    if (nodesAll.size() > 0) {
-                        //判断是否有子级,赋值
-                        Map<Long, List<WbsTreeContractLazyVO>> groupedByParentId = nodesAll.stream().collect(Collectors.groupingBy(WbsTreeContractLazyVO::getParentId));
-                        for (WbsTreeContractLazyVO vo : nodesAll) {
-                            if (vo.getParentId() == 0) {
-                                vo.setHasChildren(1);
-                            }
-                            List<WbsTreeContractLazyVO> childNodes = groupedByParentId.getOrDefault(vo.getId(), null);
-                            if (childNodes != null && childNodes.size() > 0) {
-                                vo.setHasChildren(1);
-                            } else {
-                                vo.setHasChildren(0);
-                            }
-                        }
-                        /*JSONArray array = JSONArray.parseArray(JSON.toJSONString(nodesAll));
-                        redisTemplate.opsForValue().set("blade-manager::contract:wbstree:" + contractId, JSON.toJSON(array).toString());*/
-                    }
-                    //}
+                    //获取本地缓存节点信息
+                    List<WbsTreeContractLazyVO> nodesAll = this.getNodeAll(contractId);
 
                     //获取当前层懒加载节点
-                    List<WbsTreeContractLazyVO> lazyNodes = jdbcTemplate.query("select p_key_id,contract_id,(SELECT id FROM u_contract_tree_drawings where process_id = p_key_id) AS drawingsId,id,parent_id,node_type,type,wbs_type,is_concrete,major_data_type,partition_code,old_id,contract_id_relation,is_concealed_works_node,CASE (SELECT count(1) FROM u_tree_contract_first AS tcf WHERE tcf.is_deleted = 0 AND tcf.wbs_node_id = a.p_key_id) WHEN 0 THEN 'false' ELSE 'true' END AS isFirst,IFNULL(if(length(trim(full_name))>0,full_name,node_name),node_name) AS title,(SELECT CASE WHEN count(1) > 0 THEN 1 ELSE 0 END FROM m_wbs_tree_contract b WHERE b.parent_id = a.id AND b.type = 1 and b.status = 1 AND b.contract_id = " + contractId + " AND b.is_deleted = 0 ) AS hasChildren from m_wbs_tree_contract a where a.node_type != 111 and a.type = 1 and a.status = 1 and a.is_deleted = 0 and parent_id = " + (StringUtils.isNotEmpty(id) ? id : 0) + " and contract_id = " + contractId + " ORDER BY a.sort,title,a.create_time", new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
+                    String sql = "select p_key_id,contract_id,(SELECT id FROM u_contract_tree_drawings where process_id = p_key_id and is_deleted = 0 limit 1) AS drawingsId,id,parent_id,node_type,type,wbs_type,is_concrete,major_data_type,partition_code,old_id,contract_id_relation,is_concealed_works_node,CASE (SELECT count(1) FROM u_tree_contract_first AS tcf WHERE tcf.is_deleted = 0 AND tcf.wbs_node_id = a.p_key_id) WHEN 0 THEN 'false' ELSE 'true' END AS isFirst,IFNULL(if(length(trim(full_name))>0,full_name,node_name),node_name) AS title,(SELECT CASE WHEN count(1) > 0 THEN 1 ELSE 0 END FROM m_wbs_tree_contract b WHERE b.parent_id = a.id AND b.type = 1 and b.status = 1 AND b.contract_id = " + contractId + " AND b.is_deleted = 0 ) AS hasChildren from m_wbs_tree_contract a where a.node_type != 111 and a.type = 1 and a.status = 1 and a.is_deleted = 0 and parent_id = " + (StringUtils.isNotEmpty(id) ? id : 0) + " and contract_id = " + contractId + " ORDER BY a.sort,title,a.create_time";
+                    List<WbsTreeContractLazyVO> lazyNodes = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
                     if (lazyNodes.size() > 0 && nodesAll.size() > 0) {
-                        //所有节点
                         List<WbsTreeContractLazyVO> distinctNodesAll = nodesAll.stream()
                                 .collect(Collectors.collectingAndThen(
                                         Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(WbsTreeContractLazyVO::getPKeyId))),
@@ -745,49 +751,19 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                 ArrayList::new
                         ));
 
-                        //获取当前合同段所有填报资料缓存信息
-                        List<WbsTreeContractLazyQueryInfoVO> queryInfoList;
-                        Object dataInformationQuery;
-                        if (ObjectUtil.isEmpty(tableOwner)) {
-                            dataInformationQuery = redisTemplate.opsForValue().get("blade-manager::contract:wbstree:byInformationQuery:" + contractId + "_1");
-                        } else {
-                            dataInformationQuery = redisTemplate.opsForValue().get("blade-manager::contract:wbstree:byInformationQuery:" + contractId + "_" + tableOwner);
-                        }
-                        if (dataInformationQuery != null) {
-                            queryInfoList = JSON.parseArray(dataInformationQuery.toString(), WbsTreeContractLazyQueryInfoVO.class);
-                        } else {
-                            if (ObjectUtil.isEmpty(tableOwner)) {
-                                queryInfoList = jdbcTemplate.query("select wbs_id,status from u_information_query where type = 1 and contract_id = " + contractId, new BeanPropertyRowMapper<>(WbsTreeContractLazyQueryInfoVO.class));
-                                if (queryInfoList.size() > 0) {
-                                    JSONArray array = JSONArray.parseArray(JSON.toJSONString(queryInfoList));
-                                    redisTemplate.opsForValue().set("blade-manager::contract:wbstree:byInformationQuery:" + contractId + "_1", JSON.toJSON(array).toString());
-                                }
-                            } else {
-                                queryInfoList = jdbcTemplate.query("select wbs_id,status from u_information_query where type = 1 and contract_id = " + contractId + " and classify = " + tableOwner, new BeanPropertyRowMapper<>(WbsTreeContractLazyQueryInfoVO.class));
-                                if (queryInfoList.size() > 0) {
-                                    JSONArray array = JSONArray.parseArray(JSON.toJSONString(queryInfoList));
-                                    redisTemplate.opsForValue().set("blade-manager::contract:wbstree:byInformationQuery:" + contractId + "_" + tableOwner, JSON.toJSON(array).toString());
-                                }
-                            }
-                        }
+                        //获取本地缓存资料信息
+                        List<WbsTreeContractLazyQueryInfoVO> queryInfoList = this.getQueryInfoList(contractId, tableOwner);
+
                         Map<Long, Integer> queryInfoMaps = queryInfoList.stream().filter(f -> ObjectUtil.isNotEmpty(f.getWbsId()))
                                 .collect(Collectors.toMap(WbsTreeContractLazyQueryInfoVO::getWbsId, WbsTreeContractLazyQueryInfoVO::getStatus, (existingValue, newValue) -> existingValue));
                         List<Long> pKeyIdList = new ArrayList<>(queryInfoMaps.keySet());
 
-
-                        //TODO 处理数量
+                        /*处理数量*/
                         //填报过的所有最底层节点
                         List<WbsTreeContractLazyVO> lowestNodesTB = distinctLowestNodesAll.parallelStream().filter(f -> pKeyIdList.contains(f.getPKeyId())).collect(Collectors.toList());
                         List<Long> lowestNodeParentIdsTB = lowestNodesTB.parallelStream().map(WbsTreeContractLazyVO::getParentId).collect(Collectors.toList());
-                        List<WbsTreeContractLazyVO> resultParentNodesTB = new ArrayList<>();
-
-                        //long startTime2 = System.currentTimeMillis();
-
-                        this.recursiveGetParentNodes(resultParentNodesTB, lowestNodeParentIdsTB, nodesAll);
-
-                        /*long endTime2 = System.currentTimeMillis();
-                        long executionTime2 = endTime2 - startTime2;
-                        System.out.println("2222222222222:" + executionTime2);*/
+                        //获取本地缓存节点数量统计
+                        List<WbsTreeContractLazyVO> resultParentNodesTB = this.getCachedParentCountNodes(contractId, lowestNodeParentIdsTB, nodesAll, tableOwner);
 
                         //最底层节点颜色构造后Map
                         Map<Long, WbsTreeContractLazyVO> lowestNodesMap = lowestNodesTB.stream()
@@ -803,8 +779,8 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                     }
                                 }).collect(Collectors.toMap(WbsTreeContractLazyVO::getPKeyId, Function.identity()));
 
-                        //long startTime3 = System.currentTimeMillis();
-                        //TODO 处理颜色
+                        /*处理颜色*/
+                        long startTime = System.currentTimeMillis();
                         //先将WbsTreeContractLazyVO转为NodeVO
                         List<NodeVO> nodeVOList = distinctNodesAll.stream().map(this::convertToNodeVO).collect(Collectors.toList());
                         //转为Map<Long, NodeVO>
@@ -817,12 +793,11 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                         List<NodeVO> nodeVOS = this.flattenTree(treeNodeVOList);
                         //获取所有节点颜色Map
                         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("处理颜色执行时间:" + executionTime + " ms");
 
-                        /*long endTime3 = System.currentTimeMillis();
-                        long executionTime3 = endTime3- startTime3;
-                        System.out.println("3333333333333:" + executionTime3);*/
-
-                        //TODO 处理最终结果集
+                        /*处理最终结果集*/
                         if (lazyNodes.size() > 0) {
                             //处理填报数量
                             Map<Long, Integer> countMap = new HashMap<>();
@@ -850,6 +825,11 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                 lazyNodeVO.setSubmitCounts(ObjectUtil.isNotEmpty(countMap.get(lazyNodeVO.getPKeyId())) ? countMap.get(lazyNodeVO.getPKeyId()) : (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);
@@ -864,7 +844,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                         return lazyNodes;
                     }
 
-                    //TODO ************ 监理、业主合同段 ************
+                    /*监理、业主合同段*/
                 } else if (new Integer("2").equals(contractInfo.getContractType()) || new Integer("3").equals(contractInfo.getContractType())) {
                     List<WbsTreeContractLazyVO> lazyNodesAll = new ArrayList<>();
                     List<String> contractIds = new ArrayList<>();
@@ -881,125 +861,49 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                     for (String sgContractId : contractIds) {
                         ContractInfo sgContractInfo = jdbcTemplate.query("select contract_name from m_contract_info where id = " + sgContractId, new BeanPropertyRowMapper<>(ContractInfo.class)).stream().findAny().orElse(null);
                         if (sgContractInfo != null) {
-                            //获取当前合同段所有缓存节点信息
-                            List<WbsTreeContractLazyVO> nodesAll;
-                            /*Object data = redisTemplate.opsForValue().get("blade-manager::contract:wbstree:" + sgContractId);
-                            if (data != null) {
-                                nodesAll = JSON.parseArray(data.toString(), WbsTreeContractLazyVO.class);
-                            } else {*/
-
-                            List<WbsTreeContract> wbsTreeContracts = baseMapper.selectList(Wrappers.<WbsTreeContract>lambdaQuery()
-                                    .select(WbsTreeContract::getId, WbsTreeContract::getPKeyId, WbsTreeContract::getParentId)
-                                    .eq(WbsTreeContract::getType, 1)
-                                    .eq(WbsTreeContract::getStatus, 1)
-                                    .eq(WbsTreeContract::getContractId, sgContractId)
-                            );
-                            nodesAll = BeanUtil.copyProperties(wbsTreeContracts, WbsTreeContractLazyVO.class);
-
-                            //nodesAll = jdbcTemplate.query("select a.p_key_id,a.id,a.parent_id from m_wbs_tree_contract a where a.type = 1 and a.status = 1 and a.is_deleted = 0 and a.contract_id = " + sgContractId, new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
-                            if (nodesAll.size() > 0) {
-                                //判断是否有子级,赋值
-                                Map<Long, List<WbsTreeContractLazyVO>> groupedByParentId = nodesAll.stream().collect(Collectors.groupingBy(WbsTreeContractLazyVO::getParentId));
-                                for (WbsTreeContractLazyVO vo : nodesAll) {
-                                    if (vo.getParentId() == 0) {
-                                        vo.setHasChildren(1);
-                                    }
-                                    List<WbsTreeContractLazyVO> childNodes = groupedByParentId.getOrDefault(vo.getId(), null);
-                                    if (childNodes != null && childNodes.size() > 0) {
-                                        vo.setHasChildren(1);
-                                    } else {
-                                        vo.setHasChildren(0);
-                                    }
-                                }
-
-                                /*JSONArray array = JSONArray.parseArray(JSON.toJSONString(nodesAll));
-                                redisTemplate.opsForValue().set("blade-manager::contract:wbstree:" + sgContractId, JSON.toJSON(array).toString());*/
-                            }
-                            //}
+                            List<WbsTreeContractLazyVO> nodesAll = this.getNodeAll(sgContractId);
 
-                            //获取当前层懒加载节点
-                            List<WbsTreeContractLazyVO> lazyNodes = jdbcTemplate.query("select p_key_id,contract_id,(SELECT id FROM u_contract_tree_drawings where process_id = p_key_id) AS drawingsId,id,parent_id,node_type,type,wbs_type,major_data_type,partition_code,old_id,contract_id_relation,is_concealed_works_node,CASE (SELECT count(1) FROM u_tree_contract_first AS tcf WHERE tcf.is_deleted = 0 AND tcf.wbs_node_id = a.p_key_id) WHEN 0 THEN 'false' ELSE 'true' END AS isFirst,IFNULL(if(length(trim(full_name))>0,full_name,node_name),node_name) AS title,(SELECT CASE WHEN count(1) > 0 THEN 1 ELSE 0 END FROM m_wbs_tree_contract b WHERE b.parent_id = a.id AND  b.type = 1 and b.status = 1 AND b.contract_id = " + sgContractId + " AND b.is_deleted = 0 ) AS hasChildren from m_wbs_tree_contract a where a.node_type != 111 and a.type = 1 and a.status = 1 and a.is_deleted = 0 and parent_id = " + (StringUtils.isNotEmpty(id) ? id : 0) + " and contract_id = " + sgContractId + " ORDER BY a.sort,title,a.create_time", new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
+                            List<WbsTreeContractLazyVO> lazyNodes = jdbcTemplate.query("select p_key_id,contract_id,(SELECT id FROM u_contract_tree_drawings where process_id = p_key_id and is_deleted = 0 limit 1) AS drawingsId,id,parent_id,node_type,type,wbs_type,major_data_type,partition_code,old_id,contract_id_relation,is_concealed_works_node,CASE (SELECT count(1) FROM u_tree_contract_first AS tcf WHERE tcf.is_deleted = 0 AND tcf.wbs_node_id = a.p_key_id) WHEN 0 THEN 'false' ELSE 'true' END AS isFirst,IFNULL(if(length(trim(full_name))>0,full_name,node_name),node_name) AS title,(SELECT CASE WHEN count(1) > 0 THEN 1 ELSE 0 END FROM m_wbs_tree_contract b WHERE b.parent_id = a.id AND  b.type = 1 and b.status = 1 AND b.contract_id = " + sgContractId + " AND b.is_deleted = 0 ) AS hasChildren from m_wbs_tree_contract a where a.node_type != 111 and a.type = 1 and a.status = 1 and a.is_deleted = 0 and parent_id = " + (StringUtils.isNotEmpty(id) ? id : 0) + " and contract_id = " + sgContractId + " ORDER BY a.sort,title,a.create_time", new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
                             if (lazyNodes.size() > 0 && nodesAll.size() > 0) {
-                                //所有节点
                                 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;
-                                Object dataInformationQuery;
-                                if (ObjectUtil.isEmpty(tableOwner)) {
-                                    dataInformationQuery = redisTemplate.opsForValue().get("blade-manager::contract:wbstree:byInformationQuery:" + sgContractId + "_1");
-                                } else {
-                                    dataInformationQuery = redisTemplate.opsForValue().get("blade-manager::contract:wbstree:byInformationQuery:" + sgContractId + "_" + tableOwner);
-                                }
-                                if (dataInformationQuery != null) {
-                                    queryInfoList = JSON.parseArray(dataInformationQuery.toString(), WbsTreeContractLazyQueryInfoVO.class);
-                                } else {
-                                    if (ObjectUtil.isEmpty(tableOwner)) {
-                                        queryInfoList = jdbcTemplate.query("select wbs_id,status from u_information_query where type = 1 and contract_id = " + sgContractId, new BeanPropertyRowMapper<>(WbsTreeContractLazyQueryInfoVO.class));
-                                        if (queryInfoList.size() > 0) {
-                                            JSONArray array = JSONArray.parseArray(JSON.toJSONString(queryInfoList));
-                                            redisTemplate.opsForValue().set("blade-manager::contract:wbstree:byInformationQuery:" + sgContractId + "_1", JSON.toJSON(array).toString());
-                                        }
-                                    } else {
-                                        queryInfoList = jdbcTemplate.query("select wbs_id,status from u_information_query where type = 1 and contract_id = " + sgContractId + " and classify = " + tableOwner, new BeanPropertyRowMapper<>(WbsTreeContractLazyQueryInfoVO.class));
-                                        if (queryInfoList.size() > 0) {
-                                            JSONArray array = JSONArray.parseArray(JSON.toJSONString(queryInfoList));
-                                            redisTemplate.opsForValue().set("blade-manager::contract:wbstree:byInformationQuery:" + sgContractId + "_" + tableOwner, JSON.toJSON(array).toString());
-                                        }
-                                    }
-                                }
+                                List<WbsTreeContractLazyQueryInfoVO> queryInfoList = this.getQueryInfoList(sgContractId, tableOwner);
+
                                 Map<Long, Integer> queryInfoMaps = queryInfoList.stream().filter(f -> ObjectUtil.isNotEmpty(f.getWbsId()))
                                         .collect(Collectors.toMap(WbsTreeContractLazyQueryInfoVO::getWbsId, WbsTreeContractLazyQueryInfoVO::getStatus, (existingValue, newValue) -> existingValue));
                                 List<Long> pKeyIdList = new ArrayList<>(queryInfoMaps.keySet());
 
-                                //TODO 处理数量
-                                //填报过的所有最底层节点
                                 List<WbsTreeContractLazyVO> lowestNodesTB = distinctLowestNodesAll.parallelStream().filter(f -> pKeyIdList.contains(f.getPKeyId())).collect(Collectors.toList());
                                 List<Long> lowestNodeParentIdsTB = lowestNodesTB.parallelStream().map(WbsTreeContractLazyVO::getParentId).collect(Collectors.toList());
-                                List<WbsTreeContractLazyVO> resultParentNodesTB = new ArrayList<>();
-                                this.recursiveGetParentNodes(resultParentNodesTB, lowestNodeParentIdsTB, nodesAll);
 
-                                //最底层节点颜色构造后Map
+                                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) {
-                                                //任务状态0=未上报=颜色2蓝色、任务状态1=待审批=颜色3橙色、任务状态2=已审批=颜色4绿色
-                                                ///*任务状态3=已废除=颜色1黑色*/(2023年10月16日13:59:00 已废除改为=颜色2蓝色)
                                                 vo.setColorStatus(colorStatus == 0 ? 2 : (colorStatus == 1 ? 3 : (colorStatus == 2 ? 4 : 2)));
                                             } else {
-                                                //未填报的=颜色1黑色
                                                 vo.setColorStatus(1);
                                             }
                                         }).collect(Collectors.toMap(WbsTreeContractLazyVO::getPKeyId, Function.identity()));
 
-                                //TODO 处理颜色
-                                //先将WbsTreeContractLazyVO转为NodeVO
                                 List<NodeVO> nodeVOList = distinctNodesAll.stream().map(this::convertToNodeVO).collect(Collectors.toList());
-                                //转为Map<Long, NodeVO>
                                 Map<Long, NodeVO> nodeVOMap = nodeVOList.stream().collect(Collectors.toMap(NodeVO::getId, vo -> vo, (existing, replacement) -> existing));
-                                //把distinctNodesAll把所有节点转为树形结构,再转为List<NodeVO>对象
                                 List<NodeVO> treeNodeVOList = this.buildNodeTreeByStream(distinctNodesAll, lowestNodesMap);
-                                //处理节点颜色
                                 NodeVO.calculateStatusToDFS(treeNodeVOList, nodeVOMap);
-                                //把树形结构转为普通List集合
                                 List<NodeVO> nodeVOS = this.flattenTree(treeNodeVOList);
-                                //获取所有节点颜色Map
                                 Map<Long, Integer> nodeColorStatusMap = nodeVOS.stream().collect(Collectors.toMap(NodeVO::getPKeyId, NodeVO::getStatus, (existing, replacement) -> existing));
 
-                                //TODO 处理最终结果集
                                 if (lazyNodes.size() > 0) {
-                                    //处理填报数量
                                     Map<Long, Integer> countMap = new HashMap<>();
                                     for (WbsTreeContractLazyVO node : resultParentNodesTB) {
                                         Long key = node.getPKeyId();
@@ -1010,9 +914,8 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                         }
                                     }
 
-                                    //返回最终结果集
                                     for (WbsTreeContractLazyVO lazyNodeVO : lazyNodes) {
-                                        lazyNodeVO.setType(lazyNodeVO.getNodeType()); //前端显示需要一样的,所以修改成一样的
+                                        lazyNodeVO.setType(lazyNodeVO.getNodeType());
                                         lazyNodeVO.setNotExsitChild(!lazyNodeVO.getHasChildren().equals(1));
                                         lazyNodeVO.setPrimaryKeyId(lazyNodeVO.getPKeyId());
                                         lazyNodeVO.setContractIdRelation(sgContractId);
@@ -1022,10 +925,12 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                             }
                                         }
 
-                                        //设置数量
                                         lazyNodeVO.setSubmitCounts(ObjectUtil.isNotEmpty(countMap.get(lazyNodeVO.getPKeyId())) ? countMap.get(lazyNodeVO.getPKeyId()) : (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);
@@ -1048,14 +953,162 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
         return null;
     }
 
+
+    /**
+     * 获取当前合同段所有节点缓存
+     *
+     * @param contractId
+     * @return
+     */
+    public List<WbsTreeContractLazyVO> getNodeAll(String contractId) {
+        //获取本地缓存
+        List<WbsTreeContractLazyVO> nodesAll = localCacheNodes.get(contractId);
+
+        if (nodesAll == null || nodesAll.size() == 0) {
+            //从Redis获取数据
+            Object data = redisTemplate.opsForValue().get("blade-manager::contract:wbstree:" + contractId);
+            if (data != null) {
+                nodesAll = JSON.parseArray(data.toString(), WbsTreeContractLazyVO.class);
+                //更新本地缓存
+                localCacheNodes.put(contractId, nodesAll);
+
+            } else {
+                //返回数据库数据
+                long startTime = System.currentTimeMillis();
+                nodesAll = jdbcTemplate.query("select a.p_key_id,a.id,a.parent_id from m_wbs_tree_contract a where a.type = 1 and a.status = 1 and a.is_deleted = 0 and a.contract_id = " + contractId, new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
+                long endTime = System.currentTimeMillis();
+                long executionTime = endTime - startTime;
+                logger.info("查询合同段 " + contractId + " 所有树执行时间:" + executionTime + " ms");
+
+                if (nodesAll.size() > 0) {
+                    //判断是否有子级,赋值
+                    Map<Long, List<WbsTreeContractLazyVO>> groupedByParentId = nodesAll.stream().collect(Collectors.groupingBy(WbsTreeContractLazyVO::getParentId));
+                    for (WbsTreeContractLazyVO vo : nodesAll) {
+                        if (vo.getParentId() == 0) {
+                            vo.setHasChildren(1);
+                        }
+                        List<WbsTreeContractLazyVO> childNodes = groupedByParentId.getOrDefault(vo.getId(), null);
+                        if (childNodes != null && childNodes.size() > 0) {
+                            vo.setHasChildren(1);
+                        } else {
+                            vo.setHasChildren(0);
+                        }
+                    }
+                    //存储到Redis中
+                    JSONArray array = JSONArray.parseArray(JSON.toJSONString(nodesAll));
+                    redisTemplate.opsForValue().set("blade-manager::contract:wbstree:" + contractId, JSON.toJSON(array).toString());
+
+                    //更新本地缓存
+                    localCacheNodes.put(contractId, nodesAll);
+                }
+            }
+        }
+        return nodesAll;
+    }
+
+
+    /**
+     * 获取节点数量统计缓存
+     *
+     * @param contractId
+     * @param lowestNodeParentIdsTB
+     * @param nodesAll
+     * @return
+     */
+    public List<WbsTreeContractLazyVO> getCachedParentCountNodes(String contractId, List<Long> lowestNodeParentIdsTB, List<WbsTreeContractLazyVO> nodesAll, String tableOwner) {
+        //从本地缓存获取数据
+        String cacheKey = contractId + "_" + tableOwner;
+        List<WbsTreeContractLazyVO> resultParentNodesTB = localCacheParentCountNodes.get(cacheKey);
+
+        if (resultParentNodesTB == null || resultParentNodesTB.isEmpty()) {
+
+            //从Redis获取数据
+            Object data = redisTemplate.opsForValue().get("blade-manager::contract:wbstree:byParentCountNodes:" + cacheKey);
+            if (data != null) {
+                resultParentNodesTB = JSON.parseArray(data.toString(), WbsTreeContractLazyVO.class);
+                //更新本地缓存
+                localCacheParentCountNodes.put(cacheKey, resultParentNodesTB);
+
+            } else {
+                /*重新计算,进行递归获取父节点计数统计*/
+                resultParentNodesTB = new ArrayList<>();
+                long startTime = System.currentTimeMillis();
+                this.recursiveGetParentNodes(resultParentNodesTB, lowestNodeParentIdsTB, nodesAll);
+                long endTime = System.currentTimeMillis();
+                long executionTime = endTime - startTime;
+                logger.info("节点树数量统计计算耗时:" + executionTime + " ms");
+
+                if (resultParentNodesTB.size() > 0) {
+                    //存储到Redis中
+                    JSONArray array = JSONArray.parseArray(JSON.toJSONString(resultParentNodesTB));
+                    redisTemplate.opsForValue().set("blade-manager::contract:wbstree:byParentCountNodes:" + cacheKey, JSON.toJSON(array).toString());
+
+                    //更新本地缓存
+                    localCacheParentCountNodes.put(cacheKey, resultParentNodesTB);
+                }
+            }
+        }
+
+        return resultParentNodesTB;
+    }
+
+
+    /**
+     * 获取当前合同段所有填报资料缓存信息
+     *
+     * @param contractId
+     * @param tableOwner
+     * @return
+     */
+    public List<WbsTreeContractLazyQueryInfoVO> getQueryInfoList(String contractId, String tableOwner) {
+        //从本地缓存获取
+        String cacheKey = contractId + "_" + tableOwner;
+        List<WbsTreeContractLazyQueryInfoVO> cachedQueryInfoList = localCacheQueryInfos.get(cacheKey);
+
+        if (cachedQueryInfoList != null && !cachedQueryInfoList.isEmpty()) {
+            return cachedQueryInfoList;
+        }
+
+        //从Redis获取数据
+        Object dataInformationQuery = redisTemplate.opsForValue().get("blade-manager::contract:wbstree:byInformationQuery:" + cacheKey);
+
+        List<WbsTreeContractLazyQueryInfoVO> queryInfoList;
+        if (dataInformationQuery != null) {
+            queryInfoList = JSON.parseArray(dataInformationQuery.toString(), WbsTreeContractLazyQueryInfoVO.class);
+            //更新本地缓存
+            localCacheQueryInfos.put(cacheKey, queryInfoList);
+
+        } else {
+            //返回数据库数据
+            long startTime = System.currentTimeMillis();
+            String querySql = "select wbs_id,status from u_information_query where type = 1 and contract_id = " + contractId + " and classify = " + tableOwner;
+            queryInfoList = jdbcTemplate.query(querySql, new BeanPropertyRowMapper<>(WbsTreeContractLazyQueryInfoVO.class));
+            long endTime = System.currentTimeMillis();
+            long executionTime = endTime - startTime;
+            logger.info("合同段资料信息查询耗时:" + executionTime + " ms");
+
+            if (!queryInfoList.isEmpty()) {
+                JSONArray array = JSONArray.parseArray(JSON.toJSONString(queryInfoList));
+
+                //存储到Redis中
+                redisTemplate.opsForValue().set("blade-manager::contract:wbstree:byInformationQuery:" + cacheKey, JSON.toJSON(array).toString());
+
+                //更新本地缓存
+                localCacheQueryInfos.put(cacheKey, queryInfoList);
+            }
+        }
+
+        return queryInfoList;
+    }
+
     @Override
-    public List<WbsTreeContractLazyVO> imageLazyQueryContractWbsTree(String id, String contractId, String contractIdRelation, String classId) {
+    public List<WbsTreeContractLazyVO> imageLazyQueryContractWbsTree(String id, String contractId, String
+            contractIdRelation, String classId) {
         if (ObjectUtil.isNotEmpty(contractId)) {
             ContractInfo contractInfo = jdbcTemplate.query("select contract_name,contract_type from m_contract_info where id = " + contractId, new BeanPropertyRowMapper<>(ContractInfo.class)).stream().findAny().orElse(null);
             if (contractInfo != null) {
-                //TODO 施工合同段
+                /*质检施工合同段*/
                 if (new Integer(1).equals(contractInfo.getContractType())) {
-                    //获取当前合同段所有缓存节点信息
                     List<WbsTreeContractLazyVO> nodesAll;
                     Object data = redisTemplate.opsForValue().get("blade-manager::contract:wbstree:" + contractId);
                     if (data != null) {
@@ -1063,7 +1116,6 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                     } else {
                         nodesAll = jdbcTemplate.query("select a.p_key_id,a.id,a.parent_id from m_wbs_tree_contract a where a.type = 1 and a.status = 1 and a.is_deleted = 0 and a.contract_id = " + contractId, new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
                         if (nodesAll.size() > 0) {
-                            //判断是否有子级,赋值
                             Map<Long, List<WbsTreeContractLazyVO>> groupedByParentId = nodesAll.stream().collect(Collectors.groupingBy(WbsTreeContractLazyVO::getParentId));
                             for (WbsTreeContractLazyVO vo : nodesAll) {
                                 if (vo.getParentId() == 0) {
@@ -1080,24 +1132,21 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                             redisTemplate.opsForValue().set("blade-manager::contract:wbstree:" + contractId, JSON.toJSON(array).toString());
                         }
                     }
-                    //获取当前层懒加载节点
-                    List<WbsTreeContractLazyVO> lazyNodes = jdbcTemplate.query("select p_key_id,(SELECT id FROM u_contract_tree_drawings where process_id = p_key_id) AS drawingsId,id,parent_id,node_type,type,wbs_type,is_concrete,major_data_type,partition_code,old_id,contract_id_relation,is_concealed_works_node,CASE (SELECT count(1) FROM u_tree_contract_first AS tcf WHERE tcf.is_deleted = 0 AND tcf.wbs_node_id = a.p_key_id) WHEN 0 THEN 'false' ELSE 'true' END AS isFirst,IFNULL(if(length(trim(full_name))>0,full_name,node_name),node_name) AS title,(SELECT CASE WHEN count(1) > 0 THEN 1 ELSE 0 END FROM m_wbs_tree_contract b WHERE b.parent_id = a.id AND b.type = 1 and b.status = 1 AND b.contract_id = " + contractId + " AND b.is_deleted = 0 ) AS hasChildren from m_wbs_tree_contract a where a.node_type != 111 and a.type = 1 and a.status = 1 and a.is_deleted = 0 and parent_id = " + (StringUtils.isNotEmpty(id) ? id : 0) + " and contract_id = " + contractId + " ORDER BY a.sort,title,a.create_time", new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
+                    List<WbsTreeContractLazyVO> lazyNodes = jdbcTemplate.query("select p_key_id,(SELECT id FROM u_contract_tree_drawings where process_id = p_key_id and is_deleted = 0 limit 1) AS drawingsId,id,parent_id,node_type,type,wbs_type,is_concrete,major_data_type,partition_code,old_id,contract_id_relation,is_concealed_works_node,CASE (SELECT count(1) FROM u_tree_contract_first AS tcf WHERE tcf.is_deleted = 0 AND tcf.wbs_node_id = a.p_key_id) WHEN 0 THEN 'false' ELSE 'true' END AS isFirst,IFNULL(if(length(trim(full_name))>0,full_name,node_name),node_name) AS title,(SELECT CASE WHEN count(1) > 0 THEN 1 ELSE 0 END FROM m_wbs_tree_contract b WHERE b.parent_id = a.id AND b.type = 1 and b.status = 1 AND b.contract_id = " + contractId + " AND b.is_deleted = 0 ) AS hasChildren from m_wbs_tree_contract a where a.node_type != 111 and a.type = 1 and a.status = 1 and a.is_deleted = 0 and parent_id = " + (StringUtils.isNotEmpty(id) ? id : 0) + " and contract_id = " + contractId + " ORDER BY a.sort,title,a.create_time", new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
                     if (lazyNodes.size() > 0 && nodesAll.size() > 0) {
-                        //所有节点
                         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<WbsTreeContractLazyFileVO> queryFileList = jdbcTemplate.query("select wbs_id,id from u_image_classification_file where status = 1 and is_deleted = 0 and contract_id = " + contractId + " and classify_id = " + classId, new BeanPropertyRowMapper<>(WbsTreeContractLazyFileVO.class));
-                        //最底层节点与存储文件数量map
+
                         Map<Long, Integer> queryFileMaps = queryFileList.stream()
                                 .filter(f -> ObjectUtil.isNotEmpty(f.getWbsId()))
                                 .collect(Collectors.groupingBy(
@@ -1124,7 +1173,6 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                         List<WbsTreeContractLazyVO> resultParentNodesTB = new ArrayList<>();
                         this.recursiveGetParentNodes(resultParentNodesTB, lowestNodeParentIdsTB, nodesAll);
 
-                        //处理最终结果集
                         if (lazyNodes.size() > 0) {
                             Map<Long, Integer> countMap = new HashMap<>();
                             for (WbsTreeContractLazyVO node : resultParentNodesTB) {
@@ -1136,7 +1184,6 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                 }
                             }
 
-                            //返回最终结果集
                             for (WbsTreeContractLazyVO lazyNodeVO : lazyNodes) {
                                 lazyNodeVO.setType(lazyNodeVO.getNodeType());
                                 lazyNodeVO.setNotExsitChild(!lazyNodeVO.getHasChildren().equals(1));
@@ -1146,14 +1193,13 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                         lazyNodeVO.setTitle(contractInfo.getContractName());
                                     }
                                 }
-                                //设置数量
                                 lazyNodeVO.setSubmitCounts(ObjectUtil.isNotEmpty(countMap.get(lazyNodeVO.getPKeyId())) ? countMap.get(lazyNodeVO.getPKeyId()) : (ObjectUtil.isNotEmpty(queryFileMaps.get(lazyNodeVO.getPKeyId())) ? queryFileMaps.get(lazyNodeVO.getPKeyId()) : 0));
                             }
                         }
                         return lazyNodes;
                     }
 
-                    //TODO 监理、业主合同段
+                    /*监理、业主合同段*/
                 } else if (new Integer("2").equals(contractInfo.getContractType()) || new Integer("3").equals(contractInfo.getContractType())) {
                     List<WbsTreeContractLazyVO> lazyNodesAll = new ArrayList<>();
                     List<String> contractIds = new ArrayList<>();
@@ -1170,7 +1216,6 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                     for (String sgContractId : contractIds) {
                         ContractInfo sgContractInfo = jdbcTemplate.query("select contract_name from m_contract_info where id = " + sgContractId, new BeanPropertyRowMapper<>(ContractInfo.class)).stream().findAny().orElse(null);
                         if (sgContractInfo != null) {
-                            //获取当前合同段所有缓存节点信息
                             List<WbsTreeContractLazyVO> nodesAll;
                             Object data = redisTemplate.opsForValue().get("blade-manager::contract:wbstree:" + sgContractId);
                             if (data != null) {
@@ -1178,7 +1223,6 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                             } else {
                                 nodesAll = jdbcTemplate.query("select a.p_key_id,a.id,a.parent_id from m_wbs_tree_contract a where a.type = 1 and a.status = 1 and a.is_deleted = 0 and a.contract_id = " + sgContractId, new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
                                 if (nodesAll.size() > 0) {
-                                    //判断是否有子级,赋值
                                     Map<Long, List<WbsTreeContractLazyVO>> groupedByParentId = nodesAll.stream().collect(Collectors.groupingBy(WbsTreeContractLazyVO::getParentId));
                                     for (WbsTreeContractLazyVO vo : nodesAll) {
                                         if (vo.getParentId() == 0) {
@@ -1196,17 +1240,13 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                 }
                             }
 
-                            //获取当前层懒加载节点
-                            List<WbsTreeContractLazyVO> lazyNodes = jdbcTemplate.query("select p_key_id,(SELECT id FROM u_contract_tree_drawings where process_id = p_key_id) AS drawingsId,id,parent_id,node_type,type,wbs_type,major_data_type,partition_code,old_id,contract_id_relation,is_concealed_works_node,CASE (SELECT count(1) FROM u_tree_contract_first AS tcf WHERE tcf.is_deleted = 0 AND tcf.wbs_node_id = a.p_key_id) WHEN 0 THEN 'false' ELSE 'true' END AS isFirst,IFNULL(if(length(trim(full_name))>0,full_name,node_name),node_name) AS title,(SELECT CASE WHEN count(1) > 0 THEN 1 ELSE 0 END FROM m_wbs_tree_contract b WHERE b.parent_id = a.id AND  b.type = 1 and b.status = 1 AND b.contract_id = " + sgContractId + " AND b.is_deleted = 0 ) AS hasChildren from m_wbs_tree_contract a where a.node_type != 111 and a.type = 1 and a.status = 1 and a.is_deleted = 0 and parent_id = " + (StringUtils.isNotEmpty(id) ? id : 0) + " and contract_id = " + sgContractId + " ORDER BY a.sort,title,a.create_time", new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
+                            List<WbsTreeContractLazyVO> lazyNodes = jdbcTemplate.query("select p_key_id,(SELECT id FROM u_contract_tree_drawings where process_id = p_key_id and is_deleted = 0 limit 1) AS drawingsId,id,parent_id,node_type,type,wbs_type,major_data_type,partition_code,old_id,contract_id_relation,is_concealed_works_node,CASE (SELECT count(1) FROM u_tree_contract_first AS tcf WHERE tcf.is_deleted = 0 AND tcf.wbs_node_id = a.p_key_id) WHEN 0 THEN 'false' ELSE 'true' END AS isFirst,IFNULL(if(length(trim(full_name))>0,full_name,node_name),node_name) AS title,(SELECT CASE WHEN count(1) > 0 THEN 1 ELSE 0 END FROM m_wbs_tree_contract b WHERE b.parent_id = a.id AND  b.type = 1 and b.status = 1 AND b.contract_id = " + sgContractId + " AND b.is_deleted = 0 ) AS hasChildren from m_wbs_tree_contract a where a.node_type != 111 and a.type = 1 and a.status = 1 and a.is_deleted = 0 and parent_id = " + (StringUtils.isNotEmpty(id) ? id : 0) + " and contract_id = " + sgContractId + " ORDER BY a.sort,title,a.create_time", new BeanPropertyRowMapper<>(WbsTreeContractLazyVO.class));
                             if (lazyNodes.size() > 0 && nodesAll.size() > 0) {
-                                //所有节点
                                 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
@@ -1214,7 +1254,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
 
                                 //获取当前合同段所有影像文件信息(只查看监理自己的,资料填报是查看的施工合同段的,这里有区别)
                                 List<WbsTreeContractLazyFileVO> queryFileList = jdbcTemplate.query("select wbs_id,id from u_image_classification_file where status = 1 and contract_id = " + contractId + " and classify_id = " + classId, new BeanPropertyRowMapper<>(WbsTreeContractLazyFileVO.class));
-                                //最底层节点与存储文件数量map
+
                                 Map<Long, Integer> queryFileMaps = queryFileList.stream()
                                         .filter(f -> ObjectUtil.isNotEmpty(f.getWbsId()))
                                         .collect(Collectors.groupingBy(
@@ -1239,7 +1279,6 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                 List<WbsTreeContractLazyVO> resultParentNodesTB = new ArrayList<>();
                                 this.recursiveGetParentNodes(resultParentNodesTB, lowestNodeParentIdsTB, nodesAll);
 
-                                //处理最终结果集
                                 if (lazyNodes.size() > 0) {
                                     Map<Long, Integer> countMap = new HashMap<>();
                                     for (WbsTreeContractLazyVO node : resultParentNodesTB) {
@@ -1251,9 +1290,8 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                         }
                                     }
 
-                                    //返回最终结果集
                                     for (WbsTreeContractLazyVO lazyNodeVO : lazyNodes) {
-                                        lazyNodeVO.setType(lazyNodeVO.getNodeType()); //前端显示需要一样的,所以修改成一样的
+                                        lazyNodeVO.setType(lazyNodeVO.getNodeType());
                                         lazyNodeVO.setNotExsitChild(!lazyNodeVO.getHasChildren().equals(1));
                                         lazyNodeVO.setPrimaryKeyId(lazyNodeVO.getPKeyId());
                                         lazyNodeVO.setContractIdRelation(sgContractId);
@@ -1262,7 +1300,6 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
                                                 lazyNodeVO.setTitle(sgContractInfo.getContractName());
                                             }
                                         }
-                                        //设置数量
                                         lazyNodeVO.setSubmitCounts(ObjectUtil.isNotEmpty(countMap.get(lazyNodeVO.getPKeyId())) ? countMap.get(lazyNodeVO.getPKeyId()) : (ObjectUtil.isNotEmpty(queryFileMaps.get(lazyNodeVO.getPKeyId())) ? queryFileMaps.get(lazyNodeVO.getPKeyId()) : 0));
                                     }
                                 }
@@ -1298,8 +1335,9 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
     }
 
     @Override
-    public List<AppWbsTreeContractVO> searchNodeAllTableAndFile(String primaryKeyId, String type, String contractId, String projectId) {
-        List<AppWbsTreeContractVO> vos = this.searchNodeAllTable(primaryKeyId, type, contractId, projectId);
+    public List<AppWbsTreeContractVO> searchNodeAllTableAndFile(String primaryKeyId, String type, String
+            contractId, String projectId) {
+        List<AppWbsTreeContractVO> vos = this.searchNodeAllTable(primaryKeyId, type, contractId, projectId, null);
         if (vos != null && vos.size() > 0) {
             List<Long> list = vos.stream().map(AppWbsTreeContractVO::getPKeyId).collect(Collectors.toList());
             List<TableFile> files = tableFileService.getAllFileByIds(list);
@@ -1383,7 +1421,8 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
      * @param initNode       初始化节点入参
      * @param contractId     合同段id
      */
-    private void getConcealedWorkParentNode(Set<WbsTreeContract> resultAllNodes, List<WbsTreeContract> initNode, String contractId) {
+    private void getConcealedWorkParentNode
+    (Set<WbsTreeContract> resultAllNodes, List<WbsTreeContract> initNode, String contractId) {
         Set<Long> parentIds = initNode.stream().map(WbsTreeContract::getParentId).collect(Collectors.toSet());
         if (parentIds.size() > 0) {
             List<WbsTreeContract> parentNodes = baseMapper.selectList(Wrappers.<WbsTreeContract>lambdaQuery().in(WbsTreeContract::getId, parentIds).eq(WbsTreeContract::getContractId, contractId).eq(WbsTreeContract::getType, 1));
@@ -1401,7 +1440,8 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
      * @param initNode       初始化节点入参
      * @param contractId     合同段id
      */
-    private void getConcealedWorkChildNode(Set<WbsTreeContract> resultAllNodes, List<WbsTreeContract> initNode, String contractId) {
+    private void getConcealedWorkChildNode
+    (Set<WbsTreeContract> resultAllNodes, List<WbsTreeContract> initNode, String contractId) {
         Set<Long> childIds = initNode.stream().map(WbsTreeContract::getId).collect(Collectors.toSet());
         if (childIds.size() > 0) {
             List<WbsTreeContract> childNodes = baseMapper.selectList(Wrappers.<WbsTreeContract>lambdaQuery().in(WbsTreeContract::getParentId, childIds).eq(WbsTreeContract::getContractId, contractId).eq(WbsTreeContract::getType, 1));
@@ -1439,43 +1479,31 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
      * @param lowestNodeParentIds 最底层节点ParentIds
      * @param nodesAll            所有节点
      */
-    /*public void recursiveGetParentNodes(List<WbsTreeContractLazyVO> result, List<Long> lowestNodeParentIds, List<WbsTreeContractLazyVO> nodesAll) {
+    public void recursiveGetParentNodes
+    (List<WbsTreeContractLazyVO> result, List<Long> lowestNodeParentIds, List<WbsTreeContractLazyVO> nodesAll) {
         if (lowestNodeParentIds.isEmpty()) {
             return;
         }
 
         //父级Id与出现的次数Map
-        Map<Long, Long> parentIdGroup = lowestNodeParentIds.stream()
-                .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
-
-        List<String> keysWithValueOne = new ArrayList<>();
-        Map<Long, Long> keysWithValueSome = new HashMap<>();
-
-        for (Map.Entry<Long, Long> entry : parentIdGroup.entrySet()) {
-            if (entry.getValue() == 1L) {
-                keysWithValueOne.add(entry.getKey().toString());
-            } else {
-                keysWithValueSome.put(entry.getKey(), entry.getValue());
-            }
-        }
+        Map<Long, Long> parentIdGroup = lowestNodeParentIds.parallelStream()
+                .collect(Collectors.groupingByConcurrent(Function.identity(), Collectors.counting()));
 
         //批量查询单次节点
-        List<WbsTreeContractLazyVO> parentNodes = new ArrayList<>();
-        if (keysWithValueOne.size() > 0) {
-            parentNodes = nodesAll.stream().filter(f -> keysWithValueOne.contains(f.getId().toString())).collect(Collectors.toList());
-        }
+        List<WbsTreeContractLazyVO> parentNodes = parentIdGroup.entrySet().parallelStream()
+                .filter(entry -> entry.getValue() == 1L)
+                .flatMap(entry -> nodesAll.parallelStream()
+                        .filter(f -> entry.getKey().equals(f.getId())))
+                .collect(Collectors.toList());
 
         //批量查询多次节点
-        List<WbsTreeContractLazyVO> multipleParentNodes = new ArrayList<>();
-        for (Map.Entry<Long, Long> entry : keysWithValueSome.entrySet()) {
-            Long key = entry.getKey();
-            Long count = entry.getValue();
-
-            List<WbsTreeContractLazyVO> nodes = nodesAll.stream().filter(f -> key.equals(f.getId())).collect(Collectors.toList());
-            if (!nodes.isEmpty()) {
-                multipleParentNodes.addAll(Collections.nCopies(count.intValue(), nodes.get(0)));
-            }
-        }
+        List<WbsTreeContractLazyVO> multipleParentNodes = parentIdGroup.entrySet().parallelStream()
+                .filter(entry -> entry.getValue() > 1L)
+                .flatMap(entry -> nodesAll.parallelStream()
+                        .filter(f -> entry.getKey().equals(f.getId()))
+                        .limit(1)
+                        .flatMap(node -> Collections.nCopies(entry.getValue().intValue(), node).stream()))
+                .collect(Collectors.toList());
 
         //结果集
         List<Long> collect = Stream.concat(parentNodes.stream(), multipleParentNodes.stream())
@@ -1487,8 +1515,9 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
             result.addAll(multipleParentNodes);
             this.recursiveGetParentNodes(result, collect, nodesAll);
         }
-    }*/
-    public void recursiveGetParentNodes(List<WbsTreeContractLazyVO> result, List<Long> lowestNodeParentIds, List<WbsTreeContractLazyVO> nodesAll) {
+    }
+
+    /*public void recursiveGetParentNodes(List<WbsTreeContractLazyVO> result, List<Long> lowestNodeParentIds, List<WbsTreeContractLazyVO> nodesAll) {
         if (lowestNodeParentIds.isEmpty()) {
             return;
         }
@@ -1538,7 +1567,7 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
             result.addAll(multipleParentNodes);
             this.recursiveGetParentNodes(result, collect, nodesAll);
         }
-    }
+    }*/
 
     @Override
     public boolean syncTabData(String pKeyId) throws Exception {
@@ -2525,13 +2554,15 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
      * @param distinctNodesAll 去重后所有节点数据
      * @return
      */
-    public List<NodeVO> buildNodeTreeByStream(List<WbsTreeContractLazyVO> distinctNodesAll, Map<Long, WbsTreeContractLazyVO> lowestNodesMap) {
+    public List<NodeVO> buildNodeTreeByStream
+    (List<WbsTreeContractLazyVO> distinctNodesAll, Map<Long, WbsTreeContractLazyVO> lowestNodesMap) {
         List<WbsTreeContractLazyVO> list = distinctNodesAll.stream().filter(f -> f.getParentId().equals(0L)).collect(Collectors.toList());
         Map<Long, List<WbsTreeContractLazyVO>> map = distinctNodesAll.stream().collect(Collectors.groupingBy(WbsTreeContractLazyVO::getParentId));
         return recursionFnNodeTree(list, map, lowestNodesMap);
     }
 
-    public List<NodeVO> recursionFnNodeTree(List<WbsTreeContractLazyVO> list, Map<Long, List<WbsTreeContractLazyVO>> map, Map<Long, WbsTreeContractLazyVO> lowestNodesMap) {
+    public List<NodeVO> recursionFnNodeTree
+            (List<WbsTreeContractLazyVO> list, Map<Long, List<WbsTreeContractLazyVO>> map, Map<Long, WbsTreeContractLazyVO> lowestNodesMap) {
         List<NodeVO> result = new ArrayList<>();
         for (WbsTreeContractLazyVO vo : list) {
             if (vo.getHasChildren().equals(0)) {
@@ -2675,5 +2706,30 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
         return list;
     }
 
+    /*删除合同段本地缓存*/
+    public void deleteContractLocalCache(String contractId) {
+        /*删除节点缓存*/
+        localCacheNodes.remove(contractId);
+
+        /*删除资料缓存*/
+        Iterator<Map.Entry<String, List<WbsTreeContractLazyQueryInfoVO>>> iterator_1 = localCacheQueryInfos.entrySet().iterator();
+        while (iterator_1.hasNext()) {
+            Map.Entry<String, List<WbsTreeContractLazyQueryInfoVO>> entry = iterator_1.next();
+            String cacheKey = entry.getKey();
+            if (cacheKey.startsWith(contractId + "_")) {
+                iterator_1.remove();
+            }
+        }
+
+        /*删除节点计算统计缓存*/
+        Iterator<Map.Entry<String, List<WbsTreeContractLazyVO>>> iterator_2 = localCacheParentCountNodes.entrySet().iterator();
+        while (iterator_2.hasNext()) {
+            Map.Entry<String, List<WbsTreeContractLazyVO>> entry = iterator_2.next();
+            String cacheKey = entry.getKey();
+            if (cacheKey.startsWith(contractId + "_")) {
+                iterator_2.remove();
+            }
+        }
+    }
 
 }

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

@@ -421,7 +421,7 @@ public class FileUtils {
         if (SystemUtils.isMacOs()) {
             file_path = "/Users/hongchuangyanfa/Desktop/";
         } else if (SystemUtils.isWindows()) {
-            file_path = "C://upload";
+            file_path = "C://upload//";
         }
         return file_path;
     }

+ 3 - 3
blade-service/blade-manager/src/main/resources/application-dev.yml

@@ -19,6 +19,6 @@ oss:
   bucket-name: bladex-test-info
 
 #Mybatis-plus配置
-mybatis-plus:
-  configuration:
-    cache-enabled: true #开启mybatis的二级缓存
+#mybatis-plus:
+#  configuration:
+#    cache-enabled: true