优化代码提交

This commit is contained in:
lilin 2025-06-19 11:25:40 +08:00
parent f7a3023629
commit e2ea3338f1
38 changed files with 3538 additions and 2246 deletions

View File

@ -2,10 +2,16 @@ package com.yfd.platform.config;
import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.handler.TableNameHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.DynamicTableNameInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.yfd.platform.utils.TableNameContextHolder;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
/****************************** /******************************
* 用途说明: * 用途说明:
* 作者姓名: pcj * 作者姓名: pcj
@ -16,11 +22,36 @@ public class MybitsPlusConfig {
@Bean @Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() { public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor(); MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return mybatisPlusInterceptor; // 创建动态表名拦截器
DynamicTableNameInnerInterceptor dynamicInterceptor = new DynamicTableNameInnerInterceptor();
// 创建表名处理器映射
Map<String, TableNameHandler> handlerMap = new HashMap<>();
// ts_files 表添加处理器
handlerMap.put("ts_files", new TableNameHandler() {
@Override
public String dynamicTableName(String sql, String tableName) {
String taskCode = TableNameContextHolder.getTaskCode();
if (taskCode == null || taskCode.isEmpty()) {
throw new IllegalArgumentException("任务编码不能为空");
}
return "ts_files_" + taskCode;
}
});
// 设置处理器映射
dynamicInterceptor.setTableNameHandlerMap(handlerMap);
// 添加动态表名拦截器
interceptor.addInnerInterceptor(dynamicInterceptor);
// 添加分页拦截器
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
} }
}

View File

@ -167,12 +167,12 @@ public class TsFilesController {
@PostMapping("/deleteTsFilesById") @PostMapping("/deleteTsFilesById")
@ApiOperation("根据ID删除试验数据管理文档内容") @ApiOperation("根据ID删除试验数据管理文档内容")
@PreAuthorize("@el.check('del:tsFiles')") @PreAuthorize("@el.check('del:tsFiles')")
public ResponseResult deleteTsFilesById(@RequestParam String id, @RequestParam String type) { public ResponseResult deleteTsFilesById(@RequestParam String id, @RequestParam String type,@RequestParam String taskId) {
if (StrUtil.isBlank(id)) { if (StrUtil.isBlank(id) || StrUtil.isBlank(taskId)) {
return ResponseResult.error("参数为空"); return ResponseResult.error("参数为空");
} }
List<String> dataset = Arrays.asList(id); List<String> dataset = Arrays.asList(id);
return ResponseResult.success(tsFilesService.deleteTsFilesByIds(dataset, type)); return ResponseResult.success(tsFilesService.deleteTsFilesByIds(dataset, type,taskId));
} }
/********************************** /**********************************
@ -185,14 +185,14 @@ public class TsFilesController {
@PostMapping("/deleteTsFilesByIds") @PostMapping("/deleteTsFilesByIds")
@ApiOperation("批量删除试验数据管理文档内容") @ApiOperation("批量删除试验数据管理文档内容")
@PreAuthorize("@el.check('del:tsFiles')") @PreAuthorize("@el.check('del:tsFiles')")
public ResponseResult deleteTsFilesByIds(@RequestParam String ids, @RequestParam String type) { public ResponseResult deleteTsFilesByIds(@RequestParam String ids, @RequestParam String type,@RequestParam String taskId) {
if (StrUtil.isBlank(ids)) { if (StrUtil.isBlank(ids) || StrUtil.isBlank(taskId)) {
return ResponseResult.error("参数为空"); return ResponseResult.error("参数为空");
} }
String[] splitIds = ids.split(","); String[] splitIds = ids.split(",");
// 数组转集合 // 数组转集合
List<String> dataset = Arrays.asList(splitIds); List<String> dataset = Arrays.asList(splitIds);
return ResponseResult.success(tsFilesService.deleteTsFilesByIds(dataset, type)); return ResponseResult.success(tsFilesService.deleteTsFilesByIds(dataset, type,taskId));
} }
/**************************压缩 解压缩********************************/ /**************************压缩 解压缩********************************/
@ -211,13 +211,13 @@ public class TsFilesController {
@Log(module = "实验数据管理", value = "压缩文件夹接口!") @Log(module = "实验数据管理", value = "压缩文件夹接口!")
@PostMapping("/compress") @PostMapping("/compress")
@ApiOperation("压缩文件夹接口") @ApiOperation("压缩文件夹接口")
public ResponseResult compressFolder(String ids, String compressedFormat, String compressedName, String compressedPath, String covered, String parentId, String path) { public ResponseResult compressFolder(String ids, String compressedFormat, String compressedName, String compressedPath, String covered, String parentId, String path,String taskId) {
try { try {
if (StrUtil.isBlank(ids) && StrUtil.isBlank(compressedFormat) && StrUtil.isBlank(compressedName) && StrUtil.isBlank(compressedPath) && StrUtil.isBlank(path)) { if (StrUtil.isBlank(ids) && StrUtil.isBlank(compressedFormat) && StrUtil.isBlank(compressedName) && StrUtil.isBlank(compressedPath) && StrUtil.isBlank(path) && StrUtil.isBlank(taskId)) {
return ResponseResult.error("参数为空"); return ResponseResult.error("参数为空");
} }
return ResponseResult.success(tsFilesService.compressFolder(ids, compressedFormat, compressedName, compressedPath, covered, parentId, path)); return ResponseResult.success(tsFilesService.compressFolder(ids, compressedFormat, compressedName, compressedPath, covered, parentId, path,taskId));
} catch (Exception e) { } catch (Exception e) {
System.out.print("压缩异常原因" + e); System.out.print("压缩异常原因" + e);
return ResponseResult.error("压缩失败"); return ResponseResult.error("压缩失败");
@ -235,12 +235,12 @@ public class TsFilesController {
@Log(module = "实验数据管理", value = "解压缩接口!") @Log(module = "实验数据管理", value = "解压缩接口!")
@PostMapping("/decompression") @PostMapping("/decompression")
@ApiOperation("解压缩接口") @ApiOperation("解压缩接口")
public ResponseResult decompressionFolder(String id, String decompressionPath, String parentId, String path) { public ResponseResult decompressionFolder(String id, String decompressionPath, String parentId, String path,String taskId) {
try { try {
if (StrUtil.isBlank(id)) { if (StrUtil.isBlank(id)|| StrUtil.isBlank(taskId)) {
return ResponseResult.error("参数为空"); return ResponseResult.error("参数为空");
} }
return ResponseResult.success(tsFilesService.decompressionFolder(id, decompressionPath, parentId, path)); return ResponseResult.success(tsFilesService.decompressionFolder(id, decompressionPath, parentId, path,taskId));
} catch (Exception e) { } catch (Exception e) {
System.out.print("解压缩异常原因" + e); System.out.print("解压缩异常原因" + e);
return ResponseResult.error("解压缩失败"); return ResponseResult.error("解压缩失败");
@ -654,12 +654,12 @@ public class TsFilesController {
@Log(module = "实验数据管理", value = "实时获取轨迹数据!") @Log(module = "实验数据管理", value = "实时获取轨迹数据!")
@PostMapping("/startSimpleNavi") @PostMapping("/startSimpleNavi")
@ApiOperation("实时获取轨迹数据") @ApiOperation("实时获取轨迹数据")
public ResponseResult startSimpleNavi(String id, int samTimes, String token) { public ResponseResult startSimpleNavi(String id, int samTimes, String token,String taskId) {
try { try {
// 使用线程池异步执行任务 // 使用线程池异步执行任务
CompletableFuture.runAsync(() -> { CompletableFuture.runAsync(() -> {
try { try {
tsFilesService.batchSendNaviOutDataJob(id, samTimes, token); tsFilesService.batchSendNaviOutDataJob(id, samTimes, token,taskId);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -694,12 +694,12 @@ public class TsFilesController {
@Log(module = "实验数据管理", value = "查询文件内容!") @Log(module = "实验数据管理", value = "查询文件内容!")
@GetMapping("/api/files/content") @GetMapping("/api/files/content")
@ApiOperation("查询文件内容") @ApiOperation("查询文件内容")
public ResponseResult getFileContent(@RequestParam String id) { public ResponseResult getFileContent(@RequestParam String id,String taskId) {
try { try {
if (StrUtil.isBlank(id)) { if (StrUtil.isBlank(id) && StrUtil.isBlank(taskId)) {
return ResponseResult.error("参数为空"); return ResponseResult.error("参数为空");
} }
String content = tsFilesService.readFileContent(id); String content = tsFilesService.readFileContent(id, taskId);
return ResponseResult.successData(content); return ResponseResult.successData(content);
} catch (SecurityException | IOException e) { } catch (SecurityException | IOException e) {
return ResponseResult.error("非法操作: " + e.getMessage()); return ResponseResult.error("非法操作: " + e.getMessage());
@ -715,12 +715,12 @@ public class TsFilesController {
@Log(module = "实验数据管理", value = "保存文件内容!") @Log(module = "实验数据管理", value = "保存文件内容!")
@PostMapping("/save/files/content") @PostMapping("/save/files/content")
@ApiOperation("保存文件内容") @ApiOperation("保存文件内容")
public ResponseResult saveFileContent(String id, String content) { public ResponseResult saveFileContent(String id, String content,String taskId) {
try { try {
if (StrUtil.isBlank(id) && StrUtil.isBlank(content)) { if (StrUtil.isBlank(id) && StrUtil.isBlank(content) && StrUtil.isBlank(taskId)) {
return ResponseResult.error("参数为空"); return ResponseResult.error("参数为空");
} }
tsFilesService.saveFileContent(id, content); tsFilesService.saveFileContent(id, content, taskId);
return ResponseResult.success("文件保存成功"); return ResponseResult.success("文件保存成功");
} catch (SecurityException | IOException e) { } catch (SecurityException | IOException e) {
return ResponseResult.error("非法操作: " + e.getMessage()); return ResponseResult.error("非法操作: " + e.getMessage());
@ -737,7 +737,7 @@ public class TsFilesController {
@PostMapping("/batchModify") @PostMapping("/batchModify")
@ApiOperation("批量修改文件中多行多列的内容") @ApiOperation("批量修改文件中多行多列的内容")
public ResponseResult batchModifyFile(@RequestBody BatchModifyRequest request) throws IOException { public ResponseResult batchModifyFile(@RequestBody BatchModifyRequest request) throws IOException {
tsFilesService.batchUpdateFile(request.getId(), request.getModifications()); tsFilesService.batchUpdateFile(request.getId(), request.getModifications(),request.getTaskId());
return ResponseResult.success("文件保存成功"); return ResponseResult.success("文件保存成功");
} }
@ -749,12 +749,12 @@ public class TsFilesController {
@Log(module = "实验数据管理", value = "获取文件url") @Log(module = "实验数据管理", value = "获取文件url")
@PostMapping("/obtainUrl") @PostMapping("/obtainUrl")
@ApiOperation("获取文件url") @ApiOperation("获取文件url")
public ResponseResult obtainUrl(String id, String type) { public ResponseResult obtainUrl(String id, String type,String taskId) {
if (StrUtil.isBlank(id) && StrUtil.isBlank(type)) { if (StrUtil.isBlank(id) && StrUtil.isBlank(type) && StrUtil.isBlank(type)) {
return ResponseResult.error("参数为空"); return ResponseResult.error("参数为空");
} }
//查询本地树和minio树 //查询本地树和minio树
FileItemResult fileItemResult = tsFilesService.obtainUrl(id, type); FileItemResult fileItemResult = tsFilesService.obtainUrl(id, type,taskId);
return ResponseResult.successData(fileItemResult); return ResponseResult.successData(fileItemResult);
} }
} }

View File

@ -184,9 +184,7 @@ public class TsTaskController {
@ResponseBody @ResponseBody
//@PreAuthorize("@el.check('select:devicesignal')") //@PreAuthorize("@el.check('select:devicesignal')")
public ResponseResult listTsTask() { public ResponseResult listTsTask() {
LambdaQueryWrapper<TsTask> queryWrapper = new LambdaQueryWrapper<>(); List<TsTask> tsTasks = tsTaskService.listTsTask();
queryWrapper.orderByDesc(TsTask::getTaskStartdate);
List<TsTask> tsTasks = tsTaskService.list(queryWrapper);
return ResponseResult.successData(tsTasks); return ResponseResult.successData(tsTasks);
} }
} }

View File

@ -13,6 +13,9 @@ public class BatchModifyRequest {
@NotBlank @NotBlank
private String id; // 文件ID private String id; // 文件ID
@NotBlank
private String taskId; // 任务ID
@NotEmpty @NotEmpty
private List<ModifyCommand> modifications; private List<ModifyCommand> modifications;
} }

View File

@ -12,5 +12,6 @@ public class MoveCopyFileFolderRequest {
private String newFileName; private String newFileName;
private String rename; private String rename;
private String type; private String type;
private String taskId;
} }

View File

@ -7,5 +7,6 @@ import java.util.List;
@Data @Data
public class Parameter { public class Parameter {
public List<ParameterList> parameterLists; public List<ParameterList> parameterLists;
public String taskId;
// public String parameterLists; // public String parameterLists;
} }

View File

@ -1,6 +1,7 @@
package com.yfd.platform.modules.experimentalData.domain; package com.yfd.platform.modules.experimentalData.domain;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
@ -138,7 +139,21 @@ public class TsTask implements Serializable {
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private LocalDate taskEnddate; private LocalDate taskEnddate;
/**
* 本地存储空间id
*/
private Integer localStorageId;
/**
* 备份存储空间id
*/
private Integer backupStorageId;
/**
* 上传用到KEYTODO 增加用于前端展示
*/
@TableField(exist = false)
private String key;
} }

View File

@ -21,4 +21,7 @@ public interface TsFilesMapper extends BaseMapper<TsFiles> {
int updateParentIdByPathHierarchy(@Param("taskId") String taskId, @Param("nodeId") String nodeId); int updateParentIdByPathHierarchy(@Param("taskId") String taskId, @Param("nodeId") String nodeId);
int countFiles(@Param("id") String id); int countFiles(@Param("id") String id);
void updateTsFileByPath(@Param("taskId") String taskId,@Param("oldBasePath") String oldBasePath,@Param("newBasePath") String newBasePath);
} }

View File

@ -60,7 +60,7 @@ public interface ITsFilesService extends IService<TsFiles> {
* 参数说明 type local还是minio * 参数说明 type local还是minio
* 返回值说明: com.yfd.platform.config.ResponseResult 返回批量删除成功或失败 * 返回值说明: com.yfd.platform.config.ResponseResult 返回批量删除成功或失败
***********************************/ ***********************************/
String deleteTsFilesByIds(List<String> dataset, String type); String deleteTsFilesByIds(List<String> dataset, String type, String taskId);
/********************************** /**********************************
* 用途说明: 压缩文件夹接口 * 用途说明: 压缩文件夹接口
@ -73,7 +73,7 @@ public interface ITsFilesService extends IService<TsFiles> {
* 参数说明 path 根目录 /项目名/节点名称/ * 参数说明 path 根目录 /项目名/节点名称/
* 返回值说明: com.yfd.platform.config.ResponseResult * 返回值说明: com.yfd.platform.config.ResponseResult
***********************************/ ***********************************/
String compressFolder(String ids, String compressedFormat, String compressedName, String compressedPath, String covered, String parentId,String path) throws FileNotFoundException; String compressFolder(String ids, String compressedFormat, String compressedName, String compressedPath, String covered, String parentId,String path,String taskId) throws FileNotFoundException;
/********************************** /**********************************
* 用途说明: 解压缩接口 * 用途说明: 解压缩接口
@ -83,7 +83,7 @@ public interface ITsFilesService extends IService<TsFiles> {
* 参数说明 path 根目录 /项目名/节点名称/ * 参数说明 path 根目录 /项目名/节点名称/
* 返回值说明: com.yfd.platform.config.ResponseResult * 返回值说明: com.yfd.platform.config.ResponseResult
***********************************/ ***********************************/
String decompressionFolder(String id, String decompressionPath, String parentId, String path); String decompressionFolder(String id, String decompressionPath, String parentId, String path,String taskId);
/********************************** /**********************************
* 用途说明: 将文件上传到备份空间 * 用途说明: 将文件上传到备份空间
@ -144,7 +144,7 @@ public interface ITsFilesService extends IService<TsFiles> {
* 参数说明 token SSE连接的token * 参数说明 token SSE连接的token
* 返回值说明: com.yfd.platform.config.ResponseResult * 返回值说明: com.yfd.platform.config.ResponseResult
***********************************/ ***********************************/
void batchSendNaviOutDataJob(String id, int samTimes, String token); void batchSendNaviOutDataJob(String id, int samTimes, String token,String taskId);
/** /**
* 查询文件内容接口 * 查询文件内容接口
@ -152,7 +152,7 @@ public interface ITsFilesService extends IService<TsFiles> {
* @param id 文件的id * @param id 文件的id
* @return 文件内容的纯文本UTF-8 编码 * @return 文件内容的纯文本UTF-8 编码
*/ */
String readFileContent(String id) throws IOException; String readFileContent(String id,String taskId) throws IOException;
/********************************** /**********************************
* 用途说明: 保存文件内容接口 * 用途说明: 保存文件内容接口
@ -160,14 +160,14 @@ public interface ITsFilesService extends IService<TsFiles> {
* 参数说明 content 新的文件内容HTML/文本 * 参数说明 content 新的文件内容HTML/文本
* 返回值说明: com.yfd.platform.config.ResponseResult操作结果 * 返回值说明: com.yfd.platform.config.ResponseResult操作结果
***********************************/ ***********************************/
void saveFileContent(String id, String content) throws IOException; void saveFileContent(String id, String content,String taskId) throws IOException;
/********************************** /**********************************
* 用途说明: 批量修改文件中多行多列的内容 * 用途说明: 批量修改文件中多行多列的内容
* 参数说明 request 要修改的文件信息 * 参数说明 request 要修改的文件信息
* 返回值说明: com.yfd.platform.config.ResponseResult操作结果 * 返回值说明: com.yfd.platform.config.ResponseResult操作结果
***********************************/ ***********************************/
void batchUpdateFile(String id, List<ModifyCommand> modifications) throws IOException; void batchUpdateFile(String id, List<ModifyCommand> modifications,String taskId) throws IOException;
/********************************** /**********************************
* 用途说明: 文件自动备份 * 用途说明: 文件自动备份
@ -198,7 +198,7 @@ public interface ITsFilesService extends IService<TsFiles> {
* 参数说明 id 文件夹ID * 参数说明 id 文件夹ID
* 返回值说明: com.yfd.platform.config.ResponseResult 返回文件信息 * 返回值说明: com.yfd.platform.config.ResponseResult 返回文件信息
***********************************/ ***********************************/
FileItemResult obtainUrl(String id, String type); FileItemResult obtainUrl(String id, String type,String taskId);
/********************************** /**********************************
* 用途说明: 对比本地有minio没有的文件差异 * 用途说明: 对比本地有minio没有的文件差异

View File

@ -64,4 +64,6 @@ public interface ITsTaskService extends IService<TsTask> {
* 返回值说明: com.yfd.platform.config.ResponseResult 返回删除成功或者失败 * 返回值说明: com.yfd.platform.config.ResponseResult 返回删除成功或者失败
***********************************/ ***********************************/
Object confirmDeleteTask(List<String> dataset); Object confirmDeleteTask(List<String> dataset);
List<TsTask> listTsTask();
} }

View File

@ -22,21 +22,27 @@ import com.yfd.platform.modules.experimentalData.mapper.TsTaskMapper;
import com.yfd.platform.modules.experimentalData.service.ITsFilesService; import com.yfd.platform.modules.experimentalData.service.ITsFilesService;
import com.yfd.platform.modules.experimentalData.service.ITsNodesService; import com.yfd.platform.modules.experimentalData.service.ITsNodesService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yfd.platform.modules.specialDocument.domain.Nodes;
import com.yfd.platform.modules.storage.context.StorageSourceContext; import com.yfd.platform.modules.storage.context.StorageSourceContext;
import com.yfd.platform.modules.storage.mapper.StorageSourceConfigMapper; import com.yfd.platform.modules.storage.mapper.StorageSourceConfigMapper;
import com.yfd.platform.modules.storage.mapper.StorageSourceMapper;
import com.yfd.platform.modules.storage.model.entity.StorageSource;
import com.yfd.platform.modules.storage.model.entity.StorageSourceConfig; import com.yfd.platform.modules.storage.model.entity.StorageSourceConfig;
import com.yfd.platform.modules.storage.model.enums.FileTypeEnum; import com.yfd.platform.modules.storage.model.enums.FileTypeEnum;
import com.yfd.platform.modules.storage.model.request.BatchDeleteRequest; import com.yfd.platform.modules.storage.model.request.BatchDeleteRequest;
import com.yfd.platform.modules.storage.model.request.NewFolderRequest; import com.yfd.platform.modules.storage.model.request.NewFolderRequest;
import com.yfd.platform.modules.storage.model.request.RenameFolderRequest;
import com.yfd.platform.modules.storage.model.result.FileItemResult; import com.yfd.platform.modules.storage.model.result.FileItemResult;
import com.yfd.platform.modules.storage.service.StorageSourceService; import com.yfd.platform.modules.storage.service.StorageSourceService;
import com.yfd.platform.modules.storage.service.base.AbstractBaseFileService; import com.yfd.platform.modules.storage.service.base.AbstractBaseFileService;
import com.yfd.platform.system.domain.LoginUser; import com.yfd.platform.system.domain.LoginUser;
import com.yfd.platform.utils.StringUtils; import com.yfd.platform.utils.StringUtils;
import com.yfd.platform.utils.TableNameContextHolder;
import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInboundHandlerAdapter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Async;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
@ -93,6 +99,11 @@ public class TsNodesServiceImpl extends ServiceImpl<TsNodesMapper, TsNodes> impl
@Resource @Resource
private StorageSourceConfigMapper storageSourceConfigMapper; private StorageSourceConfigMapper storageSourceConfigMapper;
@Resource
private StorageSourceMapper storageSourceMapper;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
//顶级父节点 Top level parent node //顶级父节点 Top level parent node
public static final String TOP_LEVEL_PARENT_NODE = "00"; public static final String TOP_LEVEL_PARENT_NODE = "00";
@ -289,7 +300,14 @@ public class TsNodesServiceImpl extends ServiceImpl<TsNodesMapper, TsNodes> impl
@Override @Override
@Transactional(rollbackFor = Exception.class) // 添加事务注解遇到异常时回滚 @Transactional(rollbackFor = Exception.class) // 添加事务注解遇到异常时回滚
public ResponseResult addTsNodes(TsNodes tsnodes) { public ResponseResult addTsNodes(TsNodes tsnodes) {
// 初始化变量
ResponseResult result = ResponseResult.error();
try {
TsTask tsTask = tsTaskMapper.selectById(tsnodes.getTaskId());
TableNameContextHolder.setTaskCode(tsTask.getTaskCode());
StorageSource storageSource = getStorageConfig(tsTask.getLocalStorageId());
//查询文件表 如果有一样的名称不能新增 //查询文件表 如果有一样的名称不能新增
List<TsFiles> tsFiles = tsFilesMapper.selectList(new QueryWrapper<TsFiles>() List<TsFiles> tsFiles = tsFilesMapper.selectList(new QueryWrapper<TsFiles>()
.eq("task_id", tsnodes.getTaskId()) .eq("task_id", tsnodes.getTaskId())
@ -345,19 +363,29 @@ public class TsNodesServiceImpl extends ServiceImpl<TsNodesMapper, TsNodes> impl
newFolderRequest.setName(tsnodes.getNodeName());//新建的文件夹名称,示例值(/a/b/c) newFolderRequest.setName(tsnodes.getNodeName());//新建的文件夹名称,示例值(/a/b/c)
newFolderRequest.setPassword("");//文件夹密码, 如果文件夹需要密码才能访问则支持请求密码,示例值(123456) newFolderRequest.setPassword("");//文件夹密码, 如果文件夹需要密码才能访问则支持请求密码,示例值(123456)
newFolderRequest.setPath(tsnodes.getPath());//请求路径,示例值(/) newFolderRequest.setPath(tsnodes.getPath());//请求路径,示例值(/)
newFolderRequest.setStorageKey("local");//存储源 key,示例值(local minio sdlocal) newFolderRequest.setStorageKey(storageSource.getKey());//存储源 key,示例值(local minio sdlocal)
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(newFolderRequest.getStorageKey()); AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(newFolderRequest.getStorageKey());
boolean flag = fileService.newFolder(newFolderRequest.getPath(), newFolderRequest.getName()); boolean flag = fileService.newFolder(newFolderRequest.getPath(), newFolderRequest.getName());
if (flag) { if (flag) {
return ResponseResult.success(); result = ResponseResult.success();
} else { } else {
LOGGER.error("节点新增成功但是local创建文件失败"); LOGGER.error("节点新增成功但是local创建文件失败");
return ResponseResult.error(); result = ResponseResult.error("物理文件夹创建失败");
} }
return result;
} else { } else {
LOGGER.error("tsnodes表结构增加失败"); LOGGER.error("tsnodes表结构增加失败");
return ResponseResult.error(); return ResponseResult.error();
} }
} catch (Exception e) {
// 异常处理
LOGGER.error("添加节点时发生异常: {}", e.getMessage(), e);
return ResponseResult.error("系统错误: " + e.getMessage());
} finally {
TableNameContextHolder.clear();
return result;
}
} }
@ -380,46 +408,100 @@ public class TsNodesServiceImpl extends ServiceImpl<TsNodesMapper, TsNodes> impl
@Override @Override
public ResponseResult updateTsNodes(TsNodes tsnodes) { public ResponseResult updateTsNodes(TsNodes tsnodes) {
try {
TsTask tsTask = tsTaskMapper.selectById(tsnodes.getTaskId());
TableNameContextHolder.setTaskCode(tsTask.getTaskCode());
StorageSource storageSource = getStorageConfig(tsTask.getLocalStorageId());
// 校验文件名是否包含非法字符 // 校验文件名是否包含非法字符
String nodeName = tsnodes.getNodeName(); String nodeName = tsnodes.getNodeName();
if (containsInvalidCharacters(nodeName)) { if (containsInvalidCharacters(nodeName)) {
return ResponseResult.error("文件名包含非法字符(<>:\"/\\|?*"); return ResponseResult.error("文件名包含非法字符(<>:\"/\\|?*");
} }
//查询没改之前的节点名称 // 查询旧节点名称
TsNodes nodesold = tsNodesMapper.selectById(tsnodes.getNodeId()); TsNodes nodesold = tsNodesMapper.selectById(tsnodes.getNodeId());
String nodeNameOld = ObjUtil.isNotEmpty(nodesold) ? nodesold.getNodeName() : null;
//老的节点名称
String nodeNameOld = null;
if (ObjUtil.isNotEmpty(nodesold)) {
nodeNameOld = nodesold.getNodeName();
}
// 获取当前登录用户 // 获取当前登录用户
UsernamePasswordAuthenticationToken authentication = UsernamePasswordAuthenticationToken authentication =
(UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
LoginUser loginuser = (LoginUser) authentication.getPrincipal(); LoginUser loginuser = (LoginUser) authentication.getPrincipal();
//创建人是当前登录人
// 设置创建人
tsnodes.setCreator(loginuser.getUsername()); tsnodes.setCreator(loginuser.getUsername());
// 判断节点名称是否存在 // 判断节点名称是否存在
QueryWrapper<TsNodes> queryWrapper = new QueryWrapper<>(); QueryWrapper<TsNodes> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("node_name", tsnodes.getNodeName());//名称 queryWrapper.eq("node_name", tsnodes.getNodeName())
queryWrapper.eq("task_id", tsnodes.getTaskId());//所属任务ID .eq("task_id", tsnodes.getTaskId())
queryWrapper.eq("parent_id", tsnodes.getParentId());//所属任务ID .eq("parent_id", tsnodes.getParentId());
int count = tsNodesMapper.selectCount(queryWrapper); int count = tsNodesMapper.selectCount(queryWrapper);
// 大于0说明 区域名称重复
if (count > 0) { if (count > 0) {
return ResponseResult.error("节点名称已存在!"); return ResponseResult.error("节点名称已存在!");
} }
// 更新节点信息
int valueAdded = tsNodesMapper.updateById(tsnodes); int valueAdded = tsNodesMapper.updateById(tsnodes);
// 2. 构建新旧路径
String oldBasePath = tsnodes.getPath() + nodeNameOld + "/";
String newBasePath = tsnodes.getPath() + nodeName + "/";
//4.更新文件表ts_files表 根据所属项目ID 老路径 和新路径
tsFilesMapper.updateTsFileByPath(tsnodes.getTaskId(), oldBasePath, newBasePath);
//获取项目下面的所有子节点 都清除缓存
List<TsNodes> nodesList = tsNodesMapper.selectList(new QueryWrapper<TsNodes>().eq("task_id", tsnodes.getTaskId()));
if ((nodesList != null) && (nodesList.size() > 0)) {
for (TsNodes node : nodesList) {
//todo 修改节点成功以后 删除redis
for (int page = 1; page <= 5; page++) {
String redisKey = "tsfiles_" + node.getTaskId() + "_" + node.getNodeId() + "_parentId" + node.getParentId() + "_page_" + page;
redisTemplate.delete(redisKey);
}
}
}
//判断如果更新了节点名称
if (!nodeName.equals(nodeNameOld)) {
if (valueAdded == 1) { if (valueAdded == 1) {
LOGGER.info("tsnodes表结构修改成功"); //修改文件名称
return ResponseResult.success(); RenameFolderRequest renameFolderRequest = new RenameFolderRequest();
renameFolderRequest.setName(nodeNameOld);//重命名的原文件夹名称,示例值(movie)
renameFolderRequest.setNewName(nodeName);// 重命名后的文件名称,示例值(music)
renameFolderRequest.setPassword("");//文件夹密码, 如果文件夹需要密码才能访问则支持请求密码,示例值(123456)
renameFolderRequest.setPath(tsnodes.getPath());//请求路径,示例值(/)
renameFolderRequest.setStorageKey(storageSource.getKey());//存储源 key,示例值(local minio sdlocal)
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(renameFolderRequest.getStorageKey());
boolean flag = fileService.renameFolder(renameFolderRequest.getPath(), renameFolderRequest.getName(), renameFolderRequest.getNewName());
if (flag) {
return ResponseResult.success("重命名成功");
} else { } else {
LOGGER.error("tsnodes表结构修改失败"); LOGGER.error("节点修改成功,但是本地修改文件名失败");
return ResponseResult.error("重命名失败");
}
} else {
LOGGER.error("节点修改失败");
return ResponseResult.error(); return ResponseResult.error();
} }
} else {
if (valueAdded == 1) {
return ResponseResult.success("重命名成功");
} else {
return ResponseResult.error("重命名失败");
}
}
} catch (Exception e) {
LOGGER.error("更新试验任务节点时发生异常: {}", e.getMessage(), e);
return ResponseResult.error("系统错误,请稍后重试");
} finally {
TableNameContextHolder.clear();
}
} }
/********************************** /**********************************
@ -430,8 +512,12 @@ public class TsNodesServiceImpl extends ServiceImpl<TsNodesMapper, TsNodes> impl
***********************************/ ***********************************/
@Override @Override
public boolean deleteTsNodesById(String id, String path) { public boolean deleteTsNodesById(String id, String path) {
try {
//根据ID 查询当前数据 //根据ID 查询当前数据
TsNodes tsNodes = tsNodesMapper.selectById(id); TsNodes tsNodes = tsNodesMapper.selectById(id);
TsTask tsTask = tsTaskMapper.selectById(tsNodes.getTaskId());
TableNameContextHolder.setTaskCode(tsTask.getTaskCode());
StorageSource storageSource = getStorageConfig(tsTask.getLocalStorageId());
//删除之前 先拼路径 然后删除本地和minio的文件夹 最后删除表结构 //删除之前 先拼路径 然后删除本地和minio的文件夹 最后删除表结构
//查询所有的子节点 //查询所有的子节点
List<TsNodes> tsNodesList = selectChildrentsNodes(tsNodes.getNodeId(), tsNodes.getTaskId()); List<TsNodes> tsNodesList = selectChildrentsNodes(tsNodes.getNodeId(), tsNodes.getTaskId());
@ -468,7 +554,7 @@ public class TsNodesServiceImpl extends ServiceImpl<TsNodesMapper, TsNodes> impl
BatchDeleteRequest batchDeleteRequest = new BatchDeleteRequest(); BatchDeleteRequest batchDeleteRequest = new BatchDeleteRequest();
batchDeleteRequest.setDeleteItems(deleteItemList); batchDeleteRequest.setDeleteItems(deleteItemList);
batchDeleteRequest.setStorageKey("local"); batchDeleteRequest.setStorageKey(storageSource.getKey());
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(batchDeleteRequest.getStorageKey()); AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(batchDeleteRequest.getStorageKey());
int deleteSuccessCount = 0, deleteFailCount = 0, totalCount = CollUtil.size(deleteItemList); int deleteSuccessCount = 0, deleteFailCount = 0, totalCount = CollUtil.size(deleteItemList);
@ -504,6 +590,14 @@ public class TsNodesServiceImpl extends ServiceImpl<TsNodesMapper, TsNodes> impl
} else { } else {
return false; return false;
} }
} catch (Exception e) {
LOGGER.error("删除试验任务节点时发生异常: {}", e.getMessage(), e);
return false;
} finally {
TableNameContextHolder.clear();
}
} }
private List<TsNodes> selectChildrentsNodes(String parentId, String taskId) { private List<TsNodes> selectChildrentsNodes(String parentId, String taskId) {
@ -559,7 +653,7 @@ public class TsNodesServiceImpl extends ServiceImpl<TsNodesMapper, TsNodes> impl
} }
//批量删除TsFiles表数据 //批量删除TsFiles表数据
if (dataset.size() > 0) { if (dataset.size() > 0) {
tsFilesService.deleteTsFilesByIds(dataset, "local"); tsFilesService.deleteTsFilesByIds(dataset, "local", taskId);
} }
} }
} }
@ -580,6 +674,9 @@ public class TsNodesServiceImpl extends ServiceImpl<TsNodesMapper, TsNodes> impl
if (tsNodesList.size() == 0) { if (tsNodesList.size() == 0) {
return true; return true;
} }
TsTask tsTask = tsTaskMapper.selectById(taskId);
StorageSource storageSource = getStorageConfig(tsTask.getLocalStorageId());
for (TsNodes tsNodes : tsNodesList) { for (TsNodes tsNodes : tsNodesList) {
//删除文件表 //删除文件表
@ -595,7 +692,7 @@ public class TsNodesServiceImpl extends ServiceImpl<TsNodesMapper, TsNodes> impl
BatchDeleteRequest batchDeleteRequest = new BatchDeleteRequest(); BatchDeleteRequest batchDeleteRequest = new BatchDeleteRequest();
batchDeleteRequest.setDeleteItems(deleteItemList); batchDeleteRequest.setDeleteItems(deleteItemList);
batchDeleteRequest.setStorageKey("local"); batchDeleteRequest.setStorageKey(storageSource.getKey());
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(batchDeleteRequest.getStorageKey()); AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(batchDeleteRequest.getStorageKey());
int deleteSuccessCount = 0, deleteFailCount = 0, totalCount = CollUtil.size(deleteItemList); int deleteSuccessCount = 0, deleteFailCount = 0, totalCount = CollUtil.size(deleteItemList);
@ -663,8 +760,11 @@ public class TsNodesServiceImpl extends ServiceImpl<TsNodesMapper, TsNodes> impl
***********************************/ ***********************************/
@Override @Override
public Object confirmDeleteNodes(String id) { public Object confirmDeleteNodes(String id) {
try {
JSONObject jsonObject = new JSONObject(); JSONObject jsonObject = new JSONObject();
TsNodes tsNodes = tsNodesMapper.selectById(id); TsNodes tsNodes = tsNodesMapper.selectById(id);
TsTask tsTask = tsTaskMapper.selectById(tsNodes.getTaskId());
TableNameContextHolder.setTaskCode(tsTask.getTaskCode());
if (tsNodes == null) { if (tsNodes == null) {
jsonObject.putOpt("status", "1"); jsonObject.putOpt("status", "1");
return ResponseResult.successData(jsonObject); return ResponseResult.successData(jsonObject);
@ -678,16 +778,23 @@ public class TsNodesServiceImpl extends ServiceImpl<TsNodesMapper, TsNodes> impl
jsonObject.putOpt("status", "1"); jsonObject.putOpt("status", "1");
} }
return ResponseResult.successData(jsonObject); return ResponseResult.successData(jsonObject);
} catch (Exception e) {
LOGGER.error("检查节点是否允许删除时发生异常: {}", e.getMessage(), e);
return ResponseResult.error("系统错误,请稍后重试");
} finally {
TableNameContextHolder.clear();
}
} }
private String testDataScanById(String id, LoginUser loginuser) throws Exception { private String testDataScanById(String id, LoginUser loginuser) throws Exception {
try {
//查询试验任务信息 //查询试验任务信息
TsTask tsTask = tsTaskMapper.selectById(id); TsTask tsTask = tsTaskMapper.selectById(id);
TableNameContextHolder.setTaskCode(tsTask.getTaskCode());
//文件的第一层是节点 下面的层级是文件夹 //文件的第一层是节点 下面的层级是文件夹
//获取文件列表 //获取文件列表
String absolutePath = "/" + tsTask.getTaskName() + "/"; String absolutePath = "/" + tsTask.getTaskName() + "/";
FileListRequest fileListRequest = buildFileRequest(absolutePath); FileListRequest fileListRequest = buildFileRequest(absolutePath, tsTask);
String storageKey = fileListRequest.getStorageKey(); String storageKey = fileListRequest.getStorageKey();
Integer storageId = storageSourceService.findIdByKey(storageKey); Integer storageId = storageSourceService.findIdByKey(storageKey);
if (storageId == null) { if (storageId == null) {
@ -705,6 +812,12 @@ public class TsNodesServiceImpl extends ServiceImpl<TsNodesMapper, TsNodes> impl
firstLayerData(fileItemList, id, loginuser); firstLayerData(fileItemList, id, loginuser);
return "扫描完成"; return "扫描完成";
} catch (Exception e) {
LOGGER.error("执行试验数据扫描时发生未知异常: {}", e.getMessage(), e);
return "扫描失败:" + e.getMessage();
} finally {
TableNameContextHolder.clear();
}
} }
/** /**
@ -715,7 +828,10 @@ public class TsNodesServiceImpl extends ServiceImpl<TsNodesMapper, TsNodes> impl
* @throws Exception * @throws Exception
*/ */
public void firstLayerData(List<FileItemResult> fileItemList, String taskId, LoginUser loginuser) throws Exception { public void firstLayerData(List<FileItemResult> fileItemList, String taskId, LoginUser loginuser) throws Exception {
// 设置当前时间
LocalDateTime now = LocalDateTime.now();
// 转换为 Timestamp
Timestamp currentTime = Timestamp.valueOf(now);
for (FileItemResult item : fileItemList) { for (FileItemResult item : fileItemList) {
//思路就是 如果是文件夹 就查询一下 没有就新增 新的的时候递归往下走 //思路就是 如果是文件夹 就查询一下 没有就新增 新的的时候递归往下走
if (item.getType() == FileTypeEnum.FOLDER) { if (item.getType() == FileTypeEnum.FOLDER) {
@ -730,9 +846,83 @@ public class TsNodesServiceImpl extends ServiceImpl<TsNodesMapper, TsNodes> impl
TsNodes node = savetsNodes(taskId, TOP_LEVEL_PARENT_NODE, item.getName()); TsNodes node = savetsNodes(taskId, TOP_LEVEL_PARENT_NODE, item.getName());
otherLevelsData(taskId, node.getNodeId(), item.getName(), item.getPath(), TOP_LEVEL_PARENT_NODE, loginuser); otherLevelsData(taskId, node.getNodeId(), item.getName(), item.getPath(), TOP_LEVEL_PARENT_NODE, loginuser);
} else { } else {
otherLevelsData(taskId, nodeData.getNodeId(), item.getName(), item.getPath(), TOP_LEVEL_PARENT_NODE, loginuser); //otherLevelsData(taskId, nodeData.getNodeId(), item.getName(), item.getPath(), TOP_LEVEL_PARENT_NODE, loginuser);
continue;
} }
} else {
//todo 如果是文件 首先判断表中有没有 如果没有 就新增 到节点名称为根节点的 节点下面
//查询节点表中 有没有根节点的节点 如果有就直接使用 如果没有就新增
LambdaQueryWrapper<TsNodes> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(TsNodes::getTaskId, taskId);
queryWrapper.eq(TsNodes::getParentId, TOP_LEVEL_PARENT_NODE);
queryWrapper.eq(TsNodes::getNodeName, "根节点");
TsNodes nodeData = tsNodesMapper.selectOne(queryWrapper);
if (nodeData == null) {
//新增一个根节点
TsNodes node = savetsNodes(taskId, TOP_LEVEL_PARENT_NODE, "根节点");
String finalPath = item.getPath().replace(item.getName(), "");
//保存文件信息
TsFiles tsFiles1 = new TsFiles();
//任务
tsFiles1.setTaskId(taskId);
//节点
tsFiles1.setNodeId(node.getNodeId());
//文件 文件夹 区分
tsFiles1.setIsFile("FILE");
//上级ID
tsFiles1.setParentId("00");
//文件名称
tsFiles1.setFileName(item.getName());
//工作空间路径
tsFiles1.setWorkPath(ensurePathFormat(finalPath));
tsFiles1.setUploadTime(currentTime);
tsFiles1.setUploader(loginuser.getUsername());
long bytes = item.getSize();
// 转换为 KB 并保留两位小数
double fileSizeInKB = bytes / (1024.0);
String fileSizeFormatted = String.format("%.2f", fileSizeInKB); // 保留两位小数
tsFiles1.setFileSize(fileSizeFormatted);
tsFilesMapper.insert(tsFiles1);
} else {
//先通过名称 + 节点 + 任务 + 路径 查询 如果有就跳过 没有就继续新增
LambdaQueryWrapper<TsFiles> queryWrapperFiles = new LambdaQueryWrapper<>();
queryWrapperFiles.eq(TsFiles::getNodeId, nodeData.getNodeId());
queryWrapperFiles.eq(TsFiles::getTaskId, taskId);
queryWrapperFiles.eq(TsFiles::getWorkPath, item.getPath());
queryWrapperFiles.eq(TsFiles::getFileName, item.getName());
TsFiles tsFiles = tsFilesMapper.selectOne(queryWrapperFiles);
if (tsFiles == null) {
String finalPath = item.getPath().replace(item.getName(), "");
//保存文件信息
TsFiles tsFiles1 = new TsFiles();
//任务
tsFiles1.setTaskId(taskId);
//节点
tsFiles1.setNodeId(nodeData.getNodeId());
//文件 文件夹 区分
tsFiles1.setIsFile("FILE");
//上级ID
tsFiles1.setParentId("00");
//文件名称
tsFiles1.setFileName(item.getName());
//工作空间路径
tsFiles1.setWorkPath(ensurePathFormat(finalPath));
tsFiles1.setUploadTime(currentTime);
tsFiles1.setUploader(loginuser.getUsername());
long bytes = item.getSize();
// 转换为 KB 并保留两位小数
double fileSizeInKB = bytes / (1024.0);
String fileSizeFormatted = String.format("%.2f", fileSizeInKB); // 保留两位小数
tsFiles1.setFileSize(fileSizeFormatted);
tsFilesMapper.insert(tsFiles1);
} else {
continue;
}
}
} }
} }
} }
@ -757,6 +947,7 @@ public class TsNodesServiceImpl extends ServiceImpl<TsNodesMapper, TsNodes> impl
// 查询本地文件路径根目录 E:\yun // 查询本地文件路径根目录 E:\yun
QueryWrapper<StorageSourceConfig> queryWrapper = new QueryWrapper<>(); QueryWrapper<StorageSourceConfig> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "filePath"); queryWrapper.eq("name", "filePath");
queryWrapper.eq("storage_id", "1");
queryWrapper.eq("type", "local"); queryWrapper.eq("type", "local");
StorageSourceConfig storageSourceConfig = storageSourceConfigMapper.selectOne(queryWrapper); StorageSourceConfig storageSourceConfig = storageSourceConfigMapper.selectOne(queryWrapper);
//获取文件列表 这个地方path+name //获取文件列表 这个地方path+name
@ -984,15 +1175,21 @@ public class TsNodesServiceImpl extends ServiceImpl<TsNodesMapper, TsNodes> impl
return node; return node;
} }
private FileListRequest buildFileRequest(String path) { private FileListRequest buildFileRequest(String path, TsTask tsTask) {
StorageSource storageSource = getStorageConfig(tsTask.getLocalStorageId());
FileListRequest fileListRequest = new FileListRequest(); FileListRequest fileListRequest = new FileListRequest();
fileListRequest.setOrderBy("time"); fileListRequest.setOrderBy("time");
fileListRequest.setOrderDirection("desc"); fileListRequest.setOrderDirection("desc");
fileListRequest.setPassword(""); fileListRequest.setPassword("");
fileListRequest.setPath(path); fileListRequest.setPath(path);
fileListRequest.setStorageKey("local"); fileListRequest.setStorageKey(storageSource.getKey());
return fileListRequest; return fileListRequest;
} }
// 辅助方法获取存储配置
private StorageSource getStorageConfig(Integer id) {
return storageSourceMapper.selectOne(new LambdaQueryWrapper<StorageSource>().eq(StorageSource::getId, id)
);
}
} }

View File

@ -18,13 +18,16 @@ import com.yfd.platform.modules.experimentalData.service.ITsFilesService;
import com.yfd.platform.modules.experimentalData.service.ITsNodesService; import com.yfd.platform.modules.experimentalData.service.ITsNodesService;
import com.yfd.platform.modules.experimentalData.service.ITsTaskService; import com.yfd.platform.modules.experimentalData.service.ITsTaskService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yfd.platform.modules.specialDocument.domain.Project;
import com.yfd.platform.modules.storage.context.StorageSourceContext; import com.yfd.platform.modules.storage.context.StorageSourceContext;
import com.yfd.platform.modules.storage.mapper.StorageSourceMapper;
import com.yfd.platform.modules.storage.model.entity.StorageSource;
import com.yfd.platform.modules.storage.model.entity.StorageSourceConfig;
import com.yfd.platform.modules.storage.model.enums.FileTypeEnum; import com.yfd.platform.modules.storage.model.enums.FileTypeEnum;
import com.yfd.platform.modules.storage.model.request.BatchDeleteRequest; import com.yfd.platform.modules.storage.model.request.BatchDeleteRequest;
import com.yfd.platform.modules.storage.model.request.NewFolderRequest; import com.yfd.platform.modules.storage.model.request.NewFolderRequest;
import com.yfd.platform.modules.storage.service.base.AbstractBaseFileService; import com.yfd.platform.modules.storage.service.base.AbstractBaseFileService;
import com.yfd.platform.utils.StringUtils; import com.yfd.platform.utils.StringUtils;
import com.yfd.platform.utils.TableNameContextHolder;
import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInboundHandlerAdapter;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -32,12 +35,17 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource; import java.sql.*;
import java.sql.Timestamp; import java.time.format.DateTimeFormatter;
import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.time.LocalDateTime;
/** /**
* <p> * <p>
* 试验任务表 服务实现类 * 试验任务表 服务实现类
@ -72,6 +80,11 @@ public class TsTaskServiceImpl extends ServiceImpl<TsTaskMapper, TsTask> impleme
@Resource @Resource
private StorageSourceContext storageSourceContext; private StorageSourceContext storageSourceContext;
@Resource
private StorageSourceMapper storageSourceMapper;
@Autowired
private DataSource dataSource;
private static final String INITIAL_CODE = "00001"; private static final String INITIAL_CODE = "00001";
private static final int MAX_CODE_VALUE = 99999; private static final int MAX_CODE_VALUE = 99999;
@ -169,8 +182,6 @@ public class TsTaskServiceImpl extends ServiceImpl<TsTaskMapper, TsTask> impleme
//生成任务名称 任务开始时间_结束时间_地点_载机名称_设备代号_编号 //生成任务名称 任务开始时间_结束时间_地点_载机名称_设备代号_编号
String taskName = buildTaskName(tsTask); String taskName = buildTaskName(tsTask);
tsTask.setTaskName(taskName); tsTask.setTaskName(taskName);
LambdaQueryWrapper<TsTask> queryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<TsTask> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(TsTask::getTaskName, tsTask.getTaskName()); queryWrapper.eq(TsTask::getTaskName, tsTask.getTaskName());
TsTask tsTask1 = tsTaskMapper.selectOne(queryWrapper); TsTask tsTask1 = tsTaskMapper.selectOne(queryWrapper);
@ -178,6 +189,8 @@ public class TsTaskServiceImpl extends ServiceImpl<TsTaskMapper, TsTask> impleme
throw new RuntimeException("试验任务管理项目已存在!"); throw new RuntimeException("试验任务管理项目已存在!");
} }
StorageSource storageSource = getStorageConfig(tsTask.getLocalStorageId());
// 设置当前时间 // 设置当前时间
LocalDateTime now = LocalDateTime.now(); LocalDateTime now = LocalDateTime.now();
// 转换为 Timestamp // 转换为 Timestamp
@ -193,10 +206,12 @@ public class TsTaskServiceImpl extends ServiceImpl<TsTaskMapper, TsTask> impleme
newFolderRequest.setName(tsTask.getTaskName());//新建的文件夹名称,示例值(/a/b/c) newFolderRequest.setName(tsTask.getTaskName());//新建的文件夹名称,示例值(/a/b/c)
newFolderRequest.setPassword("");//文件夹密码, 如果文件夹需要密码才能访问则支持请求密码,示例值(123456) newFolderRequest.setPassword("");//文件夹密码, 如果文件夹需要密码才能访问则支持请求密码,示例值(123456)
newFolderRequest.setPath(path);//请求路径,示例值(/) newFolderRequest.setPath(path);//请求路径,示例值(/)
newFolderRequest.setStorageKey("local");//存储源 key,示例值(local minio) newFolderRequest.setStorageKey(storageSource.getKey());//存储源 key,示例值(local minio)
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(newFolderRequest.getStorageKey()); AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(newFolderRequest.getStorageKey());
boolean flag = fileService.newFolder(newFolderRequest.getPath(), newFolderRequest.getName()); boolean flag = fileService.newFolder(newFolderRequest.getPath(), newFolderRequest.getName());
if (flag) { if (flag) {
// 动态创建数据表
createTaskFileTable(taskCode);
return true; return true;
} else { } else {
LOGGER.error("试验任务增加成功,但是本地试验任务文件夹创建失败"); LOGGER.error("试验任务增加成功,但是本地试验任务文件夹创建失败");
@ -208,12 +223,74 @@ public class TsTaskServiceImpl extends ServiceImpl<TsTaskMapper, TsTask> impleme
} }
// 动态创建任务文件表
private void createTaskFileTable(String taskCode) {
// 添加表名校验重要防止SQL注入
if (!taskCode.matches("^\\d{5}$")) { // 假设任务编号是5位数字
throw new IllegalArgumentException("非法任务编号格式: " + taskCode);
}
String tableName = "ts_files_" + taskCode;
String sql = String.format(
"CREATE TABLE IF NOT EXISTS `%s` LIKE `ts_files`",
tableName
);
try (Connection conn = dataSource.getConnection();
Statement stmt = conn.createStatement()) {
// 1. 记录要执行的SQL
LOGGER.info("执行DDL: {}", sql);
// 2. 执行SQL
boolean result = stmt.execute(sql);
// 3. 验证结果
LOGGER.debug("执行结果: {}", result);
// 4. 二次验证
if (!tableExists(tableName)) {
throw new RuntimeException("表创建后验证失败: " + tableName);
}
} catch (SQLException e) {
// 提取MySQL错误信息
String errorMsg = extractMysqlError(e);
LOGGER.error("创建表失败: {} - {}", tableName, errorMsg);
throw new RuntimeException("创建表失败: " + errorMsg, e);
}
}
private boolean tableExists(String tableName) {
try (Connection conn = dataSource.getConnection()) {
DatabaseMetaData meta = conn.getMetaData();
// 获取当前数据库信息
String catalog = conn.getCatalog();
String schema = conn.getSchema();
// 查询表是否存在
try (ResultSet rs = meta.getTables(catalog, schema, tableName, new String[]{"TABLE"})) {
return rs.next();
}
} catch (SQLException e) {
LOGGER.error("检查表存在失败: {}", tableName, e);
return false;
}
}
private String extractMysqlError(SQLException e) {
// 提取MySQL特有的错误信息
while (e != null) {
if (e.getMessage().contains("MySQL")) {
return String.format("MySQL 错误 [%d]: %s", e.getErrorCode(), e.getMessage());
}
e = e.getNextException();
}
return "未知数据库错误";
}
public static String buildTaskName(TsTask tsTask) { public static String buildTaskName(TsTask tsTask) {
List<String> parts = new ArrayList<>(); List<String> parts = new ArrayList<>();
// 定义日期格式化模板
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
// 按顺序添加非空字段 // 按顺序添加非空字段
addIfNotEmpty(parts, String.valueOf(tsTask.getTaskStartdate())); addIfNotEmpty(parts, formatDate(tsTask.getTaskStartdate(), formatter));
addIfNotEmpty(parts, String.valueOf(tsTask.getTaskEnddate())); addIfNotEmpty(parts, formatDate(tsTask.getTaskEnddate(), formatter));
addIfNotEmpty(parts, tsTask.getTaskPlace()); addIfNotEmpty(parts, tsTask.getTaskPlace());
addIfNotEmpty(parts, tsTask.getCarrierName()); addIfNotEmpty(parts, tsTask.getCarrierName());
addIfNotEmpty(parts, tsTask.getDeviceCode()); addIfNotEmpty(parts, tsTask.getDeviceCode());
@ -222,6 +299,15 @@ public class TsTaskServiceImpl extends ServiceImpl<TsTaskMapper, TsTask> impleme
return String.join("_", parts); return String.join("_", parts);
} }
// 格式化日期的方法
private static String formatDate(Object date, DateTimeFormatter formatter) {
if (date != null) {
return ((java.time.LocalDate) date).format(formatter);
}
return null;
}
private static void addIfNotEmpty(List<String> list, String value) { private static void addIfNotEmpty(List<String> list, String value) {
if (StringUtils.isNotBlank(value)) { // 使用Apache Commons Lang的空判断 if (StringUtils.isNotBlank(value)) { // 使用Apache Commons Lang的空判断
list.add(value.trim()); // 去除首尾空格 list.add(value.trim()); // 去除首尾空格
@ -262,10 +348,14 @@ public class TsTaskServiceImpl extends ServiceImpl<TsTaskMapper, TsTask> impleme
public boolean deleteTstaskByIds(List<String> dataset) { public boolean deleteTstaskByIds(List<String> dataset) {
Boolean value = false; Boolean value = false;
try {
//循环所有的ID //循环所有的ID
for (String taskId : dataset) { for (String taskId : dataset) {
//删除项目 //删除项目
TsTask tsTask = tsTaskMapper.selectById(taskId);
TableNameContextHolder.setTaskCode(tsTask.getTaskCode());
// 删除节点表 // 删除节点表
LambdaQueryWrapper<TsNodes> deleteWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<TsNodes> deleteWrapper = new LambdaQueryWrapper<>();
deleteWrapper.eq(TsNodes::getTaskId, taskId); deleteWrapper.eq(TsNodes::getTaskId, taskId);
@ -275,8 +365,10 @@ public class TsTaskServiceImpl extends ServiceImpl<TsTaskMapper, TsTask> impleme
LambdaQueryWrapper<TsFiles> deleteWrapperFiles = new LambdaQueryWrapper<>(); LambdaQueryWrapper<TsFiles> deleteWrapperFiles = new LambdaQueryWrapper<>();
deleteWrapperFiles.eq(TsFiles::getTaskId, taskId); deleteWrapperFiles.eq(TsFiles::getTaskId, taskId);
tsFilesMapper.delete(deleteWrapperFiles); tsFilesMapper.delete(deleteWrapperFiles);
//todo 删除文件表数据
// tsFilesMapper.deleteSdFilesBytaskId(taskId);
TsTask tsTask = tsTaskMapper.selectById(taskId);
// String path = "/" + tsTask.getTaskName() + "/"; // String path = "/" + tsTask.getTaskName() + "/";
// //调用删除节点 根据任务ID // //调用删除节点 根据任务ID
// Boolean deleteTsnodes = tsNodesService.deleteTsNodesByTaskId(taskId, path); // Boolean deleteTsnodes = tsNodesService.deleteTsNodesByTaskId(taskId, path);
@ -289,7 +381,7 @@ public class TsTaskServiceImpl extends ServiceImpl<TsTaskMapper, TsTask> impleme
// value = false; // value = false;
// } // }
StorageSource storageSource = getStorageConfig(tsTask.getLocalStorageId());
// 删除 local 中的文件夹 项目文件夹 // 删除 local 中的文件夹 项目文件夹
List<BatchDeleteRequest.DeleteItem> deleteItemList = new ArrayList<>(); List<BatchDeleteRequest.DeleteItem> deleteItemList = new ArrayList<>();
BatchDeleteRequest.DeleteItem deleteItemData = new BatchDeleteRequest.DeleteItem(); BatchDeleteRequest.DeleteItem deleteItemData = new BatchDeleteRequest.DeleteItem();
@ -301,7 +393,7 @@ public class TsTaskServiceImpl extends ServiceImpl<TsTaskMapper, TsTask> impleme
BatchDeleteRequest batchDeleteRequest = new BatchDeleteRequest(); BatchDeleteRequest batchDeleteRequest = new BatchDeleteRequest();
batchDeleteRequest.setDeleteItems(deleteItemList); batchDeleteRequest.setDeleteItems(deleteItemList);
batchDeleteRequest.setStorageKey("local"); batchDeleteRequest.setStorageKey(storageSource.getKey());
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(batchDeleteRequest.getStorageKey()); AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(batchDeleteRequest.getStorageKey());
int deleteSuccessCount = 0, deleteFailCount = 0, totalCount = CollUtil.size(deleteItemList); int deleteSuccessCount = 0, deleteFailCount = 0, totalCount = CollUtil.size(deleteItemList);
@ -342,6 +434,12 @@ public class TsTaskServiceImpl extends ServiceImpl<TsTaskMapper, TsTask> impleme
} }
return value;
} catch (Exception e) {
} finally {
TableNameContextHolder.clear();
}
return value; return value;
} }
@ -352,20 +450,53 @@ public class TsTaskServiceImpl extends ServiceImpl<TsTaskMapper, TsTask> impleme
***********************************/ ***********************************/
@Override @Override
public Object confirmDeleteTask(List<String> dataset) { public Object confirmDeleteTask(List<String> dataset) {
JSONObject jsonObject = new JSONObject(); try {
// 删除 getBackupPath getWorkPath 都为空的记录 LambdaQueryWrapper<TsTask> queryWrapperTsk = new LambdaQueryWrapper<>();
queryWrapperTsk.in(TsTask::getId, dataset);
List<TsTask> tsTasks = tsTaskMapper.selectList(queryWrapperTsk);
JSONObject result = new JSONObject();
boolean allDeletable = true;
for (TsTask tsTask : tsTasks) {
TableNameContextHolder.setTaskCode(tsTask.getTaskCode());
// 查询是否有备份路径或非空路径的文件
LambdaQueryWrapper<TsFiles> queryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<TsFiles> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(TsFiles::getTaskId, dataset) queryWrapper.eq(TsFiles::getTaskId, tsTask.getId())
.and(wrapper -> wrapper.isNotNull(TsFiles::getBackupPath) .and(wrapper -> wrapper.isNotNull(TsFiles::getBackupPath)
.or().ne(TsFiles::getBackupPath, "")); .or().ne(TsFiles::getBackupPath, ""));
int count = tsFilesService.count(queryWrapper); int count = tsFilesService.count(queryWrapper);
//如果大于0不让删
if (count > 0) { if (count > 0) {
jsonObject.putOpt("status", "0"); allDeletable = false;
} else { break; // 一旦发现不可删除项提前终止循环
jsonObject.putOpt("status", "1");
} }
return ResponseResult.successData(jsonObject); }
result.putOpt("status", allDeletable ? "1" : "0");
return ResponseResult.successData(result);
} catch (Exception e) {
// 使用日志框架代替 printStackTrace
LOGGER.error("确认删除实验任务时发生异常", e);
return ResponseResult.error("查询失败");
} finally {
TableNameContextHolder.clear();
}
}
@Override
public List<TsTask> listTsTask() {
LambdaQueryWrapper<TsTask> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.orderByDesc(TsTask::getTaskStartdate);
List<TsTask> tsTasks = tsTaskMapper.selectList(queryWrapper);
for (TsTask tsTask : tsTasks){
StorageSource storageSource = getStorageConfig(tsTask.getLocalStorageId());
tsTask.setKey(storageSource.getKey());
}
return tsTasks;
} }
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
@ -398,4 +529,10 @@ public class TsTaskServiceImpl extends ServiceImpl<TsTaskMapper, TsTask> impleme
} }
} }
// 辅助方法获取存储配置
private StorageSource getStorageConfig( Integer id) {
return storageSourceMapper.selectOne(new LambdaQueryWrapper<StorageSource>().eq(StorageSource::getId, id)
);
}
} }

View File

@ -161,9 +161,7 @@ public class ProjectController {
@ResponseBody @ResponseBody
//@PreAuthorize("@el.check('select:devicesignal')") //@PreAuthorize("@el.check('select:devicesignal')")
public ResponseResult listSdproject() { public ResponseResult listSdproject() {
LambdaQueryWrapper<Project> queryWrapper = new LambdaQueryWrapper<>(); List<Project> projects = projectService.listProject();
queryWrapper.orderByDesc(Project::getProjectTime);
List<Project> projects = projectService.list(queryWrapper);
return ResponseResult.successData(projects); return ResponseResult.successData(projects);
} }

View File

@ -6,6 +6,7 @@ import java.sql.Timestamp;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.io.Serializable; import java.io.Serializable;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data; import lombok.Data;
@ -91,4 +92,22 @@ public class Project implements Serializable {
private String custom3; private String custom3;
/**
* 本地存储空间id
*/
private Integer localStorageId;
/**
* 上传用到KEYTODO 增加用于前端展示
*/
@TableField(exist = false)
private String key;
/**
* 上传用到typeTODO 增加用于前端展示
*/
@TableField(exist = false)
private String type;
} }

View File

@ -1,9 +1,11 @@
package com.yfd.platform.modules.specialDocument.mapper; package com.yfd.platform.modules.specialDocument.mapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yfd.platform.modules.specialDocument.domain.Files; import com.yfd.platform.modules.specialDocument.domain.Files;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import java.util.Date;
import java.util.List; import java.util.List;
/** /**
@ -22,4 +24,33 @@ public interface FilesMapper extends BaseMapper<Files> {
//根据节点删除文件递归子节点文件 //根据节点删除文件递归子节点文件
int deleteByNodeId(@Param("nodeId")String nodeId); int deleteByNodeId(@Param("nodeId")String nodeId);
void updateFileByPath(@Param("projectId") String projectId,@Param("oldBasePath") String oldBasePath,@Param("newBasePath") String newBasePath);
//分页查询文件表
Page<Files> selectFilesPage(@Param("page") Page<Files> page,
@Param("fileName") String fileName,
@Param("keywords") String keywords,
@Param("startDate") Date startDate,
@Param("endDate") Date endDate,
@Param("projectId") String projectId,
@Param("nodeId") String nodeId,
@Param("fileName1") String fileName1,
@Param("tableName") String tableName
);
//插入文件表
int insertSdFilesTable(@Param("tableName") String tableName, @Param("files") Files filess);
//更新文件表
int updateSdFiles(@Param("tableName") String tableName, @Param("files") Files files);
//批量查询文件表
List<Files> selectSdFilesBatchIds(@Param("dataset") List<String> dataset,@Param("tableName") String tableName);
//删除文件表
int deleteSdFiles(@Param("tableName") String tableName, @Param("files") Files files);
//查询文件表根据ID
Files selectSdFilesById(@Param("tableName") String tableName, @Param("id") String id);
} }

View File

@ -2,6 +2,7 @@ package com.yfd.platform.modules.specialDocument.mapper;
import com.yfd.platform.modules.specialDocument.domain.Nodes; import com.yfd.platform.modules.specialDocument.domain.Nodes;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import java.util.List; import java.util.List;
@ -20,4 +21,6 @@ public interface NodesMapper extends BaseMapper<Nodes> {
int updateParentIdByPathHierarchy(); int updateParentIdByPathHierarchy();
int deleteNodesRecursively(String nodeId); int deleteNodesRecursively(String nodeId);
void updateNodesByPath(@Param("projectId") String projectId,@Param("oldBasePath") String oldBasePath,@Param("newBasePath") String newBasePath);
} }

View File

@ -2,6 +2,7 @@ package com.yfd.platform.modules.specialDocument.mapper;
import com.yfd.platform.modules.specialDocument.domain.Project; import com.yfd.platform.modules.specialDocument.domain.Project;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
/** /**
* <p> * <p>
@ -13,4 +14,8 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
*/ */
public interface ProjectMapper extends BaseMapper<Project> { public interface ProjectMapper extends BaseMapper<Project> {
// 新增动态建表方法
static int createFileTable(@Param("tableName") String tableName) {
return 0;
}
} }

View File

@ -46,4 +46,6 @@ public interface IProjectService extends IService<Project> {
boolean deleteProjectByIds(List<String> dataset); boolean deleteProjectByIds(List<String> dataset);
String generateNextProjectCode(); String generateNextProjectCode();
List<Project> listProject();
} }

View File

@ -11,16 +11,18 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yfd.platform.config.ResponseResult; import com.yfd.platform.config.ResponseResult;
import com.yfd.platform.exception.file.InvalidStorageSourceException; import com.yfd.platform.exception.file.InvalidStorageSourceException;
import com.yfd.platform.modules.config.model.request.FileListRequest; import com.yfd.platform.modules.config.model.request.FileListRequest;
import com.yfd.platform.modules.experimentalData.domain.TsFiles;
import com.yfd.platform.modules.specialDocument.domain.Files; import com.yfd.platform.modules.specialDocument.domain.Files;
import com.yfd.platform.modules.specialDocument.domain.Project;
import com.yfd.platform.modules.specialDocument.mapper.FilesMapper; import com.yfd.platform.modules.specialDocument.mapper.FilesMapper;
import com.yfd.platform.modules.specialDocument.mapper.ProjectMapper;
import com.yfd.platform.modules.specialDocument.service.IFilesService; import com.yfd.platform.modules.specialDocument.service.IFilesService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yfd.platform.modules.storage.chain.FileChain; import com.yfd.platform.modules.storage.chain.FileChain;
import com.yfd.platform.modules.storage.chain.FileContext;
import com.yfd.platform.modules.storage.context.StorageSourceContext; import com.yfd.platform.modules.storage.context.StorageSourceContext;
import com.yfd.platform.modules.storage.controller.file.FileController; import com.yfd.platform.modules.storage.controller.file.FileController;
import com.yfd.platform.modules.storage.mapper.StorageSourceConfigMapper; import com.yfd.platform.modules.storage.mapper.StorageSourceConfigMapper;
import com.yfd.platform.modules.storage.mapper.StorageSourceMapper;
import com.yfd.platform.modules.storage.model.entity.StorageSource;
import com.yfd.platform.modules.storage.model.entity.StorageSourceConfig; import com.yfd.platform.modules.storage.model.entity.StorageSourceConfig;
import com.yfd.platform.modules.storage.model.enums.FileTypeEnum; import com.yfd.platform.modules.storage.model.enums.FileTypeEnum;
import com.yfd.platform.modules.storage.model.request.BatchDeleteRequest; import com.yfd.platform.modules.storage.model.request.BatchDeleteRequest;
@ -81,7 +83,9 @@ public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements
private FilesMapper filesMapper; private FilesMapper filesMapper;
@Autowired @Autowired
private FileController fileController; private ProjectMapper projectMapper;
@Resource
private StorageSourceMapper storageSourceMapper;
@Resource @Resource
private StorageSourceContext storageSourceContext; private StorageSourceContext storageSourceContext;
@ -223,9 +227,11 @@ public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements
public FileItemResult sdLocalUrl(String id) { public FileItemResult sdLocalUrl(String id) {
FileItemResult fileItemResult = new FileItemResult(); FileItemResult fileItemResult = new FileItemResult();
Files files = filesMapper.selectById(id); Files files = filesMapper.selectById(id);
Project project = projectMapper.selectById(files.getProjectId());
StorageSource storageSource = storageSourceMapper.selectById(project.getLocalStorageId());
String pathAndName = files.getFilePath() + files.getFileName(); String pathAndName = files.getFilePath() + files.getFileName();
//准备获取文件的信息 //准备获取文件的信息
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey("sdlocal"); AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(storageSource.getKey());
fileItemResult = fileService.getFileItem(pathAndName); fileItemResult = fileService.getFileItem(pathAndName);
return fileItemResult; return fileItemResult;
} }
@ -299,13 +305,13 @@ public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements
if (authentication != null) { if (authentication != null) {
loginuser = (LoginUser) authentication.getPrincipal(); loginuser = (LoginUser) authentication.getPrincipal();
} }
Project project = projectMapper.selectById(files.getProjectId());
StorageSource storageSource = getStorageConfig(project.getLocalStorageId());
//新增之前从处理一下源路径的数据 ,String sourcePath,String targetPath //新增之前从处理一下源路径的数据 ,String sourcePath,String targetPath
// 查询本地文件路径根目录 E:\yun // 查询本地文件路径根目录 E:\yun
QueryWrapper<StorageSourceConfig> queryWrapper = new QueryWrapper<>(); StorageSourceConfig storageSourceConfig = getStorageSourceConfig("filePath","local",project.getLocalStorageId());
queryWrapper.eq("name", "filePath");
queryWrapper.eq("type", "sdlocal");
StorageSourceConfig storageSourceConfig = storageSourceConfigMapper.selectOne(queryWrapper);
//源路径 临时路径 //源路径 临时路径
String sourceFilePath = files.getSourcePath(); String sourceFilePath = files.getSourcePath();
//目标路径 //目标路径
@ -322,7 +328,7 @@ public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements
//校验是否真正上传 //校验是否真正上传
String pathAndName = filess.getFilePath() + filess.getFileName(); String pathAndName = filess.getFilePath() + filess.getFileName();
//准备获取文件的信息 //准备获取文件的信息
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey("sdlocal"); AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(storageSource.getKey());
FileItemResult fileItemResult = fileService.getFileItem(pathAndName); FileItemResult fileItemResult = fileService.getFileItem(pathAndName);
if (fileItemResult == null || fileItemResult.getName() == null) { if (fileItemResult == null || fileItemResult.getName() == null) {
return ResponseResult.error(filess.getFileName() + "文件没有上传到空间,请重新选择上传!"); return ResponseResult.error(filess.getFileName() + "文件没有上传到空间,请重新选择上传!");
@ -380,8 +386,8 @@ public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements
LocalDateTime now = LocalDateTime.now(); LocalDateTime now = LocalDateTime.now();
// 转换为 Timestamp // 转换为 Timestamp
Timestamp currentTime = Timestamp.valueOf(now); Timestamp currentTime = Timestamp.valueOf(now);
FileListRequest sourcefileListRequest = buildFileRequest(sourceFilePath); FileListRequest sourcefileListRequest = buildFileRequest(sourceFilePath,files.getProjectId());
FileListRequest targetfileListRequest = buildFileRequest(targetFilePath); FileListRequest targetfileListRequest = buildFileRequest(targetFilePath,files.getProjectId());
//获取源文件列表 包含文件和文件夹 //获取源文件列表 包含文件和文件夹
List<FileItemResult> sourceFileItemList = obtainFileItemResultData(sourcefileListRequest); List<FileItemResult> sourceFileItemList = obtainFileItemResultData(sourcefileListRequest);
@ -583,13 +589,16 @@ public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements
return fileItemList; return fileItemList;
} }
private FileListRequest buildFileRequest(String path) { private FileListRequest buildFileRequest(String path,String projectId) {
Project project = projectMapper.selectById(projectId);
StorageSource storageSource = getStorageConfig(project.getLocalStorageId());
FileListRequest fileListRequest = new FileListRequest(); FileListRequest fileListRequest = new FileListRequest();
fileListRequest.setOrderBy("time"); fileListRequest.setOrderBy("time");
fileListRequest.setOrderDirection("desc"); fileListRequest.setOrderDirection("desc");
fileListRequest.setPassword(""); fileListRequest.setPassword("");
fileListRequest.setPath(path); fileListRequest.setPath(path);
fileListRequest.setStorageKey("sdlocal"); fileListRequest.setStorageKey(storageSource.getKey());
return fileListRequest; return fileListRequest;
} }
@ -673,6 +682,8 @@ public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements
redisTemplate.delete(redisKey); redisTemplate.delete(redisKey);
} }
int SuccessCount = 0, FailCount = 0, total = CollUtil.size(dataset); int SuccessCount = 0, FailCount = 0, total = CollUtil.size(dataset);
Project project = projectMapper.selectById(filesList.get(0).getProjectId());
StorageSource storageSource = getStorageConfig(project.getLocalStorageId());
//Todo 最直接的办法 循环出来 一条一条删除 //Todo 最直接的办法 循环出来 一条一条删除
for (Files files : filesList) { for (Files files : filesList) {
@ -689,7 +700,7 @@ public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements
BatchDeleteRequest batchDeleteRequest = new BatchDeleteRequest(); BatchDeleteRequest batchDeleteRequest = new BatchDeleteRequest();
batchDeleteRequest.setDeleteItems(deleteItemList); batchDeleteRequest.setDeleteItems(deleteItemList);
batchDeleteRequest.setStorageKey("sdlocal"); batchDeleteRequest.setStorageKey(storageSource.getKey());
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(batchDeleteRequest.getStorageKey()); AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(batchDeleteRequest.getStorageKey());
List<BatchDeleteRequest.DeleteItem> deleteItems = batchDeleteRequest.getDeleteItems(); List<BatchDeleteRequest.DeleteItem> deleteItems = batchDeleteRequest.getDeleteItems();
@ -745,12 +756,15 @@ public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements
// 修改 sdlocal 文件名的方法 // 修改 sdlocal 文件名的方法
private boolean updateMinioFileName(Files filesData, Files files) { private boolean updateMinioFileName(Files filesData, Files files) {
try { try {
Project project = projectMapper.selectById(files.getProjectId());
StorageSource storageSource = getStorageConfig(project.getLocalStorageId());
RenameFileRequest renameFileRequest = new RenameFileRequest(); RenameFileRequest renameFileRequest = new RenameFileRequest();
renameFileRequest.setName(filesData.getFileName()); renameFileRequest.setName(filesData.getFileName());
renameFileRequest.setNewName(files.getFileName()); renameFileRequest.setNewName(files.getFileName());
renameFileRequest.setPassword(""); renameFileRequest.setPassword("");
renameFileRequest.setPath(filesData.getFilePath()); renameFileRequest.setPath(filesData.getFilePath());
renameFileRequest.setStorageKey("sdlocal"); renameFileRequest.setStorageKey(storageSource.getKey());
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(renameFileRequest.getStorageKey()); AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(renameFileRequest.getStorageKey());
return fileService.renameFile(renameFileRequest.getPath(), renameFileRequest.getName(), renameFileRequest.getNewName()); return fileService.renameFile(renameFileRequest.getPath(), renameFileRequest.getName(), renameFileRequest.getNewName());
@ -759,4 +773,17 @@ public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements
return false; return false;
} }
} }
// 辅助方法获取存储配置
private StorageSource getStorageConfig(Integer id) {
return storageSourceMapper.selectOne(new LambdaQueryWrapper<StorageSource>().eq(StorageSource::getId, id)
);
}
// 辅助方法获取存储配置
private StorageSourceConfig getStorageSourceConfig(String name, String type,Integer id) {
return storageSourceConfigMapper.selectOne(
new LambdaQueryWrapper<StorageSourceConfig>().eq(StorageSourceConfig::getName, name).eq(StorageSourceConfig::getType, type).eq(StorageSourceConfig::getStorageId,id)
);
}
} }

View File

@ -3,8 +3,6 @@ package com.yfd.platform.modules.specialDocument.service.impl;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.io.FileUtil;
import com.amazonaws.util.IOUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yfd.platform.component.TaskStatusHolder; import com.yfd.platform.component.TaskStatusHolder;
@ -23,6 +21,8 @@ import com.yfd.platform.modules.specialDocument.service.INodesService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yfd.platform.modules.storage.context.StorageSourceContext; import com.yfd.platform.modules.storage.context.StorageSourceContext;
import com.yfd.platform.modules.storage.mapper.StorageSourceConfigMapper; import com.yfd.platform.modules.storage.mapper.StorageSourceConfigMapper;
import com.yfd.platform.modules.storage.mapper.StorageSourceMapper;
import com.yfd.platform.modules.storage.model.entity.StorageSource;
import com.yfd.platform.modules.storage.model.entity.StorageSourceConfig; import com.yfd.platform.modules.storage.model.entity.StorageSourceConfig;
import com.yfd.platform.modules.storage.model.enums.FileTypeEnum; import com.yfd.platform.modules.storage.model.enums.FileTypeEnum;
import com.yfd.platform.modules.storage.model.request.BatchDeleteRequest; import com.yfd.platform.modules.storage.model.request.BatchDeleteRequest;
@ -41,6 +41,7 @@ import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Async;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
@ -100,10 +101,17 @@ public class NodesServiceImpl extends ServiceImpl<NodesMapper, Nodes> implements
@Autowired @Autowired
private TaskStatusHolder taskStatusHolder; private TaskStatusHolder taskStatusHolder;
@Resource
private StorageSourceMapper storageSourceMapper;
//专项项目表Mapper //专项项目表Mapper
@Resource @Resource
private ProjectMapper projectMapper; private ProjectMapper projectMapper;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
//顶级父节点 Top level parent node //顶级父节点 Top level parent node
public static final String TOP_LEVEL_PARENT_NODE = "00"; public static final String TOP_LEVEL_PARENT_NODE = "00";
@ -301,6 +309,9 @@ public class NodesServiceImpl extends ServiceImpl<NodesMapper, Nodes> implements
@Transactional(rollbackFor = Exception.class) // 添加事务注解遇到异常时回滚 @Transactional(rollbackFor = Exception.class) // 添加事务注解遇到异常时回滚
public ResponseResult addNodes(Nodes nodes) { public ResponseResult addNodes(Nodes nodes) {
Project project = projectMapper.selectById(nodes.getProjectId());
StorageSource storageSource = getStorageConfig(project.getLocalStorageId());
// 校验文件名是否包含非法字符 // 校验文件名是否包含非法字符
String nodeName = nodes.getNodeName(); String nodeName = nodes.getNodeName();
if (containsInvalidCharacters(nodeName)) { if (containsInvalidCharacters(nodeName)) {
@ -362,7 +373,7 @@ public class NodesServiceImpl extends ServiceImpl<NodesMapper, Nodes> implements
newFolderRequest.setName(nodes.getNodeName());//新建的文件夹名称,示例值(/a/b/c) newFolderRequest.setName(nodes.getNodeName());//新建的文件夹名称,示例值(/a/b/c)
newFolderRequest.setPassword("");//文件夹密码, 如果文件夹需要密码才能访问则支持请求密码,示例值(123456) newFolderRequest.setPassword("");//文件夹密码, 如果文件夹需要密码才能访问则支持请求密码,示例值(123456)
newFolderRequest.setPath(nodes.getPath());//请求路径,示例值(/) newFolderRequest.setPath(nodes.getPath());//请求路径,示例值(/)
newFolderRequest.setStorageKey("sdlocal");//存储源 key,示例值(local minio sdlocal) newFolderRequest.setStorageKey(storageSource.getKey());//存储源 key,示例值(local minio sdlocal)
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(newFolderRequest.getStorageKey()); AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(newFolderRequest.getStorageKey());
boolean flag = fileService.newFolder(newFolderRequest.getPath(), newFolderRequest.getName()); boolean flag = fileService.newFolder(newFolderRequest.getPath(), newFolderRequest.getName());
if (flag) { if (flag) {
@ -392,6 +403,9 @@ public class NodesServiceImpl extends ServiceImpl<NodesMapper, Nodes> implements
if (containsInvalidCharacters(nodeName)) { if (containsInvalidCharacters(nodeName)) {
return ResponseResult.error("文件名包含非法字符(<>:\"/\\|?*"); return ResponseResult.error("文件名包含非法字符(<>:\"/\\|?*");
} }
Project project = projectMapper.selectById(nodes.getProjectId());
StorageSource storageSource = getStorageConfig(project.getLocalStorageId());
//查询没改之前的节点名称 //查询没改之前的节点名称
Nodes nodesold = nodesMapper.selectById(nodes.getId()); Nodes nodesold = nodesMapper.selectById(nodes.getId());
@ -401,9 +415,6 @@ public class NodesServiceImpl extends ServiceImpl<NodesMapper, Nodes> implements
nodeNameOld = nodesold.getNodeName(); nodeNameOld = nodesold.getNodeName();
} }
//获取专项文档项目
Project project = projectMapper.selectById(nodes.getProjectId());
//获取当前登录用户 //获取当前登录用户
UsernamePasswordAuthenticationToken authentication = UsernamePasswordAuthenticationToken authentication =
(UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
@ -424,30 +435,57 @@ public class NodesServiceImpl extends ServiceImpl<NodesMapper, Nodes> implements
if (count > 0) { if (count > 0) {
return ResponseResult.error("节点名称已存在!"); return ResponseResult.error("节点名称已存在!");
} }
//更新当前数据
int valueUpdate = nodesMapper.updateById(nodes); int valueUpdate = nodesMapper.updateById(nodes);
// 4. 递归获取所有子节点ID包含当前节点 // 2. 构建新旧路径
List<String> affectedNodeIds = getAllChildNodeIds(nodes.getId()); String oldBasePath = nodes.getPath() + nodeNameOld + "/";
String newBasePath = nodes.getPath() + nodeName + "/";
// 5. 更新相关文件路径 //3.跟新节点表sd_nodes表 根据所属项目ID 老路径 和新路径
updateFilePaths(affectedNodeIds, nodes.getProjectId(), nodeNameOld, nodeName); nodesMapper.updateNodesByPath(nodes.getProjectId(), oldBasePath, newBasePath);
//4.更新文件表sd_files表 根据所属项目ID 老路径 和新路径
filesMapper.updateFileByPath(nodes.getProjectId(), oldBasePath, newBasePath);
//获取项目下面的所有子节点 都清除缓存
List<Nodes> nodesList = nodesMapper.selectList(new QueryWrapper<Nodes>().eq("project_id", nodes.getProjectId()));
if ((nodesList != null) && (nodesList.size() > 0)) {
for (Nodes node : nodesList) {
//todo 修改节点成功以后 删除redis
for (int page = 1; page <= 5; page++) {
String redisKey = "sdfiles_" + node.getProjectId() + "_" + node.getId() + "_page_" + page;
redisTemplate.delete(redisKey);
}
LOGGER.info("已清理缓存project={}, node={}, pages=1-5", nodes.getProjectId(), nodes.getId());
}
}
//判断如果更新了节点名称
if (!nodeName.equals(nodeNameOld)) {
// // 4. 递归获取所有子节点ID包含当前节点
// List<String> affectedNodeIds = getAllChildNodeIds(nodes.getId());
//
// // 5. 更新相关文件路径
// updateFilePaths(affectedNodeIds, nodes.getProjectId(), nodeNameOld, nodeName);
if (valueUpdate == 1) { if (valueUpdate == 1) {
List<String> pathNodes = new ArrayList<>(); // List<String> pathNodes = new ArrayList<>();
Nodes nodesData = nodesMapper.selectById(nodes.getParentId()); // Nodes nodesData = nodesMapper.selectById(nodes.getParentId());
// 从当前节点向上遍历直到根节点 // // 从当前节点向上遍历直到根节点
while (nodesData != null) { // while (nodesData != null) {
pathNodes.add(nodesData.getNodeName()); // pathNodes.add(nodesData.getNodeName());
// 如果父节点是 "00"说明已经到了根节点停止遍历 // // 如果父节点是 "00"说明已经到了根节点停止遍历
if ("00".equals(nodesData.getParentId())) { // if ("00".equals(nodesData.getParentId())) {
break; // break;
} // }
// 获取父节点 // // 获取父节点
nodesData = nodesMapper.selectById(nodesData.getParentId()); // 修正 nodesData 中获取 parentId // nodesData = nodesMapper.selectById(nodesData.getParentId()); // 修正 nodesData 中获取 parentId
} // }
// 反转路径使其从根节点到当前节点 // // 反转路径使其从根节点到当前节点
Collections.reverse(pathNodes); // Collections.reverse(pathNodes);
String path = String.join("/", pathNodes); // String path = String.join("/", pathNodes);
//修改文件名称 //修改文件名称
RenameFolderRequest renameFolderRequest = new RenameFolderRequest(); RenameFolderRequest renameFolderRequest = new RenameFolderRequest();
@ -455,7 +493,7 @@ public class NodesServiceImpl extends ServiceImpl<NodesMapper, Nodes> implements
renameFolderRequest.setNewName(nodeName);// 重命名后的文件名称,示例值(music) renameFolderRequest.setNewName(nodeName);// 重命名后的文件名称,示例值(music)
renameFolderRequest.setPassword("");//文件夹密码, 如果文件夹需要密码才能访问则支持请求密码,示例值(123456) renameFolderRequest.setPassword("");//文件夹密码, 如果文件夹需要密码才能访问则支持请求密码,示例值(123456)
renameFolderRequest.setPath(nodes.getPath());//请求路径,示例值(/) renameFolderRequest.setPath(nodes.getPath());//请求路径,示例值(/)
renameFolderRequest.setStorageKey("sdlocal");//存储源 key,示例值(local minio sdlocal) renameFolderRequest.setStorageKey(storageSource.getKey());//存储源 key,示例值(local minio sdlocal)
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(renameFolderRequest.getStorageKey()); AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(renameFolderRequest.getStorageKey());
boolean flag = fileService.renameFolder(renameFolderRequest.getPath(), renameFolderRequest.getName(), renameFolderRequest.getNewName()); boolean flag = fileService.renameFolder(renameFolderRequest.getPath(), renameFolderRequest.getName(), renameFolderRequest.getNewName());
if (flag) { if (flag) {
@ -468,6 +506,14 @@ public class NodesServiceImpl extends ServiceImpl<NodesMapper, Nodes> implements
LOGGER.error("节点修改失败"); LOGGER.error("节点修改失败");
return ResponseResult.error(); return ResponseResult.error();
} }
} else {
if (valueUpdate == 1) {
return ResponseResult.success("重命名成功");
} else {
return ResponseResult.error("重命名失败");
}
}
} }
// 校验文件名是否包含非法字符 // 校验文件名是否包含非法字符
@ -545,6 +591,8 @@ public class NodesServiceImpl extends ServiceImpl<NodesMapper, Nodes> implements
if (nodes == null) { if (nodes == null) {
return false; // 节点不存在 return false; // 节点不存在
} }
Project project = projectMapper.selectById(nodes.getProjectId());
StorageSource storageSource = getStorageConfig(project.getLocalStorageId());
// //递归获取当前节点和它下面的所有节点 // //递归获取当前节点和它下面的所有节点
// List<Nodes> nodesList = selectChildrenNodes(id, nodes.getProjectId()); // List<Nodes> nodesList = selectChildrenNodes(id, nodes.getProjectId());
// // 提取所有节点的 ID // // 提取所有节点的 ID
@ -581,7 +629,7 @@ public class NodesServiceImpl extends ServiceImpl<NodesMapper, Nodes> implements
BatchDeleteRequest batchDeleteRequest = new BatchDeleteRequest(); BatchDeleteRequest batchDeleteRequest = new BatchDeleteRequest();
batchDeleteRequest.setDeleteItems(deleteItemList); batchDeleteRequest.setDeleteItems(deleteItemList);
batchDeleteRequest.setStorageKey("sdlocal"); batchDeleteRequest.setStorageKey(storageSource.getKey());
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(batchDeleteRequest.getStorageKey()); AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(batchDeleteRequest.getStorageKey());
int deleteSuccessCount = 0, deleteFailCount = 0, totalCount = CollUtil.size(deleteItemList); int deleteSuccessCount = 0, deleteFailCount = 0, totalCount = CollUtil.size(deleteItemList);
@ -699,12 +747,13 @@ public class NodesServiceImpl extends ServiceImpl<NodesMapper, Nodes> implements
//查询项目信息 //查询项目信息
Project project = projectMapper.selectById(id); Project project = projectMapper.selectById(id);
StorageSource storageSource = getStorageConfig(project.getLocalStorageId());
// 查询本地文件路径根目录 E:\yun // 查询本地文件路径根目录 E:\yun
QueryWrapper<StorageSourceConfig> queryWrapper = new QueryWrapper<>(); QueryWrapper<StorageSourceConfig> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "filePath"); queryWrapper.eq("name", "filePath");
queryWrapper.eq("type", "sdlocal"); queryWrapper.eq("storage_id", project.getLocalStorageId());
queryWrapper.eq("type", storageSource.getType());
StorageSourceConfig storageSourceConfig = storageSourceConfigMapper.selectOne(queryWrapper); StorageSourceConfig storageSourceConfig = storageSourceConfigMapper.selectOne(queryWrapper);
//获取文件列表 //获取文件列表
@ -944,7 +993,7 @@ public class NodesServiceImpl extends ServiceImpl<NodesMapper, Nodes> implements
String absolutePath = path + nodeName + "/"; String absolutePath = path + nodeName + "/";
//获取文件列表 //获取文件列表
FileListRequest fileListRequest = buildFileRequest(absolutePath); FileListRequest fileListRequest = buildFileRequest(absolutePath,projectId);
String storageKey = fileListRequest.getStorageKey(); String storageKey = fileListRequest.getStorageKey();
Integer storageId = storageSourceService.findIdByKey(storageKey); Integer storageId = storageSourceService.findIdByKey(storageKey);
if (storageId == null) { if (storageId == null) {
@ -1012,13 +1061,15 @@ public class NodesServiceImpl extends ServiceImpl<NodesMapper, Nodes> implements
return map.get(adjustedIndex); return map.get(adjustedIndex);
} }
private FileListRequest buildFileRequest(String path) { private FileListRequest buildFileRequest(String path,String projectId) {
Project project = projectMapper.selectById(projectId);
StorageSource storageSource = getStorageConfig(project.getLocalStorageId());
FileListRequest fileListRequest = new FileListRequest(); FileListRequest fileListRequest = new FileListRequest();
fileListRequest.setOrderBy("time"); fileListRequest.setOrderBy("time");
fileListRequest.setOrderDirection("desc"); fileListRequest.setOrderDirection("desc");
fileListRequest.setPassword(""); fileListRequest.setPassword("");
fileListRequest.setPath(path); fileListRequest.setPath(path);
fileListRequest.setStorageKey("sdlocal"); fileListRequest.setStorageKey(storageSource.getKey());
return fileListRequest; return fileListRequest;
} }
@ -1123,14 +1174,14 @@ public class NodesServiceImpl extends ServiceImpl<NodesMapper, Nodes> implements
try { try {
// 1. 优化合并重复的异常捕获 // 1. 优化合并重复的异常捕获
//------------------------------------------ //------------------------------------------
// 查询存储配置
StorageSourceConfig config = getStorageConfig();
if (config == null) throw new RuntimeException("未找到本地存储路径配置");
// 优化提前验证项目存在性避免后续无效操作 // 优化提前验证项目存在性避免后续无效操作
Project project = projectMapper.selectById(id); Project project = projectMapper.selectById(id);
if (project == null) throw new RuntimeException("项目不存在: " + id); if (project == null) throw new RuntimeException("项目不存在: " + id);
// 查询存储配置 wrapper.eq("name", "filePath").eq("type", "sdlocal");
StorageSourceConfig config = getStorageSourceConfig("filePath", "local", project.getLocalStorageId());
if (config == null) throw new RuntimeException("未找到本地存储路径配置");
// 优化解压路径统一构建逻辑 // 优化解压路径统一构建逻辑
final String tempDir = "temporary"; final String tempDir = "temporary";
final String zipName = getFileNameWithoutExtension(fileName); final String zipName = getFileNameWithoutExtension(fileName);
@ -1172,12 +1223,7 @@ public class NodesServiceImpl extends ServiceImpl<NodesMapper, Nodes> implements
} }
} }
// 新增辅助方法解耦核心逻辑 --------------------------------------------------
private StorageSourceConfig getStorageConfig() {
QueryWrapper<StorageSourceConfig> wrapper = new QueryWrapper<>();
wrapper.eq("name", "filePath").eq("type", "sdlocal");
return storageSourceConfigMapper.selectOne(wrapper);
}
private void transferProjectFiles(String projectId, String basePath, String sourceDir, String targetDir) throws Exception { private void transferProjectFiles(String projectId, String basePath, String sourceDir, String targetDir) throws Exception {
String sourcePath = "/temporary/" + sourceDir + "/"; String sourcePath = "/temporary/" + sourceDir + "/";
@ -1201,78 +1247,7 @@ public class NodesServiceImpl extends ServiceImpl<NodesMapper, Nodes> implements
} }
} }
// public void documentUploadByIdAsync(String id, String fileName, LoginUser loginuser) throws IOException {
// try {
//
// // 查询本地文件路径根目录 E:\yun
// QueryWrapper<StorageSourceConfig> queryWrapper = new QueryWrapper<>();
// queryWrapper.eq("name", "filePath");
// queryWrapper.eq("type", "sdlocal");
// StorageSourceConfig storageSourceConfig = storageSourceConfigMapper.selectOne(queryWrapper);
//
// if (storageSourceConfig == null) {
// throw new RuntimeException("未找到本地存储路径配置");
// }
//
// //解压以后的文件夹名称
// String zipName = getFileNameWithoutExtension(fileName); // 示例222
//
// //查询项目信息
// Project project = projectMapper.selectById(id);
// if (project == null) {
// throw new RuntimeException("项目不存在");
// }
//
// if (!project.getProjectName().equals(zipName)) {
// throw new RuntimeException("压缩包名称需要和项目名称保持一致");
// }
//
// String decompressionPath = "/" + "temporary";
// //构建要解压的zip文件路径 例如 D:\yun\temporary\111.zip
// Path zipFilePath = Paths.get(storageSourceConfig.getValue(), decompressionPath, fileName);
// // 4. 构建解压目标路径 例如 D:\yun\temporary\111
// Path destRoot = Paths.get(storageSourceConfig.getValue(), decompressionPath);
//
// LOGGER.info("要解压文件路径:{}", zipFilePath);
// LOGGER.info("解压以后文件路径:{}", destRoot);
//
//
// //todo 如果项目不存在 直接拷贝到目标路径下 拷贝完成以后 然后新增一个项目结构 然后走一遍扫描
//
// //源文件夹路径
// String sourceFolderPath = "/" + "temporary" + "/" + zipName + "/";
// //目标文件夹路径
// String targetFolderPath = "/" + project.getProjectName() + "/";
//
// //首先执行解压缩
// unzipToTemp(zipFilePath, String.valueOf(destRoot));
// // 执行上传并且插入数据库
// this.documentUploadById(id, sourceFolderPath, targetFolderPath, storageSourceConfig.getValue());
// //开始执行更新表数据 名称是去掉后缀以后的
// uploadProject(zipName, loginuser);
// LOGGER.info("开始更新表数据:{}", zipName);
//
// //获取文件路径
// Path destRootPath = Paths.get(storageSourceConfig.getValue(), decompressionPath, zipName);
// File targetZip = new File(String.valueOf(zipFilePath));
// File target = new File(String.valueOf(destRootPath));
// //删除临时文件ZIP
// deleteDirectory(targetZip);
// //删除临时文件
// deleteDirectory(target);
// } catch (IOException e) {
// throw new RuntimeException(e);
// } catch (Exception e) {
// throw new RuntimeException(e);
// } finally {
// // 生成唯一Key
// String asyncKey = taskStatusHolder.documentUploadKey(id);
// // 无论成功失败都标记完成
// taskStatusHolder.finishTask(asyncKey);
// WebSocketServer.sendMessageTo("专项文档上传任务处理完成!", "projectId_" + id);
//
// }
// }
public static void deleteDirectory(File directory) throws Exception { public static void deleteDirectory(File directory) throws Exception {
if (!directory.exists()) { if (!directory.exists()) {
@ -1317,8 +1292,8 @@ public class NodesServiceImpl extends ServiceImpl<NodesMapper, Nodes> implements
return null; return null;
} }
FileListRequest sourcefileListRequest = buildFileRequest(sourceFolderPath); FileListRequest sourcefileListRequest = buildFileRequest(sourceFolderPath, id);
FileListRequest targetfileListRequest = buildFileRequest(targetFolderPath); FileListRequest targetfileListRequest = buildFileRequest(targetFolderPath, id);
//获取源文件列表 包含文件和文件夹 //获取源文件列表 包含文件和文件夹
List<FileItemResult> sourceFileItemList = obtainFileItemResultData(sourcefileListRequest); List<FileItemResult> sourceFileItemList = obtainFileItemResultData(sourcefileListRequest);
@ -1415,8 +1390,10 @@ public class NodesServiceImpl extends ServiceImpl<NodesMapper, Nodes> implements
LambdaQueryWrapper<Project> projectLambdaQueryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<Project> projectLambdaQueryWrapper = new LambdaQueryWrapper<>();
projectLambdaQueryWrapper.eq(Project::getProjectName, projectName); projectLambdaQueryWrapper.eq(Project::getProjectName, projectName);
Project project = projectMapper.selectOne(projectLambdaQueryWrapper); Project project = projectMapper.selectOne(projectLambdaQueryWrapper);
//如果项目不存在 //如果项目不存在
if (project == null) { if (project == null) {
StorageSource storageSource = getStorageConfig(project.getLocalStorageId());
String projectCode = this.generateNextProjectCode(); String projectCode = this.generateNextProjectCode();
project.setProjectCode("1"); project.setProjectCode("1");
@ -1435,7 +1412,7 @@ public class NodesServiceImpl extends ServiceImpl<NodesMapper, Nodes> implements
newFolderRequest.setName(project.getProjectName());//新建的文件夹名称,示例值(/a/b/c) newFolderRequest.setName(project.getProjectName());//新建的文件夹名称,示例值(/a/b/c)
newFolderRequest.setPassword("");//文件夹密码, 如果文件夹需要密码才能访问则支持请求密码,示例值(123456) newFolderRequest.setPassword("");//文件夹密码, 如果文件夹需要密码才能访问则支持请求密码,示例值(123456)
newFolderRequest.setPath(path);//请求路径,示例值(/) newFolderRequest.setPath(path);//请求路径,示例值(/)
newFolderRequest.setStorageKey("sdlocal");//存储源 key,示例值(local minio) newFolderRequest.setStorageKey(storageSource.getKey());//存储源 key,示例值(local minio)
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(newFolderRequest.getStorageKey()); AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(newFolderRequest.getStorageKey());
boolean flag = fileService.newFolder(newFolderRequest.getPath(), newFolderRequest.getName()); boolean flag = fileService.newFolder(newFolderRequest.getPath(), newFolderRequest.getName());
} }
@ -1748,5 +1725,21 @@ public class NodesServiceImpl extends ServiceImpl<NodesMapper, Nodes> implements
} }
} }
// 辅助方法获取存储配置
private StorageSource getStorageConfig( Integer id) {
return storageSourceMapper.selectOne(new LambdaQueryWrapper<StorageSource>().eq(StorageSource::getId, id)
);
}
// 辅助方法获取存储配置
private StorageSourceConfig getStorageSourceConfig(String name, String type,Integer id) {
return storageSourceConfigMapper.selectOne(
new LambdaQueryWrapper<StorageSourceConfig>().eq(StorageSourceConfig::getName, name).eq(StorageSourceConfig::getType, type).eq(StorageSourceConfig::getStorageId,id)
);
}
} }

View File

@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yfd.platform.modules.specialDocument.domain.Files;
import com.yfd.platform.modules.specialDocument.domain.Nodes; import com.yfd.platform.modules.specialDocument.domain.Nodes;
import com.yfd.platform.modules.specialDocument.domain.Project; import com.yfd.platform.modules.specialDocument.domain.Project;
import com.yfd.platform.modules.specialDocument.mapper.ProjectMapper; import com.yfd.platform.modules.specialDocument.mapper.ProjectMapper;
@ -12,23 +11,26 @@ import com.yfd.platform.modules.specialDocument.service.INodesService;
import com.yfd.platform.modules.specialDocument.service.IProjectService; import com.yfd.platform.modules.specialDocument.service.IProjectService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yfd.platform.modules.storage.context.StorageSourceContext; import com.yfd.platform.modules.storage.context.StorageSourceContext;
import com.yfd.platform.modules.storage.mapper.StorageSourceMapper;
import com.yfd.platform.modules.storage.model.entity.StorageSource;
import com.yfd.platform.modules.storage.model.enums.FileTypeEnum; 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.BatchDeleteRequest;
import com.yfd.platform.modules.storage.model.request.NewFolderRequest; import com.yfd.platform.modules.storage.model.request.NewFolderRequest;
import com.yfd.platform.modules.storage.service.base.AbstractBaseFileService; import com.yfd.platform.modules.storage.service.base.AbstractBaseFileService;
import com.yfd.platform.system.mapper.SysDictionaryItemsMapper;
import com.yfd.platform.utils.StringUtils; import com.yfd.platform.utils.StringUtils;
import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInboundHandlerAdapter;
import net.bytebuddy.implementation.bytecode.Throw;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.sql.Timestamp; import javax.sql.DataSource;
import java.sql.*;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
@ -57,13 +59,16 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
@Resource @Resource
private INodesService nodesService; private INodesService nodesService;
//字典表Mapper
@Resource
private SysDictionaryItemsMapper sysDictionaryItemsMapper;
@Resource @Resource
private StorageSourceContext storageSourceContext; private StorageSourceContext storageSourceContext;
@Resource
private StorageSourceMapper storageSourceMapper;
@Autowired
private DataSource dataSource;
/********************************** /**********************************
* 用途说明: 分页查询专项文档管理-项目管理 * 用途说明: 分页查询专项文档管理-项目管理
* 参数说明 * 参数说明
@ -125,6 +130,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
// 转换为 Timestamp // 转换为 Timestamp
Timestamp currentTime = Timestamp.valueOf(now); Timestamp currentTime = Timestamp.valueOf(now);
project.setCreateTime(currentTime); project.setCreateTime(currentTime);
StorageSource storageSource = getStorageConfig(project.getLocalStorageId());
LambdaQueryWrapper<Project> queryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<Project> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Project::getProjectName,project.getProjectName()); queryWrapper.eq(Project::getProjectName,project.getProjectName());
@ -144,10 +150,13 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
newFolderRequest.setName(project.getProjectName());//新建的文件夹名称,示例值(/a/b/c) newFolderRequest.setName(project.getProjectName());//新建的文件夹名称,示例值(/a/b/c)
newFolderRequest.setPassword("");//文件夹密码, 如果文件夹需要密码才能访问则支持请求密码,示例值(123456) newFolderRequest.setPassword("");//文件夹密码, 如果文件夹需要密码才能访问则支持请求密码,示例值(123456)
newFolderRequest.setPath(path);//请求路径,示例值(/) newFolderRequest.setPath(path);//请求路径,示例值(/)
newFolderRequest.setStorageKey("sdlocal");//存储源 key,示例值(local minio) newFolderRequest.setStorageKey(storageSource.getKey());//存储源 key,示例值(local minio)
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(newFolderRequest.getStorageKey()); AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(newFolderRequest.getStorageKey());
boolean flag = fileService.newFolder(newFolderRequest.getPath(), newFolderRequest.getName()); boolean flag = fileService.newFolder(newFolderRequest.getPath(), newFolderRequest.getName());
if (flag) { if (flag) {
// 动态创建数据表
//createTaskFileTable(projectCode);
return true; return true;
} else { } else {
LOGGER.error("节点新增成功,但是本地专项文件夹创建失败"); LOGGER.error("节点新增成功,但是本地专项文件夹创建失败");
@ -158,31 +167,67 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
return false; return false;
} }
}
// //查询字典表获取项目类型对应数据字典 // 动态创建任务文件表
// QueryWrapper<SysDictionaryItems> queryWrapperSysDictionary = new QueryWrapper<>(); private void createTaskFileTable(String taskCode) {
// queryWrapperSysDictionary.eq("parentcode", "compressType");
// queryWrapperSysDictionary.orderByAsc("orderno");
// SysDictionaryItems sysDictionaryItems = sysDictionaryItemsMapper.selectOne(queryWrapperSysDictionary);
// if(sysDictionaryItems != null){
// project.setProjectType(sysDictionaryItems.getDictName());
// }
// 添加表名校验重要防止SQL注入
if (!taskCode.matches("^\\d{5}$")) { // 假设任务编号是5位数字
throw new IllegalArgumentException("非法任务编号格式: " + taskCode);
}
//TODO 01.21沟通以后说是先不用管重复校验问题 String tableName = "sd_files_" + taskCode;
// //通过项目名称 项目编号查询 查看是否存在 String sql = String.format(
// QueryWrapper<Project> queryWrapper = new QueryWrapper<>(); "CREATE TABLE IF NOT EXISTS `%s` LIKE `sd_files`",
// if(project.getProjectCode() != null){ tableName
// queryWrapper.eq("project_code",project.getProjectCode()); );
// } try (Connection conn = dataSource.getConnection();
// if(project.getProjectName() != null){ Statement stmt = conn.createStatement()) {
// queryWrapper.eq("project_name",project.getProjectName()); // 1. 记录要执行的SQL
// } LOGGER.info("执行DDL: {}", sql);
// List<Project> projects = projectMapper.selectList(queryWrapper); // 2. 执行SQL
// if(){ boolean result = stmt.execute(sql);
// // 3. 验证结果
// } LOGGER.debug("执行结果: {}", result);
// 4. 二次验证
if (!tableExists(tableName)) {
throw new RuntimeException("表创建后验证失败: " + tableName);
}
} catch (SQLException e) {
// 提取MySQL错误信息
String errorMsg = extractMysqlError(e);
LOGGER.error("创建表失败: {} - {}", tableName, errorMsg);
throw new RuntimeException("创建表失败: " + errorMsg, e);
}
}
private boolean tableExists(String tableName) {
try (Connection conn = dataSource.getConnection()) {
DatabaseMetaData meta = conn.getMetaData();
// 获取当前数据库信息
String catalog = conn.getCatalog();
String schema = conn.getSchema();
// 查询表是否存在
try (ResultSet rs = meta.getTables(catalog, schema, tableName, new String[]{"TABLE"})) {
return rs.next();
}
} catch (SQLException e) {
LOGGER.error("检查表存在失败: {}", tableName, e);
return false;
}
}
private String extractMysqlError(SQLException e) {
// 提取MySQL特有的错误信息
while (e != null) {
if (e.getMessage().contains("MySQL")) {
return String.format("MySQL 错误 [%d]: %s", e.getErrorCode(), e.getMessage());
}
e = e.getNextException();
}
return "未知数据库错误";
} }
// 编号生成工具方法 // 编号生成工具方法
@ -216,6 +261,8 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
} }
/********************************** /**********************************
* 用途说明: 修改专项文档管理-项目管理 * 用途说明: 修改专项文档管理-项目管理
* 参数说明 * 参数说明
@ -256,6 +303,8 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
//循环所有的ID //循环所有的ID
for (String id : dataset) { for (String id : dataset) {
Project project = projectMapper.selectById(id); Project project = projectMapper.selectById(id);
StorageSource storageSource = getStorageConfig(project.getLocalStorageId());
String path = "/" + project.getProjectName() + "/"; String path = "/" + project.getProjectName() + "/";
QueryWrapper<Nodes> queryWrapper = new QueryWrapper<>(); QueryWrapper<Nodes> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("project_id", id); queryWrapper.eq("project_id", id);
@ -288,7 +337,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
BatchDeleteRequest batchDeleteRequest = new BatchDeleteRequest(); BatchDeleteRequest batchDeleteRequest = new BatchDeleteRequest();
batchDeleteRequest.setDeleteItems(deleteItemList); batchDeleteRequest.setDeleteItems(deleteItemList);
batchDeleteRequest.setStorageKey("sdlocal"); batchDeleteRequest.setStorageKey(storageSource.getKey());
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(batchDeleteRequest.getStorageKey()); AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(batchDeleteRequest.getStorageKey());
int deleteSuccessCount = 0, deleteFailCount = 0, totalCount = CollUtil.size(deleteItemList); int deleteSuccessCount = 0, deleteFailCount = 0, totalCount = CollUtil.size(deleteItemList);
@ -330,4 +379,23 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
} }
return value; return value;
} }
@Override
public List<Project> listProject() {
LambdaQueryWrapper<Project> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.orderByDesc(Project::getProjectTime);
List<Project> projects = projectMapper.selectList(queryWrapper);
for (Project project : projects){
StorageSource storageSource = getStorageConfig(project.getLocalStorageId());
project.setKey(storageSource.getKey());
project.setType(String.valueOf(storageSource.getType()));
}
return projects;
}
// 辅助方法获取存储配置
private StorageSource getStorageConfig(Integer id) {
return storageSourceMapper.selectOne(new LambdaQueryWrapper<StorageSource>().eq(StorageSource::getId, id)
);
}
} }

View File

@ -13,6 +13,8 @@ import com.yfd.platform.modules.storage.model.entity.StorageSource;
import com.yfd.platform.modules.storage.model.entity.StorageSourceConfig; import com.yfd.platform.modules.storage.model.entity.StorageSourceConfig;
import com.yfd.platform.modules.storage.model.enums.StorageTypeEnum; import com.yfd.platform.modules.storage.model.enums.StorageTypeEnum;
import com.yfd.platform.modules.storage.model.param.IStorageParam; import com.yfd.platform.modules.storage.model.param.IStorageParam;
import com.yfd.platform.modules.storage.service.StorageSourceConfigService;
import com.yfd.platform.modules.storage.service.StorageSourceService;
import com.yfd.platform.modules.storage.service.base.AbstractBaseFileService; import com.yfd.platform.modules.storage.service.base.AbstractBaseFileService;
import com.yfd.platform.modules.storage.support.StorageSourceSupport; import com.yfd.platform.modules.storage.support.StorageSourceSupport;
import com.yfd.platform.utils.ClassUtils; import com.yfd.platform.utils.ClassUtils;
@ -176,12 +178,23 @@ public class StorageSourceContext {
* *
* @return 存储源对应未初始化的 Service * @return 存储源对应未初始化的 Service
*/ */
private AbstractBaseFileService<IStorageParam> getInitStorageBeanByStorageId(Integer storageId) { // private AbstractBaseFileService<IStorageParam> getInitStorageBeanByStorageId(Integer storageId) {
String keyById = storageSourceMapper.findKeyById(storageId); // String keyById = storageSourceMapper.findKeyById(storageId);
StorageSource storageSource = storageSourceMapper.findByStorageKey(keyById); //// StorageSource storageSource = storageSourceMapper.findByStorageKey(keyById);
String type = String.valueOf(storageSource.getType()); // storageSourceMapper
//// String type = String.valueOf(storageSource.getType());
//
// StorageTypeEnum storageTypeEnum = Optional.ofNullable(storageSourceMapper.findByStorageKey(keyById)).map(StorageSource::getType).orElse(null);
// for (AbstractBaseFileService<?> value : storageTypeEnumFileServiceMap.values()) {
// if (Objects.equals(value.getStorageTypeEnum(), storageTypeEnum)) {
// return SpringUtil.getBean(value.getClass());
// }
// }
// return null;
// }
StorageTypeEnum storageTypeEnum = Optional.ofNullable(storageSourceMapper.findByStorageKey(keyById)).map(StorageSource::getType).orElse(null); private AbstractBaseFileService<IStorageParam> getInitStorageBeanByStorageId(Integer storageId) {
StorageTypeEnum storageTypeEnum = Optional.ofNullable(this.findById(storageId)).map(StorageSource::getType).orElse(null);;
for (AbstractBaseFileService<?> value : storageTypeEnumFileServiceMap.values()) { for (AbstractBaseFileService<?> value : storageTypeEnumFileServiceMap.values()) {
if (Objects.equals(value.getStorageTypeEnum(), storageTypeEnum)) { if (Objects.equals(value.getStorageTypeEnum(), storageTypeEnum)) {
return SpringUtil.getBean(value.getClass()); return SpringUtil.getBean(value.getClass());
@ -190,6 +203,9 @@ public class StorageSourceContext {
return null; return null;
} }
public StorageSource findById(Integer id) {
return storageSourceMapper.selectById(id);
}
/** /**
* 获取指定存储源的初始化参数. * 获取指定存储源的初始化参数.

View File

@ -1,14 +1,17 @@
package com.yfd.platform.modules.storage.controller.base; package com.yfd.platform.modules.storage.controller.base;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSort; import com.github.xiaoymin.knife4j.annotations.ApiSort;
import com.yfd.platform.config.ResponseResult; import com.yfd.platform.config.ResponseResult;
import com.yfd.platform.modules.config.model.request.SaveStorageSourceRequest; import com.yfd.platform.modules.config.model.request.SaveStorageSourceRequest;
import com.yfd.platform.modules.config.model.request.UpdateStorageSortRequest; import com.yfd.platform.modules.config.model.request.UpdateStorageSortRequest;
import com.yfd.platform.modules.experimentalData.domain.TsFiles;
import com.yfd.platform.modules.storage.convert.StorageSourceConvert; import com.yfd.platform.modules.storage.convert.StorageSourceConvert;
import com.yfd.platform.modules.storage.model.dto.StorageSourceDTO; import com.yfd.platform.modules.storage.model.dto.StorageSourceDTO;
import com.yfd.platform.modules.storage.model.entity.StorageSource; import com.yfd.platform.modules.storage.model.entity.StorageSource;
import com.yfd.platform.modules.storage.model.enums.SearchModeEnum;
import com.yfd.platform.modules.storage.model.result.StorageSourceAdminResult; import com.yfd.platform.modules.storage.model.result.StorageSourceAdminResult;
import com.yfd.platform.modules.storage.service.StorageSourceService; import com.yfd.platform.modules.storage.service.StorageSourceService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
@ -48,6 +51,33 @@ public class StorageSourceController {
return ResponseResult.successData(storageSourceAdminResults); return ResponseResult.successData(storageSourceAdminResults);
} }
@ApiOperationSupport(order = 11)
@ApiOperation(value = "根据类型获取所有存储源列表", notes = "根据类型获取所有添加的存储源列表,按照排序值由小到大排序")
@GetMapping("/storagesBytype")
public ResponseResult storageListBytype(String type) {
List<StorageSource> list = storageSourceService.findAllOrderByOrderNumByType(type);
List<StorageSourceAdminResult> storageSourceAdminResults = storageSourceConvert.entityToAdminResultList(list);
return ResponseResult.successData(storageSourceAdminResults);
}
@ApiOperationSupport(order = 10)
@ApiOperation(value = "分页获取所有存储源列表", notes = "分页获取所有添加的存储源列表,按照排序值由小到大排序")
@GetMapping("/storagesPage")
public ResponseResult storagePage(Page<StorageSource> page,String type,String name) {
Page<StorageSource> pageResult = storageSourceService.findAllOrderByOrderNumPage(page, type,name);
Page<StorageSourceAdminResult> storageSourceAdminResults = storageSourceConvert.entityToAdminResultPage(pageResult);
return ResponseResult.successData(storageSourceAdminResults);
}
@ApiOperationSupport(order = 12)
@ApiOperation(value = "通过key查询type", notes = "通过key查询type")
@GetMapping("/storagesType")
public ResponseResult storagesType(String key) {
StorageSource storageSource = storageSourceService.findAllOrderBystoragesType(key);
return ResponseResult.successData(storageSource);
}
@ApiOperationSupport(order = 2) @ApiOperationSupport(order = 2)
@ApiOperation(value = "获取指定存储源参数", notes = "获取指定存储源基本信息及其参数") @ApiOperation(value = "获取指定存储源参数", notes = "获取指定存储源基本信息及其参数")
@ -63,6 +93,10 @@ public class StorageSourceController {
@ApiOperation(value = "保存存储源参数", notes = "保存存储源的所有参数") @ApiOperation(value = "保存存储源参数", notes = "保存存储源的所有参数")
@PostMapping("/storage") @PostMapping("/storage")
public ResponseResult saveStorageItem(@RequestBody SaveStorageSourceRequest saveStorageSourceRequest) { public ResponseResult saveStorageItem(@RequestBody SaveStorageSourceRequest saveStorageSourceRequest) {
saveStorageSourceRequest.setEnable( true);
saveStorageSourceRequest.setEnableFileOperator( true);
saveStorageSourceRequest.setSearchMode(SearchModeEnum.SEARCH_CACHE_MODE);
saveStorageSourceRequest.setEnableFileAnnoOperator(false);
Integer id = storageSourceService.saveStorageSource(saveStorageSourceRequest); Integer id = storageSourceService.saveStorageSource(saveStorageSourceRequest);
return ResponseResult.successData(id); return ResponseResult.successData(id);
} }
@ -78,6 +112,7 @@ public class StorageSourceController {
} }
@ApiOperationSupport(order = 5) @ApiOperationSupport(order = 5)
@ApiOperation(value = "启用存储源", notes = "开启存储源后可在前台显示") @ApiOperation(value = "启用存储源", notes = "开启存储源后可在前台显示")
@ApiImplicitParam(paramType = "path", name = "storageId", value = "存储源 id", required = true, dataTypeClass = Integer.class) @ApiImplicitParam(paramType = "path", name = "storageId", value = "存储源 id", required = true, dataTypeClass = Integer.class)

View File

@ -1,5 +1,6 @@
package com.yfd.platform.modules.storage.convert; package com.yfd.platform.modules.storage.convert;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yfd.platform.modules.config.model.request.SaveStorageSourceRequest; import com.yfd.platform.modules.config.model.request.SaveStorageSourceRequest;
import com.yfd.platform.modules.readme.model.entity.ReadmeConfig; import com.yfd.platform.modules.readme.model.entity.ReadmeConfig;
import com.yfd.platform.modules.storage.model.dto.StorageSourceAllParamDTO; import com.yfd.platform.modules.storage.model.dto.StorageSourceAllParamDTO;
@ -53,6 +54,7 @@ public interface StorageSourceConvert {
*/ */
List<StorageSourceAdminResult> entityToAdminResultList(List<StorageSource> list); List<StorageSourceAdminResult> entityToAdminResultList(List<StorageSource> list);
Page<StorageSourceAdminResult> entityToAdminResultPage(Page<StorageSource> pageResult);
StorageSourceDTO entityToDTO(StorageSource storageSource, StorageSourceAllParamDTO storageSourceAllParam); StorageSourceDTO entityToDTO(StorageSource storageSource, StorageSourceAllParamDTO storageSourceAllParam);
@ -68,4 +70,5 @@ public interface StorageSourceConvert {
StorageSource saveRequestToEntity(SaveStorageSourceRequest saveStorageSourceRequest); StorageSource saveRequestToEntity(SaveStorageSourceRequest saveStorageSourceRequest);
} }

View File

@ -1,18 +1,31 @@
package com.yfd.platform.modules.storage.convert.impl; package com.yfd.platform.modules.storage.convert.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yfd.platform.modules.config.model.request.SaveStorageSourceRequest; import com.yfd.platform.modules.config.model.request.SaveStorageSourceRequest;
import com.yfd.platform.modules.experimentalData.domain.TsTask;
import com.yfd.platform.modules.experimentalData.mapper.TsTaskMapper;
import com.yfd.platform.modules.readme.model.entity.ReadmeConfig; import com.yfd.platform.modules.readme.model.entity.ReadmeConfig;
import com.yfd.platform.modules.specialDocument.domain.Project;
import com.yfd.platform.modules.specialDocument.mapper.ProjectMapper;
import com.yfd.platform.modules.storage.convert.StorageSourceConvert; import com.yfd.platform.modules.storage.convert.StorageSourceConvert;
import com.yfd.platform.modules.storage.mapper.StorageSourceConfigMapper;
import com.yfd.platform.modules.storage.model.dto.StorageSourceAllParamDTO; import com.yfd.platform.modules.storage.model.dto.StorageSourceAllParamDTO;
import com.yfd.platform.modules.storage.model.dto.StorageSourceDTO; import com.yfd.platform.modules.storage.model.dto.StorageSourceDTO;
import com.yfd.platform.modules.storage.model.entity.StorageSource; import com.yfd.platform.modules.storage.model.entity.StorageSource;
import com.yfd.platform.modules.storage.model.entity.StorageSourceConfig;
import com.yfd.platform.modules.storage.model.result.StorageSourceAdminResult; import com.yfd.platform.modules.storage.model.result.StorageSourceAdminResult;
import com.yfd.platform.modules.storage.model.result.StorageSourceConfigResult; import com.yfd.platform.modules.storage.model.result.StorageSourceConfigResult;
import com.yfd.platform.modules.storage.model.result.StorageSourceResult; import com.yfd.platform.modules.storage.model.result.StorageSourceResult;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.File;
import java.text.DecimalFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
/** /**
* @Date: 2025/1/10 12:44 * @Date: 2025/1/10 12:44
@ -21,6 +34,18 @@ import java.util.List;
@Service @Service
public class StorageSourceConvertImpl implements StorageSourceConvert { public class StorageSourceConvertImpl implements StorageSourceConvert {
@Resource
private StorageSourceConfigMapper storageSourceConfigMapper;
//专项项目表Mapper
@Resource
private ProjectMapper projectMapper;
//试验任务Mapper
@Resource
private TsTaskMapper tsTaskMapper;
@Override @Override
public List<StorageSourceResult> entityToResultList(List<StorageSource> list) { public List<StorageSourceResult> entityToResultList(List<StorageSource> list) {
if ( list == null ) { if ( list == null ) {
@ -58,16 +83,125 @@ public class StorageSourceConvertImpl implements StorageSourceConvert {
@Override @Override
public List<StorageSourceAdminResult> entityToAdminResultList(List<StorageSource> list) { public List<StorageSourceAdminResult> entityToAdminResultList(List<StorageSource> list) {
if (list == null) { if (list == null) {
return null; return Collections.emptyList();
} }
List<StorageSourceAdminResult> list1 = new ArrayList<StorageSourceAdminResult>( list.size() ); return list.stream()
for ( StorageSource storageSource : list ) { .map(this::storageSourceToStorageSourceAdminResult)
list1.add( storageSourceToStorageSourceAdminResult( storageSource ) ); .collect(Collectors.toList());
} }
return list1; @Override
public Page<StorageSourceAdminResult> entityToAdminResultPage(Page<StorageSource> sourcePage) {
if (sourcePage == null) {
return new Page<>();
} }
List<StorageSource> recordData = sourcePage.getRecords();
for (StorageSource storageSource : recordData) {
StringBuilder result = new StringBuilder(); // 用于拼接结果
String type = storageSource.getType().getKey();
if ("local".equals(type)) {
//获取关联的存储内容 先获取专项文档
LambdaQueryWrapper<Project> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Project::getLocalStorageId, storageSource.getId());
List<Project> projects = projectMapper.selectList(queryWrapper);
if (projects.size()>0){
for (Project project : projects) {
if (result.length() > 0) {
result.append(", "); // 如果结果不为空加上逗号分隔
}
result.append(project.getProjectName()); // 添加项目名称
}
}
LambdaQueryWrapper<TsTask> queryWrapper1 = new LambdaQueryWrapper<>();
queryWrapper1.eq(TsTask::getLocalStorageId, storageSource.getId());
List<TsTask> tsTasks = tsTaskMapper.selectList(queryWrapper1);
if (tsTasks.size()>0){
for (TsTask task : tsTasks) {
if (result.length() > 0) {
result.append(", "); // 如果结果不为空加上逗号分隔
}
result.append(task.getTaskName()); // 添加任务名称
}
}
storageSource.setStoreContent(String.valueOf(result));
//存储路径
LambdaQueryWrapper<StorageSourceConfig> queryWrapperData = new LambdaQueryWrapper<>();
queryWrapperData.eq(StorageSourceConfig::getStorageId, storageSource.getId());
queryWrapperData.eq(StorageSourceConfig::getName, "filePath");
String value = storageSourceConfigMapper.selectOne(queryWrapperData).getValue();
storageSource.setValueData(value);
//空间使用率
storageSource.setSpaceOccupancyRatio(calculateLocalStorageUsage(value));
}else {
LambdaQueryWrapper<TsTask> queryWrapper1 = new LambdaQueryWrapper<>();
queryWrapper1.eq(TsTask::getBackupStorageId, storageSource.getId());
List<TsTask> tsTasks = tsTaskMapper.selectList(queryWrapper1);
if (tsTasks.size()>0){
for (TsTask task : tsTasks) {
if (result.length() > 0) {
result.append(", "); // 如果结果不为空加上逗号分隔
}
result.append(task.getTaskName()); // 添加任务名称
}
}
storageSource.setStoreContent(String.valueOf(result));
storageSource.setValueData(null);
}
}
// 转换记录列表
List<StorageSourceAdminResult> records = entityToAdminResultList(sourcePage.getRecords());
// 创建目标分页对象并复制所有分页属性
Page<StorageSourceAdminResult> resultPage = new Page<>();
// 复制分页属性
resultPage.setRecords(records);
resultPage.setTotal(sourcePage.getTotal());
resultPage.setSize(sourcePage.getSize());
resultPage.setCurrent(sourcePage.getCurrent());
resultPage.setOrders(sourcePage.getOrders());
resultPage.setOptimizeCountSql(sourcePage.optimizeCountSql());
resultPage.setSearchCount(sourcePage.isSearchCount());
resultPage.setCountId(sourcePage.getCountId());
resultPage.setMaxLimit(sourcePage.getMaxLimit());
return resultPage;
}
// 计算本地路径的空间使用率
public static String calculateLocalStorageUsage(String path) {
File file = new File(path);
if (!file.exists()) {
throw new IllegalArgumentException("路径不存在: " + path);
}
// 获取磁盘空间信息
long totalSpace = file.getTotalSpace();
long freeSpace = file.getFreeSpace();
// 计算使用率
long usedSpace = totalSpace - freeSpace;
double usagePercentage = (double) usedSpace / totalSpace * 100;
// 格式化输出
DecimalFormat df = new DecimalFormat("#.##");
return df.format(usagePercentage) + "%";
}
@Override @Override
public StorageSourceDTO entityToDTO(StorageSource storageSource, StorageSourceAllParamDTO storageSourceAllParam) { public StorageSourceDTO entityToDTO(StorageSource storageSource, StorageSourceAllParamDTO storageSourceAllParam) {
@ -178,7 +312,9 @@ public class StorageSourceConvertImpl implements StorageSourceConvert {
storageSourceAdminResult.setOrderNum( storageSource.getOrderNum() ); storageSourceAdminResult.setOrderNum( storageSource.getOrderNum() );
storageSourceAdminResult.setDefaultSwitchToImgMode( storageSource.getDefaultSwitchToImgMode() ); storageSourceAdminResult.setDefaultSwitchToImgMode( storageSource.getDefaultSwitchToImgMode() );
storageSourceAdminResult.setCompatibilityReadme( storageSource.getCompatibilityReadme() ); storageSourceAdminResult.setCompatibilityReadme( storageSource.getCompatibilityReadme() );
storageSourceAdminResult.setStoreContent( storageSource.getStoreContent());
storageSourceAdminResult.setSpaceOccupancyRatio( storageSource.getSpaceOccupancyRatio());
storageSourceAdminResult.setValueData( storageSource.getValueData());
return storageSourceAdminResult; return storageSourceAdminResult;
} }
} }

View File

@ -2,6 +2,7 @@ package com.yfd.platform.modules.storage.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yfd.platform.modules.storage.model.entity.StorageSource; import com.yfd.platform.modules.storage.model.entity.StorageSource;
import com.yfd.platform.modules.storage.model.enums.StorageTypeEnum; import com.yfd.platform.modules.storage.model.enums.StorageTypeEnum;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
@ -96,4 +97,7 @@ public interface StorageSourceMapper extends BaseMapper<StorageSource> {
*/ */
String findKeyById(@Param("id") Integer id); String findKeyById(@Param("id") Integer id);
Page<StorageSource> findAllOrderByOrderNumPage(@Param("page") Page<StorageSource> page,@Param("type") String type,@Param("name") String name);
List<StorageSource> findAllOrderByOrderNumByType(@Param("type") String type);
} }

View File

@ -102,5 +102,13 @@ public class StorageSource implements Serializable {
@ApiModelProperty(value = "兼容 readme 模式", example = "true", notes = "兼容模式, 目录文档读取 readme.md 文件") @ApiModelProperty(value = "兼容 readme 模式", example = "true", notes = "兼容模式, 目录文档读取 readme.md 文件")
private Boolean compatibilityReadme; private Boolean compatibilityReadme;
//存储内容
@TableField(exist = false)
private String storeContent;
//存储空间使用率
@TableField(exist = false)
private String spaceOccupancyRatio;
//存储路径
@TableField(exist = false)
private String valueData;
} }

View File

@ -2,8 +2,10 @@ package com.yfd.platform.modules.storage.model.enums;
import com.baomidou.mybatisplus.annotation.EnumValue; import com.baomidou.mybatisplus.annotation.EnumValue;
import com.baomidou.mybatisplus.annotation.IEnum; import com.baomidou.mybatisplus.annotation.IEnum;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonValue;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import java.util.HashMap; import java.util.HashMap;
@ -59,6 +61,12 @@ public enum StorageTypeEnum implements IEnum {
this.description = description; this.description = description;
} }
// 添加反序列化方法
@JsonCreator // 告诉Jackson用此方法反序列化
public static StorageTypeEnum fromKey(String key) {
return ENUM_MAP.get(key);
}
@JsonValue // 告诉Jackson序列化时使用此字段
public String getKey() { public String getKey() {
return key; return key;
} }

View File

@ -1,5 +1,6 @@
package com.yfd.platform.modules.storage.model.result; package com.yfd.platform.modules.storage.model.result;
import com.baomidou.mybatisplus.annotation.TableField;
import com.yfd.platform.modules.storage.model.enums.SearchModeEnum; import com.yfd.platform.modules.storage.model.enums.SearchModeEnum;
import com.yfd.platform.modules.storage.model.enums.StorageTypeEnum; import com.yfd.platform.modules.storage.model.enums.StorageTypeEnum;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
@ -81,4 +82,14 @@ public class StorageSourceAdminResult {
@ApiModelProperty(value = "兼容 readme 模式", example = "true", notes = "兼容模式, 目录文档读取 readme.md 文件") @ApiModelProperty(value = "兼容 readme 模式", example = "true", notes = "兼容模式, 目录文档读取 readme.md 文件")
private Boolean compatibilityReadme; private Boolean compatibilityReadme;
//存储内容
@TableField(exist = false)
private String storeContent;
//存储空间使用率
@TableField(exist = false)
private String spaceOccupancyRatio;
//存储路径
@TableField(exist = false)
private String valueData;
} }

View File

@ -3,6 +3,9 @@ package com.yfd.platform.modules.storage.service;
import cn.hutool.core.convert.Convert; import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yfd.platform.exception.BadRequestException;
import com.yfd.platform.exception.StorageSourceException; import com.yfd.platform.exception.StorageSourceException;
import com.yfd.platform.exception.file.InvalidStorageSourceException; import com.yfd.platform.exception.file.InvalidStorageSourceException;
import com.yfd.platform.modules.config.model.request.SaveStorageSourceRequest; import com.yfd.platform.modules.config.model.request.SaveStorageSourceRequest;
@ -15,6 +18,7 @@ import com.yfd.platform.modules.storage.model.dto.StorageSourceDTO;
import com.yfd.platform.modules.storage.model.entity.StorageSource; import com.yfd.platform.modules.storage.model.entity.StorageSource;
import com.yfd.platform.modules.storage.model.entity.StorageSourceConfig; import com.yfd.platform.modules.storage.model.entity.StorageSourceConfig;
import com.yfd.platform.modules.storage.model.enums.StorageTypeEnum; import com.yfd.platform.modules.storage.model.enums.StorageTypeEnum;
import com.yfd.platform.modules.storage.model.param.QiniuParam;
import com.yfd.platform.utils.CodeMsg; import com.yfd.platform.utils.CodeMsg;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheConfig; import org.springframework.cache.annotation.CacheConfig;
@ -61,6 +65,14 @@ public class StorageSourceService {
return storageSourceMapper.findAllOrderByOrderNum(); return storageSourceMapper.findAllOrderByOrderNum();
} }
public List<StorageSource> findAllOrderByOrderNumByType(String type) {
return storageSourceMapper.findAllOrderByOrderNumByType(type);
}
public Page<StorageSource> findAllOrderByOrderNumPage(Page<StorageSource> page,String type,String name) {
return storageSourceMapper.findAllOrderByOrderNumPage(page,type,name);
}
/** /**
* 获取所有已启用的存储源列表按照存储源的排序号排序 * 获取所有已启用的存储源列表按照存储源的排序号排序
@ -132,7 +144,21 @@ public class StorageSourceService {
* *
* @return 存储源 DTO * @return 存储源 DTO
*/ */
@Cacheable(key = "'dto-' + #id", unless = "#result == null") // @Cacheable(key = "'dto-' + #id", unless = "#result == null")
// public StorageSourceDTO findDTOById(Integer id) {
// // 将参数列表通过反射写入到 StorageSourceAllParam .
// StorageSourceAllParamDTO storageSourceAllParam = new StorageSourceAllParamDTO();
// storageSourceConfigService.selectStorageConfigByStorageId(id)
// .forEach(storageSourceConfig ->
// ReflectUtil.setFieldValue(storageSourceAllParam, storageSourceConfig.getName(), storageSourceConfig.getValue())
// );
//
// // 获取数据库对象转为 dto 对象返回
// StorageSource storageSource = findById(id);
// return storageSourceConvert.entityToDTO(storageSource, storageSourceAllParam);
// }
//从表中直接获取 不从缓存
public StorageSourceDTO findDTOById(Integer id) { public StorageSourceDTO findDTOById(Integer id) {
// 将参数列表通过反射写入到 StorageSourceAllParam . // 将参数列表通过反射写入到 StorageSourceAllParam .
StorageSourceAllParamDTO storageSourceAllParam = new StorageSourceAllParamDTO(); StorageSourceAllParamDTO storageSourceAllParam = new StorageSourceAllParamDTO();
@ -289,6 +315,11 @@ public class StorageSourceService {
saveStorageSourceRequest.getId(), saveStorageSourceRequest.getName(), saveStorageSourceRequest.getId(), saveStorageSourceRequest.getName(),
saveStorageSourceRequest.getKey(), saveStorageSourceRequest.getType().getDescription()); saveStorageSourceRequest.getKey(), saveStorageSourceRequest.getType().getDescription());
StorageSource storageSourceData = storageSourceMapper.findByStorageKey(saveStorageSourceRequest.getKey());
if (storageSourceData != null ){
throw new BadRequestException("填充存储源别名已存在");
}
// 转换为存储源 entity 对象 // 转换为存储源 entity 对象
StorageSource storageSource = storageSourceConvert.saveRequestToEntity(saveStorageSourceRequest); StorageSource storageSource = storageSourceConvert.saveRequestToEntity(saveStorageSourceRequest);
@ -319,4 +350,8 @@ public class StorageSourceService {
return storageId; return storageId;
} }
public StorageSource findAllOrderBystoragesType(String storageKey) {
return storageSourceMapper.findByStorageKey(storageKey);
}
} }

