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

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

huangtf 2 жил өмнө
parent
commit
fcb707cc7b
31 өөрчлөгдсөн 769 нэмэгдсэн , 457 устгасан
  1. 2 0
      blade-service-api/blade-archive-api/src/main/java/org/springblade/archive/entity/ArchivesAuto.java
  2. 3 0
      blade-service-api/blade-business-api/src/main/java/org/springblade/business/feign/ArchiveFileClient.java
  3. 3 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/ArchiveTreeContractClient.java
  4. 4 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/ArchiveTreeAutoRuleVO.java
  5. 6 0
      blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/vo/CurrentNode.java
  6. 6 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.java
  7. 18 0
      blade-service/blade-archive/src/main/java/org/springblade/archive/mapper/ArchivesAutoMapper.xml
  8. 405 1
      blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java
  9. 88 41
      blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java
  10. 2 2
      blade-service/blade-business/src/main/java/org/springblade/business/controller/TrialDetectionController.java
  11. 9 0
      blade-service/blade-business/src/main/java/org/springblade/business/feignClient/ArchiveFileClientImpl.java
  12. 2 0
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/ArchiveFileServiceImpl.java
  13. 19 6
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialDeviceUseServiceImpl.java
  14. 6 27
      blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialSelfInspectionRecordServiceImpl.java
  15. 9 14
      blade-service/blade-manager/src/main/java/com/mixsmart/utils/CustomFunction.java
  16. 5 1
      blade-service/blade-manager/src/main/java/com/mixsmart/utils/FormulaUtils.java
  17. 14 5
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/TrialClassificationConfigurationController.java
  18. 16 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/feign/ArchiveTreeContractImpl.java
  19. 3 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/ITurnPointCalculator.java
  20. 1 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/SubTable.java
  21. 3 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeContractMapper.java
  22. 25 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/ArchiveTreeContractMapper.xml
  23. 0 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreePrivateMapper.java
  24. 0 10
      blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreePrivateMapper.xml
  25. 5 249
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveAutoRuleWbsServiceImpl.java
  26. 9 3
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveTreeServiceImpl.java
  27. 1 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ExcelTabServiceImpl.java
  28. 68 62
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java
  29. 8 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/TrialClassificationConfigurationServiceImpl.java
  30. 28 33
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreePrivateServiceImpl.java
  31. 1 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreeServiceImpl.java

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

@@ -157,4 +157,6 @@ public class ArchivesAuto extends BaseEntity {
 	 * 立卷单位
 	 * **/
 	private String filingUnit;
+
+	private Integer isLock;  //案卷锁定  0未锁  1已锁定    (已锁定的案卷,自动归档执行不再拆卷重新组卷)
 }

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

@@ -61,4 +61,7 @@ public interface ArchiveFileClient {
 
     @PostMapping(API_PREFIX + "/getArchiveFileByArchivesId")
     List<ArchiveFile> getArchiveFileByArchivesId(@RequestParam String archivesIds,@RequestParam String fileIds);
+
+    @PostMapping(API_PREFIX + "/updateArchiveFileForCreateArchive")
+    void updateArchiveFileForCreateArchive(@RequestBody List<ArchiveFile> waitArchiveFiles);
 }

+ 3 - 0
blade-service-api/blade-manager-api/src/main/java/org/springblade/manager/feign/ArchiveTreeContractClient.java

@@ -21,4 +21,7 @@ public interface ArchiveTreeContractClient {
     List<ArchiveTreeContract> queryAllChildByAncestors(@RequestParam String id);
 
 
+    @PostMapping(API_PREFIX + "/getHavedFileNodeByProjectID")
+    List<ArchiveTreeContract> getHavedFileNodeByProjectID(@RequestParam Long projectId);
+
 }

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

@@ -41,4 +41,8 @@ public class ArchiveTreeAutoRuleVO implements INode<ArchiveTreeAutoRuleVO> {
     public List<ArchiveTreeAutoRuleVO> getChildren() {
         return children;
     }
+
+    private boolean iswbsNode;  //是否为关联的wbs节点
+
+    private Long wbsNode2ArchiveTreeNodeId;  //wbs节点关联归档树节点ID
 }

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

@@ -9,9 +9,15 @@ import lombok.Data;
  */
 @Data
 public class CurrentNode {
+    /**流水号*/
     private Long pkId;
+    /**项目集id*/
     private Long privateId;
+    /**wbs_tree的流水号*/
     private Long id;
+    /**父节点的树id,注意非流水号*/
     private Long parentId;
+    /**用来构建树的id*/
     private Long relateId;
+    private Long wbsId;
 }

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

@@ -45,4 +45,10 @@ public interface ArchivesAutoMapper extends BaseMapper<ArchivesAuto> {
 	List<ArchivesAuto> selectArchivesAutoFilePage(@Param("current") Integer current, @Param("size") Integer size, @Param("vo")  ArchivesAutoVO vo);
 
 	Integer updateArchivesAutoFileByNodeId(@Param("ids") List<Long> ids,@Param("nodeId") String nodeId,@Param("nodeSort") String nodeSort);
+
+	/**
+	 * 自动归档前 将未锁定的案卷拆卷
+	 * @param projectId
+	 */
+    Integer splitArchvies(@Param("projectId") Long projectId);
 }

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

@@ -102,4 +102,22 @@
         </foreach>
     </update>
 
+    <update id="splitArchvies" >
+        /**把未锁定案卷的文件关联去掉*/
+        update u_archive_file set archive_id = null where
+            is_deleted=0 and
+            archive_id in(
+                select id u_archives_auto where project_id=#{projectId}
+                  and is_auto_file!=1
+                  and is_deleted=0
+                  and is_lock=0
+            );
+        /**把未锁定案卷去掉*/
+        update u_archives_auto set is_deleted=1 where project_id=#{projectId}
+            and is_auto_file!=1
+            and is_deleted=0
+            and is_lock=0;
+    </update>
+
+
 </mapper>

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

@@ -18,22 +18,28 @@ package org.springblade.archive.service.impl;
 
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.AllArgsConstructor;
 import org.apache.commons.lang.StringUtils;
 import org.springblade.archive.entity.ArchivesAuto;
 import org.springblade.archive.vo.ArchivesAutoVO;
 import org.springblade.archive.mapper.ArchivesAutoMapper;
 import org.springblade.archive.service.IArchivesAutoService;
+import org.springblade.business.entity.ArchiveFile;
+import org.springblade.business.feign.ArchiveFileClient;
 import org.springblade.core.mp.base.BaseServiceImpl;
 import org.springblade.core.mp.support.Condition;
 import org.springblade.core.mp.support.Query;
 import org.springblade.core.tool.utils.Func;
+import org.springblade.manager.entity.ArchiveTreeContract;
+import org.springblade.manager.feign.ArchiveTreeContractClient;
 import org.springblade.system.entity.DictBiz;
 import org.springblade.system.feign.IDictBizClient;
 import org.springframework.stereotype.Service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 
