Browse Source

Merge remote-tracking branch 'origin/master' into master

yangyj 1 year ago
parent
commit
9c45bba5f3
63 changed files with 1828 additions and 460 deletions
  1. 2 2
      blade-common/src/main/java/org/springblade/common/utils/AsyncConfigurer.java
  2. 15 12
      blade-common/src/main/java/org/springblade/common/utils/CommonUtil.java
  3. 2 0
      blade-gateway/src/main/java/org/springblade/gateway/provider/AuthProvider.java
  4. 2 3
      blade-ops/blade-resource/src/main/java/org/springblade/resource/builder/oss/AliOssBuilder.java
  5. 2 2
      blade-ops/blade-resource/src/main/java/org/springblade/resource/builder/oss/OssBuilder.java
  6. 71 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/ArchiveExpertConclusion.java
  7. 75 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/ArchiveExpertScore.java
  8. 27 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/TraceLog.java
  9. 1 1
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/feign/ArchiveAutoClient.java
  10. 18 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/feign/ArchiveExpertConclusionClient.java
  11. 7 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/feign/TaskClient.java
  12. 1 1
      blade-service-api/blade-e-visa-api/src/main/java/org/springblade/evisa/feign/EVisaClientFallBack.java
  13. 2 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/InspectTreeVO.java
  14. 16 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/TwoTreeVO.java
  15. 7 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsTreeContractLazyVO.java
  16. 1 1
      blade-service-api/blade-meter-api/src/main/java/org/springblade/meter/entity/MeterTreeContract.java
  17. 7 0
      blade-service-api/blade-system-api/src/main/java/org/springblade/system/entity/AuthClient.java
  18. 110 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveExpertConclusionController.java
  19. 54 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveExpertScoreController.java
  20. 30 4
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchivesAutoController.java
  21. 3 2
      blade-service/blade-archive/src/main/java/org/springblade/archive/feign/ArchiveAutoClientImpl.java
  22. 22 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/feign/ArchiveExpertConclusionClientImpl.java
  23. 18 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchiveExpertConclusionMapper.java
  24. 6 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchiveExpertConclusionMapper.xml
  25. 21 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchiveExpertScoreMapper.java
  26. 6 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchiveExpertScoreMapper.xml
  27. 4 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.java
  28. 35 6
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.xml
  29. 8 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/TraceLogMapper.java
  30. 7 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/TraceLogMapper.xml
  31. 28 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/IArchiveExpertConclusionService.java
  32. 16 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/IArchiveExpertScoreService.java
  33. 5 1
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/IArchivesAutoService.java
  34. 10 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/ITraceLogService.java
  35. 5 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchiveAutoPdfServiceImpl.java
  36. 153 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchiveExpertConclusionServiceImpl.java
  37. 44 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchiveExpertScoreServiceImpl.java
  38. 83 26
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java
  39. 43 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/TraceLogServiceImpl.java
  40. 33 18
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TaskController.java
  41. 13 0
      blade-service/blade-business/src/main/java/org/springblade/business/feignClient/TaskClientImpl.java
  42. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TaskBatchMapper.xml
  43. 6 5
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TaskServiceImpl.java
  44. 97 97
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/controller/EVisaController.java
  45. 17 14
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/EVisaServiceImpl.java
  46. 27 9
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/utils/PDFUtils.java
  47. 80 0
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/utils/ThreadPoolDemo.java
  48. 3 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ArchiveTreeContractController.java
  49. 2 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/SignPfxFileController.java
  50. 12 8
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/TextdictInfoController.java
  51. 4 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/WbsTreePrivateController.java
  52. 14 4
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeContractMapper.xml
  53. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IArchiveTreeContractService.java
  54. 52 6
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeContractServiceImpl.java
  55. 11 2
      blade-service/blade-meter/src/main/java/org/springblade/meter/controller/MeterTreeController.java
  56. 30 11
      blade-service/blade-meter/src/main/java/org/springblade/meter/controller/TaskController.java
  57. 2 0
      blade-service/blade-meter/src/main/java/org/springblade/meter/mapper/InventoryFormMeterMapper.java
  58. 18 2
      blade-service/blade-meter/src/main/java/org/springblade/meter/mapper/InventoryFormMeterMapper.xml
  59. 4 0
      blade-service/blade-meter/src/main/java/org/springblade/meter/service/MeterTreeContractService.java
  60. 220 5
      blade-service/blade-meter/src/main/java/org/springblade/meter/service/impl/MeterTreeContractServiceImpl.java
  61. 19 1
      blade-service/blade-user/src/main/java/org/springblade/system/user/controller/UserController.java
  62. 92 76
      blade-service/blade-user/src/main/java/org/springblade/system/user/mapper/UserMapper.xml
  63. 103 133
      blade-service/blade-user/src/main/java/org/springblade/system/user/service/impl/UserServiceImpl.java

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

@@ -15,7 +15,7 @@ public class AsyncConfigurer {
     /**
      * cpu 核心数量
      */
-    public static final int cpuNum =10 ;//Runtime.getRuntime().availableProcessors();
+    public static final int cpuNum =6 ;//Runtime.getRuntime().availableProcessors();
 
     /**
      * 线程池配置
@@ -25,7 +25,7 @@ public class AsyncConfigurer {
     @Bean("taskExecutor1")
     public ThreadPoolExecutor getAsyncExecutor() {
         return new ThreadPoolMonitor(cpuNum
-                , 20
+                , 12
                 , 30
                 , TimeUnit.SECONDS
                 , new LinkedBlockingQueue<>(2000)

+ 15 - 12
blade-common/src/main/java/org/springblade/common/utils/CommonUtil.java

@@ -4,6 +4,7 @@ import cn.hutool.core.io.FileUtil;
 import cn.hutool.http.HttpUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import com.aliyun.oss.common.utils.IOUtils;
 import com.drew.imaging.ImageMetadataReader;
 import com.drew.imaging.ImageProcessingException;
 import com.drew.metadata.Metadata;
@@ -110,17 +111,14 @@ public class CommonUtil {
     /**
      * 根据OSS文件路径获取文件输入流
      */
-    public static InputStream getOSSInputStream(String urlStr) throws Exception {
+    public static synchronized InputStream getOSSInputStream(String urlStr) throws Exception {
         //获取OSS文件流
-        URL imageUrl = new URL(urlStr);
-        HttpURLConnection conn = null;
+        URL url =new URL(urlStr);
+        final URLConnection conn = url.openConnection();
+        conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
         try {
-            conn = (HttpURLConnection) imageUrl.openConnection();
-            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
-            InputStream inputStream = conn.getInputStream();
-
-            return inputStream;
-        } catch (Exception e) {
+            return conn.getInputStream();
+        } catch (Exception e){
             return null;
         }
     }
@@ -149,12 +147,17 @@ public class CommonUtil {
     /**
      * 获取字节数组
      */
-    public static byte[] InputStreamToBytes(InputStream is) throws IOException {
+    public static synchronized byte[] InputStreamToBytes(InputStream is){
         BufferedInputStream bis = new BufferedInputStream(is);
         ByteArrayOutputStream os = new ByteArrayOutputStream();
         int date = -1;
-        while ((date = bis.read()) != -1) {
-            os.write(date);
+        while (true) {
+            try {
+                if (!((date = bis.read()) != -1)) break;
+                os.write(date);
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
         }
         return os.toByteArray();
     }

+ 2 - 0
blade-gateway/src/main/java/org/springblade/gateway/provider/AuthProvider.java

@@ -36,6 +36,8 @@ public class AuthProvider {
         DEFAULT_SKIP_URL.add("/example");
         DEFAULT_SKIP_URL.add("/oauth/token/**");
         DEFAULT_SKIP_URL.add("/loginByToken");
+        DEFAULT_SKIP_URL.add("/loginByToken2");
+        DEFAULT_SKIP_URL.add("/submit2");
         DEFAULT_SKIP_URL.add("/exceltab/callbackSave");
         DEFAULT_SKIP_URL.add("/oauth/captcha/**");
         DEFAULT_SKIP_URL.add("/oauth/clear-cache/**");

+ 2 - 3
blade-ops/blade-resource/src/main/java/org/springblade/resource/builder/oss/AliOssBuilder.java

@@ -52,11 +52,10 @@ public class AliOssBuilder {
         // 设置失败请求重试次数,默认为3次。
         conf.setMaxErrorRetry(5);
         OssProperties ossProperties = new OssProperties();
-
-        //ossProperties.setEndpoint(oss.getEndpoint());
+        ossProperties.setEndpoint(oss.getEndpoint());
 
         //本地测试1
-        ossProperties.setEndpoint("https://oss-cn-hangzhou.aliyuncs.com/");
+      //  ossProperties.setEndpoint("https://oss-cn-hangzhou.aliyuncs.com/");
 
         ossProperties.setAccessKey(oss.getAccessKey());
         ossProperties.setSecretKey(oss.getSecretKey());

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

@@ -145,8 +145,8 @@ public class OssBuilder {
                 Oss defaultOss = new Oss();
                 defaultOss.setId(0L);
                 defaultOss.setCategory(OssEnum.of(ossProperties.getName()).getCategory());
-              //  defaultOss.setEndpoint(ossProperties.getEndpoint());
-                defaultOss.setEndpoint("https://oss-cn-hangzhou.aliyuncs.com");
+                defaultOss.setEndpoint(ossProperties.getEndpoint());
+               // defaultOss.setEndpoint("https://oss-cn-hangzhou.aliyuncs.com");
                 defaultOss.setBucketName(ossProperties.getBucketName());
                 defaultOss.setAccessKey(ossProperties.getAccessKey());
                 defaultOss.setSecretKey(ossProperties.getSecretKey());

+ 71 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/ArchiveExpertConclusion.java

@@ -0,0 +1,71 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+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;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+
+/**
+ * 档案专家结论实体类
+ *
+ * @author BladeX
+ * @since 2023-02-17
+ */
+@Data
+@TableName("u_archive_expert_conclusion")
+@EqualsAndHashCode(callSuper = true)
+public class ArchiveExpertConclusion extends BaseEntity {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty("项目id")
+    private Long projectId;
+
+    @ApiModelProperty("申请验收的pdf地址")
+    private String appUrl;
+
+    @ApiModelProperty("结论报表的pdf地址")
+    private String tableUrl;
+
+    @ApiModelProperty("是否生成打分表:0否1是")
+    private Integer isBuildScore;
+
+    @ApiModelProperty("前言")
+    private String foreword;
+
+    @ApiModelProperty("项目概况")
+    private String generalSituation;
+
+    @ApiModelProperty("管理情况")
+    private String adminCondition;
+
+    @ApiModelProperty("存在问题及建议")
+    private String questionSuggest;
+
+    @ApiModelProperty("审批状态,0未上报,1待审批,2已审批,3已废除")
+    private Integer approveStatus;
+
+    @ApiModelProperty("审批状态,0未上报,1待审批,2已审批,3已废除")
+    private LocalDate approveDate;
+
+}

+ 75 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/ArchiveExpertScore.java

@@ -0,0 +1,75 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.archive.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.core.mp.base.BaseEntity;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * 档案专家评分实体类
+ *
+ * @author BladeX
+ * @since 2023-02-17
+ */
+@Data
+@TableName("u_archive_expert_score")
+@EqualsAndHashCode(callSuper = true)
+public class ArchiveExpertScore extends BaseEntity {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty("项目id")
+    private Long projectId;
+
+    @ApiModelProperty("单位类型:1业主2监理3施工")
+    private Integer unitType;
+
+    @ApiModelProperty("评分项")
+    private String scoreItem;
+
+    @ApiModelProperty("完整性")
+    private Integer integrality;
+
+    @ApiModelProperty("完整性扣分")
+    private Integer integralityDeduction;
+
+    @ApiModelProperty("规范性")
+    private Integer normative;
+
+    @ApiModelProperty("规范性扣分")
+    private Integer normativeDeduction;
+
+    public ArchiveExpertScore() {
+    }
+
+    public ArchiveExpertScore(Long projectId, Integer unitType, String scoreItem, Integer integrality, Integer integralityDeduction, Integer normative, Integer normativeDeduction) {
+        this.projectId = projectId;
+        this.unitType = unitType;
+        this.scoreItem = scoreItem;
+        this.integrality = integrality;
+        this.integralityDeduction = integralityDeduction;
+        this.normative = normative;
+        this.normativeDeduction = normativeDeduction;
+    }
+}

+ 27 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/TraceLog.java

@@ -0,0 +1,27 @@
+package org.springblade.archive.entity;
+
+
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.core.mp.base.BaseEntity;
+
+@Data
+@TableName("u_trace_log")
+@EqualsAndHashCode(callSuper = true)
+public class TraceLog extends BaseEntity {
+
+    //项目ID
+    private Long projectId;
+
+    //模块名
+    private String module;
+
+    //轨迹ID
+    private Long traceId;
+
+    //日志内容
+    private String content;
+
+}

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

@@ -36,7 +36,7 @@ public interface ArchiveAutoClient {
      * 批量修改档案申请验收状态
      */
     @PostMapping(API_PREFIX + "/batchUpdateIsApply")
-    R<Boolean> batchUpdateIsApply(@RequestParam Integer isApply,@RequestParam List<Long> ids);
+    R<Boolean> batchUpdateIsApply(@RequestBody List<Long> ids);
 
     /**
      * 批量修改档案专家,参数为节点集合

+ 18 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/feign/ArchiveExpertConclusionClient.java

@@ -0,0 +1,18 @@
+package org.springblade.archive.feign;
+
+import org.springblade.common.constant.ArchiveConstant;
+import org.springblade.core.tool.api.R;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.util.Map;
+
+@FeignClient(value = ArchiveConstant.APPLICATION_WEATHER_NAME)
+public interface ArchiveExpertConclusionClient {
+    String API_PREFIX = "/api/archive/archiveExpertConclusion";
+
+    @GetMapping(API_PREFIX + "/saveBaseTableInfo")
+    R saveBaseTableInfo(@RequestParam Long projectId, @RequestParam String appUrl);
+}

+ 7 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/feign/TaskClient.java

@@ -37,6 +37,13 @@ public interface TaskClient {
     String QUERY_USER_TASK = API_PREFIX + "/query-user-task";
     String DELETE_USER_TASK = API_PREFIX + "/delete-user-task";
     String BATCH_RE_SIGN = API_PREFIX + "/re-sign";
+    String ARCHIVE_APP_COUNT = API_PREFIX + "/archive-app-count";
+
+    /**
+     * 获取档案验收申请数量
+     */
+    @GetMapping(ARCHIVE_APP_COUNT)
+    Boolean getArchiveAppCount(@RequestParam Long projectId);
     /**
      * 保存任务
      */

+ 1 - 1
blade-service-api/blade-e-visa-api/src/main/java/org/springblade/evisa/feign/EVisaClientFallBack.java

@@ -1,12 +1,12 @@
 package org.springblade.evisa.feign;
 
+import feign.hystrix.FallbackFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springblade.evisa.vo.CertBeanVO;
 import org.springblade.evisa.vo.EVisaMakeSealVO;
 import org.springblade.evisa.vo.EVisaTaskApprovalVO;
 import org.springblade.evisa.vo.TaskArchiveDTO;
-import org.springframework.cloud.openfeign.FallbackFactory;
 import org.springframework.stereotype.Component;
 
 @Component

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

@@ -63,5 +63,7 @@ public class InspectTreeVO implements INode<InspectTreeVO> {
     @ApiModelProperty(value = "false没有子节点,true有子节点")
     private Boolean isChildren;
 
+    @ApiModelProperty(value = "false没有子节点,true有子节点")
+    private Integer total;
 
 }

+ 16 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/TwoTreeVO.java

@@ -0,0 +1,16 @@
+package org.springblade.manager.vo;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @Param   档案抽检分配,返回两棵树
+ * @Author wangwl
+ * @Date 2024/1/5 17:27
+ **/
+@Data
+public class TwoTreeVO {
+    List<InspectTreeVO> list;
+    List<Long> ids;
+}

+ 7 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsTreeContractLazyVO.java

@@ -5,6 +5,7 @@ import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import java.io.Serializable;
+import java.util.Date;
 import java.util.List;
 
 /**
@@ -80,4 +81,10 @@ public class WbsTreeContractLazyVO implements Serializable {
     @ApiModelProperty(value = "子级集合(在构造树形结构时使用)")
     private List<WbsTreeContractLazyVO> children;
 
+    private Integer sort;
+
+    private String fullName;
+
+    private Date createTime;
+
 }

+ 1 - 1
blade-service-api/blade-meter-api/src/main/java/org/springblade/meter/entity/MeterTreeContract.java

@@ -35,7 +35,7 @@ public class MeterTreeContract extends BaseEntity {
     @ApiModelProperty(value = "工程类型名称")
     private String engineeringTypeName;
 
-    @ApiModelProperty(value = "数据源类型 1=项目原始引用、2=合同段手动新增、3=项目新增引用(项目是新增的)")
+    @ApiModelProperty(value = "数据源类型 1=项目原始引用、2=合同段手动新增、3=项目新增引用(项目是新增的)、4=导入")
     private Integer dataSourceType;
 
     @ApiModelProperty(value = "源节点id(项目树节点id)")

+ 7 - 0
blade-service-api/blade-system-api/src/main/java/org/springblade/system/entity/AuthClient.java

@@ -47,6 +47,13 @@ public class AuthClient extends BaseEntity {
      */
     @ApiModelProperty(value = "客户端密钥")
     private String clientSecret;
+
+    /**
+     * 名称
+     */
+    @ApiModelProperty(value = "名称")
+    private String name;
+
     /**
      * 资源集合
      */

+ 110 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveExpertConclusionController.java

@@ -0,0 +1,110 @@
+package org.springblade.archive.controller;
+
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springblade.archive.entity.ArchiveConclusion;
+import org.springblade.archive.entity.ArchiveExpertConclusion;
+import org.springblade.archive.service.IArchiveExpertConclusionService;
+import org.springblade.core.boot.ctrl.BladeController;
+import org.springblade.core.tool.api.R;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ *
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/archiveExpertConclusion")
+@Api(value = "专家结论", tags = "专家结论")
+public class ArchiveExpertConclusionController extends BladeController {
+
+    private final IArchiveExpertConclusionService conclusionService;
+
+    /**
+     * 验收申请-历史验收报告
+     */
+    @GetMapping("/getHistoryTable")
+    @ApiOperationSupport(order = 1)
+    @ApiOperation(value = "验收申请-历史验收报告", notes = "传入当前项目id,返回报告数组")
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "projectId", value = "项目id", required = true)
+    })
+    public R<List<ArchiveExpertConclusion>> getHistoryTable(@RequestParam Long projectId) {
+        return R.data(conclusionService.getHistoryTable(projectId));
+    }
+
+    /**
+     * 验收申请-申请验收状态
+     */
+    @GetMapping("/getAppStatus")
+    @ApiOperationSupport(order = 3)
+    @ApiOperation(value = "验收申请-申请验收状态", notes = "传入当前项目id,true显示false屏蔽")
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "projectId", value = "项目id", required = true)
+    })
+    public R<Boolean> getAppStatus(@RequestParam Long projectId) {
+        return R.data(conclusionService.getAppStatus(projectId));
+    }
+
+    /**
+     * 在线验收-预览
+     */
+    @GetMapping("/getAppPreview")
+    @ApiOperationSupport(order = 4)
+    @ApiOperation(value = "在线验收-预览", notes = "传入当前项目id,返回当前期的档案验收URL地址")
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "projectId", value = "项目id", required = true)
+    })
+    public R getAppPreview(@RequestParam Long projectId) {
+        return R.data(conclusionService.getAppPreview(projectId));
+    }
+    /**
+     * 在线验收-查看验收报告
+     */
+    @GetMapping("/getTable")
+    @ApiOperationSupport(order = 5)
+    @ApiOperation(value = "在线验收-查看验收报告", notes = "传入当前项目id,返回当期验收报告URL地址")
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "projectId", value = "项目id", required = true)
+    })
+    public R getTable(@RequestParam Long projectId) {
+        return R.data(conclusionService.getTable(projectId));
+    }
+
+    /**
+     * 编写结论-是否生成打分表
+     */
+    @GetMapping("/creatScore")
+    @ApiOperationSupport(order = 1)
+    @ApiOperation(value = "验收申请-是否生成打分表", notes = "传入当前项目id,返回1选择0不选择")
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "projectId", value = "项目id", required = true)
+    })
+    public R creatScore(@RequestParam Long projectId) {
+        return R.data(conclusionService.creatScore(projectId));
+    }
+
+    /**
+     * 编写结论-修改是否生成打分表
+     */
+    @GetMapping("/updateScore")
+    @ApiOperationSupport(order = 1)
+    @ApiOperation(value = "验收申请-修改是否生成打分表", notes = "传入当前项目id,传入1选择0不选择")
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "projectId", value = "项目id", required = true),
+            @ApiImplicitParam(name = "isSelect", value = "1选择0不选择", required = true)
+    })
+    public R creatScore(@RequestParam Long projectId,Integer isSelect) {
+        conclusionService.updateScore(projectId,isSelect);
+        return R.data("修改成功");
+    }
+}

