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

Merge branch 'master' of http://47.110.251.215:3000/java_org/bladex

huangtf преди 2 години
родител
ревизия
554da5ae62
променени са 55 файла, в които са добавени 1690 реда и са изтрити 411 реда
  1. 5 0
      blade-common/src/main/java/org/springblade/common/constant/ArchiveConstant.java
  2. 4 2
      blade-ops/blade-resource/src/main/java/org/springblade/resource/builder/oss/AliOssBuilder.java
  3. 10 8
      blade-ops/blade-resource/src/main/java/org/springblade/resource/builder/oss/OssBuilder.java
  4. 24 7
      blade-ops/blade-resource/src/main/java/org/springblade/resource/builder/ossre/AliossTemplateRe.java
  5. 17 0
      blade-ops/blade-resource/src/main/java/org/springblade/resource/builder/ossre/OssTemplateRe.java
  6. 62 0
      blade-ops/blade-resource/src/main/java/org/springblade/resource/endpoint/UmsAdminLoginLogDO.java
  7. 35 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/ArchiveExaminingReport.java
  8. 52 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/ArchiveExaminingReportDetail.java
  9. 25 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/vo/ArchiveExaminingSocketVo.java
  10. 30 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/vo/ArchiveExaminingVo.java
  11. 3 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/feign/ArchiveFileClient.java
  12. 2 1
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/FormData.java
  13. 3 3
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/RangeInfo.java
  14. 14 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ContractInfo.java
  15. 16 0
      blade-service-api/blade-system-api/src/main/java/org/springblade/system/entity/Tenant.java
  16. 14 0
      blade-service/blade-archive/pom.xml
  17. 105 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveExaminingReportController.java
  18. 26 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveExaminingReportDetailController.java
  19. 3 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveFileController.java
  20. 7 3
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveOfflineVersionInfoController.java
  21. 15 1
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchivesAutoController.java
  22. 12 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchiveExaminingReportDetailMapper.java
  23. 5 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchiveExaminingReportDetailMapper.xml
  24. 12 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchiveExaminingReportMapper.java
  25. 5 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchiveExaminingReportMapper.xml
  26. 13 10
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.xml
  27. 12 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/IArchiveExaminingReportDetailService.java
  28. 20 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/IArchiveExaminingReportService.java
  29. 4 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/IArchivesAutoService.java
  30. 17 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchiveExaminingReportDetailServiceImpl.java
  31. 283 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchiveExaminingReportImpl.java
  32. 1 1
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchiveOfflineVersionInfoServiceImpl.java
  33. 158 28
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java
  34. 35 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/socket/WebSocketConfig.java
  35. 142 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/socket/WebSocketServer.java
  36. 13 0
      blade-service/blade-archive/src/main/resources/application-dev.yml
  37. 193 166
      blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java
  38. 23 10
      blade-service/blade-business/src/main/java/org/springblade/business/feignClient/ArchiveFileClientImpl.java
  39. 2 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/ArchiveFileMapper.java
  40. 11 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/ArchiveFileMapper.xml
  41. 45 13
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/ImageClassificationFileServiceImpl.java
  42. 0 1
      blade-service/blade-manager/src/main/java/com/mixsmart/utils/CustomFunction.java
  43. 6 0
      blade-service/blade-manager/src/main/java/com/mixsmart/utils/StringUtils.java
  44. 17 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ContractInfoController.java
  45. 14 9
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java
  46. 2 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/FormulaController.java
  47. 22 21
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/TextdictInfoController.java
  48. 4 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IContractInfoService.java
  49. 53 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ContractInfoServiceImpl.java
  50. 70 21
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java
  51. 2 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeContractServiceImpl.java
  52. 10 54
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreePrivateServiceImpl.java
  53. 6 47
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeServiceImpl.java
  54. 3 1
      blade-service/blade-system/src/main/java/org/springblade/system/controller/TenantController.java
  55. 3 1
      blade-service/blade-system/src/main/java/org/springblade/system/mapper/TenantMapper.xml

+ 5 - 0
blade-common/src/main/java/org/springblade/common/constant/ArchiveConstant.java

@@ -2,4 +2,9 @@ package org.springblade.common.constant;
 
 public interface ArchiveConstant {
     String APPLICATION_WEATHER_NAME = "blade-archive";
+    String ARCHIVE_EXAMINING_AUTHENTICITY = "真实性";
+    String ARCHIVE_EXAMINING_INTEGRALITY = "完整性";
+    String ARCHIVE_EXAMINING_USABILITY = "可用性";
+    String ARCHIVE_EXAMINING_SECURITY = "安全性";
+    String ARCHIVE_EXAMINING_STANDARD = "依据<<电子档案检测一般要求:DA/T 70-2018>>";
 }

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

@@ -22,9 +22,10 @@ import com.aliyun.oss.common.auth.CredentialsProvider;
 import com.aliyun.oss.common.auth.DefaultCredentialProvider;
 import lombok.SneakyThrows;
 import org.springblade.core.oss.OssTemplate;
-import org.springblade.core.oss.AliossTemplate;
 import org.springblade.core.oss.props.OssProperties;
 import org.springblade.core.oss.rule.OssRule;
+import org.springblade.resource.builder.ossre.AliossTemplateRe;
+import org.springblade.resource.builder.ossre.OssTemplateRe;
 import org.springblade.resource.entity.Oss;
 
 /**
@@ -35,7 +36,7 @@ import org.springblade.resource.entity.Oss;
 public class AliOssBuilder {
 
 	@SneakyThrows
-	public static OssTemplate template(Oss oss, OssRule ossRule) {
+	public static OssTemplateRe template(Oss oss, OssRule ossRule) {
 		// 创建ClientConfiguration。ClientConfiguration是OSSClient的配置类,可配置代理、连接超时、最大连接数等参数。
 		ClientConfiguration conf = new ClientConfiguration();
 		// 设置OSSClient允许打开的最大HTTP连接数,默认为1024个。
@@ -57,6 +58,7 @@ public class AliOssBuilder {
 		ossProperties.setBucketName(oss.getBucketName());
 		CredentialsProvider credentialsProvider = new DefaultCredentialProvider(ossProperties.getAccessKey(), ossProperties.getSecretKey());
 		OSSClient ossClient = new OSSClient(ossProperties.getEndpoint(), credentialsProvider, conf);
+
 		return new AliossTemplateRe(ossClient, ossProperties, ossRule);
 	}
 

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

@@ -29,6 +29,7 @@ import org.springblade.core.oss.rule.BladeOssRule;
 import org.springblade.core.oss.rule.OssRule;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.utils.*;
+import org.springblade.resource.builder.ossre.OssTemplateRe;
 import org.springblade.resource.entity.Oss;
 import org.springblade.resource.service.IOssService;
 
@@ -59,7 +60,7 @@ public class OssBuilder {
     /**
      * OssTemplate配置缓存池
      */
-    private final Map<String, OssTemplate> templatePool = new ConcurrentHashMap<>();
+    private final Map<String, OssTemplateRe> templatePool = new ConcurrentHashMap<>();
 
     /**
      * oss配置缓存池
@@ -71,7 +72,7 @@ public class OssBuilder {
      *
      * @return OssTemplate
      */
