代码提交

This commit is contained in:
lilin 2025-05-27 14:52:54 +08:00
parent 83a819b84f
commit 01d1bf1dbf
10 changed files with 245 additions and 206 deletions

View File

@ -21,7 +21,7 @@ public class TaskStatusHolder {
// 生成专项扫描唯一Keyproject_id
public String specialGenerateKey(String id) {
return id + ":";
return id + "扫描:";
}
// 生成专项文档上传唯一Keyproject_id+上传:
public String documentUploadKey(String id) {

View File

@ -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<TsFiles> cachedPage = tsFilesService.getCachedTsFilesPage(taskId, nodeId, currentPage);
if(!StrUtil.isEmpty(id)){
IPage<TsFiles> cachedPage = tsFilesService.getCachedTsFilesPage(taskId, nodeId, currentPage,id);
if (cachedPage != null) {
return ResponseResult.successData(cachedPage);
}
}
Page<TsFiles> 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;

View File

@ -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;

View File

@ -247,7 +247,7 @@ public interface ITsFilesService extends IService<TsFiles> {
Object compareMd5List(List<String> dataset, String nodeId, String taskId);
void automaticFileBackupAsyncByIds(List<String> dataset);
void automaticFileBackupAsyncByIds(List<String> dataset) throws IOException;
IPage<TsFiles> getCachedTsFilesPage(String taskId, String nodeId, int currentPage);
IPage<TsFiles> getCachedTsFilesPage(String taskId, String nodeId, int currentPage,String id);
}

View File

@ -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<TsFilesMapper, TsFiles> impl
private TaskStatusHolder taskStatusHolder;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
private TaskMessage taskMessage;
/**********************************
* 用途说明: 分页查询试验数据管理-文档内容
@ -264,24 +268,32 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
tsFilesPage.setRecords(records); // 同步到 tsFilesPage
int currentPage = (int) page.getCurrent();
// 如果是前五页将结果存入Redis有效期建议30分钟
if (!StrUtil.isEmpty(id)) {
if (currentPage >= 1 && currentPage <= 5) {
String redisKey = "tsfiles_" + taskId + "_" + nodeId + "_page_" + currentPage;
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.delete(redisKey);
}
return tsFilesPage;
}
/**
* Redis缓存获取
*
* @param taskId
* @param nodeId
* @param currentPage
* @return
*/
@Override
public IPage<TsFiles> getCachedTsFilesPage(String taskId, String nodeId, int currentPage) {
String redisKey = "tsfiles_" + taskId + "_" + nodeId + "_page_" + currentPage;
public IPage<TsFiles> 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<TsFilesMapper, TsFiles> impl
}
return null;
}
public void cachePageData(String taskId, String nodeId, int currentPage, Page<TsFiles> pageData) {
String redisKey = "tsfiles_" + taskId + "_" + nodeId + "_page_" + currentPage;
redisTemplate.opsForValue().set(redisKey, pageData, 2, TimeUnit.HOURS);
}
public boolean hasValidExtension(String name, List<SysDictionaryItems> sysDictionaryItems) {
// 如果传入的文件名为空返回 false
@ -407,7 +416,9 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> 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<TsFilesMapper, TsFiles> 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<TsFilesMapper, TsFiles> 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<TsFilesMapper, TsFiles> 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<TsFilesMapper, TsFiles> impl
String asyncKey = taskStatusHolder.generateKey(taskId, nodeId);
// 无论成功失败都标记完成
taskStatusHolder.finishTask(asyncKey);
WebSocketServer.sendMessageTo("文件自动备份完成", "backups");
}
}
@Override
@Async("asyncExecutor")
public void automaticFileBackupAsyncByIds(List<String> dataset) {
public void automaticFileBackupAsyncByIds(List<String> dataset) throws IOException {
try {
// 执行实际备份逻辑
this.automaticFileBackupByIds(dataset);
@ -3386,12 +3390,11 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
String asyncKey = taskStatusHolder.generateKeybyId(dataset);
// 无论成功失败都标记完成
taskStatusHolder.finishTask(asyncKey);
WebSocketServer.sendMessageTo("文件自动备份完成", "backups");
}
}
/**********************************
* 用途说明: 文件自动备份通过节点和任务
* 参数说明 taskId 节点ID

View File

@ -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<TsNodesMapper, TsNodes> impl
//根据ID 查询当前数据
TsNodes tsNodes = tsNodesMapper.selectById(id);
//删除之前 先拼路径 然后删除本地和minio的文件夹 最后删除表结构
//删除当前节点的 文件
//查询所有的子节点
List<TsNodes> tsNodesList = selectChildrentsNodes(tsNodes.getNodeId(), tsNodes.getTaskId());
// 提取所有节点的 ID
List<String> nodeIds = tsNodesList.stream()
.map(TsNodes::getNodeId) // 获取每个节点的 ID
.collect(Collectors.toList());
//查询所有的文件
QueryWrapper<TsFiles> queryWrapper1 = new QueryWrapper<>();
queryWrapper1.eq("node_id", tsNodes.getNodeId());
queryWrapper1.in("node_id", nodeIds);
queryWrapper1.eq("task_id", tsNodes.getTaskId());
List<TsFiles> tsFiles = tsFilesMapper.selectList(queryWrapper1);
//获取所有文件的ID集合
List<String> 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<TsFiles> updateWrapper1 = new LambdaUpdateWrapper<>();
updateWrapper1.in(TsFiles::getId,dataset).isNotNull(TsFiles::getBackupPath).ne(TsFiles::getBackupPath,"").set(TsFiles::getWorkPath, "");
tsFilesMapper.update(null, updateWrapper1);
//批量删除
LambdaQueryWrapper<TsFiles> 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<TsFiles> 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<TsNodesMapper, TsNodes> impl
}
}
private List<TsNodes> selectChildrentsNodes(String parentId, String taskId) {
List<TsNodes> nodesList = new ArrayList<>();
TsNodes tsNodes = tsNodesMapper.selectById(parentId);
// 查询当前节点的所有子节点
QueryWrapper<TsNodes> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("parent_id", parentId); // parent_id = #{parentId}
queryWrapper.eq("task_id", taskId); // parent_id = #{parentId}
List<TsNodes> children = tsNodesMapper.selectList(queryWrapper);
// 将子节点添加到 nodesList
nodesList.addAll(children);
nodesList.add(tsNodes);
// 递归删除每个子节点
for (TsNodes child : children) {
// 递归查询子节点的子节点
List<TsNodes> childNodes = selectChildrentsNodes(child.getNodeId(), taskId);
// 将子节点的所有子节点添加到 nodesList
nodesList.addAll(childNodes);
}
return nodesList;
}
/**
* 递归删除子节点
*
@ -646,6 +698,7 @@ public class TsNodesServiceImpl extends ServiceImpl<TsNodesMapper, TsNodes> impl
String asyncKey = taskStatusHolder.testDatascanKey(id);
// 无论成功失败都标记完成
taskStatusHolder.finishTask(asyncKey);
WebSocketServer.sendMessageTo("试验数据扫描接口完成", "taskId_" + id);
}
}
@ -653,23 +706,7 @@ public class TsNodesServiceImpl extends ServiceImpl<TsNodesMapper, TsNodes> impl
//查询试验任务信息
TsTask tsTask = tsTaskMapper.selectById(id);
//文件的第一层是节点 下面的层级是文件夹
//获取文件列表
String absolutePath = "/" + tsTask.getTaskName() + "/";
FileListRequest fileListRequest = buildFileRequest(absolutePath);
@ -749,7 +786,7 @@ public class TsNodesServiceImpl extends ServiceImpl<TsNodesMapper, TsNodes> 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<File> allSubDirs = new ArrayList<>();
@ -855,7 +892,7 @@ public class TsNodesServiceImpl extends ServiceImpl<TsNodesMapper, TsNodes> impl
// 记录开始时间
long startTimeFiles = System.currentTimeMillis();
// 执行更新操作 taskId, String nodeId
int affectedLevelFilesRows = tsFilesMapper.updateParentIdByPathHierarchy(taskId,nodeId);
int affectedLevelFilesRows = tsFilesMapper.updateParentIdByPathHierarchy(taskId, nodeId);
// 记录结束时间
long endTimeFiles = System.currentTimeMillis();
// 计算耗时

View File

@ -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;
@ -103,7 +106,7 @@ public class NodesController {
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("类型为空");
}
if ("0".equals(type)) {
JSONObject jsonObject1 = new JSONObject();
// 生成唯一Key
String asyncKey = taskStatusHolder.specialGenerateKey(id);
// 检查任务是否已存在
String existingStatus = taskStatusHolder.getStatus(asyncKey);
if ("TASK_NOT_FOUND".equals(existingStatus)) {
return ResponseResult.success("1");
jsonObject1.putOpt("status", "1");
jsonObject1.putOpt("name", "扫描");
return ResponseResult.successData(jsonObject1);
}
if ("IN_PROGRESS".equals(existingStatus)) {
return ResponseResult.success("0");
jsonObject1.putOpt("status", "0");
jsonObject1.putOpt("name", "扫描");
return ResponseResult.successData(jsonObject1);
} else if ("COMPLETED".equals(existingStatus)) {
return ResponseResult.success("专项文档扫描任务已完成!");
jsonObject1.putOpt("status", "1");
jsonObject1.putOpt("name", "扫描");
return ResponseResult.successData(jsonObject1);
}
} else {
// 生成唯一Key
String asyncKey = taskStatusHolder.documentUploadKey(id);
// 上传生成唯一Key
String asyncKeySc = 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("专项文档扫描任务已完成!");
}
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<String> dataset = Arrays.asList(splitIds);
// boolean isOk = nodesService.removeByIds(dataset);
// if (isOk) {
// return ResponseResult.success();
// } else {
// return ResponseResult.error();
// }
// }
}

View File

@ -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<Nodes> {
* 参数说明 id 所属项目ID
* 返回值说明: com.yfd.platform.config.ResponseResult 返回成功或者失败
***********************************/
void documentUploadByIdAsync(String id,String fileName);
void documentUploadByIdAsync(String id,String fileName) throws IOException;
}