+ 54 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveExpertScoreController.java

@@ -0,0 +1,54 @@
+package org.springblade.archive.controller;
+
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springblade.archive.entity.ArchiveExpertConclusion;
+import org.springblade.archive.entity.ArchiveExpertScore;
+import org.springblade.archive.service.IArchiveExpertScoreService;
+import org.springblade.core.boot.ctrl.BladeController;
+import org.springblade.core.tool.api.R;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ *
+ */
+@RestController
+@AllArgsConstructor
+@RequestMapping("/archiveExpertScore")
+@Api(value = "专家评分", tags = "专家评分")
+public class ArchiveExpertScoreController extends BladeController {
+
+    private final IArchiveExpertScoreService scoreService;
+
+    /**
+     * 专家评分-根据单位获取打分项
+     */
+    @GetMapping("/getItemByUnit")
+    @ApiOperationSupport(order = 1)
+    @ApiOperation(value = "专家评分-根据单位获取打分项", notes = "专家评分-根据单位获取打分项")
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "projectId", value = "项目id", required = true),
+            @ApiImplicitParam(name = "unitType", value = "单位类型:1业主2监理3施工", required = true)
+    })
+    public R<List<ArchiveExpertScore>> getItemByUnit(@RequestParam Long projectId,Integer unitType) {
+        return R.data(scoreService.getItemByUnit(projectId,unitType));
+    }
+
+    /**
+     * 专家评分-编辑
+     */
+    @PostMapping("/update")
+    @ApiOperationSupport(order = 1)
+    @ApiOperation(value = "专家评分-编辑", notes = "专家评分-编辑,传入当前行")
+    public R update(@RequestBody ArchiveExpertScore score) {
+        scoreService.updateById(score);
+        return R.data("修改成功");
+    }
+
+}

+ 30 - 4
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchivesAutoController.java

@@ -37,6 +37,7 @@ 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.service.ITraceLogService;
 import org.springblade.archive.utils.CallBgrsjk;
 import org.springblade.archive.utils.FileUtils;
 import org.springblade.archive.vo.*;
@@ -44,6 +45,7 @@ import org.springblade.business.entity.ArchiveFile;
 import org.springblade.business.entity.InformationQuery;
 import org.springblade.common.constant.CommonConstant;
 import org.springblade.common.utils.CommonUtil;
+import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
 import org.springblade.core.secure.BladeUser;