View File

@ -57,6 +57,7 @@ public class CodeMsg {
public static CodeMsg STORAGE_SOURCE_INIT_FAIL = new CodeMsg("50100", "初始化存储源失败"); public static CodeMsg STORAGE_SOURCE_INIT_FAIL = new CodeMsg("50100", "初始化存储源失败");
public static CodeMsg STORAGE_SOURCE_INIT_STORAGE_CONFIG_FAIL = new CodeMsg("50101", "初始化存储源参数失败"); public static CodeMsg STORAGE_SOURCE_INIT_STORAGE_CONFIG_FAIL = new CodeMsg("50101", "初始化存储源参数失败");
public static CodeMsg STORAGE_SOURCE_INIT_STORAGE_PARAM_FIELD_FAIL = new CodeMsg("50102", "填充存储源字段失败"); public static CodeMsg STORAGE_SOURCE_INIT_STORAGE_PARAM_FIELD_FAIL = new CodeMsg("50102", "填充存储源字段失败");
public static CodeMsg STORAGE_SOURCE_INIT_REPEAT = new CodeMsg("50103", "填充存储源别名重复");
// 文件操作相关错误 // 文件操作相关错误

View File

@ -0,0 +1,18 @@
package com.yfd.platform.utils;
public class TableNameContextHolder {
private static final ThreadLocal<String> TASK_CODE = new ThreadLocal<>();
public static void setTaskCode(String taskCode) {
TASK_CODE.set(taskCode);
}
public static String getTaskCode() {
return TASK_CODE.get();
}
public static void clear() {
TASK_CODE.remove();
}
}

View File

@ -38,7 +38,16 @@
SELECT count(*) SELECT count(*)
FROM ts_files FROM ts_files
WHERE node_id IN (SELECT node_id FROM node_tree) WHERE node_id IN (SELECT node_id FROM node_tree)
AND backup_path IS NOT NULL AND (backup_path IS NOT NULL AND backup_path != '')
</select> </select>
<update id="updateTsFileByPath">
UPDATE ts_files
SET work_path = REPLACE (
work_path,#{oldBasePath}, #{newBasePath})
WHERE
task_id = #{taskId}
AND work_path LIKE CONCAT(#{oldBasePath}, '%')
</update>
</mapper> </mapper>

View File

@ -37,4 +37,120 @@
DELETE FROM sd_files WHERE node_id IN (SELECT id FROM node_tree) DELETE FROM sd_files WHERE node_id IN (SELECT id FROM node_tree)
</delete> </delete>
<update id="updateFileByPath">
UPDATE sd_files
SET file_path = REPLACE (
file_path,#{oldBasePath}, #{newBasePath})
WHERE
project_id = #{projectId}
AND file_path LIKE CONCAT(#{oldBasePath}, '%')
</update>
<select id="selectFilesPage" resultType="com.yfd.platform.modules.specialDocument.domain.Files">
<!-- 使用反引号包裹动态表名 -->
SELECT * FROM `${tableName}`
<where>
<!-- 文件名称不为空 -->
<if test="fileName != null and fileName != ''">
AND file_name LIKE CONCAT('%', #{fileName}, '%')
</if>
<!-- 关键字不为空 -->
<if test="keywords != null and keywords != ''">
AND keywords LIKE CONCAT('%', #{keywords}, '%')
</if>
<!-- 开始时间和结束时间 -->
<if test="startDate != null">
AND upload_time &gt;= #{startDate}
</if>
<if test="endDate != null">
AND upload_time &lt; #{endDate}
</if>
<!-- 项目ID和节点ID -->
<if test="projectId != null">
AND project_id = #{projectId}
</if>
<if test="nodeId != null">
AND node_id = #{nodeId}
</if>
</where>
ORDER BY upload_time DESC
</select>
<insert id="insertSdFilesTable">
INSERT INTO `${tableName}` (
id,
project_id,
node_id,
file_name,
file_path,
keywords,
file_size,
upload_time,
uploader
<!-- 其他字段 -->
) VALUES (
#{files.id},
#{files.projectId},
#{files.nodeId},
#{files.fileName},
#{files.filePath},
#{files.keywords},
#{files.fileSize},
#{files.uploadTime},
#{files.uploader}
<!-- 其他值 -->
)
</insert>
<update id="updateSdFiles">
UPDATE `${tableName}`
SET
file_name = #{files.fileName},
file_path = #{files.filePath},
keywords = #{files.keywords},
file_size = #{files.fileSize},
upload_time = #{files.uploadTime},
uploader = #{files.uploader}
<!-- 其他字段 -->
WHERE id = #{files.id}
</update>
<select id="selectSdFilesBatchIds" resultType="com.yfd.platform.modules.specialDocument.domain.Files">
<!-- 动态表名 -->
SELECT *
FROM `${tableName}`
<where>
<!-- 动态条件ID 集合 -->
<if test="dataset != null and dataset.size() > 0">
AND id IN
<foreach item="id" collection="dataset" open="(" close=")" separator=",">
#{id}
</foreach>
</if>
</where>
</select>
<select id="selectSdFilesById" resultType="com.yfd.platform.modules.specialDocument.domain.Files">
SELECT *
FROM `${tableName}`
WHERE id = #{id}
</select>
<delete id="deleteSdFiles">
<!-- 删除动态表 -->
DELETE FROM `${tableName}`
<where>
<!-- 删除条件 -->
<if test="files.id != null">
AND id = #{files.id}
</if>
</where>
</delete>
</mapper> </mapper>

View File

@ -37,4 +37,16 @@
DELETE FROM sd_nodes WHERE id IN (SELECT id FROM node_tree) DELETE FROM sd_nodes WHERE id IN (SELECT id FROM node_tree)
</delete> </delete>
<update id="updateNodesByPath">
UPDATE sd_nodes
SET custom3 = REPLACE (
custom3,#{oldBasePath}, #{newBasePath})
WHERE
project_id = #{projectId}
AND custom3 LIKE CONCAT(#{oldBasePath}, '%')
</update>
</mapper> </mapper>

View File

@ -2,4 +2,8 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yfd.platform.modules.specialDocument.mapper.ProjectMapper"> <mapper namespace="com.yfd.platform.modules.specialDocument.mapper.ProjectMapper">
<update id="createFileTable">
CREATE TABLE IF NOT EXISTS `${tableName}` LIKE `sd_files`
</update>
</mapper> </mapper>

View File

@ -74,4 +74,37 @@
from fi_storage_source from fi_storage_source
where `id`=#{id,jdbcType=INTEGER} where `id`=#{id,jdbcType=INTEGER}
</select> </select>
<!--auto generated by MybatisCodeHelper on 2021-07-15-->
<select id="findAllOrderByOrderNumPage" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from fi_storage_source
<where>
<!-- 存储空间名称不为空 -->
<if test="name != null and name != ''">
AND name LIKE CONCAT('%', #{name}, '%')
</if>
<!-- 存储策略不为空 -->
<if test="type != null and type != ''">
AND type =#{type}
</if>
</where>
order by ifnull(order_num, -1), id desc
</select>
<select id="findAllOrderByOrderNumByType" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from fi_storage_source
<where>
<!-- 存储策略不为空 -->
<if test="type != null and type != ''">
AND type =#{type}
</if>
</where>
order by ifnull(order_num, -1), id desc
</select>
</mapper> </mapper>