From 0ce8d92a5ad0396fb801f068e60d1fcf05268423 Mon Sep 17 00:00:00 2001 From: lilin Date: Tue, 27 May 2025 09:48:19 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AF=95=E9=AA=8C=E4=BB=BB=E5=8A=A1=E6=89=AB?= =?UTF-8?q?=E6=8F=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapper/TsFilesMapper.java | 6 + .../service/impl/TsNodesServiceImpl.java | 359 ++++++++++++++---- .../mapper/experimentalData/TsFilesMapper.xml | 23 ++ 3 files changed, 306 insertions(+), 82 deletions(-) diff --git a/java/src/main/java/com/yfd/platform/modules/experimentalData/mapper/TsFilesMapper.java b/java/src/main/java/com/yfd/platform/modules/experimentalData/mapper/TsFilesMapper.java index 58f858e..614ff68 100644 --- a/java/src/main/java/com/yfd/platform/modules/experimentalData/mapper/TsFilesMapper.java +++ b/java/src/main/java/com/yfd/platform/modules/experimentalData/mapper/TsFilesMapper.java @@ -2,6 +2,9 @@ package com.yfd.platform.modules.experimentalData.mapper; import com.yfd.platform.modules.experimentalData.domain.TsFiles; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; /** *

@@ -13,4 +16,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; */ public interface TsFilesMapper extends BaseMapper { + int batchInsertTsFiles(List tsFilesToCreate); + + int updateParentIdByPathHierarchy(@Param("taskId") String taskId, @Param("nodeId") String nodeId); } 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 2e00f2b..7f308c3 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 @@ -1,6 +1,7 @@ package com.yfd.platform.modules.experimentalData.service.impl; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.ObjUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; @@ -21,6 +22,8 @@ import com.yfd.platform.modules.specialDocument.domain.Files; import com.yfd.platform.modules.specialDocument.domain.Nodes; import com.yfd.platform.modules.specialDocument.domain.Project; import com.yfd.platform.modules.storage.context.StorageSourceContext; +import com.yfd.platform.modules.storage.mapper.StorageSourceConfigMapper; +import com.yfd.platform.modules.storage.model.entity.StorageSourceConfig; import com.yfd.platform.modules.storage.model.enums.FileTypeEnum; import com.yfd.platform.modules.storage.model.request.BatchDeleteRequest; import com.yfd.platform.modules.storage.model.request.NewFolderRequest; @@ -30,6 +33,7 @@ import com.yfd.platform.modules.storage.service.base.AbstractBaseFileService; import com.yfd.platform.system.domain.LoginUser; import com.yfd.platform.utils.StringUtils; import io.netty.channel.ChannelInboundHandlerAdapter; +import lombok.val; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -86,6 +90,10 @@ public class TsNodesServiceImpl extends ServiceImpl impl @Resource private StorageSourceService storageSourceService; + @Resource + private StorageSourceConfigMapper storageSourceConfigMapper; + + //顶级父节点 Top level parent node public static final String TOP_LEVEL_PARENT_NODE = "00"; @@ -647,6 +655,21 @@ public class TsNodesServiceImpl extends ServiceImpl impl TsTask tsTask = tsTaskMapper.selectById(id); + //文件的第一层是节点 下面的层级是文件夹 + + + + + + + + + + + + + + //获取文件列表 String absolutePath = "/" + tsTask.getTaskName() + "/"; FileListRequest fileListRequest = buildFileRequest(absolutePath); @@ -664,16 +687,7 @@ public class TsNodesServiceImpl extends ServiceImpl impl if (fileItemList.size() == 0) { throw new Exception("该试验任务管理项目目录不存在或没有项目文档,请先建立项目目录和文档。"); } - -// //获取数据库父节点为0的数据 任务ID 上级节点时00 -// List tsNodes = tsNodesMapper.selectList(new LambdaQueryWrapper().eq(TsNodes::getParentId, "00").eq(TsNodes::getTaskId, id)); -// -// // 步骤 1:提取现有的 nodeName -// Set existingNodeNames = tsNodes.stream().map(TsNodes::getNodeName).collect(Collectors.toSet()); -// -// // 步骤 2:筛选新增数据 找到需要新增到数据库的文件夹 这个属于第一层架 -// List fileItemNewList = fileItemList.stream().filter(fileItem -> !existingNodeNames.contains(fileItem.getName())).collect(Collectors.toList()); - firstLayerData(fileItemList, id); + firstLayerData(fileItemList, id); return "扫描完成"; } @@ -705,27 +719,6 @@ public class TsNodesServiceImpl extends ServiceImpl impl } } -// else { -// //获取节点名称 -// String nodeName = getLastPathSegment(item.getPath()); -// //获取节点信息 主要用到ID -// QueryWrapper queryWrapper = new QueryWrapper<>(); -// queryWrapper.eq("node_name", nodeName); -// queryWrapper.eq("parent_id", TOP_LEVEL_PARENT_NODE); -// Nodes node = nodesMapper.selectOne(queryWrapper); -// -// //新增之前先查询 -// LambdaQueryWrapper queryWrapper1 = new LambdaQueryWrapper<>(); -// queryWrapper1.eq(Files::getProjectId, projectId); -// queryWrapper1.eq(Files::getNodeId, node.getId()); -// queryWrapper1.eq(Files::getFilePath, item.getPath()); -// queryWrapper1.eq(Files::getFileName, item.getName()); -// Files files = filesMapper.selectOne(queryWrapper1); -// if (files == null) { -// //保存文件信息 -// saveFiles(projectId, node.getId(), item.getPath(), item.getName(), String.valueOf(item.getSize())); -// } -// } } } @@ -739,62 +732,264 @@ public class TsNodesServiceImpl extends ServiceImpl impl */ private void otherLevelsData(String taskId, String nodeId, String nodeName, String path, String parentId) throws Exception { - //通过节点的路径加名称 查询下面的文件及文件夹 - String absolutePath = path + nodeName + "/"; - //获取文件列表 - FileListRequest fileListRequest = buildFileRequest(absolutePath); - String storageKey = fileListRequest.getStorageKey(); - Integer storageId = storageSourceService.findIdByKey(storageKey); - if (storageId == null) { - throw new InvalidStorageSourceException("通过存储源 key 未找到存储源, key: " + storageKey); - } - // 处理请求参数默认值 - fileListRequest.handleDefaultValue(); - AbstractBaseFileService fileService = storageSourceContext.getByStorageId(storageId); - //todo 首先获取两个集合 对比出数据库中没有的文件夹以及文件,递归增加 - List fileItemList = fileService.fileList(fileListRequest.getPath()); - for (FileItemResult item : fileItemList) { - //思路就是 如果是文件夹 就查询一下 没有就新增, 新的的时候递归往下走 - if (item.getType() == FileTypeEnum.FOLDER) { - //先查询有没有 如果没有就新增 条件 节点ID 任务ID 上级ID 工作空间路径 文件名称 - LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); - queryWrapper.eq(TsFiles::getTaskId, taskId); - queryWrapper.eq(TsFiles::getNodeId, nodeId); - queryWrapper.eq(TsFiles::getParentId, parentId); - queryWrapper.eq(TsFiles::getFileName, item.getName()); - queryWrapper.eq(TsFiles::getWorkPath, item.getPath()); - TsFiles tsFiles = tsFilesMapper.selectOne(queryWrapper); - //如果没有 新增 并且递归 - if (tsFiles == null) { - //保存文件 - TsFiles tsFilesData = savetsFiles(taskId, nodeId, item.getName(), item.getPath(), parentId, "FOLDER", String.valueOf(item.getSize())); - otherLevelsData(taskId, nodeId, item.getName(), item.getPath(), tsFilesData.getId()); + // 存储所有目录和文件的列表 + List tsFilesToCreate = new ArrayList<>(); - } else { - otherLevelsData(taskId, nodeId, item.getName(), item.getPath(), tsFiles.getId()); - } + // 设置当前时间 + LocalDateTime now = LocalDateTime.now(); + // 转换为 Timestamp + Timestamp currentTime = Timestamp.valueOf(now); + + + // 查询本地文件路径根目录(如 E:\yun) + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("name", "filePath"); + queryWrapper.eq("type", "local"); + StorageSourceConfig storageSourceConfig = storageSourceConfigMapper.selectOne(queryWrapper); + + //获取文件列表 这个地方path+name + File projectDir = new File(storageSourceConfig.getValue()+path+nodeName); + + // 获取所有子目录 + List allSubDirs = new ArrayList<>(); + getAllSubDirectories(projectDir, allSubDirs); + String storageSourceConfigPath = storageSourceConfig.getValue().replace("\\", "/"); + // 批量处理子目录 + long startBuildNodes = System.currentTimeMillis(); + for (File subDir : allSubDirs) { + String normalizedSubDirPath = subDir.getAbsolutePath().replace("\\", "/"); + // 获取上一级目录 + String parentPath = normalizedSubDirPath.substring(0, normalizedSubDirPath.lastIndexOf("/")); + // 去掉 D:/yun 部分 + String finalPath = parentPath.replace(storageSourceConfigPath, ""); + //保存文件信息 + TsFiles tsFiles1 = new TsFiles(); + //任务 + tsFiles1.setTaskId(taskId); + //节点 + tsFiles1.setNodeId(nodeId); + //文件 文件夹 区分 + tsFiles1.setIsFile("FOLDER"); + //上级ID + tsFiles1.setParentId("00"); + //文件名称 + tsFiles1.setFileName(subDir.getName()); + //工作空间路径 + tsFiles1.setWorkPath(ensurePathFormat(finalPath)); + tsFiles1.setUploadTime(currentTime); + + + if ("null".equals(String.valueOf(subDir.length()))) { + tsFiles1.setFileSize("0.001"); } else { - //todo 如果是文件 直接新增就可以了 不需要其他的操作 - //先查询有没有 如果没有就新增 条件 节点ID 任务ID 上级ID 工作空间路径 文件名称 - LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); - queryWrapper.eq(TsFiles::getTaskId, taskId); - queryWrapper.eq(TsFiles::getNodeId, nodeId); - queryWrapper.eq(TsFiles::getParentId, parentId); - queryWrapper.eq(TsFiles::getFileName, item.getName()); - queryWrapper.eq(TsFiles::getWorkPath, item.getPath()); - TsFiles tsFiles = tsFilesMapper.selectOne(queryWrapper); - if (tsFiles == null) { + //文件大小 + if ("0.000".equals(String.valueOf(subDir.length()))) { + tsFiles1.setFileSize("0.001"); + } else { + tsFiles1.setFileSize(String.valueOf(subDir.length())); + } + } + tsFilesToCreate.add(tsFiles1); + } + LOGGER.info("[构建文件表中的文件夹列表] 耗时 {} ms | 待处理数量: {} 条", + System.currentTimeMillis() - startBuildNodes, + tsFilesToCreate.size()); - // 获取文件大小(字节) - long fileSizeInBytes = item.getSize(); - // 转换为 MB 并保留两位小数 - double fileSizeInMB = fileSizeInBytes / (1024.0 * 1024.0); - String fileSizeFormatted = String.format("%.2f", fileSizeInMB); // 保留两位小数 - //保存文件信息 - TsFiles tsFilesData = savetsFiles(taskId, nodeId, item.getName(), item.getPath(), parentId, "FILE", fileSizeFormatted); - LOGGER.info("保存文件信息:{}", item.getPath() + item.getName()); + // 获取所有文件 + List allFiles = new ArrayList<>(); + getAllFiles(projectDir, allFiles); + System.out.println("allFiles=" + allFiles.size()); + long startBuildFiles = System.currentTimeMillis(); + // 批量处理文件 + for (File file : allFiles) { + String normalizedFilesPath = file.getAbsolutePath().replace("\\", "/"); + // 获取上一级目录 + String parentPath = normalizedFilesPath.substring(0, normalizedFilesPath.lastIndexOf("/")); + // 去掉 D:/yun 部分 + String finalPath = parentPath.replace(storageSourceConfigPath, ""); + //保存文件信息 + TsFiles tsFiles1 = new TsFiles(); + tsFiles1.setId(IdUtil.fastSimpleUUID()); + //任务 + tsFiles1.setTaskId(taskId); + //节点 + tsFiles1.setNodeId(nodeId); + //文件 文件夹 区分 + tsFiles1.setIsFile("FILE"); + //上级ID + tsFiles1.setParentId("00"); + //文件名称 + tsFiles1.setFileName(file.getName()); + //工作空间路径 + tsFiles1.setWorkPath(ensurePathFormat(finalPath)); + tsFiles1.setUploadTime(currentTime); + + + if ("null".equals(String.valueOf(file.length()))) { + tsFiles1.setFileSize("0.001"); + } else { + //文件大小 + if ("0.000".equals(String.valueOf(file.length()))) { + tsFiles1.setFileSize("0.001"); + } else { + tsFiles1.setFileSize(String.valueOf(file.length())); + } + } + tsFilesToCreate.add(tsFiles1); + } + LOGGER.info("[构建文件表中的文件列表] 耗时 {} ms | 待处理数量: {} 条", + System.currentTimeMillis() - startBuildFiles, + tsFilesToCreate.size()); + + // 批量插入文件表(忽略重复) + if (!tsFilesToCreate.isEmpty()) { + long startBatchInsertFiles = System.currentTimeMillis(); + int affectedRowsFiles = tsFilesMapper.batchInsertTsFiles(tsFilesToCreate); + LOGGER.info("[批量插入试验任务文件表] 耗时 {} ms | 实际新增数量: {} 条", + System.currentTimeMillis() - startBatchInsertFiles, + affectedRowsFiles); + } + + // 记录开始时间 + long startTimeFiles = System.currentTimeMillis(); + // 执行更新操作 taskId, String nodeId + int affectedLevelFilesRows = tsFilesMapper.updateParentIdByPathHierarchy(taskId,nodeId); + // 记录结束时间 + long endTimeFiles = System.currentTimeMillis(); + // 计算耗时 + long costTimeFiles = endTimeFiles - startTimeFiles; + // 打印日志 + LOGGER.info("文件表中的节点ID更新完成,影响 {} 行,总耗时 {} 毫秒", affectedLevelFilesRows, costTimeFiles); + + +// //获取文件列表 +// String absolutePath =path + "/" + nodeName + "/"; +// //获取当前登录用户 上传人是当前登录人 +// UsernamePasswordAuthenticationToken authentication = +// (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); +// LoginUser loginuser = null; +// if (authentication != null) { +// loginuser = (LoginUser) authentication.getPrincipal(); +// } +// //登录人 +// String uploader = null; +// if (loginuser != null) { +// uploader = loginuser.getUsername(); +// } +// // 设置当前时间 +// LocalDateTime now = LocalDateTime.now(); +// // 转换为 Timestamp +// Timestamp currentTime = Timestamp.valueOf(now); +// +// +// +// +// +// //获取文件列表 +// FileListRequest fileListRequest = buildFileRequest(absolutePath); +// String storageKey = fileListRequest.getStorageKey(); +// Integer storageId = storageSourceService.findIdByKey(storageKey); +// if (storageId == null) { +// throw new InvalidStorageSourceException("通过存储源 key 未找到存储源, key: " + storageKey); +// } +// // 处理请求参数默认值 +// fileListRequest.handleDefaultValue(); +// AbstractBaseFileService fileService = storageSourceContext.getByStorageId(storageId); +// //todo 首先获取两个集合 对比出数据库中没有的文件夹以及文件,递归增加 +// List fileItemList = fileService.fileList(fileListRequest.getPath()); +// +// for (FileItemResult item : fileItemList) { +// //思路就是 如果是文件夹 就查询一下 没有就新增, 新的的时候递归往下走 +// if (item.getType() == FileTypeEnum.FOLDER) { +// //先查询有没有 如果没有就新增 条件 节点ID 任务ID 上级ID 工作空间路径 文件名称 +// LambdaQueryWrapper queryWrapper1 = new LambdaQueryWrapper<>(); +// queryWrapper1.eq(TsFiles::getTaskId, taskId); +// queryWrapper1.eq(TsFiles::getNodeId, nodeId); +// queryWrapper1.eq(TsFiles::getParentId, parentId); +// queryWrapper1.eq(TsFiles::getFileName, item.getName()); +// queryWrapper1.eq(TsFiles::getWorkPath, item.getPath()); +// TsFiles tsFiles = tsFilesMapper.selectOne(queryWrapper1); +// //如果没有 新增 并且递归 +// if (tsFiles == null) { +// //保存文件 +// TsFiles tsFilesData = savetsFiles(taskId, nodeId, item.getName(), item.getPath(), parentId, "FOLDER", String.valueOf(item.getSize())); +// otherLevelsData(taskId, nodeId, item.getName(), item.getPath(), tsFilesData.getId()); +// +// } else { +// otherLevelsData(taskId, nodeId, item.getName(), item.getPath(), tsFiles.getId()); +// } +// } else { +// //todo 如果是文件 直接新增就可以了 不需要其他的操作 +// //先查询有没有 如果没有就新增 条件 节点ID 任务ID 上级ID 工作空间路径 文件名称 +// LambdaQueryWrapper queryWrapper2 = new LambdaQueryWrapper<>(); +// queryWrapper2.eq(TsFiles::getTaskId, taskId); +// queryWrapper2.eq(TsFiles::getNodeId, nodeId); +// queryWrapper2.eq(TsFiles::getParentId, parentId); +// queryWrapper2.eq(TsFiles::getFileName, item.getName()); +// queryWrapper2.eq(TsFiles::getWorkPath, item.getPath()); +// TsFiles tsFiles = tsFilesMapper.selectOne(queryWrapper2); +// if (tsFiles == null) { +// +// // 获取文件大小(字节) +// long fileSizeInBytes = item.getSize(); +// // 转换为 MB 并保留两位小数 +// double fileSizeInMB = fileSizeInBytes / (1024.0 * 1024.0); +// String fileSizeFormatted = String.format("%.2f", fileSizeInMB); // 保留两位小数 +// +// //保存文件信息 +// TsFiles tsFilesData = savetsFiles(taskId, nodeId, item.getName(), item.getPath(), parentId, "FILE", fileSizeFormatted); +// LOGGER.info("保存文件信息:{}", item.getPath() + item.getName()); +// } +// } +// } + } + + /** + * 确保路径格式为以 "/" 开头和结尾(例如 "/data/test/") + * 若路径为空或非法,返回根路径 "/" + */ + private String ensurePathFormat(String path) { + if (StringUtils.isBlank(path)) { + return "/"; + } + // 统一替换反斜杠为斜杠(兼容 Windows 路径) + String normalized = path.replaceAll("\\\\", "/"); + // 去掉多余的斜杠 + normalized = normalized.replaceAll("/{2,}", "/"); + // 确保以 "/" 开头 + if (!normalized.startsWith("/")) { + normalized = "/" + normalized; + } + // 确保以 "/" 结尾 + if (!normalized.endsWith("/")) { + normalized += "/"; + } + return normalized; + } + + private void getAllSubDirectories(File dir, List subDirs) { + File[] files = dir.listFiles(); + if (files != null) { + for (File file : files) { + if (file.isDirectory()) { + subDirs.add(file); + getAllSubDirectories(file, subDirs); + } + } + } + } + + + private void getAllFiles(File dir, List files) { + File[] fileList = dir.listFiles(); + if (fileList != null) { + for (File file : fileList) { + if (file.isFile()) { + files.add(file); + } else if (file.isDirectory()) { + getAllFiles(file, files); } } } diff --git a/java/src/main/resources/mapper/experimentalData/TsFilesMapper.xml b/java/src/main/resources/mapper/experimentalData/TsFilesMapper.xml index 95e280c..6442f45 100644 --- a/java/src/main/resources/mapper/experimentalData/TsFilesMapper.xml +++ b/java/src/main/resources/mapper/experimentalData/TsFilesMapper.xml @@ -2,4 +2,27 @@ + + + INSERT INTO ts_files + (id,node_id, task_id, is_file, parent_id, file_name, file_size, work_path,upload_time) + VALUES + + (#{item.id},#{item.nodeId}, #{item.taskId}, #{item.isFile}, #{item.parentId}, + #{item.fileName}, #{item.fileSize}, #{item.workPath}, #{item.uploadTime}) + + + + + UPDATE ts_files a + LEFT JOIN ts_files b + ON b.task_id = a.task_id + AND b.node_id = a.node_id + AND a.work_path = CONCAT( b.work_path, b.file_name, '/' ) + SET a.parent_id = b.id + WHERE + b.task_id = #{taskId} + AND b.node_id = #{nodeId} + +