View File

@ -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,29 +209,33 @@ public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements
String redisKeyff = "sdfiles_" + projectId + "_" + nodeId + "_page_" + currentPage;
Object data = redisTemplate.opsForValue().get(redisKeyff);
// if (data != null) {
// ObjectMapper mapper = new ObjectMapper();
// // 明确指定目标类型为 Page<Files>
// return mapper.convertValue(data, new TypeReference<Page<Files>>() {});
// }
try {
if (data instanceof IPage<?>) {
// 由于启用了类型信息可以直接强制转换
@SuppressWarnings("unchecked")
IPage<Files> page = (IPage<Files>) data;
// 检查 records 是否已正确反序列化
if (page.getRecords() != null && !page.getRecords().isEmpty()
&& page.getRecords().get(0) instanceof Files) {
// 类型校验
if (isValidPage(page)) {
return page;
} else {
// 处理可能的反序列化异常
throw new IllegalStateException("反序列化失败records 类型不正确");
}
}
return null;
} catch (Exception e) {
// 记录异常日志关键
LOGGER.error("反序列化失败,删除缓存: {}", redisKeyff, e);
// 异步删除缓存避免阻塞主流程
CompletableFuture.runAsync(() -> redisTemplate.delete(redisKeyff));
}
return null; // 或返回空分页对象 new Page<>(0)
}
private boolean isValidPage(IPage<Files> page) {
return page.getRecords() != null
&& !page.getRecords().isEmpty()
&& page.getRecords().get(0) instanceof Files;
}
/***********************************
* 用途说明新增专项文档管理-文档内容
* 参数说明

View File

@ -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<NodesMapper, Nodes> implements
if (nodes == null) {
return false; // 节点不存在
}
//递归获取当前节点和它下面的所有节点
List<Nodes> nodesList = selectChildrenNodes(id, nodes.getProjectId());
// 提取所有节点的 ID
List<String> nodeIds = nodesList.stream()
.map(Nodes::getId) // 获取每个节点的 ID
.collect(Collectors.toList());
// 构建节点路径
List<String> pathNodes = new ArrayList<>();
Nodes nodesData = nodesMapper.selectById(nodes.getParentId());
while (nodesData != null) {
pathNodes.add(nodesData.getNodeName());
if ("00".equals(nodesData.getParentId())) {
break;
// 执行批量删除节点操作
if (!nodeIds.isEmpty()) {
QueryWrapper<Nodes> deleteWrapper = new QueryWrapper<>();
deleteWrapper.in("id", nodeIds); // 根据节点 ID 批量删除
nodesMapper.delete(deleteWrapper);
}
nodesData = nodesMapper.selectById(nodesData.getParentId());
//执行批量删除文件操作
if (!nodeIds.isEmpty()) {
QueryWrapper<Files> deleteWrapper = new QueryWrapper<>();
deleteWrapper.in("node_id", nodeIds); // 根据节点 ID 批量删除
deleteWrapper.eq("project_id",nodes.getProjectId());
filesMapper.delete(deleteWrapper);
}
Collections.reverse(pathNodes);
// 删除 sdlocal 中的文件夹
List<BatchDeleteRequest.DeleteItem> deleteItemList = new ArrayList<>();
@ -594,19 +602,7 @@ public class NodesServiceImpl extends ServiceImpl<NodesMapper, Nodes> implements
}
if (deleteSuccessCount >= 1) {
// 递归删除子节点
deleteChildren(nodes.getId(), nodes.getProjectId());
// 删除当前节点的文件
filesMapper.delete(
new QueryWrapper<Files>()
.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<NodesMapper, Nodes> implements
return value;
}
/**
* 递归删除子节点
* parentId 父节点ID
* projectId 项目ID
*/
private List<Nodes> selectChildrenNodes(String parentId, String projectId) {
List<Nodes> nodesList = new ArrayList<>();
Nodes nodes = nodesMapper.selectById(parentId);
// 查询当前节点的所有子节点
QueryWrapper<Nodes> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("parent_id", parentId);
queryWrapper.eq("project_id", projectId);
List<Nodes> children = nodesMapper.selectList(queryWrapper);
// 将子节点添加到 nodesList
nodesList.addAll(children);
nodesList.add(nodes);
// 递归删除每个子节点
for (Nodes child : children) {
// 递归查询子节点的子节点
List<Nodes> childNodes = selectChildrenNodes(child.getId(), projectId);
// 将子节点的所有子节点添加到 nodesList
nodesList.addAll(childNodes);
}
return nodesList;
}
/**
* 递归删除子节点
@ -658,6 +680,8 @@ public class NodesServiceImpl extends ServiceImpl<NodesMapper, Nodes> implements
String asyncKey = taskStatusHolder.specialGenerateKey(id);
// 无论成功失败都标记完成
taskStatusHolder.finishTask(asyncKey);
WebSocketServer.sendMessageTo("专项文档扫描任务处理完成!", "projectId_"+id);
}
}
@ -1115,7 +1139,7 @@ public class NodesServiceImpl extends ServiceImpl<NodesMapper, Nodes> 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<NodesMapper, Nodes> 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<NodesMapper, Nodes> implements
//将源目录文件 复制到 目标目录文件 todo这个地方是覆盖
copyWithOverride(sourcePath, targetPath);
}
}
}
} else {
//如果为空对象不存在 则直接拷贝
String sourcePath = value + sourceFolderPath;
@ -1350,31 +1372,7 @@ public class NodesServiceImpl extends ServiceImpl<NodesMapper, Nodes> 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<FileItemResult> fileItemList = fileService.fileList(fileListRequest.getPath());
// //获取数据库父节点为0的文件夹数据 通过所属项目ID和父节点查询
// List<Nodes> nodesList = nodesMapper.selectList(new LambdaQueryWrapper<Nodes>().eq(Nodes::getParentId, "00").eq(Nodes::getProjectId, project.getId()));
//
// // 步骤 1提取现有的 nodeName
// Set<String> existingNodeNames = nodesList.stream().map(Nodes::getNodeName).collect(Collectors.toSet());
//
// // 步骤 2筛选新增数据 找到需要新增到数据库的文件夹
// List<FileItemResult> fileItemNewList = fileItemList.stream().filter(fileItem -> !existingNodeNames.contains(fileItem.getName())).collect(Collectors.toList());
firstLayerData(fileItemList, project.getId());
specialScanById(project.getId());
return "扫描完成";
}