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

Merge remote-tracking branch 'origin/master'

liuyc 2 жил өмнө
parent
commit
ac63c0bb74
45 өөрчлөгдсөн 1122 нэмэгдсэн , 195 устгасан
  1. 47 0
      blade-common/src/main/java/org/springblade/common/utils/AsyncConfigurer.java
  2. 2 0
      blade-common/src/main/java/org/springblade/common/utils/INodeEx.java
  3. 191 0
      blade-common/src/main/java/org/springblade/common/utils/ThreadPoolMonitor.java
  4. 10 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/ArchiveFile.java
  5. 6 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/feign/InformationQueryClient.java
  6. 1 1
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/feign/TaskClient.java
  7. 6 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/TaskApprovalVO.java
  8. 6 0
      blade-service-api/blade-e-visa-api/src/main/java/org/springblade/evisa/vo/EVisaTaskApprovalVO.java
  9. 2 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/ArchiveTreeContractAutoRuleMapDTO.java
  10. 8 4
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/RangeInfo.java
  11. 0 4
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ArchiveAutoRuleWbs.java
  12. 18 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ArchiveTree.java
  13. 19 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ArchiveTreeContract.java
  14. 1 1
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/EVisaConfigClient.java
  15. 7 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ArchiveTreeContractVO2.java
  16. 8 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ArchiveTreeVO2.java
  17. 10 27
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TaskController.java
  18. 5 0
      blade-service/blade-business/src/main/java/org/springblade/business/feignClient/InformationQueryClientImpl.java
  19. 3 2
      blade-service/blade-business/src/main/java/org/springblade/business/feignClient/TaskClientImpl.java
  20. 1 0
      blade-service/blade-business/src/main/java/org/springblade/business/mapper/ArchiveFileMapper.xml
  21. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/service/IInformationQueryService.java
  22. 1 1
      blade-service/blade-business/src/main/java/org/springblade/business/service/ITaskService.java
  23. 29 45
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TaskServiceImpl.java
  24. 8 8
      blade-service/blade-e-visa/src/main/java/org/springblade/evisa/service/impl/EVisaServiceImpl.java
  25. 4 10
      blade-service/blade-manager/src/main/java/com/mixsmart/utils/CustomFunction.java
  26. 9 1
      blade-service/blade-manager/src/main/java/com/mixsmart/utils/FormulaUtils.java
  27. 14 6
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ArchiveTreeController.java
  28. 2 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/feign/EVisaConfigClientImpl.java
  29. 13 6
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/SubTable.java
  30. 0 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/TableElementConverter.java
  31. 4 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveAutoRuleWbsMapper.java
  32. 11 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveAutoRuleWbsMapper.xml
  33. 6 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeMapper.java
  34. 7 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeMapper.xml
  35. 2 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ContractInfoMapper.xml
  36. 3 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IArchiveTreeContractService.java
  37. 3 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/IArchiveTreeService.java
  38. 227 13
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveAutoRuleWbsServiceImpl.java
  39. 40 11
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeContractServiceImpl.java
  40. 72 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeContractSyncImpl.java
  41. 230 20
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeServiceImpl.java
  42. 7 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java
  43. 23 13
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java
  44. 16 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/utils/ForestNodeMerger.java
  45. 39 5
      blade-service/blade-manager/src/main/java/org/springblade/manager/utils/ForestNodeMergerEx.java

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

@@ -0,0 +1,47 @@
+package org.springblade.common.utils;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableAsync;
+
+import java.util.concurrent.*;
+
+@Slf4j
+@Configuration
+@EnableAsync
+public class AsyncConfigurer {
+
+    /**
+     * cpu 核心数量
+     */
+    public static final int cpuNum = Runtime.getRuntime().availableProcessors();
+
+    /**
+     * 线程池配置
+     *
+     * @return
+     */
+    @Bean("taskExecutor1")
+    public ThreadPoolExecutor getAsyncExecutor() {
+        return new ThreadPoolMonitor(cpuNum
+                , cpuNum * 2
+                , 60
+                , TimeUnit.SECONDS
+                , new LinkedBlockingQueue<>(2000)
+                , new ThreadPoolExecutor.DiscardOldestPolicy(), "manager-thread-pool");
+    }
+
+
+    /**
+     * 线程池配置
+     *
+     * @return
+     */
+    @Bean("singleExecutor")
+    public ExecutorService getSingleExecutor() {
+        log.info("线程池初始化......");
+        return Executors.newSingleThreadExecutor();
+    }
+
+}

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

@@ -37,4 +37,6 @@ public interface INodeEx<T> extends Serializable {
     default Boolean getHasChildren() {
     default Boolean getHasChildren() {
         return false;
         return false;
     }
     }
+
+    default void clearChildren() {}
 }
 }

+ 191 - 0
blade-common/src/main/java/org/springblade/common/utils/ThreadPoolMonitor.java

@@ -0,0 +1,191 @@
+package org.springblade.common.utils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+public class ThreadPoolMonitor extends ThreadPoolExecutor {
+    private final Logger logger = LoggerFactory.getLogger(getClass());
+
+    /**
+     * ActiveCount
+     */
+    int ac = 0;
+
+    /**
+     * 当前所有线程消耗的时间
+     */
+    private AtomicLong totalCostTime = new AtomicLong();
+
+    /**
+     * 当前执行的线程总数
+     */
+    private AtomicLong totalTasks = new AtomicLong();
+
+    /**
+     * 线程池名称
+     */
+    private String poolName;
+
+    /**
+     * 最短 执行时间
+     */
+    private long minCostTime;
+
+    /**
+     * 最长执行时间
+     */
+    private long maxCostTime;
+
+
+    /**
+     * 保存任务开始执行的时间
+     */
+    private ThreadLocal<Long> startTime = new ThreadLocal<>();
+
+    public ThreadPoolMonitor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
+                             TimeUnit unit, BlockingQueue<Runnable> workQueue, String poolName) {
+        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
+                Executors.defaultThreadFactory(), poolName);
+    }
+
+    public ThreadPoolMonitor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
+                             TimeUnit unit, BlockingQueue<Runnable> workQueue,
+                             ThreadFactory threadFactory, String poolName) {
+        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
+        this.poolName = poolName;
+    }
+
+    public ThreadPoolMonitor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler, String poolName) {
+        super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
+        this.poolName = poolName;
+    }
+
+    /**
+     * 线程池延迟关闭时(等待线程池里的任务都执行完毕),统计线程池情况
+     */
+    @Override
+    public void shutdown() {
+        // 统计已执行任务、正在执行任务、未执行任务数量
+        logger.info("{} Going to shutdown. Executed tasks: {}, Running tasks: {}, Pending tasks: {}",
+                this.poolName, this.getCompletedTaskCount(), this.getActiveCount(), this.getQueue().size());
+        super.shutdown();
+    }
+
+    @Override
+    public List<Runnable> shutdownNow() {
+        // 统计已执行任务、正在执行任务、未执行任务数量
+        logger.info("{} Going to immediately shutdown. Executed tasks: {}, Running tasks: {}, Pending tasks: {}",
+                this.poolName, this.getCompletedTaskCount(), this.getActiveCount(), this.getQueue().size());
+        return super.shutdownNow();
+    }
+
+    /**
+     * 任务执行之前,记录任务开始时间
+     */
+    @Override
+    protected void beforeExecute(Thread t, Runnable r) {
+        logger.info("{}-before: " +
+                        " PoolSize: {}, CorePoolSize: {}, ActiveCount: {}, " +
+                        "Completed: {}, Task: {}, Queue: {}, LargestPoolSize: {}, " +
+                        "MaximumPoolSize: {},  KeepAliveTime: {}, isShutdown: {}, isTerminated: {}",
+                this.poolName,
+                this.getPoolSize(), this.getCorePoolSize(), super.getActiveCount(),
+                this.getCompletedTaskCount(), this.getTaskCount(), this.getQueue().size(), this.getLargestPoolSize(),
+                this.getMaximumPoolSize(), this.getKeepAliveTime(TimeUnit.MILLISECONDS), this.isShutdown(), this.isTerminated());
+        startTime.set(System.currentTimeMillis());
+    }
+
+    /**
+     * 任务执行之后,计算任务结束时间
+     */
+    @Override
+    protected void afterExecute(Runnable r, Throwable t) {
+        long costTime = System.currentTimeMillis() - startTime.get();
+        startTime.remove();  //删除,避免占用太多内存
+        //设置最大最小执行时间
+        maxCostTime = maxCostTime > costTime ? maxCostTime : costTime;
+        if (totalTasks.get() == 0) {
+            minCostTime = costTime;
+        }
+        minCostTime = minCostTime < costTime ? minCostTime : costTime;
+        totalCostTime.addAndGet(costTime);
+        totalTasks.incrementAndGet();
+        ac = this.getActiveCount();  //获取ActiveCount的值
+
+        logger.info("{}-after: " +
+                        "Duration: {} ms, PoolSize: {}, CorePoolSize: {}, ActiveCount: {}, " +
+                        "Completed: {}, Task: {}, Queue: {}, LargestPoolSize: {}, " +
+                        "MaximumPoolSize: {},  KeepAliveTime: {}, isShutdown: {}, isTerminated: {}",
+                this.poolName,
+                costTime, this.getPoolSize(), this.getCorePoolSize(), super.getActiveCount(),
+                this.getCompletedTaskCount(), this.getTaskCount(), this.getQueue().size(), this.getLargestPoolSize(),
+                this.getMaximumPoolSize(), this.getKeepAliveTime(TimeUnit.MILLISECONDS), this.isShutdown(), this.isTerminated());
+    }
+
+    public int getAc() {
+        return ac;
+    }
+
+    /**
+     * 线程平均耗时
+     *
+     * @return
+     */
+    public float getAverageCostTime() {
+        return totalCostTime.get() / totalTasks.get();
+    }
+
+    /**
+     * 线程最大耗时
+     */
+    public long getMaxCostTime() {
+        return maxCostTime;
+    }
+
+    /**
+     * 线程最小耗时
+     */
+    public long getMinCostTime() {
+        return minCostTime;
+    }
+
+    /**
+     * 生成线程池所用的线程,改写了线程池默认的线程工厂
+     */
+    static class EventThreadFactory implements ThreadFactory {
+        private static final AtomicInteger poolNumber = new AtomicInteger(1);
+        private final ThreadGroup group;
+        private final AtomicInteger threadNumber = new AtomicInteger(1);
+        private final String namePrefix;
+
+        /**
+         * 初始化线程工厂
+         *
+         * @param poolName 线程池名称
+         */
+        EventThreadFactory(String poolName) {
+            SecurityManager s = System.getSecurityManager();
+            group = Objects.nonNull(s) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
+            namePrefix = poolName + "-pool-" + poolNumber.getAndIncrement() + "-thread-";
+        }
+
+        @Override
+        public Thread newThread(Runnable r) {
+            Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
+
+            if (t.isDaemon()) {
+                t.setDaemon(false);
+            }
+            if (t.getPriority() != Thread.NORM_PRIORITY) {
+                t.setPriority(Thread.NORM_PRIORITY);
+            }
+            return t;
+        }
+    }
+}

+ 10 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/entity/ArchiveFile.java

@@ -243,4 +243,14 @@ public class ArchiveFile extends BaseEntity {
 	//是否案卷收集上传的案卷
 	//是否案卷收集上传的案卷
 	@ApiModelProperty("是否案卷收集上传的案卷")
 	@ApiModelProperty("是否案卷收集上传的案卷")
 	private Integer isAutoFile;
 	private Integer isAutoFile;
+
+
+	/**
+	 * 是否已组卷  0或null 未组卷  1已组卷
+	 */
+	@ApiModelProperty("是否组卷")
+	private Integer isArchive;
+
+
+
 }
 }

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

@@ -60,4 +60,10 @@ public interface InformationQueryClient {
 
 
     @PostMapping(API_PREFIX + "/updateInformationQuery")
     @PostMapping(API_PREFIX + "/updateInformationQuery")
     void updateInformationQuery(@RequestParam String link, @RequestParam String classify, @RequestParam String nodeId, @RequestParam String contractId);
     void updateInformationQuery(@RequestParam String link, @RequestParam String classify, @RequestParam String nodeId, @RequestParam String contractId);
+
+
+    // 更新redis数据
+    @PostMapping(API_PREFIX + "/AsyncWbsTree")
+    void  AsyncWbsTree(@RequestParam String primaryKeyId,@RequestParam String parentId,@RequestParam String contractId,@RequestParam String contractIdRelation,@RequestParam String classifyType);
+
 }
 }

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

@@ -50,7 +50,7 @@ public interface TaskClient {
      * 获取当前任务绑定的表格
      * 获取当前任务绑定的表格
      */
      */
     @PostMapping(QUERY_BUSINESS_TABLE_E_VISA_CONFIG)
     @PostMapping(QUERY_BUSINESS_TABLE_E_VISA_CONFIG)
-    List<JSONObject> queryBusinessTableEVisaConfig(@RequestParam String taskId,@RequestParam String isFinal);
+    List<JSONObject> queryBusinessTableEVisaConfig(@RequestParam String taskId,@RequestParam Long userId,@RequestParam String isFinal);
 
 
     /**
     /**
      * 获取填报人列表
      * 获取填报人列表

+ 6 - 0
blade-service-api/blade-business-api/src/main/java/org/springblade/business/vo/TaskApprovalVO.java

@@ -36,6 +36,12 @@ public class TaskApprovalVO {
     @ApiModelProperty("批量审批")
     @ApiModelProperty("批量审批")
     private String taskIds;
     private String taskIds;
 
 
+    @ApiModelProperty("用户ID")
+    private Long userId;
+
+    @ApiModelProperty("签字人名")
+    private String nickName;
+
     @ApiModelProperty("附件信息")
     @ApiModelProperty("附件信息")
     private List<ApprovalFile> approvalFileList = new ArrayList<>();
     private List<ApprovalFile> approvalFileList = new ArrayList<>();
 
 

+ 6 - 0
blade-service-api/blade-e-visa-api/src/main/java/org/springblade/evisa/vo/EVisaTaskApprovalVO.java

@@ -36,6 +36,12 @@ public class EVisaTaskApprovalVO {
     @ApiModelProperty("批量审批")
     @ApiModelProperty("批量审批")
     private String taskIds;
     private String taskIds;
 
 
+    @ApiModelProperty("用户ID")
+    private Long userId;
+
+    @ApiModelProperty("用户ID")
+    private String nickName;
+
     @ApiModelProperty("附件信息")
     @ApiModelProperty("附件信息")
     private List<ApprovalFile> approvalFileList = new ArrayList<>();
     private List<ApprovalFile> approvalFileList = new ArrayList<>();
 
 

+ 2 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/dto/ArchiveTreeContractAutoRuleMapDTO.java

@@ -15,4 +15,6 @@ public class ArchiveTreeContractAutoRuleMapDTO {
 
 
     private String selectNodeIds; //分类并卷设置选择的节点(鼠标点着的节点,不要父节点和子节点)
     private String selectNodeIds; //分类并卷设置选择的节点(鼠标点着的节点,不要父节点和子节点)
 
 
+    private Long projectId;
+
 }
 }

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

@@ -3,11 +3,14 @@ package org.springblade.manager.dto;
 import com.alibaba.fastjson.annotation.JSONField;
 import com.alibaba.fastjson.annotation.JSONField;
 import io.swagger.annotations.ApiModelProperty;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.Data;
+import org.springblade.common.utils.BaseUtils;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.core.tool.utils.Func;
 import org.springblade.core.tool.utils.StringUtil;
 import org.springblade.core.tool.utils.StringUtil;
 
 
 import java.util.Arrays;
 import java.util.Arrays;
 import java.util.List;
 import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
 
 
 /**
 /**
@@ -74,22 +77,23 @@ public class RangeInfo {
 
 
     public void build(){
     public void build(){
         if(Func.isNotBlank(this.design)){
         if(Func.isNotBlank(this.design)){
-            this.gDesign= Arrays.stream(this.design.split("[^\\d.]+")).filter(Func::isNumeric).map(Func::toDouble).collect(Collectors.toList());
+            this.gDesign= Arrays.stream(this.design.split("[^\\d.]+")).filter(BaseUtils::isNumber).map(Func::toDouble).collect(Collectors.toList());
         }
         }
         if(Func.isNotBlank(this.size)){
         if(Func.isNotBlank(this.size)){
-            this.gSize= Arrays.stream(this.size.split("[^\\d.]+")).filter(Func::isNumeric).map(Func::toInt).collect(Collectors.toList());
+            this.gSize= Arrays.stream(this.size.split("[^\\d.]+")).filter(BaseUtils::isNumber).map(Func::toInt).collect(Collectors.toList());
         }
         }
         if(Func.isNotBlank(this.dev)){
         if(Func.isNotBlank(this.dev)){
             this.gDev= Arrays.stream(this.dev.split("/+")).collect(Collectors.toList());
             this.gDev= Arrays.stream(this.dev.split("/+")).collect(Collectors.toList());
         }
         }
         if(Func.isNotBlank(this.pass)){
         if(Func.isNotBlank(this.pass)){
-            this.gPass= Arrays.stream(this.pass.split("[^\\d.%]+")).filter(Func::isNumeric).map(Func::toInt).collect(Collectors.toList());
+            this.gPass= Arrays.stream(this.pass.split("[^\\d.%]+")).filter(BaseUtils::isNumber).map(Func::toInt).collect(Collectors.toList());
         }
         }
         if(Func.isNotBlank(this.capacity)){
         if(Func.isNotBlank(this.capacity)){
-            this.gCapacity= Arrays.stream(this.capacity.split("[^\\d.]+")).filter(Func::isNumeric).map(Func::toInt).collect(Collectors.toList());
+            this.gCapacity= Arrays.stream(this.capacity.split("[^\\d.]+")).filter(BaseUtils::isNumber).map(Func::toInt).collect(Collectors.toList());
         }
         }
     }
     }
 
 
+
     public void setSize(String size) {
     public void setSize(String size) {
         this.size = size;
         this.size = size;
     }
     }

+ 0 - 4
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/entity/ArchiveAutoRuleWbs.java

@@ -55,10 +55,6 @@ public class ArchiveAutoRuleWbs extends BaseEntity {
 	* 项目id 系统级的为0
 	* 项目id 系统级的为0
 	*/
 	*/
 		private Long projectId;
 		private Long projectId;
-	/**
-	* 1删除  0正常
-	*/
-		private Integer delete;
 
 
 
 
 }
 }

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

