Browse Source

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

# Conflicts:
#	blade-service/blade-business/src/main/java/org/springblade/business/controller/TaskController.java
LHB 2 months ago
parent
commit
dd2cd497e6

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

@@ -27,6 +27,9 @@ public interface ArchiveTreeContractClient {
     @PostMapping(API_PREFIX + "/getHavedFileNodeByProjectID")
     List<ArchiveTreeContract> getHavedFileNodeByProjectID(@RequestParam Long projectId);
 
+    @PostMapping(API_PREFIX + "/getTopAutoTypeNodeByProjectID")
+    List<ArchiveTreeContract> getTopAutoTypeNodeByProjectID(@RequestParam Long projectId);
+
     /**
      * 根据项目id获取所有数据
      */

+ 275 - 3
blade-service/blade-archive/src/main/java/org/springblade/archive/service/impl/ArchivesAutoServiceImpl.java

@@ -729,6 +729,8 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		//步list = {ArrayList@18238}  size = 19骤二:查询归档树节点。存在未归档文件的节点。
 		List<ArchiveTreeContract> list = archiveTreeContractClient.getHavedFileNodeByProjectID(projectId);
 
+		List<ArchiveTreeContract> listTop = archiveTreeContractClient.getTopAutoTypeNodeByProjectID(projectId);
+
 
 		if (nodeId != null) {
 			ArchiveTreeContract node = archiveTreeContractClient.getArchiveTreeContractById(nodeId);
@@ -772,7 +774,7 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		archiveAutoMethod3(list3, boxMap, boxFileMap, traceId);//单独组卷
 		//设置完成度30%
 		projectClient.updateIsArchivesAutoById(projectId, 30);
-		archiveAutoMethod2(list2, projectId, boxMap, boxFileMap, traceId);//分类组卷
+		archiveAutoMethod2_new(list2, listTop,projectId, boxMap, boxFileMap, traceId);//分类组卷
 		//设置完成度50%
 		projectClient.updateIsArchivesAutoById(projectId, 50);
 		archiveAutoMethod1(list1, boxMap, boxFileMap, traceId);//默认组卷
@@ -1523,13 +1525,117 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 		}
 	}
 
