From aac756e5fa0de41a99d332349aa0ad36e9bfcb95 Mon Sep 17 00:00:00 2001 From: lilin Date: Tue, 6 Jan 2026 16:56:10 +0800 Subject: [PATCH] =?UTF-8?q?=E6=AF=8F=E6=AC=A1=E6=89=B9=E9=87=8F=E6=96=B0?= =?UTF-8?q?=E5=A2=9E1000=E8=A1=8C=EF=BC=8C=E9=81=87=E5=88=B0=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E5=88=A0=E9=99=A4=E8=A1=A8=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/TsNodesServiceImpl.java | 227 +++++++++++++++--- 1 file changed, 190 insertions(+), 37 deletions(-) diff --git a/java/src/main/java/com/yfd/platform/modules/experimentalData/service/impl/TsNodesServiceImpl.java b/java/src/main/java/com/yfd/platform/modules/experimentalData/service/impl/TsNodesServiceImpl.java index 126b4ce..c7b163f 100644 --- a/java/src/main/java/com/yfd/platform/modules/experimentalData/service/impl/TsNodesServiceImpl.java +++ b/java/src/main/java/com/yfd/platform/modules/experimentalData/service/impl/TsNodesServiceImpl.java @@ -38,6 +38,7 @@ import com.yfd.platform.system.domain.LoginUser; import com.yfd.platform.utils.StringUtils; import com.yfd.platform.utils.TableNameContextHolder; import io.netty.channel.ChannelInboundHandlerAdapter; +import lombok.val; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -46,6 +47,7 @@ import org.springframework.scheduling.annotation.Async; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; @@ -70,6 +72,8 @@ public class TsNodesServiceImpl extends ServiceImpl impl private static final Logger LOGGER = LoggerFactory.getLogger(ChannelInboundHandlerAdapter.class); + private static final int BATCH_SIZE = 1000; + //试验任务节点表 Mapper @Resource private TsNodesMapper tsNodesMapper; @@ -109,53 +113,178 @@ public class TsNodesServiceImpl extends ServiceImpl impl @Override public List> getTsNodesTree(String nodeName, String taskId) { - TsTask tsTask = tsTaskMapper.selectOne(new QueryWrapper().eq("id", taskId)); - // 查询所有节点数据 + List> result = new ArrayList<>(); + + // 查询所有节点数据(如果taskId为空,查询所有任务节点) List> allNodes = getAllNodes(taskId); - // 查找所有根节点(parentId为"00"的节点) - List> rootNodes = findRootNodes(allNodes, taskId); - - // 根节点的基本路径:/项目名称/ - String basePath = "/" + tsTask.getTaskName() + "/"; - - // 存储最终结果 - List> result = new ArrayList<>(); - Map rootNodeData = new HashMap<>(); - rootNodeData.put("nodeName", "根节点"); - rootNodeData.put("path", "/"+tsTask.getTaskName()+"/"); - rootNodeData.put("nodeId", tsTask.getId()); - rootNodeData.put("nodeOrder", "0"); - rootNodeData.put("taskId", tsTask.getId()); - rootNodeData.put("parentId", "00"); - result.add(rootNodeData); - - // 如果 nodeName 为空,返回所有根节点的完整树形结构 - if (StringUtils.isEmpty(nodeName)) { - if (!rootNodes.isEmpty()) { - for (Map rootNode : rootNodes) { - rootNode.put("path", basePath); - result.addAll(buildFullTree(rootNode, allNodes)); + // 如果taskId为空,根据nodeName直接过滤 + if (StringUtils.isEmpty(taskId)) { + if (StringUtils.isEmpty(nodeName)) { + // 返回所有节点(需要按任务分组构建树) + // return buildAllTaskTrees(allNodes); + return result; + } else { + // 根据nodeName查询所有匹配节点,构建到根节点的路径 + return findNodesByName(allNodes, nodeName); } + } else { + // 原有逻辑:taskId不为空时按任务查询 + TsTask tsTask = tsTaskMapper.selectOne(new QueryWrapper().eq("id", taskId)); + if (tsTask == null) { + throw new RuntimeException("任务不存在"); } - return result; - } - // 否则,返回从根节点到目标节点的树形结构 - if (!rootNodes.isEmpty()) { - for (Map rootNode : rootNodes) { - rootNode.put("path", basePath); - List> tree = buildTreeToTargetNode(rootNode, allNodes, nodeName); - if (!tree.isEmpty()) { + List> rootNodes = findRootNodes(allNodes, taskId); + String basePath = "/" + tsTask.getTaskName() + "/"; + + Map rootNodeData = new HashMap<>(); + rootNodeData.put("nodeName", "根节点"); + rootNodeData.put("path", basePath); + rootNodeData.put("nodeId", tsTask.getId()); + rootNodeData.put("nodeOrder", "0"); + rootNodeData.put("taskId", tsTask.getId()); + rootNodeData.put("taskName", tsTask.getTaskName()); + rootNodeData.put("parentId", "00"); + result.add(rootNodeData); + + if (StringUtils.isEmpty(nodeName)) { + for (Map rootNode : rootNodes) { + rootNode.put("path", basePath); + result.addAll(buildFullTree(rootNode, allNodes)); + } + } else { + for (Map rootNode : rootNodes) { + rootNode.put("path", basePath); + List> tree = buildTreeToTargetNode(rootNode, allNodes, nodeName); result.addAll(tree); } } + return result; + } + } + + + + /** + * 根据节点名称查找所有匹配节点并构建树 + */ + private List> findNodesByName(List> allNodes, String nodeName) { + List> result = new ArrayList<>(); + + // 查找所有匹配的节点 + List> matchedNodes = allNodes.stream() + .filter(node -> { + Object nodeNameObj = node.get("nodeName"); + if (nodeNameObj instanceof String) { + String currentName = (String) nodeNameObj; + return currentName.toLowerCase().contains(nodeName.toLowerCase()); + } + return false; + }) + .collect(Collectors.toList()); + + // 为每个匹配节点构建到根节点的路径 + for (Map matchedNode : matchedNodes) { + // 找到该节点的完整路径 + List> pathToRoot = findPathToRoot(matchedNode, allNodes); + if (!pathToRoot.isEmpty()) { + result.addAll(pathToRoot); + } } - // 返回结果 return result; } + /** + * 查找节点到根节点的路径 + */ + private List> findPathToRoot(Map node, List> allNodes) { + List> path = new ArrayList<>(); + Map currentNode = node; + + // 向上查找直到根节点 + while (currentNode != null) { + path.add(0, new HashMap<>(currentNode)); // 添加到路径开头 + + String parentId = (String) currentNode.get("parentId"); + if ("00".equals(parentId)) { + // 找到根节点,添加任务信息 + String taskId = (String) currentNode.get("taskId"); + TsTask task = tsTaskMapper.selectOne(new QueryWrapper().eq("id", taskId)); + if (task != null) { + Map taskNode = new HashMap<>(); + taskNode.put("nodeName", "根节点"); + taskNode.put("path", "/" + task.getTaskName() + "/"); + taskNode.put("nodeId", task.getId()); + taskNode.put("nodeOrder", "0"); + taskNode.put("taskId", task.getId()); + taskNode.put("taskName", task.getTaskName()); + taskNode.put("parentId", "00"); + path.add(0, taskNode); + } + break; + } + + // 查找父节点 + String finalParentId = parentId; + currentNode = allNodes.stream() + .filter(n -> finalParentId.equals(n.get("nodeId"))) + .findFirst() + .orElse(null); + } + + return path; + } + +// public List> getTsNodesTree(String nodeName, String taskId) { +// TsTask tsTask = tsTaskMapper.selectOne(new QueryWrapper().eq("id", taskId)); +// // 查询所有节点数据 +// List> allNodes = getAllNodes(taskId); +// +// // 查找所有根节点(parentId为"00"的节点) +// List> rootNodes = findRootNodes(allNodes, taskId); +// +// // 根节点的基本路径:/项目名称/ +// String basePath = "/" + tsTask.getTaskName() + "/"; +// +// // 存储最终结果 +// List> result = new ArrayList<>(); +// Map rootNodeData = new HashMap<>(); +// rootNodeData.put("nodeName", "根节点"); +// rootNodeData.put("path", "/"+tsTask.getTaskName()+"/"); +// rootNodeData.put("nodeId", tsTask.getId()); +// rootNodeData.put("nodeOrder", "0"); +// rootNodeData.put("taskId", tsTask.getId()); +// rootNodeData.put("parentId", "00"); +// result.add(rootNodeData); +// +// // 如果 nodeName 为空,返回所有根节点的完整树形结构 +// if (StringUtils.isEmpty(nodeName)) { +// if (!rootNodes.isEmpty()) { +// for (Map rootNode : rootNodes) { +// rootNode.put("path", basePath); +// result.addAll(buildFullTree(rootNode, allNodes)); +// } +// } +// return result; +// } +// +// // 否则,返回从根节点到目标节点的树形结构 +// if (!rootNodes.isEmpty()) { +// for (Map rootNode : rootNodes) { +// rootNode.put("path", basePath); +// List> tree = buildTreeToTargetNode(rootNode, allNodes, nodeName); +// if (!tree.isEmpty()) { +// result.addAll(tree); +// } +// } +// } +// +// // 返回结果 +// return result; +// } + /** * 查询所有节点数据 * @@ -726,6 +855,7 @@ public class TsNodesServiceImpl extends ServiceImpl impl taskStatusHolder.finishTask(asyncKey); WebSocketServer.sendMessageTo("试验数据扫描接口完成", "taskId_" + id); } + } /********************************** @@ -789,6 +919,15 @@ public class TsNodesServiceImpl extends ServiceImpl impl return "扫描完成"; } catch (Exception e) { LOGGER.error("执行试验数据扫描时发生未知异常: {}", e.getMessage(), e); + //异常的时候删除节点和文件表 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(TsNodes::getTaskId, id); + tsNodesMapper.delete(queryWrapper); + + LambdaQueryWrapper queryWrapperTsFile = new LambdaQueryWrapper<>(); + queryWrapperTsFile.eq(TsFiles::getTaskId, id); + tsFilesMapper.delete(queryWrapperTsFile); + return "扫描失败:" + e.getMessage(); } finally { TableNameContextHolder.clear(); @@ -978,12 +1117,18 @@ public class TsNodesServiceImpl extends ServiceImpl impl // 批量插入文件表(忽略重复) if (!tsFilesToCreate.isEmpty()) { long startBatchInsertFiles = System.currentTimeMillis(); - int affectedRowsFiles = tsFilesMapper.batchInsertTsFiles(tsFilesToCreate); + //int affectedRowsFiles = tsFilesMapper.batchInsertTsFiles(tsFilesToCreate); + int affected = 0; + for (int i = 0; i < tsFilesToCreate.size(); i += BATCH_SIZE) { + List sub = + new ArrayList<>(tsFilesToCreate.subList(i, Math.min(i + BATCH_SIZE, tsFilesToCreate.size()))); + affected += this.insertOneBatch(sub); + } + LOGGER.info("[批量插入试验任务文件表] 耗时 {} ms | 实际新增数量: {} 条", System.currentTimeMillis() - startBatchInsertFiles, - affectedRowsFiles); + affected); } - // 记录开始时间 long startTimeFiles = System.currentTimeMillis(); // 执行更新操作 taskId, String nodeId @@ -996,6 +1141,14 @@ public class TsNodesServiceImpl extends ServiceImpl impl LOGGER.info("文件表中的节点ID更新完成,影响 {} 行,总耗时 {} 毫秒", affectedLevelFilesRows, costTimeFiles); } + /** + * 每批独立事务插入 + */ + @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class) + public int insertOneBatch(List batch) { + return tsFilesMapper.batchInsertTsFiles(batch); + } + /** * 确保路径格式为以 "/" 开头和结尾(例如 "/data/test/") * 若路径为空或非法,返回根路径 "/"