-import java.util.List;
+import java.time.LocalDateTime;
+import java.util.*;
 
 /**
  *  服务实现类
@@ -46,6 +52,10 @@ import java.util.List;
 public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper, ArchivesAuto> implements IArchivesAutoService {
 
 	private final IDictBizClient iDictBizClient;
+	private ArchiveFileClient archiveFileClient;
+	private ArchiveTreeContractClient archiveTreeContractClient;
+
+
 	@Override
 	public IPage<ArchivesAutoVO> selectArchivesAutoPage(IPage<ArchivesAutoVO> page, ArchivesAutoVO archivesAuto) {
 		return page.setRecords(baseMapper.selectArchivesAutoPage(page, archivesAuto));
@@ -106,4 +116,398 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		return true;
 	}
 
+
+
+	public void archiveAutoMethod(Long projectId){
+		//步骤一:把项目下未锁定的案卷拆卷。
+		baseMapper.splitArchvies(projectId);
+		//步骤二:查询归档树节点。存在未归档文件的节点。
+		List<ArchiveTreeContract> list = archiveTreeContractClient.getHavedFileNodeByProjectID(projectId);
+		//步骤三:遍历归档树节点整理出 默认规则节点,分类并卷节点,单独组卷节点 三个集合。
+		List<ArchiveTreeContract> list1= new ArrayList<>();
+		List<ArchiveTreeContract> list2= new ArrayList<>();
+		List<ArchiveTreeContract> list3= new ArrayList<>();
+		for(ArchiveTreeContract treeContract:list){
+			Integer archiveAutoType = treeContract.getArchiveAutoType();
+			switch (archiveAutoType){
+				case 1:
+					list1.add(treeContract);
+					break;
+				case 2:
+					list2.add(treeContract);
+					break;
+				case 3:
+					list3.add(treeContract);
+					break;
+			}
+		}
+		//步骤四:按照单独,分类,默认的顺序执行组卷流程。
+		archiveAutoMethod3(list3);//单独组卷
+		archiveAutoMethod2(list2);//分类组卷
+		archiveAutoMethod1(list1);//默认组卷
+	}
+
+
+	/**
+	 * 检查当前案卷的文件集合是否在规格内,能否开始组卷。
+	 * 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;
+	}
+
+	private ArchivesAuto builtArchives(ArchiveTreeContract node,int pageN,int fileN){
+		ArchivesAuto archivesAuto = new ArchivesAuto();
+		archivesAuto.setProjectId(node.getProjectId());
+		archivesAuto.setContractId(node.getContractId());
+		archivesAuto.setName("");//TODO 案卷题名
+		archivesAuto.setFileNumber("");//TODO 档号
+		//archivesAuto.setMicron();//微缩号
+		archivesAuto.setUnit("");//TODO 单位
+		//archivesAuto.setQuantity();//数量/单位
+		archivesAuto.setSpecification("");//TODO 规格 从节点规格获取
+		archivesAuto.setStartDate(null);//TODO 文件开始时间
+		archivesAuto.setEndDate(null);//TODO 文件结束时间
+		archivesAuto.setStorageTime("");//TODO 保管时间  从节点规格获取
+		archivesAuto.setSecretLevel("");//TODO 保密级别 从节点规格获取
+		//archivesAuto.setCarrierType();//载体类型
+		//archivesAuto.setKeywords();//主题词
+		//archivesAuto.setStorageLocation();//存放位置
+		archivesAuto.setIsArchive(1);//已归档
+		//archivesAuto.setRemark();//备注
+		archivesAuto.setRollDate(null);// TODO 立卷日期
+		archivesAuto.setRollor("自动");//立卷人
+		archivesAuto.setNodeId(node.getId());//归档树节点
+		archivesAuto.setOutUrl("");//TODO 生成案卷的封面 目录 备考表,背级
+		archivesAuto.setFileN(fileN);//文件数量
+		archivesAuto.setPageN(pageN);//案卷页数
+		//archivesAuto.setMileage();
+		//archivesAuto.setFileType();
+		//archivesAuto.setSize();
+		archivesAuto.setTreeSort(node.getTreeSort());
+		//archivesAuto.setIsOpen();
+		archivesAuto.setIscheck(0);
+		archivesAuto.setIsAutoFile(0);//是否案卷收集上传的案卷
+		archivesAuto.setIsLock(0);//案卷锁定状态
+		baseMapper.insert(archivesAuto);
+		return archivesAuto;
+	}
+
+	/**
+	 * 单独组卷规则组卷
+	 * @param waitArchiveFiles
+	 * @param node
+	 */
+	private void createArchive3(List<ArchiveFile> waitArchiveFiles, ArchiveTreeContract node,int pageN){
+
+		//1.创建新案卷
+		ArchivesAuto archivesAuto = builtArchives(node, pageN, waitArchiveFiles.size());
+		//2.设置文件所属案卷,组卷状态
+		Long archivesAutoId = archivesAuto.getId();
+		for(ArchiveFile file:waitArchiveFiles){
+			file.setArchiveId(archivesAutoId);//设置文件所属案卷
+			file.setIsArchive(1);
+			//TODO 重新打页码文件
+		}
+		archiveFileClient.updateArchiveFileForCreateArchive(waitArchiveFiles);
+	}
+
+
+	/**
+	 * 单租组卷流程  节点下的文件只在当前节点下组卷
+	 */
+	private void archiveAutoMethod3(List<ArchiveTreeContract> list){
+		//步骤1:遍历节点集合
+		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 走分盒组卷流程
+						if(archiveFilesSize==archiveFiles.size() && waitArchiveFiles.size()>0){
+							//最后一个文件直接将waitArchiveFiles组卷
+							createArchive3(waitArchiveFiles,node,archivesSize);
+						}
+					}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()){
+								//最后一个文件直接将waitArchiveFiles组卷
+								createArchive3(waitArchiveFiles,node,archivesSize);
+							}else{
+								continue;
+							}
+						}
+						//步骤6.2达到规格 可以组一卷
+						if(checkStatus==1){
+							waitArchiveFiles.add(file);
+							//将waitArchiveFiles组卷
+							createArchive3(waitArchiveFiles,node,archivesSize);
+							//将待组卷文件集合,总页数还原初始值,
+							waitArchiveFiles.clear();
+							archivesSize=0;
+						}
+						//步骤6.3超出规格
+						if(checkStatus==-1){
+							//如果waitArchiveFiles集合size>0,先将集合中文件组卷。再将当前文件放入集合
+							if(waitArchiveFiles.size()>0){
+								//将waitArchiveFiles组卷,
+								createArchive3(waitArchiveFiles,node,archivesSize);
+								//然后将待组卷文件集合,总页数还原初始值,
+								waitArchiveFiles.clear();
+								//保存当前文件进入待组卷集合,待组卷页数=当前文件页数
+								waitArchiveFiles.add(file);
+								archivesSize=filePage;
+
+								//判断是否最后一个文件
+								if(archiveFilesSize==archiveFiles.size()){
+									//如果当前文件最后一个文件直接将waitArchiveFiles组卷
+									createArchive3(waitArchiveFiles,node,archivesSize);
+									waitArchiveFiles.clear();
+									archivesSize=0;
+								}
+							}else{
+								//步骤6.3.2如果waitArchiveFiles集合size=0,说明当前文件已经超过规格,直接将当前文件组卷
+								waitArchiveFiles.add(file);
+								//直接将waitArchiveFiles组卷
+								createArchive3(waitArchiveFiles,node,archivesSize);
+								waitArchiveFiles.clear();
+								archivesSize=0;
+							}
+						}
+					}
+				}
+			}
+
+		}
+
+
+
+
+
+	}
+
+	/**
+	 * 分类并卷组卷  设置分类的节点下只有一个案卷,节点下的所有文件都组成这个案卷。如果设置分类节点(select=1的)多个,案卷归属排序第一个节点。
+	 */
+	private void archiveAutoMethod2(List<ArchiveTreeContract> list){
+
+		//分类并卷集合<groupId,List<文件>>
+		Map<Long,List<ArchiveFile>> archiveMap = new HashMap<>();
+		//记录同个分组id的第一个节点ID 案卷归属于这个节点
+		Map<Long,Long> groupId2NodeIdMap = new HashMap<>();
+
+		//步骤1:遍历节点集合
+		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){
+						//TODO 走分盒流程
+					}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);
+							groupId2NodeIdMap.put(archiveAutoGroupId,node.getId());
+						}
+					}
+				}
+			}
+		}
+		//步骤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的第一个groupId2NodeIdMap
+
+		}
+
+	}
+
+	/**
+	 * 默认组卷流程 文件可以跨节点组卷,受最高并卷节点限制范围,跨节点文件组卷时,案卷规格按照第一个文件所在的节点规格 组卷。
+	 */
+	private void archiveAutoMethod1(List<ArchiveTreeContract> list){
+		//最高并卷节点
+		Long archiveAutoNodeId=null;
+
+		//当前待组卷规格大小
+		int specificationSize=0;
+		//待组卷文件总页数
+		int archivesSize=0;
+		//待组卷文件集合
+		List<ArchiveFile> waitArchiveFiles = new ArrayList<>();
+
+		//步骤1:遍历节点集合
+		int nodeSize=0;
+		for(ArchiveTreeContract node:list){
+			nodeSize++;
+			if(archiveAutoNodeId==null){
+				archiveAutoNodeId=node.getArchiveAutoNodeId();
+			}
+			//当前节点的的archiveAutoNodeId
+			Long archiveAutoNodeId_current = node.getArchiveAutoNodeId();
+
+
+			//步骤2:判断当前节点是否超出最高节点
+			if(!archiveAutoNodeId.equals(archiveAutoNodeId_current)) {
+				//超过最高并卷节点(节点是排序好的,只要不相等就超过了)
+				if(waitArchiveFiles.size()>0){
+					//TODO 将待组卷集合里的文件组卷
+				}
+				waitArchiveFiles.clear();
+				archivesSize=0;
+				archiveAutoNodeId=node.getArchiveAutoNodeId();//更新当前最高并卷节点
+			}
+
+			//步骤3.1:获取节点规格
+			if(waitArchiveFiles.size()==0){
+				//waitArchiveFiles待组卷文件为空时,按当前节点的规格
+				specificationSize=300;//TODO
+			}
+
+			//步骤3.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.3:遍历未组卷文件
+			int archiveFilesSize=0;
+			for(ArchiveFile file:archiveFiles){
+				archiveFilesSize++;
+				//步骤3.4:判断文件是否存在分盒设置
+				if(file.getBoxNumber()!=null) {
+					//TODO 走分盒组卷流程
+					if(nodeSize==list.size() && archiveFilesSize==archiveFiles.size()){
+						//TODO 如果当前是最后一个文件直接将waitArchiveFiles组卷
+					}
+				}else{
+					//步骤3.5 计算和判断待组卷文件集合是否达到组卷要求,达到要求创建案卷,案卷归属当前节点,案卷下文件改为已组卷
+					Integer filePage = file.getFilePage();
+					archivesSize=archivesSize+filePage;
+					Integer checkStatus = checkSpecificationSize(specificationSize, archivesSize);
+					//步骤3.6未到规格 不组卷
+					if(checkStatus==0){
+						waitArchiveFiles.add(file);
+						//判断是否最后一个节点,最后一个文件
+						if(nodeSize==list.size() && archiveFilesSize==archiveFiles.size()){
+							//TODO 直接将waitArchiveFiles待组卷集合组卷,归属集合第一个文件所在节点
+							//将待组卷文件集合,总页数还原初始值,
+							waitArchiveFiles.clear();
+							archivesSize=0;
+						}else{
+							continue;
+						}
+					}
+					//步骤3.7达到规格 可以组一卷
+					if(checkStatus==1){
+						waitArchiveFiles.add(file);
+						//TODO 将waitArchiveFiles待组卷集合组卷,归属集合第一个文件所在节点
+						//将待组卷文件集合,总页数还原初始值,
+						waitArchiveFiles.clear();
+						archivesSize=0;
+						specificationSize=300;//TODO 更新specificationSize待组卷规格为 当前节点的组卷规格
+					}
+					//步骤3.8超出规格
+					if(checkStatus==-1){
+						//步骤3.9如果waitArchiveFiles集合size>0,先将集合中文件组卷。再将当前文件加入集合
+						if(waitArchiveFiles.size()>0){
+							//3.9.1 TODO 将waitArchiveFiles组卷,归属集合第一个文件所在节点
+							//将待组卷文件集合,总页数还原初始值,
+							waitArchiveFiles.clear();
+							//3.9.2保存当前文件进入待组卷集合,
+							waitArchiveFiles.add(file);
+							//3.9.3待组卷页数=当前文件页数
+							archivesSize=filePage;
+							specificationSize=300;//TODO 更新specificationSize待组卷规格为 当前节点的组卷规格
+							//3.9.4 判断当前文件是不是最后一个节点,最后一个文件
+							if(nodeSize==list.size() && archiveFilesSize==archiveFiles.size()){
+								//TODO 最后一个文件再将waitArchiveFiles组卷
+							}
+						}else{
+							//步骤3.10 如果waitArchiveFiles集合size=0,说明当前文件已经超过规格,直接将当前文件组卷
+							waitArchiveFiles.add(file);
+							//TODO 直接将waitArchiveFiles组卷
+							waitArchiveFiles.clear();
+							archivesSize=0;
+							specificationSize=300;//TODO 更新specificationSize待组卷规格为 当前节点的组卷规格
+						}
+					}
+
+				}
+			}
+
+		}
+
+	}
+
+
 }

+ 88 - 41
blade-service/blade-business/src/main/java/org/springblade/business/controller/InformationWriteQueryController.java

@@ -1,5 +1,6 @@
 package org.springblade.business.controller;
 
+import cn.hutool.core.lang.hash.Hash;
 import com.alibaba.excel.util.DateUtils;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
