解压缩异步以及全属性查询
This commit is contained in:
parent
d3c8bde081
commit
32b34fa755
@ -0,0 +1,35 @@
|
||||
package com.yfd.platform.component;
|
||||
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@Component
|
||||
public class ExtractTaskStatus {
|
||||
|
||||
private final ConcurrentHashMap<String, String> extractTaskStatusMap = new ConcurrentHashMap<>();
|
||||
// 存入方法
|
||||
public void putTaskStatus(String key, String value) {
|
||||
extractTaskStatusMap.put(key, value);
|
||||
}
|
||||
|
||||
// 通过value获取key的方法
|
||||
public Set<String> getKeysByValue(String value) {
|
||||
Set<String> matchingKeys = new HashSet<>();
|
||||
for (String key : extractTaskStatusMap.keySet()) {
|
||||
if (extractTaskStatusMap.get(key).equals(value)) {
|
||||
matchingKeys.add(key);
|
||||
}
|
||||
}
|
||||
return matchingKeys;
|
||||
}
|
||||
|
||||
|
||||
// 通过key删除任务
|
||||
public void removeTask(String key) {
|
||||
extractTaskStatusMap.remove(key);
|
||||
}
|
||||
}
|
@ -2,7 +2,10 @@ package com.yfd.platform.component;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Component
|
||||
@ -14,6 +17,10 @@ public class TaskStatusHolder {
|
||||
public String generateKey(String taskId, String nodeId) {
|
||||
return taskId + ":" + nodeId;
|
||||
}
|
||||
// 生成唯一解压缩的Key:taskId + id
|
||||
public String extractKey(String id) {
|
||||
return id;
|
||||
}
|
||||
|
||||
// 生成专项扫描唯一Key:project_id
|
||||
public String specialGenerateKey(String id) {
|
||||
@ -47,4 +54,17 @@ public class TaskStatusHolder {
|
||||
public String getValue(String key) {
|
||||
return taskStatusMap.get(key);
|
||||
}
|
||||
|
||||
// 通过value获取所有对应的key
|
||||
public Set<String> findKeysByValue(String value) {
|
||||
Set<String> result = new HashSet<>();
|
||||
|
||||
for (Map.Entry<String, String> entry : taskStatusMap.entrySet()) {
|
||||
if (entry.getValue().equals(value)) {
|
||||
result.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -7,11 +7,14 @@ 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;
|
||||
import com.yfd.platform.component.ExtractTaskStatus;
|
||||
import com.yfd.platform.component.TaskStatusHolder;
|
||||
import com.yfd.platform.config.ResponseResult;
|
||||
import com.yfd.platform.modules.experimentalData.domain.*;
|
||||
import com.yfd.platform.modules.experimentalData.service.ITsFilesService;
|
||||
import com.yfd.platform.modules.experimentalData.service.ITsTaskService;
|
||||
import com.yfd.platform.modules.storage.model.result.FileItemResult;
|
||||
import com.yfd.platform.utils.TableNameContextHolder;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
@ -19,9 +22,7 @@ import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
@ -44,6 +45,9 @@ public class TsFilesController {
|
||||
@Autowired
|
||||
private TaskStatusHolder taskStatusHolder;
|
||||
|
||||
@Resource
|
||||
private ExtractTaskStatus extractTaskStatus;
|
||||
|
||||
/**********************************
|
||||
* 用途说明: 分页查询试验数据管理-文档内容
|
||||
* 参数说明
|
||||
@ -66,7 +70,7 @@ public class TsFilesController {
|
||||
//分页查询
|
||||
int currentPage = (int) page.getCurrent();
|
||||
// 先尝试从缓存获取 如果搜索条件为空 从Redis获取
|
||||
if(StrUtil.isBlank(fileName)&&StrUtil.isBlank(keywords) &&StrUtil.isBlank(startDate) &&StrUtil.isBlank(endDate)&& !"00".equals(id)) {
|
||||
if (StrUtil.isBlank(fileName) && StrUtil.isBlank(keywords) && StrUtil.isBlank(startDate) && StrUtil.isBlank(endDate) && !"00".equals(id)) {
|
||||
if (!StrUtil.isEmpty(id)) {
|
||||
IPage<TsFiles> cachedPage = tsFilesService.getCachedTsFilesPage(taskId, nodeId, currentPage, id);
|
||||
if (cachedPage != null) {
|
||||
@ -167,12 +171,12 @@ public class TsFilesController {
|
||||
@PostMapping("/deleteTsFilesById")
|
||||
@ApiOperation("根据ID删除试验数据管理文档内容")
|
||||
@PreAuthorize("@el.check('del:tsFiles')")
|
||||
public ResponseResult deleteTsFilesById(@RequestParam String id, @RequestParam String type,@RequestParam String taskId) {
|
||||
public ResponseResult deleteTsFilesById(@RequestParam String id, @RequestParam String type, @RequestParam String taskId) {
|
||||
if (StrUtil.isBlank(id) || StrUtil.isBlank(taskId)) {
|
||||
return ResponseResult.error("参数为空");
|
||||
}
|
||||
List<String> dataset = Arrays.asList(id);
|
||||
return ResponseResult.success(tsFilesService.deleteTsFilesByIds(dataset, type,taskId));
|
||||
return ResponseResult.success(tsFilesService.deleteTsFilesByIds(dataset, type, taskId));
|
||||
}
|
||||
|
||||
/**********************************
|
||||
@ -185,14 +189,14 @@ public class TsFilesController {
|
||||
@PostMapping("/deleteTsFilesByIds")
|
||||
@ApiOperation("批量删除试验数据管理文档内容")
|
||||
@PreAuthorize("@el.check('del:tsFiles')")
|
||||
public ResponseResult deleteTsFilesByIds(@RequestParam String ids, @RequestParam String type,@RequestParam String taskId) {
|
||||
public ResponseResult deleteTsFilesByIds(@RequestParam String ids, @RequestParam String type, @RequestParam String taskId) {
|
||||
if (StrUtil.isBlank(ids) || StrUtil.isBlank(taskId)) {
|
||||
return ResponseResult.error("参数为空");
|
||||
}
|
||||
String[] splitIds = ids.split(",");
|
||||
// 数组转集合
|
||||
List<String> dataset = Arrays.asList(splitIds);
|
||||
return ResponseResult.success(tsFilesService.deleteTsFilesByIds(dataset, type,taskId));
|
||||
return ResponseResult.success(tsFilesService.deleteTsFilesByIds(dataset, type, taskId));
|
||||
}
|
||||
|
||||
/**************************压缩 解压缩********************************/
|
||||
@ -211,13 +215,13 @@ public class TsFilesController {
|
||||
@Log(module = "实验数据管理", value = "压缩文件夹接口!")
|
||||
@PostMapping("/compress")
|
||||
@ApiOperation("压缩文件夹接口")
|
||||
public ResponseResult compressFolder(String ids, String compressedFormat, String compressedName, String compressedPath, String covered, String parentId, String path,String taskId) {
|
||||
public ResponseResult compressFolder(String ids, String compressedFormat, String compressedName, String compressedPath, String covered, String parentId, String path, String taskId) {
|
||||
try {
|
||||
if (StrUtil.isBlank(ids) && StrUtil.isBlank(compressedFormat) && StrUtil.isBlank(compressedName) && StrUtil.isBlank(compressedPath) && StrUtil.isBlank(path) && StrUtil.isBlank(taskId)) {
|
||||
return ResponseResult.error("参数为空");
|
||||
}
|
||||
|
||||
return ResponseResult.success(tsFilesService.compressFolder(ids, compressedFormat, compressedName, compressedPath, covered, parentId, path,taskId));
|
||||
return ResponseResult.success(tsFilesService.compressFolder(ids, compressedFormat, compressedName, compressedPath, covered, parentId, path, taskId));
|
||||
} catch (Exception e) {
|
||||
System.out.print("压缩异常原因" + e);
|
||||
return ResponseResult.error("压缩失败");
|
||||
@ -235,18 +239,51 @@ public class TsFilesController {
|
||||
@Log(module = "实验数据管理", value = "解压缩接口!")
|
||||
@PostMapping("/decompression")
|
||||
@ApiOperation("解压缩接口")
|
||||
public ResponseResult decompressionFolder(String id, String decompressionPath, String parentId, String path,String taskId) {
|
||||
public ResponseResult decompressionFolder(String id, String decompressionPath, String parentId, String path, String taskId) {
|
||||
try {
|
||||
if (StrUtil.isBlank(id)|| StrUtil.isBlank(taskId)) {
|
||||
if (StrUtil.isBlank(id) || StrUtil.isBlank(taskId)) {
|
||||
return ResponseResult.error("参数为空");
|
||||
}
|
||||
return ResponseResult.success(tsFilesService.decompressionFolder(id, decompressionPath, parentId, path,taskId));
|
||||
extractTaskStatus.putTaskStatus(id,taskId);
|
||||
|
||||
// 生成唯一Key
|
||||
String extractKey = taskStatusHolder.extractKey(taskId);
|
||||
|
||||
// 检查任务是否已存在
|
||||
String existingStatus = taskStatusHolder.getStatus(extractKey);
|
||||
if ("IN_PROGRESS".equals(existingStatus)) {
|
||||
return ResponseResult.success("解压缩任务正在处理中!");
|
||||
} else if ("COMPLETED".equals(existingStatus)) {
|
||||
return ResponseResult.success("解压缩任务已完成!");
|
||||
}
|
||||
// 原子性启动新任务
|
||||
if (taskStatusHolder.startTaskIfAbsent(extractKey)) {
|
||||
// 直接异步执行并推送结果
|
||||
tsFilesService.decompressionFolderAsync(id, decompressionPath, parentId, path, taskId);
|
||||
return ResponseResult.success("解压缩任务开始处理!");
|
||||
} else {
|
||||
return ResponseResult.success("解压缩任务已由其他请求启动");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.print("解压缩异常原因" + e);
|
||||
return ResponseResult.error("解压缩失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************
|
||||
* 用途说明: 获取解压异步信息
|
||||
* 参数说明 taskId 所属项目ID
|
||||
* 参数说明 nodeId 所属节点ID
|
||||
* 返回值说明: com.yfd.platform.config.ResponseResult 返回成功或者失败
|
||||
***********************************/
|
||||
@Log(module = "根据项目和节点获取异步信息", value = "根据项目和节点获取异步信息!")
|
||||
@PostMapping("/decompressionFolderData")
|
||||
@ApiOperation("获取解压异步信息")
|
||||
public ResponseResult decompressionFolderData( String taskId) throws Exception {
|
||||
return ResponseResult.successData(tsFilesService.decompressionFolderData(taskId));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 移动文件或文件夹
|
||||
* 参数说明 newPath 新路径
|
||||
@ -617,7 +654,7 @@ public class TsFilesController {
|
||||
@Log(module = "实验数据管理", value = "文件自动备份!")
|
||||
@PostMapping("/automaticFileBackupByIds")
|
||||
@ApiOperation("自动备份本地文件到备份空间通过ID")
|
||||
public ResponseResult automaticFileBackupByIds(String id,String taskId, String nodeId) throws IOException {
|
||||
public ResponseResult automaticFileBackupByIds(String id, String taskId, String nodeId) throws IOException {
|
||||
if (StrUtil.isEmpty(id)) {
|
||||
return ResponseResult.error("参数为空");
|
||||
}
|
||||
@ -636,7 +673,7 @@ public class TsFilesController {
|
||||
// 原子性启动新任务
|
||||
if (taskStatusHolder.startTaskIfAbsent(asyncKey)) {
|
||||
// 直接异步执行并推送结果
|
||||
tsFilesService.automaticFileBackupAsyncByIds(dataset,taskId,nodeId);
|
||||
tsFilesService.automaticFileBackupAsyncByIds(dataset, taskId, nodeId);
|
||||
return ResponseResult.success("任务开始处理!");
|
||||
} else {
|
||||
return ResponseResult.success("任务已由其他请求启动");
|
||||
@ -654,12 +691,12 @@ public class TsFilesController {
|
||||
@Log(module = "实验数据管理", value = "实时获取轨迹数据!")
|
||||
@PostMapping("/startSimpleNavi")
|
||||
@ApiOperation("实时获取轨迹数据")
|
||||
public ResponseResult startSimpleNavi(String id, int samTimes, String token,String taskId) {
|
||||
public ResponseResult startSimpleNavi(String id, int samTimes, String token, String taskId) {
|
||||
try {
|
||||
// 使用线程池异步执行任务
|
||||
CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
tsFilesService.batchSendNaviOutDataJob(id, samTimes, token,taskId);
|
||||
tsFilesService.batchSendNaviOutDataJob(id, samTimes, token, taskId);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@ -694,7 +731,7 @@ public class TsFilesController {
|
||||
@Log(module = "实验数据管理", value = "查询文件内容!")
|
||||
@GetMapping("/api/files/content")
|
||||
@ApiOperation("查询文件内容")
|
||||
public ResponseResult getFileContent(@RequestParam String id,String taskId) {
|
||||
public ResponseResult getFileContent(@RequestParam String id, String taskId) {
|
||||
try {
|
||||
if (StrUtil.isBlank(id) && StrUtil.isBlank(taskId)) {
|
||||
return ResponseResult.error("参数为空");
|
||||
@ -715,7 +752,7 @@ public class TsFilesController {
|
||||
@Log(module = "实验数据管理", value = "保存文件内容!")
|
||||
@PostMapping("/save/files/content")
|
||||
@ApiOperation("保存文件内容")
|
||||
public ResponseResult saveFileContent(String id, String content,String taskId) {
|
||||
public ResponseResult saveFileContent(String id, String content, String taskId) {
|
||||
try {
|
||||
if (StrUtil.isBlank(id) && StrUtil.isBlank(content) && StrUtil.isBlank(taskId)) {
|
||||
return ResponseResult.error("参数为空");
|
||||
@ -737,7 +774,7 @@ public class TsFilesController {
|
||||
@PostMapping("/batchModify")
|
||||
@ApiOperation("批量修改文件中多行多列的内容")
|
||||
public ResponseResult batchModifyFile(@RequestBody BatchModifyRequest request) throws IOException {
|
||||
tsFilesService.batchUpdateFile(request.getId(), request.getModifications(),request.getTaskId());
|
||||
tsFilesService.batchUpdateFile(request.getId(), request.getModifications(), request.getTaskId());
|
||||
return ResponseResult.success("文件保存成功");
|
||||
}
|
||||
|
||||
@ -749,12 +786,12 @@ public class TsFilesController {
|
||||
@Log(module = "实验数据管理", value = "获取文件url!")
|
||||
@PostMapping("/obtainUrl")
|
||||
@ApiOperation("获取文件url")
|
||||
public ResponseResult obtainUrl(String id, String type,String taskId) {
|
||||
public ResponseResult obtainUrl(String id, String type, String taskId) {
|
||||
if (StrUtil.isBlank(id) && StrUtil.isBlank(type) && StrUtil.isBlank(type)) {
|
||||
return ResponseResult.error("参数为空");
|
||||
}
|
||||
//查询本地树和minio树
|
||||
FileItemResult fileItemResult = tsFilesService.obtainUrl(id, type,taskId);
|
||||
FileItemResult fileItemResult = tsFilesService.obtainUrl(id, type, taskId);
|
||||
return ResponseResult.successData(fileItemResult);
|
||||
}
|
||||
}
|
||||
|
@ -44,6 +44,7 @@ public class TsTaskController {
|
||||
/**********************************
|
||||
* 用途说明: 分页查询试验数据管理-试验任务管理
|
||||
* 参数说明
|
||||
* keyword 全属性搜索
|
||||
* taskName 任务名称
|
||||
* startDate (开始日期)
|
||||
* endDate (结束日期)
|
||||
@ -62,42 +63,29 @@ public class TsTaskController {
|
||||
@GetMapping("/page")
|
||||
@ApiOperation("分页查询试验数据管理试验任务管理")
|
||||
@PreAuthorize("@el.check('select:tsTask')")
|
||||
public ResponseResult getTsTaskPage(String taskName, String startDate, String endDate, String taskPlace, String taskPerson, String taskCode, String taskType, String carrierName, String deviceCode, String testDescribe, String sensorDescribe, Page<TsTask> page, String attributeContentJson) {
|
||||
// 双重解码处理
|
||||
if (attributeContentJson != null) {
|
||||
try {
|
||||
// 第二次解码:%5B → [
|
||||
attributeContentJson = URLDecoder.decode(attributeContentJson, StandardCharsets.UTF_8.name());
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return ResponseResult.error("参数解码错误");
|
||||
}
|
||||
public ResponseResult getTsTaskPage(String keyword,
|
||||
String startDate,
|
||||
String endDate,
|
||||
String fieldName,
|
||||
Page<TsTask> page,
|
||||
String attributeContentJson) {
|
||||
//字段名称
|
||||
List<String> fieldNameData = new ArrayList<>();
|
||||
if (StrUtil.isNotEmpty(fieldName)) {
|
||||
String[] splitIds = fieldName.split(",");
|
||||
// 数组转集合
|
||||
fieldNameData = Arrays.asList(splitIds);
|
||||
}
|
||||
|
||||
// 将JSON字符串转换为List<Map<String, String>>
|
||||
List<Map<String, String>> attributeContent = null;
|
||||
if (StringUtils.isNotEmpty(attributeContentJson)) {
|
||||
try {
|
||||
// 使用 TypeReference 指定精确类型
|
||||
attributeContent = JSON.parseObject(
|
||||
attributeContentJson,
|
||||
new TypeReference<List<Map<String, String>>>() {
|
||||
}
|
||||
);
|
||||
|
||||
// 遍历并移除空值字段
|
||||
if (attributeContent != null) {
|
||||
for (Map<String, String> item : attributeContent) {
|
||||
// 遍历 Map,移除值为空的键值对
|
||||
item.entrySet().removeIf(entry -> entry.getValue() == null || entry.getValue().isEmpty());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return ResponseResult.error("属性参数格式错误");
|
||||
}
|
||||
//自定义属性
|
||||
List<String> attributeContent = new ArrayList<>();
|
||||
if (StrUtil.isNotEmpty(attributeContentJson)) {
|
||||
String[] splitIds = attributeContentJson.split(",");
|
||||
// 数组转集合
|
||||
attributeContent = Arrays.asList(splitIds);
|
||||
}
|
||||
|
||||
//分页查询
|
||||
Page<TsTask> sdProjectPage = tsTaskService.getTsTaskPage(taskName, startDate, endDate, taskPlace, taskPerson, taskCode, taskType, carrierName, deviceCode, testDescribe, sensorDescribe, page, attributeContent);
|
||||
Page<TsTask> sdProjectPage = tsTaskService.getTsTaskPage(keyword, startDate, endDate, fieldNameData, page, attributeContent);
|
||||
return ResponseResult.successData(sdProjectPage);
|
||||
}
|
||||
|
||||
|
@ -252,4 +252,8 @@ public interface ITsFilesService extends IService<TsFiles> {
|
||||
IPage<TsFiles> getCachedTsFilesPage(String taskId, String nodeId, int currentPage,String id);
|
||||
|
||||
int countFiles(String id);
|
||||
|
||||
void decompressionFolderAsync(String id, String decompressionPath, String parentId, String path, String taskId) throws IOException;
|
||||
|
||||
Object decompressionFolderData(String taskId);
|
||||
}
|
||||
|
@ -36,7 +36,8 @@ public interface ITsTaskService extends IService<TsTask> {
|
||||
* pageNum 当前页
|
||||
* 返回值说明: com.yfd.platform.config.ResponseResult 返回分页查询结果
|
||||
***********************************/
|
||||
Page<TsTask> getTsTaskPage(String taskName, String startDate, String endDate, String taskPlace, String taskPerson, String taskCode, String taskType,String carrierName,String deviceCode,String testDescribe,String sensorDescribe, Page<TsTask> page,List<Map<String, String>> attributeContent);
|
||||
//Page<TsTask> getTsTaskPage(String taskName, String startDate, String endDate, String taskPlace, String taskPerson, String taskCode, String taskType,String carrierName,String deviceCode,String testDescribe,String sensorDescribe, Page<TsTask> page,List<Map<String, String>> attributeContent);
|
||||
Page<TsTask> getTsTaskPage(String keyword, String startDate, String endDate, List<String> fieldNameData, Page<TsTask> page, List<String> attributeContent);
|
||||
|
||||
/***********************************
|
||||
* 用途说明:新增试验数据管理-试验任务管理
|
||||
@ -68,4 +69,5 @@ public interface ITsTaskService extends IService<TsTask> {
|
||||
Object confirmDeleteTask(List<String> dataset);
|
||||
|
||||
List<TsTask> listTsTask();
|
||||
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.opencsv.CSVReader;
|
||||
import com.opencsv.CSVWriter;
|
||||
import com.opencsv.exceptions.CsvValidationException;
|
||||
import com.yfd.platform.component.ExtractTaskStatus;
|
||||
import com.yfd.platform.component.ServerSendEventServer;
|
||||
import com.yfd.platform.component.TaskStatusHolder;
|
||||
import com.yfd.platform.component.WebSocketServer;
|
||||
@ -134,6 +135,8 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
||||
@Autowired
|
||||
private TaskStatusHolder taskStatusHolder;
|
||||
|
||||
@Autowired
|
||||
private ExtractTaskStatus extractTaskStatus;
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
@ -330,6 +333,7 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
||||
}
|
||||
|
||||
|
||||
|
||||
private boolean isValidPage(IPage<TsFiles> page) {
|
||||
return page.getRecords() != null
|
||||
&& !page.getRecords().isEmpty()
|
||||
@ -1124,17 +1128,6 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
||||
updateWrapper1.eq(TsFiles::getParentId, folderId).set(TsFiles::getWorkPath, "");
|
||||
int updatedCount = tsFilesMapper.update(null, updateWrapper1);
|
||||
LOGGER.info("本地更新操作:将 {} 条记录的 work_path 设置为空", updatedCount);
|
||||
|
||||
|
||||
// 批量删除备份路径和工作路径为空的数据 条件是父ID等于folderId
|
||||
LambdaQueryWrapper<TsFiles> deleteWrapper = new LambdaQueryWrapper<>();
|
||||
deleteWrapper.eq(TsFiles::getParentId, folderId)
|
||||
.and(wrapper -> wrapper.isNull(TsFiles::getBackupPath).or().eq(TsFiles::getBackupPath, ""))
|
||||
.and(wrapper -> wrapper.isNull(TsFiles::getWorkPath).or().eq(TsFiles::getWorkPath, ""));
|
||||
int deletedCounts = tsFilesMapper.delete(deleteWrapper);
|
||||
LOGGER.info("本地删除操作:成功删除了 {} 条 work_path 和 backup_path 都为空的记录", deletedCounts);
|
||||
deletedCount += deletedCounts;
|
||||
|
||||
} else {
|
||||
//删除minio的时候判断本地路径是否为空 如果为空直接删除 如果不为空把BackupPath修改成空
|
||||
//如果是minio 先先吧所有的backup_path修改成空 然后删除所有work_path和backup_path为空的数据
|
||||
@ -1142,16 +1135,6 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
||||
updateWrapper1.eq(TsFiles::getParentId, folderId).set(TsFiles::getBackupPath, "");
|
||||
int updatedCount = tsFilesMapper.update(null, updateWrapper1);
|
||||
LOGGER.info("minio更新操作:将 {} 条记录的 work_path 设置为空", updatedCount);
|
||||
|
||||
|
||||
// 批量删除备份路径和工作路径为空的数据 条件是父ID等于folderId
|
||||
LambdaQueryWrapper<TsFiles> deleteWrapper = new LambdaQueryWrapper<>();
|
||||
deleteWrapper.eq(TsFiles::getParentId, folderId)
|
||||
.and(wrapper -> wrapper.isNull(TsFiles::getBackupPath).or().eq(TsFiles::getBackupPath, ""))
|
||||
.and(wrapper -> wrapper.isNull(TsFiles::getWorkPath).or().eq(TsFiles::getWorkPath, ""));
|
||||
int deletedCounts = tsFilesMapper.delete(deleteWrapper);
|
||||
LOGGER.info("minio删除操作:成功删除了 {} 条 work_path 和 backup_path 都为空的记录", deletedCounts);
|
||||
deletedCount += deletedCounts;
|
||||
}
|
||||
|
||||
|
||||
@ -1166,7 +1149,14 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 批量删除备份路径和工作路径为空的数据 条件是父ID等于folderId
|
||||
LambdaQueryWrapper<TsFiles> deleteWrapper = new LambdaQueryWrapper<>();
|
||||
deleteWrapper.eq(TsFiles::getParentId, folderId)
|
||||
.and(wrapper -> wrapper.isNull(TsFiles::getBackupPath).or().eq(TsFiles::getBackupPath, ""))
|
||||
.and(wrapper -> wrapper.isNull(TsFiles::getWorkPath).or().eq(TsFiles::getWorkPath, ""));
|
||||
int deletedCounts = tsFilesMapper.delete(deleteWrapper);
|
||||
LOGGER.info("minio删除操作:成功删除了 {} 条 work_path 和 backup_path 都为空的记录", deletedCounts);
|
||||
deletedCount += deletedCounts;
|
||||
// 递归删除子文件
|
||||
// for (TsFiles subFile : subFiles) {
|
||||
// // 递归调用删除子文件的逻辑
|
||||
@ -1897,6 +1887,63 @@ public class TsFilesServiceImpl extends ServiceImpl<TsFilesMapper, TsFiles> impl
|
||||
|
||||
/*************************************解压缩*******************************************/
|
||||
|
||||
@Override
|
||||
public void decompressionFolderAsync(String id, String decompressionPath, String parentId, String path, String taskId) throws IOException {
|
||||
String tsfilesName = null;
|
||||
try {
|
||||
TsTask tsTask = tsTaskMapper.selectById(taskId);
|
||||
TableNameContextHolder.setTaskCode(tsTask.getTaskCode());
|
||||
TsFiles tsFiles = tsFilesMapper.selectById(id);
|
||||
tsfilesName = tsFiles.getFileName();
|
||||
// 执行实际备份逻辑
|
||||
this.decompressionFolder(id, decompressionPath, parentId, path, taskId);
|
||||
} finally {
|
||||
// 生成唯一Key
|
||||
String extractKey = taskStatusHolder.extractKey(taskId);
|
||||
// 无论成功失败都标记完成
|
||||
taskStatusHolder.finishTask(extractKey);
|
||||
extractTaskStatus.removeTask(id);
|
||||
WebSocketServer.sendMessageTo(tsfilesName + "解压缩完成", "id_extract_" + taskId);
|
||||
TableNameContextHolder.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object decompressionFolderData(String taskId) {
|
||||
try {
|
||||
StringBuilder decompressionFolder = new StringBuilder();
|
||||
TsTask tsTask = tsTaskMapper.selectById(taskId);
|
||||
TableNameContextHolder.setTaskCode(tsTask.getTaskCode());
|
||||
// 如果id为空
|
||||
Set<String> keys = extractTaskStatus.getKeysByValue(taskId);
|
||||
if (keys != null && !keys.isEmpty()) {
|
||||
for (String key : keys) {
|
||||
TsFiles tsFiles = tsFilesMapper.selectById(key);
|
||||
if (tsFiles != null) { // 确保 tsFiles 不为 null
|
||||
if (decompressionFolder.length() > 0) {
|
||||
decompressionFolder.append(";"); // 添加分号分隔
|
||||
}
|
||||
decompressionFolder.append(tsFiles.getFileName());
|
||||
}
|
||||
}
|
||||
// 如果拼接了文件名,返回结果
|
||||
if (decompressionFolder.length() > 0) {
|
||||
return (decompressionFolder+"任务正在进行中!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 如果 decompressionFolder 为空
|
||||
if (decompressionFolder.length() == 0) {
|
||||
decompressionFolder.append("没有解压任务!");
|
||||
}
|
||||
return decompressionFolder;
|
||||
}finally {
|
||||
TableNameContextHolder.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**********************************
|
||||
* 用途说明: 解压缩接口
|
||||
* 参数说明 id 要解压的文件id
|
||||
|
@ -26,6 +26,10 @@ import com.yfd.platform.modules.storage.model.enums.FileTypeEnum;
|
||||
import com.yfd.platform.modules.storage.model.request.BatchDeleteRequest;
|
||||
import com.yfd.platform.modules.storage.model.request.NewFolderRequest;
|
||||
import com.yfd.platform.modules.storage.service.base.AbstractBaseFileService;
|
||||
import com.yfd.platform.system.domain.SysDictionary;
|
||||
import com.yfd.platform.system.domain.SysDictionaryItems;
|
||||
import com.yfd.platform.system.mapper.SysDictionaryItemsMapper;
|
||||
import com.yfd.platform.system.mapper.SysDictionaryMapper;
|
||||
import com.yfd.platform.utils.StringUtils;
|
||||
import com.yfd.platform.utils.TableNameContextHolder;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
@ -82,114 +86,110 @@ public class TsTaskServiceImpl extends ServiceImpl<TsTaskMapper, TsTask> impleme
|
||||
|
||||
@Resource
|
||||
private StorageSourceMapper storageSourceMapper;
|
||||
@Resource
|
||||
private SysDictionaryMapper sysDictionaryMapper;
|
||||
|
||||
@Resource
|
||||
private SysDictionaryItemsMapper sysDictionaryItemsMapper;
|
||||
@Autowired
|
||||
private DataSource dataSource;
|
||||
|
||||
private static final String INITIAL_CODE = "00001";
|
||||
private static final int MAX_CODE_VALUE = 99999;
|
||||
|
||||
/**********************************
|
||||
* 用途说明: 分页查询试验数据管理-试验任务管理
|
||||
* 参数说明
|
||||
* taskName 任务名称
|
||||
* startDate (开始日期)
|
||||
* endDate (结束日期)
|
||||
* taskPlace 任务地点
|
||||
* taskPerson 任务人员
|
||||
* taskCode 任务编号
|
||||
* taskType 任务类型
|
||||
* carrierName 载体名称
|
||||
* deviceCode 设备代号_编号
|
||||
* testDescribe 试验描述
|
||||
* sensorDescribe 传感器描述
|
||||
* pageNum 当前页
|
||||
* 返回值说明: com.yfd.platform.config.ResponseResult 返回分页查询结果
|
||||
***********************************/
|
||||
|
||||
// * keyword 全属性搜索
|
||||
// * taskName 任务名称
|
||||
// * startDate (开始日期)
|
||||
// * endDate (结束日期)
|
||||
// * taskPlace 任务地点
|
||||
// * taskPerson 任务人员
|
||||
// * taskCode 任务编号
|
||||
// * taskType 任务类型
|
||||
// * carrierName 载体名称
|
||||
// * deviceCode 设备代号_编号
|
||||
// * testDescribe 试验描述
|
||||
// * sensorDescribe 传感器描述
|
||||
// * pageNum 当前页
|
||||
@Override
|
||||
public Page<TsTask> getTsTaskPage(String taskName, String startDate, String endDate, String taskPlace, String taskPerson, String taskCode, String taskType, String carrierName, String deviceCode, String testDescribe, String sensorDescribe, Page<TsTask> page,List<Map<String, String>> attributeContent) {
|
||||
public Page<TsTask> getTsTaskPage(String keyword, String startDate, String endDate, List<String> fieldNameData, Page<TsTask> page, List<String> attributeContent) {
|
||||
QueryWrapper<TsTask> queryWrapper = new QueryWrapper<>();
|
||||
Set<String> fieldSet = new HashSet<>(fieldNameData);
|
||||
final List<String> matchedTypeIds;
|
||||
|
||||
LambdaQueryWrapper<TsTask> queryWrapper = new LambdaQueryWrapper<>();
|
||||
//如果任务名称 taskName 不为空
|
||||
if (StringUtils.isNotEmpty(taskName)) {
|
||||
queryWrapper.like(TsTask::getTaskName, taskName);
|
||||
// === 处理任务类型字典查询 ===
|
||||
if (fieldSet.contains("task_type")) {
|
||||
QueryWrapper<SysDictionary> dictWrapper = new QueryWrapper<>();
|
||||
dictWrapper.eq("dictcode", "taskType").select("id");
|
||||
SysDictionary sysDictionary = sysDictionaryMapper.selectOne(dictWrapper);
|
||||
|
||||
if (sysDictionary != null) {
|
||||
QueryWrapper<SysDictionaryItems> itemsWrapper = new QueryWrapper<>();
|
||||
itemsWrapper.select("itemcode")
|
||||
.eq("dictid", sysDictionary.getId())
|
||||
.like("dictname", keyword);
|
||||
matchedTypeIds = sysDictionaryItemsMapper.selectList(itemsWrapper)
|
||||
.stream()
|
||||
.map(SysDictionaryItems::getItemCode)
|
||||
.collect(Collectors.toList());
|
||||
} else {
|
||||
matchedTypeIds = Collections.emptyList();
|
||||
}
|
||||
} else {
|
||||
matchedTypeIds = Collections.emptyList();
|
||||
}
|
||||
|
||||
//如果任务地点 taskPlace 不为空
|
||||
if (StringUtils.isNotEmpty(taskPlace)) {
|
||||
queryWrapper.like(TsTask::getTaskPlace, taskPlace);
|
||||
}
|
||||
// === 关键字搜索条件(包含自定义属性)===
|
||||
if (StringUtils.isNotBlank(keyword)) {
|
||||
queryWrapper.and(wrapper -> {
|
||||
boolean hasCondition = false;
|
||||
|
||||
//如果任务人员 taskPerson 不为空
|
||||
if (StringUtils.isNotEmpty(taskPerson)) {
|
||||
queryWrapper.like(TsTask::getTaskPerson, taskPerson);
|
||||
}
|
||||
// 1. 普通字段查询
|
||||
for (String field : fieldSet) {
|
||||
if (FIELD_MAPPING.containsKey(field)) {
|
||||
wrapper.or().like(true, FIELD_MAPPING.get(field), keyword);
|
||||
hasCondition = true;
|
||||
}
|
||||
}
|
||||
|
||||
//如果任务编号 taskCode 不为空
|
||||
if (StringUtils.isNotEmpty(taskCode)) {
|
||||
queryWrapper.like(TsTask::getTaskCode, taskCode);
|
||||
}
|
||||
// 2. 任务类型字典查询
|
||||
if (!matchedTypeIds.isEmpty()) {
|
||||
wrapper.or().in(true, "task_type", matchedTypeIds);
|
||||
hasCondition = true;
|
||||
}
|
||||
|
||||
//如果任务类型 taskType 不为空
|
||||
if (StringUtils.isNotEmpty(taskType)) {
|
||||
queryWrapper.eq(TsTask::getTaskType, taskType);
|
||||
}
|
||||
//如果载体名称 carrierName 不为空
|
||||
if (StringUtils.isNotEmpty(carrierName)) {
|
||||
queryWrapper.like(TsTask::getCarrierName, carrierName);
|
||||
}
|
||||
//如果设备代号_编号 deviceCode 不为空
|
||||
if (StringUtils.isNotEmpty(deviceCode)) {
|
||||
queryWrapper.like(TsTask::getDeviceCode, deviceCode);
|
||||
}
|
||||
//如果试验描述 testDescribe 不为空
|
||||
if (StringUtils.isNotEmpty(testDescribe)) {
|
||||
queryWrapper.like(TsTask::getTestDescribe, testDescribe);
|
||||
}
|
||||
//如果传感器描述 sensorDescribe 不为空
|
||||
if (StringUtils.isNotEmpty(sensorDescribe)) {
|
||||
queryWrapper.like(TsTask::getSensorDescribe, sensorDescribe);
|
||||
}
|
||||
// 3. 存储空间字段查询
|
||||
if (fieldSet.contains("local_storage_id")) {
|
||||
wrapper.or().apply(true,
|
||||
"local_storage_id IN (SELECT id FROM fi_storage_source WHERE name LIKE CONCAT('%', {0}, '%'))",
|
||||
keyword
|
||||
);
|
||||
hasCondition = true;
|
||||
}
|
||||
|
||||
if (fieldSet.contains("backup_storage_id")) {
|
||||
wrapper.or().apply(true,
|
||||
"backup_storage_id IN (SELECT id FROM fi_storage_source WHERE name LIKE CONCAT('%', {0}, '%'))",
|
||||
keyword
|
||||
);
|
||||
hasCondition = true;
|
||||
}
|
||||
|
||||
//开始时间startDate
|
||||
DateTime parseStartDate = DateUtil.parse(startDate);
|
||||
//时间endDate不为空
|
||||
DateTime parseEndDate = DateUtil.parse(endDate);
|
||||
//开始时间和结束时间不为空 查询条件>=开始时间 <结束时间
|
||||
if (parseStartDate != null && parseEndDate != null) {
|
||||
queryWrapper.ge(TsTask::getTaskStartdate, parseStartDate).lt(TsTask::getTaskEnddate, parseEndDate);
|
||||
}
|
||||
queryWrapper.orderByDesc(TsTask::getTaskStartdate);
|
||||
|
||||
|
||||
// 处理属性过滤条件 - MySQL 5.7+ 兼容版本
|
||||
if (attributeContent != null && !attributeContent.isEmpty()) {
|
||||
for (Map<String, String> attr : attributeContent) {
|
||||
for (Map.Entry<String, String> entry : attr.entrySet()) {
|
||||
String code = entry.getKey();
|
||||
String value = entry.getValue();
|
||||
|
||||
if (StringUtils.isEmpty(value)) {
|
||||
// 检查属性存在
|
||||
queryWrapper.apply(
|
||||
"EXISTS (SELECT 1 FROM JSON_TABLE(task_props, '$[*]' " +
|
||||
"COLUMNS (code VARCHAR(50) PATH '$.code') AS jt " +
|
||||
"WHERE jt.code = {0})",
|
||||
code
|
||||
);
|
||||
} else {
|
||||
// 4. 自定义属性字段查询(关键修改点)
|
||||
if (attributeContent != null && !attributeContent.isEmpty()) {
|
||||
// 处理每个自定义属性的搜索
|
||||
for (String attrCode : attributeContent) {
|
||||
// 转义特殊字符
|
||||
String safeValue = value.replace("'", "''")
|
||||
String safeValue = keyword.replace("'", "''")
|
||||
.replace("%", "\\%")
|
||||
.replace("_", "\\_");
|
||||
|
||||
// 使用 JSON_EXTRACT 实现兼容查询
|
||||
queryWrapper.apply(
|
||||
// 添加自定义属性搜索条件
|
||||
wrapper.or().apply(true,
|
||||
"EXISTS (SELECT 1 FROM (" +
|
||||
" SELECT " +
|
||||
" JSON_UNQUOTE(JSON_EXTRACT(t.obj, '$.code')) AS code, " +
|
||||
" JSON_UNQUOTE(JSON_EXTRACT(t.obj, '$.data')) AS data " +
|
||||
" COALESCE(JSON_UNQUOTE(JSON_EXTRACT(t.obj, '$.data')), '') AS data " +
|
||||
" FROM (" +
|
||||
" SELECT JSON_EXTRACT(task_props, CONCAT('$[', idx.idx, ']')) AS obj " +
|
||||
" FROM (SELECT 0 AS idx UNION SELECT 1 UNION SELECT 2 UNION SELECT 3) idx" +
|
||||
@ -197,16 +197,49 @@ public class TsTaskServiceImpl extends ServiceImpl<TsTaskMapper, TsTask> impleme
|
||||
" ) t" +
|
||||
") jt " +
|
||||
"WHERE jt.code = {0} AND jt.data LIKE CONCAT('%', {1}, '%'))",
|
||||
code, value
|
||||
attrCode, safeValue
|
||||
);
|
||||
hasCondition = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasCondition) {
|
||||
wrapper.apply(true, "1 = 0");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// === 时间范围处理 ===
|
||||
if (StringUtils.isNotBlank(startDate) && StringUtils.isNotBlank(endDate)) {
|
||||
DateTime parseStartDate = DateUtil.parse(startDate);
|
||||
DateTime parseEndDate = DateUtil.parse(endDate);
|
||||
|
||||
if (parseStartDate != null && parseEndDate != null) {
|
||||
queryWrapper.ge(true, "task_startdate", parseStartDate)
|
||||
.lt(true, "task_enddate", parseEndDate);
|
||||
}
|
||||
}
|
||||
//分页查询
|
||||
Page<TsTask> tsTaskPage = tsTaskMapper.selectPage(page, queryWrapper);
|
||||
return tsTaskPage;
|
||||
|
||||
// 添加排序
|
||||
queryWrapper.orderByDesc(true, "task_startdate");
|
||||
|
||||
return tsTaskMapper.selectPage(page, queryWrapper);
|
||||
}
|
||||
// 字段映射(避免硬编码)
|
||||
private static final Map<String, String> FIELD_MAPPING = new HashMap<>();
|
||||
static {
|
||||
FIELD_MAPPING.put("task_code", "task_code");
|
||||
FIELD_MAPPING.put("task_name", "task_name");
|
||||
FIELD_MAPPING.put("task_place", "task_place");
|
||||
FIELD_MAPPING.put("task_person", "task_person");
|
||||
FIELD_MAPPING.put("carrier_name", "carrier_name");
|
||||
FIELD_MAPPING.put("device_code", "device_code");
|
||||
FIELD_MAPPING.put("test_describe", "test_describe");
|
||||
FIELD_MAPPING.put("sensor_describe", "sensor_describe");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/***********************************
|
||||
* 用途说明:新增试验数据管理-试验任务管理
|
||||
|
Loading…
Reference in New Issue
Block a user