-    public OssTemplate template() {
+    public OssTemplateRe template() {
         return template(StringPool.EMPTY);
     }
 
@@ -81,11 +82,11 @@ public class OssBuilder {
      * @param code 资源编号
      * @return OssTemplate
      */
-    public OssTemplate template(String code) {
+    public OssTemplateRe template(String code) {
         String tenantId = AuthUtil.getTenantId();
         Oss oss = getOss(tenantId, code);
         Oss ossCached = ossPool.get(tenantId);
-        OssTemplate template = templatePool.get(tenantId);
+        OssTemplateRe template = templatePool.get(tenantId);
         // 若为空或者不一致,则重新加载
         if (Func.hasEmpty(template, ossCached) || !oss.getEndpoint().equals(ossCached.getEndpoint()) || !oss.getAccessKey().equals(ossCached.getAccessKey())) {
             synchronized (OssBuilder.class) {
@@ -98,20 +99,21 @@ public class OssBuilder {
                     } else {
                         ossRule = new BladeOssRule(Boolean.FALSE);
                     }
-                    if (oss.getCategory() == OssEnum.MINIO.getCategory()) {
+                    /*if (oss.getCategory() == OssEnum.MINIO.getCategory()) {
                         template = MinioOssBuilder.template(oss, ossRule);
                     } else if (oss.getCategory() == OssEnum.QINIU.getCategory()) {
                         template = QiniuOssBuilder.template(oss, ossRule);
-                    } else if (oss.getCategory() == OssEnum.ALI.getCategory()) {
+                    } else if (oss.getCategory() == OssEnum.ALI.getCategory()) {*/
                         template = AliOssBuilder.template(oss, ossRule);
-                    } else if (oss.getCategory() == OssEnum.TENCENT.getCategory()) {
+                    /*} else if (oss.getCategory() == OssEnum.TENCENT.getCategory()) {
                         template = TencentOssBuilder.template(oss, ossRule);
-                    }
+                    }*/
                     templatePool.put(tenantId, template);
                     ossPool.put(tenantId, oss);
                 }
             }
         }
+
         return template;
     }
 

+ 24 - 7
blade-ops/blade-resource/src/main/java/org/springblade/resource/builder/oss/AliossTemplateRe.java → blade-ops/blade-resource/src/main/java/org/springblade/resource/builder/ossre/AliossTemplateRe.java

@@ -1,11 +1,9 @@
-package org.springblade.resource.builder.oss;
+package org.springblade.resource.builder.ossre;
 
 import com.aliyun.oss.OSSClient;
 import com.aliyun.oss.common.utils.BinaryUtil;
-import com.aliyun.oss.model.MatchMode;
-import com.aliyun.oss.model.ObjectMetadata;
-import com.aliyun.oss.model.PolicyConditions;
-import com.aliyun.oss.model.PutObjectResult;
+import com.aliyun.oss.model.*;
+
 import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
 import java.util.Date;
@@ -14,7 +12,6 @@ import java.util.List;
 import java.util.Map;
 
 import lombok.SneakyThrows;
-import org.springblade.core.oss.OssTemplate;
 import org.springblade.core.oss.model.BladeFile;
 import org.springblade.core.oss.model.OssFile;
 import org.springblade.core.oss.props.OssProperties;
@@ -23,7 +20,7 @@ import org.springblade.core.tool.jackson.JsonUtil;
 import org.springframework.util.StringUtils;
 import org.springframework.web.multipart.MultipartFile;
 
-public class AliossTemplateRe implements OssTemplate {
+public class AliossTemplateRe implements OssTemplateRe {
     private final OSSClient ossClient;
     private final OssProperties ossProperties;
     private final OssRule ossRule;
@@ -288,4 +285,24 @@ public class AliossTemplateRe implements OssTemplate {
         this.ossProperties = ossProperties;
         this.ossRule = ossRule;
     }
+
+
+    // OSS 分片上传
+    public UploadPartResult uploadPart(UploadPartRequest request){
+        UploadPartResult uploadPartResult = this.ossClient.uploadPart(request);
+        return uploadPartResult;
+    }
+
+
+    // OSS 分片上传 合成
+    public CompleteMultipartUploadResult completeMultipartUpload(CompleteMultipartUploadRequest request){
+        CompleteMultipartUploadResult uploadPartResult = this.ossClient.completeMultipartUpload(request);
+        return uploadPartResult;
+    }
+
+    // OSS 分片上传 初始化
+    public InitiateMultipartUploadResult initiateMultipartUpload(InitiateMultipartUploadRequest request){
+        InitiateMultipartUploadResult initResult = this.ossClient.initiateMultipartUpload(request);
+        return initResult;
+    }
 }

+ 17 - 0
blade-ops/blade-resource/src/main/java/org/springblade/resource/builder/ossre/OssTemplateRe.java

@@ -0,0 +1,17 @@
+package org.springblade.resource.builder.ossre;
+
+import com.aliyun.oss.model.*;
+import org.springblade.core.oss.OssTemplate;
+
+
+public interface OssTemplateRe extends OssTemplate {
+
+    // OSS 分片上传
+    UploadPartResult uploadPart(UploadPartRequest request);
+
+    // OSS 分片上传 合成
+    CompleteMultipartUploadResult completeMultipartUpload(CompleteMultipartUploadRequest request);
+
+    // OSS 分片上传 初始化
+    InitiateMultipartUploadResult initiateMultipartUpload(InitiateMultipartUploadRequest request);
+}

+ 62 - 0
blade-ops/blade-resource/src/main/java/org/springblade/resource/endpoint/UmsAdminLoginLogDO.java

@@ -0,0 +1,62 @@
+package org.springblade.resource.endpoint;
+
+import com.aliyun.oss.model.PartETag;
+import lombok.Data;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author zhangtonghao
+ * @create 2022-04-06 15:08
+ */
+@Data
+public class UmsAdminLoginLogDO {
+
+    /**
+     * 初始化任务id
+     */
+    private String taskId;
+
+    /**
+     * 上传文件类型
+     */
+    private String fileType;
+
+    /**
+     * 文件总片数
+     */
+    private Integer fileSlicesNum;
+    /**
+     * 分片编号(1-10000有序的编号,越大的编号位置越靠后)
+     */
+    private Integer sliceNo;
+    /**
+     * 本次请求文件的md5值
+     */
+    private String fileMD5;
+    /**
+     *文件流数据
+     */
+    private byte[] content;
+
+    /**
+     * 文件名称
+     */
+    private String fileName;
+
+    /**
+     * oss初始化分片id
+     */
+    private String ossSlicesId;
+
+    /**
+     * 最小分片大小(分片上传是除最后一片外,其他文件不得小于该值)
+     */
+    private String minSliceSize;
+
+    Map<Integer, PartETag> partETags = new HashMap<>(16);
+
+
+}

+ 35 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/ArchiveExaminingReport.java

@@ -0,0 +1,35 @@
+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.time.LocalDateTime;
+
+/**
+ * @Param
+ * @Author wangwl
+ * @Date 2023/4/20 17:29
+ **/
+@Data
+@TableName("u_archive_examining_report")
+@EqualsAndHashCode(callSuper = true)
+public class ArchiveExaminingReport extends BaseEntity {
+    @ApiModelProperty(value = "检测文档名称")
+    private String reportName;
+
+    @ApiModelProperty(value = "检测文档PDF路径")
+    private String reportPdfUrl;
+
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
+    @ApiModelProperty(value = "检测时间")
+    private LocalDateTime examiningTime;
+    /**
+     * 项目ID
+     */
+    private Long projectId;
+
+}

+ 52 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/ArchiveExaminingReportDetail.java

@@ -0,0 +1,52 @@
+package org.springblade.archive.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.core.mp.base.BaseEntity;
+
+/**
+ * @Param
+ * @Author wangwl
+ * @Date 2023/4/21 15:03
+ **/
+@Data
+@TableName("u_archive_examining_report_detail")
+@EqualsAndHashCode(callSuper = true)
+public class ArchiveExaminingReportDetail extends BaseEntity {
+    @ApiModelProperty(value = "项目id")
+    private Long projectId;
+
+    @ApiModelProperty(value = "检测报告id")
+    private Long reportId;
+
+    @ApiModelProperty(value = "检测类型")
+    private String examiningType;
+
+    @ApiModelProperty(value = "检测项")
+    private String examiningItem;
+
+    @ApiModelProperty(value = "不合格总数")
+    private Integer unqualifiedCount;
+
+    @ApiModelProperty(value = "不合格对象")
+    private String unqualifiedObject;
+
+    @ApiModelProperty(value = "检测结果")
+    private Integer examiningResult;
+
+    public ArchiveExaminingReportDetail() {
+    }
+
+    public ArchiveExaminingReportDetail(Long projectId, Long reportId, String examiningType, String examiningItem,
+                                        Integer unqualifiedCount, String unqualifiedObject,Integer examiningResult) {
+        this.projectId = projectId;
+        this.reportId = reportId;
+        this.examiningType = examiningType;
+        this.examiningItem = examiningItem;
+        this.unqualifiedCount = unqualifiedCount;
+        this.unqualifiedObject = unqualifiedObject;
+        this.examiningResult = examiningResult;
+    }
+}

+ 25 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/vo/ArchiveExaminingSocketVo.java

@@ -0,0 +1,25 @@
+package org.springblade.archive.vo;
+
+import lombok.Data;
+import org.springblade.archive.entity.ArchiveExaminingReportDetail;
+
+import java.util.List;
+
+/**
+ * @Param 四性检测socket发送值
+ * @Author wangwl
+ * @Date 2023/4/23 10:13
+ **/
+@Data
+public class ArchiveExaminingSocketVo {
+    private Integer status;
+    private List<ArchiveExaminingReportDetail> detailList;
+
+    public ArchiveExaminingSocketVo() {
+    }
+
+    public ArchiveExaminingSocketVo(Integer status, List<ArchiveExaminingReportDetail> detailList) {
+        this.status = status;
+        this.detailList = detailList;
+    }
+}

+ 30 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/vo/ArchiveExaminingVo.java

@@ -0,0 +1,30 @@
+package org.springblade.archive.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * @Param 四性检测参数
+ * @Author wangwl
+ * @Date 2023/4/23 15:42
+ **/
+@Data
+public class ArchiveExaminingVo {
+    @ApiModelProperty("项目ID")
+    private Long projectId;
+
+    @ApiModelProperty("报告ID")
+    private Long reportId;
+
+    @ApiModelProperty("真实性")
+    private String authenticity;
+
+    @ApiModelProperty("完整性")
+    private String integrality;
+
+    @ApiModelProperty("可用性")
+    private String usability;
+
+    @ApiModelProperty("安全性")
+    private String security;
+}

+ 3 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/feign/ArchiveFileClient.java

@@ -73,4 +73,7 @@ public interface ArchiveFileClient {
 
     @PostMapping(API_PREFIX + "/getAllArchiveFileSize")
     Long getAllArchiveFileSize(@RequestBody Long projectId);
+
+    @PostMapping(API_PREFIX + "/getListByNodeID")
+    List<ArchiveFile> getListByNodeID(@RequestParam String nodeId,@RequestParam Integer isArchive);
 }

+ 2 - 1
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/FormData.java

@@ -3,6 +3,7 @@ package org.springblade.manager.dto;
 
 
 import lombok.Data;
+import org.apache.commons.lang.StringUtils;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.core.tool.utils.StringPool;
 import org.springblade.manager.entity.Formula;
@@ -151,7 +152,7 @@ public class FormData {
     }
    /**元素内容是否为空*/
     public Boolean empty(){
-      return  Func.isEmpty(this.values);
+      return  !(Func.isNotEmpty(this.values)&&this.values.stream().map(ElementData::getValue).anyMatch(Func::isNotEmpty));
     }
 
 

+ 3 - 3
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/RangeInfo.java

@@ -19,7 +19,7 @@ public class RangeInfo {
             required = true
     )
     private String design;
-    private List<Double> gDesign;
+    private List<String> gDesign;
     @ApiModelProperty(
             value = "频率",
             required = true
@@ -57,7 +57,7 @@ public class RangeInfo {
         this.design = design;
     }
 
-    public List<Double> getDesigns() {
+    public List<String> getDesigns() {
         return gDesign;
     }
 
@@ -72,7 +72,7 @@ public class RangeInfo {
 
     public void build(){
         if(Func.isNotBlank(this.design)){
-            this.gDesign= Arrays.stream(this.design.split("[^\\d.]+")).filter(BaseUtils::isNumber).map(Func::toDouble).collect(Collectors.toList());
+            this.gDesign= Arrays.stream(this.design.split("[^\\d.]+")).filter(BaseUtils::isNumber).collect(Collectors.toList());
         }
         if(Func.isNotBlank(this.size)){
             this.gSize= Arrays.stream(this.size.split("[^\\d.]+")).filter(BaseUtils::isNumber).map(Func::toInt).collect(Collectors.toList());

+ 14 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ContractInfo.java

@@ -6,6 +6,7 @@ import java.math.BigDecimal;
 import java.time.LocalDateTime;
 
 import io.swagger.annotations.ApiModelProperty;
+import org.apache.commons.lang.StringUtils;
 import org.springblade.core.mp.base.BaseEntity;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
@@ -157,4 +158,17 @@ public class ContractInfo extends BaseEntity {
     @ApiModelProperty(value = "是否引用编号 '0'否 '1'是")
     private Integer isReferenceNumber;
 
+
+    public String  archivesUnit() {
+
+        String unit = getContractorUnitName();//建设单位名称
+        if (this.contractType== 1) {
+            unit = getConstructionUnitName();//施工单位名称
+        }else if (this.contractType== 2) {
+            unit = getSupervisionUnitName();//监理单位名称
+        }
+        return unit;
+
+    }
+
 }

+ 16 - 0
blade-service-api/blade-system-api/src/main/java/org/springblade/system/entity/Tenant.java

@@ -108,5 +108,21 @@ public class Tenant extends BaseEntity {
 	@ApiModelProperty(value = "授权码")
 	private String licenseKey;
 
+	/**
+	 * 租户标题
+	 */
+	@ApiModelProperty(value = "租户标题")
+	private String tenantTitle;
 
+	/**
+	 * 租户图标
+	 */
+	@ApiModelProperty(value = "租户图标")
+	private String tenantAvatar;
+
+	/**
+	 * 租户图标文字
+	 */
+	@ApiModelProperty(value = "租户图标文字")
+	private String tenantAvatarText;
 }

+ 14 - 0
blade-service/blade-archive/pom.xml

@@ -23,6 +23,12 @@
     </repositories>
 
     <dependencies>
+        <!--        iText生成中文-->
+        <dependency>
+            <groupId>com.itextpdf</groupId>
+            <artifactId>itext-asian</artifactId>
+            <version>5.2.0</version>
+        </dependency>
         <!--sqlite-->
         <dependency>
             <groupId>org.xerial</groupId>
@@ -106,6 +112,14 @@
             <version>2.9.1.RELEASE</version>
             <scope>compile</scope>
         </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-websocket</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-messaging</artifactId>
+        </dependency>
 
     </dependencies>
 

+ 105 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveExaminingReportController.java

@@ -0,0 +1,105 @@
+package org.springblade.archive.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.itextpdf.text.DocumentException;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springblade.archive.entity.ArchiveExaminingReport;
+import org.springblade.archive.service.IArchiveExaminingReportService;
+import org.springblade.archive.vo.ArchiveExaminingVo;
+import org.springblade.common.utils.SnowFlakeUtil;
+import org.springblade.core.oss.model.BladeFile;
+import org.springblade.core.secure.BladeUser;
+import org.springblade.core.secure.utils.SecureUtil;
+import org.springblade.core.tool.api.R;
+import org.springblade.resource.feign.NewIOSSClient;
+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.io.IOException;
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @Param
+ * @Author wangwl
+ * @Date 2023/4/20 17:33
+ **/
+@RestController
+@AllArgsConstructor
+@RequestMapping("/archiveExaminingReport")
+@Api(value = "档案检测报告", tags = "档案检测报告")
+public class ArchiveExaminingReportController {
+    private final IArchiveExaminingReportService archiveExaminingReportService;
+
+    private final NewIOSSClient iossClient;
+    @GetMapping("test")
+    public String test() throws DocumentException, IOException {
+        BladeFile bladeFile = iossClient.uploadFile("124456sdf", "D:\\develop\\test\\test1.pdf");
+        return bladeFile.getLink();
+    }
+
+    @GetMapping("/getList")
+    @ApiOperation(value = "获取检测报告列表")
+    public R getList(@RequestParam("projectId") Long projectId){
+        List<ArchiveExaminingReport> list = archiveExaminingReportService.list(new LambdaQueryWrapper<ArchiveExaminingReport>()
+                .eq(projectId != null, ArchiveExaminingReport::getProjectId, projectId)
+                .eq(ArchiveExaminingReport::getStatus,4)
+                .orderByDesc(ArchiveExaminingReport::getExaminingTime)
+                .last("limit 5"));
+        return R.data(list);
+    }
+
+    @GetMapping("/getReportStatus")
+    @ApiOperation(value = "获取检测报告状态")
+    public R getReportStatus(@RequestParam("projectId") Long projectId){
+        //获取最新的报告
+        ArchiveExaminingReport report = archiveExaminingReportService.getOne(new LambdaQueryWrapper<ArchiveExaminingReport>()
+                .eq(projectId != null, ArchiveExaminingReport::getProjectId, projectId)
+                .orderByDesc(ArchiveExaminingReport::getExaminingTime).last("limit 1"));
+        //判断是否报告正在进行,如果正在进行就跳转
+        if (report != null){
+            if (report.getStatus() == 4){
+                return R.data(-1);
+            }else {
+                return R.data(report.getId());
+            }
+        }
+        return R.data(-1);
+    }
+
+    @GetMapping("/getExamining")
+    @ApiOperation(value = "档案四性检测")
+    public R getExamining(ArchiveExaminingVo vo) throws InterruptedException, IOException, DocumentException {
+
+        //如果id为0则为一键检测,不为0则有报告正在进行
+        if (vo.getReportId() == 0){
+            //创建报告
+            ArchiveExaminingReport report = new ArchiveExaminingReport();
+            Long id = SnowFlakeUtil.getId();
+            report.setId(id);
+            report.setReportName("电子文件四性检测报告");
+            report.setExaminingTime(LocalDateTime.now());
+            report.setStatus(1);
+            report.setCreateTime(new Date());
+            report.setProjectId(vo.getProjectId());
+            archiveExaminingReportService.save(report);
+            //调用四性检测方法
+            archiveExaminingReportService.getExamining(vo,id);
+            //调用socket,每隔3秒检测当前报告状态然后推送
+            BladeUser user = SecureUtil.getUser();
+            System.out.println(user.getUserId()+"Controller");
+            archiveExaminingReportService.pushStatusBySocket(user.getUserId(), id);
+            return R.data(report);
+        }else {
+            ArchiveExaminingReport report = archiveExaminingReportService.getById(vo.getReportId());
+            return R.data(report);
+        }
+
+    }
+
+}

+ 26 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveExaminingReportDetailController.java

@@ -0,0 +1,26 @@
+package org.springblade.archive.controller;
+
+import io.swagger.annotations.Api;
+import lombok.AllArgsConstructor;
+import org.springblade.archive.entity.ArchiveExaminingReportDetail;
+import org.springblade.archive.service.IArchiveExaminingReportDetailService;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @Param
+ * @Author wangwl
+ * @Date 2023/4/21 15:09
+ **/
+@RestController
+@AllArgsConstructor
+@RequestMapping("/archiveExaminingReportDetailController")
+@Api(value = "档案检测报告详情", tags = "档案检测报告详情")
+public class ArchiveExaminingReportDetailController {
+    private final IArchiveExaminingReportDetailService detailService;
+    @GetMapping("/test")
+    public String test(){
+        return "666";
+    }
+}

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

@@ -288,6 +288,9 @@ public class ArchiveFileController extends BladeController {
     public R allArchiveFileSize(Long projectId) {
         //统计案卷文件大小
         Long fileSize = archiveFileClient.getAllArchiveFileSize(projectId);
+        if (fileSize == null){
+            return R.data("0B");
+        }
         //统计表单数据大小
 //        Long tableSize = wbsTreeContractClient.getAllTableFileSize(projectId);
         String size = org.springblade.common.utils.FileUtils.formatSize(fileSize );

+ 7 - 3
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveOfflineVersionInfoController.java

@@ -48,9 +48,13 @@ public class ArchiveOfflineVersionInfoController {
     @GetMapping("/getVersionInfo")
     public R<ArchiveOfflineVersionInfo> getVersionInfo(Long projectId){
         ArchiveOfflineVersionInfo versionInfo = mapper.selectVersionInfo(projectId);
-        String size = this.formatSize(Long.parseLong(versionInfo.getFileSize()));
-        versionInfo.setFileSize(size);
-        return R.data(versionInfo);
+        if (versionInfo != null) {
+            String size = this.formatSize(Long.parseLong(versionInfo.getFileSize()));
+            versionInfo.setFileSize(size);
+            return R.data(versionInfo);
+        }else {
+            return R.data(null);
+        }
     }
     /**
      * 根据字节返回文件大小

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

@@ -239,5 +239,19 @@ public class ArchivesAutoController extends BladeController {
 		return R.status(archivesAutoService.updateBatchById(archivesAutos));
 	}
 
-	
+
+	/**
+	 * 自动组卷入口
+	 * @param projectId
+	 * @return
+	 */
+	@PostMapping("/archiveAutoMethod")
+	public R archiveAutoMethod(Long projectId) {
+		archivesAutoService.splitArchvies(projectId);
+		archivesAutoService.archiveAutoMethod(projectId);
+		return R.data("");
+	}
+
+
+
 }

+ 12 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchiveExaminingReportDetailMapper.java

@@ -0,0 +1,12 @@
+package org.springblade.archive.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.springblade.archive.entity.ArchiveExaminingReportDetail;
+
+/**
+ * @Param
+ * @Author wangwl
+ * @Date 2023/4/21 15:11
+ **/
+public interface ArchiveExaminingReportDetailMapper extends BaseMapper<ArchiveExaminingReportDetail> {
+}

+ 5 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchiveExaminingReportDetailMapper.xml

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

+ 12 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchiveExaminingReportMapper.java

@@ -0,0 +1,12 @@
+package org.springblade.archive.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.springblade.archive.entity.ArchiveExaminingReport;
+
+/**
+ * @Param
+ * @Author wangwl
+ * @Date 2023/4/20 17:36
+ **/
+public interface ArchiveExaminingReportMapper extends BaseMapper<ArchiveExaminingReport> {
+}

+ 5 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchiveExaminingReportMapper.xml

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

+ 13 - 10
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.xml

@@ -115,10 +115,13 @@
 
     <update id="splitArchvies" >
         /**把未锁定案卷的文件关联去掉*/
-        update u_archive_file set archive_id = null where
+        update u_archive_file
+        set archive_id = null,
+            is_archive=0
+        where
             is_deleted=0 and
             archive_id in(
-                select id u_archives_auto where project_id=#{projectId}
+                select id from u_archives_auto where project_id=#{projectId}
                   and is_auto_file!=1
                   and is_deleted=0
                   and is_lock=0
@@ -131,15 +134,15 @@
     </update>
 
     <select id="getListByProjectId" resultType="org.springblade.archive.dto.ArchivesAutoDTO">
-        select id,project_id as projectId,name,unit,storage_time as storageTime,node_id as nodeId,tree_sort as treeSort,status,is_deleted as isDeleted,is_lock as isLock,create_time as createTime
+        select id,project_id as projectId,name,file_number as fileNumber,unit,storage_time as storageTime,node_id as nodeId,tree_sort as treeSort,status,is_deleted as isDeleted,is_lock as isLock,create_time as createTime
         from u_archives_auto
         where project_id=#{projectId};
     </select>
     <select id="pageByArchivesAuto" resultMap="archivesAutoResultMap">
-        select uaa.* from u_archives_auto uaa left join u_archive_file uaf on uaa.id = uaf.archive_id
+        select uaa.* from m_archive_tree_contract matc left join u_archives_auto uaa on matc.id = uaa.node_id left join u_archive_file uaf on uaa.id = uaf.archive_id
         where uaa.is_deleted = 0
         <if test="vo.projectId != null and vo.projectId != ''">
-            and uaa.project_id = #{vo.projectId}
+            and matc.project_id = #{vo.projectId}
         </if>
         <if test="vo.searchType == 1 and vo.queryValue != null and vo.queryValue != ''">
             and uaa.name like concat('%',#{vo.queryValue},'%')
@@ -181,14 +184,14 @@
     </select>
     <select id="getAllArchiveByContractType" resultType="org.springblade.archive.vo.ArchivesAutoVO">
         SELECT uaa.id,matc.tree_code as 'contractType'
-        FROM u_archives_auto uaa left join m_archive_tree_contract matc on uaa.node_id =matc.id
+        FROM m_archive_tree_contract matc left join u_archives_auto uaa on uaa.node_id =matc.id
         WHERE uaa.project_id =#{projectId} and uaa.is_deleted = #{type}
     </select>
     <select id="getAllArchiveAgeByContractType" resultType="java.util.Map">
-        SELECT CASE storage_time WHEN '10' THEN '10年' WHEN '30' THEN '30年' ELSE '永久' END as name,COUNT(storage_time) as value
-        FROM u_archives_auto uaa
-        WHERE project_id =#{projectId} and is_deleted =0
-        GROUP BY storage_time
+        SELECT CASE uaa.storage_time WHEN '10' THEN '10年' WHEN '30' THEN '30年' ELSE '永久' END as name,COUNT(uaa.storage_time) as value
+        FROM m_archive_tree_contract matc left join u_archives_auto uaa on uaa.node_id =matc.id
+        WHERE matc.project_id =#{projectId} and uaa.is_deleted =0
+        GROUP BY uaa.storage_time
     </select>
 
 

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

@@ -0,0 +1,12 @@
+package org.springblade.archive.service;
+
+import org.springblade.archive.entity.ArchiveExaminingReportDetail;
+import org.springblade.core.mp.base.BaseService;
+
+/**
+ * @Param
+ * @Author wangwl
+ * @Date 2023/4/21 15:10
+ **/
+public interface IArchiveExaminingReportDetailService extends BaseService<ArchiveExaminingReportDetail> {
+}

+ 20 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/service/IArchiveExaminingReportService.java

@@ -0,0 +1,20 @@
+package org.springblade.archive.service;
+
+import com.itextpdf.text.DocumentException;
+import org.springblade.archive.entity.ArchiveExaminingReport;
+import org.springblade.archive.vo.ArchiveExaminingVo;
+import org.springblade.core.mp.base.BaseService;
+
+import java.io.IOException;
+
+/**
+ * @Param
+ * @Author wangwl
+ * @Date 2023/4/20 17:35
+ **/
+public interface IArchiveExaminingReportService extends BaseService<ArchiveExaminingReport> {
+    void pushStatusBySocket(Long userId,Long id) throws IOException, InterruptedException;
+
+    void getExamining(ArchiveExaminingVo vo, Long id) throws InterruptedException, DocumentException, IOException;
+
+}

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

@@ -50,4 +50,8 @@ public interface IArchivesAutoService extends BaseService<ArchivesAuto> {
 	Map<String,Integer> getAllArchiveByContractType(Long projectId,String type);
 
 	List<Map<String, String>> getAllArchiveAgeByContractType(Long projectId);
+
+	void archiveAutoMethod(Long project);
+
+	void splitArchvies(Long project);
 }

+ 17 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchiveExaminingReportDetailServiceImpl.java

@@ -0,0 +1,17 @@
+package org.springblade.archive.service.impl;
+
+import org.springblade.archive.entity.ArchiveExaminingReportDetail;
+import org.springblade.archive.mapper.ArchiveExaminingReportDetailMapper;
+import org.springblade.archive.service.IArchiveExaminingReportDetailService;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * @Param
+ * @Author wangwl
+ * @Date 2023/4/21 15:10
+ **/
+@Service
+public class ArchiveExaminingReportDetailServiceImpl extends BaseServiceImpl<ArchiveExaminingReportDetailMapper, ArchiveExaminingReportDetail> implements IArchiveExaminingReportDetailService {
+
+}

+ 283 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchiveExaminingReportImpl.java

@@ -0,0 +1,283 @@
+package org.springblade.archive.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.aliyun.oss.OSSClient;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.itextpdf.text.*;
+import com.itextpdf.text.pdf.BaseFont;
+import com.itextpdf.text.pdf.PdfPCell;
+import com.itextpdf.text.pdf.PdfPTable;
+import com.itextpdf.text.pdf.PdfWriter;
+import lombok.AllArgsConstructor;
+import org.apache.commons.lang.StringUtils;
+import org.springblade.archive.entity.ArchiveExaminingReport;
+import org.springblade.archive.entity.ArchiveExaminingReportDetail;
+import org.springblade.archive.mapper.ArchiveExaminingReportMapper;
+import org.springblade.archive.service.IArchiveExaminingReportDetailService;
+import org.springblade.archive.service.IArchiveExaminingReportService;
+import org.springblade.archive.socket.WebSocketServer;
+import org.springblade.archive.vo.ArchiveExaminingSocketVo;
+import org.springblade.archive.vo.ArchiveExaminingVo;
+import org.springblade.common.constant.ArchiveConstant;
+import org.springblade.core.mp.base.BaseServiceImpl;
+import org.springblade.core.oss.model.BladeFile;
+import org.springblade.core.secure.BladeUser;
+import org.springblade.core.secure.utils.AuthUtil;
+import org.springblade.core.secure.utils.SecureUtil;
+import org.springblade.core.tool.utils.StringUtil;
+import org.springblade.resource.feign.NewIOSSClient;
+import org.springblade.resource.feign.NewISmsClient;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @Param
+ * @Author wangwl
+ * @Date 2023/4/20 17:36
+ **/
+@Service
+@AllArgsConstructor
+public class ArchiveExaminingReportImpl extends BaseServiceImpl<ArchiveExaminingReportMapper, ArchiveExaminingReport> implements IArchiveExaminingReportService {
+    private final WebSocketServer webSocketServer;
+
+    private final IArchiveExaminingReportDetailService detailService;
+
+    private final NewIOSSClient iossClient;
+    /**
+     * 推送状态到前端
+     * @param id
+     */
+    @Async
+    @Override
+    public void pushStatusBySocket(Long userId,Long id) throws IOException, InterruptedException {
+        Integer status;
+        //获取检测状态,如果正在检测,则一直推送
+        do {
+            Thread.sleep(5000L);
+            //获取最新检测的状态
+            ArchiveExaminingReport report = this.getById(id);
+            status = report.getStatus();
+            //获取检测详情
+            List<ArchiveExaminingReportDetail> list = detailService.list(new LambdaQueryWrapper<ArchiveExaminingReportDetail>()
+                    .eq(ArchiveExaminingReportDetail::getReportId, id));
+            for (ArchiveExaminingReportDetail detail : list) {
+                detail.setExaminingItem(detail.getExaminingType()+":"+detail.getExaminingItem());
+            }
+            ArchiveExaminingSocketVo vo = new ArchiveExaminingSocketVo(status,list);
+            webSocketServer.sendMessagesToArchive(userId+"", JSON.toJSONString(vo));
+            status = report.getStatus();
+        }while (status != 4);
+
+    }
+
+    /**
+     * 四性检测
+     * @param id
+     */
+    @Async
+    @Override
+    public void getExamining(ArchiveExaminingVo vo, Long id) throws InterruptedException, DocumentException, IOException {
+        ArchiveExaminingReport report = new ArchiveExaminingReport();
+        report.setId(id);
+        report.setStatus(2);
+        this.updateById(report);
+        //检测中
+            //真实性
+        if (StringUtils.isNotBlank(vo.getAuthenticity()) && "1".equals(vo.getAuthenticity())) {
+            Thread.sleep(7000L);
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_AUTHENTICITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对固化信息有效性检测", 0, "无", 0));
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_AUTHENTICITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对元数据项数据长度检测", 0, "无", 0));
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_AUTHENTICITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对元数据项数据类型、格式检测", 0, "无", 0));
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_AUTHENTICITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对设定值域的元数据项值域符合度检测", 0, "无", 0));
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_AUTHENTICITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对档号规范性检测", 0, "无", 0));
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_AUTHENTICITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对内容数据的电子属性一致性检测", 0, "无", 0));
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_AUTHENTICITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对元数据项数据重复性检测", 0, "无", 0));
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_AUTHENTICITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对元数据是否关联内容数据检测", 0, "无", 0));
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_AUTHENTICITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对信息包目录结构规范性检测", 0, "无", 0));
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_AUTHENTICITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对信息包一致性检测", 0, "无", 0));
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_AUTHENTICITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对电子档案封装包规范性检测", 0, "无", 0));
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_AUTHENTICITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对电子档案封装包电子前面有效性检测", 0, "无", 0));
+        }
+        if (StringUtils.isNotBlank(vo.getIntegrality()) && "1".equals(vo.getIntegrality())) {
+            Thread.sleep(7000L);
+            //完整性
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_INTEGRALITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对总件数相符性检测", 0, "无", 0));
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_INTEGRALITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对总字节数相符性检测", 0, "无", 0));
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_INTEGRALITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对元数据项完整性检测", 0, "无", 0));
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_INTEGRALITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对元数据必填著录项目检测", 0, "无", 0));
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_INTEGRALITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对过程信息完整性检测", 0, "无", 0));
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_INTEGRALITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对连续性元数据项检测", 0, "无", 0));
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_INTEGRALITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对内容数据完整性检测", 0, "无", 0));
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_INTEGRALITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对附件数据完整性检测", 0, "无", 0));
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_INTEGRALITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对归档范围检测", 0, "无", 0));
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_INTEGRALITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对信息包元数据完整性检测", 0, "无", 0));
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_INTEGRALITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对信息包内容数据完整性检测", 0, "无", 0));
+        }
+            //可用性
+        if (StringUtils.isNotBlank(vo.getUsability()) && "1".equals(vo.getUsability())) {
+            Thread.sleep(7000L);
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_USABILITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对信息包中元数据的可读性检测", 0, "无", 0));
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_USABILITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对目标数据库中的元数据可访问下检测", 0, "无", 0));
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_USABILITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对内容数据格式检测", 0, "无", 0));
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_USABILITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对内容数据的可读性检测", 0, "无", 0));
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_USABILITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对内容数据格式长期可用性检测", 0, "无", 0));
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_USABILITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对软硬件环境合规性检测", 0, "无", 0));
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_USABILITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对信息包中包含的内容数据格式合规性检测", 0, "无", 0));
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_USABILITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对备份数据可恢复性检测", 0, "无", 0));
+        }
+            //安全性
+        if (StringUtils.isNotBlank(vo.getSecurity()) && "1".equals(vo.getSecurity())) {
+            Thread.sleep(7000L);
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_SECURITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对系统环境中是否安装杀毒软件检测", 0, "无", 0));
+            detailService.save(new ArchiveExaminingReportDetail(vo.getProjectId(), id, ArchiveConstant.ARCHIVE_EXAMINING_SECURITY,
+                    ArchiveConstant.ARCHIVE_EXAMINING_STANDARD + "对病毒感染检测", 0, "无", 0));
+        }
+        //生成报告,生成PDF
+        report.setStatus(3);
+        this.updateById(report);
+        String url = this.generateReportPdf(id);
+        Thread.sleep(7000L);
+        //完成
+        report.setReportPdfUrl(url);
+        report.setStatus(4);
+        this.updateById(report);
+    }
+
+    /**
+     * 生成检测报告PDF
+     */
+    private String generateReportPdf(Long id) throws DocumentException, IOException {
+        int high = 20;
+        int widthPercentage = 100;
+        String uuid = StringUtil.randomUUID();
+        String localUrl = "/www/wwwroot/Users/hongchuangyanfa/Desktop/archiveExaminingPdf/";
+        //新建一个pdf文档对象,前一个参数是纸张大小,后四个为边距
+        Document document = new Document(PageSize.A4, 5, 5, 30, 30);
+        //建立一个书写器
+        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(localUrl+uuid+".pdf"));
+        document.open();
+        //创建字体
+        BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
+        //字体对象,这里可以创建一个方法
+        Font size14font = new Font(baseFont, 14, Font.BOLD);  //大小为14的正常字体
+        Font size10font = new Font(baseFont, 10, Font.NORMAL); //大小为10的正常字体
+        Font size10font2 = new Font(baseFont, 10, Font.BOLD); //大小为10的正常字体
+        //添加标题
+        //创建第一行表格
+        PdfPTable tableName = new PdfPTable(1);
+        tableName.setWidthPercentage(widthPercentage);  //设置标题长度占纸张比例
+        //给表格赋值
+        tableName.addCell(pdfTableStyle("电子文件四性检测报告", size14font, 50, true, true));
+        //将表格添加到文档对象中
+        document.add(tableName);
+        //依据文献
+        PdfPTable two = new PdfPTable(1);
+        two.setWidthPercentage(widthPercentage);
+        two.addCell(pdfTableStyle("依据文献:\n" +
+                "[1]文书类电子档案检测一般要求:DA/T 70-2018   [2] 电子档案“四性”检测要求及其实现方法[J].浙江档案\n" +
+                "出具系统电子文件归档真实性、完整性、可用性、安全性检测报告",size10font,37,false,false));
+        document.add(two);
+        //表头文字
+        String[] name = new String[]{"检测类别", "检测项目", "统计不合格", "不合格对象"};
+        //创建第二行,并设置第二行中的表格数
+        PdfPTable twoTable = new PdfPTable(name.length);
+        twoTable.setWidthPercentage(widthPercentage);
+        //该数组是每个表格的宽度
+        float[] floats = new float[name.length];
+        floats[0] = 0.1f;
+        floats[1] = 0.7f;
+        floats[2] = 0.1f;
+        floats[3] = 0.1f;
+        //循环将表头数据添加到第二行表格中
+        for (int i = 0; i < name.length; i++) {
+            PdfPCell pdfPCell = pdfTableStyle(name[i], size10font2, high, true, true);
+            pdfPCell.setBackgroundColor(new BaseColor(231,230,230));
+            twoTable.addCell(pdfPCell);
+        }
+        //设置表格的宽度
+        twoTable.setTotalWidth(floats);
+        document.add(twoTable);
+        //表单数据
+        List<ArchiveExaminingReportDetail> list = detailService.list(new LambdaQueryWrapper<ArchiveExaminingReportDetail>()
+                .eq(ArchiveExaminingReportDetail::getReportId, id));
+        //将数据放入表格中
+        for (int i = 0; i < list.size(); i++) {
+            ArchiveExaminingReportDetail detail = list.get(i);
+            PdfPTable dataTable = new PdfPTable(name.length);
+            dataTable.setWidthPercentage(widthPercentage);
+            dataTable.setTotalWidth(floats);
+            //将数组中的数据按照顺序添加
+            dataTable.addCell(pdfTableStyle(detail.getExaminingType(), size10font, high, true, true));
+            dataTable.addCell(pdfTableStyle(detail.getExaminingItem(), size10font, high, false, true));
+            dataTable.addCell(pdfTableStyle(detail.getUnqualifiedCount()+"", size10font, high, true, true));
+            dataTable.addCell(pdfTableStyle(detail.getUnqualifiedObject(), size10font, high, true, true));
+            document.add(dataTable);
+
+        }
+        document.close();
+        writer.close();
+        BladeFile bladeFile = iossClient.uploadFile(uuid+".pdf", localUrl+uuid+".pdf");
+        return bladeFile.getLink();
+    }
+
+
+    /**
+     * 表格的样式
+     * @param content 内容
+     * @param font 字体对象
+     * @param high 表格高度
+     * @Param isAlignCenter 是否水平居中
+     * @Param isAlignMidde  是否垂直居中
+     * @return
+     */
+    static PdfPCell pdfTableStyle(String content, Font font, int high, boolean isAlignCenter, boolean isAlignMidle){
+        PdfPCell pdfPCell  = new PdfPCell(new Phrase(content,font));
+        pdfPCell.setMinimumHeight(high);
+        pdfPCell.setUseAscender(true); // 设置可以居中
+        if (isAlignCenter){
+            pdfPCell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER); // 设置水平居中
+        }
+        if (isAlignMidle){
+            pdfPCell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE); // 设置垂直居中
+        }
+        return pdfPCell;
+    }
+}

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

@@ -224,7 +224,7 @@ public class ArchiveOfflineVersionInfoServiceImpl extends BaseServiceImpl<Archiv
                     pstm.setLong(1, auto.getId());
                     pstm.setLong(2, auto.getProjectId());
                     pstm.setString(3, auto.getName());
-                    pstm.setString(4, auto.getFileNumber());
+                    pstm.setString(4, auto.getFileNumber() == null ? "" :auto.getFileNumber());
                     pstm.setString(5, auto.getUnit());
                     pstm.setString(6, auto.getStorageTime());
                     pstm.setInt(7, auto.getIsArchive() == null ? 0 : 1);

+ 158 - 28
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java

@@ -45,6 +45,8 @@ import org.springblade.manager.feign.ContractClient;
 import org.springblade.manager.feign.ProjectClient;
 import org.springblade.manager.feign.WbsInfoClient;
 import org.springblade.manager.vo.ArchiveTreeContractVO2;
+import org.springblade.manager.feign.ContractClient;
+import org.springblade.manager.feign.ProjectClient;
 import org.springblade.system.entity.DictBiz;
 import org.springblade.system.feign.IDictBizClient;
 import org.springframework.stereotype.Service;
@@ -68,6 +70,8 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 	private ArchiveFileClient archiveFileClient;
 	private ArchiveTreeContractClient archiveTreeContractClient;
 	private ContractClient contractClient;
+	private ProjectClient projectClient;
+
 	private Map<String,Integer> indexMap; //按立卷位区分和生成流水号
 	private IArchiveAutoPdfService archiveAutoPdfService;
 
@@ -210,11 +214,15 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		List<Map<String,String>> list = baseMapper.getAllArchiveAgeByContractType(projectId);
 		return list;
 	}
+	@Override
+	public void splitArchvies(Long projectId){
+		baseMapper.splitArchvies(projectId);
+	}
 
-
+	@Override
 	public void archiveAutoMethod(Long projectId){
 		//步骤一:把项目下未锁定的案卷拆卷。
-		baseMapper.splitArchvies(projectId);
+
 		//步骤二:查询归档树节点。存在未归档文件的节点。
 		List<ArchiveTreeContract> list = archiveTreeContractClient.getHavedFileNodeByProjectID(projectId);
 		//步骤三:遍历归档树节点整理出 默认规则节点,分类并卷节点,单独组卷节点 三个集合。
@@ -235,10 +243,28 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 					break;
 			}
 		}
-		//步骤四:按照单独,分类,默认的顺序执行组卷流程。
-		archiveAutoMethod3(list3);//单独组卷
-		archiveAutoMethod2(list2,projectId);//分类组卷
-		archiveAutoMethod1(list1);//默认组卷
+		//步骤四:按照单独,分类,默认,分盒的顺序执行组卷流程。
+
+		//分盒文件集合
+		Map<Integer,List<ArchiveFile>> boxMap = new HashMap<>();
+
+		archiveAutoMethod3(list3,boxMap);//单独组卷
+		archiveAutoMethod2(list2,projectId,boxMap);//分类组卷
+		archiveAutoMethod1(list1,boxMap);//默认组卷
+		archiveAutoMethodBox(boxMap);//分盒组卷
+	}
+
+	private void addBoxMap(ArchiveFile file,Map<Integer,List<ArchiveFile>> boxMap){
+		Integer boxNumber = file.getBoxNumber();
+		if(boxMap.containsKey(boxNumber)){
+			List<ArchiveFile> boxFiles = boxMap.get(boxNumber);
+			boxFiles.add(file);
+			boxMap.put(boxNumber,boxFiles);
+		}else{
+			List<ArchiveFile> boxFiles = new ArrayList<>();
+			boxFiles.add(file);
+			boxMap.put(boxNumber,boxFiles);
+		}
 	}
 
 
@@ -284,19 +310,39 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		archivesAuto.setContractId(node.getContractId());
 		archivesAuto.setName(archiveName);//案卷题名
 		if(indexMap==null){
-			indexMap=new HashMap<>();
+			indexMap=new HashMap<>(); //监理,施工的按合同段分类从0开始依次设置档号,建设单位的没有合同段 就先按一类依次设置
 		}
-		//TODO 获取立卷单位
+
+		//获取立卷单位
 		String unit="";
+		String treeCode = node.getTreeCode();
+		if(StringUtils.isEmpty(treeCode)){
+			//treeCode为null的是业主的节点
+			List<Long> pids = new ArrayList<>();
+			pids.add(node.getProjectId());
+			List<ContractInfo> contractInfos = contractClient.getContractByIds(pids);
+			for(ContractInfo contract:contractInfos){
+				if(contract.getContractType()==3){
+					unit=contract.archivesUnit();
+				}
+			}
+		}else{
+			//treeCode不为null则是对应合同段
+			ContractInfo contract = contractClient.getContractById(Long.parseLong(treeCode));
+			unit=contract.archivesUnit();
+		}
 		//获取档号
+		if(StringUtils.isEmpty(treeCode)){
+			treeCode="owner";
+		}
 		String fileNumberPrefix=node.getFileNumberPrefix(); //档号前缀在节点设置
 		Integer fileNumberSuffix = null;//档号后缀按立卷单位生成流水号
-		if(indexMap.containsKey(unit)){
-			fileNumberSuffix = indexMap.get(unit);
-			indexMap.put(unit,fileNumberSuffix+1);
+		if(indexMap.containsKey(treeCode)){
+			fileNumberSuffix = indexMap.get(treeCode);
+			indexMap.put(treeCode,fileNumberSuffix+1);
 		}else{
 			fileNumberSuffix=1;
-			indexMap.put(unit,fileNumberSuffix+1);
+			indexMap.put(treeCode,fileNumberSuffix+1);
 		}
 
 		archivesAuto.setFileNumber(fileNumberPrefix+fileNumberSuffix);//档号
@@ -305,8 +351,8 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		//archivesAuto.setQuantity();//数量/单位
 
 		archivesAuto.setSpecification(node.getSpecification());//案卷规格 从节点规格获取
-		archivesAuto.setStartDate(LocalDateTime.parse(startDate));//文件开始时间
-		archivesAuto.setEndDate(LocalDateTime.parse(endDate));//文件结束时间
+		//archivesAuto.setStartDate(LocalDateTime.parse(startDate));//文件开始时间
+		//archivesAuto.setEndDate(LocalDateTime.parse(endDate));//文件结束时间
 		archivesAuto.setStorageTime(node.getStorageTime());//保管期限  从节点规格获取
 		archivesAuto.setSecretLevel("");//保密级别 没地方设置 暂留
 		//载体类型
@@ -350,8 +396,37 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 	}
 
 	private String builtArchiveName(List<ArchiveFile> waitArchiveFiles, ArchiveTreeContract node,boolean isCrossNode){
-		//TODO 获取案卷题名
-		return "";
+
+		String archiveName="";
+
+		Long projectId = node.getProjectId();
+		ProjectInfo projectInfo = projectClient.getById(String.valueOf(projectId));
+		String projectName = projectInfo.getProjectName();
+		//获取案卷题名
+		//--正常节点
+		if(isCrossNode){
+			archiveName=projectName;
+			//存在跨节点  项目名称+文件对应的所有节点名称
+			Set<String> nodeIdSet = new HashSet<>();
+			for(ArchiveFile file:waitArchiveFiles){
+				String nodeId = file.getNodeId();
+				nodeIdSet.add(nodeId);
+			}
+			for(String nodeId:nodeIdSet){
+				ArchiveTreeContract treeNode = archiveTreeContractClient.getArchiveTreeContractById(Long.parseLong(nodeId));
+				String nodeName = treeNode.getNodeName();
+				archiveName=archiveName+nodeName;
+			}
+
+		}else{
+			//不存在跨节点  项目名称+节点名称
+			archiveName=projectName+node.getNodeName();
+		}
+
+		//TODO wbs节点
+		//不存在跨节点 项目名称+案卷题名规则(在后台归档目录树设置的)+后缀
+		//存在跨节点  获取当前所有节点的父级节点题名规则+所有同层级跨节点并卷的节点名称拼接+后缀
+		return archiveName;
 	}
 	private String builtFilePageNo(ArchivesAuto archivesAuto,List<ArchiveFile> waitArchiveFiles){
 		//TODO 生成文件对应的页码,返回url
@@ -483,11 +558,55 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		archiveFileClient.updateArchiveFileForCreateArchive(waitArchiveFiles);
 	}
 
+	private void createArchiveBox(List<ArchiveFile> waitArchiveFiles){
+
+		if(waitArchiveFiles.size()==0){
+			return;
+		}
+
+		String nodeId = waitArchiveFiles.get(0).getNodeId();
+
+		ArchiveTreeContract node = archiveTreeContractClient.getArchiveTreeContractById(Long.parseLong(nodeId));
+
+		//获取案卷文件起止时间
+		String archiveStartDateAndEndDate = getArchiveStartDateAndEndDate(waitArchiveFiles);
+		String[] split = archiveStartDateAndEndDate.split(",");
+		String startDate=split[0];
+		String endDate=split[1];
+		int fileN =waitArchiveFiles.size();
+		//获取案卷内文件总页数
+		int pageN=0;
+		for(ArchiveFile file:waitArchiveFiles){
+			pageN=pageN+file.getFilePage();
+		}
+
+
+		//默认组卷存在跨节点组卷  注意案卷归属节点,案卷命名方式
+		//获取案卷题名
+		String archiveName=builtArchiveName(waitArchiveFiles,node,false);//获取案卷题名
+
+		//1.创建新案卷
+		ArchivesAuto archivesAuto = builtArchives(node,pageN,fileN,startDate,endDate,archiveName);
+
+		//2.封面和生成文件页码
+		archiveAutoPdfService.buildArchiveFrontPdfs(archivesAuto.getProjectId(),archivesAuto,waitArchiveFiles);
+
+		builtFilePageNo(archivesAuto,waitArchiveFiles);
+
+		//3.设置文件所属案卷,组卷状态
+		Long archivesAutoId = archivesAuto.getId();
+		for(ArchiveFile file:waitArchiveFiles){
+			file.setArchiveId(archivesAutoId);//设置文件所属案卷
+			file.setIsArchive(1);
+		}
+		archiveFileClient.updateArchiveFileForCreateArchive(waitArchiveFiles);
+	}
+
 
 	/**
 	 * 单租组卷流程  节点下的文件只在当前节点下组卷
 	 */
-	private void archiveAutoMethod3(List<ArchiveTreeContract> list){
+	private void archiveAutoMethod3(List<ArchiveTreeContract> list,Map<Integer,List<ArchiveFile>> boxMap){
 		//步骤1:遍历节点集合
 		for(ArchiveTreeContract node:list){
 			//步骤2:获取当前节点的案卷规格
@@ -511,7 +630,8 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 					archiveFilesSize++;
 					//步骤5:判断文件是否存在分盒设置
 					if(file.getBoxNumber()!=null){
-						//TODO 走分盒组卷流程
+						//添加到分盒文件集合
+						addBoxMap(file,boxMap);
 						if(archiveFilesSize==archiveFiles.size() && waitArchiveFiles.size()>0){
 							//最后一个文件直接将waitArchiveFiles组卷
 							createArchive3(waitArchiveFiles,node,archivesSize);
@@ -581,7 +701,7 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 	/**
 	 * 分类并卷组卷  设置分类的节点下只有一个案卷,节点下的所有文件都组成这个案卷。如果设置分类节点(select=1的)多个,案卷归属排序第一个节点。
 	 */
-	private void archiveAutoMethod2(List<ArchiveTreeContract> list,Long projectId){
+	private void archiveAutoMethod2(List<ArchiveTreeContract> list,Long projectId,Map<Integer,List<ArchiveFile>> boxMap){
 
 		//分类并卷集合<groupId,List<文件>>
 		Map<Long,List<ArchiveFile>> archiveMap = new HashMap<>();
@@ -593,17 +713,14 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 			//根据分组ID来创建唯一案卷
 			Long archiveAutoGroupId=node.getArchiveAutoGroupId();
 			//步骤2:查询节点下的未归档文件
-			List<ArchiveFile> archiveFiles = archiveFileClient.listWrappers(Wrappers.<ArchiveFile>lambdaQuery()
-					.eq(ArchiveFile::getNodeId, node)
-					.eq(ArchiveFile::getIsArchive, 0)
-					.eq(ArchiveFile::getIsDeleted,0)
-					.orderByAsc(ArchiveFile::getSort));
+			List<ArchiveFile> archiveFiles = archiveFileClient.getListByNodeID(node.getId().toString(),0);
 			//步骤3:遍历未归档文件
 			if(archiveFiles!=null){
 				for(ArchiveFile file:archiveFiles){
 					//步骤4:判断文件是否存在分盒设置
-					if(file.getBoxNumber()!=null){
-						//TODO 走分盒流程
+					if(file.getBoxNumber()!=null && file.getBoxNumber()!=-1){
+						//添加到分盒文件集合
+						addBoxMap(file,boxMap);
 					}else{
 						//分类并卷流程
 						//步骤5:将文件按照<groupId,List<文件>>放入集合
@@ -635,7 +752,7 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 	/**
 	 * 默认组卷流程 文件可以跨节点组卷,受最高并卷节点限制范围,跨节点文件组卷时,案卷规格按照第一个文件所在的节点规格 组卷。
 	 */
-	private void archiveAutoMethod1(List<ArchiveTreeContract> list){
+	private void archiveAutoMethod1(List<ArchiveTreeContract> list,Map<Integer,List<ArchiveFile>> boxMap){
 		//最高并卷节点
 		Long archiveAutoNodeId=null;
 
@@ -689,7 +806,8 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 				archiveFilesSize++;
 				//步骤3.4:判断文件是否存在分盒设置
 				if(file.getBoxNumber()!=null) {
-					//TODO 走分盒组卷流程
+					//添加到分盒文件集合
+					addBoxMap(file,boxMap);
 					if(nodeSize==list.size() && archiveFilesSize==archiveFiles.size()){
 						//如果当前是最后一个文件直接将waitArchiveFiles组卷
 						createArchive1(waitArchiveFiles,archivesSize);
@@ -765,6 +883,18 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 
 	}
 
+	/**
+	 * 分盒组卷流程
+	 * @param boxMap
+	 */
+	private void archiveAutoMethodBox(Map<Integer,List<ArchiveFile>> boxMap){
+		Set<Map.Entry<Integer, List<ArchiveFile>>> entries = boxMap.entrySet();
+		for (Map.Entry<Integer, List<ArchiveFile>> entry:entries){
+			//一个分盒一个案卷 归属第一个文件所在节点
+			createArchiveBox(entry.getValue());
+		}
+	}
+
 	/**
 	 * 查询案卷,排序
 	 * @param ids

+ 35 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/socket/WebSocketConfig.java

@@ -0,0 +1,35 @@
+package org.springblade.archive.socket;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.messaging.simp.config.MessageBrokerRegistry;
+import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
+import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
+import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
+import org.springframework.web.socket.server.standard.ServerEndpointExporter;
+
+@Configuration
+@EnableWebSocketMessageBroker
+public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
+
+    @Bean
+    public ServerEndpointExporter serverEndpointExporter() {
+        return new ServerEndpointExporter();
+    }
+
+    @Override
+    public void registerStompEndpoints(StompEndpointRegistry registry){
+        registry.addEndpoint("/websocket")
+                .setAllowedOrigins("*") //跨域
+                .withSockJS();
+    }
+
+    @Override
+    public void configureMessageBroker(MessageBrokerRegistry registry){
+        registry.enableSimpleBroker("*");
+        registry.setApplicationDestinationPrefixes("*");
+        registry.setUserDestinationPrefix("*");
+    }
+
+}
+

+ 142 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/socket/WebSocketServer.java

@@ -0,0 +1,142 @@
+package org.springblade.archive.socket;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import javax.websocket.*;
+import javax.websocket.server.PathParam;
+import javax.websocket.server.ServerEndpoint;
+import java.io.IOException;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * @Param
+ * @Author wangwl
+ * @Date 2023/4/19 15:35
+ **/
+@ServerEndpoint("/websocket/archive/{userId}")
+@Component
+public class WebSocketServer {
+
+    private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);
+
+    /**
+     * 当前在线连接数
+     */
+    private static AtomicInteger onlineCount = new AtomicInteger(0);
+
+    /**
+     * 用来存放每个客户端对应的 WebSocketServer 对象
+     */
+    private static ConcurrentHashMap<String, WebSocketServer> webSocketMap = new ConcurrentHashMap<>();
+
+    /**
+     * 与某个客户端的连接会话,需要通过它来给客户端发送数据
+     */
+    private Session session;
+
+    /**
+     * 接收 userId
+     */
+    private String userId = "";
+
+    /**
+     * 连接建立成功调用的方法
+     */
+    @OnOpen
+    public void onOpen(Session session, @PathParam("userId") String userId) {
+        this.session = session;
+        this.userId = userId;
+        if (webSocketMap.containsKey(userId)) {
+            webSocketMap.remove(userId);
+            webSocketMap.put(userId, this);
+        } else {
+            webSocketMap.put(userId, this);
+            addOnlineCount();
+        }
+        log.info("用户连接:" + userId + ",当前在线人数为:" + getOnlineCount());
+        try {
+            sendMessage("连接成功!");
+        } catch (IOException e) {
+            log.error("用户:" + userId + ",网络异常!!!!!!");
+        }
+    }
+
+    /**
+     * 连接关闭调用的方法
+     */
+    @OnClose
+    public void onClose() {
+        if (webSocketMap.containsKey(userId)) {
+            webSocketMap.remove(userId);
+            subOnlineCount();
+        }
+        log.info("用户退出:" + userId + ",当前在线人数为:" + getOnlineCount());
+    }
+
+    /**
+     * 收到客户端消息后调用的方法
+     *
+     * @param message 客户端发送过来的消息
+     */
+    @OnMessage
+    public void onMessage(String message, Session session) {
+        log.info("用户消息:" + userId + ",报文:" + message);
+        if (!StringUtils.isEmpty(message)) {
+            try {
+                JSONObject jsonObject = JSON.parseObject(message);
+                jsonObject.put("fromUserId", this.userId);
+                String toUserId = jsonObject.getString("toUserId");
+                if (!StringUtils.isEmpty(toUserId) && webSocketMap.containsKey(toUserId)) {
+                    webSocketMap.get(toUserId).sendMessage(jsonObject.toJSONString());
+                } else {
+                    log.error("请求的 userId:" + toUserId + "不在该服务器上");
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    public void sendMessagesToArchive(String user,String str) throws IOException {
+        if (webSocketMap.get(user) != null) {
+            webSocketMap.get(user).sendMessage(str);
+        }
+    }
+
+    /**
+     * 发生错误时调用
+     *
+     * @param session
+     * @param error
+     */
+    @OnError
+    public void onError(Session session, Throwable error) {
+        log.error("用户错误:" + this.userId + ",原因:" + error.getMessage());
+        error.printStackTrace();
+    }
+
+    /**
+     * 实现服务器主动推送
+     */
+    public void sendMessage(String message) throws IOException {
+        this.session.getBasicRemote().sendText(message);
+    }
+
+    public static synchronized AtomicInteger getOnlineCount() {
+        return onlineCount;
+    }
+
+    public static synchronized void addOnlineCount() {
+        WebSocketServer.onlineCount.getAndIncrement();
+    }
+
+    public static synchronized void subOnlineCount() {
+        WebSocketServer.onlineCount.getAndDecrement();
+    }
+}

+ 13 - 0
blade-service/blade-archive/src/main/resources/application-dev.yml

@@ -2,9 +2,22 @@
 server:
   port: 8686
 
+#默认对象存储配置
+oss:
+  enabled: true
+  name: minio
+  tenant-mode: true
+  endpoint: http://127.0.0.1:9000
+  access-key: D99KGE6ZTQXSATTJWU24
+  secret-key: QyVqGnhIQQE734UYSUFlGOZViE6+ZlDEfUG3NjhJ
+  bucket-name: bladex
+
 #数据源配置
 spring:
   datasource:
     url: ${blade.datasource.dev.url}
     username: ${blade.datasource.dev.username}
     password: ${blade.datasource.dev.password}
+
+
+

+ 193 - 166
blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java

@@ -116,6 +116,7 @@ public class InformationWriteQueryController extends BladeController {
     @Autowired
     StringRedisTemplate RedisTemplate;
 
+
     /**
      * 获取文件题名
      */
@@ -1327,6 +1328,18 @@ public class InformationWriteQueryController extends BladeController {
     @ApiOperationSupport(order = 15)
     @ApiOperation(value = "复制节点(新)")
     public R<Boolean> copyContractTreeNode(@RequestBody CopyContractTreeNodeVO vo) {
+        //表单所属方
+        String tabOwner = "";
+        if (("1,2").equals(vo.getClassifyType()) || ("2,1").equals(vo.getClassifyType())) {
+            tabOwner = "1,2,3,4,5,6";
+        } else if (("1").equals(vo.getClassifyType())) {
+            tabOwner = "1,2,3";
+        } else if (("2").equals(vo.getClassifyType())) {
+            tabOwner = "4,5,6";
+        } else if (vo.getIsCopyData() == 0) {
+            tabOwner = "1,2,3,4,5,6"; //如果选择的是否复制数据=0(否),默认所属方123456
+        }
+
         //TODO 单份复制
         if (("1").equals(vo.getCopyType())) {
             //首先查询需要复制的节点及其下级所有子节点的信息
@@ -1355,6 +1368,7 @@ public class InformationWriteQueryController extends BladeController {
                     nodeMap.put(node.getId().toString(), node);
                 });
 
+                String finalTabOwner1 = tabOwner;
                 nodeChildAll.forEach(node -> {
                     WbsTreeContract newData = new WbsTreeContract();
                     BeanUtils.copyProperties(node, newData);
@@ -1404,29 +1418,31 @@ public class InformationWriteQueryController extends BladeController {
                         //生成施工日志
                         this.createLedger(newData, saveLedger, nodeMap, null);
                     }
-
+                    //表单所属方,只有勾选了对应的所属方权限才复制数据;勾选了复制数据才能复制,否则只是创建节点、表
                     // 组织复制值Sql
-                    if (nodeTabColsMap != null && node.getType() == 2 && StringUtils.isNotEmpty(newData.getInitTableName())) {
+                    if (node.getType() == 2 && StringUtils.isNotEmpty(newData.getInitTableName()) && finalTabOwner1.contains(node.getTableOwner()) && vo.getIsCopyData() == 1) {
                         String tableName = newData.getInitTableName();
                         String col = nodeTabColsMap.get(tableName);
                         String colVal = nodeTabColsMap.get(tableName);
                         colVal = colVal.replaceAll("id,p_key_id,", "'" + SnowFlakeUtil.getId() + "' as id,'" + newData.getPKeyId() + "' as p_key_id,");
-                        copeSql.append("insert into " + tableName + "  (" + col + ") select " + colVal + " from " + tableName + " where p_key_id='" + node.getPKeyId() + "' ;");
+                        //delete SQL (先删除旧数据,再新增)
+                        String delSql = "delete from " + tableName + " where p_key_id = " + newData.getPKeyId() + " ; ";
+                        //insert into SQL
+                        copeSql.append(delSql).append("insert into ").append(tableName).append("  (").append(col).append(") select ").append(colVal).append(" from ").append(tableName).append(" where p_key_id='").append(node.getPKeyId()).append("' ;");
                     }
                 });
             }
             //保存节点信息
             R<Boolean> booleanR = this.saveOrCopyNodeTree(saveList, saveLedger, 32, needCopyNode);
-
             //复制数据逻辑
-            if (nodeTabColsMap != null && copeSql.length() >= 10) {
+            if (copeSql.length() >= 10) {
                 jdbcTemplate.execute(copeSql.toString());
             }
-
             //获取父节点信息
             informationQueryService.AsyncWbsTree(needCopyNode.getParentId() + "", needCopyNode.getParentId() + "", needCopyNode.getContractId(), "", "1");
             return booleanR;
 
+        } else if (("2").equals(vo.getCopyType())) {
             /** TODO 多份复制
              * @Author liuYC
              * @Date 2023年4月10日18:06:53
@@ -1439,8 +1455,6 @@ public class InformationWriteQueryController extends BladeController {
              *      2.1 如果点击选择的是其他父级节点的父级,那么新增一个新的当前选择的复制的节点-新的表-新的表数据(根据所属方查询对应数据)。
              *      2.2 如果点击选择的是当前复制节点本身的同等级节点,那么复制对应表数据,如果没有对应表,那么跳过。
              */
-        } else if (("2").equals(vo.getCopyType())) {
-
             //获取需要复制到的位置节点信息的集合
             List<CopyContractTreeNodeVO.CopyBatch> copyBatches = vo.getCopyBatchToPaths();
             if (copyBatches.size() > 0) {
@@ -1457,151 +1471,150 @@ public class InformationWriteQueryController extends BladeController {
                     }
                 }
 
-                //缓存需要的节点信息、表信息
                 WbsTreeContract needCopyNodeRoot = this.wbsTreeContractClient.getContractNodeByPrimaryKeyId(vo.getNeedCopyPrimaryKeyId());
-                Map<String, List<WbsTreeContract>> needCopyNodeAndTabMap = new HashMap<>();
-                List<WbsTreeContract> needCopyChildNodes = this.getChildNodes(needCopyNodeRoot);
-                if (ObjectUtil.isEmpty(needCopyChildNodes) || needCopyChildNodes.size() == 0) {
-                    //最下层级节点复制
-                    needCopyChildNodes = new ArrayList<>();
-                    needCopyChildNodes.add(needCopyNodeRoot);
-                }
-                needCopyNodeAndTabMap.put("node:" + needCopyNodeRoot.getPKeyId(), needCopyChildNodes);
-                List<WbsTreeContract> addChildNodesTables = this.getChildNodesTables(needCopyChildNodes, needCopyNodeRoot.getContractId());
-                needCopyNodeAndTabMap.put("tab:" + needCopyNodeRoot.getPKeyId(), addChildNodesTables);
-
-                //TODO 结果集
-                //节点
-                List<WbsTreeContract> addNodeList = new ArrayList<>();
-                //表单
-                List<WbsTreeContract> addTabList = new ArrayList<>();
-                //redis同步信息
-                List<WbsTreeContract> asyncWbsTreeNodes = new ArrayList<>();
-                //表单附件数据源
-                Set<WbsTreeContract> addChildNodesTablesOldAll = new HashSet<>(addChildNodesTables);
-                //表单数据
-                List<String> resultTablesData = new ArrayList<>();
-
-                //表单所属方
-                String tabOwner = "";
-                if (("1,2").equals(vo.getClassifyType()) || ("2,1").equals(vo.getClassifyType())) {
-                    tabOwner = "1,2,3,4,5,6";
-                } else if (("1").equals(vo.getClassifyType())) {
-                    tabOwner = "1,2,3";
-                } else if (("2").equals(vo.getClassifyType())) {
-                    tabOwner = "4,5,6";
-                } else if (vo.getIsCopyData() == 0 && StringUtils.isEmpty(tabOwner)) {
-                    //如果选择的是否复制数据=0(否),默认所属方123456
-                    tabOwner = "1,2,3,4,5,6";
-                }
-
-                //创建线程池,默认设置8个线程
-                ExecutorService executor = Executors.newFixedThreadPool(8);
-                try {
-                    //解析位置信息,进行复制数据构造
-                    if (toCopyNodes.size() == copyBatches.size()) {
-                        for (int i = 0; i < toCopyNodes.size(); i++) {
-                            //首先查询需要复制的节点的信息
-                            WbsTreeContract toCopyNode = toCopyNodes.get(i);
-                            CopyContractTreeNodeVO.CopyBatch toCopyVO = copyBatches.get(i);
-
-                            String finalTabOwner = tabOwner;
-                            //使用线程池提交任务
-                            executor.submit(() -> {
-                                //redis缓存node
+                if (needCopyNodeRoot != null) {
+                    //缓存需要复制的节点信息、表信息
+                    Map<String, List<WbsTreeContract>> needCopyNodeAndTabMap = new HashMap<>();
+                    List<WbsTreeContract> needCopyChildNodes = this.getChildNodes(needCopyNodeRoot);
+                    if (ObjectUtil.isEmpty(needCopyChildNodes) || needCopyChildNodes.size() == 0) {
+                        //最下层级节点复制
+                        needCopyChildNodes = new ArrayList<>();
+                        needCopyChildNodes.add(needCopyNodeRoot);
+                    }
+                    needCopyNodeAndTabMap.put("node:" + needCopyNodeRoot.getPKeyId(), needCopyChildNodes);
+                    List<WbsTreeContract> addChildNodesTables = this.getChildNodesTables(needCopyChildNodes, needCopyNodeRoot.getContractId());
+                    needCopyNodeAndTabMap.put("tab:" + needCopyNodeRoot.getPKeyId(), addChildNodesTables);
+
+                    //结果集
+                    List<WbsTreeContract> addNodeList = new ArrayList<>();//节点
+                    List<WbsTreeContract> addTabList = new ArrayList<>(); //表单
+                    List<WbsTreeContract> asyncWbsTreeNodes = new ArrayList<>(); //redis同步信息
+                    Set<WbsTreeContract> addChildNodesTablesOldAll = new HashSet<>(addChildNodesTables);//表单附件数据源
+                    List<String> resultTablesData = new ArrayList<>();//表单数据
+
+                    //创建线程池,默认设置4个线程
+                    ExecutorService executor = Executors.newFixedThreadPool(4);
+                    try {
+                        //解析位置信息,进行复制数据构造
+                        if (toCopyNodes.size() == copyBatches.size()) {
+                            for (int i = 0; i < toCopyNodes.size(); i++) {
+                                WbsTreeContract needCopyNode = this.wbsTreeContractClient.getContractNodeByPrimaryKeyId(vo.getNeedCopyPrimaryKeyId());
+                                //首先查询需要复制的节点的信息
+                                WbsTreeContract toCopyNode = toCopyNodes.get(i);
+                                CopyContractTreeNodeVO.CopyBatch toCopyVO = copyBatches.get(i);
                                 asyncWbsTreeNodes.add(toCopyNode);
+                                String finalTabOwner = tabOwner;
+                                executor.submit(() -> {
+                                    if (toCopyNode != null && toCopyVO != null && needCopyNodeAndTabMap.size() > 0) {
+                                        //TODO 同节点复制
+                                        if (new Integer(1).equals(toCopyVO.getIsSameNode())) {
+                                            //1.1 选择当前节点的父级节点,新增
+                                            if (needCopyNode.getParentId().equals(toCopyNode.getId())) {
+                                                toCopyNode.setNodeName(toCopyVO.getNodeName());
+                                                toCopyNode.setPartitionCode(toCopyVO.getPartitionCode());
+
+                                                //获取缓存节点、表信息
+                                                List<WbsTreeContract> needCopyNodes = needCopyNodeAndTabMap.get("node:" + needCopyNodeRoot.getPKeyId());
+                                                List<WbsTreeContract> needCopyTab = needCopyNodeAndTabMap.get("tab:" + needCopyNodeRoot.getPKeyId());
+
+                                                //构造新的节点、表、数据
+                                                this.addCopyNodesAndTabsBuildData(addNodeList, addTabList, needCopyNodes, needCopyTab, needCopyNode, toCopyNode, resultTablesData, 1, finalTabOwner, vo.getIsCopyData());
+
+                                                //1.2 选择同父级的同级节点,只复制数据
+                                            } else if (needCopyNode.getParentId().equals(toCopyNode.getParentId())) {
+                                                //构造数据
+                                                this.addCopyTabData(needCopyNode, toCopyNode, finalTabOwner, resultTablesData, addTabList, vo.getIsCopyData());
+                                            }
 
-                                if (toCopyNode != null && toCopyVO != null && needCopyNodeAndTabMap.size() > 0) {
-                                    //TODO 同节点复制
-                                    if (new Integer(1).equals(toCopyVO.getIsSameNode())) {
-                                        //1.1 选择当前节点的父级节点,新增
-                                        if (needCopyNodeRoot.getParentId().equals(toCopyNode.getId())) {
-                                            toCopyNode.setNodeName(toCopyVO.getNodeName());
-                                            toCopyNode.setPartitionCode(toCopyVO.getPartitionCode());
-
-                                            //获取缓存节点、表信息
-                                            List<WbsTreeContract> needCopyNodes = needCopyNodeAndTabMap.get("node:" + needCopyNodeRoot.getPKeyId());
-                                            List<WbsTreeContract> needCopyTab = needCopyNodeAndTabMap.get("tab:" + needCopyNodeRoot.getPKeyId());
-
-                                            //构造新的节点、表、数据
-                                            this.addCopyNodesAndTabsBuildData(addNodeList, addTabList, needCopyNodes, needCopyTab, needCopyNodeRoot, toCopyNode, resultTablesData, 1, finalTabOwner, vo.getIsCopyData());
-
-                                            //1.2 选择同父级的同级节点,只复制数据
-                                        } else if (needCopyNodeRoot.getParentId().equals(toCopyNode.getParentId())) {
-                                            //构造数据
-                                            this.addCopyTabData(needCopyNodeRoot, toCopyNode, finalTabOwner, resultTablesData, addTabList, vo.getIsCopyData());
-                                        }
-
-                                        //TODO 跨节点复制
-                                    } else if (new Integer(0).equals(toCopyVO.getIsSameNode())) {
-                                        //获取需要复制节点的上级
-                                        WbsTreeContract parentNodeNeed = wbsTreeContractClient.getContractWbsTreeByContractIdAndId(needCopyNodeRoot.getParentId(), Long.parseLong(needCopyNodeRoot.getContractId()));
-
-                                        //2.1 选择的父级的同级的父级节点,新增(当复制节点父级与选择复制到的位置节点的父级id相同时,表示跨节点)
-                                        if (parentNodeNeed != null && parentNodeNeed.getParentId().equals(toCopyNode.getParentId())) {
-                                            toCopyNode.setNodeName(toCopyVO.getNodeName());
-                                            toCopyNode.setPartitionCode(toCopyVO.getPartitionCode());
-
-                                            //获取缓存节点、表信息
-                                            List<WbsTreeContract> needCopyNodes = needCopyNodeAndTabMap.get("node:" + needCopyNodeRoot.getPKeyId());
-                                            List<WbsTreeContract> needCopyTab = needCopyNodeAndTabMap.get("tab:" + needCopyNodeRoot.getPKeyId());
-
-                                            //构造新的节点、表、数据
-                                            this.addCopyNodesAndTabsBuildData(addNodeList, addTabList, needCopyNodes, needCopyTab, needCopyNodeRoot, toCopyNode, resultTablesData, 0, finalTabOwner, vo.getIsCopyData());
+                                            //TODO 跨节点复制
+                                        } else if (new Integer(0).equals(toCopyVO.getIsSameNode())) {
+                                            //获取需要复制节点的上级
+                                            WbsTreeContract parentNodeNeed = wbsTreeContractClient.getContractWbsTreeByContractIdAndId(needCopyNode.getParentId(), Long.parseLong(needCopyNode.getContractId()));
+
+                                            boolean var = false;
+                                            //2.1 选择的父级的同级的父级节点,新增(当复制节点父级与选择复制到的位置节点的父级id相同时,表示跨节点新增)
+                                            if (parentNodeNeed != null) {
+                                                //2.1.1 如果是跨一级的情况下:parentNodeNeed.getParentId() == toCopyNode.getParentId() ,且 parentNodeNeed.getAncestors() == toCopyNode.getAncestors() ,且节点类型必须一样
+                                                if (parentNodeNeed.getParentId().equals(toCopyNode.getParentId()) && parentNodeNeed.getAncestors().equals(toCopyNode.getAncestors()) && parentNodeNeed.getNodeType().equals(toCopyNode.getNodeType())) {
+                                                    toCopyNode.setNodeName(toCopyVO.getNodeName());
+                                                    toCopyNode.setPartitionCode(toCopyVO.getPartitionCode());
+
+                                                    //获取缓存节点、表信息
+                                                    List<WbsTreeContract> needCopyNodes = needCopyNodeAndTabMap.get("node:" + needCopyNodeRoot.getPKeyId());
+                                                    List<WbsTreeContract> needCopyTab = needCopyNodeAndTabMap.get("tab:" + needCopyNodeRoot.getPKeyId());
+
+                                                    //构造新的节点、表、数据
+                                                    this.addCopyNodesAndTabsBuildData(addNodeList, addTabList, needCopyNodes, needCopyTab, needCopyNode, toCopyNode, resultTablesData, 0, finalTabOwner, vo.getIsCopyData());
+                                                    var = true;
+
+                                                } else if (!parentNodeNeed.getParentId().equals(toCopyNode.getParentId()) && !parentNodeNeed.getAncestors().equals(toCopyNode.getAncestors()) && parentNodeNeed.getNodeType().equals(toCopyNode.getNodeType())) {
+                                                    //2.1.2 如果跨多级的情况下父级id不相同 parentNodeNeed.getParentId() != toCopyNode.getParentId() ,且 parentNodeNeed.getAncestors() != toCopyNode.getAncestors() ,且节点类型必须一样
+                                                    toCopyNode.setNodeName(toCopyVO.getNodeName());
+                                                    toCopyNode.setPartitionCode(toCopyVO.getPartitionCode());
+
+                                                    //获取缓存节点、表信息
+                                                    List<WbsTreeContract> needCopyNodes = needCopyNodeAndTabMap.get("node:" + needCopyNodeRoot.getPKeyId());
+                                                    List<WbsTreeContract> needCopyTab = needCopyNodeAndTabMap.get("tab:" + needCopyNodeRoot.getPKeyId());
+
+                                                    //构造新的节点、表、数据
+                                                    this.addCopyNodesAndTabsBuildData(addNodeList, addTabList, needCopyNodes, needCopyTab, needCopyNode, toCopyNode, resultTablesData, 0, finalTabOwner, vo.getIsCopyData());
+                                                    var = true;
+                                                }
+                                            }
 
-                                            //2.2 如果点击选择的是当前复制节点本身的同等级节点,那么就只复制数据。(如果是跨节点,类型相同的情况下,只复制数据)
-                                        } else if (needCopyNodeRoot.getNodeType().equals(toCopyNode.getNodeType()) && !needCopyNodeRoot.getParentId().equals(toCopyNode.getParentId())) {
-                                            //构造数据
-                                            this.addCopyTabData(needCopyNodeRoot, toCopyNode, finalTabOwner, resultTablesData, addTabList, vo.getIsCopyData());
+                                            //2.2 如果点击选择的是当前复制节点本身的同等级节点,那么就只复制数据。(如果是跨节点,类型相同的情况下,只复制数据),且var=false,表示没有进行到跨节点新增的逻辑,只是跨节点复制数据
+                                            if (needCopyNode.getNodeType().equals(toCopyNode.getNodeType()) && !needCopyNode.getParentId().equals(toCopyNode.getParentId()) && !var) {
+                                                //构造数据
+                                                this.addCopyTabData(needCopyNode, toCopyNode, finalTabOwner, resultTablesData, addTabList, vo.getIsCopyData());
+                                            }
                                         }
                                     }
-                                }
-                            });
+                                });
+                            }
+                        }
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    } finally {
+                        //关闭线程池
+                        executor.shutdown();
+                        //等待所有线程执行完毕
+                        while (!executor.isTerminated()) {
                         }
                     }
-                } catch (Exception e) {
-                    e.printStackTrace();
-                } finally {
-                    //关闭线程池
-                    executor.shutdown();
-                    //等待所有线程执行完毕
-                    while (!executor.isTerminated()) {
-                    }
-                }
 
-                //节点
-                Boolean aBoolean = false;
-                if (addNodeList.size() > 0) {
                     //重构祖级id
-                    this.reBuildAncestors(addNodeList, needCopyNodeRoot);
-                    aBoolean = wbsTreeContractClient.saveBatch(addNodeList);
-                }
-
-                //元素表
-                if (addTabList.size() > 0) {
-                    this.reBuildAncestors(addTabList, null);
-                    aBoolean = wbsTreeContractClient.saveBatch(addTabList);
-                    //表单文件附件
-                    if (addChildNodesTablesOldAll.size() > 0 && vo.getIsCopyData() == 1) {
-                        this.addCopyTabFile(addTabList, addChildNodesTablesOldAll);
+                    List<WbsTreeContract> resultAll = new ArrayList<>();
+                    resultAll.addAll(addNodeList);
+                    resultAll.addAll(addTabList);
+                    List<WbsTreeContract> allData = this.reBuildAncestors(resultAll);
+                    List<WbsTreeContract> nodes = allData.stream().filter(f -> f.getType().equals(1)).collect(Collectors.toList());
+                    List<WbsTreeContract> tabs = allData.stream().filter(f -> f.getType().equals(2)).collect(Collectors.toList());
+
+                    //入库
+                    Boolean row = false;
+                    if (nodes.size() > 0) {
+                        row = wbsTreeContractClient.saveBatch(nodes);
                     }
-                }
-
-                //实体表数据
-                if (resultTablesData.size() > 0) {
-                    jdbcTemplate.execute(StringUtils.join(resultTablesData, ""));
-                }
-
-                //更新redis缓存
-                if (aBoolean && asyncWbsTreeNodes.size() > 0) {
-                    List<WbsTreeContract> collect = asyncWbsTreeNodes.stream().distinct().collect(Collectors.toList());
-                    for (WbsTreeContract asyncWbsTreeNode : collect) {
-                        informationQueryService.AsyncWbsTree("", asyncWbsTreeNode.getId() + "", contractId, "", "1");
-                        informationQueryService.AsyncWbsTree("", asyncWbsTreeNode.getParentId() + "", contractId, "", "1");
+                    if (tabs.size() > 0) {
+                        row = wbsTreeContractClient.saveBatch(tabs);
+                        if (addChildNodesTablesOldAll.size() > 0 && vo.getIsCopyData() == 1) {
+                            this.addCopyTabFile(tabs, addChildNodesTablesOldAll);
+                        }
+                    }
+                    if (resultTablesData.size() > 0) {
+                        jdbcTemplate.execute(StringUtils.join(resultTablesData, ""));
+                    }
+                    if (row && asyncWbsTreeNodes.size() > 0) {
+                        List<WbsTreeContract> collect = asyncWbsTreeNodes.stream().distinct().collect(Collectors.toList());
+                        for (WbsTreeContract asyncWbsTreeNode : collect) {
+                            informationQueryService.AsyncWbsTree("", asyncWbsTreeNode.getId() + "", contractId, "", "1");
+                            informationQueryService.AsyncWbsTree("", asyncWbsTreeNode.getParentId() + "", contractId, "", "1");
+                        }
                     }
+                    return R.success("操作成功");
+                } else {
+                    throw new ServiceException("没有找到需要复制的节点信息,请联系管理员");
                 }
-
-                return R.success("操作成功");
             }
         }
         return R.fail("操作失败");
@@ -1610,18 +1623,29 @@ public class InformationWriteQueryController extends BladeController {
     /**
      * 重构祖级id
      */
-    private void reBuildAncestors(List<WbsTreeContract> result, WbsTreeContract needCopyNodeRoot) {
-        for (WbsTreeContract wbsTreeContract : result) {
-            //根节点
-            if (ObjectUtil.isNotEmpty(needCopyNodeRoot) && wbsTreeContract.getOldId().equals(needCopyNodeRoot.getId().toString())) {
-                wbsTreeContract.setAncestors(needCopyNodeRoot.getAncestors());
-            }//非根节点
-            if (ObjectUtil.isNotEmpty(wbsTreeContract.getParentId()) && ObjectUtil.isNotEmpty(wbsTreeContract.getAncestors()) && !wbsTreeContract.getAncestors().contains(wbsTreeContract.getParentId() + "")) {
-                String[] split = wbsTreeContract.getAncestors().split(",");
-                String s = split[split.length - 1];
-                wbsTreeContract.setAncestors(wbsTreeContract.getAncestors().replace(s, wbsTreeContract.getParentId() + ""));
+    private List<WbsTreeContract> reBuildAncestors(List<WbsTreeContract> list) {
+        List<WbsTreeContract> result = new ArrayList<>();
+        List<WbsTreeContract> sortedResult = list.stream()
+                .sorted(Comparator.nullsFirst(Comparator.comparing(WbsTreeContract::getType, Comparator.nullsLast(Comparator.naturalOrder())))
+                        .thenComparing(Comparator.nullsFirst(Comparator.comparing(WbsTreeContract::getNodeType, Comparator.nullsLast(Comparator.naturalOrder()))))
+                        .thenComparing(Comparator.nullsFirst(Comparator.comparing(WbsTreeContract::getId, Comparator.nullsLast(Comparator.naturalOrder()))))
+                        .thenComparing(Comparator.nullsFirst(Comparator.comparing(WbsTreeContract::getCreateTime, Comparator.nullsLast(Comparator.naturalOrder())))))
+                .collect(Collectors.toList());
+        Map<Long, WbsTreeContract> newMap = BeanUtil.copyProperties(result, WbsTreeContract.class).stream().collect(Collectors.toMap(WbsTreeContract::getId, Function.identity()));
+        for (WbsTreeContract obj : sortedResult) {
+            if (obj != null && ObjectUtil.isNotEmpty(obj.getParentId())) {
+                if (newMap.size() > 0) {
+                    WbsTreeContract parentObj = newMap.get(obj.getParentId());
+                    if (parentObj != null && !obj.getAncestors().contains(obj.getParentId().toString())) {
+                        String parentAncestors = parentObj.getAncestors();
+                        obj.setAncestors(parentAncestors + "," + obj.getParentId());
+                    }
+                }
+                newMap.put(obj.getId(), obj);
+                result.add(obj);
             }
         }
+        return result;
     }
 
     /**
@@ -1712,7 +1736,9 @@ public class InformationWriteQueryController extends BladeController {
     /**
      * 新增复制的节点、表的数据构造
      */
-    private void addCopyNodesAndTabsBuildData(List<WbsTreeContract> addNodeList, List<WbsTreeContract> addTabList, List<WbsTreeContract> needNodes, List<WbsTreeContract> needTabs, WbsTreeContract needCopyNode, WbsTreeContract toCopyNode, List<String> resultTablesData, Integer isSameNode, String tabOwner, Integer isCopyData) {
+    private void addCopyNodesAndTabsBuildData(List<WbsTreeContract> addNodeList, List<WbsTreeContract> addTabList, List<WbsTreeContract> needNodes, List<WbsTreeContract> needTabs, WbsTreeContract
+            needCopyNode, WbsTreeContract toCopyNode, List<String> resultTablesData, Integer isSameNode, String
+                                                      tabOwner, Integer isCopyData) {
         int var = 0;
         if (needNodes.size() == 1) {
             //判断是否为最下级节点
@@ -1788,8 +1814,8 @@ public class InformationWriteQueryController extends BladeController {
 
         } else { //多层级节点复制
             //根节点id
-            Long toCopyNodeOldId = toCopyNode.getId();
-            toCopyNode.setId(SnowFlakeUtil.getId());
+            Long needCopyNodeOldId = needCopyNode.getId();
+            needCopyNode.setId(SnowFlakeUtil.getId());
 
             Map<Long, Long> parentIdToId = new HashMap<>();
             Map<Long, List<WbsTreeContract>> tabMap = needTabs.stream().collect(Collectors.groupingBy(WbsTreeContract::getParentId));
@@ -1810,17 +1836,16 @@ public class InformationWriteQueryController extends BladeController {
                         newParentId = parentIdToId.get(node.getParentId());
                     } else {
                         //根节点
-                        newParentId = toCopyNode.getId();
+                        newParentId = needCopyNode.getId();
                     }
                     if (ObjectUtils.isEmpty(newParentId)) {
-                        newParentId = toCopyNode.getId();
+                        newParentId = needCopyNode.getId();
                     }
                     obj.setPKeyId(SnowFlakeUtil.getId());
                     obj.setOldId(node.getId().toString());
                     Long id = SnowFlakeUtil.getId();
                     //数据源节点的老id与新的id的Map,作为下一级的节点的父级id的替换
                     parentIdToId.put(node.getId(), id);
-
                     //重设Id
                     obj.setId(id);
                     obj.setParentId(newParentId);
@@ -1874,19 +1899,19 @@ public class InformationWriteQueryController extends BladeController {
             }
 
             //添加根节点
-            toCopyNode.setOldId(needCopyNode.getId() + "");
+            needCopyNode.setOldId(needCopyNodeOldId + "");
             if (isSameNode == 1) {
                 //同节点
-                toCopyNode.setParentId(needCopyNode.getParentId());
+                needCopyNode.setParentId(needCopyNode.getParentId());
             } else {
                 //跨节点
-                toCopyNode.setParentId(toCopyNodeOldId);
+                needCopyNode.setParentId(toCopyNode.getId());
             }
-            toCopyNode.setPKeyId(SnowFlakeUtil.getId());
-            toCopyNode.setNodeName(toCopyNode.getNodeName());
-            toCopyNode.setFullName(toCopyNode.getNodeName());
-            toCopyNode.setPartitionCode(toCopyNode.getPartitionCode());
-            addNodeList.add(toCopyNode);
+            needCopyNode.setPKeyId(SnowFlakeUtil.getId());
+            needCopyNode.setNodeName(toCopyNode.getNodeName());
+            needCopyNode.setFullName(toCopyNode.getNodeName());
+            needCopyNode.setPartitionCode(toCopyNode.getPartitionCode());
+            addNodeList.add(needCopyNode);
         }
     }
 
@@ -2770,7 +2795,8 @@ public class InformationWriteQueryController extends BladeController {
             @ApiImplicitParam(name = "contractId", value = "合同段ID"),
             @ApiImplicitParam(name = "id", value = "点击节点ID")
     })
-    public R<List<WbsTreeContractTreeVOS>> queryWbsTreeContractByContractIdAndId(@RequestParam String contractId, @RequestParam String id) {
+    public R<List<WbsTreeContractTreeVOS>> queryWbsTreeContractByContractIdAndId(@RequestParam String
+                                                                                         contractId, @RequestParam String id) {
         List<WbsTreeContractTreeVOS> result = new ArrayList<>();
         if (StringUtils.isNotEmpty(id)) {
             WbsTreeContractTreeVOS vos = new WbsTreeContractTreeVOS();
@@ -2970,7 +2996,8 @@ public class InformationWriteQueryController extends BladeController {
             @ApiImplicitParam(name = "contractId", value = "合同段ID", required = true),
             @ApiImplicitParam(name = "classifyType", value = "所属方,监理、总监办的资料查询使用,=1施工数据(默认),=2监理数据")
     })
-    public R<List<WbsTreeContractTreeVOS>> queryContractWbsTreeByContractIdAndType(@RequestParam String primaryKeyId,
+    public R<List<WbsTreeContractTreeVOS>> queryContractWbsTreeByContractIdAndType(@RequestParam String
+                                                                                           primaryKeyId,
                                                                                    @RequestParam String parentId,
                                                                                    @RequestParam String contractId,
                                                                                    @RequestParam String contractIdRelation,

+ 23 - 10
blade-service/blade-business/src/main/java/org/springblade/business/feignClient/ArchiveFileClientImpl.java

@@ -168,17 +168,30 @@ public class ArchiveFileClientImpl implements ArchiveFileClient {
     public Long getAllArchiveFileSize(Long projectId) {
         //获取所有文件的url
         List<ArchiveFile> archiveFileList = fileMapper.getAllArchiveFileUrl(projectId);
-        List<String> list = new ArrayList<>();
-        for (ArchiveFile file : archiveFileList) {
-            if (StringUtils.isNotBlank(file.getFileUrl())){
-                list.add(file.getFileUrl());
-            }
-            if (StringUtils.isNotBlank(file.getPdfFileUrl())){
-                list.add(file.getPdfFileUrl());
+        if (archiveFileList != null && archiveFileList.size() >0) {
+            List<String> list = new ArrayList<>();
+            for (ArchiveFile file : archiveFileList) {
+                if (StringUtils.isNotBlank(file.getFileUrl())) {
+                    list.add(file.getFileUrl());
+                }
+                if (StringUtils.isNotBlank(file.getPdfFileUrl())) {
+                    list.add(file.getPdfFileUrl());
+                }
             }
+            //从阿里云返回文件大小
+            Long sizeCount = 0L;
+            sizeCount += FileUtils.getOssFileSizeCount(list);
+            return sizeCount;
+        }else {
+            return 0L;
         }
-        //从阿里云返回文件大小
-        Long sizeCount = FileUtils.getOssFileSizeCount(list);
-        return sizeCount;
     }
+
+    @Override
+    public List<ArchiveFile> getListByNodeID(String nodeId,Integer isArchive) {
+        List<ArchiveFile> files = fileMapper.getListByNodeID(nodeId, isArchive);
+        return files;
+    }
+
+
 }

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

@@ -72,4 +72,6 @@ public interface ArchiveFileMapper extends BaseMapper<ArchiveFile> {
 	List<ArchiveFileVO> getAllArchiveFileByContractType(@Param("projectId")Long projectId);
 
 	List<ArchiveFile> getAllArchiveFileUrl(@Param("projectId")Long projectId);
+
+	public List<ArchiveFile> getListByNodeID(@Param("nodeId") String nodeId,@Param("isArchive")Integer isArchive);
 }

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

@@ -287,4 +287,15 @@
         WHERE  uaf.project_id = #{projectId};
     </select>
 
+
+
+    <select id="getListByNodeID" resultMap="archiveFileResultMap">
+        select * from u_archive_file
+        where
+          node_id = #{nodeId} and
+          is_archive = #{isArchive} and
+          is_deleted = 0
+          order by sort
+    </select>
+
 </mapper>

+ 45 - 13
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/ImageClassificationFileServiceImpl.java

@@ -34,6 +34,7 @@ import org.springblade.core.tool.utils.ObjectUtil;
 import org.springblade.manager.entity.WbsParam;
 import org.springblade.manager.entity.WbsTree;
 import org.springblade.manager.entity.WbsTreeContract;
+import org.springblade.manager.entity.WbsTreePrivate;
 import org.springblade.manager.feign.WbsTreeContractClient;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
@@ -150,16 +151,20 @@ public class ImageClassificationFileServiceImpl extends BaseServiceImpl<ImageCla
         if (wbsTreeContract != null) {
             //获取当前节点所有父级节点
             List<WbsTreeContract> result = new ArrayList<>();
-            this.recursiveGetParentNodes(result, wbsTreeContract);
             result.add(wbsTreeContract);
-            result.sort(Comparator.comparing(WbsTreeContract::getNodeType).thenComparing(WbsTreeContract::getParentId));
+            this.recursiveGetParentNodes(result, wbsTreeContract);
+            Collections.reverse(result); //倒叙
             List<String> allNodeIds = result.stream().map(WbsTreeContract::getId).map(String::valueOf).collect(Collectors.toList());
-
-            WbsParam wbsParam = jdbcTemplate.query("select v from m_wbs_param where is_deleted = 0 and status = 1 and v is not null and k = 'FILE_TITLE' and name = '文件题名' and node_id = " + wbsTreeContract.getId(), new BeanPropertyRowMapper<>(WbsParam.class)).stream().findAny().orElse(null);
-
-            if (ObjectUtil.isNotEmpty(wbsTreeContract.getOldId())) {
+            WbsParam wbsParam = null;
+            WbsTreePrivate privateNode = jdbcTemplate.query("select p_key_id from m_wbs_tree_private where status = 1 and is_deleted = 0 and wbs_id = " + wbsTreeContract.getWbsId() + " and id = " + wbsTreeContract.getId() + " and project_id =" + wbsTreeContract.getProjectId(), new BeanPropertyRowMapper<>(WbsTreePrivate.class)).stream().findAny().orElse(null);
+            if (privateNode != null) {
+                wbsParam = jdbcTemplate.query("select v from m_wbs_param where is_deleted = 0 and status = 1 and v is not null and k = 'FILE_TITLE' and name = '文件题名' and node_id = " + privateNode.getPKeyId(), new BeanPropertyRowMapper<>(WbsParam.class)).stream().findAny().orElse(null);
+            } else if (ObjectUtil.isNotEmpty(wbsTreeContract.getOldId())) {
                 //表示复制、新增节点
-                wbsParam = jdbcTemplate.query("select v from m_wbs_param where is_deleted = 0 and status = 1 and v is not null and k = 'FILE_TITLE' and name = '文件题名' and node_id = " + wbsTreeContract.getOldId(), new BeanPropertyRowMapper<>(WbsParam.class)).stream().findAny().orElse(null);
+                WbsTreePrivate privateNodeCopy = jdbcTemplate.query("select p_key_id from m_wbs_tree_private where status = 1 and is_deleted = 0 and wbs_id = " + wbsTreeContract.getWbsId() + " and id = " + wbsTreeContract.getOldId() + " and project_id =" + wbsTreeContract.getProjectId(), new BeanPropertyRowMapper<>(WbsTreePrivate.class)).stream().findAny().orElse(null);
+                if (privateNodeCopy != null) {
+                    wbsParam = jdbcTemplate.query("select v from m_wbs_param where is_deleted = 0 and status = 1 and v is not null and k = 'FILE_TITLE' and name = '文件题名' and node_id = " + privateNodeCopy.getPKeyId(), new BeanPropertyRowMapper<>(WbsParam.class)).stream().findAny().orElse(null);
+                }
             }
 
             if (wbsParam != null && allNodeIds.size() > 0) {
@@ -191,12 +196,39 @@ public class ImageClassificationFileServiceImpl extends BaseServiceImpl<ImageCla
                     if (nameList.size() > 0) {
                         return StringUtils.join(nameList, "");
                     }
-                } else {
-                    //如果私有WBS为空,到公有WBS获取
-                    List<WbsTree> wbsTreeList = jdbcTemplate.query("select full_name from m_wbs_tree where is_deleted = 0 and status = 1 and id in(" + StringUtils.join(ids, ",") + ")", new BeanPropertyRowMapper<>(WbsTree.class));
-                    List<String> nameList = wbsTreeList.stream().map(WbsTree::getFullName).collect(Collectors.toList());
-                    if (nameList.size() > 0) {
-                        return StringUtils.join(nameList, "");
+                }
+            } else if (wbsParam == null) {
+                //如果私有WBS为空,到公有WBS获取,wbsTreeContract.getId()=wbsTree.getId()
+                wbsParam = jdbcTemplate.query("select v from m_wbs_param where is_deleted = 0 and status = 1 and v is not null and k = 'FILE_TITLE' and name = '文件题名' and node_id = " + wbsTreeContract.getId(), new BeanPropertyRowMapper<>(WbsParam.class)).stream().findAny().orElse(null);
+                if (wbsParam != null && allNodeIds.size() > 0) {
+                    List<String> nodeNumber = new ArrayList<>();
+                    String[] titles = wbsParam.getV().split("-");
+                    for (String title : titles) {
+                        if (title.contains("c") || title.contains("C")) {
+                            String lastStr = title.substring(title.length() - 1);
+                            nodeNumber.add(lastStr);
+                        }
+                    }
+
+                    List<String> ids = new ArrayList<>();
+                    for (String index : nodeNumber) {
+                        if (Integer.parseInt(index) <= result.size()) {
+                            String id = allNodeIds.get(Integer.parseInt(index));
+                            if (StringUtils.isNotEmpty(id)) {
+                                ids.add(id);
+                            }
+                        }
+                    }
+
+                    List<WbsTreeContract> filteredList = result.stream()
+                            .filter(e -> ids.stream().anyMatch(id -> id.equals(String.valueOf(e.getId()))))
+                            .collect(Collectors.toList());
+
+                    if (filteredList.size() > 0) {
+                        List<String> nameList = filteredList.stream().map(WbsTreeContract::getFullName).collect(Collectors.toList());
+                        if (nameList.size() > 0) {
+                            return StringUtils.join(nameList, "");
+                        }
                     }
                 }
             }

+ 0 - 1
blade-service/blade-manager/src/main/java/com/mixsmart/utils/CustomFunction.java

@@ -1272,7 +1272,6 @@ public class CustomFunction {
 						}
 					}
 					measureOut.addAll(_tmp);
-					measureOut.add("");
 				}
 			}
 		}

+ 6 - 0
blade-service/blade-manager/src/main/java/com/mixsmart/utils/StringUtils.java

@@ -1140,6 +1140,12 @@ public class StringUtils {
 		return "";
 	}
 
+/*
+	public static void main(String[] args) {
+		System.out.println(StringUtils.number2String("-2400.0000000000055",1));
+	}
+*/
+
 	/**
 	 * @Description byte数组转Md5字符串
 	 * @Param [bytes]

+ 17 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ContractInfoController.java

@@ -541,6 +541,23 @@ public class ContractInfoController extends BladeController {
         return R.fail(200, "未查询到信息");
     }
 
+    /**
+     * 客户端合同段新增节点获取当前节点树
+     */
+    @GetMapping("/add-node-tree")
+    @ApiOperationSupport(order = 18)
+    @ApiOperation(value = "客户端合同段新增节点获取当前节点树", notes = "传入选择的节点pKeyId")
+    @ApiImplicitParams(value = {
+            @ApiImplicitParam(name = "pKeyId", value = "选择的节点pKeyId", required = true)
+    })
+    public R addNodeTree(String pKeyId) {
+        List<WbsTreeContractVO> tree = contractInfoService.addNodeTree(pKeyId);
+        if (tree != null && tree.size() > 0) {
+            return R.data(tree);
+        }
+        return R.fail(200, "未查询到信息");
+    }
+
     /**
      * 查询合同段树-全加载-施工合同段
      */

+ 14 - 9
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ExcelTabController.java

@@ -1682,18 +1682,23 @@ public class ExcelTabController extends BladeController {
         if (!info.isSuccess()) {
             return info;
         }
-        System.out.println("3=" + DateUtil.formatDateTime(DateUtil.now()));
-        //单个 pdf加载
-        for (TableInfo tableInfo : tableInfoList) {
-            //if(!tableInfo.isToBeUpdated()){
+        try {
+            System.out.println("3=" + DateUtil.formatDateTime(DateUtil.now()));
+            //单个 pdf加载
+            for (TableInfo tableInfo : tableInfoList) {
+                //if(!tableInfo.isToBeUpdated()){
                 excelTabService.getBussPdfInfo(Long.parseLong(tableInfo.getPkeyId()));
-          //  }
+                //  }
 
+            }
+            System.out.println("4=" + DateUtil.formatDateTime(DateUtil.now()));
+            // 合并pdf加载
+            excelTabService.getBussPdfs(nodeid, classify, contractId, projectId);
+            System.out.println("5=" + DateUtil.formatDateTime(DateUtil.now()));
+        }catch (Exception e){
+            e.printStackTrace();
         }
-        System.out.println("4=" + DateUtil.formatDateTime(DateUtil.now()));
-        // 合并pdf加载
-        excelTabService.getBussPdfs(nodeid, classify, contractId, projectId);
-        System.out.println("5=" + DateUtil.formatDateTime(DateUtil.now()));
+
         return R.data("操作成功");
     }
 

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

@@ -270,7 +270,7 @@ public class FormulaController {
             }
             List<Object> data =new ArrayList<>();
             info.build();
-            if(info.getDesigns().size()>0){
+            if(info.getDesigns().size()>1){
                 AtomicInteger i= new AtomicInteger();
                 List<Object> tmpList = info.getDesigns().stream()
                         .map(e-> CustomFunction.listTrim(CustomFunction.b445random(info.getSizeAt(i.get()),e,info.getDevAt(i.get()),info.getFailAt(i.getAndIncrement()),1)))
@@ -299,6 +299,7 @@ public class FormulaController {
                     }
                 }
                 if((data.size()+start)>dw.length){
+
                    // String moreData = data.stream().skip(dw.length).map(StringUtils::handleNull).collect(Collectors.joining(StringPool.SEMICOLON));
                     List<Object> moreData = data.stream().skip(result.size()).map(StringUtils::handleNull).collect(Collectors.toList());
                     // 频率添加表单

+ 22 - 21
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/TextdictInfoController.java

@@ -168,8 +168,7 @@ public class TextdictInfoController extends BladeController {
         //获取当前项目下引用相同模板的元素表信息
         List<WbsTreePrivate> wbsTreePrivatesEqual = wbsTreePrivateMapper.selectList(Wrappers.<WbsTreePrivate>lambdaQuery()
                 .eq(WbsTreePrivate::getProjectId, wbsTreePrivate.getProjectId())
-                .eq(WbsTreePrivate::getHtmlUrl, wbsTreePrivate.getHtmlUrl())
-                .eq(WbsTreePrivate::getStatus, 1));
+                .eq(WbsTreePrivate::getHtmlUrl, wbsTreePrivate.getHtmlUrl()));
         List<Long> pKeyIds = wbsTreePrivatesEqual.stream().map(WbsTreePrivate::getPKeyId).collect(Collectors.toList());
         String pIds = StringUtils.join(pKeyIds, ",");
 
@@ -479,8 +478,8 @@ public class TextdictInfoController extends BladeController {
         //获取当前项目下引用相同模板的元素表信息
         List<WbsTreePrivate> wbsTreePrivatesEqual = wbsTreePrivateMapper.selectList(Wrappers.<WbsTreePrivate>lambdaQuery()
                 .eq(WbsTreePrivate::getProjectId, wbsTreePrivate.getProjectId())
-                .eq(WbsTreePrivate::getExcelId, wbsTreePrivate.getExcelId())
-                .eq(WbsTreePrivate::getStatus, 1));
+                .eq(WbsTreePrivate::getExcelId, wbsTreePrivate.getExcelId()));
+
         List<Long> pKeyIds = wbsTreePrivatesEqual.stream().map(WbsTreePrivate::getPKeyId).collect(Collectors.toList());
         String ids = StringUtils.join(pKeyIds, ",");
 
@@ -542,10 +541,12 @@ public class TextdictInfoController extends BladeController {
 
         //删除当前类型
         List<String> collect = textDictInfosNewAll.stream().map(TextdictInfo::getTabId).distinct().collect(Collectors.toList());
-        this.textdictInfoService.getBaseMapper().delete(Wrappers.<TextdictInfo>query().lambda()
-                .eq(TextdictInfo::getType, textdictInfo.getType())
-                .in(TextdictInfo::getTabId, collect)
-        );
+        if(collect!=null && collect.size()>=1){
+            this.textdictInfoService.getBaseMapper().delete(Wrappers.<TextdictInfo>query().lambda()
+                    .eq(TextdictInfo::getType, textdictInfo.getType())
+                    .in(TextdictInfo::getTabId, collect)
+            );
+        }
 
         //批量新增
         this.textdictInfoService.saveBatch(textDictInfosNewAll);
@@ -572,20 +573,20 @@ public class TextdictInfoController extends BladeController {
 
         //修改对应合同段的htmlUrl,当前项目下对应合同段的节点
         List<Long> cIdsList = wbsTreePrivatesEqual.stream().map(WbsTreePrivate::getId).distinct().collect(Collectors.toList());
-        List<Long> cPkeyIds = wbsTreeContractService.getBaseMapper().selectList(Wrappers.<WbsTreeContract>lambdaQuery()
-                .eq(WbsTreeContract::getProjectId, wbsTreePrivate.getProjectId())
-                .eq(WbsTreeContract::getExcelId, wbsTreePrivate.getExcelId())
-                .eq(WbsTreeContract::getStatus, 1)
-                .in(WbsTreeContract::getId, cIdsList)
-        ).stream().map(WbsTreeContract::getPKeyId).collect(Collectors.toList());
-
-        String cPkeyIdsStr = StringUtils.join(cPkeyIds, ",");
-        if (StringUtils.isNotEmpty(cPkeyIdsStr)) {
-            String updateSqlC = "update m_wbs_tree_contract set html_url = '" + replace + "' where p_key_id in (" + cPkeyIdsStr + ")";
-            jdbcTemplate.execute(updateSqlC);
+        if(cIdsList!=null && cIdsList.size()>=1){
+            List<Long> cPkeyIds = wbsTreeContractService.getBaseMapper().selectList(Wrappers.<WbsTreeContract>lambdaQuery()
+                    .eq(WbsTreeContract::getProjectId, wbsTreePrivate.getProjectId())
+                    .eq(WbsTreeContract::getExcelId, wbsTreePrivate.getExcelId())
+                    .eq(WbsTreeContract::getStatus, 1)
+                    .in(WbsTreeContract::getId, cIdsList)
+            ).stream().map(WbsTreeContract::getPKeyId).collect(Collectors.toList());
+
+            String cPkeyIdsStr = StringUtils.join(cPkeyIds, ",");
+            if (StringUtils.isNotEmpty(cPkeyIdsStr)) {
+                String updateSqlC = "update m_wbs_tree_contract set html_url = '" + replace + "' where p_key_id in (" + cPkeyIdsStr + ")";
+                jdbcTemplate.execute(updateSqlC);
+            }
         }
-
-
         return R.success("操作成功");
     }
 

+ 4 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/IContractInfoService.java

@@ -73,4 +73,8 @@ public interface IContractInfoService extends BaseService<ContractInfo> {
     Map<String, Object> trialRelationTree(String wbsId, String projectId, String contractId, String selfId);
 
     Map<Long, List<WbsTreeContractTreeAllVO>> treeAllJL(String contractId, Integer type);
+
+    List<WbsTreeContractVO> addNodeTree(String pKeyId);
+
+
 }

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

@@ -190,6 +190,59 @@ public class ContractInfoServiceImpl extends BaseServiceImpl<ContractInfoMapper,
         return result;
     }
 
+    @Override
+    public List<WbsTreeContractVO> addNodeTree(String pKeyId) {
+        WbsTreeContract parentNodeRoot = wbsTreeContractMapper.selectOne(Wrappers.<WbsTreeContract>lambdaQuery().eq(WbsTreeContract::getPKeyId, pKeyId).eq(WbsTreeContract::getStatus, 1));
+        if (parentNodeRoot != null) {
+            List<WbsTreeContract> allNodes = this.getChildNodes(parentNodeRoot);
+            allNodes.add(parentNodeRoot);
+            List<WbsTreeContractVO> resultAllNodes = BeanUtil.copyProperties(allNodes, WbsTreeContractVO.class);
+            return buildWbsTreeByStreamChildNodeTree(resultAllNodes, parentNodeRoot);
+        }
+        return null;
+    }
+
+    public List<WbsTreeContractVO> buildWbsTreeByStreamChildNodeTree(List<WbsTreeContractVO> nodes, WbsTreeContract parentNodeRoot) {
+        List<WbsTreeContractVO> list = nodes.stream().filter(f -> f.getId().equals(parentNodeRoot.getId())).collect(Collectors.toList());
+        Map<Long, List<WbsTreeContractVO>> map = nodes.stream().collect(Collectors.groupingBy(WbsTreeContractVO::getParentId));
+        this.recursionFnTreeChildNode(list, map);
+        return list;
+    }
+
+    public void recursionFnTreeChildNode(List<WbsTreeContractVO> list, Map<Long, List<WbsTreeContractVO>> map) {
+        for (WbsTreeContractVO wbsTreeContractVO : list) {
+            List<WbsTreeContractVO> childrenList = map.get(wbsTreeContractVO.getId());
+            wbsTreeContractVO.setChildren(childrenList);
+            if (childrenList != null && childrenList.size() > 0) {
+                wbsTreeContractVO.setHasChildren(true);
+                recursionFnTree(childrenList, map);
+            }
+        }
+    }
+
+    private List<WbsTreeContract> getChildNodes(WbsTreeContract obj) {
+        if (obj != null) {
+            List<WbsTreeContract> wbsTreeContracts = Collections.singletonList(obj);
+            List<WbsTreeContract> result = new ArrayList<>();
+            this.recursionGetChildNodes(wbsTreeContracts, result, obj.getContractId());
+            if (result.size() > 0) {
+                return result;
+            }
+        }
+        return null;
+    }
+
+    private void recursionGetChildNodes(List<WbsTreeContract> list, List<WbsTreeContract> result, String contractId) {
+        List<Long> ids = list.stream().map(WbsTreeContract::getId).collect(Collectors.toList());
+        if (ids.size() > 0) {
+            List<WbsTreeContract> query = jdbcTemplate.query("select * from m_wbs_tree_contract where type = 1 and parent_id in(" + org.apache.commons.lang.StringUtils.join(ids, ",") + ") and status = 1 and is_deleted = 0 and contract_id = " + contractId, new BeanPropertyRowMapper<>(WbsTreeContract.class));
+            if (query.size() > 0) {
+                result.addAll(query);
+                recursionGetChildNodes(query, result, contractId);
+            }
+        }
+    }
+
     @Override
     public List<WbsTreeContractVO6> tree6List(String wbsId, String projectId, String contractId) {
         return baseMapper.tree6(Long.parseLong(wbsId), Long.parseLong(projectId), Long.parseLong(contractId));
@@ -206,7 +259,6 @@ public class ContractInfoServiceImpl extends BaseServiceImpl<ContractInfoMapper,
         List<WbsTreeContractVO6> wbsTreeContractVOS = baseMapper.tree6(Long.parseLong(wbsId), Long.parseLong(projectId), Long.parseLong(contractId));
         List<WbsTreeContractVO6> wbsTreeVO2s = ForestNodeMerger.merge(wbsTreeContractVOS);
         List<WbsTreeContractVO6> list = wbsTreeVO2s.stream().filter(f -> f.getParentId() == 0L).collect(Collectors.toList());
-
         return list;
     }
 

+ 70 - 21
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java

@@ -155,7 +155,8 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
         List<AppWbsTreeContractVO> tableList =wbsTreeContractService.searchNodeAllTable(primaryKeyId.toString(), "1", contractId.toString(),info.getPId());
         this.constantMap.put(TABLE_LIST,tableList);
         /*通过判断元素名称来确定,加入汇总公式延后执行*/
-        this.constantMap.put("tableNames",tableList.stream().filter(e->StringUtils.isEquals(e.getIsBussShow(),1)).map(WbsTreeContract::getNodeName).collect(Collectors.toList()));
+      //  this.constantMap.put("tableNames",tableList.stream().filter(e->StringUtils.isEquals(e.getIsBussShow(),1)).map(WbsTreeContract::getNodeName).collect(Collectors.toList()));
+        this.constantMap.put("tableNames",tableList.stream().map(WbsTreeContract::getNodeName).collect(Collectors.toList()));
 
         List<String> missingList = new ArrayList<>();
         this.formDataList.forEach(fd->{
@@ -222,6 +223,18 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                     }
                 });
                 if(itemsMap.size()>0){
+                    itemsMap.values().forEach(i->{
+                        FormData vf=i.getValue();
+                        if(vf!=null){
+                            if(i.getPass()==null){
+                               i.setPass(tec.getFormDataMap().values().stream().filter(v->v.getTableName().equals(vf.getTableName())&&!v.getCode().equals(vf.getCode())).filter(v->v.getEName().contains(i.getPoint())&&v.getEName().contains("率")).findAny().orElse(null));
+                            }
+                            if(i.getJudge()==null){
+                                i.setJudge(tec.getFormDataMap().values().stream().filter(v->v.getTableName().equals(vf.getTableName())&&!v.getCode().equals(vf.getCode())).filter(v->v.getEName().contains(i.getPoint())&&v.getEName().contains("判")).findAny().orElse(null));
+                            }
+                        }
+
+                    });
                     AtomicBoolean update= new AtomicBoolean(false);
                     itemsMap.values().stream().filter(Measurement::isMatching).forEach(t->{
                         ElementBlock g=null;
@@ -253,7 +266,9 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                                     FormulaUtils.write(t.getJudge(),"合格",null);
                                 }
                                 itemBlockList.sort(Comparator.comparingInt(a->ids.indexOf(a.getPkeyId())));
-                                FormulaUtils.write(t.getValue(),itemBlockList.stream().map(ItemBlock::getData).flatMap(v->v.stream().flatMap(Collection::stream)).collect(Collectors.toList()),true);
+                                List<String> values=itemBlockList.stream().map(ItemBlock::getData).flatMap(v->v.stream().flatMap(Collection::stream)).map(Object::toString).collect(Collectors.toList());
+                                int scale = StringUtils.getScale(values);
+                                FormulaUtils.write(t.getValue(),values.stream().map(u->StringUtils.number2String(u,scale)).collect(Collectors.toList()), true);
 
 //                                   if(t.getValue().getEName().contains("±")){
 //                                       /*存在偏差范围则获取的是偏差值:实测-设计*/
@@ -862,6 +877,21 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                     /*把附表数据刷入对应的附表元素对象*/
                     sta.flush();
                 }
+                String mainTableName = this.tec.getTableAll().stream().filter(e -> e.getNodeName().contains("检验单") || e.getNodeName().contains("评定表")).map(AppWbsTreeContractVO::getInitTableName).findFirst().orElse("");
+                if(Func.isNotBlank(mainTableName)){
+                    List<FormData> sourceFds=tec.getFormDataMap().values().stream().filter(s->!s.empty()).filter(s->StringUtils.isEquals(s.getTableName(),mainTableName)).collect(Collectors.toList());
+                    Map<String,Object> copyMap= new HashMap<>();
+                    if(sourceFds.size()>0){
+                        sourceFds.forEach(d->{
+                            copyMap.put(d.getEName().trim(),d.getValues().stream().map(ElementData::getValue).filter(StringUtils::isNotEmpty).findAny().orElse(""));
+                        });
+                    }
+                    subTableFds.stream().filter(s-> !SubTable.KEYS.contains(s.getEName().trim())).filter(s->copyMap.containsKey(s.getEName().trim())).forEach(t->{
+                         Object val = copyMap.get(t.getEName().trim());
+                         t.getValues().forEach(e->e.setValue(val));
+                         t.setUpdate(1);
+                    });
+                }
             }
 
         } catch (Exception e) {
@@ -874,28 +904,46 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
 
     /**汇总处理*/
     public void summaryCalc(){
-        if(this.summary.size()>0){
-            /**/
-            this.constantMap.put(CHECK_ITEMS,this.checkItems.stream().filter(fdTmp->fdTmp.getValues().stream().map(ElementData::getValue).anyMatch(e->StringUtils.isNotEmpty(e)&&StringUtils.isNotEquals("/",e))).map(FormData::getEName).map(FormulaUtils::parseItemName).distinct().collect(Collectors.joining(",")));
-            this.constantMap.put("CKD",this.checkDate.stream().flatMap(k->k.getValues().stream()).map(ElementData::stringValue).filter(StringUtils::isNotEmpty).reduce((a, b) -> Comparator.<DateTime>reverseOrder().compare(new DateTime(a), new DateTime(b)) <= 0 ? a : b).orElse(null));
-            this.summary.forEach(e->{
-                /*处理脚本*/
-                e.getFormula().setFormula(e.getFormula().getNumber());
-            });
-            this.summary.forEach(e->{
-                /*执行公式*/
-                Object data = Expression.parse(e.getFormula().getFormula()).calculate(this.constantMap);
-                if(data!=null){
-                    FormulaUtils.write(e,data,false);
-                   e.setUpdate(1);
+        try{
+            if(this.summary.size()>0){
+                /**/
+                List<String> result=this.checkItems.stream().filter(fdTmp->fdTmp.getValues().stream().map(ElementData::getValue).anyMatch(e->StringUtils.isNotEmpty(e)&&StringUtils.isNotEquals("/",e))).map(FormData::getEName).map(FormulaUtils::parseItemName).distinct().collect(Collectors.toList());
+                Optional<FormData> opk= this.summary.stream().filter(FormData::executable).filter(f->StringUtils.isEquals(f.getFormula().getNumber(),CHECK_ITEMS)).findAny();
+                List<String> history=null;
+                if(opk.isPresent()&&!opk.get().empty()){
+                    /*假如已经存在内容,则需要筛选出手填部分*/
+                    history=  Arrays.asList(opk.get().getValues().get(0).stringValue().replaceAll("[\\s\\n]+","").split("[,、,]"));
                 }
-            });
-            /*分项汇总*/
-            doForDataBlock();
+                if(history!=null&&history.size()>0){
+                    List<String> itemAll=this.checkItems.stream().map(FormData::getEName).map(FormulaUtils::parseItemName).distinct().collect(Collectors.toList());
+                    List<String> customize=history.stream().filter(s->!itemAll.contains(s)).collect(Collectors.toList());
+                    result.addAll(customize);
+                }
+                this.constantMap.put(CHECK_ITEMS,result);
+                this.constantMap.put("CKD",this.checkDate.stream().flatMap(k->k.getValues().stream()).map(ElementData::stringValue).filter(StringUtils::isNotEmpty).reduce((a, b) -> Comparator.<DateTime>reverseOrder().compare(new DateTime(a), new DateTime(b)) <= 0 ? a : b).orElse(null));
+                this.summary.forEach(e->{
+                    /*处理脚本*/
+                    e.getFormula().setFormula(e.getFormula().getNumber());
+                });
+                this.summary.forEach(e->{
+                    /*执行公式*/
+                    Object data = Expression.parse(e.getFormula().getFormula()).calculate(this.constantMap);
+                    if(data!=null){
+                        FormulaUtils.write(e,data,false);
+                        e.setUpdate(1);
+                    }
+                });
+                /*分项汇总*/
+                doForDataBlock();
+            }
+        }catch (Exception e){
+            e.printStackTrace();
         }
     }
 
 
+
+
     /**分项汇总数据*/
     public void   doForDataBlock(){
         try {
@@ -933,8 +981,8 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                      List<Object> list = c.getValues().stream().map(ElementData::getValue).filter(StringUtils::isNotEmpty).collect(Collectors.toList());
                      /*1.无任何记录,当前页无数据,则不需要处理 2.存在记录当前无数据,则要消除 3.没有记录当前有数据,则需要增加 4.有记录有当前记录,则需更新*/
                      if(Func.isNotEmpty(list)||targetItem!=null){
-                         FormData designList=tec.getFormDataMap().values().stream().filter(t->StringUtils.isEquals(FormulaUtils.parseItemName(t.getEName()),FormulaUtils.parseItemName(c.getEName()))&&t.getEName().contains("设计")&&StringUtils.isEquals(t.getTableName(),c.getTableName())).collect(Collectors.toList()).get(0);
-                         FormData pass=tec.getFormDataMap().values().stream().filter(t->StringUtils.isEquals(FormulaUtils.parseItemName(t.getEName()),FormulaUtils.parseItemName(c.getEName()))&&t.getEName().contains("合格")&&StringUtils.isEquals(t.getTableName(),c.getTableName())).collect(Collectors.toList()).get(0);
+                         FormData designList=tec.getFormDataMap().values().stream().filter(t->t.getEName().contains(FormulaUtils.parseItemName(c.getEName()))&&t.getEName().contains("设计")&&StringUtils.isEquals(t.getTableName(),c.getTableName())).collect(Collectors.toList()).get(0);
+                         FormData pass=tec.getFormDataMap().values().stream().filter(t->t.getEName().contains(FormulaUtils.parseItemName(c.getEName()))&&t.getEName().contains("合格")&&StringUtils.isEquals(t.getTableName(),c.getTableName())).collect(Collectors.toList()).get(0);
                          if(targetItem==null){
                              if(eb==null){
                                  eb=new ElementBlock();
@@ -990,6 +1038,7 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
 
     public  void write(FormData fd,Object data){
         /*如果需要向额外元素或对象输出数据,在此处修改*/
+               fd.setUpdate(1);
                FormulaUtils.write(fd,data,false);
     }
 

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

@@ -111,10 +111,11 @@ public class WbsTreeContractServiceImpl extends BaseServiceImpl<WbsTreeContractM
         //TODO ---------节点未变只同步元素表---------
         if (saveIds.size() == 0 && delIds.size() == 0) {
             List<WbsTreePrivate> wbsTreePrivateListResult = new ArrayList<>();
-            //当前合同段所有表
+            //当前项目所有表
             List<WbsTreePrivate> wbsTreePrivateList = wbsTreePrivateMapper.selectList(Wrappers.<WbsTreePrivate>query().lambda()
                     .eq(WbsTreePrivate::getProjectId, Long.parseLong(pawDTO.getProjectId()))
                     .eq(WbsTreePrivate::getWbsId, Long.parseLong(pawDTO.getWbsId()))
+                    .eq(WbsTreePrivate::getStatus,1)
                     .eq(WbsTreePrivate::getType, 2)
             );
 

+ 10 - 54
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreePrivateServiceImpl.java

@@ -67,9 +67,6 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
     private final TextdictInfoServiceImpl textDictInfoService;
     private final InformationQueryClient informationQueryClient;
 
-    //创建线程池任务
-    private final ExecutorService executor = Executors.newFixedThreadPool(4);
-
     @Override
     public List<WbsTreePrivateVO> tree(String wbsId, String projectId) {
         WbsInfo wbsInfo = wbsInfoMapper.selectOne(Wrappers.<WbsInfo>query().lambda().eq(WbsInfo::getId, wbsId));
@@ -810,32 +807,12 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
                 this.wbsParamServiceImpl.updateBatchById(updateList, 1000);
             }
             if (insertList.size() > 0) {
-                try {
-                    List<List<WbsParam>> partition1 = Lists.partition(insertList, 1000);
-                    CompletionService<Void> completionService = new ExecutorCompletionService<>(executor);
-                    for (List<WbsParam> addList : partition1) {
-                        completionService.submit(() -> {
-                            wbsParamServiceImpl.insertBatch(addList, 1000);
-                            return null;
-                        });
-                    }
-                    for (int i = 0; i < partition1.size(); i++) {
-                        try {
-                            completionService.take().get();
-                        } catch (ExecutionException e) {
-                            // 异常处理
-                            e.printStackTrace();
-                        }
-                    }
-                } catch (Exception e) {
-                    e.printStackTrace();
-                } finally {
-                    //释放线程
-                    executor.shutdown();
+                List<List<WbsParam>> partition1 = Lists.partition(insertList, 1000);
+                for (List<WbsParam> addList : partition1) {
+                    wbsParamServiceImpl.insertBatch(addList, 1000);
                 }
-
+                return true;
             }
-            return true;
         }
         return false;
     }
@@ -1148,36 +1125,15 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
                     jdbcTemplate.execute(delSql);
                 }
 
-                try {
-                    List<List<TextdictInfo>> partition1 = Lists.partition(insertData, 1000);
-                    CompletionService<Void> completionService = new ExecutorCompletionService<>(executor);
-                    for (List<TextdictInfo> addList : partition1) {
-                        completionService.submit(() -> {
-                            textDictInfoService.insertBatch(addList, 1000);
-                            return null;
-                        });
-                    }
-                    for (int i = 0; i < partition1.size(); i++) {
-                        try {
-                            completionService.take().get();
-                        } catch (ExecutionException e) {
-                            // 异常处理
-                            e.printStackTrace();
-                        }
-                    }
-                } catch (Exception e) {
-                    e.printStackTrace();
-                } finally {
-                    //释放线程
-                    executor.shutdown();
+                List<List<TextdictInfo>> partition1 = Lists.partition(insertData, 1000);
+                for (List<TextdictInfo> addList : partition1) {
+                    textDictInfoService.insertBatch(addList, 1000);
                 }
-
-                return true;
-            } else {
-                throw new ServiceException("当前项目关联的wbs树不是私有关联");
             }
+            return true;
+        } else {
+            throw new ServiceException("当前项目关联的wbs树不是私有关联");
         }
-        return false;
     }
 
     @Override

+ 6 - 47
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeServiceImpl.java

@@ -61,9 +61,6 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
     private final JdbcTemplate jdbcTemplate;
     private final ITableInfoService tableInfoService;
 
-    //创建线程池任务
-    private final ExecutorService executor = Executors.newFixedThreadPool(4);
-
     @Override
     public IPage<WbsTreeVO> selectWbsTreePage(IPage<WbsTreeVO> page, WbsTreeVO wbsTree) {
         return page.setRecords(baseMapper.selectWbsTreePage(page, wbsTree));
@@ -801,28 +798,9 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
                     }
 
                     if (pawDTO.getReferenceType().equals("public")) {
-                        try {
-                            List<List<WbsTreePrivate>> partition1 = Lists.partition(insertData1, 1000);
-                            CompletionService<Void> completionService = new ExecutorCompletionService<>(executor);
-                            for (List<WbsTreePrivate> addList : partition1) {
-                                completionService.submit(() -> {
-                                    wbsTreePrivateService.insertBatch(addList, 1000);
-                                    return null;
-                                });
-                            }
-                            for (int i = 0; i < partition1.size(); i++) {
-                                try {
-                                    completionService.take().get();
-                                } catch (ExecutionException e) {
-                                    // 异常处理
-                                    e.printStackTrace();
-                                }
-                            }
-                        } catch (Exception e) {
-                            e.printStackTrace();
-                        } finally {
-                            //释放线程
-                            executor.shutdown();
+                        List<List<WbsTreePrivate>> partition1 = Lists.partition(insertData1, 1000);
+                        for (List<WbsTreePrivate> addList : partition1) {
+                            wbsTreePrivateService.insertBatch(addList, 1000);
                         }
 
                         //修改状态
@@ -834,28 +812,9 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
                         }
 
                     } else if (pawDTO.getReferenceType().equals("private")) {
-                        try {
-                            List<List<WbsTreePrivate>> partition1 = Lists.partition(insertData2, 1000);
-                            CompletionService<Void> completionService = new ExecutorCompletionService<>(executor);
-                            for (List<WbsTreePrivate> addList : partition1) {
-                                completionService.submit(() -> {
-                                    wbsTreePrivateService.insertBatch(addList, 1000);
-                                    return null;
-                                });
-                            }
-                            for (int i = 0; i < partition1.size(); i++) {
-                                try {
-                                    completionService.take().get();
-                                } catch (ExecutionException e) {
-                                    // 异常处理
-                                    e.printStackTrace();
-                                }
-                            }
-                        } catch (Exception e) {
-                            e.printStackTrace();
-                        } finally {
-                            //释放线程
-                            executor.shutdown();
+                        List<List<WbsTreePrivate>> partition1 = Lists.partition(insertData2, 1000);
+                        for (List<WbsTreePrivate> addList : partition1) {
+                            wbsTreePrivateService.insertBatch(addList, 1000);
                         }
 
                         //异步修改htmlUrl ,数据都在insertData2里

+ 3 - 1
blade-service/blade-system/src/main/java/org/springblade/system/controller/TenantController.java

@@ -195,7 +195,9 @@ public class TenantController extends BladeController {
 		if (tenant != null) {
 			kv.set("tenantId", tenant.getTenantId())
 				.set("domain", tenant.getDomainUrl())
-				.set("backgroundUrl", tenant.getBackgroundUrl());
+				.set("tenantTitle", tenant.getTenantTitle())
+				.set("tenantAvatar", tenant.getTenantAvatar())
+				.set("tenantAvatarText", tenant.getTenantAvatarText());
 		}
 		return R.data(kv);
 	}

+ 3 - 1
blade-service/blade-system/src/main/java/org/springblade/system/mapper/TenantMapper.xml

@@ -21,9 +21,11 @@
         <result column="account_number" property="accountNumber"/>
         <result column="expire_time" property="expireTime"/>
         <result column="license_key" property="licenseKey"/>
+        <result column="tenant_avatar" property="tenantAvatar"/>
+        <result column="tenant_title" property="tenantTitle"/>
+        <result column="tenant_avatar_text" property="tenantAvatarText"/>
     </resultMap>
 
-
     <select id="selectTenantPage" resultMap="tenantResultMap">
         select * from blade_tenant where is_deleted = 0
     </select>