+	private void archiveAutoMethod3(List<ArchiveTreeContract> list, Map<String, List<ArchiveFile>> boxMap,
+									Map<Long, String> boxFileMap, Long traceId) {
+		// 步骤1:遍历节点集合
+		for (ArchiveTreeContract node : list) {
+			// 步骤2:获取当前节点的案卷规格
+			String specificationStr = node.getSpecification();
+			if (StringUtils.isEmpty(specificationStr)) {
+				specificationStr = "30";
+			}
+			int specification = Integer.parseInt(specificationStr);
+			int specificationSize = specification * 10;
+
+			// 步骤3:查询节点下的未组卷文件
+			List<ArchiveFile> archiveFiles = archiveFileClient.getListByNodeID(node.getId().toString());
+			if (archiveFiles == null || archiveFiles.isEmpty()) {
+				continue;
+			}
+
+			// 记录节点文件数量日志
+			String completeMsg = "[自动组卷] 单独组卷:" + "-traceId:" + traceId + "节点:" + node.getNodeName() + " 文件数量:" + archiveFiles.size();
+			iTraceLogService.saveLog(traceId, completeMsg);
+
+			// 步骤4:遍历未归档文件
+			List<ArchiveFile> waitArchiveFiles = new ArrayList<>();  // 待组卷文件集合
+			int archivesSize = 0;  // 待组卷文件总页数
+			int archiveFilesSize = 0;
+
+			for (ArchiveFile file : archiveFiles) {
+				archiveFilesSize++;
+
+				// 步骤5:判断文件是否存在分盒设置
+				if (file.getBoxNumber() != null && file.getBoxNumber() != -1) {
+					// 添加到分盒文件集合
+					addBoxMap(file, boxMap, boxFileMap);
+
+					// 如果是最后一个文件且有待组卷文件,则组卷
+					if (archiveFilesSize == archiveFiles.size() && !waitArchiveFiles.isEmpty()) {
+						createArchive3(waitArchiveFiles, node, archivesSize);
+						waitArchiveFiles.clear();
+						archivesSize = 0;
+					}
+				} else {
+					// 非分盒文件处理
+					Integer filePage = file.getFilePage() != null ? file.getFilePage() : 0;
+
+					// 步骤6:检查规格状态
+					int tempTotalSize = archivesSize + filePage;
+					int checkStatus = checkSpecificationSize(specificationSize, tempTotalSize);
+
+					// 6.1 未到规格
+					if (checkStatus == 0) {
+						waitArchiveFiles.add(file);
+						archivesSize = tempTotalSize;
+
+						// 最后一个文件直接组卷
+						if (archiveFilesSize == archiveFiles.size()) {
+							createArchive3(waitArchiveFiles, node, archivesSize);
+							waitArchiveFiles.clear();
+							archivesSize = 0;
+						}
+					}
+					// 6.2 达到规格
+					else if (checkStatus == 1) {
+						waitArchiveFiles.add(file);
+						archivesSize = tempTotalSize;
+						createArchive3(waitArchiveFiles, node, archivesSize);
+
+						// 重置待组卷集合
+						waitArchiveFiles.clear();
+						archivesSize = 0;
+					}
+					// 6.3 超出规格
+					else if (checkStatus == -1) {
+						if (!waitArchiveFiles.isEmpty()) {
+							// 先将现有集合组卷(不含当前文件)
+							createArchive3(waitArchiveFiles, node, archivesSize);
+
+							// 新建集合存放当前文件
+							waitArchiveFiles.clear();
+							waitArchiveFiles.add(file);
+							archivesSize = filePage;
+
+							// 最后一个文件直接组卷
+							if (archiveFilesSize == archiveFiles.size()) {
+								createArchive3(waitArchiveFiles, node, archivesSize);
+								waitArchiveFiles.clear();
+								archivesSize = 0;
+							}
+						} else {
+							// 当前文件单独成卷
+							waitArchiveFiles.add(file);
+							archivesSize = filePage;
+							createArchive3(waitArchiveFiles, node, archivesSize);
+
+							// 重置集合
+							waitArchiveFiles.clear();
+							archivesSize = 0;
+						}
+					}
+				}
+			}
+		}
+	}
+
 	/**
 	 * 单租组卷流程  20230628 SBD又说单独组卷规则节点下只组一卷,不用满规格新组。
 	 *
 	 * @param list
 	 * @param boxMap
 	 */
