代码提交
This commit is contained in:
parent
83a819b84f
commit
01d1bf1dbf
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
// 计算耗时
|
||||
|
@ -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();
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
/***********************************
|
||||
* 用途说明:新增专项文档管理-文档内容
|
||||
* 参数说明
|
||||
|
@ -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 "扫描完成";
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user