@@ -201,4 +201,22 @@ public class ArchiveTree extends BaseEntity {
             e.printStackTrace();
             e.printStackTrace();
         }
         }
     }
     }
+
+    public void sync(ArchiveTreeVO2 archiveTree) {
+        if (archiveTree == null) {
+            return;
+        }
+        this.nodeType = archiveTree.getNodeType();
+        this.postType = archiveTree.getPostType();
+        this.associationType = archiveTree.getAssociationType();
+        this.majorDataType = archiveTree.getMajorDataType();
+        this.displayHierarchy = archiveTree.getDisplayHierarchy();
+        this.isStorageNode = archiveTree.getIsStorageNode();
+        this.isBuiltDrawing = archiveTree.getIsBuiltDrawing();
+        this.isInterfaceNode = archiveTree.getIsInterfaceNode();
+        this.projectType = archiveTree.getProjectType();
+        this.storageType = archiveTree.getStorageType();
+        this.expDataType = archiveTree.getExpDataType();
+        this.archiveAutoType = archiveTree.getArchiveAutoType();
+    }
 }
 }

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

@@ -232,6 +232,25 @@ public class ArchiveTreeContract extends BaseEntity {
 		}
 		}
 	}
 	}
 
 
+	public void sync(ArchiveTree archiveTree) {
+		if (archiveTree == null) {
+			return;
+		}
+		this.nodeType = archiveTree.getNodeType();
+		this.postType = archiveTree.getPostType();
+		this.associationType = archiveTree.getAssociationType();
+		this.majorDataType = archiveTree.getMajorDataType();
+		this.displayHierarchy = archiveTree.getDisplayHierarchy();
+		this.isStorageNode = archiveTree.getIsStorageNode();
+		this.isBuiltDrawing = archiveTree.getIsBuiltDrawing();
+		this.isInterfaceNode = archiveTree.getIsInterfaceNode();
+		this.projectType = archiveTree.getProjectType();
+		this.storageType = archiveTree.getStorageType();
+		this.expDataType = archiveTree.getExpDataType();
+		this.archiveAutoType = archiveTree.getArchiveAutoType();
+	}
+
+
 	public boolean isContractRoot(){
 	public boolean isContractRoot(){
 		if (this.getExtType() != null && this.getExtType() == 2
 		if (this.getExtType() != null && this.getExtType() == 2
 				&& StringUtils.isNotEmpty(this.getTreeCode())){
 				&& StringUtils.isNotEmpty(this.getTreeCode())){

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

@@ -22,6 +22,6 @@ public interface EVisaConfigClient {
     List<JSONObject> queryEVisaConfigAllByTableIds(@RequestBody List<String> tableIds);
     List<JSONObject> queryEVisaConfigAllByTableIds(@RequestBody List<String> tableIds);
 
 
     @PostMapping(API_PREFIX + "/queryEVisaConfigByTableIds")
     @PostMapping(API_PREFIX + "/queryEVisaConfigByTableIds")
-    List<JSONObject> queryEVisaConfigByTableIds(@RequestBody List<String> tableIds, @RequestParam String contractId, @RequestParam String isFinal);
+    List<JSONObject> queryEVisaConfigByTableIds(@RequestBody List<String> tableIds, @RequestParam String contractId, @RequestParam String isFinal, @RequestParam Long userId);
 
 
 }
 }

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

@@ -97,6 +97,13 @@ public class ArchiveTreeContractVO2 implements INodeEx<ArchiveTreeContractVO2> {
 		return this.children;
 		return this.children;
 	}
 	}
 
 
+	@Override
+	public void clearChildren() {
+		if (children!= null ) {
+			children.clear();
+		}
+	}
+
 	/**
 	/**
 	 * 内业资料类型(用于显示控制)
 	 * 内业资料类型(用于显示控制)
 	 */
 	 */

+ 8 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ArchiveTreeVO2.java

@@ -65,6 +65,12 @@ public class ArchiveTreeVO2 implements INodeEx<ArchiveTreeVO2> {
         }
         }
         return this.children;
         return this.children;
     }
     }
+    @Override
+    public void clearChildren() {
+        if (children!= null ) {
+            children.clear();
+        }
+    }
 
 
     /**
     /**
      * 内业资料类型(用于显示控制)
      * 内业资料类型(用于显示控制)
@@ -187,4 +193,6 @@ public class ArchiveTreeVO2 implements INodeEx<ArchiveTreeVO2> {
 
 
     private boolean iswbsNode;  //是否为关联的wbs节点
     private boolean iswbsNode;  //是否为关联的wbs节点
 
 
+    private Long wbsNode2ArchiveTreeNodeId;  //wbs节点关联归档树节点ID
+
 }
 }

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

@@ -39,15 +39,19 @@ import org.springblade.resource.feign.NewISmsClient;
 import org.springblade.system.entity.DictBiz;
 import org.springblade.system.entity.DictBiz;
 import org.springblade.system.feign.IDictBizClient;
 import org.springblade.system.feign.IDictBizClient;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.BeanUtils;
+import org.springframework.scheduling.annotation.Async;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.*;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.springblade.business.vo.TaskVO;
 import org.springblade.business.vo.TaskVO;
 import org.springblade.core.boot.ctrl.BladeController;
 import org.springblade.core.boot.ctrl.BladeController;
 
 
+import javax.annotation.Resource;
 import java.io.FileNotFoundException;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.IOException;
 import java.time.Duration;
 import java.time.Duration;
 import java.util.*;
 import java.util.*;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ThreadPoolExecutor;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
 
 
 /**
 /**
@@ -295,7 +299,7 @@ public class TaskController extends BladeController {
             }
             }
 
 
             //审批
             //审批
-            this.taskService.batchCompleteApprovalTask(taskApprovalVOS, AuthUtil.getUserId());
+            this.taskService.batchCompleteApprovalTask(taskApprovalVOS);
 
 
             //通过WebSocket推送数量条数
             //通过WebSocket推送数量条数
             if (ObjectUtil.isNotEmpty(AuthUtil.getUserId())) {
             if (ObjectUtil.isNotEmpty(AuthUtil.getUserId())) {
@@ -581,34 +585,13 @@ public class TaskController extends BladeController {
     @ApiOperationSupport(order = 2)
     @ApiOperationSupport(order = 2)
     @ApiOperation(value = "完成/审批任务")
     @ApiOperation(value = "完成/审批任务")
     public R<Boolean> completeApprovalTask(@RequestBody TaskApprovalVO taskApprovalVO) throws FileNotFoundException {
     public R<Boolean> completeApprovalTask(@RequestBody TaskApprovalVO taskApprovalVO) throws FileNotFoundException {
-        //检查当前用户是否存在等待批次
-        //System.out.println(AuthUtil.getUserId());
-        long batchCount = this.taskBatchService.count(Wrappers.<TaskBatch>lambdaQuery().eq(TaskBatch::getCreateUser, AuthUtil.getUserId()));
 
 
-        if (batchCount > 0) {
-            this.taskParallelService.update(Wrappers.<TaskParallel>lambdaUpdate()
-                    .set(TaskParallel::getEVisaContent, "当前等待电签的批次较多,请等待几分钟后刷新页面查看........")
-                    .eq(TaskParallel::getParallelProcessInstanceId, taskApprovalVO.getParallelProcessInstanceId()));
+        //生成等待批次,任务完成后删除
+        List<TaskApprovalVO> taskApprovalVOS = new ArrayList<>();
+        taskApprovalVOS.add(taskApprovalVO);
+        this.taskService.batchCompleteApprovalTask(taskApprovalVOS);
+        return R.data(true, "提交成功");
 
 
-            //生成等待批次,任务完成后删除
-            List<TaskApprovalVO> taskApprovalVOS = new ArrayList<>();
-            taskApprovalVOS.add(taskApprovalVO);
-
-            //存在批次,当前审批的追加进队列
-            TaskBatch taskBatch = new TaskBatch(taskApprovalVO.getParallelProcessInstanceId(), JSONObject.toJSONString(taskApprovalVOS));
-            taskBatch.setCreateUser(AuthUtil.getUserId());
-            taskBatch.setCreateTime(new Date());
-            this.taskBatchService.save(taskBatch);
-
-            return R.data(true, "当前等待电签的批次较多,请等待几分钟后刷新页面查看........");
-        } else {
-            //生成等待批次,任务完成后删除
-            List<TaskApprovalVO> taskApprovalVOS = new ArrayList<>();
-            taskApprovalVOS.add(taskApprovalVO);
-            this.taskService.batchCompleteApprovalTask(taskApprovalVOS, AuthUtil.getUserId());
-
-            return R.data(true, "提交成功");
-        }
     }
     }
 
 
     /**
     /**

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

@@ -74,4 +74,9 @@ public class InformationQueryClientImpl implements InformationQueryClient {
         updateWrapper.eq(InformationQuery::getContractId, contractId);
         updateWrapper.eq(InformationQuery::getContractId, contractId);
         iInformationQueryService.update(null, updateWrapper);
         iInformationQueryService.update(null, updateWrapper);
     }
     }
+
+    @Override
+    public void AsyncWbsTree(String primaryKeyId, String parentId, String contractId, String contractIdRelation, String classifyType) {
+        iInformationQueryService.AsyncWbsTree(primaryKeyId,parentId,contractId,contractIdRelation,classifyType);
+    }
 }
 }

+ 3 - 2
blade-service/blade-business/src/main/java/org/springblade/business/feignClient/TaskClientImpl.java

@@ -14,6 +14,7 @@ import org.springblade.business.vo.TaskApprovalVO;
 import org.springblade.business.vo.TaskVO;
 import org.springblade.business.vo.TaskVO;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.api.R;
 import org.springblade.manager.feign.EVisaConfigClient;
 import org.springblade.manager.feign.EVisaConfigClient;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.bind.annotation.RestController;
 import java.util.List;
 import java.util.List;
 import java.util.Map;
 import java.util.Map;
@@ -46,7 +47,7 @@ public class TaskClientImpl implements TaskClient {
     }
     }
 
 
     @Override
     @Override
-    public List<JSONObject> queryBusinessTableEVisaConfig(String taskId, String isFinal) {
+    public List<JSONObject> queryBusinessTableEVisaConfig(String taskId, Long userId ,String isFinal) {
         //找到任务
         //找到任务
         Task task = this.queryTask(taskId);
         Task task = this.queryTask(taskId);
         if(task != null){
         if(task != null){
@@ -54,7 +55,7 @@ public class TaskClientImpl implements TaskClient {
             List<String> privatePrimaryKeyIds = this.informationQueryService.queryBusinessTableData(task.getFormDataId(),task.getTrialSelfInspectionRecordId());
             List<String> privatePrimaryKeyIds = this.informationQueryService.queryBusinessTableData(task.getFormDataId(),task.getTrialSelfInspectionRecordId());
             if(privatePrimaryKeyIds != null && privatePrimaryKeyIds.size() > 0){
             if(privatePrimaryKeyIds != null && privatePrimaryKeyIds.size() > 0){
                 //查询这些表格的电签配置
                 //查询这些表格的电签配置
-                return this.eVisaConfigClient.queryEVisaConfigByTableIds(privatePrimaryKeyIds, task.getContractId(), isFinal);
+                return this.eVisaConfigClient.queryEVisaConfigByTableIds(privatePrimaryKeyIds, task.getContractId(), isFinal,userId);
             }
             }
         }
         }
         return null;
         return null;

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

@@ -50,6 +50,7 @@
         <result column="box_name" property="boxName"/>
         <result column="box_name" property="boxName"/>
         <result column="box_number" property="boxNumber"/>
         <result column="box_number" property="boxNumber"/>
         <result column="is_auto_file" property="isAutoFile"/>
         <result column="is_auto_file" property="isAutoFile"/>
+        <result column="is_archive" property="isArchive"/>
     </resultMap>
     </resultMap>
     <update id="recoveryByIds">
     <update id="recoveryByIds">
         update u_archive_file set is_deleted = 0 where
         update u_archive_file set is_deleted = 0 where

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

@@ -129,6 +129,6 @@ public interface IInformationQueryService extends BaseService<InformationQuery>
     // 测试节点信息
     // 测试节点信息
     List<WbsTreeContractTreeVOS> queryContractTree(String parentId, String contractId, String contractIdRelation, String classifyType);
     List<WbsTreeContractTreeVOS> queryContractTree(String parentId, String contractId, String contractIdRelation, String classifyType);
 
 
-    //
+    //变更节点
     void  AsyncWbsTree(String primaryKeyId,String parentId,String contractId,String contractIdRelation,String classifyType);
     void  AsyncWbsTree(String primaryKeyId,String parentId,String contractId,String contractIdRelation,String classifyType);
 }
 }

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

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

+ 29 - 45
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TaskServiceImpl.java

@@ -45,8 +45,11 @@ import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.transaction.annotation.Transactional;
 
 
+import javax.annotation.Resource;
 import java.io.FileNotFoundException;
 import java.io.FileNotFoundException;
 import java.util.*;
 import java.util.*;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
 
 
@@ -95,6 +98,10 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
 
 
     private final ITrialSelfInspectionRecordService iTrialSelfInspectionRecordService;
     private final ITrialSelfInspectionRecordService iTrialSelfInspectionRecordService;
 
 
+    // 线程池
+    @Resource(name = "taskExecutor1")
+    private ThreadPoolExecutor executor;
+
     @Override
     @Override
     public List<TaskParallel> queryApprovalUser(String formDataIds) {
     public List<TaskParallel> queryApprovalUser(String formDataIds) {
         //返回结果
         //返回结果
@@ -121,12 +128,12 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
      */
      */
     @Override
     @Override
     public TaskApprovalVO queryBusinessDataTask(TaskApprovalVO taskApprovalVO) {
     public TaskApprovalVO queryBusinessDataTask(TaskApprovalVO taskApprovalVO) {
-        int foreachNumber = 0;
+        /*int foreachNumber = 0;
         do {
         do {
             //判断锁是否存在
             //判断锁是否存在
             if (!DistributedRedisLock.getLockStatus(taskApprovalVO.getFormDataId())) {
             if (!DistributedRedisLock.getLockStatus(taskApprovalVO.getFormDataId())) {
                 //如果不存在,直接获取并上锁,由于这个查询方法是任务方面使用,所以解锁需要在对应数据使用结束后
                 //如果不存在,直接获取并上锁,由于这个查询方法是任务方面使用,所以解锁需要在对应数据使用结束后
-                DistributedRedisLock.acquire(taskApprovalVO.getFormDataId(), 20);
+                DistributedRedisLock.acquire(taskApprovalVO.getFormDataId(), 20);*/
                 switch (taskApprovalVO.getApprovalType()) {
                 switch (taskApprovalVO.getApprovalType()) {
                     case 1:
                     case 1:
                         //填报数据
                         //填报数据
@@ -142,7 +149,7 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                         DistributedRedisLock.release(taskApprovalVO.getFormDataId());
                         DistributedRedisLock.release(taskApprovalVO.getFormDataId());
                         return null;
                         return null;
                 }
                 }
-            } else {
+            /*} else {
                 try {
                 try {
                     if (foreachNumber < 10) {
                     if (foreachNumber < 10) {
                         //如果存在锁,则等待解锁
                         //如果存在锁,则等待解锁
@@ -157,8 +164,7 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
             }
             }
         } while (true);
         } while (true);
         //能走到这说明找不到文件或者超过锁定次数,解锁并返回
         //能走到这说明找不到文件或者超过锁定次数,解锁并返回
-        DistributedRedisLock.release(taskApprovalVO.getFormDataId());
-        return taskApprovalVO;
+        DistributedRedisLock.release(taskApprovalVO.getFormDataId());*/
     }
     }
 
 
     @Override
     @Override