@@ -919,7 +920,7 @@ public class InformationWriteQueryController extends BladeController {
         //判断是否未生成文件
         List<String> list = Arrays.asList(ids.split(","));
         for (String s : list) {
-            if (StringUtils.isBlank(s)){
+            if (StringUtils.isBlank(s)) {
                 return R.fail("选择的资料未生成文件");
             }
         }
@@ -981,7 +982,7 @@ public class InformationWriteQueryController extends BladeController {
             //判断是否未生成文件
             List<String> list = Arrays.asList(ids.split(","));
             for (String s : list) {
-                if (StringUtils.isBlank(s)){
+                if (StringUtils.isBlank(s)) {
                     return R.fail("选择的资料未生成文件");
                 }
             }
@@ -1000,7 +1001,7 @@ public class InformationWriteQueryController extends BladeController {
                 }
             }
             return R.success("下载成功");
-        }else {
+        } else {
             return R.fail("选择的资料未生成文件");
         }
     }
@@ -1014,6 +1015,19 @@ public class InformationWriteQueryController extends BladeController {
     public R<Boolean> batchAbolish(@RequestParam String ids, String primaryKeyId) {
         //获取所有相关任务记录
         List<Task> taskList = this.taskClient.queryTaskListByFormDataId(ids);
+
+        if (taskList.size() == 0) {
+            //试验
+            List<InformationQuery> dataList = this.informationQueryService.getBaseMapper().selectList(Wrappers.<InformationQuery>lambdaQuery()
+                    .select(InformationQuery::getId)
+                    .eq(InformationQuery::getType, 2)
+                    .in(InformationQuery::getWbsId, Func.toStrList(ids)));
+            if (dataList.size() > 0) {
+                List<Long> dataIds = dataList.stream().map(InformationQuery::getId).collect(Collectors.toList());
+                taskList = this.taskClient.queryTaskListByFormDataId(StringUtils.join(dataIds, ","));
+            }
+        }
+
         if (taskList != null && taskList.size() > 0) {
             try {
                 //执行废除
@@ -1156,10 +1170,10 @@ public class InformationWriteQueryController extends BladeController {
                 String sql;
                 if (StringUtils.isNotEmpty(primaryKeyId)) {
                     //单个废除
-                    sql = "update u_trial_self_inspection_record set task_status = '未上报' where id in(" + primaryKeyId + ")";
+                    sql = "update u_trial_self_inspection_record set task_status = '已废除' where id = " + primaryKeyId;
                 } else {
                     //批量废除直接调的该接口,primaryKeyId为null,ids=当前试验记录的ids
-                    sql = "update u_trial_self_inspection_record set task_status = '未上报' where id in(" + ids + ")";
+                    sql = "update u_trial_self_inspection_record set task_status = '已废除' where id in(" + ids + ")";
                 }
                 jdbcTemplate.execute(sql);
 
@@ -1184,10 +1198,35 @@ public class InformationWriteQueryController extends BladeController {
             String[] ids = startTaskVO.getIds().split(",");
             if (ids.length > 0) {
                 List<InformationQuery> queryList = this.informationQueryService.list(Wrappers.<InformationQuery>lambdaQuery().in(InformationQuery::getId, Arrays.asList(ids)));
+
+                //试验批量上报
+                String trialIds = "";
+                Map<Long, Long> mapKey = new HashMap<>();
+                if (queryList.size() == 0 && startTaskVO.getTrialSelfInspectionRecordId() == 1L) {
+                    //试验填报数据
+                    queryList = new ArrayList<>(this.informationQueryService.list(Wrappers.<InformationQuery>lambdaQuery().in(InformationQuery::getWbsId, Arrays.asList(ids))));
+                    //重新绑定trialSelfInspectionRecordId使用map
+                    for (InformationQuery informationQuery : queryList) {
+                        mapKey.put(informationQuery.getId(), informationQuery.getWbsId());
+                    }
+                    //试验记录ids重新赋值映射为数据源ids
+                    ids = queryList.stream().map(InformationQuery::getId).map(String::valueOf).toArray(String[]::new);
+                    trialIds = startTaskVO.getIds();
+                }
+
                 Map<String, String> queryMap = new HashMap<>();
                 queryList.forEach(query -> queryMap.put(query.getId().toString(), query.getName()));
                 try {
                     for (String id : ids) {
+
+                        //试验-批量上报时,重新绑定当前试验记录id
+                        if (ObjectUtil.isNotEmpty(startTaskVO.getTrialSelfInspectionRecordId()) && startTaskVO.getTrialSelfInspectionRecordId() == 1L) {
+                            Long wbsId = mapKey.get(Long.parseLong(id));
+                            if (ObjectUtil.isNotEmpty(wbsId)) {
+                                startTaskVO.setTrialSelfInspectionRecordId(wbsId);
+                            }
+                        }
+
                         //生成任务实体
                         TaskVO taskVO = new TaskVO();
                         BeanUtils.copyProperties(startTaskVO, taskVO);
@@ -1225,13 +1264,21 @@ public class InformationWriteQueryController extends BladeController {
                             //修改记录
                             this.informationQueryService.update(wrappers);
 
-                            //修改试验记录上报任务状态
-                            if (ObjectUtil.isNotEmpty(startTaskVO.getTrialSelfInspectionRecordId())) {
+                            //修改试验记录上报任务状态(单上报)
+                            if (ObjectUtil.isNotEmpty(startTaskVO.getTrialSelfInspectionRecordId()) && startTaskVO.getTrialSelfInspectionRecordId() != 1L) {
                                 String sql = "update u_trial_self_inspection_record set task_status = '待审批' where id = " + startTaskVO.getTrialSelfInspectionRecordId();
                                 jdbcTemplate.execute(sql);
                             }
                         }
                     }
+
+                    if (StringUtils.isNotEmpty(trialIds)) {
+                        //修改试验记录上报任务状态(批量上报)
+                        String sql = "update u_trial_self_inspection_record set task_status = '待审批' where id in(" + trialIds + ")";
+                        jdbcTemplate.execute(sql);
+                    }
+
+
                 } catch (Exception e) {
                     e.printStackTrace();
                     return R.data(300, false, "上报失败");
@@ -1277,10 +1324,10 @@ public class InformationWriteQueryController extends BladeController {
     public R<Boolean> diySort(@RequestBody DiySortVO vo) {
         List<String> sortLists = vo.getSortList();
         boolean b = wbsTreeContractClient.diySort(sortLists);
-        if(sortLists!=null){
+        if (sortLists != null) {
             WbsTreeContract needCopyNode = this.wbsTreeContractClient.getContractNodeByPrimaryKeyId(sortLists.get(0));
             //获取父节点信息
-            informationQueryService.AsyncWbsTree(needCopyNode.getParentId()+ "",needCopyNode.getParentId()+ "",needCopyNode.getContractId(),"","1");
+            informationQueryService.AsyncWbsTree(needCopyNode.getParentId() + "", needCopyNode.getParentId() + "", needCopyNode.getContractId(), "", "1");
         }
         return R.status(b);
     }
@@ -1295,13 +1342,13 @@ public class InformationWriteQueryController extends BladeController {
         //首先查询需要复制的节点及其下级所有子节点的信息
         WbsTreeContract needCopyNode = this.wbsTreeContractClient.getContractNodeByPrimaryKeyId(vo.getNeedCopyPrimaryKeyId());
         // 获取当前节点的所有子节点
-        String vocational = SnowFlakeUtil.getId()+"";
+        String vocational = SnowFlakeUtil.getId() + "";
         //新增施工台账
-        List<WbsTreeContract>   saveList = new ArrayList<>();
+        List<WbsTreeContract> saveList = new ArrayList<>();
         List<ConstructionLedger> saveLedger = new ArrayList<>();
         // 获取附件
-        List<WbsTreeContract> nodeChildAll = informationQueryService.getNodeChildAllByNodeId(needCopyNode.getId() + "", needCopyNode.getContractId(),vo.getNeedCopyPrimaryKeyId());
-       // 获取实体表列对象
+        List<WbsTreeContract> nodeChildAll = informationQueryService.getNodeChildAllByNodeId(needCopyNode.getId() + "", needCopyNode.getContractId(), vo.getNeedCopyPrimaryKeyId());
+        // 获取实体表列对象
         List<QueryProcessDataVO> nodeTabCols = informationQueryService.getNodeChildTabColsAllByNodeId(needCopyNode.getId() + "", needCopyNode.getContractId());
         // 转化为map
         Map<String, String> nodeTabColsMap = nodeTabCols.stream().collect(Collectors.toMap(QueryProcessDataVO::getQueryType, QueryProcessDataVO::getAncestors, (key1, key2) -> key2));
@@ -1370,25 +1417,25 @@ public class InformationWriteQueryController extends BladeController {
                 }
 
                 // 组织复制值Sql
-                if(nodeTabColsMap!=null && node.getType()==2){
+                if (nodeTabColsMap != null && node.getType() == 2) {
                     String tableName = newData.getInitTableName();
                     String col = nodeTabColsMap.get(tableName);
                     String colVal = nodeTabColsMap.get(tableName);
-                    colVal = colVal.replaceAll("id,p_key_id,","'"+SnowFlakeUtil.getId()+"' as id,'"+newData.getPKeyId()+"' as p_key_id,");
-                    copeSql.append("insert into "+tableName+"  ("+col+") select "+colVal+" from "+tableName+" where p_key_id='"+node.getPKeyId()+"' ;");
+                    colVal = colVal.replaceAll("id,p_key_id,", "'" + SnowFlakeUtil.getId() + "' as id,'" + newData.getPKeyId() + "' as p_key_id,");
+                    copeSql.append("insert into " + tableName + "  (" + col + ") select " + colVal + " from " + tableName + " where p_key_id='" + node.getPKeyId() + "' ;");
                 }
             });
         }
         //保存节点信息
-         R<Boolean> booleanR = this.saveOrCopyNodeTree(saveList, saveLedger, 32, needCopyNode);
+        R<Boolean> booleanR = this.saveOrCopyNodeTree(saveList, saveLedger, 32, needCopyNode);
 
         //复制数据逻辑
-        if(nodeTabColsMap!=null &&copeSql.length()>=10){
+        if (nodeTabColsMap != null && copeSql.length() >= 10) {
             jdbcTemplate.execute(copeSql.toString());
         }
 
         //获取父节点信息
-        informationQueryService.AsyncWbsTree(needCopyNode.getParentId()+ "",needCopyNode.getParentId()+ "",needCopyNode.getContractId(),"","1");
+        informationQueryService.AsyncWbsTree(needCopyNode.getParentId() + "", needCopyNode.getParentId() + "", needCopyNode.getContractId(), "", "1");
         return booleanR;
     }
 
@@ -1424,23 +1471,23 @@ public class InformationWriteQueryController extends BladeController {
             });
         }
         //复制结构信息
-      //   R<Boolean> booleanR = this.saveOrCopyNodeTree(saveList, saveLedger, 32, needCopyNode);
+        //   R<Boolean> booleanR = this.saveOrCopyNodeTree(saveList, saveLedger, 32, needCopyNode);
         // 复制表数据
 
-        System.out.println("1="+DateUtil.formatDateTime(DateUtil.now()));
+        System.out.println("1=" + DateUtil.formatDateTime(DateUtil.now()));
         List<WbsTreeContract> parentList = new ArrayList<>(), childList = new ArrayList<>(), allList = new ArrayList<>(), saveList = new ArrayList<>();
         //新增施工台账
         List<ConstructionLedger> saveLedger = new ArrayList<>();
 
         parentList.add(needCopyNode);
-        System.out.println("2="+DateUtil.formatDateTime(DateUtil.now()));
+        System.out.println("2=" + DateUtil.formatDateTime(DateUtil.now()));
         //查询所有有效子节点(慢 10分钟)
         this.foreachQueryChildContract(parentList, childList, contractAllNodeMap);
 
-        System.out.println("3="+DateUtil.formatDateTime(DateUtil.now()));
+        System.out.println("3=" + DateUtil.formatDateTime(DateUtil.now()));
         allList.addAll(parentList);
         allList.addAll(childList);
-        System.out.println("4="+DateUtil.formatDateTime(DateUtil.now()));
+        System.out.println("4=" + DateUtil.formatDateTime(DateUtil.now()));
         if ("1".equals(vo.getCopyType())) {
             if (StringUtils.isNotEmpty(vo.getNeedCopyPrimaryKeyId())) {
                 WbsTreeContract parent = this.wbsTreeContractClient.getContractNodeByPrimaryKeyId(vo.getParentPrimaryKeyId());
@@ -1455,7 +1502,7 @@ public class InformationWriteQueryController extends BladeController {
                 });
 
 
-                System.out.println("5="+DateUtil.formatDateTime(DateUtil.now()));
+                System.out.println("5=" + DateUtil.formatDateTime(DateUtil.now()));
                 //todo 单份复制
                 allList.forEach(node -> {
                     WbsTreeContract newData = new WbsTreeContract();
@@ -1527,7 +1574,7 @@ public class InformationWriteQueryController extends BladeController {
                     }
                 });
             }
-            System.out.println("6="+DateUtil.formatDateTime(DateUtil.now()));
+            System.out.println("6=" + DateUtil.formatDateTime(DateUtil.now()));
         } else {
             //todo 多份复制
             //获取需要复制到的位置集合
@@ -1814,7 +1861,7 @@ public class InformationWriteQueryController extends BladeController {
         Boolean aBoolean = this.wbsTreeContractClient.updateContractNodeParameter(node);
 
         //获取父节点信息
-        informationQueryService.AsyncWbsTree(queries.getParentId()+ "",queries.getParentId()+ "",queries.getContractId(),"","1");
+        informationQueryService.AsyncWbsTree(queries.getParentId() + "", queries.getParentId() + "", queries.getContractId(), "", "1");
         return R.data(aBoolean);
     }
 
@@ -1886,9 +1933,9 @@ public class InformationWriteQueryController extends BladeController {
 
         if (queryProcess != null && queryProcess.size() > 0) {
             //检查这些填报节点是否存在已经审批或已经上报的节点,如果存在则不允许删除
-            List<QueryProcessDataVO> approvalList = queryProcess.stream().filter(vo -> new Integer("2").equals(vo.getStatus()) && vo.getInformationQueryId()!=null).collect(Collectors.toList());
+            List<QueryProcessDataVO> approvalList = queryProcess.stream().filter(vo -> new Integer("2").equals(vo.getStatus()) && vo.getInformationQueryId() != null).collect(Collectors.toList());
             //
-            List<QueryProcessDataVO> runTaskList = queryProcess.stream().filter(vo -> new Integer("1").equals(vo.getStatus()) && vo.getInformationQueryId()!=null).collect(Collectors.toList());
+            List<QueryProcessDataVO> runTaskList = queryProcess.stream().filter(vo -> new Integer("1").equals(vo.getStatus()) && vo.getInformationQueryId() != null).collect(Collectors.toList());
             if (approvalList.size() > 0 || runTaskList.size() > 0) {
                 //说明存在已经审批或已经上报的节点,不允许删除
                 return R.data(300, false, "存在已经上报或审批的节点,不允许删除");
@@ -1915,7 +1962,7 @@ public class InformationWriteQueryController extends BladeController {
         this.recycleBinClient.saveDelBusinessData(idArray, StringUtils.isNotEmpty(removeNode.getFullName()) ? removeNode.getFullName() : removeNode.getNodeName(), 2, parentNodeName.toString(), removeNode.getProjectId(), removeNode.getContractId());
         Boolean aBoolean = this.wbsTreeContractClient.removeContractTreeNode(idArray);
         // 更新redis
-        this.informationQueryService.AsyncWbsTree(removeNode.getParentId()+ "",removeNode.getParentId()+ "",removeNode.getContractId(),"","1");
+        this.informationQueryService.AsyncWbsTree(removeNode.getParentId() + "", removeNode.getParentId() + "", removeNode.getContractId(), "", "1");
         return R.data(aBoolean);
     }
 
@@ -2103,9 +2150,9 @@ public class InformationWriteQueryController extends BladeController {
         R<Boolean> booleanR = this.saveOrCopyNodeTree(saveList, saveLedger, 2, treeContract);
 
         //更新redis
-        List<WbsTreeContractTreeVOS> wbsTreeContractTreeVOS = this.informationQueryService.queryContractTree(treeContract.getId()+ "", treeContract.getContractId(), "", "1");
+        List<WbsTreeContractTreeVOS> wbsTreeContractTreeVOS = this.informationQueryService.queryContractTree(treeContract.getId() + "", treeContract.getContractId(), "", "1");
 
-        informationQueryService.AsyncWbsTree(treeContract.getId()+ "",treeContract.getId()+ "",treeContract.getContractId(),"","1");
+        informationQueryService.AsyncWbsTree(treeContract.getId() + "", treeContract.getId() + "", treeContract.getContractId(), "", "1");
         return booleanR;
     }
 
@@ -2360,9 +2407,9 @@ public class InformationWriteQueryController extends BladeController {
             //如果是首件列表请求,则删掉没有标记为首件的数据
             if (queryDataResult != null && queryDataResult.size() > 0) {
                 if (StringUtils.isNotEmpty(vo.getIsFirst())) {
-                    if (StringUtils.isNotEmpty(vo.getFirstTitle())){
-                        queryDataResult = queryDataResult.stream().filter(qdr->"3".equals(qdr.getQueryType())).collect(Collectors.toList());
-                    }else {
+                    if (StringUtils.isNotEmpty(vo.getFirstTitle())) {
+                        queryDataResult = queryDataResult.stream().filter(qdr -> "3".equals(qdr.getQueryType())).collect(Collectors.toList());
+                    } else {
                         //节点主键集合
                         List<String> treeIds = queryDataResult.stream().map(QueryProcessDataVO::getPrimaryKeyId).distinct().collect(Collectors.toList());
                         //通过合同段主键在首件关联表中查询出所有数据
@@ -2422,22 +2469,22 @@ public class InformationWriteQueryController extends BladeController {
                                                                                    @RequestParam String parentId,
                                                                                    @RequestParam String contractId,
                                                                                    @RequestParam String contractIdRelation,
-                                                                                   @RequestParam String classifyType){
+                                                                                   @RequestParam String classifyType) {
         if (StringUtils.isNotEmpty(primaryKeyId)) {
             parentId = primaryKeyId;
         }
 
-        String dataInfoId = contractId+"_"+parentId+"_"+classifyType;
-        Object data = RedisTemplate.opsForValue().get("blade-manager::contract:wbstree:"+dataInfoId);
+        String dataInfoId = contractId + "_" + parentId + "_" + classifyType;
+        Object data = RedisTemplate.opsForValue().get("blade-manager::contract:wbstree:" + dataInfoId);
         List<WbsTreeContractTreeVOS> wbsTreeContractTreeVOS = null;
-        if(data!=null){
+        if (data != null) {
             wbsTreeContractTreeVOS = JSON.parseArray(data.toString(), WbsTreeContractTreeVOS.class);
         }
 
         if (wbsTreeContractTreeVOS == null) {
             wbsTreeContractTreeVOS = this.informationQueryService.queryContractTree(parentId, contractId, contractIdRelation, classifyType);
-            JSONArray array= JSONArray.parseArray(JSON.toJSONString(wbsTreeContractTreeVOS));
-            RedisTemplate.opsForValue().set("blade-manager::contract:wbstree:"+dataInfoId,JSON.toJSON(array).toString());
+            JSONArray array = JSONArray.parseArray(JSON.toJSONString(wbsTreeContractTreeVOS));
+            RedisTemplate.opsForValue().set("blade-manager::contract:wbstree:" + dataInfoId, JSON.toJSON(array).toString());
         }
         return R.data(wbsTreeContractTreeVOS);
     }

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

@@ -150,10 +150,10 @@ public class TrialDetectionController extends BladeController {
     public R<Object> selfRemove(@Valid @RequestParam String ids) {
         List<TrialSelfInspectionRecord> recordList = iTrialSelfInspectionRecordService.getBaseMapper().selectList(Wrappers.<TrialSelfInspectionRecord>lambdaQuery()
                 .select(TrialSelfInspectionRecord::getTaskStatus)
-                .ne(TrialSelfInspectionRecord::getTaskStatus, "未上报")
+                .and(obj -> obj.ne(TrialSelfInspectionRecord::getTaskStatus, "未上报").ne(TrialSelfInspectionRecord::getTaskStatus, "已废除"))
                 .in(TrialSelfInspectionRecord::getId, Func.toLongList(ids)));
         if (recordList.size() > 0) {
-            return R.fail("只能删除未上报记录信息,操作失败");
+            return R.fail("只能删除未上报或已废除的试验记录信息,操作失败");
         }
         //刪除按钮状态记录
         String sql1 = "delete from u_trial_self_data_record where record_id in(" + ids + ")";

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

@@ -85,4 +85,13 @@ public class ArchiveFileClientImpl implements ArchiveFileClient {
 
         return this.iArchiveFileService.getArchiveFileByArchivesId(archivesIds,fileIds);
     }
+
+    /**
+     * 组卷完成 设置文件对应案卷
+     * @param waitArchiveFiles
+     */
+    @Override
+    public void updateArchiveFileForCreateArchive(List<ArchiveFile> waitArchiveFiles) {
+        iArchiveFileService.updateBatchById(waitArchiveFiles);
+    }
 }

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

@@ -156,6 +156,7 @@ public class ArchiveFileServiceImpl extends BaseServiceImpl<ArchiveFileMapper, A
 		}
 	}
 
+
 	@Override
 	public IPage<ArchiveFileVO> selectArchiveFilePageByBoxName(ArchiveFileVO vo) {
 		Query query = new Query();
@@ -179,4 +180,5 @@ public class ArchiveFileServiceImpl extends BaseServiceImpl<ArchiveFileMapper, A
 
 		return iPage.setRecords(pageVoList);
 	}
+
 }

+ 19 - 6
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialDeviceUseServiceImpl.java

@@ -47,10 +47,7 @@ import javax.servlet.http.HttpServletResponse;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.stream.Collectors;
 
 @Service
@@ -377,18 +374,34 @@ public class TrialDeviceUseServiceImpl extends BaseServiceImpl<TrialDeviceUseMap
 
     @Async
     public void addDeviceUseInfo(TrialSelfInspectionRecordDTO dto) {
-        if (com.baomidou.mybatisplus.core.toolkit.StringUtils.isNotEmpty(dto.getDeviceUseIds())) {
+        if (StringUtils.isNotEmpty(dto.getDeviceUseIds())) {
             //获取进场记录
             List<TrialDeviceInfo> deviceInfos = trialDeviceInfoMapper.selectList(Wrappers.<TrialDeviceInfo>lambdaQuery().in(TrialDeviceInfo::getId, dto.getDeviceUseIds()));
 
+            //获取样品编号、名称
+            String sampleNames = "";
+            String sampleNumbers = "";
+            if (StringUtils.isNotEmpty(dto.getSampleIds())) {
+                List<TrialSampleInfo> trialSampleInfos = trialSampleInfoService.getBaseMapper().selectList(Wrappers.<TrialSampleInfo>lambdaQuery()
+                        .select(TrialSampleInfo::getSpecificationNumber, TrialSampleInfo::getMaterialName)
+                        .in(TrialSampleInfo::getId, Func.toLongList(dto.getSampleIds())));
+                List<String> names = trialSampleInfos.stream().map(TrialSampleInfo::getMaterialName).filter(string -> !string.isEmpty()).collect(Collectors.toList());
+                sampleNames = StringUtils.join(names, "、");
+                List<String> numbers = trialSampleInfos.stream().map(TrialSampleInfo::getSpecificationNumber).filter(string -> !string.isEmpty()).collect(Collectors.toList());
+                sampleNumbers = StringUtils.join(numbers, "、");
+            }
+
             //构造使用记录
             List<TrialDeviceUse> list = new ArrayList<>();
             for (TrialDeviceInfo deviceInfo : deviceInfos) {
                 TrialDeviceUse trialDeviceUses = BeanUtil.copyProperties(deviceInfo, TrialDeviceUse.class);
                 if (trialDeviceUses != null) {
+                    trialDeviceUses.setId(SnowFlakeUtil.getId());
                     trialDeviceUses.setNodeId(dto.getNodeId());
                     trialDeviceUses.setDeviceInfoId(deviceInfo.getId());
-                    trialDeviceUses.setId(SnowFlakeUtil.getId());
+                    trialDeviceUses.setManagerName(dto.getTrialUserName());
+                    trialDeviceUses.setMaterialName(sampleNames);
+                    trialDeviceUses.setSpecificationNumber(sampleNumbers);
                     list.add(trialDeviceUses);
                 }
             }

+ 6 - 27
blade-service/blade-business/src/main/java/org/springblade/business/service/impl/TrialSelfInspectionRecordServiceImpl.java

@@ -239,7 +239,7 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
             List<String> mobilizationIds = new ArrayList<>();
             for (String sampleId : sampleIds) {
                 String mobilizationId = baseMapper.selectMobilizationRecord(sampleId);
-                if (StringUtils.isNotEmpty(mobilizationId)){
+                if (StringUtils.isNotEmpty(mobilizationId)) {
                     mobilizationIds.add(mobilizationId);
                 }
             }
@@ -930,38 +930,17 @@ public class TrialSelfInspectionRecordServiceImpl extends BaseServiceImpl<TrialS
             }
 
             //取样信息
-            List<TrialSampleInfo> trialSampleInfos = trialSampleInfoMapper.selectList(Wrappers.<TrialSampleInfo>lambdaQuery()
-                    .isNotNull(TrialSampleInfo::getSamplingLocation)
-                    .isNotNull(TrialSampleInfo::getSupplierUnit)
-                    .isNotNull(TrialSampleInfo::getSpecificationNumber)
-                    .isNotNull(TrialSampleInfo::getSpecificationModel)
-                    .in(TrialSampleInfo::getId, ids));
-            List<String> samplingLocations = trialSampleInfos.stream().map(TrialSampleInfo::getSamplingLocation).collect(Collectors.toList());
-            /*String samplingLocation = samplingLocations.stream().findAny().orElse(null);
-            if (samplingLocations.size() > 1 && StringUtils.isNotEmpty(samplingLocation)) {
-                samplingLocation = samplingLocation + "等" + samplingLocations.size() + "个取样地点";
-            }*/
+            List<TrialSampleInfo> trialSampleInfos = trialSampleInfoMapper.selectList(Wrappers.<TrialSampleInfo>lambdaQuery().in(TrialSampleInfo::getId, ids));
+            List<String> samplingLocations = trialSampleInfos.stream().map(TrialSampleInfo::getSamplingLocation).filter(string -> !string.isEmpty()).collect(Collectors.toList());
             String samplingLocation = org.apache.commons.lang.StringUtils.join(samplingLocations, "、");
 
-            List<String> calculationUnits = trialSampleInfos.stream().map(TrialSampleInfo::getCalculationUnit).collect(Collectors.toList());
-            /*String supplierUnit = supplierUnits.stream().findAny().orElse(null);
-            if (supplierUnits.size() > 1 && StringUtils.isNotEmpty(supplierUnit)) {
-                supplierUnit = supplierUnit + "等" + supplierUnits.size() + "个单位";
-            }*/
+            List<String> calculationUnits = trialSampleInfos.stream().map(TrialSampleInfo::getCalculationUnit).filter(string -> !string.isEmpty()).collect(Collectors.toList());
             String calculationUnit = org.apache.commons.lang.StringUtils.join(calculationUnits, "、");
 
-            List<String> specificationNumbers = trialSampleInfos.stream().map(TrialSampleInfo::getSpecificationNumber).collect(Collectors.toList());
-            /*String specificationNumber = supplierUnits.stream().findAny().orElse(null);
-            if (specificationNumbers.size() > 1 && StringUtils.isNotEmpty(specificationNumber)) {
-                specificationNumber = specificationNumber + "等" + specificationNumbers.size() + "个样品编号";
-            }*/
+            List<String> specificationNumbers = trialSampleInfos.stream().map(TrialSampleInfo::getSpecificationNumber).filter(string -> !string.isEmpty()).collect(Collectors.toList());
             String specificationNumber = org.apache.commons.lang.StringUtils.join(specificationNumbers, "、");
 
-            List<String> specificationModels = trialSampleInfos.stream().map(TrialSampleInfo::getSpecificationModel).collect(Collectors.toList());
-            /*String specificationModel = supplierUnits.stream().findAny().orElse(null);
-            if (specificationModels.size() > 1 && StringUtils.isNotEmpty(specificationModel)) {
-                specificationModel = specificationModel + "等" + specificationModels.size() + "个规格类型";
-            }*/
+            List<String> specificationModels = trialSampleInfos.stream().map(TrialSampleInfo::getSpecificationModel).filter(string -> !string.isEmpty()).collect(Collectors.toList());
             String specificationModel = org.apache.commons.lang.StringUtils.join(specificationModels, "、");
 
             //更新

+ 9 - 14
blade-service/blade-manager/src/main/java/com/mixsmart/utils/CustomFunction.java

@@ -15,23 +15,15 @@ import com.jfireel.expression.token.Token;
 import org.apache.commons.collections4.MapUtils;
 
 import org.jsoup.Jsoup;
-import org.jsoup.nodes.Document;
-import org.jsoup.nodes.Element;
-import org.jsoup.select.Elements;
 import org.springblade.core.tool.utils.*;
-import org.springblade.manager.dto.Coords;
-import org.springblade.manager.dto.ElementData;
-import org.springblade.manager.dto.FormData;
-import org.springblade.manager.entity.Formula;
 
 
-import java.io.File;
 import java.io.FileInputStream;
-import java.io.FileNotFoundException;
 import java.math.BigDecimal;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
@@ -2214,7 +2206,13 @@ public class CustomFunction {
 		List<Object> result = new ArrayList<>();
 		if(data!=null){
 			List<Object> list = obj2List(removeEmpty(data));
-			result=list.stream().distinct().collect(Collectors.toList());
+			/*外观质量,这种中文描述去重*/
+			if(list.stream().filter(CustomFunction::containsZH).anyMatch(e->e.toString().contains("\n"))){
+				AtomicInteger index= new AtomicInteger(1);
+				result=list.stream().flatMap(e-> Arrays.stream(e.toString().split("\\n+"))).map(String::trim).map(e->e.replaceAll("^\\d+、","")).distinct().map(e->(index.getAndIncrement())+"、"+e+"\n").collect(Collectors.toList());
+			}else{
+				result=list.stream().distinct().collect(Collectors.toList());
+			}
 		}
 		return  result;
 	}
@@ -2766,9 +2764,6 @@ public class CustomFunction {
 		return "";
 	}
 
-	public static void main(String[] args) {
-		getElementCell("/www/wwwroot/Users/hongchuangyanfa/Desktop//privateUrl/1640614495422251008.html");
-		System.out.println();
-	}
+
 
 }

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

@@ -74,7 +74,11 @@ public class FormulaUtils {
             if(values.size()>fd.getValues().size()){
                 /*当生成的数据超过实际容量的时候,会自动追加页数*/
                 if(fd.getCoordsList().size()==1){
-                    fd.getValues().get(0).setValue(values.stream().map(StringUtils::handleNull).collect(Collectors.joining("、")));
+                    if(values.stream().filter(CustomFunction::containsZH).anyMatch(e->e.toString().contains("\n"))){
+                        fd.getValues().get(0).setValue(values.stream().filter(Objects::nonNull).map(Object::toString).collect(Collectors.joining()));
+                    }else{
+                        fd.getValues().get(0).setValue(values.stream().map(StringUtils::handleNull).collect(Collectors.joining("、")));
+                    }
                 }else{
                     // copy(fd,values);
                     for(int n=0;n<fd.getValues().size();n++){

+ 14 - 5
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/TrialClassificationConfigurationController.java

@@ -11,6 +11,8 @@ import org.springblade.core.cache.utils.CacheUtil;
 import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.tool.api.R;
 import org.springblade.core.tool.support.Kv;
+import org.springblade.core.tool.utils.Func;
+import org.springblade.core.tool.utils.ObjectUtil;
 import org.springblade.manager.entity.TrialClassificationConfiguration;
 import org.springblade.manager.service.ITrialClassificationConfigurationService;
 import org.springblade.manager.vo.TrialClassificationConfigurationTreeVO;
@@ -56,12 +58,19 @@ public class TrialClassificationConfigurationController extends BladeController
     @ApiOperationSupport(order = 3)
     @ApiOperation(value = "删除节点", notes = "传入节点id")
     @RequestMapping(value = "/remove", method = RequestMethod.GET)
-    public R<Object> remove(@Valid @RequestParam Long id) {
-        List<TrialDetectionData> query = jdbcTemplate.query("select id from m_trial_detection_data where is_deleted = 0 and node_id = " + id, new BeanPropertyRowMapper<>(TrialDetectionData.class));
-        if (query.size() > 0) {
-            throw new ServiceException("当前节点下存在数据,删除失败");
+    public R<Object> remove(@Valid @RequestParam Long id, Long contractId) {
+        if (ObjectUtil.isNotEmpty(contractId)) {
+            //客户端删除
+            List<TrialDetectionData> query = jdbcTemplate.query("select id from m_trial_detection_data where is_deleted = 0 and node_id = " + id + " and contract_id = " + contractId, new BeanPropertyRowMapper<>(TrialDetectionData.class));
+            if (query.size() > 0) {
+                throw new ServiceException("当前节点下存在数据,删除失败");
+            }
+            TrialClassificationConfiguration obj = iTrialClassificationConfigurationService.getBaseMapper().selectById(id);
+            if (obj != null && ObjectUtil.isEmpty(obj.getContractId())) {
+                throw new ServiceException("公共节点无法删除,请联系管理员");
+            }
         }
-        return R.status(iTrialClassificationConfigurationService.removeById(id));
+        return R.status(iTrialClassificationConfigurationService.deleteLogic(Func.toLongList(String.valueOf(id))));
     }
 
     @ApiOperationSupport(order = 4)

+ 16 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/feign/ArchiveTreeContractImpl.java

@@ -3,6 +3,7 @@ package org.springblade.manager.feign;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import lombok.AllArgsConstructor;
 import org.springblade.manager.entity.ArchiveTreeContract;
+import org.springblade.manager.mapper.ArchiveTreeContractMapper;
 import org.springblade.manager.service.IArchiveTreeContractService;
 import org.springframework.web.bind.annotation.RestController;
 
@@ -15,6 +16,8 @@ public class ArchiveTreeContractImpl implements ArchiveTreeContractClient {
 
     private final IArchiveTreeContractService archiveTreeContractService;
 
+    private ArchiveTreeContractMapper archiveTreeContractMapper;
+
     @Override
     public List<ArchiveTreeContract> queryAllChildByAncestors(String id) {
         List<ArchiveTreeContract> archiveTreeList = this.archiveTreeContractService.list(Wrappers.<ArchiveTreeContract>lambdaQuery().like(ArchiveTreeContract::getAncestors, id));
@@ -29,4 +32,17 @@ public class ArchiveTreeContractImpl implements ArchiveTreeContractClient {
 
         return archiveTreeList;
     }
+
+    /**
+     * 获取项目下存在未组卷文件的归档树节点
+     * @param projectId
+     * @return
+     */
+    @Override
+    public List<ArchiveTreeContract> getHavedFileNodeByProjectID(Long projectId) {
+        List<ArchiveTreeContract> list = archiveTreeContractMapper.getHavedFileNodeByProjectID(projectId);
+        return list;
+    }
+
+
 }

+ 3 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/ITurnPointCalculator.java

@@ -214,6 +214,9 @@ public interface ITurnPointCalculator {
              g8.put("sj",data.stream().filter(e->TurnPoint.CE.equals(e.getType())).map(TurnPoint::getSj).collect(Collectors.toList()));
              g8.put("sjv",data.stream().filter(e->TurnPoint.CE.equals(e.getType())&&e.getVertical()).map(TurnPoint::getSj).collect(Collectors.toList()));
              g8.put("sjnv",data.stream().filter(e->TurnPoint.CE.equals(e.getType())&&!e.getVertical()).map(TurnPoint::getSj).collect(Collectors.toList()));
+             g8.put("cd",data.stream().filter(e->TurnPoint.CE.equals(e.getType())).map(TurnPoint::getName).collect(Collectors.toList()));
+             g8.put("cdv",data.stream().filter(e->TurnPoint.CE.equals(e.getType())&&e.getVertical()).map(TurnPoint::getName).collect(Collectors.toList()));
+             g8.put("cdnv",data.stream().filter(e->TurnPoint.CE.equals(e.getType())&&!e.getVertical()).map(TurnPoint::getName).collect(Collectors.toList()));
      }
 
 }

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

@@ -82,10 +82,10 @@ public class SubTable {
                FormulaUtils.write(itemName,itemNameList,true);
                if(design!=null&&design.getCoordsList().size()>0) {
                    FormulaUtils.write(design, designList, true);
+                   design.setUpdate(1);
                }
                FormulaUtils.write(data,dataList,true);
                itemName.setUpdate(1);
-               design.setUpdate(1);
                data.setUpdate(1);
            }
    }

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

@@ -65,4 +65,7 @@ public interface ArchiveTreeContractMapper extends BaseMapper<ArchiveTreeContrac
 	int updateBatch2(@Param("diffRent") List<String> diffRent);
 
 	int updateBatch3();
+
+
+	List<ArchiveTreeContract> getHavedFileNodeByProjectID(@Param("projectId") Long projectId);
 }

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

@@ -283,4 +283,29 @@
         AND status = 1
     </update>
 
+    <select id="getHavedFileNodeByProjectID" resultMap="archiveTreeContractResultMap">
+        SELECT
+            *
+        FROM
+            m_archive_tree_contract
+        WHERE
+            1 = 1
+          AND project_id = #{projectId}
+          AND is_deleted = 0
+          AND archive_auto_type IS NOT NULL
+          AND id IN (
+            SELECT
+                node_id
+            FROM
+                u_archive_file
+            WHERE
+                1 = 1
+              AND project_id = #{projectId}
+              AND is_deleted = 0
+              AND ( is_archive = 0 OR is_archive IS NULL )
+              AND node_id IS NOT NULL
+        )
+        order by tree_sort asc
+    </select>
+
 </mapper>

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

@@ -71,8 +71,6 @@ public interface WbsTreePrivateMapper extends EasyBaseMapper<WbsTreePrivate> {
 
     List<WbsTreePrivate> selectNodeAndTable2(String wbsId, String referencePrivateWbsProjectId);
 
-    boolean updateBatchByPid(@Param("wbsTreePrivates") WbsTreePrivateDTO3 wbsTreePrivates);
-
     List<WbsTreePrivate> selectByIds(@Param("projectId") String projectId, @Param("ids") List<String> ids);
 
     void updateBatchByIds(@Param("wbsTree") WbsTree wbsTree, @Param("projectId") String projectId);

+ 0 - 10
blade-service/blade-manager/src/main/java/org/springblade/manager/mapper/WbsTreePrivateMapper.xml

@@ -238,16 +238,6 @@
           AND is_deleted = 0
     </update>
 
-    <update id="updateBatchByPid">
-        UPDATE m_wbs_tree_private
-        SET node_name   = #{wbsTreePrivates.nodeName},
-            full_name   =#{wbsTreePrivates.nodeName},
-            table_type  = #{wbsTreePrivates.tableType},
-            table_owner = #{wbsTreePrivates.tableOwner},
-            fill_rate = #{wbsTreePrivates.fillRate}
-        WHERE p_key_id = #{wbsTreePrivates.pKeyId}
-    </update>
-
     <update id="updateBatchByIds">
         UPDATE m_wbs_tree_private
         SET node_name = #{wbsTree.nodeName},

+ 5 - 249
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/ArchiveAutoRuleWbsServiceImpl.java

@@ -22,7 +22,10 @@ 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.ArchiveTree;
 import org.springblade.manager.entity.ArchiveTreeContract;
+import org.springblade.manager.entity.WbsTreePrivate;
+import org.springblade.manager.mapper.ArchiveTreeContractMapper;
 import org.springblade.manager.vo.ArchiveAutoRuleWbsVO;
 import org.springblade.manager.mapper.ArchiveAutoRuleWbsMapper;
 import org.springblade.manager.service.IArchiveAutoRuleWbsService;
@@ -43,259 +46,12 @@ public class ArchiveAutoRuleWbsServiceImpl extends BaseServiceImpl<ArchiveAutoRu
 
 	private ArchiveFileClient archiveFileClient;
 
+	private ArchiveTreeContractMapper archiveTreeContractMapper;
+
 	@Override
 	public IPage<ArchiveAutoRuleWbsVO> selectArchiveAutoRuleWbsPage(IPage<ArchiveAutoRuleWbsVO> page, ArchiveAutoRuleWbsVO archiveAutoRuleWbs) {
 		return page.setRecords(baseMapper.selectArchiveAutoRuleWbsPage(page, archiveAutoRuleWbs));
 	}
 
-	public void archiveAutoMethod(){
-		//步骤一:把项目下未锁定的案卷拆卷。
-		//步骤二:查询归档树节点。存在未归档文件的节点。
-		//步骤三:遍历归档树节点整理出 默认规则节点,分类并卷节点,单独组卷节点 三个集合。
-		//步骤四:按照单独,分类,默认的顺序执行组卷流程。
-	}
-
-
-	/**
-	 * 检查当前案卷的文件集合是否在规格内,能否开始组卷。
-	 * 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(List<ArchiveTreeContract> list){
-		//步骤1:遍历节点集合
-		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的)多个,案卷归属排序第一个节点。
-	 */
-	private void archiveAutoMethod2(List<ArchiveTreeContract> list){
-
-		//分类并卷集合<groupId,List<文件>>
-		Map<Long,List<ArchiveFile>> archiveMap = new HashMap<>();
-
-		//步骤1:遍历节点集合
-		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的第一个
-		}
-
-	}
-
-	/**
-	 * 默认组卷流程 文件可以跨节点组卷,受最高并卷节点限制范围,跨节点文件组卷时,案卷规格按照第一个文件所在的节点规格 组卷。
-	 */
-	private void archiveAutoMethod1(){
-		//步骤1:遍历节点集合
-		//步骤2:保存当前节点的最高并卷节点archiveAutoNodeId到变量A,用来限制向上级跨节点组卷。
-		//步骤3:判断变量A是否与当前节点archiveAutoNodeId相同,不同的话(相当于当前节点已跳出最高并卷节点)直接将内存中文件集合List中的文件组卷(这些是属于上一个最高并卷节点的文件),并清空list文件集合
-		//步骤4:获取当前节点的组卷规格
-		//步骤5:查询节点下的未归档文件
-		//步骤6:遍历未归档文件
-		//步骤7:判断文件是否存在分盒设置-》走分盒组卷流程
-		//步骤8:计算和判断文件集合list里是否达到组卷规格,达到创建案卷 并清空集合list。 跨节点文件组卷,案卷归属于当前list中第一个文件所在节点
-	}
 
 }

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

@@ -430,7 +430,7 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
     }
 
     /**
-     * 归档树节点规则设置保存(系统级)
+     * 归档树节点规则设置保存
      * @param archiveAutoType
      * @param nodeIds
      * @return
@@ -479,7 +479,7 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
     }
 
     /**
-     * 归档树wbs节点规则设置保存(系统级)
+     * 归档树wbs节点规则设置保存
      * @param archiveAutoType
      * @param nodeIds
      * @return
@@ -716,7 +716,7 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
                     String nodeAncestors = ancestorssplit[0]+","+ancestorssplit[1]+","+ancestorssplit[2]; //大类的ancestors
                     Long bigNodeID =Long.parseLong(ancestorssplit[2]); //大类节点ID
                     //获取大类下所有节点,过滤单独规则,其他分类并卷规则组节点
-                    List<ArchiveTreeAutoRuleVO> nodetree = ForestNodeMerger.merge(baseMapper.getAllSonNodeforGroupView(nodeAncestors, archiveTree.getArchiveAutoNodeId(),bigNodeID));
+                    List<ArchiveTreeAutoRuleVO> nodetree = ForestNodeMerger.merge(baseMapper.getAllSonNodeforGroupView(nodeAncestors, archiveTree.getArchiveAutoGroupId(),bigNodeID));
                     //获取与当前节点设置同一分类分组的节点
                     List<ArchiveTree> listGroup= baseMapper.selectList(Wrappers.<ArchiveTree>lambdaQuery()
                             .eq(ArchiveTree::getArchiveAutoGroupId, archiveTree.getArchiveAutoGroupId())
@@ -836,6 +836,8 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
                                             vo.setNodeId(vo2.getId());
                                             vo.setParentId(vo2.getParentId());
                                             vo.setNodeName(vo2.getTitle());
+                                            vo.setIswbsNode(true);
+                                            vo.setWbsNode2ArchiveTreeNodeId(wbsNode2ArchiveTreeNodeId);
                                             nodetree.add(vo);
                                         }
                                         //如有规则,需过滤不同组的分类规则节点
@@ -844,6 +846,8 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
                                             vo.setNodeId(vo2.getId());
                                             vo.setParentId(vo2.getParentId());
                                             vo.setNodeName(vo2.getTitle());
+                                            vo.setIswbsNode(true);
+                                            vo.setWbsNode2ArchiveTreeNodeId(wbsNode2ArchiveTreeNodeId);
                                             nodetree.add(vo);
                                         }
                                     }
@@ -853,6 +857,8 @@ public class ArchiveTreeServiceImpl extends BaseServiceImpl<ArchiveTreeMapper, A
                                     vo.setNodeId(vo2.getId());
                                     vo.setParentId(vo2.getParentId());
                                     vo.setNodeName(vo2.getTitle());
+                                    vo.setIswbsNode(true);
+                                    vo.setWbsNode2ArchiveTreeNodeId(wbsNode2ArchiveTreeNodeId);
                                     nodetree.add(vo);
                                 }
                             }

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

@@ -384,6 +384,7 @@ public class ExcelTabServiceImpl extends BaseServiceImpl<ExcelTabMapper, ExcelTa
             CurrentNode currentNode = new CurrentNode();
             currentNode.setPkId(wtc.getPKeyId());
             currentNode.setParentId(wtc.getParentId());
+            currentNode.setWbsId(Long.parseLong(wtc.getWbsId()));
             List<Long> ids = this.jdbcTemplate.queryForList("select id from m_wbs_tree where id in(" + wtc.getId() + "," + wtc.getOldId() + ")", Long.class);
             if (Func.isNotEmpty(ids)) {
                 Long id = ids.get(0);

+ 68 - 62
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java

@@ -132,7 +132,7 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
             nodes=wpService.chain(contractId,one.getRelateId(),primaryKeyId,null);
         }
         if(Func.isEmpty(nodes)){
-            this.tec.getLog().append("WBS信息缺失;");
+            this.tec.getLog().append("【WBS信息缺失】");
         }
         this.constantMap.put(CHAIN,nodes.stream().map(WbsTreeContract::getNodeName).collect(Collectors.toList()));
         /*节点参数*/
@@ -197,7 +197,7 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
 
         missingFill(missingList);
         if(Func.isNotEmpty(missingList)){
-            this.tec.getLog().append("无法识别的依赖:").append(missingList.stream().map(e->e.replaceAll("'","")).collect(Collectors.joining(",")));
+            this.tec.getLog().append("【没有能加载的跨节点数据:").append(missingList.stream().map(e->e.replaceAll("'","")).collect(Collectors.joining(","))).append("】");
         }
         if(Func.isNotEmpty(cki)){
            /*检验内容*/
@@ -228,7 +228,7 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
             this.constantMap.put(TEXT_INFO_MAP,tmap);
         }
         /*公式参数*/
-        FormulaOption formulaOption = this.formulaOptionService.getOne(Wrappers.<FormulaOption>lambdaQuery().eq(FormulaOption::getParentId,one.getId()).eq(FormulaOption::getContractId,contractId));
+        FormulaOption formulaOption = this.formulaOptionService.getOne(Wrappers.<FormulaOption>lambdaQuery().eq(FormulaOption::getParentId,one.getRelateId()).eq(FormulaOption::getContractId,contractId));
         if(formulaOption!=null){
            /*数据格式 {tablename:{keyxxx:{option:[1|0]}}}*/
            this.constantMap.put(FMOT,JSON.parseObject(formulaOption.getVal(),LinkedHashMap.class));
@@ -239,28 +239,30 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
     public void missingFill(List<String> missingList){
         /*数据池里面没有任何元素匹配和当前依赖匹配*/
         if(Func.isNotEmpty(missingList)){
-            StaticLog.info("缺失元素{}", String.join(";", missingList));
+            StaticLog.info("需要挂载的元素{}", String.join(";", missingList));
             Map<String, Object> elementInfoMap=this.getElementInfoByCodes(String.join(",",missingList));
             /*1从当前节点其它表格中查找匹配的元素*/
             List<String> removeList=new ArrayList<>();
-            for(String r:missingList){
-                String tn = r.substring(0,r.indexOf(StringPool.COLON));
-                String key =r.substring(r.indexOf(StringPool.COLON)+1);
-                List<AppWbsTreeContractVO> nodeList = this.tec.getTableAll().stream().filter(e->e.getInitTableName().equals(tn)).collect(Collectors.toList());
-                if(Func.isNotEmpty(nodeList)){
-                    removeList.add(r);
-                    Map<String,Object> elementInfo= (Map<String, Object>) elementInfoMap.get(r);
-                    String tableName = nodeList.get(0).getInitTableName();
-                    if(!this.tec.getCoordinateMap().containsKey(tableName)){
-                        this.tec.getCoordinateMap().put(tableName, CustomFunction.getElementCell(nodeList.get(0).getHtmlUrl()));
+            if(false) {//全加载后,关闭当前节的搜索,假如后期改成依赖加载可以再次利用
+                for (String r : missingList) {
+                    String tn = r.substring(0, r.indexOf(StringPool.COLON));
+                    String key = r.substring(r.indexOf(StringPool.COLON) + 1);
+                    List<AppWbsTreeContractVO> nodeList = this.tec.getTableAll().stream().filter(e -> e.getInitTableName().equals(tn)).collect(Collectors.toList());
+                    if (Func.isNotEmpty(nodeList)) {
+                        removeList.add(r);
+                        Map<String, Object> elementInfo = (Map<String, Object>) elementInfoMap.get(r);
+                        String tableName = nodeList.get(0).getInitTableName();
+                        if (!this.tec.getCoordinateMap().containsKey(tableName)) {
+                            this.tec.getCoordinateMap().put(tableName, CustomFunction.getElementCell(nodeList.get(0).getHtmlUrl()));
+                        }
+                        List<Map<String, Object>> tableDatas = this.jdbcTemplate.queryForList("select * from " + tableName + " where p_key_id in(" + nodeList.stream().map(AppWbsTreeContractVO::getPKeyId).map(StringUtils::handleNull).collect(Collectors.joining(",")) + ")");
+                        fill(tableDatas, removeList, tn, key, StringUtils.handleNull(elementInfo.get("ename")));
                     }
-                    List<Map<String,Object>> tableDatas= this.jdbcTemplate.queryForList("select * from "+tableName+" where p_key_id in("+nodeList.stream().map(AppWbsTreeContractVO::getPKeyId).map(StringUtils::handleNull).collect(Collectors.joining(","))+")");
-                    fill(tableDatas,removeList,tn,key,StringUtils.handleNull(elementInfo.get("ename")));
                 }
-            }
-            if(Func.isNotEmpty(removeList)){
-                /*移除已经找到的元素数据*/
-                missingList.removeIf(removeList::contains);
+                if (Func.isNotEmpty(removeList)) {
+                    /*移除已经找到的元素数据*/
+                    missingList.removeIf(removeList::contains);
+                }
             }
             if(Func.isNotEmpty(missingList)){
                 /*2从当前节点的兄弟节点中查找匹配的元素*/
@@ -306,12 +308,9 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
             this.tableDataMaps.put(tn,map);
             String values= StringUtils.handleNull(map.get(key));
             String r= tn+StringPool.COLON+key;
-            if(StringUtils.isNotEmpty(values)){
-                FormData tmp=createFormDataFast(name,r,values);
-                if(tmp!=null){
-                    //removeList.add(r);
-                    this.formDataMap.put(r,tmp);
-                }
+            FormData tmp=createFormDataFast(name,r,values);
+            if(tmp!=null){
+                this.formDataMap.put(r,tmp);
             }
         }
     }
@@ -319,40 +318,44 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
         if(StringUtils.isNotEmpty(code,name)){
             String[] arr=code.split(":");
             String coords = tec.getCoordinateMap().get(arr[0]).get(arr[1]);
-            List<Coords> coordsList = Stream.of(coords).flatMap(s -> Arrays.stream(s.split(";"))).map(s -> {
-                String[] xy = s.split("_");
-                return new Coords(xy[1], xy[0]);
-            }).collect(Collectors.toList());
-            List<ElementData> eds = new ArrayList<>();
-            if(StringUtils.isNotEmpty(values)){
-                String[] pages=values.split(";;");
-                for(int index=0;index<pages.length;index++){
-                    String pg=pages[index];
-                    if(Func.isNotBlank(pg)){
-                        String[] val = pg.split("☆");
-                        Map<String,Object> tmpMap = new LinkedHashMap<>();
-                        for(String s:val){
-                            String[] t = s.split("_\\^_");
-                            String[] c =t[1].split("_");
-                            tmpMap.put(StringUtils.join(code,0,index,Func.toInt(c[1]),Func.toInt(c[0]),StringPool.AT),t[0]);
-                        }
-                        for(Coords c:coordsList){
-                            Object data = null;
-                            String key =StringUtils.join(code,0,index,c.getX(),c.getY(),StringPool.AT);
-                            if(tmpMap.containsKey(key)){
-                                data =  tmpMap.get(key);
+            if(StringUtils.isNotEmpty(coords)) {
+                /*定位信息存在才合法*/
+                List<Coords> coordsList = Stream.of(coords).flatMap(s -> Arrays.stream(s.split(";"))).map(s -> {
+                    String[] xy = s.split("_");
+                    return new Coords(xy[1], xy[0]);
+                }).collect(Collectors.toList());
+                List<ElementData> eds = new ArrayList<>();
+                if (StringUtils.isNotEmpty(values)) {
+                    String[] pages = values.split(";;");
+                    for (int index = 0; index < pages.length; index++) {
+                        String pg = pages[index];
+                        if (Func.isNotBlank(pg)) {
+                            String[] val = pg.split("☆");
+                            Map<String, Object> tmpMap = new LinkedHashMap<>();
+                            for (String s : val) {
+                                String[] t = s.split("_\\^_");
+                                String[] c = t[1].split("_");
+                                tmpMap.put(StringUtils.join(code, 0, index, Func.toInt(c[1]), Func.toInt(c[0]), StringPool.AT), t[0]);
+                            }
+                            for (Coords c : coordsList) {
+                                Object data = null;
+                                String key = StringUtils.join(code, 0, index, c.getX(), c.getY(), StringPool.AT);
+                                if (tmpMap.containsKey(key)) {
+                                    data = tmpMap.get(key);
+                                }
+                                eds.add(new ElementData(index, 0, data, c.getX(), c.getY()));
                             }
-                            eds.add(new ElementData(index,0,data,c.getX(),c.getY()));
                         }
                     }
-                }
 
-            }else{
-                eds =coordsList.stream().map(c->new ElementData(0,0,null,c.getX(),c.getY())).collect(Collectors.toList());
+                } else {
+                    eds = coordsList.stream().map(c -> new ElementData(0, 0, null, c.getX(), c.getY())).collect(Collectors.toList());
+                }
+                FormData one = new FormData(code, eds, null, coords);
+                one.setEName(name);
+                return one;
             }
-            FormData one=   new FormData(code,eds, null,coords);
-            one.setEName(name);
-            return one;
+            this.tec.getLog().append("【").append(name).append(code).append("定位信息不存在】");
         }
         return null;
     }
@@ -389,7 +392,7 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                 logMap.put(p.getK(),p.getName());
             }
         }
-        this.tec.getLog().append("本节点参数情况:").append(result.entrySet().stream().map(p->logMap.get(p.getKey())+":"+p.getValue()).collect(Collectors.joining(";")));
+        this.tec.getLog().append("本节点参数情况:").append(result.entrySet().stream().map(p->logMap.get(p.getKey())+":"+p.getValue()).collect(Collectors.joining(";"))).append("】");
         /*元素动态绑定*/
         this.formDataMap.values().stream().filter(e->e.getIsCurrentNodeElement()&&e.getFormula()==null).forEach(e->{
             /*执行列表里不存在,且元素的名称和节点参数名称匹配成功*/
@@ -481,7 +484,7 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                     formulaStrategyFactory.get(fd).forEach(e -> e.execute(tec));
                 }
             }catch (Exception e){
-                tec.getLog().append("特殊公式:").append(fd.getEName()).append(fd.getFormula().getNumber()).append("执行异常");
+                tec.getLog().append("特殊公式:").append(fd.getEName()).append(fd.getFormula().getNumber()).append("执行异常");
                 e.printStackTrace();
             }
         }
@@ -510,7 +513,7 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                                 }
                             });
                             if(ele.size()<relyList.size()){
-                                this.tec.getLog().append(fd.getEName()).append(fd.getFormula().getFormula().replaceAll("'", "")).append("不满足执行依赖");
+                                this.tec.getLog().append("【").append(fd.getEName()).append(fd.getFormula().getFormula().replaceAll("'", "")).append("不满足执行依赖");
                             }
                             if(fd.getCoordsList().size()>1&&f.split("[/+\\-*]").length>1){
                                 LinkedHashMap<String,FormData> fdMap =new LinkedHashMap<>();
@@ -562,7 +565,7 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                             write(fd,data);
                         }
                     }catch (Exception e){
-                        tec.getLog().append(fd.getEName()).append("计算错误; ");
+                        tec.getLog().append("【").append(fd.getEName()).append("计算错误】 ");
                     }
 
                 }
@@ -597,11 +600,14 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                         } else {
                             this.wbsTreePrivateService.addWbsTreeContractInfo(this.tec.getCurrentNode().getPkId().toString(), sub.getPKeyId().toString(), tec.getContractId());
                             AppWbsTreeContractVO one = this.tec.getTableAll().get(0);
-                            WbsTreeContract wtc = this.wbsTreeContractService.getOne(Wrappers.<WbsTreeContract>lambdaQuery().eq(WbsTreeContract::getParentId, one.getParentId()).eq(WbsTreeContract::getWbsId, one.getWbsId()).and(e->e.eq(WbsTreeContract::getNodeName, pd?"质量检验评定表(附表)":"质量检验表(附表)").or().eq(WbsTreeContract::getFullName, pd?"质量检验评定表(附表)":"质量检验表(附表)")));
+                            WbsTreeContract wtc = this.wbsTreeContractService.getOne(Wrappers.<WbsTreeContract>lambdaQuery().eq(WbsTreeContract::getParentId, one.getParentId()).eq(WbsTreeContract::getContractId,one.getContractId()).eq(WbsTreeContract::getWbsId, one.getWbsId()).and(e->e.eq(WbsTreeContract::getNodeName, pd?"质量检验评定表(附表)":"质量检验表(附表)").or().eq(WbsTreeContract::getFullName, pd?"质量检验评定表(附表)":"质量检验表(附表)")));
                             if (wtc != null) {
                                 /*附表的顺序在检验单或者评定表之后*/
                                 int sort=this.tec.getTableAll().stream().filter(e -> e.getNodeName().contains("检验单") || e.getNodeName().contains("评定表")).map(AppWbsTreeContractVO::getSort).max(Integer::compareTo).orElse(30);
-                                this.wbsTreeContractService.update(Wrappers.<WbsTreeContract>lambdaUpdate().set(WbsTreeContract::getSort,++sort).eq(WbsTreeContract::getPKeyId,wtc.getPKeyId()));
+                                this.wbsTreeContractService.update(Wrappers.<WbsTreeContract>lambdaUpdate()
+                                        .set(WbsTreeContract::getSort,sort).set(WbsTreeContract::getContractType,-1).set(WbsTreeContract::getAncestors,one.getAncestors())
+                                        .set(WbsTreeContract::getIsCopeTab,2)
+                                        .eq(WbsTreeContract::getPKeyId,wtc.getPKeyId()));
                                 /*只需要挂载一张*/
                                 AppWbsTreeContractVO obj = BeanUtil.copy(wtc, AppWbsTreeContractVO.class);
                                 this.tec.getTableAll().add(obj);
@@ -685,7 +691,7 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                     }
                 }
             } catch (Exception e) {
-                this.tec.getLog().append("|=|").append("附表异常").append("|=|");
+                this.tec.getLog().append("【").append("附表异常").append("】");
                 e.printStackTrace();
             }
         }

+ 8 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/TrialClassificationConfigurationServiceImpl.java

@@ -7,6 +7,7 @@ import org.springblade.core.mp.base.BaseServiceImpl;
 import org.springblade.core.tool.constant.BladeConstant;
 import org.springblade.core.tool.node.ForestNodeMerger;
 import org.springblade.core.tool.utils.Func;
+import org.springblade.core.tool.utils.ObjectUtil;
 import org.springblade.core.tool.utils.StringPool;
 import org.springblade.manager.entity.TrialClassificationConfiguration;
 import org.springblade.manager.mapper.TrialClassificationConfigurationMapper;
@@ -33,6 +34,13 @@ public class TrialClassificationConfigurationServiceImpl
 
     @Override
     public boolean submit(TrialClassificationConfiguration obj) {
+        if (ObjectUtil.isNotEmpty(obj.getId())) {
+            //修改
+            TrialClassificationConfiguration trialObj = baseMapper.selectById(obj.getId());
+            if (ObjectUtil.isNotEmpty(obj.getContractId()) && ObjectUtil.isEmpty(trialObj.getContractId())) {
+                throw new ServiceException("公共节点无法修改,请联系管理员");
+            }
+        }
         if (Func.isEmpty(obj.getParentId())) {
             obj.setParentId(BladeConstant.TOP_PARENT_ID);
             obj.setAncestors(String.valueOf(BladeConstant.TOP_PARENT_ID));

+ 28 - 33
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/WbsTreePrivateServiceImpl.java

@@ -290,56 +290,51 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
     }
 
     @Override
-    @Transactional(rollbackFor = Exception.class)
     public boolean updateBatchByPid(List<WbsTreePrivateDTO3> wbsTreePrivates) {
         try {
             //修改当前私有项目元素表基础信息
             wbsTreePrivates.forEach(list -> {
-                baseMapper.updateBatchByPid(list);
+                this.update(Wrappers.<WbsTreePrivate>lambdaUpdate()
+                        .set(WbsTreePrivate::getNodeName, list.getNodeName())
+                        .set(WbsTreePrivate::getFullName, list.getNodeName())
+                        .set(WbsTreePrivate::getTableType, list.getTableType())
+                        .set(WbsTreePrivate::getTableOwner, list.getTableOwner())
+                        .set(WbsTreePrivate::getFillRate, list.getFillRate())
+                        .eq(WbsTreePrivate::getPKeyId, list.getPKeyId())
+                );
             });
 
+            //获取最新项目表信息
+            List<Long> pKeyIds = wbsTreePrivates.stream().map(WbsTreePrivateDTO3::getPKeyId).collect(Collectors.toList());
+            List<WbsTreePrivate> wbsTreePrivateNew = baseMapper.selectList(Wrappers.<WbsTreePrivate>lambdaQuery()
+                    .select(WbsTreePrivate::getNodeName, WbsTreePrivate::getTableType, WbsTreePrivate::getTableOwner, WbsTreePrivate::getId, WbsTreePrivate::getSort, WbsTreePrivate::getProjectId)
+                    .in(WbsTreePrivate::getPKeyId, pKeyIds));
+            String projectId = wbsTreePrivateNew.stream().map(WbsTreePrivate::getProjectId).findAny().orElse(null);
+
             //修改当前项目下所有合同段中的元素表基础信息
-            String projectId = "";
-            String parentId = "";
-            List<WbsTreePrivate> wbsTreePrivateList = new ArrayList<>();
-            int number = 0;
-            for (WbsTreePrivateDTO3 wbsTreePrivate : wbsTreePrivates) {
-                WbsTreePrivate wbsTreePrivate1 = baseMapper.selectOne(Wrappers.<WbsTreePrivate>query().lambda().eq(WbsTreePrivate::getPKeyId, wbsTreePrivate.getPKeyId()));
-                wbsTreePrivateList.add(wbsTreePrivate1);
-                if (number == 0) {
-                    projectId = wbsTreePrivate1.getProjectId();
-                    parentId = String.valueOf(wbsTreePrivate1.getParentId());
-                    number = 1;
-                }
-            }
-            if (StringUtils.isNotEmpty(projectId) && StringUtils.isNotEmpty(parentId) && wbsTreePrivateList.size() > 0) {
+            if (StringUtils.isNotEmpty(projectId) && wbsTreePrivateNew.size() > 0) {
                 //获取所有合同段ids
-                List<ContractInfo> contractInfos = contractInfoMapper.selectList(Wrappers.<ContractInfo>query().lambda().eq(ContractInfo::getPId, projectId));
-                if (contractInfos.size() > 0) {
-                    List<Long> contractInfoIds = contractInfos.stream().map(ContractInfo::getId).collect(Collectors.toList());
-                    for (Long contractInfoId : contractInfoIds) {
-                        for (WbsTreePrivate wbsTreePrivate : wbsTreePrivateList) {
+                List<Long> contractInfoIds = contractInfoMapper.selectList(Wrappers.<ContractInfo>lambdaQuery().select(ContractInfo::getId).eq(ContractInfo::getPId, projectId)).stream().map(ContractInfo::getId).collect(Collectors.toList());
+                if (contractInfoIds.size() > 0) {
+                    for (Long contractId : contractInfoIds) {
+                        for (WbsTreePrivate wbsTreePrivate : wbsTreePrivateNew) {
                             //判断当前合同段是否存在该元素表、以及该元素表父级节点(包括新增、复制节点)
-                            List<WbsTreeContract> wbsTreeContract = wbsTreeContractMapper.selectList(Wrappers.<WbsTreeContract>query().lambda()
-                                    .eq(WbsTreeContract::getContractId, contractInfoId)
-                                    .eq(WbsTreeContract::getProjectId, wbsTreePrivate.getProjectId())
+                            long row = wbsTreeContractMapper.selectCount(Wrappers.<WbsTreeContract>lambdaQuery()
                                     .eq(WbsTreeContract::getStatus, 1)
-                                    .eq(WbsTreeContract::getId, wbsTreePrivate.getId())
-                                    .or()
-                                    .eq(WbsTreeContract::getParentId, wbsTreePrivate.getId())
-                                    .or()
-                                    .eq(WbsTreeContract::getOldId, wbsTreePrivate.getId())
+                                    .eq(WbsTreeContract::getContractId, contractId)
+                                    .eq(WbsTreeContract::getProjectId, projectId)
+                                    .and(obj -> obj.eq(WbsTreeContract::getId, wbsTreePrivate.getId()).or().eq(WbsTreeContract::getParentId, wbsTreePrivate.getId()).or().eq(WbsTreeContract::getOldId, wbsTreePrivate.getId()))
                             );
                             //修改原始、复制、新增节点下的元素表
-                            if (wbsTreeContract.size() > 0) {
-                                wbsTreeContractMapper.updateContractTablesInfo(contractInfoId, wbsTreePrivate);
+                            if (row > 0) {
+                                wbsTreeContractMapper.updateContractTablesInfo(contractId, wbsTreePrivate);
                             }
                         }
                     }
                 }
             }
         } catch (Exception e) {
-            throw new ServiceException("修改同步到合同段时异常 " + e.getMessage());
+            throw new ServiceException("修改同步到合同段时异常" + e.getMessage());
         }
         return true;
     }
@@ -1799,7 +1794,7 @@ public class WbsTreePrivateServiceImpl extends BaseServiceImpl<WbsTreePrivateMap
             tableOwnerList = Func.toStrList(tableOwners);
         }
 
-        return baseMapper.selectWbsTreeTrialTabList(roleAndTabOwners, tableType, wbsTreePrivate.getProjectId(), wbsTreePrivate.getWbsId(), wbsTreePrivate.getId(), tableOwnerList,contractId);
+        return baseMapper.selectWbsTreeTrialTabList(roleAndTabOwners, tableType, wbsTreePrivate.getProjectId(), wbsTreePrivate.getWbsId(), wbsTreePrivate.getId(), tableOwnerList, contractId);
     }
 
     @Override

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

@@ -847,6 +847,7 @@ public class WbsTreeServiceImpl extends BaseServiceImpl<WbsTreeMapper, WbsTree>
     }
 
     //新增独立表单库数据
+    @Async
     private void insertDLTabAsync(WbsTreeContractDTO pawDTO) {
         //获取当前引用项目的独立表
         List<WbsTreePrivate> wbsTreePrivates = wbsTreePrivateService.getBaseMapper().selectList(Wrappers.<WbsTreePrivate>lambdaQuery()