-	private void archiveAutoMethod3(List<ArchiveTreeContract> list, Map<String, List<ArchiveFile>> boxMap, Map<Long, String> boxFileMap, Long traceId) {
+	private void archiveAutoMethod3_1(List<ArchiveTreeContract> list, Map<String, List<ArchiveFile>> boxMap, Map<Long, String> boxFileMap, Long traceId) {
 		//步骤1:遍历节点集合
 		for (ArchiveTreeContract node : list) {
 			//步骤2:查询节点下的未组卷文件
@@ -1623,11 +1729,177 @@ public class ArchivesAutoServiceImpl extends BaseServiceImpl<ArchivesAutoMapper,
 			Long archiveAutoGroupId = entry.getKey();
 			List<ArchiveFile> archiveFiles = entry.getValue();
 			//一个archiveAutoGroupId组成一个案卷  案卷归属同个key的归档树节点select=1的第一个groupId2NodeIdMap
-			createArchive2(archiveFiles, archiveAutoGroupId, projectId);
+			//createArchive2(archiveFiles, archiveAutoGroupId, projectId);
+
+			archiveAutoMethodGroup(archiveFiles, archiveAutoGroupId, projectId);
 		}
 
 	}
 
+
+	private void archiveAutoMethod2_new(List<ArchiveTreeContract> list, List<ArchiveTreeContract> topList, Long projectId,
+										Map<String, List<ArchiveFile>> boxMap, Map<Long, String> boxFileMap, Long traceId) {
+
+		// 分类并卷集合<groupId, List<文件>>
+		Map<Long, List<ArchiveFile>> archiveMap = new LinkedHashMap<>();
+		// 记录同个分组id对应的第一个节点ID(案卷归属节点)
+		Map<Long, Long> groupId2NodeIdMap = new HashMap<>();
+
+		// 当前处理的顶层节点ID
+		Long curTopId = null;
+		// 当前顶层节点对应的分组ID
+		Long currArchiveAutoGroupId = null;
+
+		// 步骤1:遍历节点集合
+		for (ArchiveTreeContract node : list) {
+			// 初始化当前节点的分组ID和顶层节点ID
+			Long archiveAutoGroupId = node.getArchiveAutoGroupId();
+			Long nodeTopId = 0L;
+
+			// 步骤2:查找当前节点的顶层节点ID
+			for (ArchiveTreeContract topNode : topList) {
+				Long topId = topNode.getId();
+				// 检查当前节点是否属于此顶层节点
+				if (node.getAncestors() != null &&
+						node.getAncestors().contains(topId.toString())) {
+					nodeTopId = topId;
+					break;
+				}
+			}
+
+			// 步骤3:确定当前节点的分组ID
+			if (curTopId != null && curTopId.equals(nodeTopId) && nodeTopId != 0) {
+				// 如果属于同一个非零顶层节点,使用之前的分组ID
+				archiveAutoGroupId = currArchiveAutoGroupId;
+			} else {
+				// 新顶层节点或没有顶层节点,更新当前分组信息
+				curTopId = nodeTopId;
+				currArchiveAutoGroupId = archiveAutoGroupId;
+			}
+
+			// 步骤4:查询节点下的未归档文件
+			List<ArchiveFile> archiveFiles = archiveFileClient.getListByNodeID(node.getId().toString());
+
+			if (archiveFiles != null && !archiveFiles.isEmpty()) {
+				// 记录日志(每个节点只记录一次)
+				String completeMsg = "[自动组卷] 分类组卷:" + "-traceId:" + traceId + "节点:" + node.getNodeName() + " 文件数量:" + archiveFiles.size();
+				iTraceLogService.saveLog(traceId, completeMsg);
+
+				// 步骤5:遍历未归档文件
+				for (ArchiveFile file : archiveFiles) {
+					// 步骤6:判断文件是否存在分盒设置
+					if (file.getBoxNumber() != null && file.getBoxNumber() != -1) {
+						// 添加到分盒文件集合
+						addBoxMap(file, boxMap, boxFileMap);
+					} else {
+						// 分类并卷流程
+						// 步骤7:将文件按照<groupId,List<文件>>放入集合
+						if (archiveMap.containsKey(archiveAutoGroupId)) {
+							List<ArchiveFile> groupList = archiveMap.get(archiveAutoGroupId);
+							groupList.add(file);
+						} else {
+							List<ArchiveFile> groupList = new ArrayList<>();
+							groupList.add(file);
+							archiveMap.put(archiveAutoGroupId, groupList);
+							groupId2NodeIdMap.put(archiveAutoGroupId, node.getId());
+						}
+					}
+				}
+			}
+		}
+
+		// 步骤8:按集合创建案卷
+		for (Map.Entry<Long, List<ArchiveFile>> entry : archiveMap.entrySet()) {
+			Long archiveAutoGroupId = entry.getKey();
+			List<ArchiveFile> archiveFiles = entry.getValue();
+
+			// 同一个分组ID下的文件分组组卷
+			archiveAutoMethodGroup(archiveFiles, archiveAutoGroupId, projectId);
+		}
+	}
+
+	private void archiveAutoMethodGroup(List<ArchiveFile> archiveFiles, Long archiveAutoGroupId, Long projectId) {
+		if (archiveFiles.size()==0) {
+			return;
+		}
+
+		// 获取分组规格(取第一个文件的节点规格作为分组规格)
+		int specificationSize = 300; // 默认规格(300页)
+		if (archiveFiles.get(0).getNodeId() != null) {
+			// 查询文件所在节点的规格
+			Long nodeId = Long.parseLong(archiveFiles.get(0).getNodeId());
+			ArchiveTreeContract node = archiveTreeContractClient.getArchiveTreeContractById(nodeId);
+			//ArchiveTreeContract node = archiveTreeClient.getNodeById(archiveFiles.get(0).getNodeId());
+			if (node != null && !StringUtils.isEmpty(node.getSpecification())) {
+				try {
+					specificationSize = Integer.parseInt(node.getSpecification()) * 10;
+				} catch (NumberFormatException e) {
+					// 规格格式错误时使用默认值
+					log.error("规格格式错误: {}", node.getSpecification(), e);
+				}
+			}
+		}
+
+		// 待组卷文件集合
+		List<ArchiveFile> waitArchiveFiles = new ArrayList<>();
+		// 待组卷文件总页数
+		int archivesSize = 0;
+
+		// 遍历文件列表
+		int fileIndex = 0;
+		int totalFiles = archiveFiles.size();
+
+		for (ArchiveFile file : archiveFiles) {
+			fileIndex++;
+			// 获取文件页数,处理null值
+			int filePage = file.getFilePage() != null ? file.getFilePage() : 0;
+
+			// 计算临时总页数
+			int tempTotalSize = archivesSize + filePage;
+
+			// 检查规格状态
+			int checkStatus = checkSpecificationSize(specificationSize, tempTotalSize);
+
+			// 处理不同检查状态
+			switch (checkStatus) {
+				case 0: // 未到规格
+					waitArchiveFiles.add(file);
+					archivesSize = tempTotalSize;
+					if (fileIndex == totalFiles) { // 是最后一个文件
+						createArchive2(waitArchiveFiles, archiveAutoGroupId, projectId);
+					}
+					break;
+
+				case 1: // 达到规格
+					waitArchiveFiles.add(file);
+					createArchive2(waitArchiveFiles, archiveAutoGroupId, projectId);
+					waitArchiveFiles = new ArrayList<>();
+					archivesSize = 0;
+					break;
+
+				case -1: // 超出规格
+					if (waitArchiveFiles.isEmpty()) {
+						// 当前文件单独成卷
+						createArchive2(Collections.singletonList(file), archiveAutoGroupId, projectId);
+					} else {
+						// 先将现有文件组卷
+						createArchive2(waitArchiveFiles, archiveAutoGroupId, projectId);
+
+						// 创建新的待组卷集合
+						waitArchiveFiles = new ArrayList<>();
+						waitArchiveFiles.add(file);
+						archivesSize = filePage;
+
+						if (fileIndex == totalFiles) { // 是最后一个文件
+							createArchive2(waitArchiveFiles, archiveAutoGroupId, projectId);
+						}
+					}
+					break;
+			}
+		}
+	}
+
+
 	/**
 	 * 默认组卷流程 文件可以跨节点组卷,受最高并卷节点限制范围,跨节点文件组卷时,案卷规格按照第一个文件所在的节点规格 组卷。
 	 */

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

@@ -1242,7 +1242,7 @@ public class TaskController extends BladeController {
         List<TaskApprovalVO> taskApprovalVOS = new ArrayList<>();
         taskApprovalVOS.add(taskApprovalVO);
         Task task = taskService.getOne(Wrappers.<Task>lambdaQuery().eq(Task::getId, taskApprovalVO.getTaskId()));
-        if (task.getStatus() != null && task.getStatus() == 3) {
+        if (task == null || (task.getStatus() != null && task.getStatus() == 3)) {
             return R.fail("任务已被撤回或者驳回");
         }
         this.taskService.batchCompleteApprovalTask(taskApprovalVOS);

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

@@ -166,6 +166,10 @@ public class ArchiveTreeContractImpl implements ArchiveTreeContractClient {
         archiveTreeContractService.addArchiveTreeContract(archiveTreeContracts,rootId);
     }
 
+    @Override
+    public List<ArchiveTreeContract> getTopAutoTypeNodeByProjectID(@RequestParam Long projectId){
+        return archiveTreeContractMapper.getTopAutoTypeNodeByProjectID(projectId);
+    }
 
 
 }

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

@@ -84,6 +84,8 @@ public interface ArchiveTreeContractMapper extends BaseMapper<ArchiveTreeContrac
 
     List<ArchiveTreeContract> getListByProjectId(@Param("projectId") Long projectId);
 
+    List<ArchiveTreeContract> getTopAutoTypeNodeByProjectID(@Param("projectId") Long projectId);
+
     List<ArchiveTreeContract> getStorageNodeByGroupId(@Param("projectId") Long projectId, @Param("archiveAutoGroupId") Long archiveAutoGroupId);
 
     @MapKey("id")

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

@@ -357,6 +357,20 @@
         order by ancestors asc,tree_sort asc
     </select>
 
+
+    <select id="getTopAutoTypeNodeByProjectID" resultMap="archiveTreeContractResultMap">
+        SELECT
+            *
+        FROM
+            m_archive_tree_contract
+        WHERE
+            1 = 1
+          AND project_id = #{projectId}
+          AND is_deleted = 0
+          AND archive_auto_type = 1
+        order by ancestors asc,tree_sort asc
+    </select>
+
     <select id="getHavedBoxFileNodeByProjectID" resultMap="archiveTreeContractResultMap">
         SELECT
             *