@@ -407,47 +413,41 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
      * 批量电签接口
      * 批量电签接口
      *
      *
      * @param taskApprovalVOS
      * @param taskApprovalVOS
-     * @param userId
      * @throws FileNotFoundException
      * @throws FileNotFoundException
      */
      */
     @Override
     @Override
-    public void batchCompleteApprovalTask(List<TaskApprovalVO> taskApprovalVOS, Long userId) throws FileNotFoundException {
+    public void batchCompleteApprovalTask(List<TaskApprovalVO> taskApprovalVOS) {
+        Long  userId =AuthUtil.getUserId();
+        String  nickName =AuthUtil.getNickName();
         List<String> taskIds = taskApprovalVOS.stream().map(TaskApprovalVO::getParallelProcessInstanceId).distinct().collect(Collectors.toList());
         List<String> taskIds = taskApprovalVOS.stream().map(TaskApprovalVO::getParallelProcessInstanceId).distinct().collect(Collectors.toList());
-        long batch = this.taskBatchService.count(Wrappers.<TaskBatch>lambdaQuery().eq(TaskBatch::getCreateUser, userId));
-        if (batch > 0) {
-            //修改电签状态
-            this.taskParallelService.update(Wrappers.<TaskParallel>lambdaUpdate()
+        this.taskParallelService.update(Wrappers.<TaskParallel>lambdaUpdate()
                     .set(TaskParallel::getEVisaContent, "当前等待电签的批次较多,请等待几分钟后刷新页面查看........")
                     .set(TaskParallel::getEVisaContent, "当前等待电签的批次较多,请等待几分钟后刷新页面查看........")
                     .in(TaskParallel::getParallelProcessInstanceId, taskIds));
                     .in(TaskParallel::getParallelProcessInstanceId, taskIds));
             //保存批次
             //保存批次
-            TaskBatch taskBatch = new TaskBatch(null, JSONObject.toJSONString(taskApprovalVOS));
+        TaskBatch taskBatch = new TaskBatch(null, JSONObject.toJSONString(taskApprovalVOS));
             taskBatch.setCreateUser(AuthUtil.getUserId());
             taskBatch.setCreateUser(AuthUtil.getUserId());
             taskBatch.setCreateTime(new Date());
             taskBatch.setCreateTime(new Date());
-            this.taskBatchService.save(taskBatch);
-        } else {
-            //修改电签状态
-            this.taskParallelService.update(Wrappers.<TaskParallel>lambdaUpdate()
-                    .set(TaskParallel::getEVisaContent, "正在电签,请稍后查看........")
-                    .in(TaskParallel::getParallelProcessInstanceId, taskIds));
 
 
-            //保存批次
-            TaskBatch taskBatch = new TaskBatch(null, JSONObject.toJSONString(taskApprovalVOS));
-            taskBatch.setCreateUser(AuthUtil.getUserId());
-            taskBatch.setCreateTime(new Date());
             this.taskBatchService.save(taskBatch);
             this.taskBatchService.save(taskBatch);
-
-            //执行电签,结束后检查在执行是否有新的等待批次
-            this.checkIsExsitTaskBatch(taskApprovalVOS, taskBatch.getId().toString());
-        }
-
+            String taskBatchId = taskBatch.getId().toString();
+            // 添加到 线程中
+            CompletableFuture<Void> runAsync = CompletableFuture.runAsync(() -> {
+                try {
+                    this.checkIsExsitTaskBatch(taskApprovalVOS, taskBatchId,userId,nickName);
+                } catch (FileNotFoundException e) {
+                    e.printStackTrace();
+                }
+            }, executor);
     }
     }
 
 
-    private void checkIsExsitTaskBatch(List<TaskApprovalVO> taskApprovalVOS, String batchId) throws FileNotFoundException {
+    private void checkIsExsitTaskBatch(List<TaskApprovalVO> taskApprovalVOS, String batchId,Long userId,String nickName) throws FileNotFoundException {
         boolean isContinue = true;
         boolean isContinue = true;
         while (isContinue) {
         while (isContinue) {
             logger.info("【任务审核】当前批次开始电签。批次ID:" + batchId);
             logger.info("【任务审核】当前批次开始电签。批次ID:" + batchId);
             //执行电签
             //执行电签
             for (TaskApprovalVO taskApprovalVO : taskApprovalVOS) {
             for (TaskApprovalVO taskApprovalVO : taskApprovalVOS) {
+                taskApprovalVO.setUserId(userId);
+                taskApprovalVO.setNickName(nickName);
                 String pdfUrlEVisa = this.completeApprovalTask(taskApprovalVO);
                 String pdfUrlEVisa = this.completeApprovalTask(taskApprovalVO);
 
 
                 //TODO ============== 电签成功,修改试验状态,关联工程部位信息pdf(只有电签成功,才修改) liuYc 2023-03-16 ==============
                 //TODO ============== 电签成功,修改试验状态,关联工程部位信息pdf(只有电签成功,才修改) liuYc 2023-03-16 ==============
@@ -459,26 +459,10 @@ public class TaskServiceImpl extends BaseServiceImpl<TaskMapper, Task> implement
                     //已废除
                     //已废除
                     this.iTrialSelfInspectionRecordService.updateTrialSelfInspectionRecordStatusFC(taskApprovalVO);
                     this.iTrialSelfInspectionRecordService.updateTrialSelfInspectionRecordStatusFC(taskApprovalVO);
                 }
                 }
-
             }
             }
             //删除掉对应批次
             //删除掉对应批次
             this.taskBatchService.deletedById(batchId);
             this.taskBatchService.deletedById(batchId);
-            try {
-                //查询是否还存在对应批次(时间升序)
-                List<TaskBatch> taskBatches = this.taskBatchService.list(Wrappers.<TaskBatch>lambdaQuery().eq(TaskBatch::getCreateUser, AuthUtil.getUserId()).orderByAsc(TaskBatch::getCreateTime));
-                if (taskBatches != null && taskBatches.size() > 0) {
-                    TaskBatch taskBatch = taskBatches.get(0);
-                    //获取业务参数集合
-                    taskApprovalVOS = JSONArray.parseArray(JSONObject.toJSONString(taskBatch.getJsonData()), TaskApprovalVO.class);
-                    batchId = taskBatch.getId().toString();
-                } else {
-                    logger.info("【任务审核】已无等待电签批次!当前线程结束即将释放。");
-                    isContinue = false;
-                }
-            } catch (Exception e) {
-                isContinue = false;
-                e.printStackTrace();
-            }
+            isContinue = false;
         }
         }
     }
     }
 
 

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

@@ -209,7 +209,7 @@ public class EVisaServiceImpl implements EVisaService {
     @Override
     @Override
     public String eVisaContractSeal(EVisaTaskApprovalVO task, String finalPdfUrl) {
     public String eVisaContractSeal(EVisaTaskApprovalVO task, String finalPdfUrl) {
         //获取任务对应表格的电签配置(合同张)
         //获取任务对应表格的电签配置(合同张)
-        List<JSONObject> eVisaConfigList = this.taskClient.queryBusinessTableEVisaConfig(task.getParallelProcessInstanceId(), "true");
+        List<JSONObject> eVisaConfigList = this.taskClient.queryBusinessTableEVisaConfig(task.getParallelProcessInstanceId(), task.getUserId(),"true");
         if (eVisaConfigList == null || eVisaConfigList.size() == 0) {
         if (eVisaConfigList == null || eVisaConfigList.size() == 0) {
             //没有电签配置,默认当前任务为不签字审批,返回成功
             //没有电签配置,默认当前任务为不签字审批,返回成功
             return finalPdfUrl;
             return finalPdfUrl;
@@ -315,21 +315,21 @@ public class EVisaServiceImpl implements EVisaService {
         }
         }
 
 
         //获取任务对应表格的电签配置
         //获取任务对应表格的电签配置
-        List<JSONObject> eVisaConfigList = this.taskClient.queryBusinessTableEVisaConfig(task.getParallelProcessInstanceId(), "false");
+        List<JSONObject> eVisaConfigList = this.taskClient.queryBusinessTableEVisaConfig(task.getParallelProcessInstanceId(),task.getUserId(), "false");
         if (eVisaConfigList == null || eVisaConfigList.size() == 0) {
         if (eVisaConfigList == null || eVisaConfigList.size() == 0) {
             //没有电签配置,默认当前任务为不签字审批,返回成功
             //没有电签配置,默认当前任务为不签字审批,返回成功
             return SUCCESS + "@@@@" + taskFile.getApprovalFileList().get(0).getFileUrl();
             return SUCCESS + "@@@@" + taskFile.getApprovalFileList().get(0).getFileUrl();
         }
         }
 
 
         //获取当前用户的证书信息
         //获取当前用户的证书信息
-        List<SignPfxFile> userPfxList = this.signPfxClient.querySignPfxByUserIdOrContractId(AuthUtil.getUserId().toString(), "");
+        List<SignPfxFile> userPfxList = this.signPfxClient.querySignPfxByUserIdOrContractId(task.getUserId().toString(), "");
         if (userPfxList == null || userPfxList.size() <= 0) {
         if (userPfxList == null || userPfxList.size() <= 0) {
             //没有签章,不执行电签
             //没有签章,不执行电签
             return NOT_PFX_OR_FILE;
             return NOT_PFX_OR_FILE;
         }
         }
 
 
         //上锁
         //上锁
-        if (DistributedRedisLock.acquire(AuthUtil.getUserId().toString(), batch)) {
+        if (DistributedRedisLock.acquire(task.getUserId().toString(), batch)) {
             try {
             try {
                 //获取需要签章的数据
                 //获取需要签章的数据
                 List<TaskApprovalVO.ApprovalFile> files = taskFile.getApprovalFileList();
                 List<TaskApprovalVO.ApprovalFile> files = taskFile.getApprovalFileList();
@@ -346,9 +346,9 @@ public class EVisaServiceImpl implements EVisaService {
                     for (JSONObject eVisaConfig : eVisaConfigList) {
                     for (JSONObject eVisaConfig : eVisaConfigList) {
                         //设置签章策略
                         //设置签章策略
                         SealStrategyVO vo = new SealStrategyVO();
                         SealStrategyVO vo = new SealStrategyVO();
-                        vo.setSealCode(EVisaConstant.SIGN_SEAL_CODE + AuthUtil.getUserId());
-                        vo.setSealPassword(AuthUtil.getUserId().toString().substring(0, EVisaConstant.USER_ID_SUB));
-                        vo.setSealPerson(AuthUtil.getNickName());
+                        vo.setSealCode(EVisaConstant.SIGN_SEAL_CODE + task.getUserId());
+                        vo.setSealPassword(task.getUserId().toString().substring(0, EVisaConstant.USER_ID_SUB));
+                        vo.setSealPerson(task.getNickName());
                         //设置签字文件
                         //设置签字文件
                         vo.setImageUrl(userPfxList.get(0).getSignatureFileUrl());
                         vo.setImageUrl(userPfxList.get(0).getSignatureFileUrl());
                         vo.setSealType("3");
                         vo.setSealType("3");
@@ -387,7 +387,7 @@ public class EVisaServiceImpl implements EVisaService {
             }
             }
         }
         }
         //释放锁
         //释放锁
-        DistributedRedisLock.release(AuthUtil.getUserId().toString());
+        DistributedRedisLock.release(task.getUserId().toString());
 
 
         return resultMessage;
         return resultMessage;
     }
     }

+ 4 - 10
blade-service/blade-manager/src/main/java/com/mixsmart/utils/CustomFunction.java

@@ -321,6 +321,9 @@ public class CustomFunction {
 	public static Object count(Object data) {
 	public static Object count(Object data) {
 		List<Object> list=obj2ListNe(data);
 		List<Object> list=obj2ListNe(data);
 		if(ListUtils.isNotEmpty(list)){
 		if(ListUtils.isNotEmpty(list)){
+			if(list.stream().anyMatch(e->StringUtils.handleNull(e).contains(":"))){
+				return list.stream().filter(StringUtils::isNotEmpty).count();
+			}
 			return   list.stream().filter(StringUtils::isNumber).map(StringUtils::handleNull).mapToDouble(Double::parseDouble).count();
 			return   list.stream().filter(StringUtils::isNumber).map(StringUtils::handleNull).mapToDouble(Double::parseDouble).count();
 		}
 		}
 		return "";
 		return "";
@@ -1634,6 +1637,7 @@ public class CustomFunction {
 			double designD=Double.parseDouble(design.toString());
 			double designD=Double.parseDouble(design.toString());
 			double xND=Double.parseDouble(xN.toString());
 			double xND=Double.parseDouble(xN.toString());
 			String devStr = dev.toString();
 			String devStr = dev.toString();
+			devStr=devStr.replaceAll("[\\[\\]]+","");
 			double min=0;
 			double min=0;
 			double max=0;
 			double max=0;
 			devStr=devStr.replaceAll("\\s+","");
 			devStr=devStr.replaceAll("\\s+","");
@@ -2762,16 +2766,6 @@ public class CustomFunction {
 		return "";
 		return "";
 	}
 	}
 
 
-	/*public static void main(String[] args) {
-		Map<String,Object> map =new HashMap<>();
-		map.put("A","13.3");
-		map.put("B","13.5");
-//		map.put("A","17*20");
-//		map.put("B","18*18");
-//		Expression.parse("(A-B)*10").calculate(map);
-		System.out.println(Expression.parse("(A-B)*10").calculate(map).toString());
-
-	}*/
 
 
 
 
 }
 }

+ 9 - 1
blade-service/blade-manager/src/main/java/com/mixsmart/utils/FormulaUtils.java

@@ -269,6 +269,14 @@ public class FormulaUtils {
 
 
     /*从元素名称中解析项目名称*/
     /*从元素名称中解析项目名称*/
     public static  String parseItemName(String eName){
     public static  String parseItemName(String eName){
-        return StringUtils.handleNull(eName).replaceAll("^[^\\u4e00-\\u9fa5\\s]+","").split("[((].+[))]|_")[0];
+        String[] candidate= StringUtils.handleNull(eName).replaceAll("^[^\\u4e00-\\u9fa5]+","").replaceAll("\\s+","").split("[((].+[))]|_");
+        if(candidate.length>0){
+           return Arrays.stream(candidate).filter(e->!e.contains("实测项目")&&!e.contains("△")).findFirst().orElse(eName);
+        }
+        return eName;
     }
     }
+
+//    public static void main(String[] args) {
+//        System.out.println(parseItemName("实 测 项 目_3△_内轮廓高度(mm)_不小于设计值_实测值或实测偏差值"));
+//    }
 }
 }

+ 14 - 6
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/ArchiveTreeController.java

@@ -16,6 +16,7 @@ import org.springblade.core.tool.utils.Func;
 import org.springblade.manager.dto.ArchiveTreeContractAutoRuleMapDTO;
 import org.springblade.manager.dto.ArchiveTreeContractAutoRuleMapDTO;
 import org.springblade.manager.dto.ArchiveTreeDTO;
 import org.springblade.manager.dto.ArchiveTreeDTO;
 import org.springblade.manager.dto.ArchiveTreeSortDTO;
 import org.springblade.manager.dto.ArchiveTreeSortDTO;
+import org.springblade.manager.service.IArchiveTreeContractService;
 import org.springblade.manager.vo.ArchiveTreeVO2;
 import org.springblade.manager.vo.ArchiveTreeVO2;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RequestParam;
@@ -37,6 +38,8 @@ public class ArchiveTreeController extends BladeController {
 
 
     private final IArchiveTreeService archiveTreeService;
     private final IArchiveTreeService archiveTreeService;
 
 
+    private final IArchiveTreeContractService archiveTreeContractService;
+
     /**
     /**
      * 初始化归档树根节点
      * 初始化归档树根节点
      */
      */
@@ -89,6 +92,10 @@ public class ArchiveTreeController extends BladeController {
     @ApiOperation(value = "修改", notes = "传入ArchiveTree")
     @ApiOperation(value = "修改", notes = "传入ArchiveTree")
     public R update(@Valid @RequestBody ArchiveTree archiveTree) {
     public R update(@Valid @RequestBody ArchiveTree archiveTree) {
         archiveTree.setFullName(archiveTree.getNodeName());
         archiveTree.setFullName(archiveTree.getNodeName());
+        if (archiveTree.getProjectId() != null && archiveTree.getProjectId() > 0) {
+            archiveTreeContractService.UpdateByArchiveTree(archiveTree);
+        }
+
         return R.status(archiveTreeService.updateById(archiveTree));
         return R.status(archiveTreeService.updateById(archiveTree));
     }
     }
 
 
@@ -210,8 +217,9 @@ public class ArchiveTreeController extends BladeController {
     @ApiOperation(value = "保存立卷规则设置", notes = "传入archiveAutoType规则类型,nodeIds逗号拼接选择节点id")
     @ApiOperation(value = "保存立卷规则设置", notes = "传入archiveAutoType规则类型,nodeIds逗号拼接选择节点id")
     public R saveArchiveAutoRule(@ApiParam(value = "立卷规则", required = true) @RequestParam Integer archiveAutoType,
     public R saveArchiveAutoRule(@ApiParam(value = "立卷规则", required = true) @RequestParam Integer archiveAutoType,
                                  @ApiParam(value = "主键集合", required = true) @RequestParam String selectNodeIds,
                                  @ApiParam(value = "主键集合", required = true) @RequestParam String selectNodeIds,
-                                 @ApiParam(value = "是否wbs节点", required = true) @RequestParam Boolean iswbsNode) {
-        return R.status(archiveTreeService.saveArchiveAutoRule(archiveAutoType,selectNodeIds,iswbsNode));
+                                 @ApiParam(value = "是否wbs节点", required = true) @RequestParam Boolean iswbsNode,
+                                 Long projectId) {
+        return R.status(archiveTreeService.saveArchiveAutoRule(archiveAutoType,selectNodeIds,iswbsNode,projectId));
     }
     }
 
 
 
 
@@ -227,8 +235,8 @@ public class ArchiveTreeController extends BladeController {
      * 取消立卷规则设置
      * 取消立卷规则设置
      */
      */
     @PostMapping("/removeArchiveAutoRule")
     @PostMapping("/removeArchiveAutoRule")
-    public R removeArchiveAutoRule(Long nodeId,boolean iswbsNode) {
-        Map<String, String> map = archiveTreeService.removeArchiveAutoRule(nodeId, iswbsNode);
+    public R removeArchiveAutoRule(Long nodeId,boolean iswbsNode,Long projectId) {
+        Map<String, String> map = archiveTreeService.removeArchiveAutoRule(nodeId, iswbsNode,projectId);
         return R.data(map);
         return R.data(map);
     }
     }
 
 
@@ -236,8 +244,8 @@ public class ArchiveTreeController extends BladeController {
      * 查看立卷规则设置
      * 查看立卷规则设置
      */
      */
     @PostMapping("/getArchiveAutoRule")
     @PostMapping("/getArchiveAutoRule")
-    public R getArchiveAutoRule(Long nodeId,boolean iswbsNode) {
-        Map<String, Object> ruleMap=archiveTreeService.getArchiveAutoRule(nodeId,iswbsNode);
+    public R getArchiveAutoRule(Long nodeId,boolean iswbsNode,Long projectId,Long wbsNode2ArchiveTreeNodeId,String wbsId) {
+        Map<String, Object> ruleMap=archiveTreeService.getArchiveAutoRule(nodeId,iswbsNode,projectId,wbsNode2ArchiveTreeNodeId,wbsId);
         return R.data(ruleMap);
         return R.data(ruleMap);
     }
     }
 
 

+ 2 - 2
blade-service/blade-manager/src/main/java/org/springblade/manager/feign/EVisaConfigClientImpl.java

@@ -38,7 +38,7 @@ public class EVisaConfigClientImpl implements EVisaConfigClient {
     }
     }
 
 
     @Override
     @Override
-    public List<JSONObject> queryEVisaConfigByTableIds(List<String> tableIds, String contractId, String isFinal) {
+    public List<JSONObject> queryEVisaConfigByTableIds(List<String> tableIds, String contractId, String isFinal,Long userId) {
         List<JSONObject> jsonResult = new ArrayList<>();
         List<JSONObject> jsonResult = new ArrayList<>();
 
 
         List<TextdictInfo> configResult;
         List<TextdictInfo> configResult;
@@ -51,7 +51,7 @@ public class EVisaConfigClientImpl implements EVisaConfigClient {
             //需要获取这条任务对应合同段下当前用户的岗位
             //需要获取这条任务对应合同段下当前用户的岗位
             System.out.println(AuthUtil.getUserId());
             System.out.println(AuthUtil.getUserId());
             System.out.println(SecureUtil.getUserId());
             System.out.println(SecureUtil.getUserId());
-            List<SaveUserInfoByProjectDTO> contractUserList = this.saveUserInfoByProjectService.list(Wrappers.<SaveUserInfoByProjectDTO>lambdaQuery().eq(SaveUserInfoByProjectDTO::getContractId, contractId).eq(SaveUserInfoByProjectDTO::getUserId, AuthUtil.getUserId()));
+            List<SaveUserInfoByProjectDTO> contractUserList = this.saveUserInfoByProjectService.list(Wrappers.<SaveUserInfoByProjectDTO>lambdaQuery().eq(SaveUserInfoByProjectDTO::getContractId, contractId).eq(SaveUserInfoByProjectDTO::getUserId, userId));
 
 
             List<String> userRoleList;
             List<String> userRoleList;
             if(contractUserList != null && contractUserList.size() > 0){
             if(contractUserList != null && contractUserList.size() > 0){

+ 13 - 6
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/SubTable.java

@@ -7,7 +7,6 @@ import org.springblade.manager.dto.ElementData;
 import org.springblade.manager.dto.FormData;
 import org.springblade.manager.dto.FormData;
 
 
 import java.util.*;
 import java.util.*;
-import java.util.logging.Handler;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
 
 
 /**
 /**
@@ -63,19 +62,27 @@ public class SubTable {
                    String key = entry.getKey();
                    String key = entry.getKey();
                    String[] nameAndDesign=key.split("@");
                    String[] nameAndDesign=key.split("@");
                    List<String> values=entry.getValue();
                    List<String> values=entry.getValue();
+                   /*写人的行数*/
                    int count = (int)Math.ceil((double)values.size()/(double)ROW_SIZE);
                    int count = (int)Math.ceil((double)values.size()/(double)ROW_SIZE);
-                   int count2=count/STEP[0];
-                   itemNameList.addAll(Collections.nCopies(count2,nameAndDesign[0]));
-                   designList.addAll(Collections.nCopies(count2,nameAndDesign[1]));
+//                   int count2=count/STEP[0];
+                   itemNameList.addAll(Collections.nCopies(count,nameAndDesign[0]));
+                   if(nameAndDesign.length>=2) {
+                       designList.addAll(Collections.nCopies(count, nameAndDesign[1]));
+                   }else{
+                       designList.addAll(Collections.nCopies(count, ""));
+                   }
                    dataList.addAll(values);
                    dataList.addAll(values);
-                   if(count>values.size()){
-                       dataList.addAll(Collections.nCopies(count-values.size(),""));
+                   if(count*ROW_SIZE>values.size()){
+                       dataList.addAll(Collections.nCopies(count*ROW_SIZE-values.size(),""));
                    }
                    }
                }
                }
                /*写入元素*/
                /*写入元素*/
                FormulaUtils.write(itemName,itemNameList,true);
                FormulaUtils.write(itemName,itemNameList,true);
                FormulaUtils.write(design,designList,true);
                FormulaUtils.write(design,designList,true);
                FormulaUtils.write(data,dataList,true);
                FormulaUtils.write(data,dataList,true);
+               itemName.setUpdate(1);
+               design.setUpdate(1);
+               data.setUpdate(1);
            }
            }
    }
    }
 
 

+ 0 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/TableElementConverter.java

@@ -168,7 +168,6 @@ public class TableElementConverter implements ITableElementConverter {
                                  eds.add(new ElementData(Func.toInt(sa[2]),Func.toInt(sa[1]),val,Func.toInt(sa[3]),Func.toInt(sa[4])));
                                  eds.add(new ElementData(Func.toInt(sa[2]),Func.toInt(sa[1]),val,Func.toInt(sa[3]),Func.toInt(sa[4])));
                             });
                             });
                             log.append(fd.getEName()).append(fd.getCode()).append("定位信息不存在;");
                             log.append(fd.getEName()).append(fd.getCode()).append("定位信息不存在;");
-                           // StaticLog.error("FORMULA_LOG@元素{}定位信息不存在,请检查配置",fd.getTableName()+StringPool.COLON+fd.getKey());
                         }
                         }
                     }
                     }
                 }
                 }

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