@@ -99,6 +101,8 @@ public class ArchivesAutoController extends BladeController {
 
 	@Autowired
 	private ExecutorService executorService;
+	@Autowired
+	private ITraceLogService iTraceLogService;
 	/**
 	 * 详情
 	 */
@@ -441,10 +445,14 @@ public class ArchivesAutoController extends BladeController {
 				return R.fail("当前合同段已经在自动组卷中,请耐心等待");
 			}
 			log.info("开始自动组卷....");
+
+			Long traceId = SnowFlakeUtil.getId();
+			iTraceLogService.save(traceId,"开始自动组卷");
+
 			//设置自动组卷中
 			contractClient.updateIsArchivesAutoById(contractId,1);
 
-			archivesAutoService.archiveAutoMethodThread(projectId,contractId,nodeId);
+			archivesAutoService.archiveAutoMethodThread(projectId,contractId,nodeId,traceId);
 			return R.data("开始自动组卷中,请耐心等待");
 		}catch (Exception e){
 			e.printStackTrace();
@@ -713,8 +721,8 @@ public class ArchivesAutoController extends BladeController {
 	@ApiImplicitParams(value = {
 			@ApiImplicitParam(name = "projectId", value = "项目id", required = true)
 	})
-	public R<Boolean> getApplyStatus(@RequestParam Long projectId) {
-		return R.data(archivesAutoService.getApplyStatus(projectId));
+	public R<Map<String,Boolean>> getApplyStatus(@RequestParam Long projectId) {
+		return R.data(archivesAutoService.getApplyStatus2(projectId));
 	}
 
 	/**
@@ -846,7 +854,7 @@ public class ArchivesAutoController extends BladeController {
 	})
 	public R saveInspect(@RequestBody ExpertInspection inspection) {
 		archivesAutoService.saveInspect(inspection);
-		return R.data("保存成功");
+		return R.data("操作成功");
 	}
 
 	/**
@@ -865,6 +873,22 @@ public class ArchivesAutoController extends BladeController {
 		return R.data(page);
 	}
 
+	/**
+	 * 在线验收-专家抽检记录汇总
+	 */
+	@GetMapping("/getUserInspectInfo2")
+	@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>> getUserInspectInfo2(Query query,@RequestParam Long projectId) {
+		IPage<ExpertInspectionVO> page = archivesAutoService.getUserInspectInfo2(query, projectId);
+		return R.data(page);
+	}
+
 
 
 	/**
@@ -910,4 +934,6 @@ public class ArchivesAutoController extends BladeController {
 
 
 
+
+
 }

+ 3 - 2
blade-service/blade-archive/src/main/java/org/springblade/archive/feign/ArchiveAutoClientImpl.java

@@ -9,6 +9,7 @@ import org.springblade.archive.service.IArchiveProjectConfigService;
 import org.springblade.archive.service.IArchivesAutoService;
 import org.springblade.archive.vo.ArchivesAutoVO;
 import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.Func;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
@@ -44,8 +45,8 @@ public class ArchiveAutoClientImpl implements ArchiveAutoClient {
     }
 
     @Override
-    public R<Boolean> batchUpdateIsApply(Integer isApply, List<Long> ids) {
-        return archivesAutoService.batchUpdateIsApply(isApply,ids);
+    public R<Boolean> batchUpdateIsApply(List<Long> ids) {
+        return archivesAutoService.batchUpdateIsApply(1,ids);
     }
 
     @Override

+ 22 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/feign/ArchiveExpertConclusionClientImpl.java

@@ -0,0 +1,22 @@
+package org.springblade.archive.feign;
+
+import lombok.AllArgsConstructor;
+import org.springblade.archive.service.IArchiveExpertConclusionService;
+import org.springblade.archive.service.IArchiveInspectionService;
+import org.springblade.core.tool.api.R;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Map;
+
+@RestController
+@AllArgsConstructor
+public class ArchiveExpertConclusionClientImpl implements ArchiveExpertConclusionClient {
+
+    private final IArchiveExpertConclusionService conclusionService;
+
+
+    @Override
+    public R saveBaseTableInfo(Long projectId, String appUrl) {
+        return conclusionService.saveBaseTableInfo(projectId,appUrl);
+    }
+}

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

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

+ 6 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchiveExpertConclusionMapper.xml

@@ -0,0 +1,6 @@
+<?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.ArchiveExpertConclusionMapper">
+
+
+</mapper>

+ 21 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchiveExpertScoreMapper.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.ArchiveExpertScore;
+import org.springblade.archive.entity.ExpertInspection;
+
+import java.util.List;
+
+/**
+ * <p>
+ * Mapper 接口
+ * </p>
+ *
+ * @since 2023-04-09
+ */
+public interface ArchiveExpertScoreMapper extends BaseMapper<ArchiveExpertScore> {
+
+
+}

+ 6 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchiveExpertScoreMapper.xml

@@ -0,0 +1,6 @@
+<?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.ArchiveExpertScoreMapper">
+
+
+</mapper>

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

@@ -173,8 +173,12 @@ public interface ArchivesAutoMapper extends BaseMapper<ArchivesAuto> {
 	//用于档案巡检查询单位下档案
 	List<ArchivesAutoVO2> getUnitAllArchive2(@Param("firstNode") Long firstNode,@Param("grade") Integer grade,@Param("isApply") Integer isApply);
 
+	//查询所有的,树不加id,档案状态加
 	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);
 
+	//查询专家的,树加id,档案状态加
+	IPage<ArchiveInspectVO> getNodeArchives2(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);

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

@@ -1003,11 +1003,35 @@
     </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
+               if((select count(1) from u_archive_expert_inspection aei where aei.is_deleted =0 and aei.archive_id = uaa.id
+                   and aei.expert_id = #{userId}) > 0,'已抽检','未抽检') as inspectStatusName,
+               (CASE when (select count(1) from u_archive_expert_inspection aei where aei.is_deleted =0 and aei.archive_id = uaa.id
+                    and aei.expert_id = #{userId} and is_pass = 1) = 1 then '合格'
+                   when (select count(1) from u_archive_expert_inspection aei where aei.is_deleted =0 and aei.archive_id = uaa.id
+                    and aei.expert_id = #{userId} and is_pass = 0) > 0 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="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="getNodeArchives2" resultType="org.springblade.archive.vo.ArchiveInspectVO">
+        select uaa.id ,uaa.file_number,uaa.name ,uaa.unit,
+        if((select count(1) from u_archive_expert_inspection aei where aei.is_deleted =0 and aei.archive_id = uaa.id
+            and aei.expert_id = #{userId}) > 0,'已抽检','未抽检') as inspectStatusName,
+        (CASE when (select count(1) from u_archive_expert_inspection aei where aei.is_deleted =0 and aei.archive_id = uaa.id
+            and aei.expert_id = #{userId} and is_pass = 1) = 1 then '合格'
+            when (select count(1) from u_archive_expert_inspection aei where aei.is_deleted =0 and aei.archive_id = uaa.id
+            and aei.expert_id = #{userId} and is_pass = 0) > 0 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>
@@ -1032,15 +1056,20 @@
         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 COUNT(1)
+        from (SELECT DISTINCT (archive_id)
+              from u_archive_expert_inspection
+              WHERE project_id = #{projectId}
+                and is_deleted = 0
+                and expert_id = #{userId}
+             ) a
     </select>
     <select id="getUserInspectInfo" resultType="org.springblade.archive.vo.ExpertInspectionVO">
-        select aei.id,aei.archive_name ,aei.opinion , aei.archive_id,expert_name,file_id,
+        select aei.id,aei.archive_name ,aei.opinion , aei.archive_id,expert_name,file_id,aei.is_pass,
                (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
+        WHERE project_id = #{projectId} and is_deleted = 0 and is_pass = 0
         <if test="userId != null">
             and expert_id = #{userId}
         </if>

+ 8 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/TraceLogMapper.java

@@ -0,0 +1,8 @@
+package org.springblade.archive.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.springblade.archive.entity.TraceLog;
+
+public interface TraceLogMapper extends BaseMapper<TraceLog> {
+    // Define methods for querying the database that are specific to the TraceLog entity
+}

+ 7 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/TraceLogMapper.xml

@@ -0,0 +1,7 @@
+<?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.TraceLogMapper">
+
+    <!-- Additional MyBatis SQL mapping definitions for TraceLog can be specified here -->
+
+</mapper>

+ 28 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/service/IArchiveExpertConclusionService.java

@@ -0,0 +1,28 @@
+package org.springblade.archive.service;
+
+import org.springblade.archive.entity.ArchiveExpertConclusion;
+import org.springblade.archive.entity.ArchiveExpertScore;
+import org.springblade.core.mp.base.BaseService;
+import org.springblade.core.tool.api.R;
+
+import java.util.List;
+
+
+public interface IArchiveExpertConclusionService extends BaseService<ArchiveExpertConclusion> {
+
+
+    //验收申请审批通过,创建当前报表基本信息
+    R saveBaseTableInfo(Long projectId,String appUrl);
+
+    Boolean getAppStatus(Long projectId);
+
+    List<ArchiveExpertConclusion> getHistoryTable(Long projectId);
+
+    String getAppPreview(Long projectId);
+
+    String getTable(Long projectId);
+
+    Integer creatScore(Long projectId);
+
+    void updateScore(Long projectId, Integer isSelect);
+}

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

@@ -0,0 +1,16 @@
+package org.springblade.archive.service;
+
+import org.springblade.archive.entity.ArchiveExpertScore;
+import org.springblade.archive.entity.ExpertInspection;
+import org.springblade.core.mp.base.BaseService;
+
+import java.util.List;
+
+
+public interface IArchiveExpertScoreService extends BaseService<ArchiveExpertScore> {
+
+    // 审批成功,保存基础评分信息
+    void saveBaseScoreInfo(Long projectId);
+
+    List<ArchiveExpertScore> getItemByUnit(Long projectId, Integer unitType);
+}

+ 5 - 1
blade-service/blade-archive/src/main/java/org/springblade/archive/service/IArchivesAutoService.java

@@ -90,7 +90,7 @@ public interface IArchivesAutoService extends BaseService<ArchivesAuto> {
 
     List<DictBiz> getCarrierTypeByDict();
 
-	void archiveAutoMethodThread(Long projectId, Long contractId, Long nodeId);
+	void archiveAutoMethodThread(Long projectId, Long contractId, Long nodeId, Long traceId);
 
 	void refreshFileNumberThread(Long projectId, Long contractId, Long nodeId);
 
@@ -122,6 +122,8 @@ public interface IArchivesAutoService extends BaseService<ArchivesAuto> {
 
 	Boolean getApplyStatus(Long projectId);
 
+	Map<String,Boolean> getApplyStatus2(Long projectId);
+
 	void annulApply(Long projectId);
 
 	IPage<ArchiveInspectVO> getNodeArchives(Query query,Long nodeId, Long projectId,Integer searchType,String searchValue,Integer type);
@@ -134,6 +136,8 @@ public interface IArchivesAutoService extends BaseService<ArchivesAuto> {
 
 	IPage<ExpertInspectionVO> getUserInspectInfo(Query query, Long projectId);
 
+	IPage<ExpertInspectionVO> getUserInspectInfo2(Query query, Long projectId);
+
     ProjectInspectStatVO projectInspectStat(Long projectId);
 
 	ExpertInspectionVO getArchiveFileOpinion(Long fileId, Long projectId);

+ 10 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/service/ITraceLogService.java

@@ -0,0 +1,10 @@
+package org.springblade.archive.service;
+
+import org.springblade.core.mp.base.BaseService;
+import org.springblade.archive.entity.TraceLog;
+
+public interface ITraceLogService extends BaseService<TraceLog> {
+    // Define methods specific to the TraceLog entity here
+
+    void save(Long traceId, String format, Object... args);
+}

+ 5 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchiveAutoPdfServiceImpl.java

@@ -68,6 +68,11 @@ public class ArchiveAutoPdfServiceImpl implements IArchiveAutoPdfService {
         URL_MAP.put("r_Archives_spare", "https://bladex-chongqing-info.oss-cn-hangzhou.aliyuncs.com//upload/20230414/3798f8c3db6f94c8fce63eec8c716d6c.xlsx");
         URL_MAP.put("r_Archives_back", "https://bladex-chongqing-info.oss-cn-hangzhou.aliyuncs.com//upload/20230413/31081917b41e12b9b0359f6a9c1755bd.xlsx");
 
+//        URL_MAP.put("r_Archives_front", "https://bladex-oss-chongqing.oss-cn-shenzhen.aliyuncs.com//upload/20230413/306c87ffc640699aa92d53a5f4e6d632.xlsx");
+//        URL_MAP.put("r_Archives_catalog", "https://bladex-oss-chongqing.oss-cn-shenzhen.aliyuncs.com//upload/20230413/f2a083fca685c646e4a47daaaa46f04b.xlsx");
+//        URL_MAP.put("r_Archives_spare", "https://bladex-oss-chongqing.oss-cn-shenzhen.aliyuncs.com//upload/20230414/3798f8c3db6f94c8fce63eec8c716d6c.xlsx");
+//        URL_MAP.put("r_Archives_back", "https://bladex-oss-chongqing.oss-cn-shenzhen.aliyuncs.com//upload/20230413/31081917b41e12b9b0359f6a9c1755bd.xlsx");
+
         NAME_MAP.put("r_Archives_front", "封面");
         NAME_MAP.put("r_Archives_catalog", "卷内目录");
         NAME_MAP.put("r_Archives_spare", "备考表");

+ 153 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchiveExpertConclusionServiceImpl.java

@@ -0,0 +1,153 @@
+package org.springblade.archive.service.impl;
+
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import lombok.AllArgsConstructor;
+import org.apache.commons.lang.StringUtils;
+import org.springblade.archive.entity.ArchiveExpertConclusion;
+import org.springblade.archive.entity.ArchiveExpertScore;
+import org.springblade.archive.mapper.ArchiveExpertConclusionMapper;
+import org.springblade.archive.mapper.ArchiveExpertScoreMapper;
+import org.springblade.archive.service.IArchiveExpertConclusionService;
+import org.springblade.archive.service.IArchiveExpertScoreService;
+import org.springblade.core.log.exception.ServiceException;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.core.tool.api.R;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+@Service
+@AllArgsConstructor
+public class ArchiveExpertConclusionServiceImpl extends BaseServiceImpl<ArchiveExpertConclusionMapper, ArchiveExpertConclusion> implements IArchiveExpertConclusionService {
+
+    private final IArchiveExpertScoreService scoreService;
+
+    @Override
+    @Transactional
+    public R saveBaseTableInfo(Long projectId, String appUrl) {
+        //保存表单基础信息
+        ArchiveExpertConclusion conclusion = new ArchiveExpertConclusion();
+        conclusion.setProjectId(projectId);
+        conclusion.setAppUrl(appUrl);
+        conclusion.setIsBuildScore(0);
+        conclusion.setStatus(1);
+        conclusion.setApproveStatus(0);
+        this.save(conclusion);
+        //保存评分基础信息
+        scoreService.saveBaseScoreInfo(projectId);
+        return R.data("保存成功");
+    }
+
+    /**
+     * 获取申请状态
+     * @param projectId
+     * @return
+     */
+    @Override
+    public Boolean getAppStatus(Long projectId) {
+        //获取最新的最新的一期验收
+        ArchiveExpertConclusion one = this.getOne(new LambdaUpdateWrapper<ArchiveExpertConclusion>()
+                .eq(ArchiveExpertConclusion::getProjectId, projectId)
+                .orderByDesc(ArchiveExpertConclusion::getCreateTime)
+                .last("limit 1"));
+        //如果为空代表没有申请过,返回true
+        if (one == null || one.getStatus() == 2){
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * 验收申请-历史验收报告
+     * @param projectId
+     * @return
+     */
+    @Override
+    public List<ArchiveExpertConclusion> getHistoryTable(Long projectId) {
+        List<ArchiveExpertConclusion> list = this.list(new LambdaQueryWrapper<ArchiveExpertConclusion>()
+                .eq(ArchiveExpertConclusion::getProjectId, projectId)
+                .eq(ArchiveExpertConclusion::getStatus, 2)
+                .orderByDesc(ArchiveExpertConclusion::getApproveDate));
+        if (list.size() == 0){
+            throw new ServiceException("暂无历史验收报告");
+        }
+        return list;
+    }
+
+
+    /**
+     * 在线验收-预览
+     */
+    @Override
+    public String getAppPreview(Long projectId) {
+        //获取最新的最新的一期验收
+        ArchiveExpertConclusion one = this.getOne(new LambdaUpdateWrapper<ArchiveExpertConclusion>()
+                .eq(ArchiveExpertConclusion::getProjectId, projectId)
+                .orderByDesc(ArchiveExpertConclusion::getCreateTime)
+                .last("limit 1"));
+        //如果为空代表没有申请过,返回true
+        if (one == null){
+            throw new ServiceException("暂无验收档案信息,请检查是否申请过验收");
+        }
+        return one.getAppUrl();
+    }
+
+    /**
+     * 在线验收-查看验收报告
+     */
+    @Override
+    public String getTable(Long projectId) {
+        //获取最新的最新的一期验收
+        ArchiveExpertConclusion one = this.getOne(new LambdaUpdateWrapper<ArchiveExpertConclusion>()
+                .eq(ArchiveExpertConclusion::getProjectId, projectId)
+                .orderByDesc(ArchiveExpertConclusion::getCreateTime)
+                .last("limit 1"));
+        //如果为空代表没有申请过,返回true
+        if (one == null){
+            throw new ServiceException("暂无验收档案信息,请检查是否申请过验收");
+        }
+        if (StringUtils.isBlank(one.getTableUrl())){
+            throw new ServiceException("当前在线验收还未生成报告");
+        }
+        return one.getTableUrl();
+    }
+
+    /**
+     * 编写结论-是否生成打分表
+     */
+    @Override
+    public Integer creatScore(Long projectId) {
+        //获取最新的最新的一期验收
+        ArchiveExpertConclusion one = this.getOne(new LambdaUpdateWrapper<ArchiveExpertConclusion>()
+                .eq(ArchiveExpertConclusion::getProjectId, projectId)
+                .orderByDesc(ArchiveExpertConclusion::getCreateTime)
+                .last("limit 1"));
+        //如果为空代表没有申请过,返回true
+        if (one == null){
+            return 0;
+        }
+        return one.getIsBuildScore();
+    }
+
+    /**
+     * 编写结论-修改是否生成打分表
+     */
+    @Override
+    public void updateScore(Long projectId, Integer isSelect) {
+        //获取最新的最新的一期验收
+        ArchiveExpertConclusion one = this.getOne(new LambdaUpdateWrapper<ArchiveExpertConclusion>()
+                .eq(ArchiveExpertConclusion::getProjectId, projectId)
+                .orderByDesc(ArchiveExpertConclusion::getCreateTime)
+                .last("limit 1"));
+        //如果为空代表没有申请过,返回true
+        if (one == null){
+            throw new ServiceException("当前没有申请验收信息,无法修改");
+        }
+        one.setIsBuildScore(isSelect);
+        this.updateById(one);
+    }
+}
+

+ 44 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchiveExpertScoreServiceImpl.java

@@ -0,0 +1,44 @@
+package org.springblade.archive.service.impl;
+
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import org.springblade.archive.entity.ArchiveExpertScore;
+import org.springblade.archive.entity.ExpertInspection;
+import org.springblade.archive.mapper.ArchiveExpertScoreMapper;
+import org.springblade.archive.mapper.ExpertInspectionMapper;
+import org.springblade.archive.service.IArchiveExpertScoreService;
+import org.springblade.archive.service.IExpertInspectionService;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Service
+public class ArchiveExpertScoreServiceImpl extends BaseServiceImpl<ArchiveExpertScoreMapper, ArchiveExpertScore> implements IArchiveExpertScoreService {
+
+
+    @Override
+    public void saveBaseScoreInfo(Long projectId) {
+        List<ArchiveExpertScore> list = new ArrayList<>();
+        //业主
+        list.add(new ArchiveExpertScore(projectId,1,"业主评分项1",10,0,10,0));
+        //监理
+        list.add(new ArchiveExpertScore(projectId,2,"监理评分项1",10,0,10,0));
+        //施工
+        list.add(new ArchiveExpertScore(projectId,3,"施工评分项1",10,0,10,0));
+        this.saveBatch(list);
+    }
+
+    /**
+     * 专家评分-根据单位获取打分项
+     */
+    @Override
+    public List<ArchiveExpertScore> getItemByUnit(Long projectId, Integer unitType) {
+        List<ArchiveExpertScore> list = this.list(new LambdaQueryWrapper<ArchiveExpertScore>()
+                .eq(ArchiveExpertScore::getProjectId, projectId)
+                .eq(ArchiveExpertScore::getUnitType, unitType));
+        return list;
+    }
+}
+

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

@@ -37,10 +37,7 @@ 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.entity.ExpertInspection;
+import org.springblade.archive.entity.*;
 import org.springblade.archive.mapper.ArchiveConclusionMapper;
 import org.springblade.archive.service.*;
 import org.springblade.archive.utils.ArchiveTreeUtil;
@@ -144,6 +141,8 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 	private final ArchiveConclusionMapper conclusionMapper;
 
 	private final NewIOSSClient newIOSSClient;
+
+	private final IArchiveExpertConclusionService expertConclusionService;
 	//表格高度
 	private static int high = 20;
 	//表格宽度
@@ -2330,11 +2329,11 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 	}
 
 	@Override
-	public void archiveAutoMethodThread(Long projectId, Long contractId, Long nodeId) {
+	public void archiveAutoMethodThread(Long projectId, Long contractId, Long nodeId, Long traceId) {
 		executorService.execute(()->{
 			try{
 				//将项目未锁定案卷拆卷
-				log.info("[自动组卷]{}","开始对未锁定案卷拆卷。projectId:"+projectId+"-contractId:"+contractId+"-nodeId:"+nodeId);
+				log.info("[自动组卷]{}","开始对未锁定案卷拆卷。projectId:"+projectId+"-contractId:"+contractId+"-nodeId:"+nodeId+"-traceId:"+traceId);
 
 				//todo 有项目上传几百G文件,点组卷会产生大量费用,等改完文件下载走内网再打开此开关。
 //				if (true) {
@@ -2346,27 +2345,27 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 				contractClient.updateIsArchivesAutoById(contractId,10);
 
 				//项目自动组卷入口
-				log.info("[自动组卷]{}","开始自动组卷。projectId:"+projectId+"-contractId:"+contractId+"-nodeId:"+nodeId);
+				log.info("[自动组卷]{}","开始自动组卷。projectId:"+projectId+"-contractId:"+contractId+"-nodeId:"+nodeId+"-traceId:"+traceId);
 				archiveAutoMethod(projectId,contractId,nodeId);
 				//设置完成度80%
 				contractClient.updateIsArchivesAutoById(contractId,80);
 
 				//刷新项目档号
-				log.info("[自动组卷]{}","开始刷新组卷档号。projectId:"+projectId+"-contractId:"+contractId+"-nodeId:"+nodeId);
+				log.info("[自动组卷]{}","开始刷新组卷档号。projectId:"+projectId+"-contractId:"+contractId+"-nodeId:"+nodeId+"-traceId:"+traceId);
 				refreshFileNumberNoSlipt(projectId,contractId,nodeId,true);
 
 
 				//设置自动组卷结束
 				contractClient.updateIsArchivesAutoById(contractId,0);
-				log.info("[自动组卷]{}","自动组卷完成。projectId:"+projectId+"-contractId:"+contractId+"-nodeId:"+nodeId);
+				log.info("[自动组卷]{}","自动组卷完成。projectId:"+projectId+"-contractId:"+contractId+"-nodeId:"+nodeId+"-traceId:"+traceId);
 			}catch (Exception e){
 				e.printStackTrace();
-				log.error("[自动组卷] 报错。"+e.getMessage()+"--projectId:"+projectId+"-contractId:"+contractId+"-nodeId:"+nodeId);
+				log.error("[自动组卷] 报错。"+e.getMessage()+"--projectId:"+projectId+"-contractId:"+contractId+"-nodeId:"+nodeId+"-traceId:"+traceId);
 				//设置自动组卷结束
 				contractClient.updateIsArchivesAutoById(contractId, 0);
 			}finally {
 				contractClient.updateIsArchivesAutoById(contractId, 0);
-				log.error("[自动组卷] 流程结束--projectId:"+projectId+"-contractId:"+contractId+"-nodeId:"+nodeId);
+				log.error("[自动组卷] 流程结束--projectId:"+projectId+"-contractId:"+contractId+"-nodeId:"+nodeId+"-traceId:"+traceId);
 			}
 		});
 	}
@@ -2640,10 +2639,10 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		}else {
 			unitAllArchive = baseMapper.getUnitAllArchive2(FirstNode.getId(),4,isApply);
 		}
+		vo.setUnitInfo(unitName+"("+unitAllArchive.size()+"卷)");
 		if (unitAllArchive.size() == 0){
-			return null;
+			return vo;
 		}
-		vo.setUnitInfo(unitName+"("+unitAllArchive.size()+"卷)");
 		List<ArchiveInspectPreviewVO.NodeList> nodeLists = new ArrayList<>();
 		//档案按照二级节点分组
 		Map<Long, List<ArchivesAutoVO2>> archiveMap = unitAllArchive.stream().collect(Collectors.groupingBy(ArchivesAutoVO2::getMasterNode));
@@ -2667,6 +2666,8 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		return vo;
 	}
 
+
+
 	@Override
 	public void batchDownloadFileToZip(String ids, HttpServletResponse response) {
 		List<Long> longs = Func.toLongList(ids);
@@ -2756,6 +2757,19 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		if (aBoolean){
 			throw new ServiceException("当前用户已存在验收任务,请勿重复上报");
 		}
+		//判断当前是否已经存在上报任务
+		Boolean b = taskClient.getArchiveAppCount(dto.getProjectId());
+		if (b == null || b){
+			throw new ServiceException("当前项目已存在上报中的验收任务,请勿重复上报");
+		}
+		//判断上一期是否完成
+		ArchiveExpertConclusion one = expertConclusionService.getOne(new LambdaUpdateWrapper<ArchiveExpertConclusion>()
+				.eq(ArchiveExpertConclusion::getProjectId, dto.getProjectId())
+				.orderByDesc(ArchiveExpertConclusion::getCreateTime)
+				.last("limit 1"));
+		if (one != null && one.getStatus() == 1){
+			throw new ServiceException("上期验收任务还未完成,请勿上报");
+		}
 		//设置任务表信息
 		Task task = new Task();
 		Long id = SnowFlakeUtil.getId();
@@ -2923,6 +2937,7 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		return R.data(true);
 	}
 
+
 	@Override
 	public Boolean getApplyStatus(Long projectId) {
 		//查出所有当前用户待审批的验收任务
@@ -2934,6 +2949,30 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 			return true;
 		}
 	}
+	@Override
+	public Map<String,Boolean> getApplyStatus2(Long projectId) {
+		Map<String,Boolean> map = new HashMap<>();
+		//查出所有当前用户待审批的验收任务
+		Long userId = AuthUtil.getUserId();
+		List<Task> tasks = taskClient.queryUserTask(projectId,2, userId, 1);
+		//显示上报还是撤销
+		if (tasks == null || tasks.size() == 0){
+			map.put("appStatus",false);
+		}else {
+			map.put("appStatus",true);
+		}
+		//控制是否能点击
+		ArchiveExpertConclusion one = expertConclusionService.getOne(new LambdaUpdateWrapper<ArchiveExpertConclusion>()
+				.eq(ArchiveExpertConclusion::getProjectId, projectId)
+				.orderByDesc(ArchiveExpertConclusion::getCreateTime)
+				.last("limit 1"));
+		if (one == null || one.getStatus() == 2){
+			map.put("isShow",true);
+		}else {
+			map.put("isShow",false);
+		}
+		return map;
+	}
 
 	@Override
 	public void annulApply(Long projectId) {
@@ -2951,9 +2990,11 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 	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 {
+			//查询所有的,树不加id,档案状态加
 			return baseMapper.getNodeArchives(page,nodeId,projectId,searchType,searchValue,AuthUtil.getUserId());
+		}else {
+			//查询专家的,树加id,档案状态加
+			return baseMapper.getNodeArchives2(page,nodeId,projectId,searchType,searchValue,AuthUtil.getUserId());
 		}
 	}
 
@@ -2972,6 +3013,9 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		map.put("total",t1+"");
 		//获取用户归属档案所有已阅总数
 		Integer t2 = baseMapper.getUserReviewedTotal(projectId, userId);
+		if (t2 == null){
+			t2 = 0;
+		}
 		if (t2 > t1){
 			throw new ServiceException("数据错误,已阅比总数多");
 		}
@@ -3055,42 +3099,45 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 			ContractInfo contract = contractClient.getContractById(archive.getContractId());
 			unitType = contract.getContractType();
 		}
-		//判断是否存在意见
+		//判断是否合格
 		Integer isPass = 1;
 		if (StringUtils.isNotBlank(inspection.getOpinion())){
+			//专家有填写意见,不合格
 			isPass = 0;
 		}
+		inspection.setProjectId(archive.getProjectId());
 		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>()
+			//判断当前档案是否存在合格意见,存在则直接跳过,不存在就重新保存
+			ExpertInspection one = inspectionService.getOne(new LambdaQueryWrapper<ExpertInspection>()
 					.eq(ExpertInspection::getExpertId, userId)
 					.eq(ExpertInspection::getArchiveId, archive.getId())
 					.eq(ExpertInspection::getIsPass, 1));
-			if (count3 == 0){
+			if (one == null) {
 				//先删除当前专家对当前案卷当前文件的意见
 				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>()
+				//判断当前档案是否存在其他意见,有则直接跳过
+				long count3 = inspectionService.count(new LambdaQueryWrapper<ExpertInspection>()
 						.eq(ExpertInspection::getExpertId, userId)
 						.eq(ExpertInspection::getArchiveId, archive.getId())
 						.eq(ExpertInspection::getIsPass, 0));
-				//没有就直接保存合格
-				if (count2 == 0) {
+				if (count3 == 0) {
+					//没有就直接保存合格
 					inspection.setFileId(null);
+					inspection.setId(null);
 					inspectionService.save(inspection);
 				}
 			}
 		}else {
-			//如果专家对案卷有意见,先删除当前专家在意见表对当前档案合格的意见
+			//专家对案卷有意见,先删除当前专家在意见表对当前档案合格的意见
 			inspectionService.remove(new LambdaQueryWrapper<ExpertInspection>()
 					.eq(ExpertInspection::getExpertId, userId)
 					.eq(ExpertInspection::getArchiveId, inspection.getArchiveId())
@@ -3129,10 +3176,20 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 	 */
 	@Override
 	public IPage<ExpertInspectionVO> getUserInspectInfo(Query query, Long projectId) {
+		Long userId = AuthUtil.getUserId();
+		IPage<ExpertInspectionVO> page = new Page<>(query.getCurrent(),query.getSize());
+		return baseMapper.getUserInspectInfo(page,projectId,userId);
+	}
+
+	/**
+	 * 在线验收-抽检记录-汇总
+	 */
+	@Override
+	public IPage<ExpertInspectionVO> getUserInspectInfo2(Query query, Long projectId) {
 		Long userId = AuthUtil.getUserId();
 		//判断当前用户职位是否为专家组长,专家组长查看所有
 		String userRole = AuthUtil.getUserRole();
-		if ("1656191696348082177".equals(userRole)){
+		if ("专家组长".equals(userRole)){
 			userId = null;
 		}
 		IPage<ExpertInspectionVO> page = new Page<>(query.getCurrent(),query.getSize());

+ 43 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/TraceLogServiceImpl.java

@@ -0,0 +1,43 @@
+package org.springblade.archive.service.impl;
+
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.archive.entity.TraceLog;
+import org.springblade.archive.mapper.TraceLogMapper;
+import org.springblade.archive.service.ITraceLogService;
+import org.springframework.stereotype.Service;
+
+@Service
+public class TraceLogServiceImpl extends BaseServiceImpl<TraceLogMapper, TraceLog> implements ITraceLogService {
+    // Implementations of methods defined in ITraceLogService
+
+    /**
+     * 保存日志信息
+     *
+     * @param traceId 追踪ID
+     * @param format 格式化字符串
+     * @param args 格式化参数
+     */
+    @Override
+    public void save(Long traceId, String format, Object... args) {
+        try {
+            // 使用String.format来格式化字符串
+            String content = String.format(format, args);
+
+            // 截取content,确保长度不超过400字符
+            if (content.length() > 400) {
+                content = content.substring(0, 400);
+            }
+
+            // 创建TraceLog对象
+            TraceLog traceLog = new TraceLog();
+            traceLog.setTraceId(traceId);
+            traceLog.setContent(content);
+            save(traceLog);
+
+        } catch (Exception e) {
+            // 异常处理逻辑,比如打印日志
+            System.err.println("Error saving trace log: " + e.getMessage());
+        }
+    }
+
+}

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

@@ -19,6 +19,7 @@ import org.apache.commons.lang.time.DateUtils;
 import org.jetbrains.annotations.NotNull;
 import org.springblade.archive.dto.SaveApplyDTO;
 import org.springblade.archive.feign.ArchiveAutoClient;
+import org.springblade.archive.feign.ArchiveExpertConclusionClient;
 import org.springblade.business.dto.*;
 import org.springblade.business.entity.*;
 import org.springblade.business.service.*;
@@ -64,6 +65,7 @@ import org.springframework.web.bind.annotation.*;
 import javax.servlet.http.HttpServletRequest;
 import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.io.InputStream;
 import java.text.SimpleDateFormat;
 import java.time.Duration;
 import java.util.*;
@@ -93,6 +95,7 @@ public class TaskController extends BladeController {
     private final ArchiveFileTaskClient archiveFileTaskClient;
     private final IUserClient userClient;
     private final ArchiveAutoClient archiveClient;
+    private final ArchiveExpertConclusionClient conclusionClient;
 
     /**
      * 记录短信验证码超时时间
@@ -631,7 +634,7 @@ public class TaskController extends BladeController {
             for (TaskArchiveDTO taskArchiveDTO : taskArchiveOuterLayerDTO.getTaskArchiveDtoList()) {
                 if (StringUtils.isNotEmpty(taskArchiveDTO.getTaskId())) {
                     //通过checkArchiveTaskUserByCurrent检查,说明当前登陆用户是该条任务的审批人,修改审批任务状态
-                    Task task = jdbcTemplate.queryForObject("select id,contract_id,project_id,process_instance_id,form_data_id,type,archive_ids from u_task where id = " + taskArchiveDTO.getTaskId(), new BeanPropertyRowMapper<>(Task.class));
+                    Task task = jdbcTemplate.queryForObject("select id,contract_id,project_id,process_instance_id,form_data_id,type,archive_ids,attachment_pdf_url from u_task where id = " + taskArchiveDTO.getTaskId(), new BeanPropertyRowMapper<>(Task.class));
                     if (task != null) {
                         //判断任务类型是否是验收任务,档案验收任务单独处理修改状态直接返回
                         if (task.getType() == 2) {
@@ -696,12 +699,17 @@ public class TaskController extends BladeController {
                                 //修改档案类型
                                 String archiveIds = task.getArchiveIds();
                                 if (StringUtils.isNotBlank(archiveIds)) {
-                                    List<Long> longs = Func.toLongList(archiveIds);
-                                    R<Boolean> booleanR = archiveClient.batchUpdateIsApply(1, longs);
+                                    List<Long> ids = Func.toLongList(archiveIds);
+                                    R<Boolean> booleanR = archiveClient.batchUpdateIsApply(ids);
                                     if (booleanR.getData() == null || !booleanR.isSuccess()) {
                                         throw new ServiceException("修改档案类型失败");
                                     }
                                 }
+                                //创建报表基本信息,报表中会自动创建评分基础信息
+                                R r = conclusionClient.saveBaseTableInfo(Long.parseLong(task.getProjectId()), task.getAttachmentPdfUrl());
+                                if (r == null || !"保存成功".equals(r.getData())){
+                                    throw new ServiceException("保存报表基本信息失败");
+                                }
                             }
                             return R.data(true);
                         }
@@ -781,22 +789,29 @@ public class TaskController extends BladeController {
     @PostMapping("/getArchiveFileTaskPdfs")
     @ApiOperationSupport(order = 8)
     @ApiOperation(value = "批量审批-获取档案审批任务对应业务数据的pdf信息", notes = "传入任务id,封装成taskIds,字符串逗号分割拼接")
-    public R<List<ArchiveFileTaskPDFVO>> getArchiveFileTaskPdfs(@RequestParam String taskIds) {
-        if (StringUtils.isNotEmpty(taskIds)) {
-            List<Task> taskList = jdbcTemplate.query("select form_data_id from u_task where approval_type = 4 and id in(" + taskIds + ")", new BeanPropertyRowMapper<>(Task.class));
-            Set<String> formDataIds = taskList.stream().map(Task::getFormDataId).collect(Collectors.toSet());
-            if (formDataIds.size() > 0) {
-                List<ArchiveFile> archiveFiles = jdbcTemplate.query("select id,file_name,pdf_file_url,e_visa_file from u_archive_file where id in(" + StringUtils.join(formDataIds, ",") + ")", new BeanPropertyRowMapper<>(ArchiveFile.class));
-                List<ArchiveFileTaskPDFVO> collect = archiveFiles.stream()
-                        .map(obj -> {
-                            ArchiveFileTaskPDFVO vo = new ArchiveFileTaskPDFVO();
-                            vo.setId(obj.getId());
-                            vo.setPdfUrl(ObjectUtil.isNotEmpty(obj.getEVisaFile()) ? obj.getEVisaFile() : obj.getPdfFileUrl());
-                            vo.setFileName(obj.getFileName());
-                            return vo;
-                        }).collect(Collectors.toList());
-                return R.data(collect);
+    public R<List<ArchiveFileTaskPDFVO>> getArchiveFileTaskPdfs(@RequestParam String taskIds,@RequestParam Integer type) {
+        //普通任务
+        if (type == 1) {
+            if (StringUtils.isNotEmpty(taskIds)) {
+                List<Task> taskList = jdbcTemplate.query("select form_data_id from u_task where approval_type = 4 and id in(" + taskIds + ")", new BeanPropertyRowMapper<>(Task.class));
+                Set<String> formDataIds = taskList.stream().map(Task::getFormDataId).collect(Collectors.toSet());
+                if (formDataIds.size() > 0) {
+                    List<ArchiveFile> archiveFiles = jdbcTemplate.query("select id,file_name,pdf_file_url,e_visa_file from u_archive_file where id in(" + StringUtils.join(formDataIds, ",") + ")", new BeanPropertyRowMapper<>(ArchiveFile.class));
+                    List<ArchiveFileTaskPDFVO> collect = archiveFiles.stream()
+                            .map(obj -> {
+                                ArchiveFileTaskPDFVO vo = new ArchiveFileTaskPDFVO();
+                                vo.setId(obj.getId());
+                                vo.setPdfUrl(ObjectUtil.isNotEmpty(obj.getEVisaFile()) ? obj.getEVisaFile() : obj.getPdfFileUrl());
+                                vo.setFileName(obj.getFileName());
+                                return vo;
+                            }).collect(Collectors.toList());
+                    return R.data(collect);
+                }
             }
+        }else if (type == 2){
+            //验收任务
+            List<ArchiveFileTaskPDFVO> vos = jdbcTemplate.query("select id,task_name as fileName,attachment_pdf_url as pdfUrl from u_task where approval_type = 4 and id in(" + taskIds + ")", new BeanPropertyRowMapper<>(ArchiveFileTaskPDFVO.class));
+            return R.data(vos);
         }
         return R.data(null);
     }

+ 13 - 0
blade-service/blade-business/src/main/java/org/springblade/business/feignClient/TaskClientImpl.java

@@ -34,6 +34,19 @@ public class TaskClientImpl implements TaskClient {
 
     private final ITaskParallelService taskParallelService;
 
+    @Override
+    public Boolean getArchiveAppCount(Long projectId) {
+        List<Task> list = taskService.list(new LambdaQueryWrapper<Task>()
+                .eq(Task::getProjectId, projectId)
+                .eq(Task::getType, 2)
+                .eq(Task::getStatus, 1));
+        if (list.size() > 0){
+            return true;
+        }else {
+            return false;
+        }
+    }
+
     @Override
     public void saveTask(Task task) {
         taskService.save(task);

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

@@ -26,7 +26,7 @@
     </delete>
 
     <select id="queryDataInfo" resultMap="taskBatchResultMap">
-        SELECT DISTINCT JSON_EXTRACT(a.json_data, '$.formDataId') ,a.* from u_task_batch a GROUP BY JSON_EXTRACT(a.json_data, '$.formDataId') LIMIT 140
+        SELECT a.* from u_task_batch a LIMIT 40
     </select>
 
 </mapper>

+ 6 - 5
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TaskServiceImpl.java

@@ -61,7 +61,6 @@ import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.RequestHeader;
-import org.springframework.web.bind.annotation.RequestParam;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
@@ -580,19 +579,20 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
     }
 
 
-    @Scheduled(cron = "0 */1 * * * ?")
-    public void SignInfo() {
+    //@Scheduled(cron = "0/20 * * * * ?")
+    public void SignInfo() throws InterruptedException {
         //执行代码
         logger.debug("扫描开始");
         List<TaskBatch> maps = taskBatchService.queryDataInfo();
-        if (maps != null && maps.size() >= 1 && executor.getQueue().size() <= 200) {
+        if (maps != null && maps.size() >= 1 && executor.getQueue().size()<=200) {
             for (TaskBatch dataInfo : maps) {
+                if (executor.getQueue().size()<=40 ) {
                 String jsonData = dataInfo.getJsonData();
                 TaskApprovalVO taskApprovalVO = JSON.parseObject(jsonData, TaskApprovalVO.class);
                 String taskBatchId = dataInfo.getId().toString();
                 Long userId = dataInfo.getCreateUser();
                 String nickName = dataInfo.getNickName();
-
+                Thread.sleep(100);
                 Boolean aBoolean = RedisTemplate.hasKey("sign-" + taskApprovalVO.getFormDataId());
                 System.out.println("---------" + aBoolean);
                 if (!aBoolean) {
@@ -606,6 +606,7 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                         }
                     }, executor);
                 }
+                }
             }
         }
         System.out.println("队列数量" + executor.getQueue().size());

+ 97 - 97
blade-service/blade-e-visa/src/main/java/org/springblade/evisa/controller/EVisaController.java

@@ -1,97 +1,97 @@
-package org.springblade.evisa.controller;
-
-import com.alibaba.fastjson.JSON;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
-import io.swagger.annotations.*;
-import lombok.AllArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang.StringUtils;
-import org.springblade.business.entity.TaskBatch;
-import org.springblade.business.vo.TaskApprovalVO;
-import org.springblade.core.boot.ctrl.BladeController;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.data.redis.core.StringRedisTemplate;
-import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.web.bind.annotation.*;
-
-import javax.annotation.Resource;
-import java.io.BufferedReader;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.*;
-import java.util.concurrent.*;
-
-import java.lang.management.ManagementFactory;
-import java.lang.management.OperatingSystemMXBean;
-import java.util.concurrent.locks.ReentrantLock;
-
-/**
- * 清表基础数据表 控制器
- *
- * @author BladeX
- * @since 2022-05-18
- */
-@RestController
-@AllArgsConstructor
-@RequestMapping("/evisaInfo")
-@Api(value = "电签类", tags = "电签类接口")
-@Slf4j
-public class EVisaController {
-
-    @Autowired
-    StringRedisTemplate RedisTemplate;
-
-    private final JdbcTemplate jdbcTemplate;
-
-    // 线程池
-    @Resource(name = "taskExecutor1")
-    private ThreadPoolExecutor executor;
-
-    // 电签主类
-  //  @Scheduled(cron = "0 */1 * * * ?")
-    public void SignInfo() {
-
-        //执行代码
-        log.info("扫描开始");
-        String sql = "SELECT * from u_task_batch where is_deleted =0 LIMIT 100";
-        List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);
-        if (maps != null && maps.size() >= 1) {
-            for (Map<String, Object> dataInfo : maps) {
-                String jsonData = dataInfo.get("json_data")+"";
-                TaskApprovalVO taskApprovalVO = JSON.parseObject(jsonData, TaskApprovalVO.class);
-                String taskBatchId = dataInfo.get("id").toString();
-                Long userId = Long.valueOf(dataInfo.get("create_user")+"");
-                String nickName = dataInfo.get("nick_name")+"";
-                Boolean aBoolean = RedisTemplate.hasKey("sign-" + taskApprovalVO.getFormDataId());
-                System.out.println(aBoolean);
-
-                RedisTemplate.opsForValue().set("sign-" + taskApprovalVO.getFormDataId(), "1", 600, TimeUnit.SECONDS);
-
-               /* String formDataId = taskApprovalVO.getFormDataId().substring(0,5);
-                synchronized (formDataId){
-                    executor.execute(new Runnable() {
-                        @Override
-                        public void run() {
-                            checkIsExsitTaskBatch(taskApprovalVO,formDataId,userId,nickName);
-                        }
-                    });
-                }*/
-            }
-        }
-    }
-
-    public void checkIsExsitTaskBatch(TaskApprovalVO taskApprovalVO, String batchId, Long userId, String nickName){
-           synchronized (batchId){
-               try {
-                   System.out.println("开始执行-------");
-                   Thread.sleep(8000);
-                   System.out.println(batchId);
-                   System.out.println("结束执行-------");
-               } catch (InterruptedException e) {
-                   throw new RuntimeException(e);
-               }
-           }
-    }
-}
+//package org.springblade.evisa.controller;
+//
+//import com.alibaba.fastjson.JSON;
+//import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+//import io.swagger.annotations.*;
+//import lombok.AllArgsConstructor;
+//import lombok.extern.slf4j.Slf4j;
+//import org.apache.commons.lang.StringUtils;
+//import org.springblade.business.entity.TaskBatch;
+//import org.springblade.business.vo.TaskApprovalVO;
+//import org.springblade.core.boot.ctrl.BladeController;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.data.redis.core.StringRedisTemplate;
+//import org.springframework.jdbc.core.JdbcTemplate;
+//import org.springframework.scheduling.annotation.Scheduled;
+//import org.springframework.web.bind.annotation.*;
+//
+//import javax.annotation.Resource;
+//import java.io.BufferedReader;
+//import java.io.FileNotFoundException;
+//import java.io.IOException;
+//import java.io.InputStreamReader;
+//import java.util.*;
+//import java.util.concurrent.*;
+//
+//import java.lang.management.ManagementFactory;
+//import java.lang.management.OperatingSystemMXBean;
+//import java.util.concurrent.locks.ReentrantLock;
+//
+///**
+// * 清表基础数据表 控制器
+// *
+// * @author BladeX
+// * @since 2022-05-18
+// */
+//@RestController
+//@AllArgsConstructor
+//@RequestMapping("/evisaInfo")
+//@Api(value = "电签类", tags = "电签类接口")
+//@Slf4j
+//public class EVisaController {
+//
+//    @Autowired
+//    StringRedisTemplate RedisTemplate;
+//
+//    private final JdbcTemplate jdbcTemplate;
+//
+//    // 线程池
+//   // @Resource(name = "taskExecutor1")
+//  //  private ThreadPoolExecutor executor;
+//
+//    // 电签主类
+//  //  @Scheduled(cron = "0 */1 * * * ?")
+//    public void SignInfo() {
+//
+//        //执行代码
+//        log.info("扫描开始");
+//        String sql = "SELECT * from u_task_batch where is_deleted =0 LIMIT 100";
+//        List<Map<String, Object>> maps = jdbcTemplate.queryForList(sql);
+//        if (maps != null && maps.size() >= 1) {
+//            for (Map<String, Object> dataInfo : maps) {
+//                String jsonData = dataInfo.get("json_data")+"";
+//                TaskApprovalVO taskApprovalVO = JSON.parseObject(jsonData, TaskApprovalVO.class);
+//                String taskBatchId = dataInfo.get("id").toString();
+//                Long userId = Long.valueOf(dataInfo.get("create_user")+"");
+//                String nickName = dataInfo.get("nick_name")+"";
+//                Boolean aBoolean = RedisTemplate.hasKey("sign-" + taskApprovalVO.getFormDataId());
+//                System.out.println(aBoolean);
+//
+//                RedisTemplate.opsForValue().set("sign-" + taskApprovalVO.getFormDataId(), "1", 600, TimeUnit.SECONDS);
+//
+//               /* String formDataId = taskApprovalVO.getFormDataId().substring(0,5);
+//                synchronized (formDataId){
+//                    executor.execute(new Runnable() {
+//                        @Override
+//                        public void run() {
+//                            checkIsExsitTaskBatch(taskApprovalVO,formDataId,userId,nickName);
+//                        }
+//                    });
+//                }*/
+//            }
+//        }
+//    }
+//
+//    public void checkIsExsitTaskBatch(TaskApprovalVO taskApprovalVO, String batchId, Long userId, String nickName){
+//           synchronized (batchId){
+//               try {
+//                   System.out.println("开始执行-------");
+//                   Thread.sleep(8000);
+//                   System.out.println(batchId);
+//                   System.out.println("结束执行-------");
+//               } catch (InterruptedException e) {
+//                   throw new RuntimeException(e);
+//               }
+//           }
+//    }
+//}

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

@@ -76,6 +76,7 @@ import javax.imageio.metadata.IIOMetadataNode;
 import javax.imageio.stream.ImageOutputStream;
 import java.awt.image.BufferedImage;
 import java.io.*;
+import java.net.URL;
 import java.nio.charset.StandardCharsets;
 import java.util.*;
 
@@ -475,7 +476,7 @@ public class EVisaServiceImpl implements EVisaService {
                         return SUCCESS + "@@@@" + taskFile.getApprovalFileList().get(0).getFileUrl();
                     }
                 } else { //安心签证
-                    String sqlinfo = " SELECT a.id,a.pyzbx ,a.pyzby,(SELECT signature_file_url from m_sign_pfx_file where is_register=1 and certificate_user_id='" + task.getUserId() + "' and is_deleted=0  ) as signature_file_url from m_textdict_info a where  a.type =2 and a.id in (" + ids + ")  and sig_role_id in (SELECT DISTINCT c.role_id from m_project_assignment_user c  where c.contract_id=" + contractId + " and user_id=" + task.getUserId() + " and c.is_deleted=0 )";
+                    String sqlinfo = " SELECT DISTINCT a.id,a.pyzbx ,a.pyzby,(SELECT signature_file_url from m_sign_pfx_file where is_register=1 and certificate_user_id='" + task.getUserId() + "' and is_deleted=0  ) as signature_file_url from m_textdict_info a where  a.type =2 and a.id in (" + ids + ")  and sig_role_id in (SELECT DISTINCT c.role_id from m_project_assignment_user c  where c.contract_id=" + contractId + " and user_id=" + task.getUserId() + " and c.is_deleted=0 )";
                     List<Map<String, Object>> maps = jdbcTemplate.queryForList(sqlinfo);
                     System.out.println("安心签-个人-user-id" + task.getUserId() + "--SQL=" + sqlinfo);
                     if (maps == null || maps.size() <= 0) {
@@ -503,7 +504,14 @@ public class EVisaServiceImpl implements EVisaService {
                     pdfVO.setStrategyVoList(sealStrategyVOS);
 
                     //获取字节
-                    byte[] fileByte = CommonUtil.InputStreamToBytes(CommonUtil.getOSSInputStream(pdfUrl));
+                    URL url =new URL(pdfUrl);
+                    byte[] fileByte;
+                    try {
+                        fileByte = IOUtils.toByteArray(url);
+                    }catch (Exception e){
+                        return null;
+                    }
+
                     //执行电签
                     Object[] result = this.signPdfByAXQZ(pdfVO, fileByte);
                     if (result != null) {
@@ -776,8 +784,8 @@ public class EVisaServiceImpl implements EVisaService {
      */
     private Object[] signPdfByAXQZ(SealPdfVO pdfVO, byte[] fileByte) {
         Object[] result = new Object[3];
-        try {
-            PaperlessClient paperlessClient = new PaperlessClient(SIGN_HOST, SIGN_PORT, 300000, 36000000);
+            try {
+            PaperlessClient paperlessClient = new PaperlessClient(SIGN_HOST, SIGN_PORT, 300000, 1800000);
             paperlessClient.setSSL(false);
             //*****************************************************************************
             CompoundSealPdfListDetachedRequest compoundSealPdfListDetachedRequest = new CompoundSealPdfListDetachedRequest();
@@ -791,7 +799,6 @@ public class EVisaServiceImpl implements EVisaService {
             String operatorCode = EVisaConstant.operationCode;
             //渠道编码 可为空
             String channelCode = "";
-
             //设置属性
             requestHead.setBasicInfo(transactionNo, organizationCode, operatorCode, channelCode);
 
@@ -828,9 +835,10 @@ public class EVisaServiceImpl implements EVisaService {
             compoundSealPdfListDetachedRequest.setBody(requestBody);
             //****************************** 请求服务端进行签章 *********************************************
             System.out.println("-----------------------"+new Date().toString()+"开始"+transactionNo +"----------------------------");
+
             ResponseDto responseDto = paperlessClient.execute(compoundSealPdfListDetachedRequest);
-            System.out.println("-----------------------"+new Date().toString()+"结束"+transactionNo +"----------------------------");
 
+            System.out.println("-----------------------"+new Date().toString()+"结束"+transactionNo +"----------------------------");
             //******************************解析响应结果 *********************************************
             CompoundSealPdfListDetachedResponse compoundSealPdfListDetachedResponse = (CompoundSealPdfListDetachedResponse) responseDto;
             ResponseHead responseHead = compoundSealPdfListDetachedResponse.getHead();
@@ -848,14 +856,9 @@ public class EVisaServiceImpl implements EVisaService {
                 result[1] = compoundSealPdfListDetachedResponse.toString();
                 result[2] = responseHead.getMessage();
             }
-
-        } catch (Exception e) {
-            e.printStackTrace();
-            logger.info("【电签模块】{}", "电签签章接口调用异常");
-            e.printStackTrace();
-            return null;
-        }
-
+            }catch (Exception e){
+                e.printStackTrace();
+            }
         return result;
     }
 

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

@@ -7,11 +7,17 @@ import com.spire.pdf.general.find.PdfTextFindCollection;
 import com.spire.pdf.utilities.PdfTable;
 import com.spire.pdf.utilities.PdfTableExtractor;
 
+import org.apache.commons.io.IOUtils;
 import org.springblade.common.utils.CommonUtil;
 import org.springblade.core.tool.utils.Func;
+import org.springblade.core.tool.utils.ResourceUtil;
 
+import java.io.File;
+import java.io.FileInputStream;
 import java.io.InputStream;
+import java.net.HttpURLConnection;
 import java.net.URL;
+import java.net.URLConnection;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -62,15 +68,26 @@ public class PDFUtils {
 */
 
 
-    public static List<String> getPdfSignIds(String pdfUrl) {
+    public static synchronized List<String>  getPdfSignIds(String pdfUrl) {
         PdfDocument pdf = new PdfDocument();
         List<String> eVisaConfigList = new ArrayList<>();
         try {
-            InputStream ossInputStream = CommonUtil.getOSSInputStream(pdfUrl);;
-          //  InputStream ossInputStream = new URL(pdfUrl).openStream();
-            //加载PDF文档
-            pdf.loadFromStream(ossInputStream);
 
+            URL url =new URL(pdfUrl);
+/*            URLConnection conn = url.openConnection();
+            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
+            //加载PDF文档
+            System.out.println("-------getid------"+pdfUrl);
+            conn.setConnectTimeout(30000);
+            conn.setConnectTimeout(60000);
+            InputStream ossInputStream = conn.getInputStream();
+            Is
+            pdf.loadFromStream(ossInputStream);*/
+            byte[] byteArray = IOUtils.toByteArray(url);
+            pdf.loadFromBytes(byteArray);
+            /*if (conn instanceof HttpURLConnection) {
+                ((HttpURLConnection) conn).disconnect();
+            }*/
             for(int i= 0;i<pdf.getPages().getCount();i++){
                 PdfPageBase page = pdf.getPages().get(i);
                 PdfTextFindCollection allText = page.findAllText();
@@ -78,20 +95,21 @@ public class PDFUtils {
                 for(int k=0;k<finds.length;k++){
                     String textStr = finds[k].getMatchText();
                     if (textStr.length() >= 15 && Func.isNumeric(textStr)) {
-                        System.out.println(textStr);
                         eVisaConfigList.add(textStr);
                     }
                 }
             }
 
-
+           // ossInputStream.close();
             List<String> unique = eVisaConfigList.stream().distinct().collect(Collectors.toList());
-            ossInputStream.close();
+
             return unique;
         }catch (Exception e){
             e.printStackTrace();
+            return null;
+        }finally {
+            pdf.close();
         }
-        return null;
     }
 
     public static void main123(String[] args) {

+ 80 - 0
blade-service/blade-e-visa/src/main/java/org/springblade/evisa/utils/ThreadPoolDemo.java

@@ -0,0 +1,80 @@
+package org.springblade.evisa.utils;
+import com.alibaba.fastjson.JSON;
+import org.springblade.business.vo.TaskApprovalVO;
+import org.springframework.scheduling.annotation.Scheduled;
+
+import java.io.FileNotFoundException;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.*;
+
+public class ThreadPoolDemo {
+
+    ThreadPoolDemo(){
+        System.out.println("-----------------------");
+        System.out.println("----------启动-------------");
+        System.out.println("-----------------------");
+    }
+
+
+    @Scheduled(cron = "0 */1 * * * ?")
+    public void SignInfo() {
+
+    }
+
+    public static void main11(String[] args) throws InterruptedException {
+
+        // 准备创建线程池所需要的7个参数
+        int corePoolSize = 3;
+        int maximumPoolSize = 3;
+        int keepLiveTime = 0;
+        TimeUnit timeUnit = TimeUnit.SECONDS;
+        ThreadFactory threadFactory = Executors.defaultThreadFactory();
+        ArrayBlockingQueue queue = new ArrayBlockingQueue<>(30);
+
+        RejectedExecutionHandler policy =
+                new ThreadPoolExecutor.DiscardOldestPolicy();
+        // 创建线程池对象
+        ThreadPoolExecutor myThreadPool = new ThreadPoolExecutor(
+                corePoolSize,
+                maximumPoolSize,
+                keepLiveTime,
+                timeUnit,
+                queue,
+                threadFactory,
+                policy);
+
+        for (int i=0;i<10;i++){
+            final int index = i;
+            String index2 = "1";
+            if(i%3==0){
+                index2="2";
+            }
+
+
+            String finalIndex = index2;
+            myThreadPool.execute(new Runnable() {
+
+                @Override
+                public void run() {
+                    try {
+                        synchronized (finalIndex) {
+                            System.out.println(index+"------"+finalIndex);
+                            if(finalIndex.equals("2")){
+                                System.out.println(index+"--2--开始");
+                                Thread.sleep(20000);
+                                System.out.println(index+"--2--结束");
+                            }else{
+                                Thread.sleep(1000);
+                            }
+                        }
+                    } catch (InterruptedException e) {
+                        // TODO Auto-generated catch block
+                        e.printStackTrace();
+                    }
+                }
+            });
+        }
+    }
+
+}

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

@@ -459,9 +459,9 @@ public class ArchiveTreeContractController extends BladeController {
             @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);
+    public R<TwoTreeVO> getUnitAllNode(@RequestParam Long projectId, @RequestParam String types) {
+        TwoTreeVO vo = archiveTreeContractService.getUnitAllNode(projectId,types);
+        return R.data(vo);
     }
 
     /**

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

@@ -430,7 +430,7 @@ public class SignPfxFileController extends BladeController {
     @ApiOperation(value = "新增", notes = "传入signPfxFile")
     public R<Boolean> save(@Valid @RequestBody SignPfxFileVO vo) {
 
-        if (new Integer("2").equals(vo.getCertificateType())) {
+        if (new Integer("2").equals(vo.getCertificateType()) || new Integer("3").equals(vo.getCertificateType())) {
             this.saveSignPfxDeputy(vo, true);
         }
         vo.setCreateUser(AuthUtil.getUserId());
@@ -446,7 +446,7 @@ public class SignPfxFileController extends BladeController {
     @ApiOperationSupport(order = 3)
     @ApiOperation(value = "修改", notes = "传入signPfxFile")
     public R<Boolean> update(@Valid @RequestBody SignPfxFileVO vo) {
-        if (new Integer("2").equals(vo.getCertificateType())) {
+        if (new Integer("2").equals(vo.getCertificateType())||new Integer("3").equals(vo.getCertificateType())) {
             //查询旧数据
             SignPfxFile oldData = this.signPfxFileService.getById(vo.getId());
             if (StringUtils.isNotEmpty(oldData.getProjectContractRole()) && !vo.getProjectContractRole().trim().equals(oldData.getProjectContractRole().trim())) {

+ 12 - 8
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/TextdictInfoController.java

@@ -533,8 +533,6 @@ public class TextdictInfoController extends BladeController {
         String ids = StringUtils.join(pKeyIds, ",");
 
         //读取html页面信息
-        //File file1 = ResourceUtil.getFile(wbsTreePrivate.getHtmlUrl());
-        //String htmlString = IoUtil.readToString(new FileInputStream(file1));
         InputStream inputStreamByUrl = FileUtils.getInputStreamByUrl(wbsTreePrivate.getHtmlUrl());
         String htmlString = IoUtil.readToString(inputStreamByUrl);
 
@@ -563,37 +561,43 @@ public class TextdictInfoController extends BladeController {
         List<TextdictInfo> textDictInfosNewAll = new ArrayList<>();
         for (Long pKeyId : pKeyIds) {
             List<TextdictInfo> textDictInfosNew = JSON.parseArray(JSON.toJSONString(textDictInfosOld), TextdictInfo.class);
+            List<TextdictInfo> textDictInfosNew2 = new ArrayList<>();
 
+            // 由于一个key 只能配置一个 对象 需要去除多余的 对象
+            for(TextdictInfo dafa:textDictInfosNew){
+                if(!dafa.getColKey().equals(id)){
+                    textDictInfosNew2.add(dafa);
+                }
+            }
             TextdictInfo textDictBean = new TextdictInfo();
             textDictBean.setColKey(id);
             textDictBean.setColName(placeholder);
             textDictBean.setSigRoleName(textdictInfo.getTextId());
             textDictBean.setIsDeleted(0);
             textDictBean.setProjectId(wbsTreePrivate.getProjectId());
-
-            textDictInfosNew.add(textDictBean);
+            textDictInfosNew2.add(textDictBean);
 
             //重新构造赋值
             if (textdictInfo.getType() == 4) {
-                for (TextdictInfo obj : textDictInfosNew) {
+                for (TextdictInfo obj : textDictInfosNew2) {
                     obj.setId(SnowFlakeUtil.getId());
                     obj.setTabId(pKeyId.toString());
                     obj.setType(4);
                     obj.setName("编辑默认值");
                 }
             } else if (textdictInfo.getType() == 5) {
-                for (TextdictInfo obj : textDictInfosNew) {
+                for (TextdictInfo obj : textDictInfosNew2) {
                     obj.setId(SnowFlakeUtil.getId());
                     obj.setTabId(pKeyId.toString());
                     obj.setType(5);
                     obj.setName("提示信息");
                 }
             }
-            textDictInfosNewAll.addAll(textDictInfosNew);
+            textDictInfosNewAll.addAll(textDictInfosNew2);
         }
 
         //删除当前类型
-        List<String> collect = textDictInfosNewAll.stream().map(TextdictInfo::getTabId).distinct().collect(Collectors.toList());
+        List<String> collect = textDictInfosOld.stream().map(TextdictInfo::getTabId).distinct().collect(Collectors.toList());
         if (collect != null && collect.size() >= 1) {
             this.textdictInfoService.getBaseMapper().delete(Wrappers.<TextdictInfo>query().lambda()
                     .eq(TextdictInfo::getType, textdictInfo.getType())

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

@@ -325,7 +325,10 @@ public class WbsTreePrivateController extends BladeController {
             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));
+                    .in(WbsTree::getId, ids))
+                    .stream()
+                    .filter(wbsTree -> wbsTree.getId() != null && wbsTree.getInitTableId() != null)
+                    .collect(Collectors.toMap(WbsTree::getId, WbsTree::getInitTableId));
 
             /*元素FidSet,统计数量*/
             Set<Long> formElementFids = new HashSet<>();

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

@@ -540,7 +540,11 @@
             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
+            and (id = atc.id or FIND_IN_SET(atc.id,ancestors)))), '卷)')) as 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 total
+
             from m_archive_tree_contract atc
             WHERE is_deleted =0 and project_id = #{projectId}
             and (id = #{ownerUnit} or FIND_IN_SET(#{ownerUnit},ancestors))
@@ -554,7 +558,9 @@
             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
+            and (id = atc.id or FIND_IN_SET(atc.id,ancestors)))), '卷)')) as 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 total
             from m_archive_tree_contract atc
             WHERE is_deleted =0 and project_id = #{projectId}
             and  (id = #{supervisorUnit} or FIND_IN_SET(#{supervisorUnit},ancestors))
@@ -568,7 +574,9 @@
             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
+            and (id = atc.id or FIND_IN_SET(atc.id,ancestors)))), '卷)')) as 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 total
             from m_archive_tree_contract atc
             WHERE is_deleted =0 and project_id = #{projectId}
             and  (id = #{buildUnit} or FIND_IN_SET(#{buildUnit},ancestors))
@@ -581,7 +589,9 @@
                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
+                and (id = atc.id or FIND_IN_SET(atc.id,ancestors)))), ')')) as 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 total
         from m_archive_tree_contract atc
         WHERE atc.parent_id = 0 and atc.is_deleted = 0 and project_id =#{projectId}
     </select>

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

@@ -125,7 +125,7 @@ public interface IArchiveTreeContractService extends BaseService<ArchiveTreeCont
 
     public void updateWbsRuleNodes(Long projectId);
 
-    List<InspectTreeVO> getUnitAllNode(Long project, String types);
+   TwoTreeVO getUnitAllNode(Long project, String types);
 
     void saveAllSelectNodes(Map<String, String> map);
 

+ 52 - 6
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeContractServiceImpl.java

@@ -1353,7 +1353,8 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 	 * @return
 	 */
 	@Override
-	public List<InspectTreeVO> 	getUnitAllNode(Long projectId,String types) {
+	public TwoTreeVO getUnitAllNode(Long projectId,String types) {
+		TwoTreeVO twoTreeVO = new TwoTreeVO();
 		/**
 		 *  1业主2监理3施工4影像5竣工图,根据勾选的类型,返回单位首节点集合,勾选哪个单位回显哪个
 		 *   如果勾选了施工,又勾选了影像和竣工图,则只返回施工,
@@ -1385,9 +1386,52 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 		List<InspectTreeVO> unitAllNode = baseMapper.getUnitAllNode(projectId,ownerUnit,supervisorUnit,buildUnit);
 		unitAllNode.add(firstNode);
 		List<InspectTreeVO> list = org.springblade.manager.utils.ForestNodeMerger.merge(unitAllNode);
+		twoTreeVO.setList(list);
+		List<InspectTreeVO> list2 = new ArrayList<>();
+		gatherSortNode(list,list2);
+		//查看当前档案是否分配过其他专家
+		if (list.size() > 1){
+			throw new ServiceException("节点信息错误");
+		}
+		//判断是否被分配
+		Boolean isAllot = false;
+		List<InspectTreeVO> vos = list.get(0).getChildren();
+		for (InspectTreeVO vo : vos) {
+			if (org.apache.commons.lang3.StringUtils.isNotBlank(vo.getNodeInfo())){
+				isAllot = true;
+				break;
+			}
+		}
 		List<Long> ids = new ArrayList<>();
-		gatherSortNode(list,ids);
-		return org.springblade.manager.utils.ForestNodeMerger.merge(unitAllNode);
+		if (isAllot){
+			//分配过其他专家,过滤出没有绑定专家的案卷
+			List<InspectTreeVO> list3 = list2.stream().filter(l-> org.apache.commons.lang3.StringUtils.isBlank(l.getNodeInfo())).collect(Collectors.toList());
+			if (list3.size() != 0){
+				//把剩下未分配的档案全部分配给当前专家
+				ids = list3.stream().map(InspectTreeVO::getId).collect(Collectors.toList());
+			}else {
+				//没有可分配的档案,直接为当前专家分配所有案卷
+				ids = list2.stream().map(InspectTreeVO::getId).collect(Collectors.toList());
+			}
+		}else {
+			//没有分配过
+			int reduce = firstNode.getTotal();
+			if (reduce == 0){
+				throw new ServiceException("当前没有案卷申请验收,无法分配");
+			}
+			int t = 0;
+			reduce = (int)(reduce * 0.7);
+			for (InspectTreeVO vo : list2) {
+				ids.add(vo.getId());
+				t += vo.getTotal();
+				if (t > reduce){
+					break;
+				}
+			}
+
+		}
+		twoTreeVO.setIds(ids);
+		return twoTreeVO;
 	}
 
 	@Override
@@ -1432,13 +1476,15 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 	}
 
 	//递归方法
-	private void gatherSortNode(List<InspectTreeVO>list, List<Long> ids){
+	private void gatherSortNode(List<InspectTreeVO>list, List<InspectTreeVO> list2){
 		for (InspectTreeVO vo : list) {
 			if (vo.getChildren().size() == 0){
-				ids.add(vo.getId());
+				if (vo.getTotal() > 0) {
+					list2.add(vo);
+				}
 				continue;
 			}else {
-				gatherSortNode(vo.getChildren(), ids);
+				gatherSortNode(vo.getChildren(), list2);
 			}
 		}
 	}

+ 11 - 2
blade-service/blade-meter/src/main/java/org/springblade/meter/controller/MeterTreeController.java

@@ -29,6 +29,7 @@ import org.springblade.system.entity.Dict;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
 
 import java.util.*;
 import java.util.stream.Collectors;
@@ -586,8 +587,6 @@ public class MeterTreeController extends BladeController {
                             .eq(MeterTreeProject::getParentId, projectNode.getId())
                             .eq(MeterTreeProject::getStatus, 1)
                     ));
-                } else {
-                    throw new ServiceException("未获取到项目计量单元信息");
                 }
             }
         }
@@ -830,4 +829,14 @@ public class MeterTreeController extends BladeController {
         return R.data(null);
     }
 
+    @PostMapping("/contract/import")
+    @ApiOperationSupport(order = 33)
+    @ApiOperation(value = "合同段计量单元导入", notes = "传入当前选择的节点id,excel文件file")
+    public R<Object> contractTreeNodeImport(@RequestParam String id, MultipartFile file) {
+        if (ObjectUtil.isNotEmpty(id) && meterTreeContractService.contractTreeNodeImport(id, file)) {
+            return R.success("操作成功");
+        }
+        return R.fail("操作失败");
+    }
+
 }

+ 30 - 11
blade-service/blade-meter/src/main/java/org/springblade/meter/controller/TaskController.java

@@ -374,8 +374,8 @@ public class TaskController extends BladeController {
             } else if (approvalDTO.getType().equals(4)) {
                 /*==================== 变更令 ====================*/
                 Set<String> aopParamsSet = new HashSet<>();
+                Long taskId = SnowFlakeUtil.getId();
                 for (String id : approvalDTO.getPeriodId().split(",")) {
-                    Long taskId = SnowFlakeUtil.getId();
                     /*获取变更令信息*/
                     ChangeTokenForm changeTokenForm = changeTokenFormService.getById(id);
                     if (changeTokenForm != null) {
@@ -412,23 +412,30 @@ public class TaskController extends BladeController {
                                 }
                                 changeTokenInventoryServiceTask.saveBatch(changeTokenInventoryTasks, 1000); //清单
 
-                                /*构造创建审批任务*/
-                                try {
-                                    this.buildTaskInfo(taskId, approvalDTO, aopParamsSet, 4);
-                                } catch (Exception e) {
-                                    throw new ServiceException("创建审批任务异常,操作失败:" + e.getMessage());
+                                /*获取变更令的附件信息*/
+                                List<AttachmentForm> attachmentForms = attachmentFormService.getBaseMapper().selectList(Wrappers.<AttachmentForm>lambdaQuery()
+                                        .in(AttachmentForm::getMasterId, changeTokenForm.getId())
+                                        .eq(AttachmentForm::getContractId, approvalDTO.getContractId())
+                                        .eq(AttachmentForm::getProjectId, approvalDTO.getProjectId()));
+                                List<AttachmentFormTask> attachmentFormTasks = BeanUtil.copyProperties(attachmentForms, AttachmentFormTask.class);
+                                for (AttachmentFormTask attachmentFormTask : attachmentFormTasks) {
+                                    attachmentFormTask.setTaskId(taskId);
                                 }
+                                /*复制变更令的附件信息VO*/
+                                attachmentFormServiceTask.saveBatch(attachmentFormTasks, 1000);
 
                                 /*修改变更令原始数据的审批状态=待审批*/
                                 changeTokenFormService.update(Wrappers.<ChangeTokenForm>lambdaUpdate()
                                         .set(ChangeTokenForm::getApproveStatus, 1)
                                         .eq(ChangeTokenForm::getId, id));
+
                                 /*复制数据的审批状态=待审批*/
                                 changeTokenFormServiceTask.update(Wrappers.<ChangeTokenFormTask>lambdaUpdate()
                                         .set(ChangeTokenFormTask::getApproveStatus, 1)
                                         .eq(ChangeTokenFormTask::getTaskId, taskId)
                                         .eq(ChangeTokenFormTask::getId, id));
                             }
+
                         } else {
                             throw new ServiceException("【" + changeTokenForm.getChangeName() + "】变更令下不存在变更申请部位,操作失败");
                         }
@@ -436,6 +443,14 @@ public class TaskController extends BladeController {
                         throw new ServiceException("未获取到当前变更令信息,操作失败");
                     }
                 }
+
+                /*构造创建审批任务*/
+                try {
+                    this.buildTaskInfo(taskId, approvalDTO, aopParamsSet, 4);
+                } catch (Exception e) {
+                    throw new ServiceException("创建审批任务异常,操作失败:" + e.getMessage());
+                }
+
                 return R.data(200, aopParamsSet, "操作成功");
             }
         }
@@ -1291,26 +1306,30 @@ public class TaskController extends BladeController {
 
             obj.setProjectId(Long.parseLong(task.getProjectId()));
             obj.setContractId(Long.parseLong(task.getContractId()));
-            if (inventoryFormApplyServiceTask.updateById(obj)) {
+
+            /*需要修改原始数据(统计累计计量量的时候需要查原始表数据)*/
+            InventoryFormApply inventoryFormApply = BeanUtil.copyProperties(obj, InventoryFormApply.class);
+
+            if (inventoryFormApplyServiceTask.updateById(obj) && inventoryFormApplyService.updateById(inventoryFormApply)) {
                 MiddleMeterApplyTask middleMeterApplyTask = middleMeterApplyServiceTask.getById(inventoryFormApplyTask.getMiddleMeterId());
                 if (middleMeterApplyTask != null) {
 
                     /*清单信息*/
                     List<MeterInventoryVO> formToTask = middleMeterApplyMapper.getFormCopy(middleMeterApplyTask.getId(), middleMeterApplyTask.getContractId(), middleMeterApplyTask.getContractUnitId());
 
-                    BigDecimal totalSum = BigDecimal.ZERO;
+                    BigDecimal totalSumMoney = BigDecimal.ZERO;
                     for (MeterInventoryVO meterInventoryVO : formToTask) {
                         BigDecimal currentMeterTotal = meterInventoryVO.getCurrentMeterTotal();
                         BigDecimal currentPrice = meterInventoryVO.getCurrentPrice();
                         BigDecimal product = currentMeterTotal.multiply(currentPrice);
-                        totalSum = totalSum.add(product);
+                        totalSumMoney = totalSumMoney.add(product);
                     }
 
                     String updateSql = "UPDATE s_middle_meter_apply_task SET meter_money = ? WHERE id = ?";
-                    Object[] params = {totalSum, inventoryFormApplyTask.getMiddleMeterId()};
+                    Object[] params = {totalSumMoney, inventoryFormApplyTask.getMiddleMeterId()};
                     jdbcTemplate.update(updateSql, params);
 
-                    return R.data(200, totalSum, "操作成功");
+                    return R.data(200, totalSumMoney, "操作成功");
                 }
             }
         }

+ 2 - 0
blade-service/blade-meter/src/main/java/org/springblade/meter/mapper/InventoryFormMeterMapper.java

@@ -35,4 +35,6 @@ public interface InventoryFormMeterMapper extends BaseMapper<InventoryFormMeter>
     List<Long> getNodeAllForm(@Param("nodeId") Long nodeId);
     ContractInventoryForm dadainfo(@Param("forid") long forid);
 
+    void batchInsert(List<InventoryFormMeter> inventoryFormMeters);
+
 }

+ 18 - 2
blade-service/blade-meter/src/main/java/org/springblade/meter/mapper/InventoryFormMeterMapper.xml

@@ -18,14 +18,30 @@
         <result column="contract_meter_id" property="contractMeterId"/>
         <result column="build_picture_total" property="buildPictureTotal"/>
     </resultMap>
+
+    <insert id="batchInsert" parameterType="java.util.List">
+        INSERT INTO s_inventory_form_meter (id,
+        project_id,contract_id,contract_form_id,contract_meter_id,build_picture_total,
+        change_build_picture_total,build_picture_money,change_build_picture_money,create_user,update_user,create_dept)
+        VALUES
+        <foreach collection="list" item="item" separator=",">
+            (#{item.id}, #{item.projectId},#{item.contractId}, #{item.contractFormId},#{item.contractMeterId},
+            #{item.buildPictureTotal},#{item.changeBuildPictureTotal},#{item.buildPictureMoney},
+            #{item.changeBuildPictureMoney},#{item.createUser},#{item.updateUser},#{item.createDept})
+        </foreach>
+    </insert>
+
     <select id="getNodeAllForm" resultType="java.lang.Long">
         select contract_form_id
         from s_inventory_form_meter
-        where contract_meter_id = #{nodeId} and is_deleted = 0
+        where contract_meter_id = #{nodeId}
+          and is_deleted = 0
     </select>
 
     <select id="dadainfo" resultType="org.springblade.meter.entity.ContractInventoryForm">
-        select * from s_contract_inventory_form where id=#{forid} ;
+        select *
+        from s_contract_inventory_form
+        where id = #{forid};
     </select>
 
 </mapper>

+ 4 - 0
blade-service/blade-meter/src/main/java/org/springblade/meter/service/MeterTreeContractService.java

@@ -6,6 +6,7 @@ import org.springblade.meter.entity.MeterTreeContract;
 import org.springblade.meter.entity.MeterTreeProject;
 import org.springblade.meter.vo.ChangeNodeVO;
 import org.springblade.meter.vo.MeterTreeContractVO;
+import org.springframework.web.multipart.MultipartFile;
 
 import java.util.List;
 
@@ -23,4 +24,7 @@ public interface MeterTreeContractService extends BaseService<MeterTreeContract>
 
     //异步重新计算节点金额,和修改施工图号
     void asyncCalculateNodeMoney(List<ChangeNodeVO> vos);
+
+    boolean contractTreeNodeImport(String id, MultipartFile file);
+
 }

+ 220 - 5
blade-service/blade-meter/src/main/java/org/springblade/meter/service/impl/MeterTreeContractServiceImpl.java

@@ -3,6 +3,9 @@ package org.springblade.meter.service.impl;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.AllArgsConstructor;
 import org.apache.commons.lang.StringUtils;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.mp.base.BaseServiceImpl;
@@ -11,21 +14,29 @@ import org.springblade.core.tool.utils.BeanUtil;
 import org.springblade.core.tool.utils.ObjectUtil;
 import org.springblade.meter.dto.MeterTreeContractSaveBatchDTO;
 import org.springblade.meter.dto.MeterTreeContractSaveDTO;
+import org.springblade.meter.entity.ContractInventoryForm;
 import org.springblade.meter.entity.InventoryFormMeter;
 import org.springblade.meter.entity.MeterTreeContract;
 import org.springblade.meter.entity.MeterTreeProject;
+import org.springblade.meter.mapper.InventoryFormMeterMapper;
 import org.springblade.meter.mapper.MeterTreeContractMapper;
 import org.springblade.meter.mapper.MeterTreeProjectMapper;
 import org.springblade.meter.service.MeterTreeContractService;
 import org.springblade.meter.vo.ChangeNodeVO;
 import org.springblade.meter.vo.MeterTreeContractVO;
+import org.springblade.system.entity.Dict;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
 
+import java.io.IOException;
+import java.io.InputStream;
 import java.math.BigDecimal;
 import java.util.*;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 @Service
@@ -34,6 +45,7 @@ public class MeterTreeContractServiceImpl extends BaseServiceImpl<MeterTreeContr
 
     private final JdbcTemplate jdbcTemplate;
     private final MeterTreeProjectMapper meterTreeProjectMapper;
+    private final InventoryFormMeterMapper inventoryFormMeterMapper;
 
     @Override
     public Integer selectMaxSort(Long parentId) {
@@ -510,24 +522,26 @@ public class MeterTreeContractServiceImpl extends BaseServiceImpl<MeterTreeContr
 
     /**
      * 获取所有子节点金额
+     *
      * @param vo
      */
     @Override
     public void getAllChildNodeMoney(MeterTreeContractVO vo) {
-        MeterTreeContract m = baseMapper.getAllChildNodeMoney(vo.getContractId(),vo.getId());
+        MeterTreeContract m = baseMapper.getAllChildNodeMoney(vo.getContractId(), vo.getId());
         vo.setBuildPictureMoney(m.getBuildPictureMoney());
         vo.setChangeMoney(m.getChangeMoney());
     }
 
     /**
      * 异步重新计算节点金额,和修改施工图号
+     *
      * @param vos
      */
     @Override
 //    @Async
     public void asyncCalculateNodeMoney(List<ChangeNodeVO> vos) {
         for (ChangeNodeVO vo : vos) {
-            if (StringUtils.isBlank(vo.getContractPicture())){
+            if (StringUtils.isBlank(vo.getContractPicture())) {
                 vo.setContractPicture("");
             }
         }
@@ -540,16 +554,170 @@ public class MeterTreeContractServiceImpl extends BaseServiceImpl<MeterTreeContr
                 .collect(Collectors.groupingBy(l -> l.getContractMeterId(),
                         Collectors.mapping(InventoryFormMeter::getChangeBuildPictureMoney,
                                 Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))));
-        list.stream().forEach(l->{
+        list.stream().forEach(l -> {
             String picture = map.get(l.getId());
-            l.setContractPicture(StringUtils.isBlank(picture)?"":picture);
+            l.setContractPicture(StringUtils.isBlank(picture) ? "" : picture);
             //统计节点下所有分解的表单的总金额
-            l.setChangeMoney(decimalMap.get(l.getId())==null?BigDecimal.ZERO:decimalMap.get(l.getId()));
+            l.setChangeMoney(decimalMap.get(l.getId()) == null ? BigDecimal.ZERO : decimalMap.get(l.getId()));
         });
         //拼接SQL修改合同图号和重新计算的金额
         baseMapper.batchUpdateById(list);
     }
 
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public boolean contractTreeNodeImport(String id, MultipartFile file) {
+        MeterTreeContract meterTreeContract = baseMapper.selectById(id);
+        if (meterTreeContract.getAncestor().split(",").length > 3) {
+            throw new ServiceException("只能从前三层节点开始导入,操作失败");
+        }
+        List<MeterTreeContract> rootNodesImport = new ArrayList<>();
+        if (meterTreeContract.getParentId().equals(0L) && meterTreeContract.getAncestor().equals("0")) {
+            /*根节点导入,获取下一层级节点*/
+            rootNodesImport = baseMapper.selectList(Wrappers.<MeterTreeContract>lambdaQuery().eq(MeterTreeContract::getParentId, id).isNotNull(MeterTreeContract::getNodeCode));
+        } else {
+            /*非根节点导入,获取当前节点*/
+            if (ObjectUtil.isEmpty(meterTreeContract.getNodeCode())) {
+                throw new ServiceException("当前选择导入的工程编号为空,操作失败");
+            }
+            rootNodesImport.add(meterTreeContract);
+        }
+
+        List<MeterTreeContract> resultNodeList = new ArrayList<>();
+        List<InventoryFormMeter> resultFormList = new ArrayList<>();
+        List<Map<String, String>> parseExcelFileToList = this.parseExcelFile(file);
+        Map<String, String> meterStakeTypeMaps = jdbcTemplate.query("SELECT dict_key,dict_value FROM blade_dict WHERE is_deleted = 0 AND code = 'meter_stake_type'", new BeanPropertyRowMapper<>(Dict.class)).stream().collect(Collectors.toMap(Dict::getDictValue, Dict::getDictKey));
+        Map<String, ContractInventoryForm> contractInventoryFormMaps = jdbcTemplate.query("SELECT id,change_price,form_number FROM s_contract_inventory_form WHERE is_deleted = 0 AND contract_id = " + meterTreeContract.getContractId(), new BeanPropertyRowMapper<>(ContractInventoryForm.class)).stream().collect(Collectors.toMap(ContractInventoryForm::getFormNumber, Function.identity()));
+        Map<String, List<Map<String, String>>> rootCodeMaps = parseExcelFileToList.stream()
+                .collect(Collectors.groupingBy(
+                        map -> map.get("工程编号"),
+                        LinkedHashMap::new,
+                        Collectors.toList()
+                ));
+        for (MeterTreeContract treeContract : rootNodesImport) {
+            List<Map<String, String>> projectCodeGroup = rootCodeMaps.getOrDefault(treeContract.getNodeCode(), null);
+            if (ObjectUtil.isNotEmpty(projectCodeGroup)) {
+                Map<String, List<Map<String, String>>> nodeCodeGroup = projectCodeGroup.stream()
+                        .collect(Collectors.groupingBy(
+                                map -> map.get("节点编号"),
+                                LinkedHashMap::new,
+                                Collectors.toList()
+                        ));
+                int sort = 1;
+                for (Map.Entry<String, List<Map<String, String>>> listEntry : nodeCodeGroup.entrySet()) {
+                    String nodeCode = listEntry.getKey();
+                    List<Map<String, String>> rows = listEntry.getValue().stream()
+                            .sorted(Comparator.comparing(map -> {
+                                String formCode = map.get("清单编号");
+                                return formCode == null ? "" : formCode;
+                            })).collect(Collectors.toList());
+                    long nullFormCodeCount = rows.stream()
+                            .filter(map -> ObjectUtil.isEmpty(map.get("清单编号")))
+                            .count();
+                    if (nullFormCodeCount > 1) {
+                        throw new RuntimeException("节点编号【" + nodeCode + "】存在多条清单编号为空的数据,请确认是否只有一条");
+                    }
+
+                    MeterTreeContract obj = new MeterTreeContract();
+                    Long nodeId = SnowFlakeUtil.getId();
+                    BigDecimal money = BigDecimal.ZERO;
+                    BigDecimal moneyChange = BigDecimal.ZERO;
+
+                    for (Map<String, String> map : rows) {
+                        String currCode = map.get("节点编号");
+                        if (currCode.equals(nodeCode)) {
+                            String formCode = map.get("清单编号");
+                            String nodeName = map.get("工程名称");
+                            String buildPictureTotal = map.get("施工图数量");
+                            String stakeType = map.get("桩号类型");
+                            String startStake = map.get("起始桩号");
+                            String endStake = map.get("结束桩号");
+                            String contractPicture = map.get("合同图号");
+                            String remarks = map.get("备注");
+
+                            //节点
+                            if (ObjectUtil.isEmpty(formCode)) {
+                                obj.setId(nodeId);
+                                obj.setParentId(treeContract.getId());
+                                obj.setAncestor(treeContract.getAncestor() + "," + obj.getParentId());
+                                obj.setNodeName(nodeName);
+                                obj.setNodeCode(currCode);
+                                obj.setUpdateStatus(0);
+                                obj.setSort(sort);
+                                if (ObjectUtil.isNotEmpty(stakeType)) {
+                                    String upperCase = stakeType.toUpperCase();
+                                    String key = meterStakeTypeMaps.getOrDefault(upperCase, null);
+                                    if (key != null) {
+                                        obj.setStakeType(Integer.parseInt(key));
+                                    }
+                                }
+                                obj.setStartStake(startStake);
+                                obj.setEndStake(endStake);
+                                obj.setContractPicture(contractPicture);
+                                obj.setRemarks(remarks);
+
+                                obj.setTemplateId(treeContract.getTemplateId());
+                                obj.setProjectId(treeContract.getProjectId());
+                                obj.setContractId(treeContract.getContractId());
+
+                                obj.setDataSourceType(4); //导入
+
+                            } else {
+                                //清单
+                                ContractInventoryForm contractInventoryForm = contractInventoryFormMaps.getOrDefault(formCode, null);
+                                if (contractInventoryForm != null) {
+                                    InventoryFormMeter objForm = new InventoryFormMeter();
+                                    objForm.setId(SnowFlakeUtil.getId());
+                                    objForm.setProjectId(treeContract.getProjectId());
+                                    objForm.setContractId(treeContract.getContractId());
+
+                                    if (ObjectUtil.isNotEmpty(SecureUtil.getUser())) {
+                                        objForm.setCreateUser(SecureUtil.getUserId());
+                                        objForm.setUpdateUser(SecureUtil.getUserId());
+                                        if (SecureUtil.getDeptId().contains(",")) {
+                                            objForm.setCreateDept(Long.parseLong(SecureUtil.getDeptId().split(",")[0]));
+                                        } else {
+                                            objForm.setCreateDept(Long.parseLong(SecureUtil.getDeptId()));
+                                        }
+                                    }
+
+                                    objForm.setContractMeterId(nodeId);
+                                    objForm.setContractFormId(contractInventoryForm.getId());
+
+                                    objForm.setBuildPictureTotal(this.parseString(buildPictureTotal));
+                                    objForm.setChangeBuildPictureTotal(objForm.getBuildPictureTotal());
+                                    objForm.setBuildPictureMoney(objForm.getBuildPictureTotal().multiply(contractInventoryForm.getChangePrice())); //数量*变更后单价
+                                    objForm.setChangeBuildPictureMoney(objForm.getBuildPictureMoney());
+
+                                    /*计量单元节点金额相关累加*/
+                                    money = money.add(objForm.getBuildPictureMoney());
+                                    moneyChange = moneyChange.add(objForm.getChangeBuildPictureMoney());
+
+                                    resultFormList.add(objForm);
+                                }
+                            }
+                        }
+                    }
+                    obj.setBuildPictureMoney(money);
+                    obj.setChangeMoney(moneyChange);
+                    resultNodeList.add(obj);
+                    sort++;
+                }
+            }
+        }
+        if (resultNodeList.size() > 0) {
+            this.saveBatch(resultNodeList, 1000);
+            if (resultFormList.size() > 0) {
+                inventoryFormMeterMapper.batchInsert(resultFormList);
+                /*for (InventoryFormMeter inventoryFormMeter : resultFormList) {
+                    inventoryFormMeterMapper.insert(inventoryFormMeter);
+                }*/
+            }
+            return true;
+        }
+        return false;
+    }
+
     /**
      * 获取对应的父级的ancestor字段
      *
@@ -638,4 +806,51 @@ public class MeterTreeContractServiceImpl extends BaseServiceImpl<MeterTreeContr
         return false;
     }
 
+    private List<Map<String, String>> parseExcelFile(MultipartFile file) {
+        List<Map<String, String>> result = new ArrayList<>();
+        try (InputStream inputStream = file.getInputStream()) {
+            Workbook workbook;
+            if (Objects.requireNonNull(file.getOriginalFilename()).toLowerCase().endsWith(".xls")) {
+                workbook = new HSSFWorkbook(inputStream);
+            } else if (file.getOriginalFilename().toLowerCase().endsWith(".xlsx")) {
+                workbook = new XSSFWorkbook(inputStream);
+            } else {
+                throw new ServiceException("Unsupported Excel file format");
+            }
+            Sheet sheet = workbook.getSheetAt(0);
+            Row headerRow = sheet.getRow(0);
+            int columnCount = headerRow.getLastCellNum();
+            Iterator<Row> rowIterator = sheet.iterator();
+            rowIterator.next();
+            while (rowIterator.hasNext()) {
+                Row currentRow = rowIterator.next();
+                Map<String, String> rowMap = new LinkedHashMap<>();
+                for (int columnIndex = 0; columnIndex < columnCount; columnIndex++) {
+                    Cell currentCell = currentRow.getCell(columnIndex, Row.MissingCellPolicy.CREATE_NULL_AS_BLANK);
+                    currentCell.setCellType(CellType.STRING);
+                    String headerValue = headerRow.getCell(columnIndex).getStringCellValue();
+                    String cellValue = currentCell.getStringCellValue();
+                    rowMap.put(headerValue, cellValue);
+                }
+                result.add(rowMap);
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+            throw new ServiceException("excel解析失败,errorMsg:" + e.getMessage());
+        }
+        return result;
+    }
+
+    private BigDecimal parseString(String value) {
+        if (value == null || value.trim().isEmpty()) {
+            return BigDecimal.ZERO;
+        }
+        try {
+            return new BigDecimal(value.trim());
+        } catch (NumberFormatException e) {
+            e.printStackTrace();
+            return BigDecimal.ZERO;
+        }
+    }
+
 }

+ 19 - 1
blade-service/blade-user/src/main/java/org/springblade/system/user/controller/UserController.java

@@ -182,9 +182,27 @@ public class UserController {
     @PostMapping("/submit2")
     @ApiOperationSupport(order = 4)
     @ApiOperation(value = "新增2", notes = "传入UserDTO")
-    @PreAuth(RoleConstant.HAS_ROLE_ADMIN)
+  //  @PreAuth(RoleConstant.HAS_ROLE_ADMIN)
     public R submitTow(@Valid @RequestBody UserDTO user) {
         CacheUtil.clear(USER_CACHE);
+        // 为第三方系统
+        if(user.getSysId().equals("30")){
+            user.setUserType("1,2,3");
+            user.setPassword("123456");
+            user.setPlaintextPassword("123456");
+            user.setTenantId("000000");
+            user.setDeptId("1592394131177873410");
+            user.setStatus(1);
+            user.setSysType(2);
+            List<SaveUserInfoByProjectDTO> projectAndUserList = new ArrayList<>();
+            SaveUserInfoByProjectDTO data= new SaveUserInfoByProjectDTO();
+            data.setContractId("1714919227250950146");
+            data.setProjectId("1612329251049537537");
+            data.setRoleId("1537248158277914626");
+            projectAndUserList.add(data);
+            user.setProjectAndUserList(projectAndUserList);
+        }
+
         return R.status(userService.submit2(user));
     }
 

+ 92 - 76
blade-service/blade-user/src/main/java/org/springblade/system/user/mapper/UserMapper.xml

@@ -129,82 +129,98 @@
     </select>
 
     <select id="selectInformationQueryPageTwo" resultType="org.springblade.business.entity.InformationQuery">
-        select
-        query.pdf_trial_url,
-        query.pdf_trial_url_position,
-        query.wbs_id,
-        query.id,
-        query.name,
-        query.number,
-        query.create_time,
-        query.status,
-        query.report_number,
-        query.file_user_id_and_name,
-        query.pdf_url,
-        query.e_visa_pdf_url,
-        query.task_id,
-        query.sj_record_ids
-        from
-        (
-        select
-        iq.pdf_trial_url_position,
-        iq.pdf_trial_url,
-        iq.sort,
-        iq.id,
-        iq.name,
-        iq.number,
-        iq.create_time,
-        iq.status,
-        (case iq.STATUS when 0 THEN null else t.batch end) as report_number,
-        iq.file_user_id_and_name,
-        date_format(iq.create_time,'%Y-%m-%d') as createTimes,
-        iq.pdf_url,
-        iq.e_visa_pdf_url,
-        iq.wbs_id,
-        t.id as task_id,
-        iq.sj_record_ids
-        from u_information_query iq left join (select * from u_task k where k.status!=3 and k.project_id =
-        #{query.projectId} group by
-        form_data_id) t on iq.id = t.form_data_id and t.is_deleted = 0
-        where
-        iq.is_deleted = 0
-        and iq.classify = #{query.classify}
-        and iq.contract_id = #{query.contractId}
-        <if test="query.taskStatus != null and query.taskStatus != ''">
-            <choose>
-                <when test="query.taskStatus == 0">
-                    and (iq.status = 0 or iq.status = 3)
-                </when>
-                <otherwise>
-                    and iq.status = #{query.taskStatus}
-                </otherwise>
-            </choose>
-        </if>
-        <if test="query.sourceType != null and query.sourceType != ''">and iq.source_type = #{query.sourceType}</if>
-        <if test="query.reportNumber != null and query.reportNumber != ''">and t.batch = #{query.reportNumber}</if>
-        <if test="query.fileUserIdAndName != null and query.fileUserIdAndName != ''">and iq.file_user_id_and_name like
-            concat('%',#{query.fileUserIdAndName},'%')
-        </if>
-        <if test="query.queryValue != null and query.queryValue != ''">and (iq.name like
-            concat('%',#{query.queryValue},'%') OR iq.number like concat('%',#{query.queryValue},'%'))
-        </if>
-        <if test="query.firstTitle != null and query.firstTitle != ''">and iq.type = 3</if>
-        <if test="query.firstTitle == null or query.firstTitle == ''">and iq.type != 3</if>
-        <if test="query.wbsIds != null">
-            and iq.wbs_id in
-            <foreach collection="query.wbsIds" item="wbsIdc" open="(" separator="," close=")">
-                #{wbsIdc}
-            </foreach>
-        </if>
-        ) AS query
-        where
-        1 = 1
-        <if test="query.reportNumber != null and query.reportNumber != ''">and report_number = #{query.reportNumber}
-        </if>
-        <if test="query.startTime != null and query.startTime != '' and query.endTime != null and query.endTime != ''">
-            and query.createTimes between #{query.startTime} and #{query.endTime}
-        </if>
-        order by create_time desc
+        SELECT
+            query.pdf_trial_url,
+            query.pdf_trial_url_position,
+            query.wbs_id,
+            query.id,
+            query.name,
+            query.number,
+            query.create_time,
+            query.status,
+            query.report_number,
+            query.file_user_id_and_name,
+            query.pdf_url,
+            query.e_visa_pdf_url,
+            query.task_id,
+            query.sj_record_ids
+        FROM
+            (
+            SELECT
+                iq.pdf_trial_url_position,
+                iq.pdf_trial_url,
+                iq.sort,
+                iq.id,
+                iq.name,
+                iq.number,
+                iq.create_time,
+                date_format(iq.create_time,'%Y-%m-%d') AS createTimes,
+                iq.status,
+                (CASE iq.STATUS WHEN 0 THEN NULL ELSE t.batch END) AS report_number,
+                iq.file_user_id_and_name,
+                iq.pdf_url,
+                iq.e_visa_pdf_url,
+                iq.wbs_id,
+                t.id AS task_id,
+                iq.sj_record_ids
+            FROM
+                 u_information_query iq
+                LEFT JOIN
+                ( SELECT form_data_id, batch, id, is_deleted FROM u_task k
+                WHERE k.STATUS != 3 AND k.contract_id = #{query.contractId}
+                ORDER BY k.create_time DESC LIMIT 1 ) t ON iq.id = t.form_data_id
+                AND t.is_deleted = 0
+
+            WHERE
+                iq.is_deleted = 0
+            AND iq.classify = #{query.classify}
+            AND iq.contract_id = #{query.contractId}
+
+                <if test="query.taskStatus != null and query.taskStatus != ''">
+                    <choose>
+                        <when test="query.taskStatus == 0">
+                            AND (iq.status = 0 OR iq.status = 3)
+                        </when>
+                        <otherwise>
+                            AND iq.status = #{query.taskStatus}
+                        </otherwise>
+                    </choose>
+                </if>
+                <if test="query.sourceType != null and query.sourceType != ''">
+                    AND iq.source_type = #{query.sourceType}
+                </if>
+                <if test="query.reportNumber != null and query.reportNumber != ''">
+                    AND t.batch = #{query.reportNumber}
+                </if>
+                <if test="query.fileUserIdAndName != null and query.fileUserIdAndName != ''">
+                    AND iq.file_user_id_and_name LIKE concat('%',#{query.fileUserIdAndName},'%')
+                </if>
+                <if test="query.queryValue != null and query.queryValue != ''">
+                    AND (iq.name LIKE concat('%',#{query.queryValue},'%') OR iq.number LIKE concat('%',#{query.queryValue},'%'))
+                </if>
+                <if test="query.firstTitle != null and query.firstTitle != ''">
+                    AND iq.type = 3
+                </if>
+                <if test="query.firstTitle == null or query.firstTitle == ''">
+                    AND iq.type != 3
+                </if>
+                <if test="query.wbsIds != null">
+                    AND iq.wbs_id IN
+                    <foreach collection="query.wbsIds" item="wbsIdc" open="(" separator="," close=")">
+                        #{wbsIdc}
+                    </foreach>
+                </if>
+            ) AS query
+
+        WHERE 1 = 1
+
+            <if test="query.reportNumber != null and query.reportNumber != ''">
+                AND report_number = #{query.reportNumber}
+            </if>
+            <if test="query.startTime != null and query.startTime != '' and query.endTime != null and query.endTime != ''">
+                AND query.createTimes BETWEEN #{query.startTime} AND #{query.endTime}
+            </if>
+
     </select>
 
 </mapper>

+ 103 - 133
blade-service/blade-user/src/main/java/org/springblade/system/user/service/impl/UserServiceImpl.java

@@ -1,5 +1,7 @@
 package org.springblade.system.user.service.impl;
 
+import cn.hutool.core.date.StopWatch;
+import cn.hutool.log.StaticLog;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.nacos.common.utils.StringUtils;
@@ -948,7 +950,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
     /**
      * 定时清理本地缓存信息,不在批量电签时删除,批量电签是多线程,会一直删除,导致缓存基本不生效(已废除Redis缓存,走本地缓存不需要Redis)
      */
-    @Scheduled(fixedRate = 120000) //每2分钟执行一次
+    @Scheduled(fixedRate = 180000) //每3分钟执行一次
     public void clearContractLocalCacheAndRedisCache() {
         //获取锁
         ReentrantLock lock = new ReentrantLock();
@@ -968,7 +970,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
         } finally {
             //释放锁
             lock.unlock();
-            _logger.info("定时执行任务:{clearContractLocalCacheAndRedisCache} 完成 ... ");
+            _logger.info("定时执行任务:{clearContractLocalCacheAndRedisCache} 完成 ");
         }
     }
 
@@ -996,7 +998,9 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
             do {
                 offset = (pageNumber - 1) * pageSize;
                 nodesAllPage = jdbcTemplate.query(
-                        "SELECT p_key_id, id, parent_id FROM m_wbs_tree_contract " +
+                        "SELECT p_key_id,id,parent_id " +
+                                ",sort,create_time,IFNULL(if(LENGTH (trim(full_name)) > 0, full_name, node_name), node_name) AS fullName " +
+                                "FROM m_wbs_tree_contract " +
                                 "WHERE type = 1 " +
                                 "AND status = 1 " +
                                 "AND is_deleted = 0 " +
@@ -1241,7 +1245,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
         if (ObjectUtil.isEmpty(contract)) {
             throw new ServiceException("获取合同段信息失败");
         }
-        vo.setClassify(org.apache.commons.lang.StringUtils.isNotEmpty(vo.getClassifyType()) ? new Integer(vo.getClassifyType()) : contract.getContractType() == null ? 1 : new Integer("1").equals(contract.getContractType()) ? 1 : 2);
+        vo.setClassify(StringUtils.isNotEmpty(vo.getClassifyType()) ? new Integer(vo.getClassifyType()) : contract.getContractType() == null ? 1 : new Integer("1").equals(contract.getContractType()) ? 1 : 2);
 
         Query query = new Query();
         query.setSize(vo.getSize());
@@ -1251,18 +1255,18 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
         submitNodeKeyIds.add(vo.getWbsId().toString());
         WbsTreeContract node = jdbcTemplate.query("SELECT * FROM m_wbs_tree_contract WHERE p_key_id = " + vo.getWbsId(), new BeanPropertyRowMapper<>(WbsTreeContract.class)).stream().findAny().orElse(null);
         if (node == null) {
-            if (org.apache.commons.lang.StringUtils.isEmpty(vo.getContractIdRelation())) {
+            if (StringUtils.isEmpty(vo.getContractIdRelation())) {
                 return null;
             }
             //监理
             node = jdbcTemplate.query("SELECT * FROM m_wbs_tree_contract WHERE id = " + vo.getWbsId() + " AND contract_id = " + vo.getContractIdRelation(), new BeanPropertyRowMapper<>(WbsTreeContract.class)).stream().findAny().orElse(null);
         }
 
+        List<Long> childNodesPkeyIds = new ArrayList<>();
+        List<Long> lowestNodesPkeyIds = new ArrayList<>();
+
         if (node != null) {
-            List<WbsTreeContractVO8> lowestNodes = new ArrayList<>();
-            List<QueryProcessDataVO> queryDataResult = new ArrayList<>();
             if (!new Integer("6").equals(node.getNodeType()) && !Arrays.asList("1,2,3,4".split(",")).contains(node.getMajorDataType() + "")) {
-                //TODO(暂不响应第一层根节点、第二层数据,数据量过多会导致响应超时)
                 if (node.getParentId() == 0) {
                     throw new ServiceException("请从第三层级节点开始进行检索");
                 } else {
@@ -1270,53 +1274,24 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
                     if (wbsTreeContract != null && wbsTreeContract.getParentId().equals(0L)) {
                         throw new ServiceException("请从第三层级节点开始进行检索");
                     }
-
-                    WbsTreeContractVO8 vo8 = BeanUtil.copyProperties(node, WbsTreeContractVO8.class);
-                    this.lowestNodesRecursively(lowestNodes, Collections.singleton(vo8), node.getContractId());
-
-                    List<String> pKeyIds = lowestNodes.stream().map(WbsTreeContractVO8::getPKeyId).map(String::valueOf).collect(Collectors.toList());
-                    List<List<String>> partition = Lists.partition(pKeyIds, 1000);
-                    for (List<String> items : partition) {
-                        String sql = "SELECT wtc.id AS treeId,wtc.p_key_id AS primaryKeyId,wtc.ancestors AS ancestors,wtc.major_data_type AS majorDataType," +
-                                " wtc.node_type AS nodeType,IFNULL(if(length(trim(wtc.full_name)) > 0, wtc.full_name, wtc.node_name), wtc.node_name) AS title," +
-                                " wtc.parent_id AS parentId,uiq.id AS informationQueryId,IFNULL(uiq.status, 0) AS status,uiq.type AS queryType," +
-                                " CASE WHEN uiq.pdf_trial_url IS NULL THEN FALSE ELSE TRUE end AS isExperiment FROM m_wbs_tree_contract AS wtc" +
-                                " LEFT JOIN u_information_query AS uiq ON wtc.p_key_id = uiq.wbs_id AND uiq.classify = " + contract.getContractType() +
-                                " AND uiq.is_deleted = 0 AND wtc.is_deleted = 0 AND wtc.status = 1 WHERE wtc.p_key_id IN (" + org.apache.commons.lang.StringUtils.join(items, ",") + ")";
-                        List<QueryProcessDataVO> result = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(QueryProcessDataVO.class));
-                        if (result.size() > 0) {
-                            queryDataResult.addAll(result);
-                        }
-                    }
-                }
-
-                //首件
-                if (queryDataResult.size() > 0) {
-                    if (org.apache.commons.lang.StringUtils.isNotEmpty(vo.getIsFirst())) {
-                        if (org.apache.commons.lang.StringUtils.isNotEmpty(vo.getFirstTitle())) {
-                            queryDataResult = queryDataResult.stream().filter(qdr -> "3".equals(qdr.getQueryType())).collect(Collectors.toList());
-                        } else {
-                            List<String> treeIds = queryDataResult.stream().map(QueryProcessDataVO::getPrimaryKeyId).distinct().collect(Collectors.toList());
-                            List<TreeContractFirst> firstList = jdbcTemplate.query("SELECT * FROM u_tree_contract_first WHERE is_deleted = 0 AND wbs_node_id IN (" + org.apache.commons.lang.StringUtils.join(treeIds, ",") + ")", new BeanPropertyRowMapper<>(TreeContractFirst.class));
-                            List<String> list = firstList.stream().map(fl -> (fl.getWbsNodeId() + "")).collect(Collectors.toList());
-                            queryDataResult = queryDataResult.stream().filter(qdr -> list.contains(qdr.getPrimaryKeyId())).collect(Collectors.toList());
-                        }
+                    WbsTreeContract oldSelectedNode = BeanUtil.copyProperties(node, WbsTreeContract.class);
+                    childNodesPkeyIds = this.getChildNodesPkeyIds(oldSelectedNode, lowestNodesPkeyIds);
+                    List<String> sj = this.getSJ(contract, vo, lowestNodesPkeyIds);
+                    if (sj != null && sj.size() > 0) {
+                        submitNodeKeyIds.addAll(sj);
                     }
-                    submitNodeKeyIds.addAll(queryDataResult.stream().map(QueryProcessDataVO::getPrimaryKeyId).distinct().collect(Collectors.toList()));
                 }
             }
-
             vo.setWbsIds(submitNodeKeyIds);
-
-            if (org.apache.commons.lang.StringUtils.isNotEmpty(vo.getContractIdRelation())) {
+            if (StringUtils.isNotEmpty(vo.getContractIdRelation())) {
                 vo.setContractId(Long.valueOf(vo.getContractIdRelation()));
             }
         }
 
-        return this.selectInformationQueryPage(Condition.getPage(query), vo, node);
+        return this.selectInformationQueryPage(Condition.getPage(query), vo, node, childNodesPkeyIds);
     }
 
-    private IPage<InformationQueryVO> selectInformationQueryPage(IPage<InformationQueryVO> page, InformationQueryVO vo, WbsTreeContract node) {
+    private IPage<InformationQueryVO> selectInformationQueryPage(IPage<InformationQueryVO> page, InformationQueryVO vo, WbsTreeContract node, List<Long> childNodesPkeyIds) {
         if (StringUtils.isNotEmpty(vo.getBetweenTime())) {
             String[] betweenTime;
             if (vo.getBetweenTime().contains("~")) {
@@ -1329,7 +1304,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
             vo.setEndTime(betweenTime[1]);
         }
 
-        if (org.apache.commons.lang.StringUtils.isNotEmpty(vo.getFileUserIdAndName())) {
+        if (StringUtils.isNotEmpty(vo.getFileUserIdAndName())) {
             vo.setFileUserIdAndName(vo.getFileUserIdAndName().split("-")[0]);
         }
 
@@ -1337,15 +1312,24 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
             vo.setTaskStatus(vo.getStatus().toString());
         }
 
-        //获取全部数据
-        List<InformationQuery> result = baseMapper.selectInformationQueryPageTwo(vo);
-        if (result != null && result.size() != 0) {
-            //属于待审批、已审批状态任务Task信息,以及当前任务对应的副任务TaskParallel信息
+        long startTime = System.currentTimeMillis();
+        List<InformationQuery> result = new ArrayList<>();
+        List<List<String>> partition = Lists.partition(vo.getWbsIds(), 500);
+        for (List<String> wbsIds : partition) {
+            vo.setWbsIds(wbsIds);
+            List<InformationQuery> queries = baseMapper.selectInformationQueryPageTwo(vo);
+            result.addAll(queries);
+        }
+        long endTime = System.currentTimeMillis();
+        long executionTime = endTime - startTime;
+        _logger.info("合同段 " + node.getContractId() + " 获取当前资料缓存 执行时间:" + executionTime + " ms");
+
+        if (result.size() != 0) {
             Map<String, List<Task>> taskMaps = new HashMap<>();
             Map<String, List<TaskParallel>> taskParallelMaps = new HashMap<>();
             List<Long> informationIds = result.stream().filter(f -> f.getStatus().equals(1) || f.getStatus().equals(2)).map(InformationQuery::getId).collect(Collectors.toList());
             String informationIdsStr = informationIds.stream().map(String::valueOf).collect(Collectors.joining(","));
-            if (org.apache.commons.lang.StringUtils.isNotEmpty(informationIdsStr)) {
+            if (StringUtils.isNotEmpty(informationIdsStr)) {
                 List<Task> query = jdbcTemplate.query("SELECT id,form_data_id,process_instance_id,approval_type,status,batch,project_id,contract_id,create_time FROM u_task WHERE form_data_id IN(" + informationIdsStr + ") AND status IN (1, 2) AND is_deleted = 0", new BeanPropertyRowMapper<>(Task.class));
                 taskMaps = query.stream().collect(Collectors.groupingBy(Task::getFormDataId));
                 Set<String> processInstanceIds = query.stream().map(Task::getProcessInstanceId).map(id -> "'" + id + "'").collect(Collectors.toSet());
@@ -1355,7 +1339,6 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
                 }
             }
 
-            //校验关联的工序节点是否全都已审批
             List<String> sjRecordIds = result.stream().map(InformationQuery::getSjRecordIds).filter(Objects::nonNull).collect(Collectors.toList());
             Set<Long> ids = new HashSet<>();
             for (String sjRecordId : sjRecordIds) {
@@ -1364,7 +1347,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
             }
             List<InformationQuery> informationQueries = new ArrayList<>();
             if (ids.size() > 0) {
-                informationQueries = jdbcTemplate.query("SELECT * FROM u_information_query WHERE id IN(" + StringUtils.join(ids, ",") + ")", new BeanPropertyRowMapper<>(InformationQuery.class));
+                informationQueries = jdbcTemplate.query("SELECT id FROM u_information_query WHERE id IN(" + StringUtils.join(ids, ",") + ")", new BeanPropertyRowMapper<>(InformationQuery.class));
             }
 
             List<InformationQueryVO> voResult = JSONArray.parseArray(JSONObject.toJSONString(result), InformationQueryVO.class);
@@ -1391,9 +1374,10 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
                     e.printStackTrace();
                 }
 
+                /*任务状态*/
                 if (Arrays.asList("1,2".split(",")).contains(vor.getStatus().toString())) {
                     List<Task> tasks = finalTaskMaps.getOrDefault(vor.getId().toString(), null);
-                    //获取创建时间最新的那条任务数据(存在多条任务指向同一个form_data_id,即一条资料多次上报,这里要获取最新的)
+                    /*获取创建时间最新的那条任务数据(存在多条任务指向同一个form_data_id,即一条资料多次上报,这里要获取最新的)*/
                     if (tasks != null && tasks.size() > 0) {
                         Optional<Task> maxTask = tasks.stream().max(Comparator.comparing(Task::getCreateTime));
                         Task maxTaskObject = maxTask.get();
@@ -1405,7 +1389,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
                     }
                 }
 
-                //校验关联的工序节点是否全都已审批
+                /*首件判断*/
                 if (StringUtils.isNotEmpty(vor.getSjRecordIds())) {
                     List<String> recordIdList = Func.toStrList(vor.getSjRecordIds());
                     List<InformationQuery> informationQueryList = finalInformationQueries.stream()
@@ -1416,7 +1400,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
                     vor.setIsApprove(isApprove);
                 }
 
-                //试验关联文件pdf
+                /*试验文件关联*/
                 try {
                     this.getMergePdf(vor);
                 } catch (FileNotFoundException e) {
@@ -1434,7 +1418,6 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
 
             } else if (voResult.size() > 1) {
                 if (org.apache.commons.lang.StringUtils.isNotEmpty(vo.getIsFirst())) {
-
                     long current = (page.getCurrent() - 1) * page.getSize();
                     if (current < 0) {
                         throw new IllegalArgumentException("当前页码不能小于0");
@@ -1447,33 +1430,16 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
                     page.setRecords(subList);
                     page.setTotal(voResult.size());
                     return page;
-
                 } else {
-                    /**
-                     * 资料查询
-                     * @author liuyc
-                     * @date 2024年1月6日10:23:14
-                     * @description
-                     *   处理资料查询,page资料填报数据与节点顺序同步展示问题,查询出当前选择节点下所有资料填报信息,
-                     *   然后匹配节点位置信息,不分页查询page数据,分页查询会导致数据匹配异常,处理完匹配后,再分页返回。
-                     */
-                    //获取选择的节点下的所有子节点信息
-                    WbsTreeContract oldSelectedNode = BeanUtil.copyProperties(node, WbsTreeContract.class);
-                    List<WbsTreeContract> treeAll = this.getChildNodesZL(oldSelectedNode);
-                    if (treeAll == null) {
-                        treeAll = new ArrayList<>();
-                    }
-                    treeAll.add(0, oldSelectedNode);
-
-                    if (treeAll.size() > 1) {
+                    childNodesPkeyIds.add(0, node.getPKeyId());
+                    if (childNodesPkeyIds.size() > 1) {
                         LinkedList<InformationQueryVO> resultData = new LinkedList<>();
                         LinkedHashMap<Long, InformationQueryVO> dataMaps = voResult.stream()
                                 .collect(Collectors.toMap(InformationQueryVO::getWbsId, Function.identity(),
                                         (oldValue, newValue) -> oldValue, LinkedHashMap::new));
-                        for (WbsTreeContract resultNode : treeAll) {
-                            InformationQueryVO queryVO = dataMaps.get(resultNode.getPKeyId());
+                        for (Long pKeyId : childNodesPkeyIds) {
+                            InformationQueryVO queryVO = dataMaps.get(pKeyId);
                             if (queryVO != null) {
-                                //按节点顺序插入Page数据
                                 resultData.add(queryVO);
                             }
                         }
@@ -1500,25 +1466,38 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
         return page.setRecords(null);
     }
 
-    private void lowestNodesRecursively(List<WbsTreeContractVO8> lowestNodes, Set<WbsTreeContractVO8> nodes, String contractId) {
-        if (nodes.size() > 0) {
-            Set<Long> ids = nodes.stream().map(WbsTreeContractVO8::getId).collect(Collectors.toSet());
-            if (ids.size() > 0) {
-                List<WbsTreeContractVO8> childNodes = jdbcTemplate.query("select a.p_key_id,a.id,(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.contract_id = " + contractId + " AND b.status = 1 AND b.type = 1 AND b.is_deleted = 0) AS hasChildren from m_wbs_tree_contract a where a.type = 1 and a.status = 1 and a.is_deleted = 0 and a.contract_id = " + contractId + " and a.parent_id in(" + org.apache.commons.lang.StringUtils.join(ids, ",") + ")", new BeanPropertyRowMapper<>(WbsTreeContractVO8.class));
-                if (childNodes.size() > 0) {
-                    Set<WbsTreeContractVO8> lowestNode = childNodes.stream().filter(f -> f.getHasChildren().equals(0)).collect(Collectors.toSet());
-                    Set<WbsTreeContractVO8> noLowestNode = childNodes.stream().filter(f -> f.getHasChildren().equals(1)).collect(Collectors.toSet());
-                    //最底层节点
-                    if (lowestNode.size() > 0) {
-                        lowestNodes.addAll(lowestNode);
-                    }
-                    //非最底层节点
-                    if (noLowestNode.size() > 0) {
-                        this.lowestNodesRecursively(lowestNodes, noLowestNode, contractId);
-                    }
+    private List<String> getSJ(ContractInfo contract, InformationQueryVO vo, List<Long> lowestNodesPkeyIds) {
+        /*首件相关*/
+        List<QueryProcessDataVO> queryDataResult = new ArrayList<>();
+        List<List<Long>> partition = Lists.partition(lowestNodesPkeyIds, 500);
+        for (List<Long> items : partition) {
+            String sql = "SELECT wtc.p_key_id AS primaryKeyId,uiq.type AS queryType " +
+                    " FROM m_wbs_tree_contract AS wtc" +
+                    " LEFT JOIN u_information_query AS uiq ON wtc.p_key_id = uiq.wbs_id" +
+                    " AND uiq.classify = " + contract.getContractType() +
+                    " AND uiq.is_deleted = 0 " +
+                    " WHERE wtc.p_key_id IN (" + org.apache.commons.lang.StringUtils.join(items, ",") + ") " +
+                    " AND wtc.is_deleted = 0 AND wtc.status = 1 ";
+
+            List<QueryProcessDataVO> result = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(QueryProcessDataVO.class));
+            if (result.size() > 0) {
+                queryDataResult.addAll(result);
+            }
+        }
+        if (queryDataResult.size() > 0) {
+            if (org.apache.commons.lang.StringUtils.isNotEmpty(vo.getIsFirst())) {
+                if (org.apache.commons.lang.StringUtils.isNotEmpty(vo.getFirstTitle())) {
+                    queryDataResult = queryDataResult.stream().filter(qdr -> "3".equals(qdr.getQueryType())).collect(Collectors.toList());
+                } else {
+                    List<String> treeIds = queryDataResult.stream().map(QueryProcessDataVO::getPrimaryKeyId).distinct().collect(Collectors.toList());
+                    List<TreeContractFirst> firstList = jdbcTemplate.query("SELECT wbs_node_id FROM u_tree_contract_first WHERE is_deleted = 0 AND wbs_node_id IN (" + org.apache.commons.lang.StringUtils.join(treeIds, ",") + ")", new BeanPropertyRowMapper<>(TreeContractFirst.class));
+                    List<String> list = firstList.stream().map(fl -> (fl.getWbsNodeId() + "")).collect(Collectors.toList());
+                    queryDataResult = queryDataResult.stream().filter(qdr -> list.contains(qdr.getPrimaryKeyId())).collect(Collectors.toList());
                 }
             }
+            return queryDataResult.stream().map(QueryProcessDataVO::getPrimaryKeyId).distinct().collect(Collectors.toList());
         }
+        return null;
     }
 
     private void integrationMethod(InformationQueryVO vo, List<TaskParallel> linkList) {
@@ -1589,52 +1568,43 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implement
         }
     }
 
-    private List<WbsTreeContract> getChildNodesZL(WbsTreeContract obj) {
+    private List<Long> getChildNodesPkeyIds(WbsTreeContract obj, List<Long> lowestNodesPkeyIds) {
         if (obj != null) {
-            List<WbsTreeContract> wbsTreeContracts = Collections.singletonList(obj);
-            List<WbsTreeContract> result = new ArrayList<>();
-            this.recursionGetChildNodesZL(wbsTreeContracts, result, obj.getContractId());
-            if (result.size() > 0) {
-                return result;
+            List<Long> resultPKeyId = new ArrayList<>();
+            List<WbsTreeContractLazyVO> nodeAll = this.getNodeAll(obj.getContractId());
+            this.recursionGetChildNodesPkeyIds(nodeAll, Collections.singletonList(obj.getId()), resultPKeyId, lowestNodesPkeyIds);
+            if (resultPKeyId.size() > 0) {
+                return resultPKeyId;
             }
         }
-        return null;
+        return new ArrayList<>();
     }
 
-    private void recursionGetChildNodesZL(List<WbsTreeContract> list, List<WbsTreeContract> result, String contractId) {
-        List<Long> ids = list.stream().map(WbsTreeContract::getId).collect(Collectors.toList());
+    private void recursionGetChildNodesPkeyIds(List<WbsTreeContractLazyVO> nodeAll, List<Long> ids, List<Long> resultPKeyId, List<Long> lowestNodesPkeyIds) {
         if (ids.size() > 0) {
-            //构建以parent_id为key的Map
-            Map<Long, List<WbsTreeContract>> queryMap = jdbcTemplate.query(
-                    "SELECT id,p_key_id,parent_id,sort,create_time," +
-                            "IFNULL(if(LENGTH (trim(full_name)) > 0, full_name, node_name), node_name) AS fullName " +
-                            "FROM m_wbs_tree_contract WHERE type = 1 AND status = 1 AND is_deleted = 0 " +
-                            "AND parent_id IN (" + org.apache.commons.lang.StringUtils.join(ids, ",") + ") " +
-                            "AND contract_id = " + contractId + " ORDER BY sort,fullName,create_time",
-                    rs -> {
-                        Map<Long, List<WbsTreeContract>> map = new LinkedHashMap<>();
-                        while (rs.next()) {
-                            WbsTreeContract item = new WbsTreeContract();
-                            item.setId(rs.getLong("id"));
-                            item.setPKeyId(rs.getLong("p_key_id"));
-                            item.setParentId(rs.getLong("parent_id"));
-                            item.setSort(rs.getInt("sort"));
-                            item.setFullName(rs.getString("fullName"));
-                            item.setCreateTime(rs.getTime("create_time"));
-                            Long parentId = item.getParentId();
-                            if (!map.containsKey(parentId)) {
-                                map.put(parentId, new ArrayList<>());
-                            }
-                            map.get(parentId).add(item);
-                        }
-                        return map;
-                    });
-            //按照ids的顺序加入result
+            List<WbsTreeContractLazyVO> sortedFilteredNodes = nodeAll.stream()
+                    .filter(f -> ids.contains(f.getParentId()))
+                    .sorted(Comparator.comparing(WbsTreeContractLazyVO::getSort, Comparator.nullsLast(Integer::compareTo))
+                            .thenComparing(WbsTreeContractLazyVO::getFullName, Comparator.nullsLast(String::compareTo))
+                            .thenComparing(WbsTreeContractLazyVO::getCreateTime, Comparator.nullsLast(Comparator.naturalOrder())))
+                    .collect(Collectors.toList());
+
+            Map<Long, List<WbsTreeContractLazyVO>> filteredNodesMap = new LinkedHashMap<>();
+            sortedFilteredNodes.forEach(node -> {
+                Long parentId = node.getParentId();
+                filteredNodesMap.computeIfAbsent(parentId, k -> new ArrayList<>()).add(node);
+            });
+
             for (Long id : ids) {
-                if (queryMap != null && queryMap.containsKey(id)) {
-                    List<WbsTreeContract> nodes = queryMap.get(id);
-                    result.addAll(nodes);
-                    recursionGetChildNodesZL(nodes, result, contractId);
+                if (filteredNodesMap.containsKey(id)) {
+                    List<WbsTreeContractLazyVO> nodes = filteredNodesMap.get(id);
+                    for (WbsTreeContractLazyVO node : nodes) {
+                        if (node.getHasChildren().equals(0)) {
+                            lowestNodesPkeyIds.add(node.getPKeyId());
+                        }
+                        resultPKeyId.add(node.getPKeyId());
+                    }
+                    this.recursionGetChildNodesPkeyIds(nodeAll, nodes.stream().map(WbsTreeContractLazyVO::getId).collect(Collectors.toList()), resultPKeyId, lowestNodesPkeyIds);
                 }
             }
         }