From 01d1bf1dbfec7806d0276ce238bddfed5e25ba6e Mon Sep 17 00:00:00 2001 From: lilin Date: Tue, 27 May 2025 14:52:54 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../platform/component/TaskStatusHolder.java | 2 +- .../controller/TsFilesController.java | 21 ++-- .../controller/TsNodesController.java | 15 ++- .../service/ITsFilesService.java | 4 +- .../service/impl/TsFilesServiceImpl.java | 49 ++++---- .../service/impl/TsNodesServiceImpl.java | 95 ++++++++++----- .../controller/NodesController.java | 115 ++++++++---------- .../service/INodesService.java | 3 +- .../service/impl/FilesServiceImpl.java | 41 ++++--- .../service/impl/NodesServiceImpl.java | 106 ++++++++-------- 10 files changed, 245 insertions(+), 206 deletions(-) diff --git a/java/src/main/java/com/yfd/platform/component/TaskStatusHolder.java b/java/src/main/java/com/yfd/platform/component/TaskStatusHolder.java index 2b0d381..a063616 100644 --- a/java/src/main/java/com/yfd/platform/component/TaskStatusHolder.java +++ b/java/src/main/java/com/yfd/platform/component/TaskStatusHolder.java @@ -21,7 +21,7 @@ public class TaskStatusHolder { // 生成专项扫描唯一Key:project_id public String specialGenerateKey(String id) { - return id + ":"; + return id + "扫描:"; } // 生成专项文档上传唯一Key:project_id+上传: public String documentUploadKey(String id) { diff --git a/java/src/main/java/com/yfd/platform/modules/experimentalData/controller/TsFilesController.java b/java/src/main/java/com/yfd/platform/modules/experimentalData/controller/TsFilesController.java index ae08f07..0232dbc 100644 --- a/java/src/main/java/com/yfd/platform/modules/experimentalData/controller/TsFilesController.java +++ b/java/src/main/java/com/yfd/platform/modules/experimentalData/controller/TsFilesController.java @@ -3,6 +3,7 @@ package com.yfd.platform.modules.experimentalData.controller; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONObject; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.yfd.platform.annotation.Log; @@ -65,11 +66,12 @@ public class TsFilesController { //分页查询 int currentPage = (int) page.getCurrent(); // 先尝试从缓存获取 - IPage cachedPage = tsFilesService.getCachedTsFilesPage(taskId, nodeId, currentPage); - if (cachedPage != null) { - return ResponseResult.successData(cachedPage); + if(!StrUtil.isEmpty(id)){ + IPage cachedPage = tsFilesService.getCachedTsFilesPage(taskId, nodeId, currentPage,id); + if (cachedPage != null) { + return ResponseResult.successData(cachedPage); + } } - Page tsfilesPage = tsFilesService.getTsFilesPage(id, fileName, startDate, endDate, keywords, nodeId, taskId, fileName, childNode, page); return ResponseResult.successData(tsfilesPage); } @@ -589,16 +591,19 @@ public class TsFilesController { } // 生成唯一Key String asyncKey = taskStatusHolder.generateKey(taskId, nodeId); - + JSONObject jsonObject1 = new JSONObject(); // 检查任务是否已存在 String existingStatus = taskStatusHolder.getStatus(asyncKey); if ("TASK_NOT_FOUND".equals(existingStatus)) { - return ResponseResult.success("1"); + jsonObject1.putOpt("status", "1"); + return ResponseResult.successData(jsonObject1); } if ("IN_PROGRESS".equals(existingStatus)) { - return ResponseResult.success("0"); + jsonObject1.putOpt("status", "0"); + return ResponseResult.successData(jsonObject1); } else if ("COMPLETED".equals(existingStatus)) { - return ResponseResult.success("自动备份任务已完成!"); + jsonObject1.putOpt("status", "1"); + return ResponseResult.successData(jsonObject1); } return null; diff --git a/java/src/main/java/com/yfd/platform/modules/experimentalData/controller/TsNodesController.java b/java/src/main/java/com/yfd/platform/modules/experimentalData/controller/TsNodesController.java index 29be37a..2b26c4a 100644 --- a/java/src/main/java/com/yfd/platform/modules/experimentalData/controller/TsNodesController.java +++ b/java/src/main/java/com/yfd/platform/modules/experimentalData/controller/TsNodesController.java @@ -3,6 +3,7 @@ package com.yfd.platform.modules.experimentalData.controller; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONObject; import com.yfd.platform.annotation.Log; import com.yfd.platform.component.TaskStatusHolder; import com.yfd.platform.config.ResponseResult; @@ -103,11 +104,11 @@ public class TsNodesController { @PostMapping("/deleteTsNodesById") @ApiOperation("根据ID删除试验任务节点") @PreAuthorize("@el.check('del:tsnodes')") - public ResponseResult deleteTsNodesById(@RequestParam String id,String path) { + public ResponseResult deleteTsNodesById(@RequestParam String id, String path) { if (StrUtil.isBlank(id)) { return ResponseResult.error("参数为空"); } - boolean isOk = tsNodesService.deleteTsNodesById(id,path); + boolean isOk = tsNodesService.deleteTsNodesById(id, path); if (isOk) { return ResponseResult.success(); } else { @@ -160,6 +161,7 @@ public class TsNodesController { if (StrUtil.isEmpty(id)) { return ResponseResult.error("id为空"); } + JSONObject jsonObject1 = new JSONObject(); // 生成唯一Key String asyncKey = taskStatusHolder.testDatascanKey(id); @@ -167,12 +169,15 @@ public class TsNodesController { // 检查任务是否已存在 String existingStatus = taskStatusHolder.getStatus(asyncKey); if ("TASK_NOT_FOUND".equals(existingStatus)) { - return ResponseResult.success("1"); + jsonObject1.putOpt("status", "1"); + return ResponseResult.successData(jsonObject1); } if ("IN_PROGRESS".equals(existingStatus)) { - return ResponseResult.success("0"); + jsonObject1.putOpt("status", "0"); + return ResponseResult.successData(jsonObject1); } else if ("COMPLETED".equals(existingStatus)) { - return ResponseResult.success("专项文档扫描任务已完成!"); + jsonObject1.putOpt("status", "1"); + return ResponseResult.successData(jsonObject1); } return null; diff --git a/java/src/main/java/com/yfd/platform/modules/experimentalData/service/ITsFilesService.java b/java/src/main/java/com/yfd/platform/modules/experimentalData/service/ITsFilesService.java index 60d8d75..95d8b66 100644 --- a/java/src/main/java/com/yfd/platform/modules/experimentalData/service/ITsFilesService.java +++ b/java/src/main/java/com/yfd/platform/modules/experimentalData/service/ITsFilesService.java @@ -247,7 +247,7 @@ public interface ITsFilesService extends IService { Object compareMd5List(List dataset, String nodeId, String taskId); - void automaticFileBackupAsyncByIds(List dataset); + void automaticFileBackupAsyncByIds(List dataset) throws IOException; - IPage getCachedTsFilesPage(String taskId, String nodeId, int currentPage); + IPage getCachedTsFilesPage(String taskId, String nodeId, int currentPage,String id); } diff --git a/java/src/main/java/com/yfd/platform/modules/experimentalData/service/impl/TsFilesServiceImpl.java b/java/src/main/java/com/yfd/platform/modules/experimentalData/service/impl/TsFilesServiceImpl.java index 11f95fa..00880b8 100644 --- a/java/src/main/java/com/yfd/platform/modules/experimentalData/service/impl/TsFilesServiceImpl.java +++ b/java/src/main/java/com/yfd/platform/modules/experimentalData/service/impl/TsFilesServiceImpl.java @@ -17,6 +17,7 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; +import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; import com.amazonaws.services.s3.model.ObjectMetadata; import com.amazonaws.services.s3.model.S3Object; @@ -31,6 +32,7 @@ import com.opencsv.CSVWriter; import com.opencsv.exceptions.CsvValidationException; import com.yfd.platform.component.ServerSendEventServer; import com.yfd.platform.component.TaskStatusHolder; +import com.yfd.platform.component.WebSocketServer; import com.yfd.platform.config.ResponseResult; import com.yfd.platform.modules.experimentalData.domain.*; import com.yfd.platform.modules.experimentalData.mapper.TsFilesMapper; @@ -52,6 +54,7 @@ import com.yfd.platform.modules.storage.service.base.AbstractBaseFileService; import com.yfd.platform.system.domain.LoginUser; import com.yfd.platform.system.domain.SysDictionaryItems; import com.yfd.platform.system.mapper.SysDictionaryItemsMapper; +import com.yfd.platform.task.TaskMessage; import com.yfd.platform.utils.StringUtils; import io.netty.channel.ChannelInboundHandlerAdapter; import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry; @@ -79,6 +82,7 @@ import java.io.*; import java.sql.Timestamp; import java.time.LocalDateTime; import java.util.zip.*; + import com.fasterxml.jackson.core.type.TypeReference; import org.apache.commons.codec.binary.Hex; @@ -132,9 +136,9 @@ public class TsFilesServiceImpl extends ServiceImpl impl private TaskStatusHolder taskStatusHolder; - @Autowired private RedisTemplate redisTemplate; + private TaskMessage taskMessage; /********************************** * 用途说明: 分页查询试验数据管理-文档内容 @@ -264,9 +268,14 @@ public class TsFilesServiceImpl extends ServiceImpl impl tsFilesPage.setRecords(records); // 同步到 tsFilesPage int currentPage = (int) page.getCurrent(); // 如果是前五页,将结果存入Redis(有效期建议30分钟) - if (currentPage >= 1 && currentPage <= 5) { + if (!StrUtil.isEmpty(id)) { + if (currentPage >= 1 && currentPage <= 5) { + String redisKey = "tsfiles_" + taskId + "_" + nodeId + "_parentId" + id + "_page_" + currentPage + ""; + redisTemplate.opsForValue().set(redisKey, tsFilesPage, 2, TimeUnit.HOURS); + } + } else { String redisKey = "tsfiles_" + taskId + "_" + nodeId + "_page_" + currentPage; - redisTemplate.opsForValue().set(redisKey, tsFilesPage, 2, TimeUnit.HOURS); + redisTemplate.delete(redisKey); } return tsFilesPage; @@ -274,14 +283,17 @@ public class TsFilesServiceImpl extends ServiceImpl impl /** * Redis缓存获取 + * * @param taskId * @param nodeId * @param currentPage * @return */ @Override - public IPage getCachedTsFilesPage(String taskId, String nodeId, int currentPage) { - String redisKey = "tsfiles_" + taskId + "_" + nodeId + "_page_" + currentPage; + public IPage getCachedTsFilesPage(String taskId, String nodeId, int currentPage, String id) { + String redisKey = "tsfiles_" + taskId + "_" + nodeId + "_parentId" + id + "_page_" + currentPage; + + Object data = redisTemplate.opsForValue().get(redisKey); if (data instanceof IPage) { @@ -299,10 +311,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl } return null; } - public void cachePageData(String taskId, String nodeId, int currentPage, Page pageData) { - String redisKey = "tsfiles_" + taskId + "_" + nodeId + "_page_" + currentPage; - redisTemplate.opsForValue().set(redisKey, pageData, 2, TimeUnit.HOURS); - } + public boolean hasValidExtension(String name, List sysDictionaryItems) { // 如果传入的文件名为空,返回 false @@ -407,7 +416,9 @@ public class TsFilesServiceImpl extends ServiceImpl impl //todo 新增成功以后 删除redis for (int page = 1; page <= 5; page++) { - String redisKey = "tsfiles_" + tsFiles.getTaskId() + "_" + tsFiles.getNodeId() + "_page_" + page; + String redisKey = "tsfiles_" + tsFiles.getTaskId() + "_" + tsFiles.getNodeId() + "_parentId" + tsFiles.getParentId() + "_page_" + page; + + redisTemplate.delete(redisKey); } LOGGER.info("已清理缓存:taskid={}, node={}, pages=1-5", tsFiles.getTaskId(), tsFiles.getNodeId()); @@ -539,7 +550,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl //todo 新增成功以后 删除redis for (int page = 1; page <= 5; page++) { - String redisKey = "tsfiles_" + tsFiles.getTaskId() + "_" + tsFiles.getNodeId() + "_page_" + page; + String redisKey = "tsfiles_" + tsFiles.getTaskId() + "_" + tsFiles.getNodeId() + "_parentId" + tsFiles.getParentId() + "_page_" + page; redisTemplate.delete(redisKey); } LOGGER.info("已清理缓存:taskid={}, node={}, pages=1-5", tsFiles.getTaskId(), tsFiles.getNodeId()); @@ -649,7 +660,7 @@ public class TsFilesServiceImpl extends ServiceImpl impl //todo 新增成功以后 删除redis for (int page = 1; page <= 5; page++) { - String redisKey = "tsfiles_" + tsFiles.getTaskId() + "_" + tsFiles.getNodeId() + "_page_" + page; + String redisKey = "tsfiles_" + tsFiles.getTaskId() + "_" + tsFiles.getNodeId() + "_parentId" + tsFiles.getParentId() + "_page_" + page; redisTemplate.delete(redisKey); } LOGGER.info("已清理缓存:taskid={}, node={}, pages=1-5", tsFiles.getTaskId(), tsFiles.getNodeId()); @@ -932,14 +943,6 @@ public class TsFilesServiceImpl extends ServiceImpl impl int LocalSuccessCount = 0, LocalFailCount = 0, Localtotal = CollUtil.size(dataset); //Todo 最直接的办法 循环出来 一条一条删除 for (TsFiles files : filesList) { - -// //todo 新增成功以后 删除redis -// for (int page = 1; page <= 5; page++) { -// String redisKey = "tsfiles_" + files.getTaskId() + "_" + files.getNodeId() + "_page_" + page; -// redisTemplate.delete(redisKey); -// } -// LOGGER.info("已清理缓存:taskid={}, node={}, pages=1-5", files.getTaskId(), files.getNodeId()); - //判断是文件还是文件夹 if ("FOLDER".equals(files.getIsFile())) { //如果是文件夹 @@ -3372,12 +3375,13 @@ public class TsFilesServiceImpl extends ServiceImpl impl String asyncKey = taskStatusHolder.generateKey(taskId, nodeId); // 无论成功失败都标记完成 taskStatusHolder.finishTask(asyncKey); + WebSocketServer.sendMessageTo("文件自动备份完成", "backups"); } } @Override @Async("asyncExecutor") - public void automaticFileBackupAsyncByIds(List dataset) { + public void automaticFileBackupAsyncByIds(List dataset) throws IOException { try { // 执行实际备份逻辑 this.automaticFileBackupByIds(dataset); @@ -3386,12 +3390,11 @@ public class TsFilesServiceImpl extends ServiceImpl impl String asyncKey = taskStatusHolder.generateKeybyId(dataset); // 无论成功失败都标记完成 taskStatusHolder.finishTask(asyncKey); + WebSocketServer.sendMessageTo("文件自动备份完成", "backups"); } } - - /********************************** * 用途说明: 文件自动备份通过节点和任务 * 参数说明 taskId 节点ID 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 7f308c3..2e7346c 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 @@ -5,7 +5,9 @@ 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; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.yfd.platform.component.TaskStatusHolder; +import com.yfd.platform.component.WebSocketServer; import com.yfd.platform.config.ResponseResult; import com.yfd.platform.exception.file.InvalidStorageSourceException; import com.yfd.platform.modules.config.model.request.FileListRequest; @@ -449,24 +451,51 @@ public class TsNodesServiceImpl extends ServiceImpl impl //根据ID 查询当前数据 TsNodes tsNodes = tsNodesMapper.selectById(id); //删除之前 先拼路径 然后删除本地和minio的文件夹 最后删除表结构 - //删除当前节点的 文件 + //查询所有的子节点 + List tsNodesList = selectChildrentsNodes(tsNodes.getNodeId(), tsNodes.getTaskId()); + // 提取所有节点的 ID + List nodeIds = tsNodesList.stream() + .map(TsNodes::getNodeId) // 获取每个节点的 ID + .collect(Collectors.toList()); + + + //查询所有的文件 QueryWrapper queryWrapper1 = new QueryWrapper<>(); - queryWrapper1.eq("node_id", tsNodes.getNodeId()); + queryWrapper1.in("node_id", nodeIds); queryWrapper1.eq("task_id", tsNodes.getTaskId()); List tsFiles = tsFilesMapper.selectList(queryWrapper1); - + //获取所有文件的ID集合 List dataset = new ArrayList<>(); if (tsFiles != null && !tsFiles.isEmpty()) { - dataset = tsFiles.stream() - .map(TsFiles::getId) // 假设 TsFiles 类中有 getId() 方法 - .collect(Collectors.toList()); + dataset.addAll(tsFiles.stream() + .map(TsFiles::getId) + .collect(Collectors.toList())); } - //批量删除TsFiles表数据 - if (dataset.size() > 0) { - tsFilesService.deleteTsFilesByIds(dataset, "local"); + if (dataset.size() <= 0) { + return true; } -// // 递归删除子节点 + //批量修改 + LambdaUpdateWrapper updateWrapper1 = new LambdaUpdateWrapper<>(); + updateWrapper1.in(TsFiles::getId,dataset).isNotNull(TsFiles::getBackupPath).ne(TsFiles::getBackupPath,"").set(TsFiles::getWorkPath, ""); + tsFilesMapper.update(null, updateWrapper1); + //批量删除 + LambdaQueryWrapper deleteWrapper = new LambdaQueryWrapper<>(); + deleteWrapper.in(TsFiles::getId,dataset).isNull(TsFiles::getBackupPath).eq(TsFiles::getBackupPath,"").isNull(TsFiles::getWorkPath).eq(TsFiles::getWorkPath,""); + tsFilesMapper.delete(deleteWrapper); + +// //批量修改TsFiles表结构 +// if (dataset.size() > 0) { +// QueryWrapper updateWrapper = new QueryWrapper<>(); +// updateWrapper.in("id", dataset); +// // 创建 TsFiles 实体对象,设置要更新的字段 +// TsFiles tsFiles1 = new TsFiles(); +// tsFiles1.setWorkPath(""); // 将 work_path 更新为 "" +// tsFilesMapper.update(tsFiles1, updateWrapper); +// LOGGER.info("tsFiles一共删除 {}跳", dataset.size()); +// } +// +//// // 递归删除子节点 // deleteChildren(tsNodes.getNodeId(), tsNodes.getTaskId()); @@ -520,6 +549,29 @@ public class TsNodesServiceImpl extends ServiceImpl impl } } + private List selectChildrentsNodes(String parentId, String taskId) { + List nodesList = new ArrayList<>(); + TsNodes tsNodes = tsNodesMapper.selectById(parentId); + // 查询当前节点的所有子节点 + + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("parent_id", parentId); // parent_id = #{parentId} + queryWrapper.eq("task_id", taskId); // parent_id = #{parentId} + List children = tsNodesMapper.selectList(queryWrapper); + // 将子节点添加到 nodesList 中 + nodesList.addAll(children); + nodesList.add(tsNodes); + + // 递归删除每个子节点 + for (TsNodes child : children) { + // 递归查询子节点的子节点 + List childNodes = selectChildrentsNodes(child.getNodeId(), taskId); + // 将子节点的所有子节点添加到 nodesList 中 + nodesList.addAll(childNodes); + } + return nodesList; + } + /** * 递归删除子节点 * @@ -646,6 +698,7 @@ public class TsNodesServiceImpl extends ServiceImpl impl String asyncKey = taskStatusHolder.testDatascanKey(id); // 无论成功失败都标记完成 taskStatusHolder.finishTask(asyncKey); + WebSocketServer.sendMessageTo("试验数据扫描接口完成", "taskId_" + id); } } @@ -653,23 +706,7 @@ public class TsNodesServiceImpl extends ServiceImpl impl //查询试验任务信息 TsTask tsTask = tsTaskMapper.selectById(id); - - //文件的第一层是节点 下面的层级是文件夹 - - - - - - - - - - - - - - //获取文件列表 String absolutePath = "/" + tsTask.getTaskName() + "/"; FileListRequest fileListRequest = buildFileRequest(absolutePath); @@ -687,7 +724,7 @@ public class TsNodesServiceImpl extends ServiceImpl impl if (fileItemList.size() == 0) { throw new Exception("该试验任务管理项目目录不存在或没有项目文档,请先建立项目目录和文档。"); } - firstLayerData(fileItemList, id); + firstLayerData(fileItemList, id); return "扫描完成"; } @@ -749,7 +786,7 @@ public class TsNodesServiceImpl extends ServiceImpl impl StorageSourceConfig storageSourceConfig = storageSourceConfigMapper.selectOne(queryWrapper); //获取文件列表 这个地方path+name - File projectDir = new File(storageSourceConfig.getValue()+path+nodeName); + File projectDir = new File(storageSourceConfig.getValue() + path + nodeName); // 获取所有子目录 List allSubDirs = new ArrayList<>(); @@ -855,7 +892,7 @@ public class TsNodesServiceImpl extends ServiceImpl impl // 记录开始时间 long startTimeFiles = System.currentTimeMillis(); // 执行更新操作 taskId, String nodeId - int affectedLevelFilesRows = tsFilesMapper.updateParentIdByPathHierarchy(taskId,nodeId); + int affectedLevelFilesRows = tsFilesMapper.updateParentIdByPathHierarchy(taskId, nodeId); // 记录结束时间 long endTimeFiles = System.currentTimeMillis(); // 计算耗时 diff --git a/java/src/main/java/com/yfd/platform/modules/specialDocument/controller/NodesController.java b/java/src/main/java/com/yfd/platform/modules/specialDocument/controller/NodesController.java index da52f7f..26aa56a 100644 --- a/java/src/main/java/com/yfd/platform/modules/specialDocument/controller/NodesController.java +++ b/java/src/main/java/com/yfd/platform/modules/specialDocument/controller/NodesController.java @@ -3,8 +3,11 @@ package com.yfd.platform.modules.specialDocument.controller; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; import com.yfd.platform.annotation.Log; import com.yfd.platform.component.TaskStatusHolder; +import com.yfd.platform.component.WebSocketServer; import com.yfd.platform.config.ResponseResult; import com.yfd.platform.modules.specialDocument.domain.Nodes; import com.yfd.platform.modules.specialDocument.service.INodesService; @@ -99,11 +102,11 @@ public class NodesController { @PostMapping("/deleteNodesById") @ApiOperation("根据ID删除专项文档节点") @PreAuthorize("@el.check('del:nodes')") - public ResponseResult deleteNodesById(@RequestParam String id, String path) { + public ResponseResult deleteNodesById(@RequestParam String id, String path) { if (StrUtil.isBlank(id)) { return ResponseResult.error("参数为空"); } - boolean isOk = nodesService.deleteNodesById(id,path); + boolean isOk = nodesService.deleteNodesById(id, path); if (isOk) { return ResponseResult.success(); } else { @@ -144,60 +147,66 @@ public class NodesController { } } + /********************************** * 用途说明: 获取异步信息 * 参数说明 id 所属项目ID * 参数说明 type 要查询的信息类型 0扫描 1上传扫描 * 返回值说明: com.yfd.platform.config.ResponseResult 返回成功或者失败 + * 没有 1 + * 有 0 ***********************************/ @Log(module = "获取异步信息", value = "获取异步信息!") @PostMapping("/obtainInformationAsync") @ApiOperation("获取异步信息") - public ResponseResult obtainInformationAsync(String id, String type) throws Exception { + public ResponseResult obtainInformationAsync(String id) throws Exception { if (StrUtil.isEmpty(id)) { return ResponseResult.error("id为空"); } - if (StrUtil.isEmpty(type)) { - return ResponseResult.error("类型为空"); + JSONObject jsonObject1 = new JSONObject(); + // 生成唯一Key + String asyncKey = taskStatusHolder.specialGenerateKey(id); + // 检查任务是否已存在 + String existingStatus = taskStatusHolder.getStatus(asyncKey); + if ("TASK_NOT_FOUND".equals(existingStatus)) { + + jsonObject1.putOpt("status", "1"); + jsonObject1.putOpt("name", "扫描"); + return ResponseResult.successData(jsonObject1); } - if ("0".equals(type)) { - - - // 生成唯一Key - String asyncKey = taskStatusHolder.specialGenerateKey(id); - - // 检查任务是否已存在 - String existingStatus = taskStatusHolder.getStatus(asyncKey); - if ("TASK_NOT_FOUND".equals(existingStatus)) { - return ResponseResult.success("1"); - } - if ("IN_PROGRESS".equals(existingStatus)) { - return ResponseResult.success("0"); - } else if ("COMPLETED".equals(existingStatus)) { - return ResponseResult.success("专项文档扫描任务已完成!"); - } - - } else { - // 生成唯一Key - String asyncKey = taskStatusHolder.documentUploadKey(id); - - // 检查任务是否已存在 - String existingStatus = taskStatusHolder.getStatus(asyncKey); - if ("TASK_NOT_FOUND".equals(existingStatus)) { - return ResponseResult.success("1"); - } - if ("IN_PROGRESS".equals(existingStatus)) { - return ResponseResult.success("0"); - } else if ("COMPLETED".equals(existingStatus)) { - return ResponseResult.success("专项文档扫描任务已完成!"); - } - + if ("IN_PROGRESS".equals(existingStatus)) { + jsonObject1.putOpt("status", "0"); + jsonObject1.putOpt("name", "扫描"); + return ResponseResult.successData(jsonObject1); + } else if ("COMPLETED".equals(existingStatus)) { + jsonObject1.putOpt("status", "1"); + jsonObject1.putOpt("name", "扫描"); + return ResponseResult.successData(jsonObject1); } + // 上传生成唯一Key + String asyncKeySc = taskStatusHolder.documentUploadKey(id); + // 检查任务是否已存在 + String existingStatusSc = taskStatusHolder.getStatus(asyncKeySc); + if ("TASK_NOT_FOUND".equals(existingStatusSc)) { + jsonObject1.putOpt("status", "1"); + jsonObject1.putOpt("name", "上传"); + return ResponseResult.successData(jsonObject1); + } + if ("IN_PROGRESS".equals(existingStatusSc)) { + jsonObject1.putOpt("status", "0"); + jsonObject1.putOpt("name", "上传"); + return ResponseResult.successData(jsonObject1); + } else if ("COMPLETED".equals(existingStatusSc)) { + jsonObject1.putOpt("status", "1"); + jsonObject1.putOpt("name", "上传"); + return ResponseResult.successData(jsonObject1); + } return null; } + /********************************** * 用途说明: 专项文档管理文档上传接口 * 参数说明 id 所属项目ID @@ -222,43 +231,19 @@ public class NodesController { // 检查任务是否已存在 String existingStatus = taskStatusHolder.getStatus(asyncKey); if ("IN_PROGRESS".equals(existingStatus)) { - return ResponseResult.success("专项文档扫描任务正在处理中!"); + return ResponseResult.success("专项文档上传任务正在处理中!"); } else if ("COMPLETED".equals(existingStatus)) { - return ResponseResult.success("专项文档扫描任务已完成!"); + return ResponseResult.success("专项文档上传任务已完成!"); } // 原子性启动新任务 if (taskStatusHolder.startTaskIfAbsent(asyncKey)) { // 直接异步执行并推送结果 nodesService.documentUploadByIdAsync(id, fileName); - return ResponseResult.success("专项文档扫描任务开始处理!"); + return ResponseResult.success("专项文档上传任务开始处理!"); } else { - return ResponseResult.success("专项文档扫描任务已由其他请求启动"); + return ResponseResult.success("专项文档上传任务已由其他请求启动"); } } -// /********************************** -// * 用途说明: 批量删除专项文档节点 -// * 参数说明 ids 专项文档节点id数组 -// * 返回值说明: com.yfd.platform.config.ResponseResult 返回批量删除成功或失败 -// ***********************************/ -// @Log(module = "专项文档管理", value = "批量删除专项文档节点",type = "1") -// @PostMapping("/deleteNodesByIds") -// @ApiOperation("批量删除专项文档节点") -// @PreAuthorize("@el.check('del:nodes')") -// public ResponseResult deleteSdprojectByIds(@RequestParam String ids) { -// if (StrUtil.isBlank(ids)) { -// return ResponseResult.error("参数为空"); -// } -// String[] splitIds = ids.split(","); -// // 数组转集合 -// List dataset = Arrays.asList(splitIds); -// boolean isOk = nodesService.removeByIds(dataset); -// if (isOk) { -// return ResponseResult.success(); -// } else { -// return ResponseResult.error(); -// } -// } - } diff --git a/java/src/main/java/com/yfd/platform/modules/specialDocument/service/INodesService.java b/java/src/main/java/com/yfd/platform/modules/specialDocument/service/INodesService.java index ab922ee..51657b3 100644 --- a/java/src/main/java/com/yfd/platform/modules/specialDocument/service/INodesService.java +++ b/java/src/main/java/com/yfd/platform/modules/specialDocument/service/INodesService.java @@ -4,6 +4,7 @@ import com.yfd.platform.config.ResponseResult; import com.yfd.platform.modules.specialDocument.domain.Nodes; import com.baomidou.mybatisplus.extension.service.IService; +import java.io.IOException; import java.util.List; import java.util.Map; @@ -61,5 +62,5 @@ public interface INodesService extends IService { * 参数说明 id 所属项目ID * 返回值说明: com.yfd.platform.config.ResponseResult 返回成功或者失败 ***********************************/ - void documentUploadByIdAsync(String id,String fileName); + void documentUploadByIdAsync(String id,String fileName) throws IOException; } diff --git a/java/src/main/java/com/yfd/platform/modules/specialDocument/service/impl/FilesServiceImpl.java b/java/src/main/java/com/yfd/platform/modules/specialDocument/service/impl/FilesServiceImpl.java index e40580d..830fe24 100644 --- a/java/src/main/java/com/yfd/platform/modules/specialDocument/service/impl/FilesServiceImpl.java +++ b/java/src/main/java/com/yfd/platform/modules/specialDocument/service/impl/FilesServiceImpl.java @@ -46,6 +46,7 @@ import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -208,28 +209,32 @@ public class FilesServiceImpl extends ServiceImpl implements String redisKeyff = "sdfiles_" + projectId + "_" + nodeId + "_page_" + currentPage; Object data = redisTemplate.opsForValue().get(redisKeyff); + try { + if (data instanceof IPage) { + @SuppressWarnings("unchecked") + IPage page = (IPage) data; -// if (data != null) { -// ObjectMapper mapper = new ObjectMapper(); -// // 明确指定目标类型为 Page -// return mapper.convertValue(data, new TypeReference>() {}); -// } - - if (data instanceof IPage) { - // 由于启用了类型信息,可以直接强制转换 - @SuppressWarnings("unchecked") - IPage page = (IPage) data; - // 检查 records 是否已正确反序列化 - if (page.getRecords() != null && !page.getRecords().isEmpty() - && page.getRecords().get(0) instanceof Files) { - return page; - } else { - // 处理可能的反序列化异常 - throw new IllegalStateException("反序列化失败,records 类型不正确"); + // 类型校验 + if (isValidPage(page)) { + return page; + } } + } catch (Exception e) { + // 记录异常日志(关键!) + LOGGER.error("反序列化失败,删除缓存: {}", redisKeyff, e); + + // 异步删除缓存,避免阻塞主流程 + CompletableFuture.runAsync(() -> redisTemplate.delete(redisKeyff)); } - return null; + + return null; // 或返回空分页对象 new Page<>(0) } + private boolean isValidPage(IPage page) { + return page.getRecords() != null + && !page.getRecords().isEmpty() + && page.getRecords().get(0) instanceof Files; + } + /*********************************** * 用途说明:新增专项文档管理-文档内容 diff --git a/java/src/main/java/com/yfd/platform/modules/specialDocument/service/impl/NodesServiceImpl.java b/java/src/main/java/com/yfd/platform/modules/specialDocument/service/impl/NodesServiceImpl.java index 3aa50a5..636635b 100644 --- a/java/src/main/java/com/yfd/platform/modules/specialDocument/service/impl/NodesServiceImpl.java +++ b/java/src/main/java/com/yfd/platform/modules/specialDocument/service/impl/NodesServiceImpl.java @@ -8,6 +8,7 @@ import com.amazonaws.util.IOUtils; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.yfd.platform.component.TaskStatusHolder; +import com.yfd.platform.component.WebSocketServer; import com.yfd.platform.config.ResponseResult; import com.yfd.platform.exception.file.InvalidStorageSourceException; import com.yfd.platform.modules.config.model.request.FileListRequest; @@ -544,19 +545,26 @@ public class NodesServiceImpl extends ServiceImpl implements if (nodes == null) { return false; // 节点不存在 } + //递归获取当前节点和它下面的所有节点 + List nodesList = selectChildrenNodes(id, nodes.getProjectId()); + // 提取所有节点的 ID + List nodeIds = nodesList.stream() + .map(Nodes::getId) // 获取每个节点的 ID + .collect(Collectors.toList()); - // 构建节点路径 - List pathNodes = new ArrayList<>(); - Nodes nodesData = nodesMapper.selectById(nodes.getParentId()); - while (nodesData != null) { - pathNodes.add(nodesData.getNodeName()); - if ("00".equals(nodesData.getParentId())) { - break; - } - nodesData = nodesMapper.selectById(nodesData.getParentId()); + // 执行批量删除节点操作 + if (!nodeIds.isEmpty()) { + QueryWrapper deleteWrapper = new QueryWrapper<>(); + deleteWrapper.in("id", nodeIds); // 根据节点 ID 批量删除 + nodesMapper.delete(deleteWrapper); + } + //执行批量删除文件操作 + if (!nodeIds.isEmpty()) { + QueryWrapper deleteWrapper = new QueryWrapper<>(); + deleteWrapper.in("node_id", nodeIds); // 根据节点 ID 批量删除 + deleteWrapper.eq("project_id",nodes.getProjectId()); + filesMapper.delete(deleteWrapper); } - Collections.reverse(pathNodes); - // 删除 sdlocal 中的文件夹 List deleteItemList = new ArrayList<>(); @@ -594,19 +602,7 @@ public class NodesServiceImpl extends ServiceImpl implements } if (deleteSuccessCount >= 1) { - // 递归删除子节点 - deleteChildren(nodes.getId(), nodes.getProjectId()); - - // 删除当前节点的文件 - filesMapper.delete( - new QueryWrapper() - .eq("node_id", nodes.getId()) - .eq("project_id", nodes.getProjectId()) - ); - - // 删除当前节点 - int deleteCount = nodesMapper.deleteById(id); - value = deleteCount > 0; + value = true; } else { value = false; } @@ -614,6 +610,32 @@ public class NodesServiceImpl extends ServiceImpl implements return value; } + /** + * 递归删除子节点 + * parentId 父节点ID + * projectId 项目ID + */ + private List selectChildrenNodes(String parentId, String projectId) { + List nodesList = new ArrayList<>(); + Nodes nodes = nodesMapper.selectById(parentId); + // 查询当前节点的所有子节点 + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("parent_id", parentId); + queryWrapper.eq("project_id", projectId); + List children = nodesMapper.selectList(queryWrapper); + // 将子节点添加到 nodesList 中 + nodesList.addAll(children); + nodesList.add(nodes); + + // 递归删除每个子节点 + for (Nodes child : children) { + // 递归查询子节点的子节点 + List childNodes = selectChildrenNodes(child.getId(), projectId); + // 将子节点的所有子节点添加到 nodesList 中 + nodesList.addAll(childNodes); + } + return nodesList; + } /** * 递归删除子节点 @@ -658,6 +680,8 @@ public class NodesServiceImpl extends ServiceImpl implements String asyncKey = taskStatusHolder.specialGenerateKey(id); // 无论成功失败都标记完成 taskStatusHolder.finishTask(asyncKey); + WebSocketServer.sendMessageTo("专项文档扫描任务处理完成!", "projectId_"+id); + } } @@ -1115,7 +1139,7 @@ public class NodesServiceImpl extends ServiceImpl implements @Override @Async("asyncExecutor") - public void documentUploadByIdAsync(String id, String fileName) { + public void documentUploadByIdAsync(String id, String fileName) throws IOException { try { // 查询本地文件路径根目录(如 E:\yun) @@ -1176,9 +1200,10 @@ public class NodesServiceImpl extends ServiceImpl implements String asyncKey = taskStatusHolder.documentUploadKey(id); // 无论成功失败都标记完成 taskStatusHolder.finishTask(asyncKey); + WebSocketServer.sendMessageTo("专项文档上传任务处理完成!", "projectId_"+id); + } } - //todo 首先得上传到一个临时目录 然后找到这个目录我去解压缩到当前文件夹 解压缩以后 然后开始循环 我通过第一层去查询 如果没有就新增 如果有就循环 看看需不需要覆盖 public static void deleteDirectory(File directory) throws Exception { @@ -1281,11 +1306,8 @@ public class NodesServiceImpl extends ServiceImpl implements //将源目录文件 复制到 目标目录文件 todo这个地方是覆盖 copyWithOverride(sourcePath, targetPath); } - } } - - } else { //如果为空对象不存在 则直接拷贝 String sourcePath = value + sourceFolderPath; @@ -1350,31 +1372,7 @@ public class NodesServiceImpl extends ServiceImpl implements boolean flag = fileService.newFolder(newFolderRequest.getPath(), newFolderRequest.getName()); } } - - - //获取文件列表 - String absolutePath = "/" + project.getProjectName() + "/"; - 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()); - -// //获取数据库父节点为0的文件夹数据 通过所属项目ID和父节点查询 -// List nodesList = nodesMapper.selectList(new LambdaQueryWrapper().eq(Nodes::getParentId, "00").eq(Nodes::getProjectId, project.getId())); -// -// // 步骤 1:提取现有的 nodeName -// Set existingNodeNames = nodesList.stream().map(Nodes::getNodeName).collect(Collectors.toSet()); -// -// // 步骤 2:筛选新增数据 找到需要新增到数据库的文件夹 -// List fileItemNewList = fileItemList.stream().filter(fileItem -> !existingNodeNames.contains(fileItem.getName())).collect(Collectors.toList()); - firstLayerData(fileItemList, project.getId()); + specialScanById(project.getId()); return "扫描完成"; }