@@ -21,6 +21,8 @@ import org.springblade.manager.entity.ArchiveAutoRuleWbs;
 import org.springblade.manager.vo.ArchiveAutoRuleWbsVO;
 import org.springblade.manager.vo.ArchiveAutoRuleWbsVO;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+
+import java.util.Date;
 import java.util.List;
 import java.util.List;
 
 
 /**
 /**
@@ -43,4 +45,6 @@ public interface ArchiveAutoRuleWbsMapper extends BaseMapper<ArchiveAutoRuleWbs>
 	int removeNodeForArchiveAutoRule_Group(@Param("archiveAutoGroupId") Long archiveAutoGroupId,
 	int removeNodeForArchiveAutoRule_Group(@Param("archiveAutoGroupId") Long archiveAutoGroupId,
 										   @Param("projectId") Long projectId);
 										   @Param("projectId") Long projectId);
 
 
+	int removeArchiveAutoRule(@Param("id") Long id, @Param("time") Date time);
+
 }
 }

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

@@ -14,7 +14,7 @@
         <result column="archive_auto_type" property="archiveAutoType"/>
         <result column="archive_auto_type" property="archiveAutoType"/>
         <result column="archive_auto_group_id" property="archiveAutoGroupId"/>
         <result column="archive_auto_group_id" property="archiveAutoGroupId"/>
         <result column="project_id" property="projectId"/>
         <result column="project_id" property="projectId"/>
-        <result column="delete" property="delete"/>
+        <result column="is_deleted" property="isDeleted"/>
     </resultMap>
     </resultMap>
 
 
 
 
@@ -33,4 +33,14 @@
           and archive_auto_group_id = #{archiveAutoGroupId}
           and archive_auto_group_id = #{archiveAutoGroupId}
     </update>
     </update>
 
 
+    <update id="removeArchiveAutoRule">
+        /**取消同一组的分类并卷规则*/
+        update m_archive_auto_rule_wbs
+        set
+            is_deleted = 1,
+            update_time = #{time}
+        where
+            id = #{id}
+    </update>
+
 </mapper>
 </mapper>

+ 6 - 3
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeMapper.java

