Эх сурвалжийг харах

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

laibulaizheli 5 өдөр өмнө
parent
commit
334f3b9c69
100 өөрчлөгдсөн 2738 нэмэгдсэн , 479 устгасан
  1. 6 2
      blade-common/pom.xml
  2. 3 3
      blade-common/src/main/java/org/springblade/common/utils/DeepSeekClient.java
  3. 2 0
      blade-gateway/src/main/java/org/springblade/gateway/provider/AuthProvider.java
  4. 25 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/dto/AutoOCRDTO.java
  5. 3 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/ArchivesAuto.java
  6. 6 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/TaskSplit.java
  7. 53 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/vo/ArchivesAutoInsertVO.java
  8. 6 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/dto/TrialClassificationTreeDTO.java
  9. 1 1
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/dto/TrialSummaryRecordDTO.java
  10. 2 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/dto/TrialSystemDockingDTO.java
  11. 2 1
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/ArchiveFile.java
  12. 7 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/TrialClassificationTree.java
  13. 1 1
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/TrialCyFinishTestReport.java
  14. 5 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/TrialCyTestType.java
  15. 3 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/TrialSelfInspectionRecord.java
  16. 2 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/TrialSystemDocking.java
  17. 4 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/feign/ArchiveFileClient.java
  18. 3 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/feign/InformationQueryClient.java
  19. 1 1
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/TrialCyThirdReportQueryVo.java
  20. 2 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/TrialSystemDockingVO.java
  21. 1 1
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/FormData.java
  22. 17 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/WbsInfoDTO.java
  23. 17 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/WbsTreeSynchronousRecordDTO.java
  24. 103 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ContractCollectFolder.java
  25. 18 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ContractInfo.java
  26. 6 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ExctabCell.java
  27. 3 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/TrialSummaryClassificationConfiguration.java
  28. 83 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/UserProjectInfoCollect.java
  29. 6 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/WbsFormElement.java
  30. 13 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/WbsInfo.java
  31. 19 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/WbsTreeSynchronousRecord.java
  32. 19 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/cq/Attachment.java
  33. 21 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/cq/QualityData.java
  34. 24 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/cq/QualityDataFile.java
  35. 30 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/cq/ResultApi.java
  36. 6 1
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/enums/ExecuteType.java
  37. 3 2
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/WbsTreePrivateClient.java
  38. 51 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/APIWbsContractSubdivisionExpandVo.java
  39. 3 27
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/APIWbsContractSubdivisionVo.java
  40. 22 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ContractCollectFolderVO.java
  41. 6 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ContractInfoVO.java
  42. 19 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ExcelTabVO.java
  43. 17 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ProjectInfoVO.java
  44. 33 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ProjectInfoVO3.java
  45. 6 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/TreeNodeVO.java
  46. 80 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/TrialTableDataInfo.java
  47. 7 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsNodeTableVO.java
  48. 2 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsTreeContractLazyVO.java
  49. 9 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsTreeContractTreeAllVO.java
  50. 39 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsTreePrivateQueryVO.java
  51. 36 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsTreePrivateTableVO.java
  52. 4 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsTreePrivateVO.java
  53. 10 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/copyNodeVo.java
  54. 25 0
      blade-service-api/blade-user-api/src/main/java/org/springblade/system/user/dto/TokenVerifyResult.java
  55. 23 4
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveFileAutoController.java
  56. 33 2
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveFileController.java
  57. 143 47
      blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchivesAutoController.java
  58. 3 3
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.xml
  59. 2 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/TaskSplitMapper.java
  60. 7 1
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/TaskSplitMapper.xml
  61. 6 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/IArchivesAutoService.java
  62. 295 9
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java
  63. 26 5
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/TaskSplitServiceImpl.java
  64. 31 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/utils/FileUtils.java
  65. 491 6
      blade-service/blade-business/src/main/java/org/springblade/business/controller/FixedFlowController.java
  66. 6 1
      blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java
  67. 153 12
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TaskController.java
  68. 8 4
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialClassificationTreeController.java
  69. 2 2
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialCyController.java
  70. 20 1
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialDetectionController.java
  71. 170 92
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialSummaryController.java
  72. 3 0
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialSystemDockingController.java
  73. 24 6
      blade-service/blade-business/src/main/java/org/springblade/business/controller/UserViewProjectContractController.java
  74. 14 0
      blade-service/blade-business/src/main/java/org/springblade/business/feignClient/ArchiveFileClientImpl.java
  75. 5 1
      blade-service/blade-business/src/main/java/org/springblade/business/feignClient/InformationQueryClientImpl.java
  76. 13 54
      blade-service/blade-business/src/main/java/org/springblade/business/feignClient/TrialCyAccessoriesClientImpl.java
  77. 3 4
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/ArchiveFileMapper.xml
  78. 2 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/InformationQueryMapper.java
  79. 15 3
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/InformationQueryMapper.xml
  80. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialClassificationTreeMapper.java
  81. 2 2
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialClassificationTreeMapper.xml
  82. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyAccessoriesMapper.java
  83. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyAccessoriesMapper.xml
  84. 7 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyFinishTestReportMapper.java
  85. 32 14
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyFinishTestReportMapper.xml
  86. 2 1
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyTestTypeMapper.java
  87. 3 2
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyTestTypeMapper.xml
  88. 12 13
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyThirdReportMapper.xml
  89. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialSelfInspectionRecordMapper.xml
  90. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialSystemDockingMapper.xml
  91. 36 58
      blade-service/blade-business/src/main/java/org/springblade/business/scheduled/ChenYuTestScheduled.java
  92. 1 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/IArchiveFileService.java
  93. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/service/ITaskService.java
  94. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/service/ITrialClassificationTreeService.java
  95. 8 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/TrialCyFinishTestReportService.java
  96. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/service/TrialCyService.java
  97. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/service/TrialCyTestTypeService.java
  98. 5 3
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/EntrustInfoServiceImpl.java
  99. 26 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/InformationQueryServiceImpl.java
  100. 202 80
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TaskServiceImpl.java

+ 6 - 2
blade-common/pom.xml

@@ -77,11 +77,11 @@
         </dependency>
 
         <!-- 使用OkHttp -->
-        <dependency>
+   <!--     <dependency>
             <groupId>com.squareup.okhttp3</groupId>
             <artifactId>okhttp</artifactId>
             <version>4.9.3</version>
-        </dependency>
+        </dependency>-->
 
         <!-- 使用Gson进行JSON处理 -->
         <dependency>
@@ -89,6 +89,10 @@
             <artifactId>gson</artifactId>
             <version>2.8.9</version>
         </dependency>
+        <dependency>
+            <groupId>io.github.openfeign</groupId>
+            <artifactId>feign-okhttp</artifactId>
+        </dependency>
 
     </dependencies>
 

+ 3 - 3
blade-common/src/main/java/org/springblade/common/utils/DeepSeekClient.java

@@ -33,7 +33,7 @@ public class DeepSeekClient {
                 .build();
     }
 
-/**
+    /**
      * 请求 DeepSeek API
      */
 
@@ -62,7 +62,7 @@ public class DeepSeekClient {
     }
 
 
-/**
+    /**
      * 解析响应获取结果
      */
 
@@ -92,7 +92,7 @@ public class DeepSeekClient {
     }
 
 
-/**
+    /**
      * 直接获取精简后的内容
      */
 

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