@@ -39,11 +39,14 @@ public interface ArchiveTreeMapper extends BaseMapper<ArchiveTree> {
      * @return
      * @return
      */
      */
     int removeAllSonNodeIdsForArchiveAutoRule_1(@Param("archiveAutoType") Integer archiveAutoType,
     int removeAllSonNodeIdsForArchiveAutoRule_1(@Param("archiveAutoType") Integer archiveAutoType,
-                                                @Param("ancestors") String ancestors);
+                                                @Param("ancestors") String ancestors,
+                                                @Param("nodeId") Long nodeId);
     int removeAllSonNodeIdsForArchiveAutoRule_2(@Param("archiveAutoType") Integer archiveAutoType,
     int removeAllSonNodeIdsForArchiveAutoRule_2(@Param("archiveAutoType") Integer archiveAutoType,
-                                                @Param("ancestors") String ancestors);
+                                                @Param("ancestors") String ancestors,
+                                                @Param("nodeId") Long nodeId);
     int removeAllSonNodeIdsForArchiveAutoRule_3(@Param("archiveAutoType") Integer archiveAutoType,
     int removeAllSonNodeIdsForArchiveAutoRule_3(@Param("archiveAutoType") Integer archiveAutoType,
-                                                @Param("ancestors") String ancestors);
+                                                @Param("ancestors") String ancestors,
+                                                @Param("nodeId") Long nodeId);
     int removeNodeForArchiveAutoRule_Group(@Param("archiveAutoGroupId") Long archiveAutoGroupId);
     int removeNodeForArchiveAutoRule_Group(@Param("archiveAutoGroupId") Long archiveAutoGroupId);
     /**
     /**
      * 查看分类并卷规则-获取大类所有节点
      * 查看分类并卷规则-获取大类所有节点

+ 7 - 3
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeMapper.xml

@@ -315,8 +315,9 @@
         set
         set
             archive_auto_node_id = NULL
             archive_auto_node_id = NULL
         where
         where
-            is_deleted = 0
-          and ancestors like concat('', #{ancestors}, '%');
+          is_deleted = 0
+          and ancestors like concat('', #{ancestors}, '%')
+          or id=#{nodeId} ;
 
 
 
 
         update m_archive_tree
         update m_archive_tree
@@ -326,7 +327,8 @@
             is_deleted = 0
             is_deleted = 0
           and ancestors like concat('', #{ancestors}, '%')
           and ancestors like concat('', #{ancestors}, '%')
             /*取消规则 只取消规则与自己一致的*/
             /*取消规则 只取消规则与自己一致的*/
-          and archive_auto_type = #{archiveAutoType} ;
+          and archive_auto_type = #{archiveAutoType}
+          or id=#{nodeId} ;
     </update>
     </update>
 
 
     <update id="removeAllSonNodeIdsForArchiveAutoRule_3">
     <update id="removeAllSonNodeIdsForArchiveAutoRule_3">
@@ -339,6 +341,7 @@
           and ancestors like concat('', #{ancestors}, '%')
           and ancestors like concat('', #{ancestors}, '%')
             /*取消规则 只取消规则与自己一致的*/
             /*取消规则 只取消规则与自己一致的*/
           and archive_auto_type = #{archiveAutoType}
           and archive_auto_type = #{archiveAutoType}
+          or id=#{nodeId} ;
     </update>
     </update>
     <update id="removeAllSonNodeIdsForArchiveAutoRule_2">
     <update id="removeAllSonNodeIdsForArchiveAutoRule_2">
         /*取消单个节点的分类并卷规则*/
         /*取消单个节点的分类并卷规则*/
@@ -353,6 +356,7 @@
           and ancestors like concat('', #{ancestors}, '%')
           and ancestors like concat('', #{ancestors}, '%')
             /*取消规则 只取消规则与自己一致的*/
             /*取消规则 只取消规则与自己一致的*/
           and archive_auto_type = #{archiveAutoType}
           and archive_auto_type = #{archiveAutoType}
+          or id=#{nodeId} ;
     </update>
     </update>
 
 
     <update id="removeNodeForArchiveAutoRule_Group">
     <update id="removeNodeForArchiveAutoRule_Group">

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

@@ -67,6 +67,7 @@
     <resultMap id="treeNodeResultMap6" type="org.springblade.manager.vo.WbsTreeContractVO6">
     <resultMap id="treeNodeResultMap6" type="org.springblade.manager.vo.WbsTreeContractVO6">
         <id column="id" property="id"/>
         <id column="id" property="id"/>
         <result column="parentId" property="parentId"/>
         <result column="parentId" property="parentId"/>
+        <result column="primaryKeyId" property="pKeyId"/>
         <result column="title" property="title"/>
         <result column="title" property="title"/>
         <result column="value" property="value"/>
         <result column="value" property="value"/>
         <result column="key" property="key"/>
         <result column="key" property="key"/>
@@ -439,6 +440,7 @@
 
 
     <select id="tree6" resultMap="treeNodeResultMap6">
     <select id="tree6" resultMap="treeNodeResultMap6">
         SELECT
         SELECT
+        d.p_key_id AS "primaryKeyId",
         d.id,
         d.id,
         d.parent_id AS "parentId",
         d.parent_id AS "parentId",
         IFNULL(if(length(trim(full_name)) > 0, full_name, node_name),node_name) AS title,
         IFNULL(if(length(trim(full_name)) > 0, full_name, node_name),node_name) AS title,

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

@@ -67,7 +67,7 @@ public interface IArchiveTreeContractService extends BaseService<ArchiveTreeCont
 
 
 	List<ArchiveTreeContractVO2> tree2(String tenantI,Integer disPlayTree,Integer nodeType,Long projectId, Long contractId);
 	List<ArchiveTreeContractVO2> tree2(String tenantI,Integer disPlayTree,Integer nodeType,Long projectId, Long contractId);
 
 
-
+	List<ArchiveTreeContractVO2> tree2Root(String tenantId, Integer disPlayTree, Integer nodeType, Long projectId, Long contractId);
 
 
 	List<ArchiveTreeContract> selectByParentIdOrId(String id);
 	List<ArchiveTreeContract> selectByParentIdOrId(String id);
 
 
@@ -79,7 +79,7 @@ public interface IArchiveTreeContractService extends BaseService<ArchiveTreeCont
 
 
 	boolean submitDisplayConfigTree(String ids);
 	boolean submitDisplayConfigTree(String ids);
 
 
-	public boolean syncProjectTree(ArchiveTreeContract dstNode);
-
+	boolean syncProjectTree(ArchiveTreeContract dstNode);
 
 
+	boolean UpdateByArchiveTree(ArchiveTree archiveTree);
 }
 }

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

@@ -44,11 +44,11 @@ public interface IArchiveTreeService extends BaseService<ArchiveTree> {
 	 *项目级立卷规则新增
 	 *项目级立卷规则新增
 	 * @return
 	 * @return
 	 */
 	 */
-	boolean saveArchiveAutoRule(Integer archiveAutoType,String nodeIds,boolean iswbsNode);
+	boolean saveArchiveAutoRule(Integer archiveAutoType,String nodeIds,boolean iswbsNode,Long projectId);
 
 
 
 
 
 
-	Map<String,Object> getArchiveAutoRule(Long id,boolean iswbsNode);
+	Map<String,Object> getArchiveAutoRule(Long id,boolean iswbsNode,Long projectId,Long wbsNode2ArchiveTreeNodeId,String wbsId);
 
 
 	/**
 	/**
 	 *项目级立卷规则更新
 	 *项目级立卷规则更新
@@ -63,5 +63,5 @@ public interface IArchiveTreeService extends BaseService<ArchiveTree> {
 	 * @param iswbsNode
 	 * @param iswbsNode
 	 * @return
 	 * @return
 	 */
 	 */
-	Map<String,String> removeArchiveAutoRule(Long nodeId,boolean iswbsNode);
+	Map<String,String> removeArchiveAutoRule(Long nodeId,boolean iswbsNode,Long projectId);
 }
 }

+ 227 - 13
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveAutoRuleWbsServiceImpl.java

@@ -16,7 +16,13 @@
  */
  */
 package org.springblade.manager.service.impl;
 package org.springblade.manager.service.impl;
 
 
+import com.alibaba.druid.sql.dialect.h2.visitor.H2ASTVisitor;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import org.springblade.archive.entity.ArchivesAuto;
+import org.springblade.business.entity.ArchiveFile;
+import org.springblade.business.feign.ArchiveFileClient;
 import org.springblade.manager.entity.ArchiveAutoRuleWbs;
 import org.springblade.manager.entity.ArchiveAutoRuleWbs;
+import org.springblade.manager.entity.ArchiveTreeContract;
 import org.springblade.manager.vo.ArchiveAutoRuleWbsVO;
 import org.springblade.manager.vo.ArchiveAutoRuleWbsVO;
 import org.springblade.manager.mapper.ArchiveAutoRuleWbsMapper;
 import org.springblade.manager.mapper.ArchiveAutoRuleWbsMapper;
 import org.springblade.manager.service.IArchiveAutoRuleWbsService;
 import org.springblade.manager.service.IArchiveAutoRuleWbsService;
@@ -24,6 +30,8 @@ import org.springblade.core.mp.base.BaseServiceImpl;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 
 
+import java.util.*;
+
 /**
 /**
  *  服务实现类
  *  服务实现类
  *
  *
@@ -33,6 +41,8 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 @Service
 @Service
 public class ArchiveAutoRuleWbsServiceImpl extends BaseServiceImpl<ArchiveAutoRuleWbsMapper, ArchiveAutoRuleWbs> implements IArchiveAutoRuleWbsService {
 public class ArchiveAutoRuleWbsServiceImpl extends BaseServiceImpl<ArchiveAutoRuleWbsMapper, ArchiveAutoRuleWbs> implements IArchiveAutoRuleWbsService {
 
 
+	private ArchiveFileClient archiveFileClient;
+
 	@Override
 	@Override
 	public IPage<ArchiveAutoRuleWbsVO> selectArchiveAutoRuleWbsPage(IPage<ArchiveAutoRuleWbsVO> page, ArchiveAutoRuleWbsVO archiveAutoRuleWbs) {
 	public IPage<ArchiveAutoRuleWbsVO> selectArchiveAutoRuleWbsPage(IPage<ArchiveAutoRuleWbsVO> page, ArchiveAutoRuleWbsVO archiveAutoRuleWbs) {
 		return page.setRecords(baseMapper.selectArchiveAutoRuleWbsPage(page, archiveAutoRuleWbs));
 		return page.setRecords(baseMapper.selectArchiveAutoRuleWbsPage(page, archiveAutoRuleWbs));
@@ -45,29 +55,233 @@ public class ArchiveAutoRuleWbsServiceImpl extends BaseServiceImpl<ArchiveAutoRu
 		//步骤四:按照单独,分类,默认的顺序执行组卷流程。
 		//步骤四:按照单独,分类,默认的顺序执行组卷流程。
 	}
 	}
 
 
+
+	/**
+	 * 检查当前案卷的文件集合是否在规格内,能否开始组卷。
+	 * return
+	 * 0不能组卷,当前文件入待组卷集合,还能试加文件。
+	 * 1可以组卷,当前文件加入待组卷集合后开始组卷。
+	 * -1 不可组卷,当前文件不能加入待组卷集合, 待组卷集合要组卷了。
+	 * null 程序出错了
+	 */
+	private Integer checkSpecificationSize(int SpecificationSize,int archivesSize){
+		//按照当前目录节点的参数(卷盒规格)进行页数组合,
+		// 30MM默认为300页组成一卷、400MM默认为400页组成一卷、50MM默认为500页组成一卷、60MM默认为600组成一卷。
+		//注意:允许组卷上浮区间为100页
+		//意思是如果A\B两个文件进行并卷组卷,总页数规格为300页,但是A+B的文件数为350页,已经超过固定规格,但是上浮区间在100以内,则允许这样组卷。
+		//超过300之后,则不在继续与其他文件进行并卷组卷了。
+		int SpecificationSizeMax =SpecificationSize+100;
+
+		if(archivesSize<SpecificationSize){
+			//小于规格的 返回true ,当前文件加入待组卷集合,还可以试加文件,未到组卷规格
+			return 0;
+		}
+		if(archivesSize==SpecificationSize){
+			//等于规则的  当前文件加入待组卷集合,待组卷集合可以组卷了。
+			return 1;
+		}
+		if(archivesSize<=SpecificationSizeMax){
+			//小于等于规格上浮区间,当前文件加入待组卷集合,当前文件集合可以组卷了
+			return 1;
+		}
+		if(archivesSize>SpecificationSizeMax){
+			//大于规格上浮区间,当前文件不能加入当前待组卷集合,先把当前待组卷集合的文件先组卷完成,清空待组卷集合后再重新计算检查当前文件。
+			return -1;
+		}
+
+		return null;
+	}
+
+	/**
+	 * 单独组卷规则组卷
+	 * @param waitArchiveFiles
+	 * @param node
+	 */
+	private void createArchive3(List<ArchiveFile> waitArchiveFiles,ArchiveTreeContract node){
+		//1.创建新案卷
+		ArchivesAuto archivesAuto = new ArchivesAuto();
+		//archivesAuto.setProjectId();
+		//archivesAuto.setContractId();
+		//archivesAuto.setName();//案卷题名
+		//archivesAuto.setFileNumber();//档号
+		//archivesAuto.setMicron();//微缩号
+		//archivesAuto.setUnit();//单位
+		//archivesAuto.setQuantity();//数量/单位
+		//archivesAuto.setSpecification();//规格
+		//archivesAuto.setStartDate();
+		//archivesAuto.setEndDate();
+		//archivesAuto.setStorageTime();//保管时间
+		//archivesAuto.setSecretLevel();//保密级别
+		//archivesAuto.setCarrierType();//载体类型
+		//archivesAuto.setKeywords();//主题词
+		//archivesAuto.setStorageLocation();//存放位置
+		//archivesAuto.setIsArchive(1);//已归档
+		//archivesAuto.setRemark();//备注
+		//archivesAuto.setRollDate();//立卷日期
+		//archivesAuto.setRollor();//立卷人
+		//archivesAuto.setNodeId();//归档树节点
+		//archivesAuto.setOutUrl();
+		//archivesAuto.setFileN();//文件数量
+		//archivesAuto.setPageN();//案卷页数
+		//archivesAuto.setMileage();
+		//archivesAuto.setFileType();
+		//archivesAuto.setSize();
+		//archivesAuto.setTreeSort();
+		//archivesAuto.setIsOpen();
+		//archivesAuto.setIscheck();
+		//archivesAuto.setIsAutoFile();
+
+		//2.设置文件所属案卷,组卷状态
+	}
+
+
 	/**
 	/**
 	 * 单租组卷流程  节点下的文件只在当前节点下组卷
 	 * 单租组卷流程  节点下的文件只在当前节点下组卷
 	 */
 	 */
-	private void archiveAutoMethod3(){
+	private void archiveAutoMethod3(List<ArchiveTreeContract> list){
 		//步骤1:遍历节点集合
 		//步骤1:遍历节点集合
-		//步骤2:获取当前节点的案卷规格
-		//步骤3:查询节点下的未归档文件
-		//步骤4:遍历未归档文件
-		//步骤5:判断文件是否存在分盒设置-》走分盒组卷流程
-		//步骤6:计算和判断待组卷文件集合是否达到组卷要求,达到要求创建案卷,案卷归属当前节点,案卷下文件改为已组卷
+		for(ArchiveTreeContract node:list){
+			//步骤2:获取当前节点的案卷规格
+			int specificationSize=300;//TODO
+			//步骤3:查询节点下的未归档文件
+			List<ArchiveFile> archiveFiles = archiveFileClient.listWrappers(Wrappers.<ArchiveFile>lambdaQuery()
+					.eq(ArchiveFile::getNodeId, node)
+					.eq(ArchiveFile::getIsArchive, 0)
+					.eq(ArchiveFile::getIsDeleted,0)
+					.orderByAsc(ArchiveFile::getSort));
+			//步骤4:遍历未归档文件
+			//待组卷文件集合
+			List<ArchiveFile> waitArchiveFiles = new ArrayList<>();
+			//待组卷文件总页数
+			int archivesSize=0;
+			if(archiveFiles!=null){
+				int archiveFilesSize=0;
+				for(ArchiveFile file:archiveFiles){
+					archiveFilesSize++;
+					//步骤5:判断文件是否存在分盒设置
+					if(file.getBoxNumber()!=null){
+						//TODO 走分盒组卷流程
+					}else{
+						//单独组卷流程
+						//步骤6:计算和判断待组卷文件集合是否达到组卷要求,达到要求创建案卷,案卷归属当前节点,案卷下文件改为已组卷
+						Integer filePage = file.getFilePage();
+						archivesSize=archivesSize+filePage;
+						Integer checkStatus = checkSpecificationSize(specificationSize, archivesSize);
+						//步骤6.1未到规格 不组卷
+						if(checkStatus==0){
+							waitArchiveFiles.add(file);
+							//判断是否最后一个文件
+							if(archiveFilesSize==archiveFiles.size()){
+								//TODO 最后一个文件直接将waitArchiveFiles组卷
+							}else{
+								continue;
+							}
+						}
+						//步骤6.2达到规格 可以组一卷
+						if(checkStatus==1){
+							waitArchiveFiles.add(file);
+							//TODO 将waitArchiveFiles组卷
+							//将待组卷文件集合,总页数还原初始值,
+							waitArchiveFiles.clear();
+							archivesSize=0;
+						}
+						//步骤6.3超出规格---开始
+						if(checkStatus==-1){
+							//步骤6.3.1如果waitArchiveFiles集合size>0,先将集合中文件组卷。再重新计算当前文件
+							if(waitArchiveFiles.size()>0){
+								//步骤6.3.1_1 TODO 将waitArchiveFiles组卷,然后将待组卷文件集合,总页数还原初始值,
+								waitArchiveFiles.clear();
+								//步骤6.3.1_2保存当前文件进入待组卷集合,待组卷页数=当前文件页数
+								waitArchiveFiles.add(file);
+								archivesSize=filePage;
+								//步骤6.3.1_3当前文件再次检查规格
+								Integer checkStatusAgain = checkSpecificationSize(specificationSize, archivesSize);
+								//步骤6.3.1_3_1未到规格
+								if(checkStatusAgain==0){
+									//判断是否最后一个文件
+									if(archiveFilesSize==archiveFiles.size()){
+										//TODO 最后一个文件直接将waitArchiveFiles组卷
+									}else{
+										continue;
+									}
+								}else{
+									//步骤6.3.1_3_2单个文件 就达到规格或超出规格 直接组卷
+									if(checkStatusAgain!=null){
+										//TODO 直接将waitArchiveFiles组卷
+										//将待组卷文件集合,总页数还原初始值,
+										waitArchiveFiles.clear();
+										archivesSize=0;
+									}
+								}
+							}else{
+								//步骤6.3.2如果waitArchiveFiles集合size=0,说明当前文件已经超过规格,直接将当前文件组卷
+								waitArchiveFiles.add(file);
+								//TODO 直接将waitArchiveFiles组卷
+								waitArchiveFiles.clear();
+								archivesSize=0;
+							}
+						}
+						//步骤6.3超出规格---结束
+					}
+				}
+			}
+
+		}
+
+
+
+
+
 	}
 	}
 
 
 	/**
 	/**
 	 * 分类并卷组卷  设置分类的节点下只有一个案卷,节点下的所有文件都组成这个案卷。如果设置分类节点(select=1的)多个,案卷归属排序第一个节点。
 	 * 分类并卷组卷  设置分类的节点下只有一个案卷,节点下的所有文件都组成这个案卷。如果设置分类节点(select=1的)多个,案卷归属排序第一个节点。
 	 */
 	 */
-	private void archiveAutoMethod2(){
+	private void archiveAutoMethod2(List<ArchiveTreeContract> list){
+
+		//分类并卷集合<groupId,List<文件>>
+		Map<Long,List<ArchiveFile>> archiveMap = new HashMap<>();
+
 		//步骤1:遍历节点集合
 		//步骤1:遍历节点集合
-		//步骤2:查询节点下的未归档文件
-		//步骤4:遍历未归档文件
-		//步骤5:判断文件是否存在分盒设置-》走分盒组卷流程
-		//步骤6:将文件按照<groupId,List<文件>>放入集合
-		//步骤7:将文件按照<groupId,List<文件>>放入集合
-		//步骤8:按集合创建案卷,每个group类的案卷归属顺序排第一个节点
+		for(ArchiveTreeContract node:list) {
+			//根据分组ID来创建唯一案卷
+			Long archiveAutoGroupId=node.getArchiveAutoGroupId();
+			//步骤2:查询节点下的未归档文件
+			List<ArchiveFile> archiveFiles = archiveFileClient.listWrappers(Wrappers.<ArchiveFile>lambdaQuery()
+					.eq(ArchiveFile::getNodeId, node)
+					.eq(ArchiveFile::getIsArchive, 0)
+					.eq(ArchiveFile::getIsDeleted,0)
+					.orderByAsc(ArchiveFile::getSort));
+			//步骤3:遍历未归档文件
+			if(archiveFiles!=null){
+				for(ArchiveFile file:archiveFiles){
+					//步骤4:判断文件是否存在分盒设置
+					if(file.getBoxNumber()!=null){
+						//走分盒流程
+					}else{
+						//分类并卷流程
+						//步骤5:将文件按照<groupId,List<文件>>放入集合
+						if(archiveMap.containsKey(archiveAutoGroupId)){
+							List<ArchiveFile> groupList = archiveMap.get(archiveAutoGroupId);
+							groupList.add(file);
+							archiveMap.put(archiveAutoGroupId,groupList);
+						}else{
+							List<ArchiveFile> groupList= new ArrayList<>();
+							groupList.add(file);
+							archiveMap.put(archiveAutoGroupId,groupList);
+						}
+					}
+				}
+			}
+		}
+		//步骤6:按集合创建案卷,每个group类的案卷归属顺序排第一个节点
+		Set<Map.Entry<Long, List<ArchiveFile>>> entries = archiveMap.entrySet();
+		for(Map.Entry<Long, List<ArchiveFile>> entry:entries){
+			Long key = entry.getKey();
+			List<ArchiveFile> archiveFiles = entry.getValue();
+			//TODO 一个key 组成一个案卷  案卷归属同个key的归档树节点select=1的第一个
+		}
+
 	}
 	}
 
 
 	/**
 	/**

+ 40 - 11
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeContractServiceImpl.java

@@ -185,6 +185,11 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 		return ForestNodeMergerEx.merge(baseMapper.tree2(tenantId, disPlayTree, nodeType,projectId,getAuthCode(contractId),getAuthContractId(contractId)));
 		return ForestNodeMergerEx.merge(baseMapper.tree2(tenantId, disPlayTree, nodeType,projectId,getAuthCode(contractId),getAuthContractId(contractId)));
 	}
 	}
 
 
+	@Override
+	public List<ArchiveTreeContractVO2> tree2Root(String tenantId, Integer disPlayTree, Integer nodeType, Long projectId, Long contractId) {
+
+		return ForestNodeMergerEx.mergeOnlyRoot(baseMapper.tree2(tenantId, disPlayTree, nodeType,projectId,getAuthCode(contractId),getAuthContractId(contractId)));
+	}
 
 
 
 
 	@Override
 	@Override
@@ -352,15 +357,13 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 			return false;
 			return false;
 		}
 		}
 
 
-		// 0,业主树同步, 1,根节点同步,  2. 建设单位或者施工单位同步添加合同段 3.  合同段内部同步
-
-
 		List<ArchiveTreeVO2> srcTrees = archiveTreeService.tree2(AuthUtil.getTenantId(), dstNode.getProjectId(),
 		List<ArchiveTreeVO2> srcTrees = archiveTreeService.tree2(AuthUtil.getTenantId(), dstNode.getProjectId(),
 				null, null,null,false);
 				null, null,null,false);
-		List<ArchiveTreeContractVO2> dstTrees = this.tree2(AuthUtil.getTenantId(),null,null,dstNode.getProjectId(),null);
+		List<ArchiveTreeContractVO2> dstTrees = this.tree2Root(AuthUtil.getTenantId(),null,null,dstNode.getProjectId(),null);
 		List<ArchiveTreeContract> saveList = new ArrayList<>();
 		List<ArchiveTreeContract> saveList = new ArrayList<>();
 		ArchiveTreeContractVO2 dstTree = dstTrees.get(0);
 		ArchiveTreeContractVO2 dstTree = dstTrees.get(0);
-		if (dstTree == null ) {
+		ArchiveTreeVO2 srcTree = srcTrees.get(0);
+		if (dstTree == null || srcTree == null) {
 			return false;
 			return false;
 		}
 		}
 
 
@@ -382,7 +385,6 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 
 
 			for (ArchiveTreeContractVO2 ar: dstTree.getChildren()) {
 			for (ArchiveTreeContractVO2 ar: dstTree.getChildren()) {
 				//施工和监理
 				//施工和监理
-
 				ar.setValue(1L);
 				ar.setValue(1L);
 				if (ar.getTreeCode()!= null && (
 				if (ar.getTreeCode()!= null && (
 						ar.getTreeCode().equals("C") || ar.getTreeCode().equals("S"))) {
 						ar.getTreeCode().equals("C") || ar.getTreeCode().equals("S"))) {
@@ -413,16 +415,21 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 						deleteTreeChildren(ar);
 						deleteTreeChildren(ar);
 					}
 					}
 
 
-
 					for(Map.Entry<Long,ContractInfo> entry : contractMap.entrySet()){
 					for(Map.Entry<Long,ContractInfo> entry : contractMap.entrySet()){
 						ContractInfo contractInfo = entry.getValue();
 						ContractInfo contractInfo = entry.getValue();
 
 
 						if (contractInfo.getStatus() == 0) {
 						if (contractInfo.getStatus() == 0) {
 							if (ar.getTreeCode().equals("C") && contractInfo.getContractType() == 1) {
 							if (ar.getTreeCode().equals("C") && contractInfo.getContractType() == 1) {
 								//复制施工
 								//复制施工
+								List<ArchiveTreeContract> tmpSaveList =
+										archiveTreeContractSync.getContractSaveList(srcTree,ar,contractInfo,dstNode);
+								saveList.addAll(tmpSaveList);
 							}
 							}
 							if (ar.getTreeCode().equals("S") && contractInfo.getContractType() == 2) {
 							if (ar.getTreeCode().equals("S") && contractInfo.getContractType() == 2) {
 								//复制监理
 								//复制监理
+								List<ArchiveTreeContract> tmpSaveList =
+										archiveTreeContractSync.getContractSaveList(srcTree,ar,contractInfo,dstNode);
+								saveList.addAll(tmpSaveList);
 							}
 							}
 						}
 						}
 					}
 					}
@@ -447,10 +454,7 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 								srcTrees.get(0),dstNode.getId(),ar);
 								srcTrees.get(0),dstNode.getId(),ar);
 						saveList.addAll(tmpSaveList);
 						saveList.addAll(tmpSaveList);
 					}
 					}
-
-
 				}else {
 				}else {
-
 					for (ArchiveTreeContractVO2 contractNode : ar.getChildren()){
 					for (ArchiveTreeContractVO2 contractNode : ar.getChildren()){
 						if (dstNode.getParentId() == 0 || dstScopeTree.getId() == contractNode.getId()) {
 						if (dstNode.getParentId() == 0 || dstScopeTree.getId() == contractNode.getId()) {
 
 
@@ -459,11 +463,15 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 							saveList.addAll(tmpSaveList);
 							saveList.addAll(tmpSaveList);
 						}
 						}
 					}
 					}
-
 				}
 				}
 			}
 			}
 		}
 		}
 
 
+		//更新排序
+		archiveTreeContractSync.InitTreeSort(dstTree,saveList);
+
+		//todo 同步wbs等扩展节点
+
 		this.saveBatch(saveList);
 		this.saveBatch(saveList);
 		return true;
 		return true;
 	}
 	}
@@ -481,6 +489,27 @@ public class ArchiveTreeContractServiceImpl extends BaseServiceImpl<ArchiveTreeC
 		return this.deleteLogic(ids);
 		return this.deleteLogic(ids);
 	}
 	}
 
 
+	/**
+	 * 同步修改
+	 * @param archiveTree
+	 * @return
+	 */
+	public boolean UpdateByArchiveTree(ArchiveTree archiveTree){
+
+		List<ArchiveTreeContract> archiveTreeContracts =  baseMapper.selectList(Wrappers.<ArchiveTreeContract>query().lambda()
+				.eq(ArchiveTreeContract::getFromId, archiveTree.getId())
+				.eq(ArchiveTreeContract::getProjectId, archiveTree.getProjectId())
+				.eq(ArchiveTreeContract::getIsDeleted, 0)
+		);
+
+		for (ArchiveTreeContract archiveTreeContract : archiveTreeContracts) {
+			archiveTreeContract.sync(archiveTree);
+		}
+
+		this.saveOrUpdateBatch(archiveTreeContracts);
+		return true;
+	}
+
 
 
 
 
 
 

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

@@ -4,18 +4,31 @@ import lombok.AllArgsConstructor;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.manager.entity.ArchiveTree;
 import org.springblade.manager.entity.ArchiveTree;
 import org.springblade.manager.entity.ArchiveTreeContract;
 import org.springblade.manager.entity.ArchiveTreeContract;
+import org.springblade.manager.entity.ContractInfo;
 import org.springblade.manager.utils.ForestNodeMergerEx;
 import org.springblade.manager.utils.ForestNodeMergerEx;
 import org.springblade.manager.vo.ArchiveTreeContractVO2;
 import org.springblade.manager.vo.ArchiveTreeContractVO2;
 import org.springblade.manager.vo.ArchiveTreeVO2;
 import org.springblade.manager.vo.ArchiveTreeVO2;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 
 
 import java.util.ArrayList;
 import java.util.ArrayList;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.List;
+import java.util.Map;
 
 
 @Service
 @Service
 @AllArgsConstructor
 @AllArgsConstructor
 public class ArchiveTreeContractSyncImpl {
 public class ArchiveTreeContractSyncImpl {
 
 
+    private final ArTreeContractInitServiceImpl arTreeContractInitService;
+
+    /**
+     * 普通同步
+     * @param srcNodeId
+     * @param srcTrees
+     * @param dstNodeId
+     * @param dstTrees
+     * @return
+     */
     public List<ArchiveTreeContract> getNormalSaveList(Long srcNodeId,ArchiveTreeVO2 srcTrees,Long dstNodeId,ArchiveTreeContractVO2 dstTrees){
     public List<ArchiveTreeContract> getNormalSaveList(Long srcNodeId,ArchiveTreeVO2 srcTrees,Long dstNodeId,ArchiveTreeContractVO2 dstTrees){
         List<ArchiveTreeContract> saveList = new ArrayList<>();
         List<ArchiveTreeContract> saveList = new ArrayList<>();
         ArchiveTreeVO2 srcTree = ForestNodeMergerEx.getSubTree(srcTrees,srcNodeId);
         ArchiveTreeVO2 srcTree = ForestNodeMergerEx.getSubTree(srcTrees,srcNodeId);
@@ -33,4 +46,63 @@ public class ArchiveTreeContractSyncImpl {
 
 
         return saveList;
         return saveList;
     }
     }
+
+    /**
+     * 复制合同段
+     * @param srcTree
+     * @param dstTree
+     * @param contractInfo
+     * @param dstNode
+     * @return
+     */
+    public List<ArchiveTreeContract> getContractSaveList(ArchiveTreeVO2 srcTree,
+                                                         ArchiveTreeContractVO2 dstTree, ContractInfo contractInfo,ArchiveTreeContract dstNode){
+        List<ArchiveTreeContract> saveList = new ArrayList<>();
+        Long srcNodeId = dstTree.getFromId();
+        Long newNodeId = dstTree.getId();
+        ArchiveTreeVO2 subTree = ForestNodeMergerEx.getSubTree(srcTree,srcNodeId);
+
+
+        arTreeContractInitService.copyContractTree(dstNode.getTenantId(),dstNode.getProjectId()
+        ,contractInfo,newNodeId,subTree.getChildren(),saveList,null);
+
+        return saveList;
+    }
+
+    /**
+     * 刷新祖先节点和排序
+     * @param dstTree
+     * @param addList
+     */
+    public void InitTreeSort(ArchiveTreeContractVO2  dstTree,List<ArchiveTreeContract> addList)
+    {
+        List<ArchiveTreeContractVO2> contractVO2List = new ArrayList<>();
+        ForestNodeMergerEx.getTreeList(dstTree,contractVO2List);
+
+        Map<Long,ArchiveTreeContractVO2> vo2Map = new LinkedHashMap<>();
+        for (ArchiveTreeContract archiveTreeContract:addList) {
+            ArchiveTreeContractVO2 treeContractVO2 = new ArchiveTreeContractVO2();
+            treeContractVO2.setId(archiveTreeContract.getId());
+            treeContractVO2.setParentId(archiveTreeContract.getParentId());
+            treeContractVO2.setTitle(archiveTreeContract.getNodeName());
+            treeContractVO2.setSort(archiveTreeContract.getSort());
+            contractVO2List.add(treeContractVO2);
+            vo2Map.put(treeContractVO2.getId(),treeContractVO2);
+        }
+
+        List<ArchiveTreeContractVO2> trees = ForestNodeMergerEx.merge(contractVO2List);
+
+        ForestNodeMergerEx.InitAncestors(trees.get(0),"0");
+
+        ForestNodeMergerEx.InitTreeSort(trees.get(0), "");
+
+        for (ArchiveTreeContract archiveTreeContract:addList) {
+            ArchiveTreeContractVO2 tmp = vo2Map.get(archiveTreeContract.getId());
+            if (tmp != null ) {
+                archiveTreeContract.setAncestors(tmp.getAncestors());
+                archiveTreeContract.setTreeSort(tmp.getTreeSort());
+
+            }
+        }
+    }
 }
 }

+ 230 - 20
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeServiceImpl.java

@@ -380,6 +380,7 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
             archiveTree.setTitle(wbsTreeVO2.getTitle());
             archiveTree.setTitle(wbsTreeVO2.getTitle());
 
 
             archiveTree.setIswbsNode(true);
             archiveTree.setIswbsNode(true);
+            archiveTree.setWbsNode2ArchiveTreeNodeId(parentId);
             archiveTree.setId(wbsTreeVO2.getId());
             archiveTree.setId(wbsTreeVO2.getId());
             archiveTree.setParentId(wbsTreeVO2.getParentId());
             archiveTree.setParentId(wbsTreeVO2.getParentId());
             archiveTree.setExtId(wbsTreeVO2.getId());
             archiveTree.setExtId(wbsTreeVO2.getId());
@@ -414,9 +415,9 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
      * @return
      * @return
      */
      */
     @Override
     @Override
-    public boolean saveArchiveAutoRule(Integer archiveAutoType, String nodeIds,boolean iswbsNode) {
+    public boolean saveArchiveAutoRule(Integer archiveAutoType, String nodeIds,boolean iswbsNode,Long projectId) {
         if(iswbsNode){
         if(iswbsNode){
-            return saveArchiveAutoRule_WbsTreeNode(archiveAutoType, nodeIds);
+            return saveArchiveAutoRule_WbsTreeNode(archiveAutoType, nodeIds,projectId);
         }else{
         }else{
             return saveArchiveAutoRule_ArchiveTreeNode(archiveAutoType, nodeIds);
             return saveArchiveAutoRule_ArchiveTreeNode(archiveAutoType, nodeIds);
         }
         }
@@ -477,7 +478,7 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
      * @param nodeIds
      * @param nodeIds
      * @return
      * @return
      */
      */
-    private Boolean saveArchiveAutoRule_WbsTreeNode(Integer archiveAutoType, String nodeIds){
+    private Boolean saveArchiveAutoRule_WbsTreeNode(Integer archiveAutoType, String nodeIds,Long projectId){
         try{
         try{
             String[] ids = nodeIds.split(",");
             String[] ids = nodeIds.split(",");
             Long archiveAutoGroupId=null;
             Long archiveAutoGroupId=null;
@@ -492,14 +493,14 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
                 //步骤1:保存选择节点的立卷规则。
                 //步骤1:保存选择节点的立卷规则。
                 long nodeIdLong = Long.parseLong(nodeId);
                 long nodeIdLong = Long.parseLong(nodeId);
                 //1.1最高规则和单独规则 将选择的wbs节点ID(wbsId),规则类型(archive_auto_type), 保存表m_archive_auto_rule_wbs
                 //1.1最高规则和单独规则 将选择的wbs节点ID(wbsId),规则类型(archive_auto_type), 保存表m_archive_auto_rule_wbs
-                WbsTree wbsTree = wbsTreeService.getById(nodeIdLong);
+                //WbsTree wbsTree = wbsTreeService.getById(nodeIdLong);
                 ArchiveAutoRuleWbs autoRuleWbs = new ArchiveAutoRuleWbs();
                 ArchiveAutoRuleWbs autoRuleWbs = new ArchiveAutoRuleWbs();
                 autoRuleWbs.setWbsId(nodeIdLong);
                 autoRuleWbs.setWbsId(nodeIdLong);
                 autoRuleWbs.setArchiveAutoType(archiveAutoType);
                 autoRuleWbs.setArchiveAutoType(archiveAutoType);
                 if(archiveAutoType==2){
                 if(archiveAutoType==2){
                     autoRuleWbs.setArchiveAutoGroupId(archiveAutoGroupId);
                     autoRuleWbs.setArchiveAutoGroupId(archiveAutoGroupId);
                 }
                 }
-                autoRuleWbs.setProjectId(0L);//TODO
+                autoRuleWbs.setProjectId(projectId);//项目ID  系统级为0
                 autoRuleWbs.setWbsRootId(null);//TODO
                 autoRuleWbs.setWbsRootId(null);//TODO
                 archiveAutoRuleWbsMapper.insert(autoRuleWbs);
                 archiveAutoRuleWbsMapper.insert(autoRuleWbs);
             }
             }
@@ -577,7 +578,7 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
                     String selectNodeIds = dto.getSelectNodeIds();
                     String selectNodeIds = dto.getSelectNodeIds();
                     List<String> selectNodeIdlist = Arrays.asList(selectNodeIds);
                     List<String> selectNodeIdlist = Arrays.asList(selectNodeIds);
                     //先将同一分组的节点删除配置,。
                     //先将同一分组的节点删除配置,。
-                    archiveAutoRuleWbsMapper.removeNodeForArchiveAutoRule_Group(groupId,0L);
+                    archiveAutoRuleWbsMapper.removeNodeForArchiveAutoRule_Group(groupId,dto.getProjectId());
                     //然后再按照选择节点保存新的设置
                     //然后再按照选择节点保存新的设置
                     for(String nodeId:selectNodeIdlist){
                     for(String nodeId:selectNodeIdlist){
                         long nodeIdLong = Long.parseLong(nodeId);
                         long nodeIdLong = Long.parseLong(nodeId);
@@ -587,8 +588,8 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
                         if(archiveAutoType==2){
                         if(archiveAutoType==2){
                             autoRuleWbs.setArchiveAutoGroupId(groupId);
                             autoRuleWbs.setArchiveAutoGroupId(groupId);
                         }
                         }
-                        autoRuleWbs.setProjectId(0L);//TODO
-                        autoRuleWbs.setWbsRootId(null);//TODO
+                        autoRuleWbs.setProjectId(dto.getProjectId()==null?0L:dto.getProjectId());
+                        autoRuleWbs.setWbsRootId(null);//TODO 不懂有没有这个东西
                         archiveAutoRuleWbsMapper.insert(autoRuleWbs);
                         archiveAutoRuleWbsMapper.insert(autoRuleWbs);
                     }
                     }
                 }
                 }
@@ -604,22 +605,24 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
      * 移除节点规则
      * 移除节点规则
      * @param nodeId
      * @param nodeId
      */
      */
-    public Map<String,String> removeArchiveAutoRule(Long nodeId,boolean iswbsNode){
+    public Map<String,String> removeArchiveAutoRule(Long nodeId,boolean iswbsNode,Long projectId){
         Map<String,String> returnMap= new HashMap<>();
         Map<String,String> returnMap= new HashMap<>();
         returnMap.put("code","1");
         returnMap.put("code","1");
         try{
         try{
             if(iswbsNode){
             if(iswbsNode){
-                ArchiveAutoRuleWbs archiveAutoRuleWbs = archiveAutoRuleWbsMapper.selectById(nodeId);
-                archiveAutoRuleWbs.setDelete(1);
-                archiveAutoRuleWbs.setUpdateTime(new Date());
-                archiveAutoRuleWbsMapper.updateById(archiveAutoRuleWbs);
+                ArchiveAutoRuleWbs autoRuleWbs = archiveAutoRuleWbsMapper.selectOne(Wrappers.<ArchiveAutoRuleWbs>lambdaQuery()
+                        .eq(ArchiveAutoRuleWbs::getWbsId, nodeId)
+                        .eq(ArchiveAutoRuleWbs::getIsDeleted, 0)
+                        .eq(ArchiveAutoRuleWbs::getProjectId, projectId));
+                archiveAutoRuleWbsMapper.removeArchiveAutoRule(autoRuleWbs.getId(),new Date());
             }else{
             }else{
                 ArchiveTree node = baseMapper.selectById(nodeId);
                 ArchiveTree node = baseMapper.selectById(nodeId);
                 Integer archiveAutoType = node.getArchiveAutoType();
                 Integer archiveAutoType = node.getArchiveAutoType();
                 if(archiveAutoType!=null){
                 if(archiveAutoType!=null){
                     //删除默认规则
                     //删除默认规则
                     if(archiveAutoType==1){
                     if(archiveAutoType==1){
-                        baseMapper.removeAllSonNodeIdsForArchiveAutoRule_1(node.getArchiveAutoType(),node.getAncestors());
+                        String ancestors = node.getAncestors()+","+nodeId;
+                        baseMapper.removeAllSonNodeIdsForArchiveAutoRule_1(node.getArchiveAutoType(),ancestors,nodeId);
                     }
                     }
                     //删除节点及所有子节点 分类并卷规则
                     //删除节点及所有子节点 分类并卷规则
                     if(archiveAutoType==2){
                     if(archiveAutoType==2){
@@ -627,7 +630,8 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
                             //删除规则  只能修改archive_auto_group_select=1的节点,
                             //删除规则  只能修改archive_auto_group_select=1的节点,
                             // 因为分类并卷规则影响范围包括下面所有子节点,如果给archive_auto_group_select=0的节点也就是范围内的子节点单独取消规则,会造成案卷归属节点错乱。
                             // 因为分类并卷规则影响范围包括下面所有子节点,如果给archive_auto_group_select=0的节点也就是范围内的子节点单独取消规则,会造成案卷归属节点错乱。
                             // (不理那么多,就这样限制先 。如业务非要发神经就要 TODO 验证节点的父节点是否为分类并卷规则,如是则取消。若无其他兄弟节点,继续往上验证。)
                             // (不理那么多,就这样限制先 。如业务非要发神经就要 TODO 验证节点的父节点是否为分类并卷规则,如是则取消。若无其他兄弟节点,继续往上验证。)
-                            baseMapper.removeAllSonNodeIdsForArchiveAutoRule_2(node.getArchiveAutoType(),node.getAncestors());
+                            String ancestors = node.getAncestors()+","+nodeId;
+                            baseMapper.removeAllSonNodeIdsForArchiveAutoRule_2(node.getArchiveAutoType(),ancestors,nodeId);
                         }else{
                         }else{
                             returnMap.put("code","0");
                             returnMap.put("code","0");
                             returnMap.put("msg","只能取消设置的节点,不能取消设置节点范围下节点");
                             returnMap.put("msg","只能取消设置的节点,不能取消设置节点范围下节点");
@@ -635,7 +639,8 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
                     }
                     }
                     //删除节点及所有子节点 单独并卷规则
                     //删除节点及所有子节点 单独并卷规则
                     if(archiveAutoType==3){
                     if(archiveAutoType==3){
-                        baseMapper.removeAllSonNodeIdsForArchiveAutoRule_3(node.getArchiveAutoType(),node.getAncestors());
+                        String ancestors = node.getAncestors()+","+nodeId;
+                        baseMapper.removeAllSonNodeIdsForArchiveAutoRule_3(node.getArchiveAutoType(),ancestors,nodeId);
                     }
                     }
                 }
                 }
             }
             }
@@ -653,10 +658,10 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
      * @return
      * @return
      */
      */
     @Override
     @Override
-    public Map<String,Object> getArchiveAutoRule(Long id,boolean iswbsNode) {
+    public Map<String,Object> getArchiveAutoRule(Long id,boolean iswbsNode,Long projectId,Long wbsNode2ArchiveTreeNodeId,String wbsId) {
 
 
         if(iswbsNode){
         if(iswbsNode){
-            return getArchiveAutoRule_WbsTreeNode(id);
+            return getArchiveAutoRule_WbsTreeNode(id,projectId,wbsNode2ArchiveTreeNodeId,wbsId);
         }else{
         }else{
             return getArchiveAutoRule_ArchiveTreeNode(id);
             return getArchiveAutoRule_ArchiveTreeNode(id);
         }
         }
@@ -757,10 +762,137 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
      * @param id
      * @param id
      * @return
      * @return
      */
      */
-    private Map<String,Object> getArchiveAutoRule_WbsTreeNode(Long id) {
+    private Map<String,Object> getArchiveAutoRule_WbsTreeNode(Long id,Long projectId,Long wbsNode2ArchiveTreeNodeId,String wbsId) {
         Map<String,Object> map= new HashMap<>();
         Map<String,Object> map= new HashMap<>();
         try{
         try{
-            //TODO 需要了解关联的wbs节点
+            ArchiveTree archiveTree = baseMapper.selectById(wbsNode2ArchiveTreeNodeId);
+
+            //步骤1:找出wbs的规则设置
+                ArchiveAutoRuleWbs autoRuleWbs = archiveAutoRuleWbsMapper.selectOne(Wrappers.<ArchiveAutoRuleWbs>lambdaQuery()
+                        .eq(ArchiveAutoRuleWbs::getWbsId, id)
+                        .eq(ArchiveAutoRuleWbs::getIsDeleted, 0)
+                        .eq(ArchiveAutoRuleWbs::getProjectId, projectId));
+
+                if(autoRuleWbs!=null){
+                    Integer archiveAutoType = autoRuleWbs.getArchiveAutoType();
+
+
+                    if(archiveAutoType!=null){
+
+                        //获取wbs关联树
+                        ArchiveTreeVO2 archiveTreeVO2 = getWbsArchiveTree(AuthUtil.getTenantId(),projectId,wbsNode2ArchiveTreeNodeId,wbsId,"1",Long.parseLong(archiveTree.getDisplayHierarchy()));
+                        List<ArchiveTreeVO2> archiveTreeVO2List = new ArrayList<>();
+                        ForestNodeMerger.getTreeListEx(archiveTreeVO2,archiveTreeVO2List);
+                        Map<Long,ArchiveTreeVO2> ArchiveTreeVO2Map = new HashMap<>();
+                        for(ArchiveTreeVO2 vo2:archiveTreeVO2List){
+                            ArchiveTreeVO2Map.put(vo2.getId(),vo2);
+                        }
+
+                        if(archiveAutoType==1){
+                            //最高并卷层级 默认规则的节点 显示最高并卷层级节点
+                            StringBuffer allName= new StringBuffer();
+                            ArchiveTreeVO2 nameVo2 = ArchiveTreeVO2Map.get(id);
+                            while (nameVo2.getParentId()!=0L){
+                                allName.insert(0,nameVo2.getTitle());
+                                allName.insert(0,"/");
+                                Long parentId = nameVo2.getParentId();
+                                nameVo2 = ArchiveTreeVO2Map.get(parentId);
+                            }
+                            //nameVo2.getParentId()==0L时加上名字
+                            allName.insert(0,nameVo2.getTitle());
+
+                            ArchiveTreeAutoRuleVO vo= new ArchiveTreeAutoRuleVO();
+                            vo.setAllName(allName.toString());
+                            vo.setNodeId(id);
+                            vo.setArchiveAutoType(archiveAutoType);
+                            map.put("type",archiveAutoType);
+                            map.put("data",vo);
+                            return map;
+                        }
+                        if(archiveAutoType==2){
+                            Long archiveAutoGroupId = autoRuleWbs.getArchiveAutoGroupId();
+                            //用于分类并卷编辑树
+                            List<ArchiveTreeAutoRuleVO> nodetree = new ArrayList<>();
+
+                            //遍历wbs关联树 生成分类并将编辑树
+                            for(ArchiveTreeVO2 vo2:archiveTreeVO2List){
+                                //查询wbs节点是否有规则设置
+                                ArchiveAutoRuleWbs autoRuleWbs2 = archiveAutoRuleWbsMapper.selectOne(Wrappers.<ArchiveAutoRuleWbs>lambdaQuery()
+                                        .eq(ArchiveAutoRuleWbs::getWbsId, vo2.getId())
+                                        .eq(ArchiveAutoRuleWbs::getIsDeleted, 0)
+                                        .eq(ArchiveAutoRuleWbs::getProjectId, projectId));
+                                if(autoRuleWbs2!=null){
+                                    //如有规则,需过滤单独规则节点,和不同组的分类规则节点
+                                    if(autoRuleWbs2.getArchiveAutoType()!=3){
+
+                                        if(autoRuleWbs2.getArchiveAutoType()==1){
+                                            ArchiveTreeAutoRuleVO vo=new ArchiveTreeAutoRuleVO();
+                                            vo.setNodeId(vo2.getId());
+                                            vo.setParentId(vo2.getParentId());
+                                            vo.setNodeName(vo2.getTitle());
+                                            nodetree.add(vo);
+                                        }
+                                        //如有规则,需过滤不同组的分类规则节点
+                                        if(autoRuleWbs2.getArchiveAutoType()==2 && autoRuleWbs2.getArchiveAutoGroupId().equals(archiveAutoGroupId)){
+                                            ArchiveTreeAutoRuleVO vo=new ArchiveTreeAutoRuleVO();
+                                            vo.setNodeId(vo2.getId());
+                                            vo.setParentId(vo2.getParentId());
+                                            vo.setNodeName(vo2.getTitle());
+                                            nodetree.add(vo);
+                                        }
+                                    }
+                                }else{
+                                    //没有规则的直接加上
+                                    ArchiveTreeAutoRuleVO vo=new ArchiveTreeAutoRuleVO();
+                                    vo.setNodeId(vo2.getId());
+                                    vo.setParentId(vo2.getParentId());
+                                    vo.setNodeName(vo2.getTitle());
+                                    nodetree.add(vo);
+                                }
+                            }
+
+                            List<ArchiveTreeAutoRuleVO> merge = ForestNodeMerger.merge(nodetree);
+                            //获取与当前节点设置同一分类分组的节点
+                            List<ArchiveAutoRuleWbs> archiveAutoRuleWbs = archiveAutoRuleWbsMapper.selectList(Wrappers.<ArchiveAutoRuleWbs>lambdaQuery()
+                                    .eq(ArchiveAutoRuleWbs::getArchiveAutoGroupId,archiveAutoGroupId)
+                                    .eq(ArchiveAutoRuleWbs::getIsDeleted, 0)
+                                    .eq(ArchiveAutoRuleWbs::getProjectId, projectId));
+                            StringBuffer nodeSelect = new StringBuffer();
+
+                            for(ArchiveAutoRuleWbs node:archiveAutoRuleWbs){
+                                nodeSelect.append(node.getWbsId()+",");
+                            }
+
+                            map.put("archiveAutoType",archiveAutoType);
+                            map.put("archiveAutoGroupId",archiveAutoGroupId);
+                            map.put("tree",merge);
+                            map.put("selectNodeIds",nodeSelect.toString());
+                            return map;
+                        }
+                        if(archiveAutoType==3){
+                            StringBuffer allName= new StringBuffer();
+                            ArchiveTreeVO2 nameVo2 = ArchiveTreeVO2Map.get(id);
+                            while (nameVo2.getParentId()!=0L){
+                                allName.insert(0,nameVo2.getTitle());
+                                allName.insert(0,"/");
+                                Long parentId = nameVo2.getParentId();
+                                nameVo2 = ArchiveTreeVO2Map.get(parentId);
+                            }
+                            //nameVo2.getParentId()==0L时加上名字
+                            allName.insert(0,nameVo2.getTitle());
+
+                            ArchiveTreeAutoRuleVO vo= new ArchiveTreeAutoRuleVO();
+                            vo.setAllName(allName.toString());
+                            vo.setNodeId(id);
+                            vo.setArchiveAutoType(archiveAutoType);
+                            map.put("type",archiveAutoType);
+                            map.put("data",vo);
+                            return map;
+                        }
+                    }
+                }
+
+
         }catch (Exception e){
         }catch (Exception e){
             e.printStackTrace();
             e.printStackTrace();
             return map;
             return map;
@@ -798,11 +930,89 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
         }
         }
 
 
         //刷新treeCode
         //刷新treeCode
+        InitAncestors(dstTree,saveList);
 
 
         //相同的属性刷新?
         //相同的属性刷新?
+        updateDstArchiveTrees(srcTree,dstTree);
 
 
         this.saveBatch(saveList);
         this.saveBatch(saveList);
 
 
         return true;
         return true;
     }
     }
+
+
+    public void InitAncestors(ArchiveTreeVO2  dstTree,List<ArchiveTree> addList)
+    {
+        List<ArchiveTreeVO2> archiveTreeVO2s = new ArrayList<>();
+        ForestNodeMergerEx.getTreeList(dstTree,archiveTreeVO2s);
+
+        Map<Long,ArchiveTreeVO2> vo2Map = new LinkedHashMap<>();
+        for (ArchiveTree archiveTree:addList) {
+            ArchiveTreeVO2 archiveTreeVO2 = new ArchiveTreeVO2();
+            archiveTreeVO2.setId(archiveTree.getId());
+            archiveTreeVO2.setParentId(archiveTree.getParentId());
+            archiveTreeVO2.setTitle(archiveTree.getNodeName());
+            archiveTreeVO2.setSort(archiveTree.getSort());
+            archiveTreeVO2s.add(archiveTreeVO2);
+            vo2Map.put(archiveTreeVO2.getId(),archiveTreeVO2);
+        }
+
+
+        List<ArchiveTreeVO2> trees = ForestNodeMergerEx.merge(archiveTreeVO2s);
+
+        ForestNodeMergerEx.InitAncestors(trees.get(0),"0");
+
+        for (ArchiveTree archiveTree:addList) {
+            ArchiveTreeVO2 tmp = vo2Map.get(archiveTree.getId());
+            if (tmp != null ) {
+                archiveTree.setAncestors(tmp.getAncestors());
+            }
+        }
+    }
+
+    public void updateDstArchiveTrees(ArchiveTreeVO2 srcTree,ArchiveTreeVO2  dstTree){
+
+        List<ArchiveTreeVO2> srcList = new ArrayList<>();
+
+        List<ArchiveTreeVO2> dstList = new ArrayList<>();
+        Map<Long,ArchiveTreeVO2> srcDstMap = new LinkedHashMap<>();
+        Map<Long,ArchiveTreeVO2> srcMap = new LinkedHashMap<>();
+        List<Long> matchIds = new ArrayList<>();
+
+
+        ForestNodeMergerEx.getTreeList(srcTree,srcList);
+        ForestNodeMergerEx.getTreeList(dstTree,dstList);
+
+
+        //from  - dst 映射
+        for (ArchiveTreeVO2 dst :dstList) {
+            if (dst.getFromId() != null ) {
+                srcDstMap.put(dst.getFromId(),dst);
+            }
+        }
+
+        for (ArchiveTreeVO2 src :srcList) {
+            //匹配的节点
+
+            ArchiveTreeVO2 dst = srcDstMap.get(src.getId());
+            if (dst != null) {
+                matchIds.add(dst.getId());
+                srcMap.put(src.getId(),src);
+            }
+        }
+
+
+        List<ArchiveTree> archiveTreeList = archiveTreeMapper.selectBatchIds(matchIds);
+        if (archiveTreeList == null ) {
+            return;
+        }
+        for (ArchiveTree oldAr: archiveTreeList) {
+            ArchiveTreeVO2 src = srcMap.get(oldAr.getFromId());
+            if (src != null ) {
+                oldAr.sync(src);
+            }
+        }
+
+        this.saveOrUpdateBatch(archiveTreeList);
+    }
 }
 }

+ 7 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java

@@ -18,6 +18,7 @@ package org.springblade.manager.service.impl;
 
 
 import cn.hutool.core.date.StopWatch;
 import cn.hutool.core.date.StopWatch;
 import cn.hutool.log.StaticLog;
 import cn.hutool.log.StaticLog;
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -71,6 +72,7 @@ import org.springblade.manager.vo.*;
 import org.springblade.resource.feign.NewIOSSClient;
 import org.springblade.resource.feign.NewIOSSClient;
 import org.springblade.system.cache.ParamCache;
 import org.springblade.system.cache.ParamCache;
 import org.springframework.beans.factory.annotation.Autowired;
 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.BeanPropertyRowMapper;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.datasource.DataSourceTransactionManager;
 import org.springframework.jdbc.datasource.DataSourceTransactionManager;
@@ -122,6 +124,9 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
     private final TrialSelfInspectionRecordClient inspectionRecordClient;
     private final TrialSelfInspectionRecordClient inspectionRecordClient;
     private final TableInfoServiceImpl tableInfoService;
     private final TableInfoServiceImpl tableInfoService;
 
 
+    @Autowired
+    StringRedisTemplate RedisTemplate;
+
     @Override
     @Override
     public IPage<ExcelTabVO> selectExcelTabPage(IPage<ExcelTabVO> page, ExcelTabVO excelTab) {
     public IPage<ExcelTabVO> selectExcelTabPage(IPage<ExcelTabVO> page, ExcelTabVO excelTab) {
         return page.setRecords(baseMapper.selectExcelTabPage(page, excelTab));
         return page.setRecords(baseMapper.selectExcelTabPage(page, excelTab));
@@ -789,6 +794,8 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
 
 
                 //保存操作记录
                 //保存操作记录
                 this.operationLogClient.saveUserOperationLog(1, "资料填报", "工序填报页面", json);
                 this.operationLogClient.saveUserOperationLog(1, "资料填报", "工序填报页面", json);
+                // 更新redis
+                informationQueryClient.AsyncWbsTree(wbsTreeContract.getParentId()+"",wbsTreeContract.getParentId()+"",wbsTreeContract.getContractId(),"","1");
             } catch (Exception e) {
             } catch (Exception e) {
                 e.printStackTrace();
                 e.printStackTrace();
                 return R.fail("操作失败");
                 return R.fail("操作失败");

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

@@ -201,16 +201,15 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
         }
         }
         if(Func.isNotEmpty(cki)){
         if(Func.isNotEmpty(cki)){
            /*检验内容*/
            /*检验内容*/
-            StringBuilder sb = new StringBuilder();
+            List<String> sb = new ArrayList<>();
             for(String s:cki){
             for(String s:cki){
                 FormData fdTmp=this.formDataMap.get(s);
                 FormData fdTmp=this.formDataMap.get(s);
                 if(fdTmp!=null&&fdTmp.getValues().stream().map(ElementData::getValue).anyMatch(e->StringUtils.isNotEmpty(e)&&StringUtils.isNotEquals("/",e))){
                 if(fdTmp!=null&&fdTmp.getValues().stream().map(ElementData::getValue).anyMatch(e->StringUtils.isNotEmpty(e)&&StringUtils.isNotEquals("/",e))){
-                    sb.append(FormulaUtils.parseItemName(fdTmp.getEName())).append(",");
+                   sb.add(FormulaUtils.parseItemName(fdTmp.getEName()));
                 }
                 }
             }
             }
-            if(sb.length()>1){
-                sb.deleteCharAt(sb.length()-1);
-                this.constantMap.put(CHECK_ITEMS,sb.toString());
+            if(sb.size()>0){
+                this.constantMap.put(CHECK_ITEMS,sb.stream().distinct().filter(StringUtils::isNotEmpty).collect(Collectors.joining(",")));
             }
             }
         }
         }
         if(Func.isNotBlank(ckd.get())){
         if(Func.isNotBlank(ckd.get())){
@@ -571,7 +570,7 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
         }
         }
 
 
 /*###############################附表的处理##################################*/
 /*###############################附表的处理##################################*/
-        if(true) {
+        if(true) {//临时开关,稳定后移除
             try {
             try {
                 /*检验单附表处理*/
                 /*检验单附表处理*/
                 List<FormData> inspectionList = new ArrayList<>();
                 List<FormData> inspectionList = new ArrayList<>();
@@ -610,17 +609,21 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                         /*找不到附表表单数据,则从数据库加载*/
                         /*找不到附表表单数据,则从数据库加载*/
                         JSONArray dataArray = new JSONArray();
                         JSONArray dataArray = new JSONArray();
                         for (WbsTreeContract data : subTabList) {
                         for (WbsTreeContract data : subTabList) {
+                            /*自动挂载附表情况下,装配TableInfo数据*/
                             R bussDataInfo = this.getBussDataInfo(data.getPKeyId(), 1);
                             R bussDataInfo = this.getBussDataInfo(data.getPKeyId(), 1);
-                            Object data1 = bussDataInfo.getData();
+                            Map<String, Object>  data1 = (Map<String, Object>) bussDataInfo.getData();
+                            data1.put("pkeyId",data.getPKeyId());
                             dataArray.add(data1);
                             dataArray.add(data1);
                         }
                         }
                         List<TableInfo> subTableInfo = FormulaUtils.getTableInfoList(dataArray);
                         List<TableInfo> subTableInfo = FormulaUtils.getTableInfoList(dataArray);
                         tec.getTableInfoList().addAll(subTableInfo);
                         tec.getTableInfoList().addAll(subTableInfo);
+                        /*获取附表元素定位集*/
                         tec.getCoordinateMap().put(subTabList.get(0).getInitTableName(), CustomFunction.getElementCell(first.getHtmlUrl()));
                         tec.getCoordinateMap().put(subTabList.get(0).getInitTableName(), CustomFunction.getElementCell(first.getHtmlUrl()));
-                        List<Map<String, Object>> elementMaps = this.jdbcTemplate.queryForList("select b.e_name name , CONCAT(a.tab_en_name,':',b.e_key) code , b.e_key ekey ,b.id fieldId,a.tab_en_name tableName from m_table_info a join m_wbs_form_element b on a.id = b.f_id where a.tab_en_name='" + first.getInitTableName() + "' and b.is_deleted=0 ");
+                        /*附表元素关键信息*/
+                        List<Map<String, Object>> elementMaps = this.jdbcTemplate.queryForList("select b.e_name ename , CONCAT(a.tab_en_name,':',b.e_key) code , b.e_key ekey ,b.id fieldId,a.tab_en_name tableName from m_table_info a join m_wbs_form_element b on a.id = b.f_id where a.tab_en_name='" + first.getInitTableName() + "' and b.is_deleted=0 ");
                         if (Func.isNotEmpty(elementMaps)) {
                         if (Func.isNotEmpty(elementMaps)) {
                             elementMaps.forEach(e->{
                             elementMaps.forEach(e->{
-                                /*生成附表元素*/
+                                /*装配元素*/
                                 String values=subTableInfo.stream().map(TableInfo::getDataMap).map(m->m.get(StringUtils.handleNull(e.get("ekey")))).filter(StringUtils::isNotEmpty).collect(Collectors.joining(";;"));
                                 String values=subTableInfo.stream().map(TableInfo::getDataMap).map(m->m.get(StringUtils.handleNull(e.get("ekey")))).filter(StringUtils::isNotEmpty).collect(Collectors.joining(";;"));
                                 FormData tmp=  createFormDataFast(StringUtils.handleNull(e.get("ename")),StringUtils.handleNull(e.get("code")),values);
                                 FormData tmp=  createFormDataFast(StringUtils.handleNull(e.get("ename")),StringUtils.handleNull(e.get("code")),values);
                                 if(tmp!=null){
                                 if(tmp!=null){
@@ -628,7 +631,7 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                                     this.formDataList.add(tmp);
                                     this.formDataList.add(tmp);
                                 }
                                 }
                             });
                             });
-                            /*生成元素数据*/
+                            /*生成元素映射关系*/
                             subTabList.forEach(s->{
                             subTabList.forEach(s->{
                                 elementMaps.forEach(e->{
                                 elementMaps.forEach(e->{
                                     KeyMapper km = new KeyMapper();
                                     KeyMapper km = new KeyMapper();
@@ -642,20 +645,27 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
 
 
                         }
                         }
                     }
                     }
-                    List<FormData> subTableFds=this.formDataList.stream().filter(e->StringUtils.isEquals(first.getInitTableName(),e.getTableName())).collect(Collectors.toList());
+                    /*获取封装好的附表元素*/
+                    List<FormData> subTableFds=this.formDataMap.values().stream().filter(e->StringUtils.isEquals(first.getInitTableName(),e.getTableName())).collect(Collectors.toList());
+                    /*初始化附表对象*/
                     SubTable sta=new SubTable(subTableFds);
                     SubTable sta=new SubTable(subTableFds);
-                    /*检验单或者评定表存在超页数据*/
+
                     inspectionList.forEach(f -> {
                     inspectionList.forEach(f -> {
+                        /*检验单或者评定表存的超页数据汇总到附表对象*/
                            List<ElementData> overList = f.getValues().stream().skip(f.getCoordsList().size()).collect(Collectors.toList());
                            List<ElementData> overList = f.getValues().stream().skip(f.getCoordsList().size()).collect(Collectors.toList());
+                           f.setValues(f.getValues().stream().limit(f.getCoordsList().size()).collect(Collectors.toList()));
+                           f.setAddPages(0);
                            String itemName=FormulaUtils.parseItemName(f.getEName());
                            String itemName=FormulaUtils.parseItemName(f.getEName());
                            String key=itemName.trim();
                            String key=itemName.trim();
-                           Optional<FormData> designFdOp=  this.formDataMap.values().stream().filter(o->o.getTableName().equals(f.getTableName())&&StringUtils.isEquals(itemName,FormulaUtils.parseItemName(o.getEName()))).findAny();
+                           /*同项目*/
+                           Optional<FormData> designFdOp=  this.formDataMap.values().stream().filter(o->o.getTableName().equals(f.getTableName())&&StringUtils.isEquals(itemName,FormulaUtils.parseItemName(o.getEName()))&&o.getEName().contains("设计值")&&!o.getEName().contains("判定")).findAny();
                            if(designFdOp.isPresent()){
                            if(designFdOp.isPresent()){
                                key+="@"+designFdOp.get().getValues().stream().map(ElementData::stringValue).filter(StringUtils::isNotEmpty).findAny().orElse("");
                                key+="@"+designFdOp.get().getValues().stream().map(ElementData::stringValue).filter(StringUtils::isNotEmpty).findAny().orElse("");
                            }
                            }
                            sta.put(key,overList);
                            sta.put(key,overList);
                     });
                     });
                     if(sta.checked()){
                     if(sta.checked()){
+                        /*把附表数据刷入对应的附表元素对象*/
                         sta.flush();
                         sta.flush();
                     }
                     }
                 }
                 }

+ 16 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/utils/ForestNodeMerger.java

@@ -1,5 +1,6 @@
 package org.springblade.manager.utils;
 package org.springblade.manager.utils;
 
 
+import org.springblade.common.utils.INodeEx;
 import org.springblade.core.tool.node.ForestNodeManager;
 import org.springblade.core.tool.node.ForestNodeManager;
 import org.springblade.core.tool.node.INode;
 import org.springblade.core.tool.node.INode;
 
 
@@ -37,5 +38,20 @@ public class ForestNodeMerger {
         }
         }
     }
     }
 
 
+    public static <T extends INodeEx<T>> void getTreeListEx(T tree, List<T> nodes){
+        if (tree == null) {
+            return;
+        }
+
+        nodes.add(tree);
+
+        List<T> childrens = tree.getChildren();
+        if (childrens!= null) {
+            for (T child :childrens) {
+                getTreeListEx(child,nodes);
+            }
+        }
+    }
+
 
 
 }
 }

+ 39 - 5
blade-service/blade-manager/src/main/java/org/springblade/manager/utils/ForestNodeMergerEx.java

@@ -14,6 +14,11 @@ import java.util.stream.Collectors;
 
 
 public class ForestNodeMergerEx {
 public class ForestNodeMergerEx {
     public static <T extends INodeEx<T>> List<T> merge(List<T> items) {
     public static <T extends INodeEx<T>> List<T> merge(List<T> items) {
+
+        for (T item: items) {
+            item.clearChildren();
+        }
+
         ForestNodeManagerEx<T> forestNodeManager = new ForestNodeManagerEx(items);
         ForestNodeManagerEx<T> forestNodeManager = new ForestNodeManagerEx(items);
         items.forEach((forestNode) -> {
         items.forEach((forestNode) -> {
             if (forestNode.getParentId()!= null && forestNode.getParentId() != 0L) {
             if (forestNode.getParentId()!= null && forestNode.getParentId() != 0L) {
@@ -26,9 +31,38 @@ public class ForestNodeMergerEx {
             }
             }
 
 
         });
         });
+
         return forestNodeManager.getRoot();
         return forestNodeManager.getRoot();
     }
     }
 
 
+    public static <T extends INodeEx<T>> List<T> mergeOnlyRoot(List<T> items) {
+
+        for (T item: items) {
+            item.clearChildren();
+        }
+
+        ForestNodeManagerEx<T> forestNodeManager = new ForestNodeManagerEx(items);
+        items.forEach((forestNode) -> {
+            if (forestNode.getParentId()!= null && forestNode.getParentId() != 0L) {
+                INodeEx<T> node = forestNodeManager.getTreeNodeAt(forestNode.getParentId());
+                if (node != null) {
+                    node.getChildren().add(forestNode);
+                } else {
+                    forestNodeManager.addParentId(forestNode.getId());
+                }
+            }
+
+        });
+        List<T> roots = forestNodeManager.getRoot();;
+        List<T> newRoots = new ArrayList();
+        for (T root : roots) {
+            if (root.getParentId() == 0L) {
+                newRoots.add(root);
+            }
+        }
+        return newRoots;
+    }
+
     public static <T extends INodeEx<T>> void getTreeList(T tree, List<T> nodes){
     public static <T extends INodeEx<T>> void getTreeList(T tree, List<T> nodes){
         if (tree == null) {
         if (tree == null) {
             return;
             return;
@@ -94,12 +128,12 @@ public class ForestNodeMergerEx {
 
 
 
 
 
 
-    public static <T extends INodeEx<T>,E extends INodeEx<E>> void syncTreeList(T srcTree, E dstTree, List<E> outList){
+    public static <T extends INodeEx<T>,E extends INodeEx<E>>  void syncTreeList(T srcTree, E dstTree, List<E> outList){
         List<T> srcList = new ArrayList<>();
         List<T> srcList = new ArrayList<>();
         List<T> srcAddList = new ArrayList<>();
         List<T> srcAddList = new ArrayList<>();
         List<E> dstList = new ArrayList<>();
         List<E> dstList = new ArrayList<>();
         Map<Long,Long> srcDstMap = new LinkedHashMap<>();
         Map<Long,Long> srcDstMap = new LinkedHashMap<>();
-        Map<Long,E> srcTMap = new LinkedHashMap<>();
+        //Map<Long,E> srcTMap = new LinkedHashMap<>();
 
 
 
 
         getTreeList(srcTree,srcList);
         getTreeList(srcTree,srcList);
@@ -114,7 +148,7 @@ public class ForestNodeMergerEx {
         for (E dst :dstList) {
         for (E dst :dstList) {
             if (dst.getFromId() != null ) {
             if (dst.getFromId() != null ) {
                 srcDstMap.put(dst.getFromId(),dst.getId());
                 srcDstMap.put(dst.getFromId(),dst.getId());
-                srcTMap.put(dst.getFromId(),dst);
+                //srcTMap.put(dst.getFromId(),dst);
             }
             }
         }
         }
 
 
@@ -164,7 +198,7 @@ public class ForestNodeMergerEx {
         return a;
         return a;
     }
     }
 
 
-    public  <T extends INodeEx<T>> void InitAncestors(T tree, String ancestors) {
+    public  static <T extends INodeEx<T>> void InitAncestors(T tree, String ancestors) {
         String localAncestors = ancestors + "," + tree.getId();
         String localAncestors = ancestors + "," + tree.getId();
         tree.setAncestors(ancestors);
         tree.setAncestors(ancestors);
 
 
@@ -176,7 +210,7 @@ public class ForestNodeMergerEx {
         }
         }
     }
     }
 
 
-    public <T extends INodeEx<T>> void InitTreeSort(T tree, String treeSort) {
+    public static <T extends INodeEx<T>> void InitTreeSort(T tree, String treeSort) {
 
 
         Integer localSort = 100;
         Integer localSort = 100;
         if (tree.getSort() != null ) {
         if (tree.getSort() != null ) {