@@ -37,6 +37,7 @@ public class AuthProvider {
         DEFAULT_SKIP_URL.add("/oauth/token/**");
         DEFAULT_SKIP_URL.add("/loginByToken");
         DEFAULT_SKIP_URL.add("/loginByToken2");
+        DEFAULT_SKIP_URL.add("/loginByToken5");
         DEFAULT_SKIP_URL.add("/submit2");
         DEFAULT_SKIP_URL.add("/exceltab/callbackSave");
         DEFAULT_SKIP_URL.add("/oauth/captcha/**");
@@ -67,6 +68,7 @@ public class AuthProvider {
         DEFAULT_SKIP_URL.add("/getQualityTestingToken"); //成渝第三方登录获取质检系统tokne
         DEFAULT_SKIP_URL.add("/getArchiveToken"); //成渝第三方登录获取档案系统tokne
         DEFAULT_SKIP_URL.add("/meeting/**");//DingDing会议接口
+        DEFAULT_SKIP_URL.add("/hczc/api/meter/**");//重庆高速计量获取分部分项划分
 
     }
 

+ 25 - 0
blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/dto/AutoOCRDTO.java

@@ -0,0 +1,25 @@
+package org.springblade.archive.dto;
+
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Data
+public class AutoOCRDTO {
+    private String ids;  // 改为String类型
+
+    // 添加方法获取Long列表
+    public List<Long> getIdList() {
+        if (ids == null || ids.trim().isEmpty()) {
+            return new ArrayList<>();
+        }
+        return Arrays.stream(ids.split(","))
+                .map(String::trim)
+                .filter(s -> !s.isEmpty())
+                .map(Long::valueOf)
+                .collect(Collectors.toList());
+    }
+}

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

@@ -189,6 +189,9 @@ public class ArchivesAuto extends BaseEntity {
 
     @ApiModelProperty("颜色状态")
     private Integer colourStatus;
+
+    @ApiModelProperty("案卷操作(0:无,1:正在并卷,2:正在重组,3:等待重组(拆卷完成后),-1:并卷失败,-2:重组失败)")
+    private Integer actionType;
     //是否是影音
     public boolean isMedia() {
         return (this.getCarrierType() != null &&

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

@@ -71,4 +71,10 @@ public class TaskSplit extends BaseEntity {
 
 	@ApiModelProperty("分解任务名称")
 	private String taskName;
+
+	/**
+	 * 分解类型
+	 */
+	@ApiModelProperty("1:案卷分解 2 :仓库扫描 ")
+	private Integer dataType;
 }

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

@@ -0,0 +1,53 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.springblade.archive.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 视图实体类
+ *
+ * @author BladeX
+ * @since 2023-02-17
+ */
+@Data
+public class ArchivesAutoInsertVO implements Serializable {
+	private static final long serialVersionUID = 1L;
+
+	@ApiModelProperty("目标案卷id")
+	private Long targetId;
+
+//	@ApiModelProperty("type, 0:后,1:前")
+//	private Integer type;
+
+	@ApiModelProperty("被选择的案卷id")
+	private Long sourceId;
+
+	@ApiModelProperty("被插入的文件ids")
+	private String sourceArchiveFileIds;
+
+//	@ApiModelProperty("选择位置的文件id")
+//	private Long targetIndexFileId;
+
+	@ApiModelProperty("ids")
+	private String sortFileList;
+
+}

+ 6 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/dto/TrialClassificationTreeDTO.java

@@ -44,10 +44,16 @@ public class TrialClassificationTreeDTO {
 
 	private Long projectId;
 
+	private Long contractId;
+
 	/**
 	 * 分类名称
 	 */
 	private String classificationName;
 
+	/**
+	 * 排序
+	 */
+	private Integer sort;
 
 }

+ 1 - 1
blade-service-api/blade-business-api/src/main/java/org/springblade/business/dto/TrialSummaryRecordDTO.java

@@ -17,7 +17,7 @@ public class TrialSummaryRecordDTO implements Serializable {
     @ApiModelProperty(value = "检测类型")
     private Integer detectionType;
 
-    @ApiModelProperty(value = "单位类型")
+    @ApiModelProperty(value = "单位类型, 1施工,2监理,3业主")
     private Integer unitType;
 
     @ApiModelProperty(value = "汇总开始时间,格式yyyy-MM-dd")

+ 2 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/dto/TrialSystemDockingDTO.java

@@ -42,6 +42,8 @@ public class TrialSystemDockingDTO {
 	 */
 	@NotNull(message = "projectId 不能为空")
 	private Long projectId;
+
+	private Long contractId;
 	/**
 	 * 报告文件名称
 	 */

+ 2 - 1
blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/ArchiveFile.java

@@ -509,7 +509,8 @@ public class ArchiveFile extends BaseEntity {
     }
 
     public void setFileTime(String fileTime) {
-        if (fileTime == null || fileTime.equals("null") ) {
+        if (fileTime == null) return;
+        if (fileTime.equals("null")) {
             this.fileTime = "";
             return;
         }

+ 7 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/TrialClassificationTree.java

@@ -42,6 +42,8 @@ public class TrialClassificationTree extends BaseEntity {
 
 
 	private Long projectId;
+
+	private Long contractId;
 	/**
 	* 父级ID
 	*/
@@ -66,4 +68,9 @@ public class TrialClassificationTree extends BaseEntity {
 
 	private Integer isDeleted;
 
+	/**
+	 * 排序
+ 	 */
+	private Integer sort;
+
 }

+ 1 - 1
blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/TrialCyFinishTestReport.java

@@ -138,7 +138,7 @@ public class TrialCyFinishTestReport {
      * 试验树id
      */
     @ApiModelProperty("组装文件(报告+记录+委托单)")
-    @TableField("assemble_file")
+        @TableField("assemble_file")
     public String assembleFile;
     /**
      * 附件

+ 5 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/TrialCyTestType.java

@@ -23,6 +23,11 @@ public class TrialCyTestType {
      */
     @ApiModelProperty("项目id")
     private Long projectId;
+    /**
+     * 项目id
+     */
+    @ApiModelProperty("合同段id")
+    private Long contractId;
     /**
      * ID唯一标识
      */

+ 3 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/TrialSelfInspectionRecord.java

@@ -1,5 +1,7 @@
 package org.springblade.business.entity;
 
+import com.baomidou.mybatisplus.annotation.FieldStrategy;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import io.swagger.annotations.ApiModelProperty;
@@ -78,6 +80,7 @@ public class TrialSelfInspectionRecord extends BaseEntity {
     private String pdfUrl;
 
     @ApiModelProperty(value = "委托单Id")
+    @TableField(updateStrategy= FieldStrategy.IGNORED)
     private Long entrustId;
 
     @ApiModelProperty("判断依据:规范id")

+ 2 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/TrialSystemDocking.java

@@ -48,6 +48,8 @@ public class TrialSystemDocking extends BaseEntity {
 	 */
 	private Long projectId;
 
+	private Long contractId;
+
 	private String classificationAncestors;
 	/**
 	* 报告文件名称

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

@@ -42,6 +42,10 @@ public interface ArchiveFileClient {
     @PostMapping(API_PREFIX + "/updateArchiveFileSort")
     void updateArchiveFileSort(@RequestBody ArchiveFileVO vo);
 
+    //只修改实体数据
+    @PostMapping(API_PREFIX + "/batchUpdateInfo")
+    void batchUpdateInfo(@RequestBody ArchiveFileVO vo);
+
     @PostMapping(API_PREFIX + "/updateArchiveFileByBoxName")
     boolean updateArchiveFileByBoxName(@RequestBody Map<String, Object> jsons);
 

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

@@ -104,4 +104,7 @@ public interface InformationQueryClient {
 
     @PostMapping(API_PREFIX+"/delInformation")
     void delInformation(@RequestBody InformationQuery infoByWbsId);
+
+    @PostMapping(API_PREFIX+"/getInformationByContractIdAll")
+    List<InformationQuery> getInformationByContractIdAll(@RequestParam Long contractId);
 }

+ 1 - 1
blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/TrialCyThirdReportQueryVo.java

@@ -19,7 +19,7 @@ public class TrialCyThirdReportQueryVo {
     private String endTime;
     @ApiModelProperty("树节点id")
     @NotNull(message = "树节点id不能为空")
-    private Long nodeId;
+    private String nodeId;
     @ApiModelProperty("合同段id")
     @NotNull(message = "合同段id不能为空")
     private Long contractId;

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

@@ -38,6 +38,8 @@ public class TrialSystemDockingVO {
 	 * 项目Id
 	 */
 	private Long projectId;
+
+	private Long contractId;
 	/**
 	 * 报告文件名称
 	 */

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

@@ -66,7 +66,7 @@ public class FormData {
      */
     private Integer sort = 0;
     /**
-     * 内容:同一个groupId下List<每一页内容>
+     * 内容:同一个groupId下List<每一页内容> key 坐标
      * 用于输出
      */
     private List<ElementData> values=new ArrayList<>();

+ 17 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/WbsInfoDTO.java

@@ -4,8 +4,11 @@ import io.swagger.annotations.ApiModelProperty;
 import io.swagger.models.auth.In;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
+import org.springblade.manager.entity.ProjectInfo;
 import org.springblade.manager.entity.WbsInfo;
 
+import java.util.List;
+
 @Data
 @EqualsAndHashCode(callSuper = true)
 public class WbsInfoDTO extends WbsInfo {
@@ -27,5 +30,19 @@ public class WbsInfoDTO extends WbsInfo {
      */
     private Integer status;
 
+    /**
+     * 项目名称
+     */
+    @ApiModelProperty(value = "项目名称")
+    private String projectName;
+
+    /**
+     * 项目名称
+     */
+    @ApiModelProperty(value = "项目名称")
+    private String projectId;
+
+    List<ProjectInfo> projectInfoList;
+
 
 }

+ 17 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/WbsTreeSynchronousRecordDTO.java

@@ -0,0 +1,17 @@
+package org.springblade.manager.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springblade.manager.entity.WbsTreeSynchronousRecord;
+
+/**
+ * @author LHB
+ */
+@Data
+public class WbsTreeSynchronousRecordDTO extends WbsTreeSynchronousRecord {
+    @ApiModelProperty("进度")
+    private Integer progress = 0;
+
+    @ApiModelProperty("剩余数量")
+    private Integer surplusCount = 0;
+}

+ 103 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ContractCollectFolder.java

@@ -0,0 +1,103 @@
+package org.springblade.manager.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+@TableName("m_contract_collect_folder")
+@NoArgsConstructor
+@AllArgsConstructor
+public class ContractCollectFolder implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty("主键id")
+    @TableId(
+            value = "id",
+            type = IdType.ASSIGN_ID
+    )
+    private Long id;
+
+    /**
+     * 父主键
+     */
+    @ApiModelProperty(value = "父主键id")
+    private Long parentId;
+
+    /**
+     * 收藏夹名称
+     */
+    @ApiModelProperty("收藏夹名称")
+    private String folderName;
+    /**
+     * 节点Id
+     */
+    @ApiModelProperty("节点Id")
+    private Long nodeId;
+
+    /**
+     * 节点父Id
+     */
+    @ApiModelProperty("节点父Id")
+    private Long nodeParentId;
+
+    /**
+     * 节点路径pKeyIds
+     */
+    @ApiModelProperty("节点路径pKeyIds")
+    @TableField(exist = false)
+    private String nodeAncestors;
+
+    /**
+     * 合同Id
+     */
+    @ApiModelProperty("合同段Id")
+    private Long contractId;
+
+    /**
+     * 类型, 0 收藏夹, 1 节点
+     */
+    @ApiModelProperty(value = "类型, 0 收藏夹, 1 节点")
+    private Integer type;
+
+    /**
+     * 排序
+     */
+    @ApiModelProperty(value = "排序")
+    private Integer sort;
+
+    @ApiModelProperty("创建人")
+    private Long createUser;
+
+    @DateTimeFormat(
+            pattern = "yyyy-MM-dd HH:mm:ss"
+    )
+    @JsonFormat(
+            pattern = "yyyy-MM-dd HH:mm:ss"
+    )
+    @ApiModelProperty("创建时间")
+    private Date createTime;
+
+
+    @DateTimeFormat(
+            pattern = "yyyy-MM-dd HH:mm:ss"
+    )
+    @JsonFormat(
+            pattern = "yyyy-MM-dd HH:mm:ss"
+    )
+    @ApiModelProperty("更新时间")
+    private Date updateTime;
+
+    @ApiModelProperty("业务状态")
+    private Integer status;
+
+    @ApiModelProperty("是否已删除")
+    private Integer isDeleted;
+}

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

@@ -184,6 +184,24 @@ public class ContractInfo extends BaseEntity {
     @ApiModelProperty(value = "1正在扫描中 ,2没有扫描")
     private Integer isScan;
 
+    @ApiModelProperty(value = "电签项目id")
+    private String sealProjectId;
+
+    @ApiModelProperty(value = "账号id")
+    private String sealAccountId;
+
+    @ApiModelProperty(value = "客户编号")
+    private String sealCustomerId;
+
+    @ApiModelProperty(value = "通信key")
+    private String sealCommKey;
+
+    /**
+     * 排序
+     */
+    @ApiModelProperty(value = "排序")
+    private Integer sort;
+
     public BigDecimal getProjectMileage() {
         if (projectMileage == null){
             return null;

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

@@ -80,4 +80,10 @@ public class ExctabCell extends BaseEntity {
      */
     private String textDeviation;
 
+    /**
+     * exid
+     */
+    @ApiModelProperty(value = "exid")
+    private Long exid;
+
 }

+ 3 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/TrialSummaryClassificationConfiguration.java

@@ -32,4 +32,7 @@ public class TrialSummaryClassificationConfiguration extends BaseEntity {
     @ApiModelProperty(value = "排序")
     private Integer sort;
 
+    @ApiModelProperty(value = "项目类型,0:公路工程, 1:水利工程")
+    private Integer projectType;
+
 }

+ 83 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/UserProjectInfoCollect.java

@@ -0,0 +1,83 @@
+package org.springblade.manager.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.core.mp.base.BaseEntity;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.Date;
+
+@Data
+@TableName("m_user_project_collect")
+public class UserProjectInfoCollect implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "主键id")
+    @JsonProperty(value = "id")
+    @TableId(type = IdType.ASSIGN_ID)
+    private Long id;
+
+    /**
+     * 项目Id
+     */
+    @JsonProperty(value = "projectId")
+    @ApiModelProperty(name = "projectId", value = "项目Id", required = true)
+    private Long projectId;
+
+    @ApiModelProperty("排序")
+    private Integer sort;
+
+    /**
+     * 用户id
+     */
+    @JsonProperty(value = "userId")
+    @ApiModelProperty(name = "userId", value = "用户id", required = true)
+    private Long userId;
+
+
+    @JsonProperty(value = "createUser")
+    @ApiModelProperty(name = "createUser", value = "创建人", required = true)
+    private Long createUser;
+
+    @JsonProperty(value = "updateUser")
+    @ApiModelProperty(name = "updateUser", value = "更新人", required = true)
+    private Long updateUser;
+
+    @DateTimeFormat(
+            pattern = "yyyy-MM-dd HH:mm:ss"
+    )
+    @JsonFormat(
+            pattern = "yyyy-MM-dd HH:mm:ss"
+    )
+    @ApiModelProperty("创建时间")
+    private Date createTime;
+
+
+
+    @DateTimeFormat(
+            pattern = "yyyy-MM-dd HH:mm:ss"
+    )
+    @JsonFormat(
+            pattern = "yyyy-MM-dd HH:mm:ss"
+    )
+
+    @ApiModelProperty("更新时间")
+    private Date updateTime = new Date();
+
+    @ApiModelProperty("状态")
+    private Integer status = 1;
+
+    @TableLogic
+    @ApiModelProperty("是否已删除")
+    private Integer isDeleted = 0;
+}

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

@@ -71,4 +71,10 @@ public class WbsFormElement extends BaseEntity {
     @ApiModelProperty(value = "动态字典,征拆统计")
     @JsonProperty(value = "dynamicDict")
     private Integer dynamicDict;
+
+    /**
+     * exid
+     */
+    @ApiModelProperty(value = "exid")
+    private Long exid;
 }

+ 13 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/WbsInfo.java

@@ -1,10 +1,13 @@
 package org.springblade.manager.entity;
 
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import org.springblade.core.mp.base.BaseEntity;
 
+import java.util.List;
+
 @Data
 @TableName("m_wbs_info")
 @EqualsAndHashCode(callSuper = true)
@@ -21,5 +24,15 @@ public class WbsInfo extends BaseEntity {
      */
     private Integer wbsType;
 
+    /**
+     * 排序
+     */
+    private Integer sort;
+
+    /**
+     * 项目列表
+     */
+    @TableField(exist = false)
+    private List<ProjectInfo> projectInfoList;
 
 }

+ 19 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/WbsTreeSynchronousRecord.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.annotation.FieldStrategy;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import java.util.Date;
@@ -26,69 +27,84 @@ public class WbsTreeSynchronousRecord {
     /**
      * 项目id
      */
+    @ApiModelProperty(value = "项目id")
     private Long projectId;
 
     /**
      * 项目名称
      */
+    @ApiModelProperty(value = "项目名称")
     private String projectName;
 
 
+    @ApiModelProperty(value = "同步范围(1-从后管同步,2-同步到合同段)")
     @TableField("`range`")
     private Integer range;
     /**
      * 同步范围名称
      */
+    @ApiModelProperty(value = "同步范围名称")
     private String rangeName;
     /**
      * 合同段范围 逗号拼接的编号 101.未填报 102.已填报-未上报 103.未上报 104.待审批 105.已审批
      */
+    @ApiModelProperty(value = "合同段范围 逗号拼接的编号 101.未填报 102.已填报-未上报 103.未上报 104.待审批 105.已审批")
     private String contractRange;
     /**
      * 合同段范围名称
      */
+    @ApiModelProperty(value = "合同段范围名称")
     private String contractRangeName;
 
     /**
      * 同步源Id
      */
+    @ApiModelProperty(value = "同步源Id")
     private Long templateId;
 
     /**
      * 同步源名称
      */
+    @ApiModelProperty(value = "同步源名称")
     private String templateName;
 
     /**
      * 同步类型 逗号拼接的编号 1.新增表单 2.清表配置 3.元素配置 4.电签配置 5.公式配置 6.默认值配置 7.表单排序
      */
+    @ApiModelProperty(value = "同步类型 逗号拼接的编号 1.新增表单 2.清表配置 3.元素配置 4.电签配置 5.公式配置 6.默认值配置 7.表单排序")
     private String type;
 
     /**
      * 同步类型名称
      */
+    @ApiModelProperty(value = "同步类型名称")
     private String typeName;
 
     /**
      * 同步节点id 多个节点
      */
+    @ApiModelProperty(value = "同步节点id 多个节点")
     private String nodeId;
 
     /**
      * 同步节点名称
      */
+    @ApiModelProperty(value = "同步节点名称")
     private String nodeName;
     /**
      * 表单Ids     range = 4 强制同步时  当前数据为同步源
      */
+    @ApiModelProperty(value = "表单Ids     range = 4 强制同步时  当前数据为同步源")
     private String formIds;
     /**
      * 同步节点数量
      */
+    @ApiModelProperty(value = "同步节点数量")
     private Integer nodeNum;
     /**
      * 已同步数量
      */
+    @ApiModelProperty(value = "已同步数量")
     private Integer nodeNumEnd;
 
     /**
@@ -99,15 +115,18 @@ public class WbsTreeSynchronousRecord {
     /**
      * 状态(0-未同步,1-正在同步,2-已同步,3-同步失败)
      */
+    @ApiModelProperty(value = "状态(0-未同步,1-正在同步,2-已同步,3-同步失败)")
     private Integer status;
     /**
      * 状态(0-未同步,1-正在同步,2-已同步,3-同步失败)
      */
+    @ApiModelProperty(value = "状态名称")
     @TableField(exist = false)
     private String statusName;
     /**
      * 错误信息
      */
+    @ApiModelProperty(value = "错误信息")
     @TableField(updateStrategy = FieldStrategy.NOT_EMPTY)
     private String errorMsg;
     /**

+ 19 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/cq/Attachment.java

@@ -0,0 +1,19 @@
+package org.springblade.manager.entity.cq;
+
+import lombok.Data;
+
+/**
+ * @author LHB
+ */
+@Data
+public class Attachment {
+
+    //文件名称
+    private String name;
+    //文件类型排序
+    private String order;
+    //pdf文件url
+    private String url;
+    //文件备注
+    private String comment;
+}

+ 21 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/cq/QualityData.java

@@ -0,0 +1,21 @@
+package org.springblade.manager.entity.cq;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author LHB
+ * 质量资料对象
+ */
+@Data
+public class QualityData {
+    //文件类型(支持多个文件类型)
+    private String type;
+    //文件类型名称
+    private String typename;
+    //文件类型排序
+    private Integer typeOrder;
+    //文件(支持多个文件)
+    private List<QualityDataFile> files;
+}

+ 24 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/cq/QualityDataFile.java

@@ -0,0 +1,24 @@
+package org.springblade.manager.entity.cq;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author LHB
+ */
+@Data
+public class QualityDataFile {
+    //文件名称
+    private String name;
+    //文件类型名称
+    private String typeName;
+    //文件类型排序
+    private String order;
+    //pdf文件url
+    private String url;
+    //文件备注
+    private String comment;
+    //附件(支持多个附件)
+    private List<Attachment> attachments;
+}

+ 30 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/cq/ResultApi.java

@@ -0,0 +1,30 @@
+package org.springblade.manager.entity.cq;
+
+
+import lombok.Data;
+
+/**
+ * @author LHB
+ * 重庆高速计量接口响应类
+ */
+@Data
+public class ResultApi<T> {
+    private Integer state;
+    private String message;
+    private T data;
+
+    public static ResultApi success(Object data) {
+        ResultApi resultApi = new ResultApi();
+        resultApi.setState(1);
+        resultApi.setMessage("");
+        resultApi.setData(data);
+        return resultApi;
+    }
+
+    public static ResultApi fail(String message) {
+        ResultApi resultApi = new ResultApi();
+        resultApi.setState(2);
+        resultApi.setMessage(message);
+        return resultApi;
+    }
+}

+ 6 - 1
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/enums/ExecuteType.java

@@ -12,10 +12,15 @@ import lombok.Getter;
 public enum ExecuteType {
     /*Quality Inspection (质量检查)*/
     INSPECTION("质检", 0),
+
     /*Material Testing (材料试验) */
     TESTING("试验", 1),
+
     /*First Article 首件*/
-    FAI("首件", 2);
+    FAI("首件", 2),
+
+    /*log info 日志*/
+    LOGINFO("日志", 3);
     final String name;
     final int mode;
 }

+ 3 - 2
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/WbsTreePrivateClient.java

@@ -51,7 +51,7 @@ public interface WbsTreePrivateClient {
     List<WbsTreeContractTreeVOS> queryWbsTreePrivateByProjectIdAndId(@RequestParam String projectId, @RequestParam Long id);
 
     @PostMapping(API_PREFIX + "/copyBussTab")
-    boolean copyBussTab(@RequestParam Long pKeyId, @RequestParam Long id, @RequestParam Long contractId);
+    Long copyBussTab(@RequestParam Long pKeyId, @RequestParam Long id, @RequestParam Long contractId, @RequestParam(required = false) String tableIds);
 
     @PostMapping(API_PREFIX + "/getRawMaterialTree")
     List<WbsTreePrivateVO> getRawMaterialTree(@RequestParam Long pKeyId);
@@ -88,5 +88,6 @@ public interface WbsTreePrivateClient {
     @GetMapping(API_PREFIX +"/get-node-class")
     WbsTreePrivate getNodeClass(@RequestParam Long isTypePrivatePid);
 
-
+    @PostMapping(API_PREFIX + "/testFormInit")
+    List<Long> testFormInit(@RequestParam Long projectId, @RequestParam Long contractId, @RequestParam String wbsId, @RequestParam Long id);
 }

+ 51 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/APIWbsContractSubdivisionExpandVo.java

@@ -0,0 +1,51 @@
+package org.springblade.manager.vo;
+
+import lombok.Data;
+
+/**
+ * 合同段分部分项划分节点试图
+ * 包含各个状态
+ * | 01   | 交工证书     | 所有子节点存在一个的major_data_type = 3   值为 true     |
+ * | 02   | 7天强度报告  | 所有最小节点中在m_table_file 中type = 11  存在一个true  |
+ * | 03   | 28天强度报告 | 所有最小节点中在m_table_file 中type = 12   存在一个true |
+ * | 04   | 监理收验资料 | 监理 major_data_type = 4  全部已审批                    |
+ * | 05   | 桩检报告     | 所有最小节点中在m_table_file  中type = 13   存在一个true |
+ * | 06   | 质检资料     | 质检 major_data_type = 4  全部已审批                    |
+ * | 07   | 评定资料     | major_data_type = 2  全部已审批                         |
+ * @author LHB
+ */
+@Data
+public class APIWbsContractSubdivisionExpandVo {
+    /**
+     * 主键
+     */
+    private Long id;
+    /**
+     * 交工证书
+     */
+    private Boolean completionCertificate = false;
+    /**
+     * 7天强度报告
+     */
+    private Boolean strengthReportSeven = false;
+    /**
+     * 28天强度报告
+     */
+    private Boolean strengthReportTwentyEight = false;
+    /**
+     * 监理资料
+     */
+    private Boolean supervisionData = false;
+    /**
+     * 桩检报告
+     */
+    private Boolean pileInspectionReport = false;
+    /**
+     * 质检资料
+     */
+    private Boolean qualityInspectionData = false;
+    /**
+     * 评定资料
+     */
+    private Boolean evaluationData = false;
+}

+ 3 - 27
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/APIWbsContractSubdivisionVo.java

@@ -10,7 +10,7 @@ import org.springblade.manager.entity.WbsTreeContract;
  * | 02   | 7天强度报告  | 所有最小节点中在m_table_file 中type = 11  存在一个true  |
  * | 03   | 28天强度报告 | 所有最小节点中在m_table_file 中type = 12   存在一个true |
  * | 04   | 监理收验资料 | 监理 major_data_type = 4  全部已审批                    |
- * | 05   | 桩检报告     | 所有最小节点中在m_table_file 中type = 13   存在一个true |
+ * | 05   | 桩检报告     | 所有最小节点中在m_table_file  中type = 13   存在一个true |
  * | 06   | 质检资料     | 质检 major_data_type = 4  全部已审批                    |
  * | 07   | 评定资料     | major_data_type = 2  全部已审批                         |
  * @author LHB
@@ -54,31 +54,7 @@ public class APIWbsContractSubdivisionVo {
      */
     private String partitionCatagName;
     /**
-     * 交工证书
+     * 排序
      */
-    private Boolean completionCertificate = false;
-    /**
-     * 7天强度报告
-     */
-    private Boolean strengthReportSeven = false;
-    /**
-     * 28天强度报告
-     */
-    private Boolean strengthReportTwentyEight = false;
-    /**
-     * 监理资料
-     */
-    private Boolean supervisionData = false;
-    /**
-     * 桩检报告
-     */
-    private Boolean pileInspectionReport = false;
-    /**
-     * 质检资料
-     */
-    private Boolean qualityInspectionData = false;
-    /**
-     * 评定资料
-     */
-    private Boolean evaluationData = false;
+    private Integer sort;
 }

+ 22 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ContractCollectFolderVO.java

@@ -0,0 +1,22 @@
+package org.springblade.manager.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+public class ContractCollectFolderVO {
+    @ApiModelProperty(value = "id, 收藏夹id")
+    private Long id;
+
+    @ApiModelProperty(value = "收藏夹名称")
+    private String name;
+
+    @ApiModelProperty(value = "节点pKeyId, 收藏和取消收藏时使用")
+    private Long nodeId;
+
+    @ApiModelProperty(value = "合同段id")
+    private Long contractId;
+
+    @ApiModelProperty(value = "1收藏,0取消收藏")
+    private Integer type;
+}

+ 6 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ContractInfoVO.java

@@ -40,5 +40,11 @@ public class ContractInfoVO extends ContractInfo {
     @ApiModelProperty("计量合同段-关联详情信息")
     private MeterContractInfo meterContractInfo;
 
+    /**
+     * 关联合同段
+     */
+    @ApiModelProperty("关联合同段")
+    private List<ContractInfo> relationContractInfo;
+
 
 }

+ 19 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ExcelTabVO.java

@@ -20,6 +20,9 @@ import io.swagger.annotations.ApiModelProperty;
 import org.springblade.manager.entity.ExcelTab;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
+import org.springblade.manager.entity.ProjectInfo;
+
+import java.util.List;
 
 /**
  * 清表基础数据表视图实体类
@@ -35,4 +38,20 @@ public class ExcelTabVO extends ExcelTab {
     @ApiModelProperty(value = "清表模板类型名称")
     private String tableTemplateTypeName;
 
+    @ApiModelProperty(value = "项目id")
+    private Long projectId;
+
+    @ApiModelProperty(value = "项目名称")
+    private String projectName;
+
+    List<ProjectInfoVO1> projectInfoList;
+
+    @ApiModelProperty(value = "项目使用数量")
+    private Integer projectUseNumber;
+
+    @ApiModelProperty(value = "清表使用数量")
+    private Integer excelUseNumber;
+
+    @ApiModelProperty(value = "创建人名称")
+    private String createUserName;
 }

+ 17 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ProjectInfoVO.java

@@ -38,4 +38,21 @@ public class ProjectInfoVO extends ProjectInfo {
     @ApiModelProperty(value = "wbsType")
     private Integer wbsType;
 
+    /**
+     * 项目负责人
+     */
+    @ApiModelProperty(value = "项目负责人姓名")
+    private String projectLeaderName;
+
+    /**
+     * 是否收藏
+     */
+    @ApiModelProperty(value = "是否收藏 0 否, 1 是")
+    private Integer isCollect;
+
+    /**
+     * wbs 类型
+     */
+    @ApiModelProperty(value = "wbs 类型")
+    private List<Integer> wbsTypes;
 }

+ 33 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ProjectInfoVO3.java

@@ -1,5 +1,38 @@
 package org.springblade.manager.vo;
 
+import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
+import org.springblade.manager.entity.ProjectInfo;
+import java.io.Serializable;
+@Data
+public class ProjectInfoVO3 implements Serializable {
+    private static final long serialVersionUID = 1L;
 
+    /**
+     * 项目名称、别名
+     */
+    @ApiModelProperty(value = "项目名称、别名")
+    private String name;
+    /**
+     * 项目状态, 0:未开始, 1:配置中, 2: 进行中, 3: 已完成, null: 全部
+     */
+    @ApiModelProperty(value = "项目状态, 0:未开始, 1:配置中, 2: 进行中, 3: 已完成, null: 全部。 默认值:null")
+    private Integer status;
+    /**
+     * 排序方式,0:默认排序, 1:收藏优先, 2:创建时间, 3:我负责的
+     */
+    @ApiModelProperty(value = "排序方式,0:默认排序, 1:收藏优先, 2:创建时间, 3:我负责的。默认值:0")
+    private Integer sort = 0;
+    /**
+     * 是否收藏,0:全部, 1:收藏
+     */
+    @ApiModelProperty(value = "是否收藏,0:全部, 1:收藏。 默认值:1")
+    private Integer isCollect = 1;
+    /**
+     * 用户id
+     */
+    @ApiModelProperty(value = "用户id, 可以不传值")
+    private Long userId;
+
+}
 

+ 6 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/TreeNodeVO.java

@@ -6,6 +6,8 @@ import lombok.Data;
 import org.springblade.core.tool.node.BaseNode;
 import org.springblade.core.tool.node.TreeNode;
 
+import java.util.Date;
+
 @Data
 public class TreeNodeVO extends BaseNode<TreeNode> {
     private static final long serialVersionUID = 1L;
@@ -55,6 +57,10 @@ public class TreeNodeVO extends BaseNode<TreeNode> {
 
     private String erTreeId;
 
+    private Long updateUser;
+    private Date updateTime;
+    private String updateUserName;
+
     public TreeNodeVO() {
     }
 

+ 80 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/TrialTableDataInfo.java

@@ -0,0 +1,80 @@
+package org.springblade.manager.vo;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import lombok.Data;
+import lombok.Getter;
+import org.springblade.manager.entity.WbsFormElement;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+
+@Data
+public class TrialTableDataInfo implements java.io.Serializable {
+    private static final long serialVersionUID = 1L;
+    public static final String ID="203700000001";
+    public static final Long LONG_ID=203700000001L;
+    public static final String TBN="TrialTableDataInfo";
+    public static final String TBN_CH="试验表格数据";
+    static final String UNKNOWN="未设置";
+
+    public static List<WbsFormElement> getElementList() {
+        TrialTableElementEnum[] values = TrialTableElementEnum.values();
+        List<WbsFormElement> result = new ArrayList<>();
+        for (TrialTableElementEnum value : values) {
+            WbsFormElement element = new WbsFormElement();
+            element.setId(value.id);
+            element.setEKey(value.key);
+            element.setEName(value.cnName);
+            element.setEType(1);
+            element.setELength(200);
+            element.setIsDeleted(0);
+            element.setStatus(1);
+            result.add(element);
+        }
+        return result;
+    }
+
+    public static String getElementName(String key) {
+        TrialTableElementEnum[] values = TrialTableElementEnum.values();
+        for (TrialTableElementEnum value : values) {
+            if (value.key.equals(key)) {
+                return value.cnName;
+            }
+        }
+        return UNKNOWN;
+    }
+
+    @Getter
+    public static enum TrialTableElementEnum {
+        RECORD_NO(203700000001001L, "key_301","recordNo", "记录编号"),
+        REPORT_NO(203700000001002L, "key_302","reportNo", "报告编号"),
+        ENTRUST_NO(203700000001003L, "key_303","entrustNo", "委托单编号"),
+        SPECIFICATION_NUMBER(203700000001004L, "key_304","specificationNumber", "样品编号"),
+        TRIAL_PROJECT_NAME(203700000001005L, "key_305","trialProjectName", "试验项目名称"),
+        TASK_STATUS(203700000001006L, "key_306","taskStatus", "任务状态"),
+        REPORT_DATE(203700000001007L, "key_307","reportDate", "报告日期"),
+        TRIAL_USER_NAME(203700000001008L, "key_308","trialUserName", "试验人员"),
+        DETECTION_CATEGORY(203700000001009L, "key_309","detectionCategory", "检测类别"),
+        SPECIFICATION_MODEL(203700000001010L, "key_310","specificationModel", "规格类型"),
+        PROJECT_POSITION(203700000001011L, "key_311","projectPosition", "工程部位及用途"),
+        SAMPLING_LOCATION(203700000001012L, "key_312","samplingLocation", "取样地点"),
+        IS_UPLOAD_CERTIFICATE(203700000001013L, "key_313","isUploadCertificate", "是否上传合格证"),
+        ENTRUST_NAME(203700000001014L, "key_314","entrustName", "委托单名称"),
+        CONTRACT_NAME(203700000001015L, "key_315","contractName", "合同段"),
+        COMPANY(203700000001016L, "key_316","company", "单位"),
+        DETECTION_RESULT(203700000001017L, "key_317","detectionResult", "检测结果"),
+        ;
+        private final Long id;
+        private final String key;
+        private final String enName;
+        private final String cnName;
+        TrialTableElementEnum(Long id, String key, String enName, String chName) {
+            this.id = id;
+            this.key = key;
+            this.cnName = chName;
+            this.enName = enName;
+        }
+    }
+}

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

@@ -92,5 +92,12 @@ public class WbsNodeTableVO implements Serializable {
     private String htmlUrl;
 
     private String nodeType;
+    private Integer wbsType;
+
+    @ApiModelProperty(value = "父级节点名称")
+    private String parentName;
+
+    @ApiModelProperty(value = "祖级路径")
+    private String ancestorPId;
 
 }

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

@@ -142,4 +142,6 @@ public class WbsTreeContractLazyVO implements Serializable {
     @ApiModelProperty(value = "是否最近同步节点")
     private Integer isSync;
 
+    @ApiModelProperty(value = "是否收藏")
+    private Integer isCollect;
 }

+ 9 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsTreeContractTreeAllVO.java

@@ -53,6 +53,15 @@ public class WbsTreeContractTreeAllVO implements INode<WbsTreeContractTreeAllVO>
     @JsonInclude(JsonInclude.Include.NON_EMPTY)
     private Boolean hasChildren;
 
+    @ApiModelProperty(value = "是否收藏")
+    private Integer isCollect;
+
+    @ApiModelProperty(value = "是否隐藏,2为隐藏")
+    private Integer isBussShow;
+
+    @ApiModelProperty("是否存在下级")
+    private Boolean notExsitChild;
+
     @Override
     public List<WbsTreeContractTreeAllVO> getChildren() {
         if (this.children == null) {

+ 39 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsTreePrivateQueryVO.java

@@ -0,0 +1,39 @@
+package org.springblade.manager.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+
+@Data
+public class WbsTreePrivateQueryVO {
+
+    @ApiModelProperty(value = "wbs Id", required = true)
+    @NotBlank(message = "wbsId不能为空")
+    private String wbsId;
+
+    @ApiModelProperty(value = "项目id", required = true)
+    @NotBlank(message = "projectId不能为空")
+    private String projectId;
+
+    @ApiModelProperty("搜索内容")
+    private String queryValue;
+
+    @ApiModelProperty("节点类型")
+    private Integer nodeType;
+
+    @ApiModelProperty("内业资料类型")
+    private Integer majorDataType;
+
+    @ApiModelProperty("标准分类")
+    private Integer className;
+
+    @ApiModelProperty(value = "单元名称")
+    private Integer unitName;
+
+    @ApiModelProperty(value = "是否在客户端新增时隐藏,0否1是")
+    private Integer isAddConceal;
+
+    @ApiModelProperty("参数掩码")
+    private String uniqueCode;
+}

+ 36 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsTreePrivateTableVO.java

@@ -0,0 +1,36 @@
+package org.springblade.manager.vo;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springblade.core.tool.node.INode;
+import org.springblade.manager.entity.WbsTree;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+@Data
+public class WbsTreePrivateTableVO  implements Serializable {
+    private static final long serialVersionUID = 1L;
+    /**
+     * 标题
+     */
+    @ApiModelProperty(value = "标题")
+    private String title;
+
+    @ApiModelProperty(value = "表单list")
+    List<WbsNodeTableVO> list;
+
+    private int sort;
+
+    public WbsTreePrivateTableVO() {
+    }
+    public WbsTreePrivateTableVO(String title, List<WbsNodeTableVO> list) {
+        this.title = title;
+        this.list = list;
+    }
+}

+ 4 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/WbsTreePrivateVO.java

@@ -76,5 +76,9 @@ public class WbsTreePrivateVO extends WbsTreePrivate implements INode<WbsTreePri
      */
     private List<String> tableFileTypes;
 
+    /**
+     * 项目名称
+     */
+    private String updateUserName;
 
 }

+ 10 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/copyNodeVo.java

@@ -0,0 +1,10 @@
+package org.springblade.manager.vo;
+
+import lombok.Data;
+
+import java.util.List;
+@Data
+public class copyNodeVo {
+  private   List<Long> leftIds;
+  private  List<Long>rightIds;
+}

+ 25 - 0
blade-service-api/blade-user-api/src/main/java/org/springblade/system/user/dto/TokenVerifyResult.java

@@ -0,0 +1,25 @@
+package org.springblade.system.user.dto;
+
+import lombok.Data;
+
+/**
+ * @author LHB
+ */
+@Data
+public class TokenVerifyResult {
+    // 验证结果
+    private boolean valid;
+    // 提示消息
+    private String message;
+    // JWT解析出的账号
+    private String account;
+
+    public TokenVerifyResult() {
+    }
+
+    public TokenVerifyResult(boolean valid, String message, String account) {
+        this.valid = valid;
+        this.message = message;
+        this.account = account;
+    }
+}

+ 23 - 4
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveFileAutoController.java

@@ -20,6 +20,7 @@ import org.springblade.business.feign.ArchiveFileClient;
 import org.springblade.business.vo.ArchiveFileVO;
 import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.boot.ctrl.BladeController;
+import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.oss.model.BladeFile;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.api.R;
@@ -132,8 +133,13 @@ ArchiveFileAutoController extends BladeController {
                     archivesAutoService.save(archive);
                 } else {
                     ArchivesAuto archivesAuto = archivesAutoService.getById(archive.getId());
+                    ArchivesAuto update= new ArchivesAuto();
+                    update.setId(archive.getId());
                     if (archivesAuto!= null ) {
-                        archive.setAutoFileSort(archivesAuto.getAutoFileSort());
+                        if (archivesAuto.getActionType() == 1 || archivesAuto.getActionType() == 2 ) {
+                            return R.fail("【" + archivesAuto.getName() + "】案卷已正在并卷或重组,请稍后再试!");
+                        }
+                        update.setAutoFileSort(archivesAuto.getAutoFileSort());
                     }
                     //如果有替换文件,则替换
                     List<ArchivesAutoVO.ApprovalFile> list = archive.getApprovalFileList();
@@ -156,12 +162,20 @@ ArchiveFileAutoController extends BladeController {
                                 archiveFile.setRectification(2);
                             }
                             //只修改档案的文件大小和页数
-                            archive.setPageN(file.getFilePage());
-                            archive.setFileSize(file.getFileSize());
+                            update.setPageN(file.getFilePage());
+                            update.setFileSize(file.getFileSize());
                             archiveFileClient.updateById2(archiveFile);
                         }
                     }
-                    archivesAutoService.updateById(archive);
+                    update.setName(archive.getName());
+                    update.setFileNumber(archive.getFileNumber());
+                    update.setUnit(archive.getUnit());
+                    update.setStorageTime(archive.getStorageTime());
+                    update.setRemark(archive.getRemark());
+                    update.setSecretLevel(archive.getSecretLevel());
+                    update.setStartDate(archive.getStartDate());
+                    update.setEndDate(archive.getEndDate());
+                    archivesAutoService.updateById(update);
 
                 }
             }
@@ -241,6 +255,11 @@ ArchiveFileAutoController extends BladeController {
                     }
                     archivesAutoService.save(archive);
                 } else {
+                    ArchivesAuto archivesAuto = archivesAutoService.getById(archive.getId());
+                    if (archivesAuto!= null && (archivesAuto.getActionType() == 1 || archivesAuto.getActionType() == 2)) {
+                        return R.fail("【" + archivesAuto.getName() + "】案卷已正在并卷或重组,请稍后再试!");
+                    }
+                    archive.setActionType(null);
                     archivesAutoService.updateById(archive);
                 }
             }

+ 33 - 2
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchiveFileController.java

@@ -157,7 +157,7 @@ public class ArchiveFileController extends BladeController {
     @ApiOperationSupport(order = 3)
     @ApiOperation(value = "分页")
     public R<Object> page(ArchiveFileVO queryVo) {
-        if (queryVo.getNodeIds().isEmpty() || queryVo.getNodeIds().equals("")) {
+        if (queryVo.getNodeIds()==null||queryVo.getNodeIds().isEmpty() || queryVo.getNodeIds().equals("")) {
 
         } else {
             ArchiveTreeContract rootNode = this.archiveTreeContractClient.getArchiveTreeContractById(Long.parseLong(queryVo.getNodeIds()));
@@ -367,7 +367,7 @@ public class ArchiveFileController extends BladeController {
     }
 
     /**
-     * 批量编辑
+     *
      */
     @PostMapping("/batchUpdate")
     @ApiOperationSupport(order = 13)
@@ -382,6 +382,37 @@ public class ArchiveFileController extends BladeController {
         return R.data(true);
     }
 
+    /**
+     * 批量编辑
+     */
+    @PostMapping("/batchUpdateInfo")
+    @ApiOperationSupport(order = 13)
+    @ApiOperation(value = "修改基础信息")
+    public R<Boolean> batchUpdateInfo(@RequestBody ArchiveFileVO vo) {
+        try {
+            List<ArchiveFileVO> list = vo.getList();
+            if (list != null && !list.isEmpty()) {
+                List<ArchiveFileVO> newList = new ArrayList<>();
+                for (ArchiveFileVO fileVO : list) {
+                    ArchiveFileVO newVo = new ArchiveFileVO();
+                    newVo.setId(fileVO.getId());
+                    newVo.setFileName(fileVO.getFileName());
+                    newVo.setFileNumber(fileVO.getFileNumber());
+                    newVo.setFileTime(fileVO.getFileTime());
+                    newVo.setDutyUser(fileVO.getDutyUser());
+                    newList.add(newVo);
+                }
+                vo.setList(newList);
+            }
+            this.archiveFileClient.batchUpdateInfo(vo);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return R.data(false);
+        }
+        return R.data(true);
+    }
+
+
     /**
      * 删除分盒
      */

+ 143 - 47
blade-service/blade-archive/src/main/java/org/springblade/archive/controller/ArchivesAutoController.java

@@ -18,6 +18,7 @@ package org.springblade.archive.controller;
 
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import io.swagger.annotations.*;
 import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import lombok.AllArgsConstructor;
@@ -33,6 +34,7 @@ import org.apache.http.message.BasicNameValuePair;
 import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
 import org.apache.poi.ss.usermodel.*;
 import org.springblade.archive.dto.ArchiveWarningDTO;
+import org.springblade.archive.dto.AutoOCRDTO;
 import org.springblade.archive.dto.FindAndReplaceDto;
 import org.springblade.archive.dto.SaveApplyDTO;
 import org.springblade.archive.entity.ArchiveConclusion;
@@ -43,12 +45,15 @@ import org.springblade.archive.utils.CallBgrsjk;
 import org.springblade.archive.vo.*;
 import org.springblade.business.entity.ArchiveFile;
 import org.springblade.business.feign.ArchiveFileClient;
+import org.springblade.business.vo.ArchiveFileVO;
 import org.springblade.business.vo.NeiYeLedgerVO1;
 //import org.springblade.common.utils.DeepSeekClient;
 import org.springblade.common.utils.SnowFlakeUtil;
+import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
 import org.springblade.core.secure.BladeUser;
+import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.manager.entity.ArchiveTreeContract;
@@ -279,6 +284,15 @@ public class ArchivesAutoController extends BladeController {
     }
 
 
+	@PostMapping("/atuoOCR")
+	@ApiOperationSupport(order = 5)
+	@ApiOperation(value = "档案自动识别")
+	public R atuoOCR(@RequestBody AutoOCRDTO dto) throws Exception {
+		archivesAutoService.atuoOCR(dto.getIdList());
+		return R.success("正在识别中");
+	}
+
+
 
 
 
@@ -650,7 +664,6 @@ public class ArchivesAutoController extends BladeController {
 	@PostMapping("/reCreateArchiveAuto")
 	@ApiOperationSupport(order = 13)
 	@ApiOperation(value = "重新生成案卷", notes = "传入ids")
-	@Transactional
 	public R reCreateArchiveAuto(@ApiParam(value = "主键集合", required = true) @RequestParam String ids,@ApiParam(value = "合并后的文件题目", required = true)String name,Integer type){
 		if(type==1){
 			//先查出勾选的案卷
@@ -658,59 +671,39 @@ public class ArchivesAutoController extends BladeController {
 			if(archivesAutoList.size()<=1){
 				return R.fail("请选择多个案卷进行合并");
 			}
-			//根据档号后缀排序 拿到第一个
-			ArchivesAuto auto = archivesAutoList.get(0);
-			archivesAutoList.sort(Comparator.comparingInt(a -> {
-				String fileNumber = a.getFileNumber();
-				if (fileNumber == null || fileNumber.isEmpty()) {
-					return Integer.MAX_VALUE;
-				}
-				String[] parts;
-				if (fileNumber.indexOf("_") > 0) {
-					parts = fileNumber.split("_");
-				} else if (fileNumber.indexOf("-") > 0) {
-					parts = fileNumber.split("-");
-				} else {
-					return Integer.MAX_VALUE;
-				}
-				if (parts.length > 0) {
-					try {
-						return Integer.parseInt(parts[parts.length - 1]);
-					} catch (NumberFormatException e) {
-						return Integer.MAX_VALUE;
-					}
-				}
-				return Integer.MAX_VALUE;
-			}));
-			//将除第一个以外的案卷文件archiveId 设置成第一个的id
-			List<ArchiveFile>updateArchiveFileList=new ArrayList<>();
-			//查出所有案卷文件
-			List<ArchiveFile>archiveFileList=new ArrayList<>();
-			List<Long> longList = Func.toLongList(ids);
-			for (Long id : longList) {
-				archiveFileList.addAll(archiveFileClient.getArchiveFileByArchiveIds(id+""));
-			}
-			int i=1;
-			for (ArchiveFile file : archiveFileList) {
-				if (!file.getArchiveId().equals(auto.getId())) {
-					file.setArchiveId(auto.getId());
-				}
-				file.setArchiveSort(i++);
-				updateArchiveFileList.add(file);
-			}
-			archiveFileClient.updateArchiveFile(updateArchiveFileList);
-			auto.setName(name);
-			//删除其他案卷
-			archivesAutoList.remove(auto);
-			archivesAutoService.deleteLogic(archivesAutoList.stream().map(o->o.getId()).collect(Collectors.toList()));
+			checkAndUpdateArchiveAction(archivesAutoList,1);
 			//设置案卷页码和四要素
-			archivesAutoService.reCreateArchiveAuto(auto, archiveFileList);
+			archivesAutoService.reCreateArchiveAuto2(archivesAutoList, ids, name);
 			return R.status(true);
 		}else {
+			List<ArchivesAuto> archivesAutoList=archivesAutoService.listByIds(Func.toLongList(ids));
+			if(archivesAutoList.isEmpty()){
+				return R.fail("选择的案卷不存在");
+			}
+			checkAndUpdateArchiveAction(archivesAutoList, 2);
 			archivesAutoService.reCreateArchiveAuto1(ids);
 			return R.success("正在重组,请稍后查看");
 		}
 	}
+	private void checkAndUpdateArchiveAction(List<ArchivesAuto> archivesAutoList, int type){
+		if (archivesAutoList == null || archivesAutoList.isEmpty()) {
+			return;
+		}
+		List<ArchivesAuto> collect = archivesAutoList.stream().filter(item -> item.getActionType() != null && (item.getActionType() == 1 || item.getActionType() == 2)).collect(Collectors.toList());
+		if (!collect.isEmpty()) {
+			String names = collect.stream().map(ArchivesAuto::getName).collect(Collectors.joining(","));
+			throw  new ServiceException("【" + names + "】案卷正在重组或者并卷,请稍后在进行相关操作");
+		}
+		Set<Long> ids = archivesAutoList.stream().map(ArchivesAuto::getId).collect(Collectors.toSet());
+		Date now = new Date();
+		boolean update = archivesAutoService.update(Wrappers.<ArchivesAuto>lambdaUpdate().set(ArchivesAuto::getActionType, type).set(ArchivesAuto::getUpdateTime, now)
+				// createDept 并卷批次
+				.set(ArchivesAuto::getUpdateUser, AuthUtil.getUserId()).set(ArchivesAuto::getCreateDept, SnowFlakeUtil.getId()).in(ArchivesAuto::getId, ids)
+				.and(item -> item.notIn(ArchivesAuto::getActionType, 1,2).or().isNull(ArchivesAuto::getActionType)));
+		if (!update) {
+			throw new ServiceException("操作失败,案卷可能正在重组或者并卷,请稍后在进行相关操作");
+		}
+	}
 
 	@PostMapping("/creatFileNameFormAI")
 	@ApiOperationSupport(order = 10)
@@ -1221,4 +1214,107 @@ public class ArchivesAutoController extends BladeController {
         return R.status(archivesAutoService.sortRule(projectId,type));
     }
 
+
+	@PostMapping("/insertArchives")
+	@ApiOperationSupport(order = 43)
+	@ApiModelProperty(value = "插入案卷")
+	public R<Boolean> insertArchives(@RequestBody ArchivesAutoInsertVO vo){
+		// 校验
+		if (vo ==  null || vo.getTargetId() == null) {
+			return R.fail("参数错误");
+		}
+		if (vo.getTargetId().equals(vo.getSourceId())) {
+			return R.fail("自己不能选择自己");
+		}
+		String archiveFileIds = vo.getSourceArchiveFileIds();
+		if (StringUtils.isBlank(archiveFileIds)) {
+			return R.fail("请选择要插入的文件");
+		}
+		String[] split = archiveFileIds.split(",");
+		List<String> sourceFileIds = new ArrayList<>();
+		for (String s : split) {
+			if (StringUtils.isNumeric(s)) {
+				sourceFileIds.add(s);
+			}
+		}
+		if (sourceFileIds.isEmpty()) {
+			return R.fail("请选择要插入的文件");
+		}
+		ArchivesAuto target = archivesAutoService.getById(vo.getTargetId());
+		ArchivesAuto source = archivesAutoService.getById(vo.getSourceId());
+		if (target == null || source == null) {
+			return R.fail("插入或选择的案卷不存在");
+		}
+		if (target.getActionType() != null && (target.getActionType() == 1 || target.getActionType() == 2)) {
+			return R.fail("案卷【"+ target.getName() + "进行重组或者并卷,请稍后再试");
+		}
+		if (source.getActionType() != null && (source.getActionType() == 1 || source.getActionType() == 2)) {
+			return R.fail("案卷【"+ source.getName() + "进行重组或者并卷,请稍后再试");
+		}
+		List<ArchiveFile> sourceArchiveFileList = archiveFileClient.getAllArchiveFileByIds(sourceFileIds);
+		if (sourceArchiveFileList == null || sourceArchiveFileList.isEmpty()) {
+			return R.fail("请择要插入的文件不存在");
+		}
+		for (ArchiveFile archiveFile : sourceArchiveFileList) {
+			if (!vo.getSourceId().equals(archiveFile.getArchiveId())) {
+				return R.fail("文件【" + archiveFile.getFileName() + "】不属于【" + source.getName() + "】案卷,请重新选择");
+			}
+		}
+		if ((vo.getSortFileList() ==  null || !vo.getSortFileList().contains(","))) {
+			return R.fail("参数错误");
+		}
+		List<ArchiveFileVO> updateArchiveFileList = new ArrayList<>();
+		String[] split1 = vo.getSortFileList().split(",");
+		List<ArchiveFile> targetArchiveFileList = archiveFileClient.getArchiveFileByArchiveIds(target.getId() + "");
+		targetArchiveFileList.addAll(sourceArchiveFileList);
+		Map<Long, ArchiveFile> targetMap = targetArchiveFileList.stream().collect(Collectors.toMap(ArchiveFile::getId, item -> item, (k1, k2) -> k1));
+		Map<Long, ArchiveFile> map = sourceArchiveFileList.stream().collect(Collectors.toMap(ArchiveFile::getId, item -> item));
+		for (int i = 0; i < split1.length; i++) {
+			if (StringUtils.isNumeric(split1[i])) {
+				ArchiveFile tempFile = targetMap.get(Long.parseLong(split1[i]));
+				if (tempFile != null) {
+					ArchiveFileVO file = new ArchiveFileVO();
+					file.setId(tempFile.getId());
+					file.setSort(tempFile.getSort());
+					file.setArchiveSort(tempFile.getArchiveSort());
+					updateArchiveFileList.add(file);
+					if (map.containsKey(file.getId())) {
+						file.setPageNum("");
+						file.setArchiveId(target.getId());
+						for (int j = i + 1; j < split1.length; j++) {
+							if (StringUtils.isNumeric(split1[j])) {
+								ArchiveFile tempFile1 = targetMap.get(Long.parseLong(split1[j]));
+								if (tempFile1 != null && !map.containsKey(tempFile1.getId())) {
+									file.setNodeId(tempFile1.getNodeId());
+								}
+							}
+						}
+						if (file.getNodeId() == null) {
+							for (int j = i - 1; j >= 0; j--) {
+								if (StringUtils.isNumeric(split1[j])) {
+									ArchiveFile tempFile1 = targetMap.get(Long.parseLong(split1[j]));
+									if (tempFile1 != null && !map.containsKey(tempFile1.getId())) {
+										file.setNodeId(tempFile1.getNodeId());
+									}
+								}
+							}
+						}
+						if (file.getNodeId() == null) {
+							file.setNodeId(target.getNodeId() + "");
+						}
+					}
+				}
+			}
+		}
+		// 修改标识
+		boolean update = archivesAutoService.update(Wrappers.<ArchivesAuto>lambdaUpdate().in(ArchivesAuto::getId, vo.getTargetId(), vo.getSourceId()).set(ArchivesAuto::getActionType, 3).last("and (action_type is null or action_type not in (1,2))"));
+		if (!update) {
+			return R.fail("案卷【" + target.getName() + "】或【" + source.getName() + "】正在被其他用户操作,请稍后再试");
+		}
+		ArchiveFileVO fileVO = new ArchiveFileVO();
+		fileVO.setList(updateArchiveFileList);
+		archiveFileClient.updateArchiveFileSort(fileVO);
+		return R.status(true);
+	}
+
 }

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

@@ -250,7 +250,7 @@
 
     <select id="approvalFile" resultType="org.springblade.archive.vo.ArchivesAutoVO$ApprovalFile">
         <if test="archiveId!=null">
-            select * from u_archive_file where archive_id = #{archiveId} order by sort
+            select * from u_archive_file where archive_id = #{archiveId} order by archive_sort,sort,sort_num,create_time
         </if>
     </select>
 
@@ -375,12 +375,12 @@
                 ORDER BY
                     m.tree_sort,
                     CASE WHEN u.file_number IS NULL THEN 1 ELSE 0 END,
-                    trailing_number
+                    trailing_number,u.create_time
             </when>
             <when test="vo.sortRuleType != null and vo.sortRuleType == 2 and vo.isArchive != null and vo.isArchive != ''">
                 order by
                     CASE WHEN u.file_number IS NULL THEN 1 ELSE 0 END,
-                    trailing_number
+                    trailing_number,u.create_time
             </when>
             <otherwise>
                 order by m.tree_sort,u.auto_file_sort is null ,u.auto_file_sort,u.file_number is null,

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

@@ -46,6 +46,8 @@ public interface TaskSplitMapper extends BaseMapper<TaskSplit> {
 	// 获取分解任务是否存在
 	Integer getSpliteTaskCount(String contractId);
 
+	Integer getSpliteTaskCountByScan(String contractId);
+
 	Integer updateArchiveByContratId(String contractId);
 
 	Integer updateArchiveByIds(@Param("split") List<String> split);

+ 7 - 1
blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/TaskSplitMapper.xml

@@ -19,11 +19,12 @@
         <result column="tool_count" property="toolCount"/>
         <result column="finished" property="finished"/>
         <result column="task_name" property="taskName"/>
+        <result column="data_type" property="dataType"/>
     </resultMap>
 
 
     <select id="selectTaskSplitPage" resultMap="taskSplitResultMap">
-        select * from u_task_split where is_deleted = 0 and contract_id = #{taskSplit.contractId}
+        select * from u_task_split where is_deleted = 0 and contract_id = #{taskSplit.contractId} and data_type=#{taskSplit.dataType}
     </select>
 
     <select id="getArchiveCount" resultType="java.lang.Integer">
@@ -33,6 +34,11 @@
     <select id="getSpliteTaskCount" resultType="java.lang.Integer">
         select count(1) from u_task_split where contract_id = #{contractId} and type=2
     </select>
+
+    <select id="getSpliteTaskCountByScan" resultType="java.lang.Integer">
+        select count(1) from scan_file where contract_id = #{contractId}
+    </select>
+
     <update id="updateArchiveByContratId" >
         update u_archives_auto set split_status = 0 where contract_id = #{contractId} and is_deleted = 0
     </update>

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

@@ -187,4 +187,10 @@ public interface IArchivesAutoService extends BaseService<ArchivesAuto> {
 	void reomoveArchiveAndFile(List<Long> archiveIds);
 
     void reCreateArchiveAuto1(String ids);
+
+	Boolean atuoOCR(List<Long> ids) throws Exception;
+
+	void reCreateArchiveAuto2(List<ArchivesAuto> archivesAutoList, String ids, String name);
+
+
 }

+ 295 - 9
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java

@@ -19,6 +19,9 @@ package org.springblade.archive.service.impl;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import java.lang.reflect.Type;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -36,10 +39,7 @@ import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang.StringUtils;
 
-import org.springblade.archive.dto.ArchiveWarningDTO;
-import org.springblade.archive.dto.FindAndReplaceDto;
-import org.springblade.archive.dto.JiLinQueryDto;
-import org.springblade.archive.dto.SaveApplyDTO;
+import org.springblade.archive.dto.*;
 import org.springblade.archive.entity.*;
 import org.springblade.archive.mapper.ArchiveConclusionMapper;
 import org.springblade.archive.service.*;
@@ -55,6 +55,7 @@ import org.springblade.business.feign.TaskClient;
 import org.springblade.common.utils.CommonUtil;
 import org.springblade.common.utils.DeepSeekClient;
 import org.springblade.common.utils.SnowFlakeUtil;
+import org.springblade.common.utils.SystemUtils;
 import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.mp.base.BaseServiceImpl;
 import org.springblade.core.mp.support.Condition;
@@ -77,9 +78,11 @@ import org.springblade.system.entity.DictBiz;
 import org.springblade.system.feign.IDictBizClient;
 import org.springblade.system.user.entity.User;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.springframework.transaction.annotation.Transactional;
@@ -96,7 +99,9 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.rmi.ServerException;
+import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.List;
 import java.util.concurrent.ExecutorService;
@@ -165,6 +170,8 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 
 	private final ArchivesSortRuleService archivesSortRuleService;
 
+	private final StringRedisTemplate redisTemplate;
+
 
 	@Override
 	public IPage<ArchivesAutoVO> selectArchivesAutoPage(IPage<ArchivesAutoVO> page, ArchivesAutoVO archivesAuto) {
@@ -3015,6 +3022,7 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		List orgIds = Func.toLongList(ids);
 
 		List<String> strIds = new ArrayList<>();
+		List<Long> emptyIds = new ArrayList<>();
 		List<Long> lIds = new ArrayList<>();
 
 		//排除锁定的和单文件案卷这种
@@ -3024,11 +3032,27 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 				continue;
 			}
 			if (ar.getIsAutoFile() != null && ar.getIsAutoFile() == 1) {
+				emptyIds.add(ar.getId());
 				continue;
 			}
 			lIds.add(ar.getId());
 			strIds.add(ar.getId().toString());
 		}
+		if (!emptyIds.isEmpty()) {
+			List<ArchiveFile> files = archiveFileClient.getAllArchiveFileByArchiveIds(emptyIds.stream().map(id -> id + "").collect(Collectors.toList()));
+			if (files == null || files.isEmpty()) {
+				this.deleteLogic(emptyIds);
+			} else {
+				Map<Long, List<ArchiveFile>> groupArchiveFiles = files.stream().collect(Collectors.groupingBy(ArchiveFile::getArchiveId));
+				emptyIds.removeIf(groupArchiveFiles::containsKey);
+				if (!emptyIds.isEmpty()) {
+					this.deleteLogic(emptyIds);
+				}
+			}
+			if (strIds.isEmpty()) {
+				return true;
+			}
+		}
 
 		if (strIds.size() == 0) {
 			return false;
@@ -4820,7 +4844,7 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 			}
 		}
 		if (!updates.isEmpty()) {
-			return this.updateBatchById(archivesAutos);
+			return this.updateBatchById(updates);
 		}
 		return true;
 	}
@@ -5160,14 +5184,97 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 	@Override
 	@Async
 	public void reCreateArchiveAuto1(String ids) {
+		try {
+			// 等待事务提交
+			Thread.sleep(500);
+		} catch (InterruptedException e) {
+			e.printStackTrace();
+		}
 		for (Long id : Func.toLongList(ids)) {
-			//先查出勾选的案卷
-			ArchivesAuto archivesAuto=this.getById(id);
+			try {
+				//先查出勾选的案卷
+				ArchivesAuto archivesAuto=this.getById(id);
+				if (archivesAuto == null || archivesAuto.getActionType() != 2) {
+					continue;
+				}
+				String value = redisTemplate.opsForValue().get("blade:archive:reCreateArchiveAuto1:" + archivesAuto.getId());
+				if (value != null) {
+					continue;
+				}
+				redisTemplate.opsForValue().set("blade:archive:reCreateArchiveAuto1:" + archivesAuto.getId(), "", 60 * 60 * 1000, TimeUnit.MILLISECONDS);
+				//查出所有案卷文件
+				List<ArchiveFile>archiveFileList=archiveFileClient.getArchiveFileByArchiveIds(id+"");
+				//设置案卷页码和四要素
+				if (archiveFileList != null && !archiveFileList.isEmpty()) {
+					archivesAuto.setActionType(null);
+					this.reCreateArchiveAuto(archivesAuto, archiveFileList);
+				}
+				this.update(Wrappers.<ArchivesAuto>lambdaUpdate().set(ArchivesAuto::getActionType, 0).eq(ArchivesAuto::getId, id));
+			} catch (Exception e) {
+				log.error("案卷重组失败," + "案卷ID:" + id, e);
+				this.update(Wrappers.<ArchivesAuto>lambdaUpdate().set(ArchivesAuto::getActionType, -2).eq(ArchivesAuto::getId, id));
+			} finally {
+				redisTemplate.delete("blade:archive:reCreateArchiveAuto1:" + id);
+			}
+		}
+	}
+	@Override
+	@Async
+	public void reCreateArchiveAuto2(List<ArchivesAuto> archivesAutoList, String ids, String name) {
+		try {
+			//根据档号后缀排序 拿到第一个
+			ArchivesAuto archivesAuto = archivesAutoList.get(0);
+			archivesAutoList.sort(Comparator.comparingInt(a -> {
+				String fileNumber = a.getFileNumber();
+				if (fileNumber == null || fileNumber.isEmpty()) {
+					return Integer.MAX_VALUE;
+				}
+				String[] parts;
+				if (fileNumber.indexOf("_") > 0) {
+					parts = fileNumber.split("_");
+				} else if (fileNumber.indexOf("-") > 0) {
+					parts = fileNumber.split("-");
+				} else {
+					return Integer.MAX_VALUE;
+				}
+				if (parts.length > 0) {
+					try {
+						return Integer.parseInt(parts[parts.length - 1]);
+					} catch (NumberFormatException e) {
+						return Integer.MAX_VALUE;
+					}
+				}
+				return Integer.MAX_VALUE;
+			}));
+			//将除第一个以外的案卷文件archiveId 设置成第一个的id
+			List<ArchiveFile> waitArchiveFiles = new ArrayList<>();
 			//查出所有案卷文件
-			List<ArchiveFile>archiveFileList=archiveFileClient.getArchiveFileByArchiveIds(id+"");
-			//设置案卷页码和四要素
+			List<ArchiveFile>archiveFileList=new ArrayList<>();
+			List<Long> longList = Func.toLongList(ids);
+			for (Long id : longList) {
+				archiveFileList.addAll(archiveFileClient.getArchiveFileByArchiveIds(id+""));
+			}
+			int i=1;
+			for (ArchiveFile file : archiveFileList) {
+				if (!file.getArchiveId().equals(archivesAuto.getId())) {
+					file.setArchiveId(archivesAuto.getId());
+				}
+				file.setArchiveSort(i++);
+				waitArchiveFiles.add(file);
+			}
+			archiveFileClient.updateArchiveFile(waitArchiveFiles);
+			archivesAuto.setName(name);
+			archivesAuto.setActionType(null);
+			//删除其他案卷
+			archivesAutoList.remove(archivesAuto);
+			this.deleteLogic(archivesAutoList.stream().map(o->o.getId()).collect(Collectors.toList()));
 			this.reCreateArchiveAuto(archivesAuto, archiveFileList);
+			this.update(Wrappers.<ArchivesAuto>lambdaUpdate().set(ArchivesAuto::getActionType, 0).in(ArchivesAuto::getId, longList));
+		} catch (Exception e) {
+			log.error("案卷并卷失败," + "案卷Ids:" + ids, e);
+			this.update(Wrappers.<ArchivesAuto>lambdaUpdate().set(ArchivesAuto::getActionType, -1).in(ArchivesAuto::getId, Func.toLongList(ids)));
 		}
+
 	}
 
 	/**
@@ -5253,6 +5360,185 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 				.mapToInt(file -> file.getFilePage() != null ? file.getFilePage() : 0)
 				.sum();
 	}
+
+	@Override
+	@Async
+	public Boolean atuoOCR(List<Long> idsList) throws Exception {
+		String url="/mnt/sdc/AutoPdf/";
+		//String url="D:\\AutoPdf\\";
+		//List<Long> idsList=Func.toLongList(ids);
+		List<ArchivesAuto> archivesAutoList = this.list(new LambdaQueryWrapper<ArchivesAuto>().in(ArchivesAuto::getId, idsList));
+		for (ArchivesAuto auto : archivesAutoList) {
+			if(auto.getOutUrl()==null||auto.getOutUrl().isEmpty()){
+				continue;
+			}
+			String sql=" select * from u_archive_file where is_deleted = 0 and archive_id="+auto.getId();
+			List<ArchiveFile> archiveFiles = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(ArchiveFile.class));
+			if(archiveFiles.isEmpty()){
+				continue;
+			}
+			String fileUrl=StringUtils.isNotEmpty(archiveFiles.get(0).getPdfFileUrl())?archiveFiles.get(0).getPdfFileUrl():StringUtils.isNotEmpty(archiveFiles.get(0).getFileUrl())?archiveFiles.get(0).getFileUrl():null;
+			if(fileUrl==null){
+				continue;
+			}
+			String filePath=url+auto.getName()+".pdf";
+			System.out.println("开始保存:"+fileUrl);
+			Boolean b = FileUtils.saveInputStreamByUrl(fileUrl, filePath);
+			System.out.println("保存完成:"+b);
+			try {
+				if(b){
+					System.out.println("开始识别:"+filePath);
+					List<String> list = extractTextFromPDF(filePath);
+					System.out.println("识别完成:"+list);
+					if(!list.isEmpty()){
+						StringBuilder fileName=new StringBuilder();
+						for (String result : list) {
+							if(result.contains("档号")){
+								String fileNum=result.replace("档号","").replace(":","").replace(":","");
+								auto.setFileNumber(fileNum);
+							}else if(result.contains("立卷单位")){
+								String unit=result.replace("立卷单位","").replace(":","").replace(":","");
+								auto.setUnit(unit);
+							} else if (result.contains("起止日期")) {
+								String time=result.replace("起止日期","").replace(":","").replace(":","");
+								if(result.contains("~")){
+									LocalDateTime[] localDateTimes = convertDateRange(time, "~");
+									auto.setStartDate(localDateTimes[0]);
+									auto.setEndDate(localDateTimes[1]);
+								} else if (result.contains("-")) {
+									LocalDateTime[] localDateTimes = convertDateRange(time, "-");
+									auto.setStartDate(localDateTimes[0]);
+									auto.setEndDate(localDateTimes[1]);
+								}
+							} else if (result.contains("保管期限")||result.contains("保管限期")) {
+								String storageTime=result.replace("保管期限","").replace("保管限期","").replace(":","").replace(":","");
+								auto.setStorageTime(storageTime);
+							} else if (result.contains("密1")||result.contains("密级")) {
+								String secretLevel=result.replace("密1","").replace("密级","");
+								auto.setSecretLevel(secretLevel);
+							} else {
+								fileName.append(result);
+							}
+						}
+						auto.setName(fileName.toString());
+					}
+				}
+			}catch (Exception e){
+
+			}finally {
+				FileUtils.removeFile(filePath);
+			}
+		}
+		this.updateBatchById(archivesAutoList);
+		return true;
+	}
+
+	public static LocalDateTime[] convertDateRange(String dateRange,String split) {
+		String[] dates = dateRange.split(split);
+
+		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
+
+		LocalDate startLocalDate = LocalDate.parse(dates[0], formatter);
+		LocalDate endLocalDate = LocalDate.parse(dates[1], formatter);
+
+		LocalDateTime startDateTime = startLocalDate.atStartOfDay(); // 00:00:00
+		LocalDateTime endDateTime = endLocalDate.atStartOfDay();; // 00:00:00
+
+		return new LocalDateTime[]{startDateTime, endDateTime};
+	}
+
+	public List<String> extractTextFromPDF(String pdfFilePath) throws IOException, InterruptedException {
+		//String PYTHON_SCRIPT_PATH = "C:\\Users\\hc01\\AppData\\Local\\Programs\\Python\\Python310\\Python\\pdfTextExtractorWindows.py";
+		//String PYTHON_INTERPRETER = "C:\\Users\\hc01\\AppData\\Local\\Programs\\Python\\Python310\\python.exe";
+		System.out.println("进入识别1");
+		String PYTHON_SCRIPT_PATH = "/www/wwwlogs/python/pdfTextExtractorWindows.py";
+		String PYTHON_INTERPRETER = "python3";
+		String[] command = {
+				PYTHON_INTERPRETER,
+				PYTHON_SCRIPT_PATH,
+				pdfFilePath
+		};
+
+		Process process = new ProcessBuilder(command)
+				.redirectErrorStream(true)
+				.start();
+		System.out.println("进入识别2");
+		// 读取Python输出
+		StringBuilder output = new StringBuilder();
+		try (InputStream inputStream = process.getInputStream();
+			 BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"))) {
+
+			String line;
+			while ((line = reader.readLine()) != null) {
+				output.append(line);
+			}
+		}
+		System.out.println("进入识别3");
+		int exitCode = process.waitFor();
+		if (exitCode != 0) {
+			System.out.println("进入识别4");
+			throw new RuntimeException("Python脚本执行失败,退出码: " + exitCode + ", 输出: " + output.toString());
+		}
+
+		// -------------------------- 关键修改:提取纯JSON部分 --------------------------
+		String rawOutput = output.toString();
+		// 找到JSON的起始位置(第一个'{')和结束位置(最后一个'}')
+		int jsonStart = rawOutput.indexOf('{');
+		int jsonEnd = rawOutput.lastIndexOf('}');
+		System.out.println("进入识别5");
+		if (jsonStart == -1 || jsonEnd == -1 || jsonStart >= jsonEnd) {
+			System.out.println("进入识别6");
+			throw new RuntimeException("无法提取有效的JSON结果,原始输出: " + rawOutput);
+		}
+		// 截取纯JSON字符串
+		String jsonStr = rawOutput.substring(jsonStart, jsonEnd + 1);
+		System.out.println("进入识别7");
+		// 解析清理后的JSON
+		Gson gson = new Gson();
+		Type type = new TypeToken<Map<String, Object>>(){}.getType();
+		Map<String, Object> resultMap = gson.fromJson(jsonStr, type);
+
+		if (!"success".equals(resultMap.get("status"))) {
+			System.out.println("进入识别8");
+			String message = (String) resultMap.get("message");
+			throw new RuntimeException("处理PDF失败: " + (message != null ? message : "未知错误"));
+		}
+		System.out.println("进入识别9");
+		Type listType = new TypeToken<List<String>>(){}.getType();
+		return gson.fromJson(gson.toJson(resultMap.get("lines")), listType);
+	}
+
+	@Scheduled(fixedDelay = 1000 * 60 * 10)
+	public void reCreateArchiveAuto() {
+		if (SystemUtils.isWindows() || SystemUtils.isMacOs()) {
+			return;
+		}
+		List<ArchivesAuto> archivesAutoList = this.list(Wrappers.<ArchivesAuto>lambdaQuery().eq(ArchivesAuto::getActionType, 2));
+		if (archivesAutoList == null || archivesAutoList.isEmpty()) {
+			return;
+		}
+		archivesAutoList.forEach(archivesAuto -> {
+			String value = redisTemplate.opsForValue().get("blade:archive:reCreateArchiveAuto1:" + archivesAuto.getId());
+			if (value == null) {
+				try {
+					redisTemplate.opsForValue().set("blade:archive:reCreateArchiveAuto1:" + archivesAuto.getId(), "", 60 * 60 * 1000, TimeUnit.MILLISECONDS);
+					//查出所有案卷文件
+					List<ArchiveFile>archiveFileList=archiveFileClient.getArchiveFileByArchiveIds(archivesAuto.getId()+"");
+					//设置案卷页码和四要素
+					if (archiveFileList != null && !archiveFileList.isEmpty()) {
+						archivesAuto.setActionType(null);
+						this.reCreateArchiveAuto(archivesAuto, archiveFileList);
+					}
+					this.update(Wrappers.<ArchivesAuto>lambdaUpdate().set(ArchivesAuto::getActionType, 0).eq(ArchivesAuto::getId, archivesAuto.getId()));
+				} catch (Exception e) {
+					log.error("案卷重组失败," + "案卷ID:" + archivesAuto.getId(), e);
+					this.update(Wrappers.<ArchivesAuto>lambdaUpdate().set(ArchivesAuto::getActionType, -2).eq(ArchivesAuto::getId, archivesAuto.getId()));
+				} finally {
+					redisTemplate.delete("blade:archive:reCreateArchiveAuto1:" + archivesAuto.getId());
+				}
+			}
+		});
+	}
 }
 
 

+ 26 - 5
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/TaskSplitServiceImpl.java

@@ -62,6 +62,12 @@ public class TaskSplitServiceImpl extends BaseServiceImpl<TaskSplitMapper, TaskS
 		Map<String,Object> data = new HashMap<>();
 		String contractId = taskSplit.getContractId();
 		String splitIds = taskSplit.getIds();
+		int dataType = taskSplit.getDataType();
+
+		if(dataType!=2){
+			taskSplit.setDataType(1);
+		}
+
 		if (contractId=="" || contractId==null || contractId.length()==0 || Func.isEmpty(contractId)){
 			return R.fail("合同段Id为空");
 		}
@@ -69,7 +75,14 @@ public class TaskSplitServiceImpl extends BaseServiceImpl<TaskSplitMapper, TaskS
 		if (splitIds=="" || splitIds==null || splitIds.length()==0 || Func.isEmpty(splitIds)){ // 代表整个合同解析
 			taskSplit.setType(2);
 			// 查询整个合同段下的所有文件
-			Integer spliteTaskCount =baseMapper.getSpliteTaskCount(contractId);
+
+			Integer spliteTaskCount = 0;
+			if(dataType==2){ //
+				spliteTaskCount = baseMapper.getSpliteTaskCountByScan(contractId);
+			}else {
+				spliteTaskCount = baseMapper.getSpliteTaskCount(contractId);
+			}
+
 			if(spliteTaskCount>=1){
 				return R.fail("该合同已经添加任务,无需重复操作");
 			}
@@ -81,8 +94,11 @@ public class TaskSplitServiceImpl extends BaseServiceImpl<TaskSplitMapper, TaskS
 			Integer archiveCount = baseMapper.getArchiveCount(contractId);
 			taskSplit.setToolCount(archiveCount);
 			taskSplit.setFinished(0);
-
-			taskSplit.setTaskName("整个合同段 "+archiveCount+" 条的分解任务");
+            if(dataType==2) { //
+                taskSplit.setTaskName("整个合同段 " + archiveCount + " 条的识别任务");
+            }else {
+                taskSplit.setTaskName("整个合同段 " + archiveCount + " 条的分解任务");
+            }
 			data.put("fileCount",archiveCount);
 			data.put("taskTime",i);
 			// 修改整个合同任务状态为 未分解
@@ -103,8 +119,13 @@ public class TaskSplitServiceImpl extends BaseServiceImpl<TaskSplitMapper, TaskS
 			data.put("taskTime",i);
 			LocalDateTime now = LocalDateTime.now();
 			DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss");
-			String formattedDateTime = now.format(formatter)+"_"+split.size()+"条分解任务";
-			taskSplit.setTaskName(formattedDateTime);
+            if(dataType==2) { //
+                String formattedDateTime = now.format(formatter)+"_"+split.size()+"条识别任务";
+                taskSplit.setTaskName(formattedDateTime);
+            }else {
+                String formattedDateTime = now.format(formatter)+"_"+split.size()+"条分解任务";
+                taskSplit.setTaskName(formattedDateTime);
+            }
 			baseMapper.updateArchiveByIds(split);
 		}
 

+ 31 - 0
blade-service/blade-archive/src/main/java/org/springblade/archive/utils/FileUtils.java

@@ -897,4 +897,35 @@ public class FileUtils {
         return "";
     }
 
+    // 获取OSS文件流并且保存到本地
+    public static Boolean saveInputStreamByUrl(String fileUrl,String filePath) throws Exception {
+        InputStream fileInputStream = CommonUtil.getOSSInputStream(fileUrl);
+        if(fileInputStream==null){
+            return false;
+        }
+        try (FileOutputStream outputStream = new FileOutputStream(filePath)) {
+            byte[] buffer = new byte[1024];
+            int length;
+
+            while ((length = fileInputStream.read(buffer)) > 0) {
+                outputStream.write(buffer, 0, length);
+            }
+            return true;
+        } catch (IOException e) {
+            e.printStackTrace();
+            System.err.println("文件下载失败: " + e.getMessage());
+            return false;
+        }
+
+    }
+
+    public static Boolean removeFile(String filePath){
+        File file=new File(filePath);
+        if(file.exists()){
+           return file.delete();
+        }
+        return true;
+    }
+
+
 }

+ 491 - 6
blade-service/blade-business/src/main/java/org/springblade/business/controller/FixedFlowController.java

@@ -1,7 +1,9 @@
 package org.springblade.business.controller;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -13,20 +15,30 @@ import org.springblade.business.entity.FixedFlowLink;
 import org.springblade.business.entity.Task;
 import org.springblade.business.service.IFixedFlowLinkService;
 import org.springblade.business.service.IFixedFlowService;
+import org.springblade.business.service.impl.TaskServiceImpl;
 import org.springblade.business.vo.FixedFlowVO;
 import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.boot.ctrl.BladeController;
+import org.springblade.core.log.exception.ServiceException;
+import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.api.R;
+import org.springblade.core.tool.utils.BeanUtil;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.core.tool.utils.ObjectUtil;
 import org.springblade.manager.dto.SaveUserInfoByProjectDTO;
+import org.springblade.manager.entity.ProjectInfo;
 import org.springblade.manager.entity.SignPfxFile;
 import org.springblade.manager.feign.ContractClient;
 import org.springblade.manager.feign.ProjectAssignmentUserClient;
+import org.springblade.manager.feign.ProjectClient;
+import org.springblade.manager.feign.SignPfxClient;
 import org.springblade.manager.vo.RoleSignPfxUserVO;
 import org.springblade.manager.vo.RoleSignPfxUserVO1;
 import org.springblade.manager.vo.RoleSignPfxUserVO2;
 import org.springblade.manager.vo.RoleSignPfxUserVO3;
+import org.springblade.meter.dto.PageFixedFlowDTO;
+import org.springblade.meter.dto.SaveFixedFlowDTO;
+import org.springblade.meter.dto.UpdateFixedFlowDTO;
 import org.springblade.system.feign.ISysClient;
 import org.springblade.system.user.entity.User;
 import org.springblade.system.user.feign.IUserClient;
@@ -34,12 +46,13 @@ import org.springblade.system.vo.RoleVO;
 import org.springframework.beans.BeanUtils;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.transaction.annotation.Isolation;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
 import javax.validation.Valid;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
+import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * 控制器
@@ -67,14 +80,16 @@ public class FixedFlowController extends BladeController {
 
     private final JdbcTemplate jdbcTemplate;
 
+    private final ProjectClient projectClient;
+
+    private final TaskServiceImpl taskServiceImpl;
     /**
      * 获取系统所有角色划分
      */
     @GetMapping("/queryAllRoleList")
     @ApiOperationSupport(order = 9)
     @ApiOperation(value = "获取系统所有角色划分")
-    public R<List<RoleSignPfxUserVO>> queryAllRoleList(@RequestParam String contractId) {
-        RoleSignPfxUserVO1 vo1 = new RoleSignPfxUserVO1();
+    public R<List<RoleSignPfxUserVO>> queryAllRoleList(@RequestParam String contractId, @RequestParam(required = false, defaultValue = "0") Integer  type) {
         //获取当前系统配置的角色划分
         List<RoleVO> roleVOS = this.sysClient.search().getData();
         //获取项目人员
@@ -95,6 +110,15 @@ public class FixedFlowController extends BladeController {
         //返回结果
         List<RoleSignPfxUserVO> result = new ArrayList<>();
         for (RoleVO vo : roleVOS) {
+            if (type != null && type == 1) {
+                // 除“超级管理员”外,其余只展示“业主方”、“监理方”、“施工方”。“超级管理员”只有用户角色为“超级管理员”时才展示。其余角色均不展示;
+                if (vo.getRoleName() == null || (!vo.getRoleName().contains("管理员") && !vo.getRoleName().contains("业主方") && !vo.getRoleName().contains("施工方") && !vo.getRoleName().contains("监理方"))) {
+                    continue;
+                }
+                if (!"administrator".equals(AuthUtil.getUserRole()) && vo.getRoleName() != null && "administrator".equals(vo.getRoleAlias())) {
+                    continue;
+                }
+            }
             //设置实体
             RoleSignPfxUserVO pfxUserVo = new RoleSignPfxUserVO();
             pfxUserVo.setRoleId(vo.getId());
@@ -129,6 +153,9 @@ public class FixedFlowController extends BladeController {
                         }
                     }
                     //设置子集
+                    if (childPfxUserVo.getSignPfxFileList() ==  null || childPfxUserVo.getSignPfxFileList().isEmpty()) {
+                        continue;
+                    }
                     pfxUserVo.getChildRoleList().add(childPfxUserVo);
                     pfxUserVo.getSignPfxFileList().addAll(childPfxUserVo.getSignPfxFileList());
                 }
@@ -174,7 +201,28 @@ public class FixedFlowController extends BladeController {
         if (vo.getCurrent() == null || vo.getSize() == null) {
             return R.data(-1, null, "缺少size或current参数");
         }
-        return R.data(this.fixedFlowService.selectFixedFlowPage(vo));
+        IPage<FixedFlowVO> page = this.fixedFlowService.selectFixedFlowPage(vo);
+        List<FixedFlowVO> records = page.getRecords();
+        if (records != null && !records.isEmpty()) {
+            Map<Boolean, List<FixedFlowVO>> groupMap = records.stream().collect(Collectors.groupingBy(record -> record.getFixedFlowName() != null && record.getFixedFlowName().contains("_") && record.getSort() == null));
+            List<FixedFlowVO> copyFixedFlowVOS = groupMap.get(true);
+            List<FixedFlowVO> fixedFlowVOS = groupMap.get(false);
+            if (copyFixedFlowVOS ==  null || copyFixedFlowVOS.isEmpty() || fixedFlowVOS ==  null || fixedFlowVOS.isEmpty()) {
+                return R.data(page);
+            }
+            Map<String, List<FixedFlowVO>> nameMap = copyFixedFlowVOS.stream().collect(Collectors.groupingBy(record -> record.getFixedFlowName().split("_")[0]));
+            List<FixedFlowVO> newData = new ArrayList<>();
+            for (FixedFlowVO flowVO : fixedFlowVOS) {
+                newData.add(flowVO);
+                List<FixedFlowVO> flowVOS = nameMap.get(flowVO.getFixedFlowName());
+                if (flowVOS != null && !flowVOS.isEmpty()) {
+                    flowVOS.sort(Comparator.comparing(FixedFlow::getFixedFlowName));
+                    newData.addAll(flowVOS);
+                }
+            }
+            page.setRecords(newData);
+        }
+        return R.data(page);
     }
 
     /**
@@ -282,5 +330,442 @@ public class FixedFlowController extends BladeController {
         return R.status(false);
     }
 
+    /**
+     * 复制
+     */
+    @PostMapping("/copy")
+    @ApiOperationSupport(order = 6)
+    @ApiOperation(value = "复制", notes = "传入fixedFlow id")
+    @Transactional(rollbackFor = Exception.class)
+    public R<String> copy(String ids) {
+        if (StringUtils.isBlank(ids)) {
+            return R.fail("请选择要复制的流程");
+        }
+        List<Long> idList = Func.toLongList(ids);
+        List<FixedFlow> fixedFlowList = this.fixedFlowService.listByIds(idList);
+        if (fixedFlowList.isEmpty()) {
+            return R.fail("选择的流程不存在");
+        }
+        List<FixedFlowLink> fixedFlowLinkList = this.fixedFlowLinkService.list(Wrappers.<FixedFlowLink>lambdaQuery().in(FixedFlowLink::getFixedFlowId, idList));
+        Map<Long, List<FixedFlowLink>> linkMap = fixedFlowLinkList.stream().collect(Collectors.groupingBy(FixedFlowLink::getFixedFlowId));
+        List<FixedFlowLink> newFixedFolwLinkList = new ArrayList<>();
+        Map<String, Long> nameCountMap = new HashMap<>();
+        StringBuilder sb = new StringBuilder();
+        fixedFlowList.forEach(fixedFlow -> {
+            //生成主表主键
+            long fixedFlowId = SnowFlakeUtil.getId();
+            sb.append(fixedFlowId).append( ",");
+            List<FixedFlowLink> sourceFixedFolwLinkList = linkMap.get(fixedFlow.getId());
+            if (sourceFixedFolwLinkList != null && !sourceFixedFolwLinkList.isEmpty()) {
+                for (FixedFlowLink fixedFlowLink : sourceFixedFolwLinkList) {
+                    FixedFlowLink newLink = new FixedFlowLink();
+                    BeanUtils.copyProperties(fixedFlowLink, newLink);
+                    newLink.setId(SnowFlakeUtil.getId());
+                    newLink.setFixedFlowId(fixedFlowId);
+                    newLink.setCreateUser(AuthUtil.getUserId());
+                    newLink.setCreateTime(new Date());
+                    newFixedFolwLinkList.add(newLink);
+                }
+            }
+            Long number = nameCountMap.get(fixedFlow.getFixedFlowName());
+            if (number == null) {
+                List<FixedFlow> list = this.fixedFlowService.list(Wrappers.<FixedFlow>lambdaQuery().select(FixedFlow::getFixedFlowName).likeRight(FixedFlow::getFixedFlowName, fixedFlow.getFixedFlowName())
+                        .eq(FixedFlow::getContractId, fixedFlow.getContractId()).ne(FixedFlow::getId, fixedFlow.getId()));
+                if (list.isEmpty()) {
+                    number = 0L;
+                } else {
+                    int length = fixedFlow.getFixedFlowName().split("_").length;
+                    number = list.stream().filter(item -> item.getFixedFlowName().split("_").length == length + 1).count();
+                }
+            }
+            nameCountMap.put(fixedFlow.getFixedFlowName(), number + 1);
+            fixedFlow.setId(fixedFlowId);
+            fixedFlow.setFixedFlowName(fixedFlow.getFixedFlowName() + "_" + (number + 1));
+            fixedFlow.setCreateTime(new Date());
+            fixedFlow.setCreateDept(fixedFlow.getId());
+            fixedFlow.setUpdateTime(new Date());
+            fixedFlow.setCreateUser(AuthUtil.getUserId());
+        });
+        boolean flow = this.fixedFlowService.saveBatch(fixedFlowList);
+        if (flow && !newFixedFolwLinkList.isEmpty()) {
+            flow = this.fixedFlowLinkService.saveBatch(newFixedFolwLinkList);
+        }
+        if (flow) {
+            return R.data(sb.deleteCharAt(sb.length() - 1).toString());
+        }
+        return R.status(false);
+    }
+
+    @PostMapping("/saveFixedFlow")
+    @ApiOperationSupport(order = 7)
+    @ApiOperation(value = "新增任务流程", notes = "传入dto")
+    public R<Object> saveFixedFlow(@RequestBody SaveFixedFlowDTO dto) {
+        if (ObjectUtil.isEmpty(dto.getFixedBranchList())) {
+            return R.fail("请选择任务流程人员");
+        }
+        if (ObjectUtil.isNotEmpty(dto.getFixedName()) && ObjectUtil.isNotEmpty(dto.getProjectId()) && ObjectUtil.isNotEmpty(dto.getContractId())) {
+            ProjectInfo projectInfo = projectClient.getById(dto.getProjectId() + "");
+            if (projectInfo == null) {
+                return R.fail("暂未找到项目信息,请稍后再试");
+            }
+            List<String> userIds = dto.getFixedBranchList().stream().map(SaveFixedFlowDTO.FixedBranch::getUserIds).collect(Collectors.toList());
+            List<User> users = jdbcTemplate.query("select id,name,acc_code,real_name from blade_user where is_deleted = 0 and id in (" + StringUtils.join(userIds, ",") + ")", new BeanPropertyRowMapper<>(User.class));
+            Map<Long, User> userMap = users.stream().collect(Collectors.toMap(User::getId, item -> item));
+            if (ObjectUtil.isEmpty( users)) {
+                return R.fail("请选择任务流程人员");
+            }
+            if (Objects.equals(projectInfo.getRemarkType(), 1)) {
+                //安心签,校验证书 检查签字证书信息
+                Set<String> notCertificateUserInfoSet = new HashSet<>();
+                //获取用户的证书信息
+                String ids = users.stream().map(user -> user.getId() + "").collect(Collectors.joining(","));
+                List<SignPfxFile> signPfxFiles = jdbcTemplate.query("select * from m_sign_pfx_file where is_register = 1 and certificate_user_id in ( " + ids + " )", new BeanPropertyRowMapper<>(SignPfxFile.class));
+                Map<String, List<SignPfxFile>> collect = signPfxFiles.stream().collect(Collectors.groupingBy(signPfxFile -> signPfxFile.getCertificateUserId() + ""));
+                for (String userId : userIds) {
+                    String[] split = userId.split(",");
+                    for (String s : split) {
+                        if (StringUtils.isNumeric( s)) {
+                            List<SignPfxFile> userPfxList = collect.get(s);
+                            if (userPfxList == null || userPfxList.isEmpty()) {
+                                notCertificateUserInfoSet.add(s);
+                            }
+                        }
+                    }
+                }
+                if (!notCertificateUserInfoSet.isEmpty()) {
+                    List<String> names = new ArrayList<>();
+                    for (String userId : notCertificateUserInfoSet) {
+                        User user = userMap.get(Long.parseLong(userId));
+                        if (user != null && user.getName() != null && !user.getName().isEmpty()) {
+                            names.add(user.getName());
+                        }
+                    }
+                    throw new ServiceException("未获取到用户【" + StringUtils.join(names, "、") + "】的签字证书信息");
+                }
+            } else {
+                // 东方中讯,校验用户 accCode
+                List<String> names = new ArrayList<>();
+                for (User user : users) {
+                    if (user.getAccCode() == null || user.getAccCode().isEmpty() || user.getAccCode().equals("null")) {
+                        names.add(user.getName());
+                    }
+                }
+                if (!names.isEmpty()) {
+                    throw new ServiceException("未获取到用户【" + StringUtils.join(names, "、") + "】的签字证书信息");
+                }
+            }
+            Long fixedFlowId = SnowFlakeUtil.getId();
+            FixedFlow fixedFlow = new FixedFlow();
+            fixedFlow.setId(fixedFlowId);
+            fixedFlow.setFixedFlowName(dto.getFixedName());
+            fixedFlow.setProjectId(dto.getProjectId());
+            fixedFlow.setContractId(dto.getContractId());
+            fixedFlow.setStatus(1);
+            fixedFlow.setIsMeter(0);
+            fixedFlow.setSort(0);
+            fixedFlow.setCreateTime(new Date());
+            boolean save = fixedFlowService.save(fixedFlow);
+            if (save) {
+                int userSort = 0;
+                for (int i = 0; i < dto.getFixedBranchList().size(); i++) {
+                    SaveFixedFlowDTO.FixedBranch fixedBranch = dto.getFixedBranchList().get(i);
+                    if(i>0){
+                        userSort += Func.toLongList(dto.getFixedBranchList().get(i-1).getUserIds()).size();
+                    }
+                    List<FixedFlowLink> saveList = new ArrayList<>();
+                    if (fixedBranch.getUserIds() ==  null) {
+                        continue;
+                    }
+                    for (String userId : fixedBranch.getUserIds().split(",")) {
+                        User user = userMap.get(Long.parseLong(userId));
+                        if (user == null) {
+                            continue;
+                        }
+                        FixedFlowLink fixedFlowLink = new FixedFlowLink();
+                        fixedFlowLink.setFixedFlowId(fixedFlowId);
+                        fixedFlowLink.setFixedFlowLink(fixedBranch.getName() == null ? dto.getFixedName() : fixedBranch.getName());
+                        fixedFlowLink.setFixedFlowLinkType(projectInfo.getApprovalType());
+                        fixedFlowLink.setFixedFlowLinkUser(Long.parseLong(userId));
+                        fixedFlowLink.setFixedFlowLinkUserName(user.getRealName());
+                        fixedFlowLink.setFixedFlowLinkSort(i+1);
+                        fixedFlowLink.setProjectId(dto.getProjectId());
+                        fixedFlowLink.setContractId(dto.getContractId());
+                        fixedFlowLink.setFixedFlowBranchSort(userSort+=1);
+                        fixedFlowLink.setFlowTaskType(fixedBranch.getFlowTaskType());
+                        saveList.add(fixedFlowLink);
+                    }
+                    if (!saveList.isEmpty()) {
+                        fixedFlowLinkService.saveBatch(saveList);
+                    }
+                }
+                return R.success("操作成功");
+            }
+        }
+        return R.fail("操作失败");
+    }
+
+    /**
+     * 自定义分页
+     */
+    @GetMapping("/getFixedFlowPage")
+    @ApiOperationSupport(order = 2)
+    @ApiOperation(value = "分页", notes = "传入fixedFlow")
+    public R<Page<FixedFlowVO>> getFixedFlowPage(PageFixedFlowDTO dto) {
+        if (dto.getCurrent() == null || dto.getSize() == null) {
+            return R.data(-1, null, "缺少size或current参数");
+        }
+
+        Page<FixedFlow> page = new Page<>(dto.getCurrent(), dto.getSize());
+        IPage<FixedFlow> fixedFlowsPage = fixedFlowService.getBaseMapper().selectPage(page,
+                Wrappers.<FixedFlow>lambdaQuery()
+                        .eq(FixedFlow::getContractId, dto.getContractId())
+                        .eq(FixedFlow::getProjectId, dto.getProjectId()).last(" and (is_meter is null or is_meter != 1) order by sort, fixed_flow_name, create_time desc"));
+        List<FixedFlow> fixedFlows = fixedFlowsPage.getRecords();
+        List<Long> collect = fixedFlows.stream().map(FixedFlow::getId).collect(Collectors.toList());
+        if (!collect.isEmpty()) {
+            List<FixedFlowLink> fixedFlowLinkList = fixedFlowLinkService.getBaseMapper().selectList(
+                    Wrappers.<FixedFlowLink>lambdaQuery()
+                            .in(FixedFlowLink::getFixedFlowId, collect)
+                            .orderByAsc(FixedFlowLink::getFixedFlowBranchSort)
+                            .orderByAsc(FixedFlowLink::getFixedFlowLinkSort)
+            );
+            Map<Long, List<FixedFlowLink>> group = fixedFlowLinkList.stream()
+                    .collect(Collectors.groupingBy(FixedFlowLink::getFixedFlowId,
+                            LinkedHashMap::new,
+                            Collectors.toList()));
+            //获取当前任务中所有的流程,并且去重,如果该流程已经存在,那么则不允许编辑和删除
+            List<Long> ids = taskServiceImpl.list(new LambdaQueryWrapper<Task>()
+                    .select(Task::getFixedFlowId)
+                    .eq(Task::getContractId, dto.getContractId())
+                    .isNotNull(Task::getFixedFlowId)
+                    .groupBy(Task::getFixedFlowId)).stream().map(Task::getFixedFlowId).collect(Collectors.toList());
+            List<FixedFlowVO> fixedFlowVOList = new ArrayList<>();
+            for (FixedFlow fixedFlow : fixedFlows) {
+                List<FixedFlowLink> one = group.getOrDefault(fixedFlow.getId(), null);
+                FixedFlowVO vo = new FixedFlowVO();
+                BeanUtil.copyProperties(fixedFlow, vo);
+                fixedFlowVOList.add(vo);
+                vo.setFixedFlowLinkList( one);
+                if (one != null) {
+                    /** 上面方法会去除同名流程*/
+                    for (FixedFlowLink link : one) {
+                        if (link.getFixedFlowBranchSort() == null ) {
+                            link.setFixedFlowBranchSort(link.getFixedFlowLinkSort());
+                            link.setFixedFlowLinkSort(1);
+                        }
+                        if (link.getFixedFlowLink() == null || link.getFixedFlowLink().isEmpty()) {
+                            link.setFixedFlowLink(fixedFlow.getFixedFlowName());
+                        }
+                    }
+                    List<String> names = one.stream().filter(l->l.getFixedFlowLinkSort() != null).collect(Collectors.groupingBy(
+                            FixedFlowLink::getFixedFlowLinkSort,
+                            Collectors.collectingAndThen(
+                                    Collectors.toList(),
+                                    l -> l.isEmpty() ? null : l.get(0)
+                            )
+                    )).values().stream().map(FixedFlowLink::getFixedFlowLink).collect(Collectors.toList());
+                    vo.setDeletedIs(!ids.contains(fixedFlow.getId()));
+                    vo.setLinkUserJoinString(StringUtils.join(names, ","));
+                }
+            }
+            Page<FixedFlowVO> resultMap = new Page<>();
+            resultMap.setCurrent(fixedFlowsPage.getCurrent());
+            resultMap.setSize(fixedFlowsPage.getSize());
+            resultMap.setTotal(fixedFlowsPage.getTotal());
+            resultMap.setRecords(fixedFlowVOList);
+//            Map<Boolean, List<FixedFlowVO>> groupMap = fixedFlowVOList.stream().collect(Collectors.groupingBy(record -> record.getFixedFlowName() != null && record.getFixedFlowName().contains("_") && record.getSort() == null));
+//            List<FixedFlowVO> copyFixedFlowVOS = groupMap.get(true);
+//            List<FixedFlowVO> fixedFlowVOS = groupMap.get(false);
+//            if (copyFixedFlowVOS ==  null || copyFixedFlowVOS.isEmpty() || fixedFlowVOS ==  null || fixedFlowVOS.isEmpty()) {
+//                return R.data(resultMap);
+//            }
+//            Map<String, List<FixedFlowVO>> nameMap = copyFixedFlowVOS.stream().collect(Collectors.groupingBy(record -> record.getFixedFlowName().split("_")[0]));
+//            List<FixedFlowVO> newData = new ArrayList<>(fixedFlowVOList);
+//            for (FixedFlowVO flowVO : fixedFlowVOS) {
+////                newData.add(flowVO);
+//                List<FixedFlowVO> flowVOS = nameMap.get(flowVO.getFixedFlowName());
+//                if (flowVOS != null && !flowVOS.isEmpty()) {
+//                    flowVOS.sort(Comparator.comparing(FixedFlow::getFixedFlowName));
+//                    newData.addAll(flowVOS);
+//                }
+//            }
+//            resultMap.setRecords(newData);
+            return R.data(resultMap);
+        }
+        return R.data(new Page<>());
+    }
+    @GetMapping("/getFixedFlow")
+    @ApiOperationSupport(order = 25)
+    @ApiOperation(value = "获取预设流程信息", notes = "传入预设流程id")
+    public R<org.springblade.meter.vo.FixedFlowVO> getFixedFlow(@RequestParam String id) {
+        FixedFlow fixedFlow = jdbcTemplate.query("SELECT * FROM u_fixed_flow WHERE is_deleted = 0 AND id = ?", new Object[]{id}, new BeanPropertyRowMapper<>(FixedFlow.class)).stream().findAny().orElse(null);
+        if (fixedFlow != null) {
+            ProjectInfo projectInfo = projectClient.getById(fixedFlow.getProjectId() + "");
+            List<FixedFlowLink> fixedFlowLinkList = jdbcTemplate.query("SELECT * FROM u_fixed_flow_link WHERE is_deleted = 0 AND fixed_flow_id = ? ORDER BY fixed_flow_branch_sort,fixed_flow_link_sort", new Object[]{fixedFlow.getId()}, new BeanPropertyRowMapper<>(FixedFlowLink.class));
+            if (!fixedFlowLinkList.isEmpty()) {
+                for (FixedFlowLink link : fixedFlowLinkList) {
+                    if (link.getFixedFlowBranchSort() == null ) {
+                        link.setFixedFlowBranchSort(link.getFixedFlowLinkSort());
+                        link.setFixedFlowLinkSort(1);
+                    }
+                    if (link.getFixedFlowLink() == null || link.getFixedFlowLink().isEmpty()) {
+                        link.setFixedFlowLink(fixedFlow.getFixedFlowName());
+                    }
+                    if (link.getFixedFlowLinkType() == null) {
+                        link.setFixedFlowLinkType(projectInfo == null ? (link.getFlowTaskType() == null ? 2 : link.getFlowTaskType()) : projectInfo.getApprovalType());
+                    }
+                }
+                Map<String, List<FixedFlowLink>> group = fixedFlowLinkList.stream().collect(Collectors.groupingBy(
+                        obj -> obj.getFixedFlowLink() + "@@@" + obj.getFixedFlowLinkType() + "@@@"+obj.getFlowTaskType() + "@@@"+obj.getFixedFlowLinkSort(),
+                        LinkedHashMap::new,
+                        Collectors.toList())
+                );
+
+                org.springblade.meter.vo.FixedFlowVO vo = new org.springblade.meter.vo.FixedFlowVO();
+                vo.setFixedFlowId(fixedFlow.getId());
+                vo.setFixedFlowName(fixedFlow.getFixedFlowName());
+
+                List<org.springblade.meter.vo.FixedFlowVO.FixedBranchVO> fixedBranchVOList = new LinkedList<>();
+                for (Map.Entry<String, List<FixedFlowLink>> listEntry : group.entrySet()) {
+
+                    String nameAndType = listEntry.getKey();
+                    String name = nameAndType.split("@@@")[0];
+                    String type = nameAndType.split("@@@")[1];
+                    String flowTaskType = nameAndType.split("@@@")[2];
+
+                    org.springblade.meter.vo.FixedFlowVO.FixedBranchVO fixedBranchVO = new org.springblade.meter.vo.FixedFlowVO.FixedBranchVO();
+                    fixedBranchVO.setName(name);
+                    fixedBranchVO.setType(Integer.parseInt(type));
+                    fixedBranchVO.setFlowTaskType(Integer.valueOf(flowTaskType));
+
+                    List<org.springblade.meter.vo.FixedFlowVO.FixedBranchVO.User> userListResult = new LinkedList<>();
+                    List<FixedFlowLink> userList = listEntry.getValue();
+                    for (FixedFlowLink fixedFlowLink : userList) {
+                        org.springblade.meter.vo.FixedFlowVO.FixedBranchVO.User user = new org.springblade.meter.vo.FixedFlowVO.FixedBranchVO.User();
+                        user.setUserId(fixedFlowLink.getFixedFlowLinkUser());
+                        user.setUserName(fixedFlowLink.getFixedFlowLinkUserName());
+                        user.setSort(ObjectUtil.isNotEmpty(fixedFlowLink.getFixedFlowLinkSort()) ? fixedFlowLink.getFixedFlowLinkSort() : null);
+                        userListResult.add(user);
+                    }
+
+                    fixedBranchVO.setUserList(userListResult);
+                    fixedBranchVO.setUserIds(userListResult.stream().map(l->l.getUserId()+"").collect(Collectors.joining(",")));
+                    fixedBranchVOList.add(fixedBranchVO);
+                }
+
+                vo.setFixedBranchVOList(fixedBranchVOList);
+                return R.data(vo);
+            }
+        }
+        return R.data(null);
+    }
+
+    @PostMapping("/updateFixedFlow")
+    @ApiOperationSupport(order = 26)
+    @ApiOperation(value = "修改预设流程", notes = "传入dto")
+    @Transactional(isolation = Isolation.READ_COMMITTED)
+    public R<Object> updateFixedFlow(@RequestBody UpdateFixedFlowDTO dto) {
+        if (ObjectUtil.isEmpty(dto.getFixedBranchList()) || dto.getFixedBranchList().isEmpty()) {
+            return R.fail("请选择任务流程人员");
+        }
+        //校验是否被使用过
+        List<Task> tasks = jdbcTemplate.query("SELECT * FROM u_task WHERE contract_id = ? and is_deleted = 0 and status != 3 AND fixed_flow_id = ? ", new Object[]{dto.getContractId(), dto.getFixedFlowId()}, new BeanPropertyRowMapper<>(Task.class));
+        if (!tasks.isEmpty()) {
+            return R.fail("当前流程已经使用,不能修改");
+        }
+        if (ObjectUtil.isNotEmpty(dto.getFixedName())) {
+            ProjectInfo projectInfo = projectClient.getById(dto.getProjectId() + "");
+            if (projectInfo == null) {
+                return R.fail("暂未找到项目信息,请稍后再试");
+            }
+            /*检查签字证书信息*/
+            List<String> userIds = dto.getFixedBranchList().stream().map(UpdateFixedFlowDTO.FixedBranch::getUserIds).collect(Collectors.toList());
+            List<User> users = jdbcTemplate.query("select id,name,acc_code,real_name from blade_user where is_deleted = 0 and id in (" + StringUtils.join(userIds, ",") + ")", new BeanPropertyRowMapper<>(User.class));
+            Map<Long, User> userMap = users.stream().collect(Collectors.toMap(User::getId, item -> item));
+            if (ObjectUtil.isEmpty( users)) {
+                return R.fail("请选择任务流程人员");
+            }
+            if (Objects.equals(projectInfo.getRemarkType(), 1)) {
+                //安心签,校验证书 检查签字证书信息
+                Set<String> notCertificateUserInfoSet = new HashSet<>();
+                //获取用户的证书信息
+                String ids = users.stream().map(user -> user.getId() + "").collect(Collectors.joining(","));
+                List<SignPfxFile> signPfxFiles = jdbcTemplate.query("select * from m_sign_pfx_file where is_register = 1 and certificate_user_id in ( " + ids + " )", new BeanPropertyRowMapper<>(SignPfxFile.class));
+                Map<String, List<SignPfxFile>> collect = signPfxFiles.stream().collect(Collectors.groupingBy(signPfxFile -> signPfxFile.getCertificateUserId() + ""));
+                for (User user : users) {
+                    List<SignPfxFile> userPfxList = collect.get(user.getId() + "");
+                    if (userPfxList == null || userPfxList.isEmpty()) {
+                        notCertificateUserInfoSet.add(user.getId() + "");
+                    }
+                }
+                if (!notCertificateUserInfoSet.isEmpty()) {
+                    List<String> names = new ArrayList<>();
+                    for (String userId : notCertificateUserInfoSet) {
+                        User user = userMap.get(Long.parseLong(userId));
+                        if (user != null && user.getName() != null && !user.getName().isEmpty()) {
+                            names.add(user.getName());
+                        }
+                    }
+                    throw new ServiceException("未获取到用户【" + StringUtils.join(names, "、") + "】的签字证书信息");
+                }
+            } else {
+                // 东方中讯,校验用户 accCode
+                List<String> names = new ArrayList<>();
+                for (User user : users) {
+                    if (user.getAccCode() == null || user.getAccCode().isEmpty() || user.getAccCode().equals("null")) {
+                        names.add(user.getName());
+                    }
+                }
+                if (!names.isEmpty()) {
+                    throw new ServiceException("未获取到用户【" + StringUtils.join(names, "、") + "】的签字证书信息");
+                }
+            }
+            jdbcTemplate.update("DELETE FROM u_fixed_flow_link WHERE  fixed_flow_id = ? ", dto.getFixedFlowId());
+            int userSort = 0;
+            for (int i = 0; i < dto.getFixedBranchList().size(); i++) {
+                UpdateFixedFlowDTO.FixedBranch fixedBranch = dto.getFixedBranchList().get(i);
+                if (i > 0) {
+                    userSort += Func.toLongList(dto.getFixedBranchList().get(i - 1).getUserIds()).size();
+                }
+                if (fixedBranch.getUserIds() ==  null) {
+                    continue;
+                }
+                List<FixedFlowLink> saveList = new ArrayList<>();
+                for (String userId : fixedBranch.getUserIds().split(",")) {
+                    FixedFlowLink fixedFlowLink = new FixedFlowLink();
+                    fixedFlowLink.setFixedFlowId(dto.getFixedFlowId());
+                    fixedFlowLink.setFixedFlowLink(fixedBranch.getName());
+                    fixedFlowLink.setFixedFlowLinkType(fixedBranch.getType());
+                    fixedFlowLink.setFixedFlowLinkUser(Long.parseLong(userId));
+                    fixedFlowLink.setFixedFlowLinkUserName(userMap.get(Long.parseLong(userId)).getRealName());
+                    fixedFlowLink.setFixedFlowLinkSort(i + 1);
+                    fixedFlowLink.setProjectId(dto.getProjectId());
+                    fixedFlowLink.setContractId(dto.getContractId());
+                    fixedFlowLink.setFixedFlowBranchSort(userSort+=1);
+                    fixedFlowLink.setFlowTaskType(fixedBranch.getFlowTaskType());
+                    saveList.add(fixedFlowLink);
+                }
+                if (!saveList.isEmpty()) {
+                    fixedFlowLinkService.saveBatch(saveList);
+                }
+            }
+            fixedFlowService.update(Wrappers.<FixedFlow>lambdaUpdate().set(FixedFlow::getFixedFlowName, dto.getFixedName()).eq(FixedFlow::getId, dto.getFixedFlowId()));
+            return R.success("操作成功");
+        }
+        return R.fail("操作失败");
+    }
+
+    @PostMapping("/deleteFixedFlow")
+    @ApiOperationSupport(order = 27)
+    @ApiOperation(value = "刪除预设流程", notes = "传入预设流程id")
+    public R<Object> deleteFixedFlow(@RequestParam String id) {
+        List<Task> tasks = jdbcTemplate.query("SELECT * FROM u_task WHERE is_deleted = 0 and status != 3 AND fixed_flow_id = ? ", new Object[]{id}, new BeanPropertyRowMapper<>(Task.class));
+        if (tasks.size() > 0) {
+            return R.fail("当前流程已经使用,不能删除");
+        }
+        jdbcTemplate.update("DELETE FROM u_fixed_flow WHERE id = ?", new Object[]{id});
+        jdbcTemplate.update("DELETE FROM u_fixed_flow_link WHERE fixed_flow_id = ?", new Object[]{id});
+        return R.success("操作成功");
+    }
 
 }

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

@@ -3630,7 +3630,10 @@ public R<Boolean> updateContractNodeParameter(@RequestParam Long pKeyId, @Reques
             if (sourceType >= targetType) {
                 throw new ServiceException("当前节点类型不能大于或等于父级节点类型");
             }
+            node.setNodeType(nodeType);
         }
+    }else {
+        node.setNodeType(nodeType);
     }
 
     WbsTreeContract queries = this.wbsTreeContractClient.getContractWbsTreeByPrimaryKeyId(pKeyId);
@@ -3840,7 +3843,9 @@ public R removeContractTreeNodeJudge(@RequestParam String ids) {
                 position.append(",").append(StringUtils.isNotEmpty(wbsTreeContract.getFullName()) ? wbsTreeContract.getFullName() : wbsTreeContract.getNodeName());
                 return wbsTreeContract.getPKeyId() + "";
             }).distinct().collect(Collectors.toList());
-
+            if (idArray.isEmpty()) {
+                return R.fail("删除失败,该节点下有已填报的资料");
+            }
             JSONObject json = new JSONObject();
             json.put("operationObjIds", idArray);
             String positionStr="";

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

@@ -1257,6 +1257,36 @@ public class TaskController extends BladeController {
         if (task == null || (task.getStatus() != null && task.getStatus() == 3)) {
             return R.fail("任务已被撤回或者驳回");
         }
+        //校验当前项目是否为垂直审批
+        if (ObjectUtil.isEmpty(task.getProjectId())) {
+            throw new ServiceException("未获取到任务【" + task.getTaskName() + "】对应的项目信息");
+        }
+        ProjectInfo projectInfo = jdbcTemplate.query("select approval_type from m_project_info where id = " + task.getProjectId(), new BeanPropertyRowMapper<>(ProjectInfo.class)).stream().findAny().orElse(null);
+        //如果是垂直审批,那么检查当前用户是否符合当前顺序
+        if (projectInfo != null && projectInfo.getApprovalType() != null && new Integer(1).equals(projectInfo.getApprovalType())) {
+            List<TaskParallel> taskParallelList = jdbcTemplate.query("select id,process_instance_id,task_user,task_user_name,status from u_task_parallel where process_instance_id ='" + task.getProcessInstanceId() + "'", new BeanPropertyRowMapper<>(TaskParallel.class));
+            taskParallelList.sort(Comparator.comparing(TaskParallel::getId)); //根据id排序
+            Map<String, List<TaskParallel>> taskParallelGroup = taskParallelList.stream().collect(Collectors.groupingBy(TaskParallel::getProcessInstanceId));
+            for (Map.Entry<String, List<TaskParallel>> taskObj : taskParallelGroup.entrySet()) {
+                //获取当前审批人前面的审批人信息
+                List<TaskParallel> frontTaskUser = new LinkedList<>();
+                for (TaskParallel taskParallel : taskObj.getValue()) {
+                    Long userId = SecureUtil.getUserId();
+                    if (!userId.toString().equals(taskParallel.getTaskUser())) {
+                        frontTaskUser.add(taskParallel);
+                    } else {
+                        //如果是当前的审批人,那么直接跳过
+                        break;
+                    }
+                }
+                List<TaskParallel> resultTaskStatus = frontTaskUser.stream().filter(f -> !f.getStatus().equals(2)).collect(Collectors.toList());
+                if (!resultTaskStatus.isEmpty()) {
+                    String names = resultTaskStatus.stream().map(TaskParallel::getTaskUserName).collect(Collectors.joining("、"));
+                    throw new ServiceException("当前任务【" + task.getTaskName() + "】还有【" + names + "】未完成审批,请您稍后再试");
+                }
+            }
+        }
+        //正常流程(平行签直接执行,垂直签会校验完再执行)
         this.taskService.batchCompleteApprovalTask(taskApprovalVOS);
         if (!taskApprovalVO.isPass()) {
             JSONObject json = new JSONObject();
@@ -1644,8 +1674,12 @@ public class TaskController extends BladeController {
         }
         // 3.2 任务状态过滤
         if (ObjectUtil.isNotEmpty(dto.getStatusValue())) {
-            sqlString.append(" AND status = ?");
-            params.add(dto.getStatusValue());
+            if(dto.getStatusValue() .equals(4) ){//----先查询出所有待审批的 然后根据条件进行过滤出任务已经到当前登陆人的任务为可审批
+                sqlString.append(" AND status = 1");
+            }else {
+                sqlString.append(" AND status = ?");
+                params.add(dto.getStatusValue());
+            }
         }
         // 3.3 合同段过滤(区分合同类型)
         if (contractInfo != null && contractInfo.getContractType().equals(1)) {
@@ -1709,11 +1743,11 @@ public class TaskController extends BladeController {
             if (dto.getSelectedType().equals(1)) {
                 // 待办页面逻辑
                 if (ObjectUtil.isNotEmpty(dto.getStatusValue()) && dto.getStatusValue().equals(1)) {
-                    sqlString.append("EXISTS (SELECT 1 FROM u_task_parallel WHERE u_task.process_instance_id = u_task_parallel.process_instance_id AND u_task_parallel.status = ? AND u_task_parallel.task_user = ?)");
+                    sqlString.append("EXISTS (SELECT 1 FROM u_task_parallel WHERE u_task.process_instance_id = u_task_parallel.process_instance_id AND u_task_parallel.status = ? AND u_task_parallel.task_user = ? AND (u_task_parallel.e_visa_status IS NULL OR u_task_parallel.e_visa_status=0) AND (u_task_parallel.e_visa_content IS NULL OR u_task_parallel.e_visa_content != '当前等待电签的批次较多,请等待几分钟后刷新页面查看........'))");
                     params.add(1);
                     params.add(SecureUtil.getUserId());
                     // 关联电签状态字段
-                    sqlResult = "SELECT *, (SELECT ifnull(e_visa_status, -1)  FROM u_task_parallel WHERE u_task.process_instance_id = u_task_parallel.process_instance_id AND u_task_parallel.STATUS = 1 " +
+                    sqlResult = "SELECT *, (SELECT ifnull(e_visa_status, -1)  FROM u_task_parallel WHERE is_resign = 0 and u_task.process_instance_id = u_task_parallel.process_instance_id AND u_task_parallel.STATUS = 1 " +
                             "AND u_task_parallel.task_user = " + SecureUtil.getUserId() + " and is_deleted = 0 order by id desc limit 1) as e_status";
                 } else if (ObjectUtil.isNotEmpty(dto.getStatusValue()) && !dto.getStatusValue().equals(1)) {
                     // 待办页选非待审批状态:直接返回空分页
@@ -1723,21 +1757,26 @@ public class TaskController extends BladeController {
                     return R.data(emptyPage);
                 } else {
                     // 待办页未选状态:默认查待审批
-                    sqlString.append("EXISTS (SELECT 1 FROM u_task_parallel WHERE u_task.process_instance_id = u_task_parallel.process_instance_id AND u_task_parallel.status = ? AND u_task_parallel.task_user = ?)");
+                    sqlString.append("EXISTS (SELECT 1 FROM u_task_parallel WHERE u_task.process_instance_id = u_task_parallel.process_instance_id AND u_task_parallel.status = ? AND u_task_parallel.task_user = ? AND (u_task_parallel.e_visa_status IS NULL OR u_task_parallel.e_visa_status=0) AND (u_task_parallel.e_visa_content IS NULL OR u_task_parallel.e_visa_content != '当前等待电签的批次较多,请等待几分钟后刷新页面查看........'))");
                     params.add(1);
                     params.add(SecureUtil.getUserId());
                     sqlString.append(" AND status = 1");
-                    sqlResult = "SELECT *, (SELECT ifnull(e_visa_status, -1)  FROM u_task_parallel WHERE u_task.process_instance_id = u_task_parallel.process_instance_id AND u_task_parallel.STATUS = 1 " +
+                    sqlResult = "SELECT *, (SELECT ifnull(e_visa_status, -1)  FROM u_task_parallel WHERE is_resign = 0 and u_task.process_instance_id = u_task_parallel.process_instance_id AND u_task_parallel.STATUS = 1 " +
                             "AND u_task_parallel.task_user = " + SecureUtil.getUserId() + " and is_deleted = 0 order by id desc limit 1) as e_status";
                 }
             } else if (dto.getSelectedType().equals(2)) {
                 // 已办页面逻辑
-                sqlString.append("EXISTS (SELECT 1 FROM u_task_parallel WHERE u_task.process_instance_id = u_task_parallel.process_instance_id AND u_task_parallel.status in(2,3) AND u_task_parallel.task_user = ?)");
+                sqlString.append("EXISTS (SELECT 1 FROM u_task_parallel WHERE is_resign = 0 and u_task.process_instance_id = u_task_parallel.process_instance_id  AND u_task_parallel.task_user = ? AND u_task_parallel.e_visa_status >0)");
                 params.add(SecureUtil.getUserId());
             } else if (dto.getSelectedType().equals(3)) {
                 // 我发起页面逻辑
                 sqlString.append("report_user = ?");
                 params.add(SecureUtil.getUserId());
+            } else if (dto.getSelectedType().equals(4)) {
+                sqlString.append("EXISTS (SELECT 1 FROM u_task_parallel WHERE u_task.process_instance_id = u_task_parallel.process_instance_id AND u_task_parallel.status = ? AND u_task_parallel.task_user = ? AND (u_task_parallel.e_visa_status IS NULL OR u_task_parallel.e_visa_status=0) AND u_task_parallel.e_visa_content='当前等待电签的批次较多,请等待几分钟后刷新页面查看........')");
+                params.add(1);
+                params.add(SecureUtil.getUserId());
+                sqlString.append(" AND status = 1");
             }
             sqlString.append(")");
         }
@@ -1775,7 +1814,7 @@ public class TaskController extends BladeController {
         if (CollectionUtil.isNotEmpty(processInstanceIds)) {
             String idsStr = processInstanceIds.stream().map(id -> "'" + id + "'").collect(Collectors.joining(","));
             taskParallelGroupMap = jdbcTemplate.query(
-                    "select process_instance_id,task_user,task_user_name,e_visa_status,e_visa_content,parallel_process_instance_id,status from u_task_parallel where process_instance_id in(" + idsStr + ") order by id",
+                    "select process_instance_id,task_user,task_user_name,e_visa_status,e_visa_content,parallel_process_instance_id,status,sort from u_task_parallel where process_instance_id in(" + idsStr + ") order by id",
                     new BeanPropertyRowMapper<>(TaskParallel.class)
             ).stream().collect(Collectors.groupingBy(TaskParallel::getProcessInstanceId));
         }
@@ -1798,11 +1837,37 @@ public class TaskController extends BladeController {
         }
 
         // 6. 对原始数据执行业务过滤(核心:垂直签待办任务可见性判断)
+        //根据条件过滤出可审批的数据(流程审批-非自定义流程)   flowid为0的是自定义审批的流程
+        Map<Long, List<Task>> flowIdMaps = allResultList.stream().filter(task->!"0".equals(task.getFixedFlowId().toString())).collect(Collectors.groupingBy(Task::getFixedFlowId));
+        Map<Long, List<FixedFlowLink>> fixedsMap;
+        if(ObjectUtil.isNotEmpty(flowIdMaps)){
+            String join = StringUtils.join(flowIdMaps.keySet(), ",");
+            //结果集所有数据
+            String sql = "select fixed_flow_id ,fixed_flow_branch_sort,fixed_flow_link_type,fixed_flow_link_sort from u_fixed_flow_link where  is_deleted = 0  and  fixed_flow_id in ( "+join+")";
+            List<FixedFlowLink> fixedFlowLinks = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(FixedFlowLink.class));
+            fixedsMap = fixedFlowLinks.stream().collect(Collectors.groupingBy(FixedFlowLink::getFixedFlowId));
+        } else {
+            fixedsMap = new HashMap<>();
+        }
         Map<String, List<TaskParallel>> finalTaskParallelGroupMap = taskParallelGroupMap;
         List<Task> filteredList = allResultList.stream()
                 .filter(task -> {
+                    // 获取任务流程信息,判断是否是垂直签
+                    if (task.getFixedFlowId() != null && fixedsMap.containsKey(task.getFixedFlowId())) {
+                        // 预设流程
+                        List<FixedFlowLink> fixedFlowLinks = fixedsMap.get(task.getFixedFlowId());
+                        List<FixedFlowLink> linkList = fixedFlowLinks.stream().filter(link -> link.getFixedFlowLinkType() == null).collect(Collectors.toList());
+                        if (linkList.isEmpty()) {
+                            // 获取垂直流程
+                            List<FixedFlowLink> collect = fixedFlowLinks.stream().filter(link -> link.getFixedFlowLinkType() != null && link.getFixedFlowLinkType() == 1).collect(Collectors.toList());
+                            if (!collect.isEmpty()) {
+                                // 走垂直审批逻辑
+                                return handleTaskParallel(fixedFlowLinks, finalTaskParallelGroupMap.get(task.getProcessInstanceId()), SecureUtil.getUserId());
+                            }
+                        }
+                    }
                     // 仅处理垂直签+待办页面的过滤逻辑
-                    if (projectInfo != null && projectInfo.getApprovalType() == 1 && dto.getSelectedType() == 1) {
+                    if (((projectInfo != null && projectInfo.getApprovalType() == 1)) && dto.getSelectedType() == 1) {
                         List<TaskParallel> parallelList = finalTaskParallelGroupMap.get(task.getProcessInstanceId());
                         if (CollectionUtil.isEmpty(parallelList)) {
                             return false;
@@ -1838,7 +1903,6 @@ public class TaskController extends BladeController {
         if (startIndex < endIndex && CollectionUtil.isNotEmpty(filteredList)) {
             currentPageTaskList = filteredList.subList(startIndex, endIndex);
         }
-
         // 8. 转换当前页数据为VO(复用原逻辑,补充已废除任务日志信息)
         Map<String, List<TaskParallel>> finalTaskParallelGroupMap1 = taskParallelGroupMap;
         Map<String, List<OperationLog>> finalOperationLogMap = operationLogMap;
@@ -1949,6 +2013,71 @@ public class TaskController extends BladeController {
         return R.data(page);
     }
 
+    private boolean handleTaskParallel(List<FixedFlowLink> fixedFlowLinks, List<TaskParallel> taskParallels, Long userId) {
+        taskParallels.sort(Comparator.comparing(TaskParallel::getSort, Comparator.nullsLast(Comparator.naturalOrder())));
+        for (int i = 0; i < taskParallels.size(); i++) {
+            TaskParallel parallel = taskParallels.get(i);
+            parallel.setSort(i);
+        }
+        fixedFlowLinks.sort(Comparator.comparing(FixedFlowLink::getFixedFlowBranchSort, Comparator.nullsLast(Comparator.naturalOrder())));
+        for (int i = 0; i < fixedFlowLinks.size(); i++) {
+            FixedFlowLink link = fixedFlowLinks.get(i);
+            link.setFixedFlowBranchSort(i);
+        }
+        //查出当前电签到的节点sort
+        Optional<Integer> sortDq = taskParallels.stream()
+                .filter(t -> t.getStatus() == 1)
+                .min(Comparator.comparing(TaskParallel::getSort))
+                .map(TaskParallel::getSort);
+        //获取当前用户的sort值
+        List<Integer> userSort = taskParallels.stream()
+                .filter(t -> t.getTaskUser().equals(userId.toString()))
+                .sorted(Comparator.comparing(TaskParallel::getSort))
+                .map(TaskParallel::getSort).collect(Collectors.toList());
+        Integer dqSort = sortDq.orElse(null);
+        if(ObjectUtil.isNotEmpty(dqSort)){
+            List<Integer> list1 = userSort.stream().filter(a -> dqSort.compareTo(a) <= 0).collect(Collectors.toList());
+            if(ObjectUtil.isEmpty(list1)){
+                //当前用户已经签字过
+                return false;
+            }else {
+                //筛选出最近的一条没有电签的当前用户的sort
+                Integer userMinSort = Collections.min(list1);
+                if(userMinSort.toString().equals(dqSort.toString())){
+                    //当前用户就是下一个电签用户 可审批 放行
+                    return true;
+                }
+                FixedFlowLink dqFlowLink = null;
+                FixedFlowLink userFlowLink = null;
+                for (FixedFlowLink fixedFlowLink : fixedFlowLinks) {
+                    if (fixedFlowLink.getFixedFlowBranchSort() != null && fixedFlowLink.getFixedFlowBranchSort() >= dqSort && dqFlowLink == null) {
+                        dqFlowLink = fixedFlowLink;
+                    }
+                    if (fixedFlowLink.getFixedFlowBranchSort() != null && fixedFlowLink.getFixedFlowBranchSort() >= userMinSort && userFlowLink == null) {
+                        userFlowLink = fixedFlowLink;
+                    }
+                    if (dqFlowLink != null && userFlowLink != null) {
+                        break;
+                    }
+                }
+                if (dqFlowLink == null || userFlowLink == null) {
+                    return false;
+                }
+                if(Objects.equals(dqFlowLink.getFixedFlowLinkSort(), userFlowLink.getFixedFlowLinkSort())){
+                    //在同一个小流程里面去判断是否垂直还是水平
+                    //平行 通过
+                    return dqFlowLink.getFixedFlowLinkType() == 2;
+                }else {
+                    //不在一个小流程 不可审批
+                    return  false;
+                }
+            }
+        }else {
+            //全部签完了 肯定不是可审批
+            return false;
+        }
+    }
+
     @PostMapping("/pageset")
     @ApiOperationSupport(order = 1)
     @ApiOperation(value = "电签显示等待 batch中没有 用于跑电签数据的接口 手动调用", notes = "传入BusinessTaskDTO")
@@ -2442,6 +2571,18 @@ public class TaskController extends BladeController {
         return taskService.reSigningEVisaStatus0(dtos,header);
     }
 
+    @GetMapping("/checkAndRepairPDFisNull")
+    @ApiOperation(value = "检查PDF是否为空")
+    @ApiOperationSupport(order = 3)
+    public void checkAndRepairPDFisNull(HttpServletRequest request) throws Exception {
+        String header = request.getHeader("Blade-Auth");
+        Long projectId=1904814720589430785L;
+        String sql="select id,wbs_id,project_id,contract_id from u_information_query where project_id="+projectId+" and pdf_url is null and node_pdf_url is null  and status in(0,1,2) and is_deleted=0";
+        List<reSigningEVisaStatus> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(reSigningEVisaStatus.class));
+        taskService.reSigningEVisaStatus0(query,header);
+        System.out.println("完成");
+    }
+
     @PostMapping("/reSigningEntrust")
     @ApiOperationSupport(order = 3)
     @ApiOperation(value = "委托单管理-一键重签", notes = "传入taskIds、下拉框的contractId、projectId")
@@ -2603,9 +2744,9 @@ public class TaskController extends BladeController {
     @PostMapping("/reSigningEVisaByUserIds")
     @ApiOperationSupport(order = 3)
     @ApiOperation(value = "任务管理-一键重签", notes = "传入taskIds、下拉框的contractId、projectId")
-    public R<Object> reSigningEVisaByUserIds(@RequestParam String ids, @RequestParam String userIds) {
+    public R<Object> reSigningEVisaByUserIds(@RequestBody Map<String, String> vo) {
 
-       return taskService.reSigningEVisaByUserIds(ids,userIds);
+       return taskService.reSigningEVisaByUserIds(vo.get("ids"),vo.get("userIds"));
     }
 
 }

+ 8 - 4
blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialClassificationTreeController.java

@@ -61,6 +61,7 @@ import java.util.stream.Collectors;
 public class TrialClassificationTreeController extends BladeController {
 
 	private final ITrialClassificationTreeService trialClassificationTreeService;
+	private final Long TJ05_CONTRACT_ID = 1912405021063585793L;
 
 //	/**
 //	 * 详情
@@ -79,11 +80,11 @@ public class TrialClassificationTreeController extends BladeController {
 	@GetMapping("/list")
 	@ApiOperationSupport(order = 2)
 	@ApiOperation(value = "查询当前节点的子节点", notes = "传入trialClassificationTree")
-	public R<List<TrialClassificationTreeVO>> list(Long id,Long projectId) {
+	public R<List<TrialClassificationTreeVO>> list(Long id,Long projectId,Long TJ05_CONTRACT_ID) {
 		if(projectId==null){
 			throw new ServiceException("请选择项目");
 		}
-		List<TrialClassificationTreeVO> list = trialClassificationTreeService.selectAllNode(id,projectId);
+		List<TrialClassificationTreeVO> list = trialClassificationTreeService.selectAllNode(id,projectId,TJ05_CONTRACT_ID);
 		return R.data(list);
 	}
 
@@ -122,6 +123,7 @@ public class TrialClassificationTreeController extends BladeController {
 		for (TrialClassificationTreeDTO trialClassificationTreeDTO : dto.getList()) {
 			TrialClassificationTree trialClassificationTree = new TrialClassificationTree();
 			BeanUtil.copy(trialClassificationTreeDTO, trialClassificationTree);
+			trialClassificationTree.setContractId(TJ05_CONTRACT_ID);
 			Long parentId = trialClassificationTree.getParentId();
 			StringBuilder classificationAncestors = new StringBuilder();
 			classificationAncestors.append(trialClassificationTree.getId());
@@ -136,6 +138,7 @@ public class TrialClassificationTreeController extends BladeController {
 			}
 			trialClassificationTree.setClassificationAncestors(classificationAncestors.toString());
 			trialClassificationTree.setGroupType(dto.getGroupType());
+			trialClassificationTree.setSort(trialClassificationTree.getSort());
 			insertList.add(trialClassificationTree);
 		}
 		return R.status(trialClassificationTreeService.saveBatch(insertList));
@@ -163,7 +166,7 @@ public class TrialClassificationTreeController extends BladeController {
 	@PostMapping("/update")
 	@ApiOperationSupport(order = 5)
 	@ApiOperation(value = "修改", notes = "传入trialClassificationTree")
-	public R update(Long id,String classificationName) {
+	public R update(Long id,String classificationName, Integer sort) {
 		if(id==null){
 			return R.fail("请选择要修改的分类");
 		}
@@ -172,7 +175,8 @@ public class TrialClassificationTreeController extends BladeController {
 		}
 		TrialClassificationTree trialClassificationTree = new TrialClassificationTree();
 		trialClassificationTree.setClassificationName(classificationName);
-		return R.status(trialClassificationTreeService.update(new UpdateWrapper<TrialClassificationTree>().set("classification_name", classificationName).eq("id", id)));
+		return R.status(trialClassificationTreeService.update(new UpdateWrapper<TrialClassificationTree>()
+				.set(sort != null,"sort", sort).set("classification_name", classificationName).eq("id", id)));
 	}
 
 //	/**

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

@@ -55,8 +55,8 @@ public class TrialCyController {
     @GetMapping("/getTree")
     @ApiOperationSupport(order = 1)
     @ApiOperation(value = "获取成渝那边的树", notes = "传入项目id")
-    public R<List<TrialCyTestType>> getTree(Long projectId, String parentId){
-        return R.data(trialCyService.getTree(projectId,parentId));
+    public R<List<TrialCyTestType>> getTree(Long projectId, String parentId, String contractId){
+        return R.data(trialCyService.getTree(projectId,parentId,contractId));
     }
 
     /**

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

@@ -1,5 +1,6 @@
 package org.springblade.business.controller;
 
+import cn.hutool.core.stream.CollectorUtil;
 import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
@@ -10,6 +11,7 @@ import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiOperation;
+import jodd.util.StringUtil;
 import lombok.AllArgsConstructor;
 import lombok.SneakyThrows;
 import org.springblade.business.dto.*;
@@ -25,6 +27,7 @@ import org.springblade.core.mp.support.Query;
 import org.springblade.core.oss.model.BladeFile;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.BeanUtil;
+import org.springblade.core.tool.utils.CollectionUtil;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.core.tool.utils.ResourceUtil;
 import org.springblade.manager.entity.ContractInfo;
@@ -232,7 +235,23 @@ public class TrialDetectionController extends BladeController {
             }
         } else {
             //编辑复制 复制数据 附件文件
-            if (wbsTreePrivateClient.copyBussTab(pKeyId, id, contractId)) {
+            //获取复制表的pkid
+
+            TrialSelfInspectionRecord byId = iTrialSelfInspectionRecordService.getById(id);
+            Long copyId = wbsTreePrivateClient.copyBussTab(pKeyId, id, contractId, byId.getTableIds());
+            if (copyId != null) {
+                if(StringUtils.isEmpty(byId.getTableIds())){
+                    //绑定初始表单
+                    WbsTreePrivate nodeByPrimaryKeyId = wbsTreePrivateClient.getNodeByPrimaryKeyId(pKeyId.toString());
+                    List<Long> tableIds = wbsTreePrivateClient.testFormInit(Long.valueOf(nodeByPrimaryKeyId.getProjectId()), contractId, nodeByPrimaryKeyId.getWbsId(), nodeByPrimaryKeyId.getId());
+                    if(CollectionUtil.isNotEmpty(tableIds)){
+                        tableIds.add(copyId);
+                    }
+                    byId.setTableIds(StringUtil.join(tableIds, ","));
+                }else{
+                    byId.setTableIds(byId.getTableIds() + "," + copyId);
+                }
+                iTrialSelfInspectionRecordService.updateById(byId);
                 return R.success("复制成功");
             }
         }

+ 170 - 92
blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialSummaryController.java

@@ -3,6 +3,7 @@ package org.springblade.business.controller;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.fasterxml.jackson.core.JsonProcessingException;
@@ -16,18 +17,21 @@ import org.apache.commons.lang.StringUtils;
 import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
 import org.apache.poi.ss.usermodel.*;
 import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.ss.util.CellRangeAddressBase;
 import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.jsoup.Jsoup;
 import org.jsoup.nodes.Document;
 import org.jsoup.nodes.Element;
 import org.jsoup.select.Elements;
+import org.springblade.business.dto.TrialSeleInspectionRecordBaseInfoDTO;
 import org.springblade.business.dto.TrialSummaryRecordDTO;
 import org.springblade.business.dto.TrialSummaryRecordPageDTO;
-import org.springblade.business.entity.TrialSelfInspectionRecord;
-import org.springblade.business.entity.TrialSummaryRecord;
-import org.springblade.business.entity.TrialSummaryRecordDataJson;
+import org.springblade.business.entity.*;
 import org.springblade.business.service.impl.TrialSelfInspectionRecordServiceImpl;
 import org.springblade.business.service.impl.TrialSummaryRecordServiceImpl;
+import org.springblade.business.vo.TrialRawMaterialSelfRecord;
+import org.springblade.business.vo.TrialSelfInspectionRecordVO;
+import org.springblade.business.vo.TrialSelfSample;
 import org.springblade.business.vo.TrialSummaryRecordVO;
 import org.springblade.common.constant.CommonConstant;
 import org.springblade.common.utils.CommonUtil;
@@ -36,16 +40,16 @@ import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.oss.model.BladeFile;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.utils.*;
-import org.springblade.manager.entity.ContractInfo;
-import org.springblade.manager.entity.ExcelTab;
-import org.springblade.manager.entity.TrialSummaryClassificationConfiguration;
-import org.springblade.manager.entity.TrialSummaryExcelTabReflection;
+import org.springblade.manager.entity.*;
+import org.springblade.manager.vo.TrialTableDataInfo;
 import org.springblade.resource.feign.NewIOSSClient;
 import org.springblade.resource.vo.NewBladeFile;
 import org.springblade.system.cache.ParamCache;
 import org.springblade.system.entity.Dict;
+import org.springframework.beans.BeanUtils;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.SingleColumnRowMapper;
 import org.springframework.mock.web.MockMultipartFile;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
@@ -156,7 +160,8 @@ public class TrialSummaryController {
                     vo.setClassIdName(classificationConfigurationMap.get(obj.getClassId()).getClassName());
                     vo.setDetectionTypeName(dictMap.get(obj.getDetectionType().toString()).getDictValue());
                     vo.setSummaryDateName(obj.getStartDate() + "~" + obj.getEndDate());
-                    vo.setUnitTypeName(obj.getUnitType().equals(1) ? "施工" : "监理");
+                    vo.setUnitTypeName(obj.getUnitType().equals(1) ? "施工" : obj.getUnitType().equals(2) ? "监理" : "业主");
+                    vo.setClassIdName(vo.getClassIdName() + "(" + vo.getUnitTypeName() + ")");
                     return vo;
                 }).collect(Collectors.toList());
         page.setRecords(collect);
@@ -191,12 +196,20 @@ public class TrialSummaryController {
                     .in(TrialSelfInspectionRecord::getNodeId, Func.toLongList(classC.getTrialTreeIds()))
                     .eq(TrialSelfInspectionRecord::getContractId, dto.getContractId())
                     .eq(TrialSelfInspectionRecord::getDetectionCategory, dto.getDetectionType())
+                    .eq(TrialSelfInspectionRecord::getType, dto.getUnitType())
+                    .eq(TrialSelfInspectionRecord::getTaskStatus, "已审批")
                     .between(TrialSelfInspectionRecord::getReportDate, startDate, endDate)
+                    .last(" order by report_date, report_no, record_no asc")
             );
             if (records.size() <= 0) {
                 throw new ServiceException("未获取到该报告时间段范围内的试验自检记录信息,操作失败");
             }
-            List<Long> recordIds = records.stream().map(TrialSelfInspectionRecord::getId).collect(Collectors.toList());
+            List<Long> recordIds = new ArrayList<>();
+            Map<Long, Integer> sortMap = new HashMap<>();
+            for (int i = 0; i < records.size(); i++) {
+                sortMap.put(records.get(i).getId(), i);
+                recordIds.add(records.get(i).getId());
+            }
 
             String sql_2 = "SELECT * FROM m_trial_summary_excel_tab_reflection WHERE excel_id = ? AND class_id = ?";
             List<TrialSummaryExcelTabReflection> excelTabReflections = jdbcTemplate.query(sql_2,
@@ -208,6 +221,7 @@ public class TrialSummaryController {
 
             /*构造实体数据map*/
             Map<String, Object> map = new LinkedHashMap<>();
+            List<Map<String, Object>> trialTableData = trialSelfInspectionRecordServiceImpl.getTrialTableData(recordIds);
             for (Map.Entry<String, List<TrialSummaryExcelTabReflection>> entry : maps.entrySet()) {
                 String tabName = entry.getKey().split("###")[0];
                 String tabPkeyId = entry.getKey().split("###")[1];
@@ -215,96 +229,115 @@ public class TrialSummaryController {
                 List<TrialSummaryExcelTabReflection> value = entry.getValue();
                 Map<String, List<TrialSummaryExcelTabReflection>> elementKeyWithHtmlKeyNameMap = value.stream().collect(Collectors.groupingBy(TrialSummaryExcelTabReflection::getElementKey));
                 Set<String> elementKeys = elementKeyWithHtmlKeyNameMap.keySet();
-
-                String sql_3 = "SELECT " + String.join(",", elementKeys) + " FROM " + tabName + " WHERE p_key_id = " + tabPkeyId + " AND group_id in(" + StringUtils.join(recordIds, ",") + ")";
-                List<Map<String, Object>> tabDataList = jdbcTemplate.queryForList(sql_3);
+                List<Map<String, Object>> tabDataList;
+                if (TrialTableDataInfo.TBN.equals(tabName)) {
+                    if (trialTableData != null && !trialTableData.isEmpty()) {
+                        tabDataList = trialTableData;
+                    } else {
+                        tabDataList = new ArrayList<>();
+                    }
+                } else {
+                    String sql_3 = "SELECT " + String.join(",", elementKeys) + " ,group_id FROM " + tabName + " WHERE p_key_id = " + tabPkeyId + " AND group_id in(" + StringUtils.join(recordIds, ",") + ")";
+                    tabDataList = jdbcTemplate.queryForList(sql_3);
+                }
                 if (tabDataList.isEmpty()) {
                     continue;
                 }
-
+                Map<String, List<Map<String, Object>>> dataGroupMap = tabDataList.stream().collect(Collectors.groupingBy(data -> data.get("group_id") + ""));
+                List<String> list = tabDataList.stream().map(data -> data.get("group_id") + "").sorted((o1, o2) -> {
+                    int i = sortMap.get(Long.parseLong(o1));
+                    int j = sortMap.get(Long.parseLong(o2));
+                    return Integer.compare(i, j);
+                }).collect(Collectors.toList());
                 for (String elementKey : elementKeys) {
-                    for (Map<String, Object> stringObjectMap : tabDataList) {
-                        stringObjectMap.entrySet().removeIf(obj -> obj.getValue() == null || obj.getValue().equals(""));
-                        Object tabData = stringObjectMap.getOrDefault(elementKey, null);
-                        if (ObjectUtil.isEmpty(tabData)) {
+                    for (String key : list) {
+                        List<Map<String, Object>> dataList = dataGroupMap.get(key);
+                        if (dataList == null || dataList.isEmpty()) {
                             continue;
                         }
-
-                        String tabDataStr = (String) tabData;
-                        //跨行
-                        if (tabDataStr.contains("☆")) {
-                            String[] split = tabDataStr.split("☆");
-                            for (String valueRow : split) {
-                                String[] splitValues = valueRow.split(Pattern.quote("_^_"));
-                                String valueInput = splitValues[0];
-                                /*String indexKey = splitValues[1];*/
-                                String keyName = elementKey + "__";
-
-                                if (map.containsKey(keyName)) {
-                                    String existingValue = (String) map.get(keyName);
-                                    map.put(keyName, existingValue + "@@@###" + valueInput);
-                                } else {
-                                    map.put(keyName, valueInput);
-                                }
+                        for (Map<String, Object> stringObjectMap : dataList) {
+                            stringObjectMap.entrySet().removeIf(obj -> obj.getValue() == null || obj.getValue().equals(""));
+                            Object tabData = stringObjectMap.getOrDefault(elementKey, null);
+                            if (ObjectUtil.isEmpty(tabData)) {
+                                continue;
                             }
 
-                        } else {
-                            //非跨行
-                            if (tabDataStr.contains(".000Z]") && tabDataStr.contains("T")) {
-                                String[] splitValues = tabDataStr.split(Pattern.quote("_^_"));
-                                String valueInput = splitValues[0];
-                                /*String indexKey = splitValues[1];*/
-                                String keyName = elementKey + "__";
-
-                                //范围日期
-                                String[] split = valueInput.split(",");
-                                String date_1 = split[0].trim();
-                                String date_2 = split[1].trim();
-                                LocalDateTime startTime = LocalDateTime.parse(date_1, DateTimeFormatter.ISO_DATE_TIME);
-                                LocalDateTime endTime = LocalDateTime.parse(date_2, DateTimeFormatter.ISO_DATE_TIME);
-                                ZonedDateTime startZonedTime = startTime.atZone(ZoneId.of("UTC"));
-                                ZonedDateTime endZonedTime = endTime.atZone(ZoneId.of("UTC"));
-                                String time_1 = startZonedTime.format(DateTimeFormatter.ISO_DATE_TIME);
-                                String time_2 = endZonedTime.format(DateTimeFormatter.ISO_DATE_TIME);
-
-                                if (map.containsKey(keyName)) {
-                                    String existingValue = (String) map.get(keyName);
-                                    map.put(keyName, existingValue + "@@@###" + time_1 + "~" + time_2);
-                                } else {
-                                    map.put(keyName, time_1 + "~" + time_2);
+                            String tabDataStr = (String) tabData;
+                            //跨行
+                            if (tabDataStr.contains("☆")) {
+                                String[] split = tabDataStr.split("☆");
+                                for (String valueRow : split) {
+                                    String[] splitValues = valueRow.split(Pattern.quote("_^_"));
+                                    String valueInput = splitValues[0];
+                                    /*String indexKey = splitValues[1];*/
+                                    String keyName = elementKey + "__" + tabPkeyId;
+
+                                    if (map.containsKey(keyName)) {
+                                        String existingValue = (String) map.get(keyName);
+                                        map.put(keyName, existingValue + "@@@###" + valueInput);
+                                    } else {
+                                        map.put(keyName, valueInput);
+                                    }
                                 }
 
-                            } else if (tabDataStr.contains(".000Z") && tabDataStr.contains("T")) {
-                                String[] splitValues = tabDataStr.split(Pattern.quote("_^_"));
-                                String valueInput = splitValues[0];
-                                /*String indexKey = splitValues[1];*/
-                                String keyName = elementKey + "__";
+                            } else {
+                                //非跨行
+                                if (tabDataStr.contains(".000Z]") && tabDataStr.contains("T")) {
+                                    String[] splitValues = tabDataStr.split(Pattern.quote("_^_"));
+                                    String valueInput = splitValues[0];
+                                    /*String indexKey = splitValues[1];*/
+                                    String keyName = elementKey + "__" + tabPkeyId;
+
+                                    //范围日期
+                                    String[] split = valueInput.split(",");
+                                    String date_1 = split[0].trim();
+                                    String date_2 = split[1].trim();
+                                    LocalDateTime startTime = LocalDateTime.parse(date_1, DateTimeFormatter.ISO_DATE_TIME);
+                                    LocalDateTime endTime = LocalDateTime.parse(date_2, DateTimeFormatter.ISO_DATE_TIME);
+                                    ZonedDateTime startZonedTime = startTime.atZone(ZoneId.of("UTC"));
+                                    ZonedDateTime endZonedTime = endTime.atZone(ZoneId.of("UTC"));
+                                    String time_1 = startZonedTime.format(DateTimeFormatter.ISO_DATE_TIME);
+                                    String time_2 = endZonedTime.format(DateTimeFormatter.ISO_DATE_TIME);
+
+                                    if (map.containsKey(keyName)) {
+                                        String existingValue = (String) map.get(keyName);
+                                        map.put(keyName, existingValue + "@@@###" + time_1 + "~" + time_2);
+                                    } else {
+                                        map.put(keyName, time_1 + "~" + time_2);
+                                    }
 
-                                //单日期
-                                LocalDateTime time = LocalDateTime.parse(valueInput, DateTimeFormatter.ISO_DATE_TIME);
-                                ZonedDateTime zonedDateTime = time.atZone(ZoneId.of("UTC"));
-                                String timeStr = zonedDateTime.format(DateTimeFormatter.ISO_DATE_TIME);
+                                } else if (tabDataStr.contains(".000Z") && tabDataStr.contains("T")) {
+                                    String[] splitValues = tabDataStr.split(Pattern.quote("_^_"));
+                                    String valueInput = splitValues[0];
+                                    /*String indexKey = splitValues[1];*/
+                                    String keyName = elementKey + "__" + tabPkeyId;
+
+                                    //单日期
+                                    LocalDateTime time = LocalDateTime.parse(valueInput, DateTimeFormatter.ISO_DATE_TIME);
+                                    ZonedDateTime zonedDateTime = time.atZone(ZoneId.of("UTC"));
+                                    String timeStr = zonedDateTime.format(DateTimeFormatter.ISO_DATE_TIME);
+
+                                    if (map.containsKey(keyName)) {
+                                        String existingValue = (String) map.get(keyName);
+                                        map.put(keyName, existingValue + "@@@###" + timeStr);
+                                    } else {
+                                        map.put(keyName, timeStr);
+                                    }
 
-                                if (map.containsKey(keyName)) {
-                                    String existingValue = (String) map.get(keyName);
-                                    map.put(keyName, existingValue + "@@@###" + timeStr);
                                 } else {
-                                    map.put(keyName, timeStr);
-                                }
+                                    String[] splitValues = tabDataStr.split(Pattern.quote("_^_"));
+                                    String valueInput = splitValues[0];
+                                    /*String indexKey = splitValues[1];*/
+                                    String keyName = elementKey + "__" + tabPkeyId;
+
+                                    if (map.containsKey(keyName)) {
+                                        String existingValue = (String) map.get(keyName);
+                                        map.put(keyName, existingValue + "@@@###" + valueInput);
+                                    } else {
+                                        map.put(keyName, valueInput);
+                                    }
 
-                            } else {
-                                String[] splitValues = tabDataStr.split(Pattern.quote("_^_"));
-                                String valueInput = splitValues[0];
-                                /*String indexKey = splitValues[1];*/
-                                String keyName = elementKey + "__";
-
-                                if (map.containsKey(keyName)) {
-                                    String existingValue = (String) map.get(keyName);
-                                    map.put(keyName, existingValue + "@@@###" + valueInput);
-                                } else {
-                                    map.put(keyName, valueInput);
                                 }
-
                             }
                         }
                     }
@@ -315,7 +348,7 @@ public class TrialSummaryController {
             Map<String, Object> map2 = new HashMap<>();
              for(String mapKey : map.keySet()){
                  for(TrialSummaryExcelTabReflection data: excelTabReflections){
-                    if(mapKey.equals((data.getElementKey()+"__"))){
+                    if(mapKey.equals(data.getElementKey() + "__" + data.getTrialTabId())){
                         map2.put(data.getHtmlKeyName().split("__")[0]+"__",map.get(mapKey));
                     }
                  }
@@ -327,7 +360,7 @@ public class TrialSummaryController {
             if (indexMap.size() > 0) {
                 ExcelTab excelTab = jdbcTemplate.query("SELECT file_url FROM m_excel_tab WHERE id = ?", new Object[]{classC.getExcelId()}, new BeanPropertyRowMapper<>(ExcelTab.class)).stream().findAny().orElse(null);
                 if (excelTab != null) {
-                    List<MultipartFile> files = this.writeDataToMultipartFile(excelTab.getFileUrl(), indexMap);
+                    List<MultipartFile> files = this.writeDataToMultipartFile(excelTab.getFileUrl(), indexMap, dto.getContractId());
                     if (files.size() > 0) {
                         NewBladeFile newBladeFile = newIOSSClient.excelToPdfs(files);
                         if (newBladeFile != null) {
@@ -379,7 +412,7 @@ public class TrialSummaryController {
      * @return
      * @throws Exception
      */
-    private List<MultipartFile> writeDataToMultipartFile(String fileUrl, Map<String, String> indexMap) throws Exception {
+    private List<MultipartFile> writeDataToMultipartFile(String fileUrl, Map<String, String> indexMap, Long contractId) throws Exception {
         /*pageSize分页分组*/
         Map<String, List<Map.Entry<String, String>>> groupedByPageSize = indexMap.entrySet().stream()
                 .collect(Collectors.groupingBy(entry -> {
@@ -388,7 +421,9 @@ public class TrialSummaryController {
                 }));
 
         List<MultipartFile> files = new LinkedList<>();
-
+        List<String> query = jdbcTemplate.query("select project_name from m_project_info a left join m_contract_info b on a.id = b.p_id where b.id =" + contractId, new SingleColumnRowMapper<>(String.class));
+        String projectName = query.isEmpty()? "" : query.get(0);
+        indexMap.put("projectName", projectName);
         /*每一页视为一份新excel*/
         for (Map.Entry<String, List<Map.Entry<String, String>>> page : groupedByPageSize.entrySet()) {
             InputStream modInput = CommonUtil.getOSSInputStream(fileUrl);
@@ -414,6 +449,48 @@ public class TrialSummaryController {
                         /*根据位置信息,将value写入excel*/
                         mergeAndCenterCells(sheet, x1, x2, y1, y2, value);
                     }
+                    //标题添加
+                    sheet.setForceFormulaRecalculation(true);
+                    int all = 0;
+                    List<CellRangeAddress> mergedRegions = sheet.getMergedRegions();
+                    mergedRegions.sort(Comparator.comparingInt(CellRangeAddressBase::getFirstRow));
+                    int xle = Math.min(mergedRegions.size(), 10);
+                    for (int i = 0; i < xle; i++) {
+                        CellRangeAddress mergedCell = sheet.getMergedRegion(i);
+                        int xx = mergedCell.getLastColumn();
+                        if (xx >= all) {
+                            all = xx;
+                        }
+                    }
+                    for (int i = 0; i < xle; i++) {
+                        CellRangeAddress mergedCell = mergedRegions.get(i);
+                        int xx = mergedCell.getLastColumn() + 2;
+                        if (xx >= all) {
+                            int fisRow = mergedCell.getFirstRow();
+                            int firsrCol = mergedCell.getFirstColumn();
+                            Cell cell = sheet.getRow(fisRow).getCell(firsrCol);
+                            short fontIndex = cell.getCellStyle().getFontIndex();
+                            Font oldfontAt = workbook.getFontAt(fontIndex);
+                            Font redFont = workbook.createFont();
+                            redFont.setFontHeightInPoints(oldfontAt.getFontHeightInPoints());//设置字体大小
+                            redFont.setFontName(oldfontAt.getFontName());//设置字体
+                            CellStyle newStyle = workbook.createCellStyle(); //创建单元格样式
+                            newStyle.cloneStyleFrom(cell.getCellStyle());
+                            short fontHeightInPoints = redFont.getFontHeightInPoints();
+                            if (fontHeightInPoints >= 10 && StringUtils.isBlank(cell.getStringCellValue()) && fisRow <= 8) {
+                                String title = indexMap.get("projectName");
+                                if (title.length() >= 30) {
+                                    sheet.getRow(fisRow).setHeight((short) 900);
+                                    newStyle.setWrapText(true);
+                                }
+                                redFont.setBold(true);
+                                newStyle.setFont(redFont);
+                                cell.setCellStyle(newStyle);
+                                cell.setCellValue(title);
+                                break;
+                            }
+                        }
+                    }
 
                     try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
                         workbook.write(byteArrayOutputStream);
@@ -567,10 +644,11 @@ public class TrialSummaryController {
 
                 if (sortedElements.size() < data.length) {
                     /*html输入框数量 < 试验自检实体数据 ,存在多页,需翻页*/
-                    int countInputAdd = data.length - sortedElements.size();
-                    /*每页需要sortedElements.size()个输入框,共需要countPage页*/
-                    int countPage = (countInputAdd + sortedElements.size()) / sortedElements.size();
-                    countPage += (countInputAdd + sortedElements.size() - 1) % sortedElements.size() > 0 ? 1 : 0;
+//                    int countInputAdd = data.length - sortedElements.size();
+//                    /*每页需要sortedElements.size()个输入框,共需要countPage页*/
+//                    int countPage = (countInputAdd + sortedElements.size()) / sortedElements.size();
+//                    countPage += (countInputAdd + sortedElements.size() - 1) % sortedElements.size() > 0 ? 1 : 0;
+                    int countPage = data.length % sortedElements.size() == 0 ? data.length / sortedElements.size() : data.length / sortedElements.size() + 1;
 
                     List<Element> sortedElementsAll = new LinkedList<>();
                     for (int i = 0; i < countPage; i++) {

+ 3 - 0
blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialSystemDockingController.java

@@ -63,6 +63,7 @@ public class TrialSystemDockingController extends BladeController {
 
 	private final ITrialClassificationTreeService trialClassificationTreeService;
 
+	private final Long TJ05_CONTRACT_ID = 1912405021063585793L;
 
 	/**
 	 * 详情
@@ -93,6 +94,7 @@ public class TrialSystemDockingController extends BladeController {
 	@ApiOperationSupport(order = 3)
 	@ApiOperation(value = "分页", notes = "传入trialSystemDocking")
 	public R<IPage<TrialSystemDockingVO>> page(TrialSystemDockingVO trialSystemDocking, Query query) {
+		trialSystemDocking.setContractId(TJ05_CONTRACT_ID);
 		IPage<TrialSystemDockingVO> pages = trialSystemDockingService.selectTrialSystemDockingPage(Condition.getPage(query), trialSystemDocking);
 		return R.data(pages);
 	}
@@ -108,6 +110,7 @@ public class TrialSystemDockingController extends BladeController {
 		for (TrialSystemDockingDTO trialSystemDockingDTO : list) {
 			TrialSystemDocking trialSystemDocking = new TrialSystemDocking();
 			BeanUtil.copy(trialSystemDockingDTO,trialSystemDocking);
+			trialSystemDocking.setContractId(TJ05_CONTRACT_ID);
 			TrialClassificationTree trialClassificationTree = trialClassificationTreeService.getById(trialSystemDockingDTO.getClassificationId());
 			if(trialClassificationTree!=null){
 				trialSystemDocking.setClassificationAncestors(trialClassificationTree.getClassificationAncestors());

+ 24 - 6
blade-service/blade-business/src/main/java/org/springblade/business/controller/UserViewProjectContractController.java

@@ -23,18 +23,21 @@ import org.springblade.manager.dto.SaveUserInfoByProjectDTO;
 import org.springblade.manager.entity.ContractInfo;
 import org.springblade.manager.entity.ProjectInfo;
 import org.springblade.manager.entity.SignPfxFile;
+import org.springblade.manager.entity.UserProjectInfoCollect;
 import org.springblade.manager.feign.ContractClient;
 import org.springblade.manager.feign.ProjectAssignmentUserClient;
 import org.springblade.manager.feign.ProjectClient;
 import org.springblade.manager.feign.SignPfxClient;
 import org.springblade.manager.vo.ContractInfoVO;
 import org.springblade.manager.vo.ProjectInfoVO;
+import org.springblade.manager.vo.WbsTreeContractLazyVO;
 import org.springblade.system.entity.Role;
 import org.springblade.system.feign.ISysClient;
 import org.springblade.system.user.entity.User;
 import org.springblade.system.user.feign.IUserClient;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.SingleColumnRowMapper;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -46,9 +49,7 @@ import java.io.InputStream;
 import java.math.BigDecimal;
 import java.net.URL;
 import java.net.URLConnection;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
+import java.util.*;
 import java.util.stream.Collectors;
 
 @RestController
@@ -268,18 +269,35 @@ public class UserViewProjectContractController {
                     contractInfoList.sort(Comparator.comparingInt(ContractInfoVO::getIsDefault).reversed());
                     vo.setContractInfoList(contractInfoList);
                 });
-                //排序项目
-                projectInfoVOS.sort(Comparator.comparingInt(ProjectInfoVO::getIsDefault).reversed());
             }
 
             //剔除没有合同段的项目
             projectInfoVOS.removeIf(next -> next.getContractInfoList().size() == 0);
+            //排序项目
+            List<UserProjectInfoCollect> collectIds = new ArrayList<>();
+            if (!projectInfoVOS.isEmpty()) {
+                String pIds = projectInfoVOS.stream().map(projectInfoVO -> projectInfoVO.getId() + "").collect(Collectors.joining(","));
+                collectIds = jdbcTemplate.query("select project_id,sort from m_user_project_collect where is_deleted = 0 and user_id = " + AuthUtil.getUserId() + " and project_id in ( " + pIds + ")",
+                        new BeanPropertyRowMapper<>(UserProjectInfoCollect.class));
+            }
+            Map<Long, Integer> collect = collectIds.stream().collect(Collectors.toMap(UserProjectInfoCollect::getProjectId, UserProjectInfoCollect::getSort, (k1, k2) -> k1));
+            for (ProjectInfoVO vo : projectInfoVOS) {
+                vo.setIsCollect(collect.getOrDefault(vo.getId(), 999));
+            }
+            // 按是否收藏进行排序,然后按照sort 进行排序, 按照创建时间倒序排序
+            projectInfoVOS.sort(Comparator.comparing(ProjectInfoVO::getIsCollect, Comparator.nullsLast(Comparator.naturalOrder()))
+                    .thenComparing(ProjectInfoVO::getSort, Comparator.nullsLast(Comparator.naturalOrder())).thenComparing(ProjectInfoVO::getCreateTime, Comparator.nullsLast(Comparator.reverseOrder())));
+
             //将合同段中业主合同段排在最前面
             if(ObjectUtil.isNotEmpty(projectInfoVOS)){
                 for (ProjectInfoVO projectInfoVO : projectInfoVOS) {
                     if(ObjectUtil.isNotEmpty(projectInfoVO.getContractInfoList())){
                         List<ContractInfoVO> contractInfoList = projectInfoVO.getContractInfoList();
-                        contractInfoList.sort(Comparator.comparingInt(contractInfo->contractInfo.getContractType() == 3 ? -1:0));
+                        contractInfoList.sort(Comparator
+                                .comparing(ContractInfoVO::getSort, Comparator.nullsLast(Comparator.naturalOrder()))
+                                .thenComparing(
+                                        ContractInfoVO::getCreateTime,
+                                        Comparator.nullsLast(Comparator.reverseOrder())));
                     }
                 }
             }

+ 14 - 0
blade-service/blade-business/src/main/java/org/springblade/business/feignClient/ArchiveFileClientImpl.java

@@ -23,6 +23,7 @@ import org.springblade.core.log.exception.ServiceException;
 import org.springblade.manager.entity.ContractInfo;
 import org.springblade.manager.enums.StorageTypeEnum;
 import org.springblade.manager.feign.ContractClient;
+import org.springframework.beans.BeanUtils;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RestController;
 
@@ -68,6 +69,19 @@ public class ArchiveFileClientImpl implements ArchiveFileClient {
         this.iArchiveFileService.updateArchiveFileSort(vo.getList());
     }
 
+    @Override
+    public void batchUpdateInfo(ArchiveFileVO vo) {
+        List<ArchiveFileVO> list = vo.getList();
+        List<ArchiveFile> archiveFileList = list.stream()
+                .map(voen -> {
+                    ArchiveFile file = new ArchiveFile();
+                    BeanUtils.copyProperties(voen, file);
+                    return file;
+                })
+                .collect(Collectors.toList());
+        this.iArchiveFileService.saveOrUpdateBatch(archiveFileList);
+    }
+
     @Override
     public boolean updateArchiveFileByBoxName(Map<String, Object> jsons) {
         return this.iArchiveFileService.updateArchiveFileByBoxName(jsons);

+ 5 - 1
blade-service/blade-business/src/main/java/org/springblade/business/feignClient/InformationQueryClientImpl.java

@@ -15,6 +15,7 @@ import org.springblade.business.vo.QueryProcessDataVO;
 import org.springblade.common.utils.SnowFlakeUtil;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 
@@ -142,5 +143,8 @@ public class InformationQueryClientImpl implements InformationQueryClient {
         informationQueryMapper.deleteById(infoByWbsId);
     }
 
-
+    @Override
+    public List<InformationQuery> getInformationByContractIdAll(Long contractId) {
+        return informationQueryMapper.getInformationByContractIdAll(contractId);
+    }
 }

+ 13 - 54
blade-service/blade-business/src/main/java/org/springblade/business/feignClient/TrialCyAccessoriesClientImpl.java

@@ -17,6 +17,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * @author LHB
@@ -40,70 +41,28 @@ public class TrialCyAccessoriesClientImpl implements TrialCyAccessoriesClient {
     @Override
     public List<JSONObject> getTrialFilePdfRecord(String primaryKeyId, List<Integer> list) {
         //获取id
-        List<Map<String, Object>> trialFilePdfRecord = trialSelfInspectionRecordMapper.getTrialFilePdfRecord(primaryKeyId, list);
+        List<Map<String,Object>> trialFilePdfRecord = trialSelfInspectionRecordMapper.getTrialFilePdfRecord(primaryKeyId, list);
+        //
+        List<String> recordIds = trialFilePdfRecord.stream().map(f -> f.get("record_id").toString()).collect(Collectors.toList());
+        Map<String,Integer> map = trialFilePdfRecord.stream().collect(Collectors.toMap(f -> f.get("record_id").toString(), f -> Integer.valueOf(f.get("sort").toString())));
 
         if (CollectionUtil.isNotEmpty(trialFilePdfRecord)) {
 
-            //试验报告ids
-            List<Long> listOne = new ArrayList<>();
-            //第三方外委ids
-            List<Long> listTwo = new ArrayList<>();
-
-            for (Map<String, Object> stringObjectMap : trialFilePdfRecord) {
-
-                Integer type = (Integer) stringObjectMap.get("type");
-                Long recordId = (Long) stringObjectMap.get("record_id");
-                //试验报告
-                if (type == 11) {
-                    listOne.add(recordId);
-                } else {
-                    //第三方、外委
-                    listTwo.add(recordId);
-                }
-            }
-
             List<JSONObject> result = new ArrayList<>();
-
-            if (CollectionUtil.isNotEmpty(listOne)) {
-                List<TrialCyFinishTestReport> list1 = trialCyFinishTestReportService.list(Wrappers.<TrialCyFinishTestReport>lambdaQuery()
-                        .isNotNull(TrialCyFinishTestReport::getAssembleFile)
-                        .in(TrialCyFinishTestReport::getTaskId, listOne)
-                );
-
-                if (CollectionUtil.isNotEmpty(list1)) {
-                    list1.forEach(f -> {
-                        String[] split = f.getAssembleFile().split("/");
-                        JSONObject jsonObject = new JSONObject();
-                        jsonObject.put("id", f.getTaskId());
-                        jsonObject.put("name", split[split.length - 1]);
-                        jsonObject.put("contractId", f.getContractId());
-                        jsonObject.put("domainUrl", f.getAssembleFile());
-                        jsonObject.put("domainPdfUrl", f.getAssembleFile());
-                        jsonObject.put("tabId", primaryKeyId);
-                        jsonObject.put("extension", "pdf");
-                        //是否为试验关联的附件
-                        jsonObject.put("isTrial", true);
-                        result.add(jsonObject);
-                    });
-                }
-            }
-            if (CollectionUtil.isNotEmpty(listTwo)) {
-                List<TrialCyThirdReport> list1 = trialCyThirdReportService.list(Wrappers.<TrialCyThirdReport>lambdaQuery()
-                        .isNotNull(TrialCyThirdReport::getAssembleFile)
-                        .in(TrialCyThirdReport::getId, listTwo)
-                );
-
+            if (CollectionUtil.isNotEmpty(trialFilePdfRecord)) {
+                List<Map<String,Object>> list1 = trialCyFinishTestReportService.selectViewList(recordIds);
                 if (CollectionUtil.isNotEmpty(list1)) {
                     list1.forEach(f -> {
-                        String[] split = f.getAssembleFile().split("/");
+                        String[] split = f.get("assembleFile").toString().split("/");
                         JSONObject jsonObject = new JSONObject();
-                        jsonObject.put("id", f.getId());
+                        jsonObject.put("id", f.get("id"));
                         jsonObject.put("name", split[split.length - 1]);
-                        jsonObject.put("contractId", f.getContractId());
-                        jsonObject.put("domainUrl", f.getAssembleFile());
-                        jsonObject.put("domainPdfUrl", f.getAssembleFile());
+                        jsonObject.put("contractId", f.get("contractId"));
+                        jsonObject.put("domainUrl", f.get("assembleFile"));
+                        jsonObject.put("domainPdfUrl", f.get("assembleFile"));
                         jsonObject.put("tabId", primaryKeyId);
                         jsonObject.put("extension", "pdf");
+                        jsonObject.put("sort", map.get(f.get("id").toString()) == null ? 9999 : map.get(f.get("id").toString()));
                         //是否为试验关联的附件
                         jsonObject.put("isTrial", true);
                         result.add(jsonObject);

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

@@ -240,7 +240,6 @@
             )
         </if>
         order by
-        u.sort,
         <if test="vo.nodeIds != null and vo.nodeIds != ''">
             case
             when t.tree_sort regexp '^[a-zA-Z]' then 0  -- 字母开头的排在前面
@@ -249,7 +248,7 @@
             end,
             t.tree_sort,
         </if>
-        u.sort_num,u.create_time
+        u.archive_sort,u.sort,u.sort_num,u.create_time
         limit #{current}, #{size}
     </select>
 
@@ -434,7 +433,7 @@
           and (is_archive = 0 OR is_archive IS NULL)
           and (is_auto_file is null or is_auto_file != 1)
           and is_deleted = 0
-        order by sort,sort_num,create_time
+        order by archive_sort,sort,sort_num,create_time
     </select>
 
     <select id="getListByNodeIDName" resultMap="archiveFileResultMap">
@@ -444,7 +443,7 @@
           and (is_archive = 0 OR is_archive IS NULL)
           and (is_auto_file is null or is_auto_file != 1)
           and is_deleted = 0
-        order by sort,sort_num,create_time
+        order by archive_sort,sort,sort_num,create_time
     </select>
 
     <select id="getArchiveFileByArchiveID" resultMap="archiveFileResultMap">

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

@@ -152,4 +152,6 @@ public interface InformationQueryMapper extends BaseMapper<InformationQuery> {
     int addCheckPdfInfoByIds(@Param("ids") List<String> ids,@Param("classify") String classify);
 
     ChekPdfPaceVo getCheckPdfPaceInfo(@Param("contractId") String contractId, @Param("classify") String classify);
+
+    List<InformationQuery> getInformationByContractIdAll(@Param("contractId") Long contractId);
 }

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

@@ -988,7 +988,7 @@
         node_pdf_url
         from u_information_query
         where is_deleted = 0
-          and contract_id = #{contractId} and classify = #{classify} and status = 2 and is_deleted = 0;
+          and contract_id = #{contractId} and classify = #{classify} and status in(0,1,2) and is_deleted = 0;
     </select>
 
     <select id="getTabussTimeInfo" resultMap="tabBusstimeInfoResultMap">
@@ -1012,12 +1012,12 @@
     <update id="addCheckPdfInfoByNodeId" >
         update u_information_query a set a.chek_status=1
         where a.is_deleted = 0 and a.classify=#{classify} and a.wbs_id
-        in( select b.p_key_id from m_wbs_tree_contract b where b.is_deleted = 0 and b.ancestors_p_id like CONCAT(CONCAT('%', #{ids}), '%') and b.is_deleted = 0) and a.status in(1,2)
+        in( select b.p_key_id from m_wbs_tree_contract b where b.is_deleted = 0 and b.ancestors_p_id like CONCAT(CONCAT('%', #{ids}), '%') and b.is_deleted = 0) and a.status = 2
     </update>
 
     <update id="addCheckPdfInfoByIds">
         update u_information_query set chek_status=1
-        where is_deleted = 0 and classify=#{classify} and id in
+        where status = 2 and is_deleted = 0 and classify=#{classify} and id in
         <foreach collection="ids" item="id" open="(" separator="," close=")">
             #{id}
         </foreach>
@@ -1043,5 +1043,17 @@
           AND classify = #{classify,jdbcType=VARCHAR}
           AND chek_status IN (0,1,2,3)
     </select>
+    <select id="getInformationByContractIdAll" resultType="org.springblade.business.entity.InformationQuery">
+        select id,
+               wbs_id,
+               name,
+               IFNULL(IFNULL(e_visa_pdf_url,node_pdf_url),pdf_url) pdf_url,
+               classify,
+               sort
+        from u_information_query
+        where is_deleted = 0
+          and (pdf_url is not null or e_visa_pdf_url is not null or node_pdf_url is not null)
+          and contract_id = #{contractId} and classify in(1,2) and status in(0,1,2) and is_deleted = 0;
+    </select>
 
 </mapper>

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

@@ -44,7 +44,7 @@ public interface TrialClassificationTreeMapper extends BaseMapper<TrialClassific
 
 	Long selectAncestors(Long parentId);
 
-    List<TrialClassificationTreeVO> selectAllNode(@Param("id") Long id, @Param("projectId") Long projectId);
+    List<TrialClassificationTreeVO> selectAllNode(@Param("id") Long id, @Param("projectId") Long projectId,@Param("contractId")Long contractId);
 
 	void deleteByGroupType(@Param("groupType") Integer groupType);
 }

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

@@ -24,7 +24,7 @@
         select parent_id from u_trial_classification_tree where id = #{parentId} and is_deleted = 0
     </select>
     <select id="selectAllNode" resultType="org.springblade.business.vo.TrialClassificationTreeVO">
-        select tree.id,tree.parent_id,tree.project_id,tree.classification_name,(
+        select tree.id,tree.parent_id,tree.project_id,tree.contract_id,tree.classification_name,(
             SELECT
                 CASE WHEN count(1) > 0 THEN 1 ELSE 0 END
             FROM
@@ -33,7 +33,7 @@
                 parent_id = tree.id and is_deleted = 0
         ) AS "has_children"
         from u_trial_classification_tree tree
-        where tree.is_deleted = 0 and tree.project_id = #{projectId}
+        where tree.is_deleted = 0 and tree.project_id = #{projectId} and tree.contract_id = #{contractId}
         <if test="id!=null and id!=''">
             and tree.parent_id = #{id}
         </if>

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

@@ -18,7 +18,7 @@ public interface TrialCyAccessoriesMapper extends BaseMapper<TrialCyAccessories>
     Boolean clearTrialAssociation(@Param("nodeId") Long nodeId,
                                   @Param("recordId") Long recordId);
 
-    List<String> selectFilePdfList(@Param("nodeId") Long nodeId,
+    List<Long> selectFilePdfList(@Param("nodeId") Long nodeId,
                                    @Param("types") Integer... types);
 }
 

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

@@ -19,7 +19,7 @@
     <delete id="clearTrialAssociation">
         delete from u_trial_file_pdf_record where node_id = #{nodeId} and record_id=#{recordId}
     </delete>
-    <select id="selectFilePdfList" resultType="java.lang.String">
+    <select id="selectFilePdfList" resultType="java.lang.Long">
         select record_id from u_trial_file_pdf_record where node_id = #{nodeId} and type in
           <foreach collection="types" item="type" open="(" close=")" separator=",">
               #{type}

+ 7 - 0
blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyFinishTestReportMapper.java

@@ -7,6 +7,9 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import org.springblade.business.vo.ThirdReportVo;
 import org.springblade.business.vo.TrialCyThirdReportQueryVo;
 
+import java.util.List;
+import java.util.Map;
+
 /**
 * @author LHB
 * @description 针对表【u_trial_cy_finish_test_report(成渝-获取标段已完成(已签章完成)的检测报告)】的数据库操作Mapper
@@ -16,6 +19,10 @@ import org.springblade.business.vo.TrialCyThirdReportQueryVo;
 public interface TrialCyFinishTestReportMapper extends BaseMapper<TrialCyFinishTestReport> {
 
     Page<ThirdReportVo> myPage(Page<ThirdReportVo> page, @Param("query") TrialCyThirdReportQueryVo queryVo);
+
+    List<String> selectViewPdfList(@Param("ids") List<Long> ids);
+
+    List<Map<String,Object>> selectViewList(@Param("ids") List<String> ids);
 }
 
 

+ 32 - 14
blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyFinishTestReportMapper.xml

@@ -5,33 +5,51 @@
 <mapper namespace="org.springblade.business.mapper.TrialCyFinishTestReportMapper">
     <select id="myPage" resultType="org.springblade.business.vo.ThirdReportVo">
         select
-            task_id id,
-            contract_id contractId,
-            report_number reportNo,
-            report_date reportDate,
-            position projectPositionName,
-            case
-                when experiment_result = 1 then '合格'
-                else '不合格'
-            end detectionResultName,
+            id,
+            contractId,
+            reportNo,
+            reportDate,
+            projectPositionName,
+            detectionResultName,
         (select count(0) > 0 from u_trial_file_pdf_record where node_id = #{query.qualityTestPKeyId}  and type = 11 and record_id = t.id) isSelectedStatus
-        from u_trial_cy_finish_test_report t
+        from vw_u_trial_cy_decoment t
         <where>
+            and `type` in(1,2)
             <if test="query.contractId != null">
-                AND contract_id = #{query.contractId}
+                AND contractId = #{query.contractId}
             </if>
             <if test="query.nodeId != null">
-                AND exam_name_info_id = #{query.nodeId}
+                AND node_id = #{query.nodeId}
             </if>
             <if test="query.startTime != null">
-                AND report_date >= #{query.startTime}
+                AND reportDate >= #{query.startTime}
             </if>
             <if test="query.endTime != null">
-                AND report_date &lt;= #{query.endTime}
+                AND reportDate &lt;= #{query.endTime}
             </if>
             <if test="query.reportType != null">
                 AND cs = #{query.reportType}
             </if>
         </where>
     </select>
+    <select id="selectViewPdfList" resultType="java.lang.String">
+        select
+            assemble_file
+        from vw_u_trial_cy_decoment
+        where id in
+        <foreach item="item" collection="ids" separator="," open="(" close=")" index="">
+            #{item}
+        </foreach>
+    </select>
+    <select id="selectViewList" resultType="java.util.Map">
+        select
+            id,
+            contractId,
+            assemble_file as assembleFile
+        from vw_u_trial_cy_decoment
+        where assemble_file is not null and id in
+        <foreach item="item" collection="ids" separator="," open="(" close=")" index="">
+            #{item}
+        </foreach>
+    </select>
 </mapper>

+ 2 - 1
blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyTestTypeMapper.java

@@ -15,7 +15,8 @@ import java.util.List;
 public interface TrialCyTestTypeMapper extends BaseMapper<TrialCyTestType> {
 
     List<TrialCyTestType> getTree(@Param("projectId") Long projectId,
-                                  @Param("parentId") String parentId);
+                                  @Param("parentId") String parentId,
+                                  @Param("contractId") String contractId);
 }
 
 

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

@@ -15,9 +15,10 @@
     <select id="getTree" resultType="org.springblade.business.entity.TrialCyTestType">
         select
             <include refid="Base_sql"/>,
-            (select count(1) > 0 from u_trial_cy_test_type where father_id = t.id) has_children
-        from u_trial_cy_test_type t
+            (select count(1) > 0 from vw_u_trial_cy_tree where father_id = t.id and contract_id = #{contractId}) has_children
+        from vw_u_trial_cy_tree t
         where project_id = #{projectId}
+          and contract_id = #{contractId}
           and father_id = #{parentId}
         order by order_index
     </select>

+ 12 - 13
blade-service/blade-business/src/main/java/org/springblade/business/mapper/TrialCyThirdReportMapper.xml

@@ -6,30 +6,29 @@
     <select id="myPage" resultType="org.springblade.business.vo.ThirdReportVo">
         select
             id,
-            contract_id contractId,
-            report_no reportNo,
-            report_date reportDate,
-            project_part projectPositionName,
-            case when is_qualified = 1 then '合格'
-                else '不合格'
-            end detectionResultName,
+            contractId,
+            reportNo,
+            reportDate,
+            projectPositionName,
+            detectionResultName,
         (select count(0) > 0 from u_trial_file_pdf_record where node_id = #{query.qualityTestPKeyId}  and type in(12,13) and record_id = t.id) isSelectedStatus
-        from u_trial_cy_third_report t
+        from vw_u_trial_cy_decoment t
         <where>
+            AND `type` in(3,4)
             <if test="query.contractId != null">
-                AND contract_id = #{query.contractId}
+                AND contractId = #{query.contractId}
             </if>
             <if test="query.type != null">
-                AND `third_type` = #{query.type}
+                AND `type` = #{query.type}
             </if>
             <if test="query.startTime != null">
-                AND report_date >= #{query.startTime}
+                AND reportDate >= #{query.startTime}
             </if>
             <if test="query.endTime != null">
-                AND report_date &lt;= #{query.endTime}
+                AND reportDate &lt;= #{query.endTime}
             </if>
             <if test="query.nodeId != null">
-                AND exam_name_info_id = #{query.nodeId}
+                AND node_id = #{query.nodeId}
             </if>
         </where>
     </select>

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

@@ -109,7 +109,7 @@
         </where>
     </select>
     <select id="getTrialFilePdfRecord" resultType="java.util.Map">
-        select record_id,type from u_trial_file_pdf_record where node_id = #{nodeId} and `type` in
+        select record_id,IFNULL(sort,9999) sort from u_trial_file_pdf_record where node_id = #{nodeId} and `type` in
        <foreach collection="types" item="type" open="(" close=")" separator=",">
            #{type}
        </foreach>

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

@@ -19,7 +19,7 @@
 
 
     <select id="selectTrialSystemDockingPage" resultMap="trialSystemDockingResultMap">
-        select id,project_id,report_name,report_number,unit_name,classification_id,specification,report_type,purpose_location,report_date,file_url,person_in_charge from u_trial_system_docking where is_deleted = 0 and project_id=#{vo.projectId}
+        select id,project_id,report_name,report_number,unit_name,classification_id,specification,report_type,purpose_location,report_date,file_url,person_in_charge from u_trial_system_docking where is_deleted = 0 and project_id=#{vo.projectId} and contract_id=#{vo.contractId}
         <if test="vo.reportName != null and vo.reportName != ''">
             and report_name like concat('%',#{vo.reportName},'%')
         </if>

+ 36 - 58
blade-service/blade-business/src/main/java/org/springblade/business/scheduled/ChenYuTestScheduled.java

@@ -101,6 +101,7 @@ public class ChenYuTestScheduled {
     private CloseableHttpClient httpClient;
     private static final String TOKEN_REDIS_KEY = "blade:cqcy:token";
     private static final String PROJECT_CODE = "cqcyfx";
+    private static final String CONTRACT_CODE = "CYTJ03";
     private static Long PROJECT_ID = null;
     private static final String BASE_URL = "https://apicqcyfx.qdm123.com";
     private final Map<String, Long> contractCodeMap = new ConcurrentHashMap<>();
@@ -209,62 +210,20 @@ public class ChenYuTestScheduled {
         if (!SystemUtils.isLinux()) {
             return;
         }
-
-        contractCodeMap.clear();
-        String token = getToken();
-        ensureProjectIdInitialized();
-
-        if (token == null || PROJECT_ID == null) {
-            log.error("Invalid token or project ID");
-            return;
-        }
-
         try {
-            //获取合同段列表接口
-            Result result = getContractList();
-            if (result == null || result.getState() != 1) {
-                log.error("Failed to get contract sections: {}",
-                        result != null ? result.getMessage() : "No response");
-                return;
-            }
-
-            JSONArray data = (JSONArray) result.getData();
-            if (CollectionUtil.isEmpty(data)) {
-                log.warn("No contract sections found");
-                return;
-            }
-
-            List<String> codes = new ArrayList<>();
-            for (int i = 0; i < data.size(); i++) {
-                JSONObject obj = data.getJSONObject(i);
-                String name = obj.getString("Name");
-                if (StringUtil.isNotBlank(name)) {
-                    codes.add(name);
-                }
-            }
-
-            if (CollectionUtil.isEmpty(codes)) {
-                log.info("No valid contract codes found");
-                return;
-            }
-
             // 构建参数化查询
-            String placeholders = String.join(",", Collections.nCopies(codes.size(), "?"));
-            String sql = "SELECT * FROM m_contract_info WHERE contract_number IN (" + placeholders + ")";
-
+            String sql = "SELECT id FROM m_contract_info WHERE contract_number = '" + CONTRACT_CODE + "'";
             List<ContractInfo> contracts = jdbcTemplate.query(
                     sql,
-                    codes.toArray(),
                     new BeanPropertyRowMapper<>(ContractInfo.class)
             );
-
-            for (ContractInfo contract : contracts) {
-                contractCodeMap.put(contract.getContractNumber(), contract.getId());
+            if(CollectionUtil.isNotEmpty(contracts)){
+                ContractInfo contractInfo = contracts.get(0);
+                contractCodeMap.put(CONTRACT_CODE, contractInfo.getId());
             }
-
             log.info("Loaded {} contract mappings", contractCodeMap.size());
         } catch (Exception e) {
-            log.error("Error processing contract sections", e);
+            log.error(CONTRACT_CODE + " 合同段编码不存在", e);
         }
     }
 
@@ -294,6 +253,8 @@ public class ChenYuTestScheduled {
                     .eq(TrialCyFinishTestReport::getContractId, contractId));
             //等会准备删除的历史数据
             List<Long> ids = list.stream().map(TrialCyFinishTestReport::getId).collect(Collectors.toList());
+            //获取旧数据 task_id 与 id的映射关系
+            Map<Integer, Long> taskIdMap = list.stream().collect(Collectors.toMap(TrialCyFinishTestReport::getTaskId, TrialCyFinishTestReport::getId));
 
             int pageIndex = 0;
             final int pageSize = 100;
@@ -333,7 +294,12 @@ public class ChenYuTestScheduled {
 
                     List<TrialCyFinishTestReport> reports = data.toJavaList(TrialCyFinishTestReport.class);
                     for (TrialCyFinishTestReport report : reports) {
-                        Long id = SnowFlakeUtil.getId();
+                        //数据太长且不需要
+                        report.setTestParamInfo(null);
+                        Long id = taskIdMap.get(report.getTaskId());
+                        if(id == null){
+                            id = SnowFlakeUtil.getId();
+                        }
                         report.setId(id);
                         report.setContractId(contractId);
                         //处理boolean值
@@ -350,9 +316,10 @@ public class ChenYuTestScheduled {
                         //处理附件
                         List<TrialCyAccessories> accessories = report.getAccessories();
                         if (CollectionUtil.isNotEmpty(accessories)) {
+                            Long finalId = id;
                             accessories.forEach(f -> {
                                 f.setId(SnowFlakeUtil.getId());
-                                f.setReportId(id);
+                                f.setReportId(finalId);
                                 if (StringUtil.isNotBlank(f.getFilePath())) {
                                     urls.add(f.getFilePath());
                                 }
@@ -382,8 +349,6 @@ public class ChenYuTestScheduled {
                         }
                     }
                     if (CollectionUtil.isNotEmpty(ids)) {
-                        trialCyFinishTestReportService.removeBatchByIds(ids);
-
                         List<String> fileUrls = list.stream().map(TrialCyFinishTestReport::getAssembleFile).filter(StringUtil::isNotBlank).collect(Collectors.toList());
                         if(CollectionUtil.isNotEmpty(fileUrls)){
                             //删除组合文件
@@ -391,8 +356,12 @@ public class ChenYuTestScheduled {
                                 String pdfName = f.split("upload")[1];
                                 this.newIOSSClient.removeFile("upload" + pdfName);
                             });
+                            ids.clear();
                         }
                     }
+                    //获取taskId,把之前的taskId删除
+                    List<Integer> taskIds = reports.stream().map(TrialCyFinishTestReport::getTaskId).collect(Collectors.toList());
+                    trialCyFinishTestReportService.remove(Wrappers.<TrialCyFinishTestReport>lambdaQuery().in(TrialCyFinishTestReport::getTaskId,taskIds));
 
                     trialCyFinishTestReportService.saveBatch(reports);
                     hasMore = reports.size() >= pageSize;
@@ -434,7 +403,8 @@ public class ChenYuTestScheduled {
                     .eq(TrialCyThirdReport::getContractId, contractId));
             //等会要删除的id
             List<Long> ids = list.stream().map(TrialCyThirdReport::getPKeyId).collect(Collectors.toList());
-
+            //获取旧数据 id 和 pKId的映射关系
+            Map<String, Long> linkMap = list.stream().collect(Collectors.toMap(TrialCyThirdReport::getId, TrialCyThirdReport::getPKeyId));
 
             int pageIndex = 0;
             final int pageSize = 100;
@@ -475,7 +445,9 @@ public class ChenYuTestScheduled {
 
                         List<TrialCyThirdReport> reports = data.toJavaList(TrialCyThirdReport.class);
                         for (TrialCyThirdReport report : reports) {
-
+                            //数据太长 忽略
+                            report.setTestStandard(null);
+                            report.setTestConclusion(null);
                             List<String> urls = new ArrayList<>();
                             if (StringUtil.isNotBlank(report.getReportDocFilePath())) {
                                 urls.add(report.getReportDocFilePath());
@@ -483,8 +455,11 @@ public class ChenYuTestScheduled {
                             if (StringUtil.isNotBlank(report.getRecordDocFilePath())) {
                                 urls.add(report.getRecordDocFilePath());
                             }
-
-                            Long id = SnowFlakeUtil.getId();
+                            //如果能通过id找到旧pkid 就使用旧pkid
+                            Long id = linkMap.get(report.getId());
+                            if(id == null){
+                                id = SnowFlakeUtil.getId();
+                            }
                             report.setPKeyId(id);
                             report.setContractId(contractId);
                             //报告类型
@@ -496,9 +471,10 @@ public class ChenYuTestScheduled {
                             //处理附件
                             List<TrialCyAccessories> accessories = report.getAccessories();
                             if (CollectionUtil.isNotEmpty(accessories)) {
+                                Long finalId = id;
                                 accessories.forEach(f -> {
                                     f.setId(SnowFlakeUtil.getId());
-                                    f.setReportId(id);
+                                    f.setReportId(finalId);
 
                                     if (StringUtil.isNotBlank(f.getFilePath())) {
                                         urls.add(f.getFilePath());
@@ -531,7 +507,6 @@ public class ChenYuTestScheduled {
                         }
                         //删除旧数据
                         if (CollectionUtil.isNotEmpty(ids)) {
-                            trialCyThirdReportService.removeBatchByIds(ids);
                             List<String> fileUrls = list.stream().map(TrialCyThirdReport::getAssembleFile).filter(StringUtil::isNotBlank).collect(Collectors.toList());
                             if(CollectionUtil.isNotEmpty(fileUrls)){
                                 //删除组合文件
@@ -539,9 +514,11 @@ public class ChenYuTestScheduled {
                                     String pdfName = f.split("upload")[1];
                                     this.newIOSSClient.removeFile("upload" + pdfName);
                                 });
+                                ids.clear();
                             }
                         }
-
+                        List<String> collect = reports.stream().map(TrialCyThirdReport::getId).collect(Collectors.toList());
+                        trialCyThirdReportService.remove(Wrappers.<TrialCyThirdReport>lambdaQuery().in(TrialCyThirdReport::getId, collect));
                         //添加新数据
                         trialCyThirdReportService.saveBatch(reports);
                         hasMore = reports.size() >= pageSize;
@@ -593,6 +570,7 @@ public class ChenYuTestScheduled {
             for (TrialCyTestType type : testTypes) {
                 type.setPKeyId(SnowFlakeUtil.getId());
                 type.setProjectId(PROJECT_ID);
+                type.setContractId(contractCodeMap.get(CONTRACT_CODE));
                 type.setFatherId(type.getFatherId() == null || type.getFatherId().isEmpty() ? "0" : type.getFatherId());
             }
             //先删除旧数据

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

@@ -59,6 +59,7 @@ public interface IArchiveFileService extends BaseService<ArchiveFile> {
 
     void updateArchiveFileSort(List<ArchiveFileVO> list);
 
+
     boolean updateArchiveFileByBoxName(Map<String, Object> jsons);
 
     String isBoxName(String boxName);

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

@@ -57,7 +57,7 @@ public interface ITaskService extends BaseService<Task> {
     /**
      * 批量审批
      */
-    void batchCompleteApprovalTask(List<TaskApprovalVO> taskApprovalVOS) throws FileNotFoundException;
+    Boolean batchCompleteApprovalTask(List<TaskApprovalVO> taskApprovalVOS) throws FileNotFoundException;
 
     /**
      * 启动流程

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

@@ -48,7 +48,7 @@ public interface ITrialClassificationTreeService extends BaseService<TrialClassi
     boolean deleteById(Long id);
 
 
-    List<TrialClassificationTreeVO> selectAllNode(Long id, Long projectId);
+    List<TrialClassificationTreeVO> selectAllNode(Long id, Long projectId,Long contractId);
 
 	void deleteByGroupType(Integer groupType);
 }

+ 8 - 0
blade-service/blade-business/src/main/java/org/springblade/business/service/TrialCyFinishTestReportService.java

@@ -7,6 +7,9 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import org.springblade.business.vo.ThirdReportVo;
 import org.springblade.business.vo.TrialCyThirdReportQueryVo;
 
+import java.util.List;
+import java.util.Map;
+
 /**
 * @author LHB
 * @description 针对表【u_trial_cy_finish_test_report(成渝-获取标段已完成(已签章完成)的检测报告)】的数据库操作Service
@@ -16,4 +19,9 @@ public interface TrialCyFinishTestReportService extends IService<TrialCyFinishTe
 
     Page<ThirdReportVo> myPage(Page<ThirdReportVo> objectPage,
                                TrialCyThirdReportQueryVo queryVo);
+
+    List<String> selectViewPdfList(List<Long> longList);
+
+    List<Map<String,Object>> selectViewList(List<String> trialFilePdfRecord);
+
 }

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

@@ -15,7 +15,7 @@ import java.util.List;
 public interface TrialCyService {
     Boolean isCyAndTestModule(Long projectId, Long contractId);
 
-    List<TrialCyTestType> getTree(Long projectId, String parentId);
+    List<TrialCyTestType> getTree(Long projectId, String parentId, String contractId);
 
     Page<ThirdReportVo> getTrialDetectionReport(TrialCyThirdReportQueryVo queryVo);
 

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

@@ -12,5 +12,5 @@ import java.util.List;
 */
 public interface TrialCyTestTypeService extends IService<TrialCyTestType> {
 
-    List<TrialCyTestType> getTree(Long projectId, String parentId);
+    List<TrialCyTestType> getTree(Long projectId, String parentId, String contractId);
 }

+ 5 - 3
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/EntrustInfoServiceImpl.java

@@ -287,9 +287,11 @@ public class EntrustInfoServiceImpl extends BaseServiceImpl<EntrustInfoMapper, E
                 if(entrustInfo.getStatus()!=2&&entrustInfo.getStatus()!=3){
                     throw new ServiceException("该委托单不能废除"+entrustInfo.getEntrustNo());
                 }
-                entrustInfo.setEntrustEPdf(null);
-                entrustInfo.setStatus(1);
-                entrustInfoMapper.updateById(entrustInfo);
+				// mybatis plus 默认的updateById 会跳过null值字段, 改为 lambda 方式
+                entrustInfoMapper.update(null,Wrappers.<EntrustInfo>lambdaUpdate()
+						.set(EntrustInfo::getStatus, 1)
+						.set(EntrustInfo::getEntrustEPdf, null)
+						.eq(EntrustInfo::getId, Long.parseLong(i)));
             }
             List<InformationQuery> queryList = this.informationQueryService.list(Wrappers.<InformationQuery>lambdaQuery().in(InformationQuery::getId, Arrays.asList(ids)));
             if (queryList.size() == 0) {

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

@@ -82,6 +82,7 @@ public class InformationQueryServiceImpl extends BaseServiceImpl<InformationQuer
     private final ContractClient contractClient;
 
     private final JdbcTemplate jdbcTemplate;
+    private final IOperationLogService operationLogService;
 
     @Autowired
     StringRedisTemplate RedisTemplate;
@@ -1134,8 +1135,33 @@ public class InformationQueryServiceImpl extends BaseServiceImpl<InformationQuer
         }else{
             return R.fail("type有误,无法处理该业务");
         }
+        List<InformationQuery> list = this.list(Wrappers.<InformationQuery>lambdaQuery().in(InformationQuery::getId, strList));
+        recordResignLog("电签检测", ids, list, new HashMap<String, Object>() {{
+            put("ids", ids);
+            put("classify", classify);
+            put("type", type);
+        }}, list.get(0).getProjectId()+"", list.get(0).getContractId()+"");
         return R.success("操作成功");
     }
+    public void recordResignLog(String module, String businessIds, Object data, Object requestData, String projectId, String contractId){
+        try {
+            OperationLog resignLog = new OperationLog();
+            resignLog.setProjectId(StringUtil.isNumeric(projectId) ? Long.parseLong(projectId) : null);
+            resignLog.setContractId(StringUtil.isNumeric(contractId) ? Long.parseLong(contractId) : null);
+            resignLog.setOperationType(33);
+            resignLog.setOperationModule(module);
+            resignLog.setOperationContent(JSON.toJSONString(requestData));
+            resignLog.setSaveData(JSON.toJSONString(data));
+            resignLog.setOperationTime(DateUtil.formatTime(DateUtil.now()));
+            resignLog.setOperationView("");
+            resignLog.setBusinessId(businessIds);
+            resignLog.setCreateUser(AuthUtil.getUserId());
+            resignLog.setOperationAccount(AuthUtil.getNickName());
+            operationLogService.save(resignLog);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
     @Override
     public ChekPdfPaceVo getCheckPdfPaceInfo(String contractId, String classify) {
        /* ChekPdfPaceVo da = new ChekPdfPaceVo();

+ 202 - 80
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TaskServiceImpl.java

@@ -1,9 +1,10 @@
 package org.springblade.business.service.impl;
 
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
-import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.AllArgsConstructor;
@@ -20,7 +21,6 @@ import org.springblade.business.feignClient.WbsTreeContractStatisticsClientImpl;
 import org.springblade.business.mapper.TaskMapper;
 import org.springblade.business.mapper.TrialSelfInspectionRecordMapper;
 import org.springblade.business.service.*;
-import org.springblade.business.sync.TaskSync;
 import org.springblade.business.utils.FileUtils;
 import org.springblade.business.vo.*;
 import org.springblade.common.constant.CommonConstant;
@@ -29,15 +29,12 @@ import org.springblade.common.utils.SnowFlakeUtil;
 import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.mp.base.BaseServiceImpl;
 import org.springblade.core.oss.model.BladeFile;
-import org.springblade.core.redis.cache.BladeRedis;
+import org.springblade.core.secure.BladeUser;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.secure.utils.SecureUtil;
 import org.springblade.core.tool.api.R;
 
-import org.springblade.core.tool.utils.DateUtil;
-import org.springblade.core.tool.utils.Func;
-import org.springblade.core.tool.utils.ObjectUtil;
-import org.springblade.core.tool.utils.ResourceUtil;
+import org.springblade.core.tool.utils.*;
 import org.springblade.evisa.feign.EVisaClient;
 import org.springblade.evisa.redissionUtil.DistributedRedisLock;
 import org.springblade.evisa.vo.EVisaTaskApprovalVO;
@@ -66,7 +63,6 @@ import org.springframework.data.redis.core.StringRedisTemplate;
 import org.springframework.jdbc.core.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.SingleColumnRowMapper;
-import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -134,6 +130,7 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
     private final WbsTreePrivateClient wbsTreePrivateClient;
     private final TrialSelfInspectionRecordMapper trialSelfInspectionRecordMapper;
     private final WbsTreeContractStatisticsClientImpl wbsTreeContractStatisticsClient;
+    private final IOperationLogService operationLogService;
     //超级管理员的角色id
     private final String SUPER_ADMIN_ROLE_ID = "1123598816738675201";
     //泓创智诚公司的部门id
@@ -625,7 +622,7 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
      * @throws FileNotFoundException
      */
     @Override
-    public void batchCompleteApprovalTask(List<TaskApprovalVO> taskApprovalVOS) {
+    public Boolean batchCompleteApprovalTask(List<TaskApprovalVO> taskApprovalVOS) {
         Long userId = AuthUtil.getUserId();
         String nickName = AuthUtil.getNickName();
         // 批量审批接口
@@ -673,7 +670,7 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                         e.printStackTrace();
                     }
                 }
-                this.taskBatchService.saveBatch(taskList);
+               return this.taskBatchService.saveBatch(taskList);
             } else if (taskAppr.getFlag().equals("NO")) { //废除
                 Set<String> taskIds = taskApprovalVOS.stream().map(TaskApprovalVO::getTaskId).collect(Collectors.toSet());
                 List<Task> tasks = this.listByIds(taskIds);
@@ -766,8 +763,10 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                     }
                 }
                 wbsTreeContractStatisticsClient.updateInformationQueryStatusByTaskId(String.join(",", taskIds));
+                return true;
             }
         }
+        return false;
     }
 
 
@@ -1214,6 +1213,13 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                                 .eq(TaskParallel::getProcessInstanceId, task.getProcessInstanceId()));
                     }
                 }
+                recordResignLog("re-sign(日志)", formDataIds, contractLogList, new HashMap<String, Object>() {{
+                    put("logids", logids);
+                    put("type", type);
+                    put("logPkeyId", logPkeyId);
+                    put("nodePrimaryKeyId", nodePrimaryKeyId);
+                    put("contractId", contractId);
+                }}, null, contractId, request);
             } catch (Exception e) {
                 e.printStackTrace();
                 throw new ServiceException("重新保存PDF信息失败,原因:" + e.getMessage());
@@ -1242,7 +1248,9 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
             Map<String, List<TaskParallel>> finalTaskParallelGroupMap = taskParallelGroupMap;
             //获取每条任务对应的节点信息
             List<String> dataIdList = taskList.stream().map(Task::getFormDataId).filter(ObjectUtil::isNotEmpty).collect(Collectors.toList());
-            Map<String, String> queryMap = jdbcTemplate.query("select * from u_information_query where id in(" + StringUtils.join(dataIdList, ",") + ")", new BeanPropertyRowMapper<>(InformationQuery.class)).stream().collect(Collectors.toMap(l -> l.getId() + "", l -> l.getWbsId() + ""));
+            //Map<String, String> queryMap = jdbcTemplate.query("select * from u_information_query where id in(" + StringUtils.join(dataIdList, ",") + ")", new BeanPropertyRowMapper<>(InformationQuery.class)).stream().collect(Collectors.toMap(l -> l.getId() + "", l -> l.getWbsId() + ""));
+            List<InformationQuery> list = informationQueryService.list(new LambdaQueryWrapper<InformationQuery>().in(InformationQuery::getId, dataIdList));
+            Map<String, String> queryMap=list.stream().collect(Collectors.toMap(l -> l.getId() + "", l -> l.getWbsId() + ""));
             Map<String, String> typeMap = jdbcTemplate.query("select * from u_information_query where id in(" + StringUtils.join(dataIdList, ",") + ")", new BeanPropertyRowMapper<>(InformationQuery.class)).stream().collect(Collectors.toMap(l -> l.getId() + "", l -> l.getClassify() + ""));
 
             try {
@@ -1315,6 +1323,7 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                     String taskIds = StringUtils.join(taskList, ",");
                     removeUserAndName(taskIds, userId, userName);
                 }*/
+                recordResignLog("re-sign(试验)", StringUtils.join(dataIdList, ","), list, dto, dto.getProjectId(), null, request);
             } catch (Exception e) {
                 e.printStackTrace();
                 throw new ServiceException("重新保存PDF信息失败,原因:" + e.getMessage());
@@ -1348,6 +1357,8 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
             }
             Map<String, List<TaskParallel>> finalTaskParallelGroupMap = taskParallelGroupMap;
             try {
+                String entrustIds = dtos.stream().map(ReSigningEntrustDto::getEntrustId).collect(Collectors.joining(","));
+                List<EntrustInfo> entrustInfos = jdbcTemplate.query("select * from u_entrust_info where id in ( " + entrustIds + " )", new BeanPropertyRowMapper<>(EntrustInfo.class));
                 for (int i = 0; i < taskList.size(); i++) {
                     ReSigningEntrustDto dto = longMap.get(taskList.get(i).getId());
                     R result = new R();
@@ -1380,7 +1391,7 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                         if (!b) {
                             throw new ServiceException("清空电签PDF失败");
                         }
-                        result.setData("成功");
+                        result.setMsg("操作成功");
                     }
                     //重新电签
                     if (result != null && "操作成功".equals(result.getMsg())) {
@@ -1419,6 +1430,7 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                                 .eq(TaskParallel::getProcessInstanceId, taskList.get(i).getProcessInstanceId()));
                     }
                 }
+                this.recordResignLog("re-sign(委托单)",  entrustIds, entrustInfos, dtos,taskList.get(0).getProjectId() , taskList.get(0).getContractId(), request);
             } catch (Exception e) {
                 e.printStackTrace();
                 throw new ServiceException("重新保存PDF信息失败,原因:" + e.getMessage());
@@ -1489,26 +1501,8 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
             vo.setStartTime(DateUtil.format(nowTime, "yyyy-MM-dd"));
             vo.setEndTime(DateUtil.format(DateUtils.addDays(nowTime, vo.getRestrictDay()), "yyyy-MM-dd"));
 
-//            Query query = new Query();
-//            query.setCurrent(1);
-//            query.setSize(999);
-            //获取流程
-//            List<FlowProcessVO> modeProcessVOS = this.newFlowClient.startFlowList("", query, 1);
-//            if (modeProcessVOS == null || modeProcessVOS.size() == 0) {
-//                return false;
-//            }
             //获取当中的审批流程
             String taskFlowId = SnowFlakeUtil.getId() + "";
-//            for (FlowProcessVO processVO : modeProcessVOS) {
-//                if ("approval".equals(processVO.getKey())) {
-//                    taskFlowId = processVO.getId();
-//                    break;
-//                }
-//            }
-//            //如果没有对应流程,直接返回
-//            if (StringUtils.isEmpty(taskFlowId)) {
-//                return false;
-//            }
             //获取选择的固定流程
             List<FixedFlowLink> links = new ArrayList<>();
             if (Long.valueOf("0").equals(vo.getFixedFlowId())) {
@@ -1527,33 +1521,15 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                 }
             }
 
-            //启动主流程
-//            R<BladeFlow> result = this.flowClient.startProcessInstanceById(taskFlowId, FlowUtil.getBusinessKey(businessTable, String.valueOf(vo.getId())),
-//                    Kv.create().set(ProcessConstant.TASK_VARIABLE_CREATE_USER, AuthUtil.getUserName()).set("taskUser", TaskUtil.getTaskUser("")));
-//            if (result.isSuccess()) {
-//                log.debug("主流程已启动,流程ID:" + result.getData().getProcessInstanceId());
-//                //拼接并行的实例ID
-//                vo.setProcessInstanceId(result.getData().getProcessInstanceId());
-//            } else {
-//                throw new ServiceException("开启主流程失败");
-//            }
             vo.setProcessInstanceId(SnowFlakeUtil.getId() + "");
 
             //根据所选择的固定流程所含有的环节发起审批任务
             List<TaskParallel> taskParallelArray = new ArrayList<>();
-            for (FixedFlowLink link : links) {
-                //启动并行流程
-//                Kv variables = Kv.create()
-//                        //下一步流程审批人
-//                        .set("taskUser", TaskUtil.getTaskUser(link.getFixedFlowLinkUser().toString()));
-//                R<BladeFlow> linkResult = this.flowClient.startProcessInstanceById(taskFlowId, FlowUtil.getBusinessKey(businessTable, String.valueOf(vo.getId())), variables);
-//                if (linkResult.isSuccess()) {
-//                    log.debug("并行流程已启动,流程ID:" + linkResult.getData().getProcessInstanceId());
-//                    taskParallelArray.add(new TaskParallel(vo.getProcessInstanceId(), linkResult.getData().getProcessInstanceId(), link.getFixedFlowLinkUser().toString(), link.getFixedFlowLinkUserName()));
-//                } else {
-//                    throw new ServiceException("开启并行流程失败");
-//                }
-                taskParallelArray.add(new TaskParallel(vo.getProcessInstanceId(), SnowFlakeUtil.getId() + "", link.getFixedFlowLinkUser().toString(), link.getFixedFlowLinkUserName()));
+            for (int i = 0, linksSize = links.size(); i < linksSize; i++) {
+                FixedFlowLink link = links.get(i);
+                TaskParallel parallel = new TaskParallel(vo.getProcessInstanceId(), SnowFlakeUtil.getId() + "", link.getFixedFlowLinkUser().toString(), link.getFixedFlowLinkUserName());
+                parallel.setSort(link.getFixedFlowBranchSort() == null ? i : link.getFixedFlowBranchSort());
+                taskParallelArray.add(parallel);
             }
             //设置流程信息
             vo.setProcessDefinitionId(taskFlowId);
@@ -1994,6 +1970,8 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                     .set(InformationQuery::getSaveAgain, 0)
                     .ne(InformationQuery::getSaveAgain, 1)
                     .in(InformationQuery::getId, newIds));
+            List<InformationQuery> list = informationQueryService.list(new LambdaQueryWrapper<>(InformationQuery.class).in(InformationQuery::getId, newIds));
+            recordResignLog("save-again", StringUtils.join(newIds, ","), list, dtos, dtos.get(0).getProjectId()+"", dtos.get(0).getContractId()+"", null);
         }
         return R.success("操作成功");
     }
@@ -2030,6 +2008,7 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
             Map<String, List<TaskParallel>> finalTaskParallelGroupMap = taskParallelGroupMap;
             //获取每条任务对应的节点信息
             List<String> dataIdList = taskList.stream().map(Task::getFormDataId).filter(ObjectUtil::isNotEmpty).collect(Collectors.toList());
+            List<InformationQuery> list = informationQueryService.list(Wrappers.<InformationQuery>lambdaQuery().in(InformationQuery::getId, dataIdList));
             Map<String, String> queryMap = jdbcTemplate.query("select * from u_information_query where id in(" + StringUtils.join(dataIdList, ",") + ")", new BeanPropertyRowMapper<>(InformationQuery.class)).stream().collect(Collectors.toMap(l -> l.getId() + "", l -> l.getWbsId() + ""));
             Map<String, String> typeMap = jdbcTemplate.query("select * from u_information_query where id in(" + StringUtils.join(dataIdList, ",") + ")", new BeanPropertyRowMapper<>(InformationQuery.class)).stream().collect(Collectors.toMap(l -> l.getId() + "", l -> l.getClassify() + ""));
 
@@ -2038,22 +2017,45 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                     R result = new R();
                     jdbcTemplate.execute("DELETE from u_task_batch where json_data like '%" + task.getId() + "%'");
                     boolean b = false;
-                    if (type == 1) {
-                        b = informationQueryService.update(new LambdaUpdateWrapper<InformationQuery>()
-                                        .eq(InformationQuery::getId, task.getFormDataId())
-                                        .set(InformationQuery::getEVisaPdfUrl, null)
-//                                .set(InformationQuery::getPdfUrl, null)
-                        );
-                    } else {
-                        if (task.getApprovalType() == 3) {
-                            b = contractLogService.update(new LambdaUpdateWrapper<ContractLog>()
-                                    .eq(ContractLog::getId, task.getFormDataId())
-                                    .set(ContractLog::getEVisaPdfUrl, null));
-                            if (!b) {
-                                jdbcTemplate.update("update u_task set is_deleted=1 where id=" + task.getId());
-                                return;
+
+                    //是否恢复pdf
+                    Boolean isRestorePdf = false;
+                    //当前节点的电签pdf
+                    String eVisaPdfUrl = "";
+                    String pdfUrl = "";
+                    if(type == 1){
+                        //当前节点的电签pdf
+                        InformationQuery byId = informationQueryService.getById(task.getFormDataId());
+                        if(byId != null){
+                            eVisaPdfUrl = byId.getEVisaPdfUrl();
+                            pdfUrl = byId.getPdfUrl();
+                        }
+                         b = informationQueryService.update(new LambdaUpdateWrapper<InformationQuery>()
+                                .eq(InformationQuery::getId, task.getFormDataId())
+                                .set(InformationQuery::getEVisaPdfUrl, null)
+                                .set(InformationQuery::getPdfUrl, null)
+                         );
+                    }else {
+                        if(task.getApprovalType()==3){
+                            //当前节点的电签pdf
+                            ContractLog byId = contractLogService.getById(task.getFormDataId());
+                            if(byId != null){
+                                eVisaPdfUrl = byId.getEVisaPdfUrl();
+                            }
+
+                            b=contractLogService.update(new LambdaUpdateWrapper<ContractLog>()
+                               .eq(ContractLog::getId,task.getFormDataId())
+                               .set(ContractLog::getEVisaPdfUrl,null));
+                           if(!b){
+                               jdbcTemplate.update("update u_task set is_deleted=1 where id="+task.getId());
+                               return;
+                           }
+                        }else {
+                            //当前节点的电签pdf
+                            InformationQuery byId = informationQueryService.getById(task.getFormDataId());
+                            if(byId != null){
+                                eVisaPdfUrl = byId.getEVisaPdfUrl();
                             }
-                        } else {
                             b = informationQueryService.update(new LambdaUpdateWrapper<InformationQuery>()
                                     .eq(InformationQuery::getId, task.getFormDataId())
                                     .set(InformationQuery::getEVisaPdfUrl, null));
@@ -2074,7 +2076,15 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                             String sql = "select type from u_information_query where id=" + task.getFormDataId();
                             Integer InformationType = jdbcTemplate.queryForObject(sql, new SingleColumnRowMapper<>(Integer.class));
                             if (InformationType == 1) {
-                                result = this.saveNodePdf(typeMap.get(task.getFormDataId()), queryMap.get(task.getFormDataId()), contractId, projectId, header);
+                                try {
+                                    result = this.saveNodePdf(typeMap.get(task.getFormDataId()), queryMap.get(task.getFormDataId()), contractId, projectId, header);
+                                    //恢复pdf
+                                    if(result.getCode()!=200){
+                                        isRestorePdf = true;
+                                    }
+                                } catch (Exception e) {
+                                    isRestorePdf = true;
+                                }
                             } else {
                                 TrialResignDto dto = new TrialResignDto();
                                 dto.setType(1);
@@ -2094,14 +2104,23 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                             String sql = "SELECT * from u_entrust_info where id=(select wbs_id from u_information_query where id=" + task.getFormDataId() + ")";
                             EntrustInfo info = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(EntrustInfo.class));
                             ReSigningEntrustDto dto = new ReSigningEntrustDto(info.getId().toString(), task.getId().toString(), contractId, info.getNodeId(), 2, 1);
-                            result = excelTabClient.saveReEntrustTabData(dto, header);
-                            if (result.getCode() == 200) {
-                                if (result.getData() != null) {
-                                    informationQueryService.update(new LambdaUpdateWrapper<InformationQuery>()
-                                            .eq(InformationQuery::getId, task.getFormDataId())
-                                            .set(InformationQuery::getPdfUrl, result.getData()));
+                            try {
+                                result=excelTabClient.saveReEntrustTabData(dto,header);
+                                if(result.getCode()==200){
+                                    if(result.getData()!=null){
+                                        informationQueryService.update(new LambdaUpdateWrapper<InformationQuery>()
+                                                .eq(InformationQuery::getId, task.getFormDataId())
+                                                .set(InformationQuery::getPdfUrl,result.getData()));
+                                    }
+                                }else{
+                                    //恢复pdf
+                                    isRestorePdf = true;
                                 }
+                            } catch (Exception e) {
+                                //恢复pdf
+                                isRestorePdf = true;
                             }
+
                         }
                         long endTime_1 = System.currentTimeMillis();
                         long executionTime_1 = endTime_1 - startTime_1;
@@ -2112,6 +2131,16 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                         }
                         result.setData("成功");
                     }
+                    //恢复pdf 并且 恢复电签pdf
+                    if(isRestorePdf){
+                        informationQueryService.update(new LambdaUpdateWrapper<InformationQuery>()
+                                .eq(InformationQuery::getId, task.getFormDataId())
+                                .set(InformationQuery::getPdfUrl, pdfUrl)
+                                .set(InformationQuery::getEVisaPdfUrl, eVisaPdfUrl));
+                        continue;
+                    }
+
+
                     //重新电签
                     if (result != null && ("成功".equals(result.getData()) || 200 == result.getCode())) {
                         List<TaskApprovalVO> taskApprovalVOS = new ArrayList<>();
@@ -2133,12 +2162,57 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                         }
                         long startTime_2 = System.currentTimeMillis();
                         if (taskApprovalVOS != null && taskApprovalVOS.size() >= 1) {
-                            this.batchCompleteApprovalTask(taskApprovalVOS);
+                            boolean b1 = this.batchCompleteApprovalTask(taskApprovalVOS);
+                            //如果失败 恢复电签
+                            if (!b1) {
+                                if (type == 1) {
+                                    //当前节点的电签pdf
+                                    informationQueryService.update(new LambdaUpdateWrapper<InformationQuery>()
+                                            .eq(InformationQuery::getId, task.getFormDataId())
+                                            .set(InformationQuery::getEVisaPdfUrl, eVisaPdfUrl)
+                                    );
+                                } else {
+                                    if (task.getApprovalType() == 3) {
+                                        contractLogService.update(new LambdaUpdateWrapper<ContractLog>()
+                                                .eq(ContractLog::getId, task.getFormDataId())
+                                                .set(ContractLog::getEVisaPdfUrl, eVisaPdfUrl));
+                                        if (!b) {
+                                            jdbcTemplate.update("update u_task set is_deleted=1 where id=" + task.getId());
+                                            return;
+                                        }
+                                    } else {
+                                        informationQueryService.update(new LambdaUpdateWrapper<InformationQuery>()
+                                                .eq(InformationQuery::getId, task.getFormDataId())
+                                                .set(InformationQuery::getEVisaPdfUrl, eVisaPdfUrl));
+                                    }
+                                }
+                            }
                         }
                         long endTime_2 = System.currentTimeMillis();
                         long executionTime_2 = endTime_2 - startTime_2;
                         log.info("batchCompleteApprovalTask执行时间:" + executionTime_2 + " 毫秒");
                     } else {
+                        if (type == 1) {
+                            //当前节点的电签pdf
+                            informationQueryService.update(new LambdaUpdateWrapper<InformationQuery>()
+                                    .eq(InformationQuery::getId, task.getFormDataId())
+                                    .set(InformationQuery::getEVisaPdfUrl, eVisaPdfUrl)
+                            );
+                        } else {
+                            if (task.getApprovalType() == 3) {
+                                contractLogService.update(new LambdaUpdateWrapper<ContractLog>()
+                                        .eq(ContractLog::getId, task.getFormDataId())
+                                        .set(ContractLog::getEVisaPdfUrl, eVisaPdfUrl));
+                                if (!b) {
+                                    jdbcTemplate.update("update u_task set is_deleted=1 where id=" + task.getId());
+                                    return;
+                                }
+                            } else {
+                                informationQueryService.update(new LambdaUpdateWrapper<InformationQuery>()
+                                        .eq(InformationQuery::getId, task.getFormDataId())
+                                        .set(InformationQuery::getEVisaPdfUrl, eVisaPdfUrl));
+                            }
+                        }
                         //修改重签状态为保存PDF失败
                         this.taskParallelService.update(Wrappers.<TaskParallel>lambdaUpdate()
                                 .set(TaskParallel::getEVisaContent, "重新保存PDF失败")
@@ -2153,6 +2227,13 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                     //满足去除当前填报人的条件 去除当前任务的填报人中当前操作人的信息
                     removeUserAndName(taskIds, userId, userName);
                 }
+                recordResignLog("re-sign(质检)",StringUtils.join(dataIdList, ","), list, new HashMap<String, Object>() {{
+                    put("taskIds", taskIds);
+                    put("contractId", contractId);
+                    put("projectId", projectId);
+                    put("classify", classify);
+                    put("type", type);
+                }}, projectId, contractId, request);
             } catch (Exception e) {
                 e.printStackTrace();
                 throw new ServiceException("重新保存PDF信息失败,原因:" + e.getMessage());
@@ -2242,6 +2323,10 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
 
     @Override
     public R reSigningEVisaByUserIds(String ids, String userIds) {
+        BladeUser user = AuthUtil.getUser();
+        if (user == null || user.getUserId() == null || user.getDeptId() == null || !"1536982621165592577".equals(user.getDeptId())) {
+            return R.fail("权限不足,请联系管理员处理!");
+        }
         if (Func.isEmpty(ids) && ids == null) {
             return R.fail("未获取到taskIds,操作失败!");
         }
@@ -2255,10 +2340,10 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
             }
             ids2 = ids2.substring(0, ids2.length() - 1);
         }
-
-        String sqlqu = "update u_information_query set status=2,e_visa_pdf_url='' where id in( " + ids + ") and is_deleted=0 ";
+        List<InformationQuery> queryList = jdbcTemplate.query("select id, e_visa_pdf_url, status from u_information_query where id in( " + ids + ") and is_deleted=0 and status in (1,2)", new BeanPropertyRowMapper<>(InformationQuery.class));
+        String sqlqu = "update u_information_query set status=2,e_visa_pdf_url='' where id in( " + ids + ") and is_deleted=0 and status in (1,2)";
         String sqlForTask = "update u_task set status=2 where form_data_id in( " + ids2 + ") and status in(1,2) and is_deleted=0 ";
-        String sqlForTaskPall = "UPDATE u_task_parallel a  set a.is_resign = 1, a.`status`=2 , a.e_visa_status=1 ,a.e_visa_content='电签成功' where a.process_instance_id in(select process_instance_id  from u_task b  where b.form_data_id in( " + ids2 + ") and b.status in(0,1,2) and b.is_deleted = 0)  and a.`status` in(0,1)";
+        String sqlForTaskPall = "update u_task_parallel a INNER JOIN u_task b on a.process_instance_id = b.process_instance_id set a.is_resign = 1, a.`status`=2 , a.e_visa_status=1 ,a.e_visa_content='电签成功' where b.form_data_id in( " + ids2 + ") and b.status in(0,1,2) and b.is_deleted = 0 and a.`status` in(0,1)";
 
         String taskBtech = "insert into u_task_batch(id,task_parallel_id,json_data,create_user,create_dept,create_time,update_user,update_time,status,is_deleted,nick_name,sign_format,sign_type)  " +
                 " SELECT a.id,a.process_instance_id,json_object('approvalFileList',json_array(),'approvalType',b.approval_type,'comment','','flag','OK','formDataId',b.form_data_id,'parallelProcessInstanceId',a.parallel_process_instance_id,'pass',true,'taskId',b.id) as  json_data,a.task_user,a.create_dept,a.create_time,a.update_user,SYSDATE(),1 as status,0 as is_deleted,a.task_user_name as nick_name ,1 as sign_format,1 as sign_type from u_task_parallel a,u_task b where b.`status` in(1,2) and a.`status` in(2)  and   a.process_instance_id=b.process_instance_id " +
@@ -2268,7 +2353,7 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
             taskBtech += " and b.task_user in("+userIds+")";
             sqlForTaskPall += " and a.task_user in("+userIds+")";
             sqlqu = "update u_information_query a set status = if((select count(1) from u_task_parallel where process_instance_id = ( select process_instance_id  from u_task  where form_data_id = cast(a.id as char) and is_deleted = 0 and status in (1,2) order by id desc limit 1 ) " +
-                    "and `is_deleted` = 0 and task_user not in ( " + userIds + ") and status != 2 and e_visa_status != 1 ) > 0, 1, 2) ,e_visa_pdf_url='' where id in( "+ ids + ") and is_deleted=0 ";
+                    "and `is_deleted` = 0 and task_user not in ( " + userIds + ") and status != 2 and e_visa_status != 1 ) > 0, 1, 2) ,e_visa_pdf_url='' where id in( "+ ids + ") and is_deleted=0 and status in (1,2)";
             sqlForTask = "update u_task a set status = if((select count(1) from u_task_parallel where process_instance_id = a.process_instance_id " +
                     "and `is_deleted` = 0 and task_user not in ( " + userIds + ") and status != 2 and e_visa_status != 1 ) > 0, 1, 2) where form_data_id in( " + ids2 + ") and status in(1,2) and is_deleted=0 ";
         }
@@ -2277,6 +2362,43 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
         jdbcTemplate.execute(sqlForTaskPall);
         jdbcTemplate.execute(taskBtech);
 
+        if (!queryList.isEmpty()) {
+            Map<String, String> requestMap = new HashMap<>();
+            requestMap.put("ids", ids);
+            requestMap.put("userIds", userIds);
+            recordResignLog("一键重签", ids, queryList, requestMap, null, null, null);
+        }
         return R.success("操作成功");
     }
+
+
+    public void recordResignLog(String module, String businessIds, Object data, Object requestData, String projectId, String contractId, HttpServletRequest request){
+        try {
+            OperationLog resignLog = new OperationLog();
+            resignLog.setProjectId(StringUtil.isNumeric(projectId) ? Long.parseLong(projectId) : null);
+            resignLog.setContractId(StringUtil.isNumeric(contractId) ? Long.parseLong(contractId) : null);
+            resignLog.setOperationType(33);
+            resignLog.setOperationModule(module);
+            resignLog.setOperationContent(JSON.toJSONString(requestData));
+            resignLog.setSaveData(JSON.toJSONString(data));
+            resignLog.setOperationTime(DateUtil.formatTime(DateUtil.now()));
+            resignLog.setOperationView("");
+            resignLog.setBusinessId(businessIds);
+            if (request != null) {
+                BladeUser user = AuthUtil.getUser(request);
+                if (user != null) {
+                    resignLog.setCreateUser(user.getUserId());
+                    resignLog.setOperationAccount(user.getUserName());
+                    resignLog.setCreateUserName(user.getNickName());
+                }
+            } else {
+                resignLog.setCreateUser(AuthUtil.getUserId());
+                resignLog.setOperationAccount(AuthUtil.getUserName());
+                resignLog.setCreateUserName(AuthUtil.getNickName());
+            }
+            operationLogService.save(resignLog);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
 }

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно