代码提交

This commit is contained in:
lilin 2025-03-03 11:26:32 +08:00
parent e365ef7365
commit 8ea12a93f7
52 changed files with 7309 additions and 16 deletions

View File

@ -53,6 +53,34 @@ public class SwaggerConfig {
.enable(swaggerEnabled); .enable(swaggerEnabled);
} }
@Bean
public Docket createSpecialDocumentApi() {
return new Docket(DocumentationType.OAS_30)
.apiInfo(apiInfo())
// .globalRequestParameters(generateRequestParameters())
.groupName("3. 专项文档管理")
.select()
.apis(RequestHandlerSelectors.basePackage("com.yfd.platform.modules.specialDocument.controller"))
.paths(PathSelectors.any())
.build()
.pathMapping("/")
.enable(swaggerEnabled);
}
@Bean
public Docket createExperimentalDataApi() {
return new Docket(DocumentationType.OAS_30)
.apiInfo(apiInfo())
// .globalRequestParameters(generateRequestParameters())
.groupName("4. 试验数据管理")
.select()
.apis(RequestHandlerSelectors.basePackage("com.yfd.platform.modules.experimentalData.controller"))
.paths(PathSelectors.any())
.build()
.pathMapping("/")
.enable(swaggerEnabled);
}
/** /**
* 获取通用的全局参数 * 获取通用的全局参数

View File

@ -0,0 +1,398 @@
package com.yfd.platform.modules.experimentalData.controller;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yfd.platform.annotation.Log;
import com.yfd.platform.config.ResponseResult;
import com.yfd.platform.modules.experimentalData.domain.DualTreeResponse;
import com.yfd.platform.modules.experimentalData.domain.FileCompareResult;
import com.yfd.platform.modules.experimentalData.domain.MoveCopyFileFolderRequest;
import com.yfd.platform.modules.experimentalData.domain.TsFiles;
import com.yfd.platform.modules.experimentalData.service.ITsFilesService;
import com.yfd.platform.modules.specialDocument.domain.Files;
import com.yfd.platform.modules.specialDocument.service.IFilesService;
import io.swagger.annotations.ApiOperation;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
/**
* <p>
* 试验任务文档表 前端控制器
* </p>
*
* @author LiMengNan
* @since 2025-01-21
*/
@RestController
@RequestMapping("/experimentalData/ts-files")
public class TsFilesController {
//实验任务文档表
@Resource
private ITsFilesService tsFilesService;
/**********************************
* 用途说明: 分页查询试验数据管理-文档内容
* 参数说明
* id id
* fileName 文件名称
* startDate (开始日期)
* endDate 结束日期
* keywords 关键字
*nodeId 节点ID
*taskId 任务ID
*isFile 文件夹文件区分
* pageNum 当前页
* 返回值说明: com.yfd.platform.config.ResponseResult 返回分页查询结果
***********************************/
@GetMapping("/page")
@ApiOperation("分页查询实验数据管理文档内容")
@PreAuthorize("@el.check('select:tsfiles')")
public ResponseResult getTsFilesPage(String id, String fileName, String startDate, String endDate, String keywords, String nodeId, String taskId, String childNode, Page<TsFiles> page) throws Exception {
//分页查询
Page<TsFiles> tsfilesPage = tsFilesService.getTsFilesPage(id, fileName, startDate, endDate, keywords, nodeId, taskId, fileName, childNode, page);
return ResponseResult.successData(tsfilesPage);
}
/**********************************
* 用途说明: 查询实验数据管理文件夹
* 参数说明
* pageNum 当前页
* 返回值说明: com.yfd.platform.config.ResponseResult 返回分页查询结果
***********************************/
@GetMapping("/listTsFiles")
@ApiOperation("查询实验数据管理文件夹")
@PreAuthorize("@el.check('select:tsfiles')")
public ResponseResult getsListTsFiles(String id, String path) throws Exception {
//分页查询
List<TsFiles> tsfiles = tsFilesService.getsListTsFiles(id, path);
return ResponseResult.successData(tsfiles);
}
/***********************************
* 用途说明新增试验数据管理-文档内容
* 参数说明
* TsFiles 文档内容
* 返回值说明: com.yfd.platform.config.ResponseResult 返回新增成功或者失败
***********************************/
@Log(module = "实验数据管理", value = "新增试验数据管理文档内容!", type = "1")
@PostMapping("/addTsFiles")
@ApiOperation("新增试验数据管理文档内容")
@ResponseBody
@PreAuthorize("@el.check('add:tsFiles')")
public ResponseResult addTsFiles(@RequestBody TsFiles tsFiles) {
//对象不能为空
if (ObjUtil.isEmpty(tsFiles)) {
return ResponseResult.error("参数为空");
}
Boolean isOk = tsFilesService.addTsFiles(tsFiles);
if (isOk) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
/***********************************
* 用途说明新增试验数据管理-文件夹
* 参数说明
* TsFiles 文档内容
* 返回值说明: com.yfd.platform.config.ResponseResult 返回新增成功或者失败
***********************************/
@Log(module = "实验数据管理", value = "新增试验数据管理文件夹", type = "1")
@PostMapping("/addTsFile")
@ApiOperation("新增试验数据管理文件夹")
@ResponseBody
@PreAuthorize("@el.check('add:tsFiles')")
public ResponseResult addTsFile(@RequestBody TsFiles tsFiles) {
//对象不能为空
if (ObjUtil.isEmpty(tsFiles)) {
return ResponseResult.error("参数为空");
}
return tsFilesService.addTsFile(tsFiles);
}
/**********************************
* 用途说明: 修改试验数据管理-文档内容
* 参数说明
* TsFiles 文档内容
* 返回值说明: com.yfd.platform.config.ResponseResult 返回修改成功或者失败
***********************************/
@Log(module = "试验数据管理", value = "修改试验数据管理文档内容", type = "1")
@PostMapping("/updateTsFiles")
@ApiOperation("修改试验数据管理文档内容")
@PreAuthorize("@el.check('update:tsFiles')")
public ResponseResult updateTsFiles(@RequestBody TsFiles tsFiles) {
//对象不能为空
if (ObjUtil.isEmpty(tsFiles) && StrUtil.isBlank(tsFiles.getId())) {
return ResponseResult.error("参数为空");
}
return tsFilesService.updateTsFiles(tsFiles);
}
/**********************************
* 用途说明: 根据ID删除试验数据管理-文档内容
* 参数说明 id 文档内容ID
* 返回值说明: com.yfd.platform.config.ResponseResult 返回删除成功或者失败
***********************************/
@Log(module = "试验数据管理", value = "根据ID删除试验数据管理文档内容", type = "1")
@PostMapping("/deleteTsFilesById")
@ApiOperation("根据ID删除试验数据管理文档内容")
@PreAuthorize("@el.check('del:tsFiles')")
public ResponseResult deleteTsFilesById(@RequestParam String id) {
if (StrUtil.isBlank(id)) {
return ResponseResult.error("参数为空");
}
List<String> dataset = Arrays.asList(id);
return ResponseResult.success(tsFilesService.deleteTsFilesByIds(dataset));
}
/**********************************
* 用途说明: 批量删除试验数据管理-文档内容
* 参数说明 ids 文档内容id数组
* 返回值说明: com.yfd.platform.config.ResponseResult 返回批量删除成功或失败
***********************************/
@Log(module = "专项文档管理", value = "批量删除试验数据管理文档内容", type = "1")
@PostMapping("/deleteTsFilesByIds")
@ApiOperation("批量删除试验数据管理文档内容")
@PreAuthorize("@el.check('del:tsFiles')")
public ResponseResult deleteTsFilesByIds(@RequestParam String ids) {
if (StrUtil.isBlank(ids)) {
return ResponseResult.error("参数为空");
}
String[] splitIds = ids.split(",");
// 数组转集合
List<String> dataset = Arrays.asList(splitIds);
return ResponseResult.success(tsFilesService.deleteTsFilesByIds(dataset));
}
/**************************压缩 解压缩********************************/
/**********************************
* 用途说明: 压缩文件夹接口
* 参数说明 ids 文件id数组
* 参数说明 compressedFormat 压缩文件格式
* 参数说明 compressedName 压缩文件名称
* 参数说明 compressedPath 压缩文件路径
* 参数说明 covered 是否覆盖 0 覆盖更新updateTime时间 1提示文件存在
* 参数说明 parentId 父ID
* 返回值说明: com.yfd.platform.config.ResponseResult
***********************************/
@PostMapping("/compress")
@ApiOperation("压缩文件夹接口")
public ResponseResult compressFolder(String ids, String compressedFormat, String compressedName, String compressedPath, String covered, String parentId) {
try {
if (StrUtil.isBlank(ids) && StrUtil.isBlank(compressedFormat) && StrUtil.isBlank(compressedName) && StrUtil.isBlank(compressedPath)) {
return ResponseResult.error("参数为空");
}
return ResponseResult.success(tsFilesService.compressFolder(ids, compressedFormat, compressedName, compressedPath, covered, parentId));
} catch (Exception e) {
System.out.print("压缩异常原因" + e);
return ResponseResult.error("压缩失败");
}
}
/**********************************
* 用途说明: 解压缩接口
* 参数说明 id 要解压的文件id
* 参数说明 decompressionPath 解压缩路径
* 参数说明 parentId 父ID
* 返回值说明: com.yfd.platform.config.ResponseResult
***********************************/
@PostMapping("/decompression")
@ApiOperation("解压缩接口")
public ResponseResult decompressionFolder(String id, String decompressionPath, String parentId) {
try {
if (StrUtil.isBlank(id)) {
return ResponseResult.error("参数为空");
}
return ResponseResult.success(tsFilesService.decompressionFolder(id, decompressionPath, parentId));
} catch (Exception e) {
System.out.print("解压缩异常原因" + e);
return ResponseResult.error("解压缩失败");
}
}
/**
* 移动文件或文件夹
* 参数说明 newPath 新路径
* 参数说明 oldpaths 原路径
* 参数说明 ParentId 父ID
* 参数说明 newFileName 勾选的所有文件名称
* 参数说明 Rename 重命名的文件名称
* 参数说明 type 覆盖还是重命名 0 1
*/
@PostMapping("/moveFileFolder")
@ApiOperation("移动")
public ResponseResult moveFileFolder(@RequestBody MoveCopyFileFolderRequest request) throws IOException {
try {
if (request == null) {
throw new IllegalArgumentException("请求参数不能为空");
}
if (request.getNewFileName() == null || request.getNewFileName().isEmpty()) {
throw new IllegalArgumentException("newFileName 不能为空");
}
if (request.getNewPath() == null || request.getOldpaths() == null) {
throw new IllegalArgumentException("路径参数不能为空");
}
return ResponseResult.success(tsFilesService.moveFileFolder(request));
} catch (Exception e) {
System.out.print("移动异常原因" + e);
return ResponseResult.error("移动失败");
}
}
/**
* 复制文件或文件夹
* 参数说明 newPath 新路径
* 参数说明 oldpaths 原路径
* 参数说明 ParentId 父ID
* 参数说明 newFileName 勾选的所有文件名称
* 参数说明 Rename 重命名的文件名称
* 参数说明 type 覆盖还是重命名 0 1
*/
@PostMapping("/copyFileFolder")
@ApiOperation("复制")
public ResponseResult copyFileFolder(@RequestBody MoveCopyFileFolderRequest request) throws IOException {
try {
if (request == null) {
throw new IllegalArgumentException("请求参数不能为空");
}
if (request.getNewFileName() == null || request.getNewFileName().isEmpty()) {
throw new IllegalArgumentException("newFileName 不能为空");
}
if (request.getNewPath() == null || request.getOldpaths() == null) {
throw new IllegalArgumentException("路径参数不能为空");
}
return ResponseResult.success(tsFilesService.copyFileFolder(request));
} catch (Exception e) {
System.out.print("复制异常原因" + e);
return ResponseResult.error("复制失败");
}
}
/**
* 对比两个目录的文件差异
*
* @param localPath 本地目录的相对路径相对于E:\yun\qqq
* @param minioPath MinIO目录的相对路径相对于test-bucket/qqq
* @return 文件差异列表
*/
@PostMapping("/compare")
@ApiOperation("对比两个目录的文件差异")
public ResponseResult compareDirectories(@RequestParam String localPath, @RequestParam String minioPath) {
try {
if (StrUtil.isBlank(localPath) && StrUtil.isBlank(minioPath)) {
return ResponseResult.error("参数为空");
}
TsFiles tsFiles = tsFilesService.compareDirectories(localPath, minioPath);
return ResponseResult.successData(tsFiles);
} catch (Exception e) {
return ResponseResult.error("对比失败");
}
}
/**********************************
* 用途说明: 将文件上传到备份空间
* 参数说明 paths 路径集合
* 参数说明 names 文件名集合
* 参数说明 sizes 文件大小集合
* 返回值说明: com.yfd.platform.config.ResponseResult 返回成功或者失败
***********************************/
@PostMapping("/uploadToBackup")
@ApiOperation("将文件上传到备份空间")
public ResponseResult uploadToBackup(@RequestParam String paths, @RequestParam String names, @RequestParam String sizes) {
if (StrUtil.isBlank(paths) && StrUtil.isBlank(names)) {
return ResponseResult.error("参数为空");
}
Boolean isOk = tsFilesService.uploadToBackup(paths, names, sizes);
if (isOk) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
/**********************************
* 用途说明: 从备份空间下载到工作空间
* 参数说明 paths 路径集合
* 参数说明 names 文件名集合
* 参数说明 sizes 文件大小集合
* 返回值说明: com.yfd.platform.config.ResponseResult 返回成功或者失败
***********************************/
@PostMapping("/downloadToLocal")
@ApiOperation("从备份空间下载到工作空间")
public ResponseResult downloadToLocal(@RequestParam String paths, @RequestParam String names, @RequestParam String sizes) {
if (StrUtil.isBlank(paths) && StrUtil.isBlank(names)) {
return ResponseResult.error("参数为空");
}
Boolean isOk = tsFilesService.downloadToLocal(paths, names, sizes);
if (isOk) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
/**********************************
* 用途说明: 查询本地和备份空间结构树
* 参数说明 taskId 节点ID
* 参数说明 nodeId 任务ID
* 返回值说明: com.yfd.platform.config.ResponseResult 返回双树数据
***********************************/
@PostMapping("/listLocalAndBackup")
@ApiOperation("查询本地和备份空间结构树")
public ResponseResult listLocalAndBackup( String taskId, String nodeId) {
if (StrUtil.isBlank(taskId) && StrUtil.isBlank(nodeId)) {
return ResponseResult.error("参数为空");
}
//查询本地树和minio树
DualTreeResponse response = tsFilesService.listLocalAndBackup(taskId, nodeId);
return ResponseResult.successData(response);
}
}

View File

@ -0,0 +1,110 @@
package com.yfd.platform.modules.experimentalData.controller;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.yfd.platform.annotation.Log;
import com.yfd.platform.config.ResponseResult;
import com.yfd.platform.modules.experimentalData.domain.TsNodes;
import com.yfd.platform.modules.experimentalData.service.ITsNodesService;
import com.yfd.platform.modules.experimentalData.service.ITsTaskService;
import com.yfd.platform.modules.specialDocument.domain.Nodes;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
/**
* <p>
* 试验任务节点表 前端控制器
* </p>
*
* @author LiMengNan
* @since 2025-01-21
*/
@RestController
@RequestMapping("/experimentalData/ts-nodes")
public class TsNodesController {
//试验任务节点服务类
@Resource
private ITsNodesService tsNodesService;
/***********************************
* 用途说明获取试验任务节点 树形结构
* 参数说明
* nodeName 节点名称
* taskId 所属任务ID
* 返回值说明: 专项文档节点树形结构
***********************************/
@PostMapping("/getTsNodesTree")
@ApiOperation("获取试验任务节点树形结构")
@ResponseBody
@PreAuthorize("@el.check('select:tsnodes')")
public ResponseResult getTsNodesTree(String nodeName, String taskId) {
List<Map<String, Object>> list = tsNodesService.getTsNodesTree(nodeName,taskId);
return ResponseResult.successData(list);
}
/**********************************
* 用途说明: 增加试验任务节点
* 参数说明 tsnodes 试验任务节点信息
* 返回值说明: com.yfd.platform.config.ResponseResult 返回增加成功或者失败
***********************************/
@Log(module = "试验数据管理", value = "增加试验任务节点",type = "1")
@PostMapping("/addTsNodes")
@ApiOperation("增加试验任务节点")
@PreAuthorize("@el.check('add:tsnodes')")
public ResponseResult addTsNodes(@RequestBody TsNodes tsnodes) {
//参数校验 对象 节点名称 所属任务ID
if (ObjUtil.isEmpty(tsnodes) && StrUtil.isBlank(tsnodes.getNodeName()) && StrUtil.isBlank(tsnodes.getTaskId()) ) {
return ResponseResult.error("参数为空");
}
return tsNodesService.addTsNodes(tsnodes);
}
/**********************************
* 用途说明: 修改试验任务节点
* 参数说明 tsnodes 试验任务节点信息
* 返回值说明: com.yfd.platform.config.ResponseResult 返回修改成功或者失败
***********************************/
@Log(module = "试验数据管理", value = "修改试验任务节点",type = "1")
@PostMapping("/updateTsNodes")
@ApiOperation("修改试验任务节点")
@PreAuthorize("@el.check('update:tsnodes')")
public ResponseResult updateTsNodes(@RequestBody TsNodes tsnodes) {
//参数校验 对象 节点名称 所属任务ID id
if (ObjUtil.isEmpty(tsnodes) && StrUtil.isBlank(tsnodes.getNodeName()) && StrUtil.isBlank(tsnodes.getTaskId()) && StrUtil.isBlank(tsnodes.getNodeId())) {
return ResponseResult.error("参数为空");
}
return tsNodesService.updateTsNodes(tsnodes);
}
/**********************************
* 用途说明: 根据ID删除试验任务节点
* 参数说明 id 试验任务节点ID
* 返回值说明: com.yfd.platform.config.ResponseResult 返回删除成功或者失败
***********************************/
@Log(module = "试验数据管理", value = "根据ID删除试验任务节点",type = "1")
@PostMapping("/deleteTsNodesById")
@ApiOperation("根据ID删除试验任务节点")
@PreAuthorize("@el.check('del:tsnodes')")
public ResponseResult deleteTsNodesById(@RequestParam String id) {
if (StrUtil.isBlank(id)) {
return ResponseResult.error("参数为空");
}
boolean isOk = tsNodesService.deleteTsNodesById(id);
if (isOk) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
}

View File

@ -0,0 +1,163 @@
package com.yfd.platform.modules.experimentalData.controller;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yfd.platform.annotation.Log;
import com.yfd.platform.config.ResponseResult;
import com.yfd.platform.modules.experimentalData.domain.TsTask;
import com.yfd.platform.modules.experimentalData.service.ITsTaskService;
import com.yfd.platform.modules.specialDocument.domain.Project;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
/**
* <p>
* 试验任务表 前端控制器
* </p>
*
* @author LiMengNan
* @since 2025-01-21
*/
@RestController
@RequestMapping("/experimentalData/tstask")
public class TsTaskController {
//试验任务服务类
@Resource
private ITsTaskService tsTaskService;
/**********************************
* 用途说明: 分页查询试验数据管理-试验任务管理
* 参数说明
* taskName 任务名称
* startDate (开始日期)
* endDate 结束日期
* taskPlace 任务地点
* taskPerson 任务人员
* carrierType 载体类型
* deviceCode 设备
* pageNum 当前页
* 返回值说明: com.yfd.platform.config.ResponseResult 返回分页查询结果
***********************************/
@GetMapping("/page")
@ApiOperation("分页查询试验数据管理试验任务管理")
@PreAuthorize("@el.check('select:tsTask')")
public ResponseResult getTsTaskPage(String taskName, String startDate, String endDate,String taskPlace, String taskPerson, String carrierType, String deviceCode, Page<TsTask> page) {
//分页查询
Page<TsTask> sdProjectPage = tsTaskService.getTsTaskPage(taskName, startDate, endDate,taskPlace,taskPerson,carrierType,deviceCode, page);
return ResponseResult.successData(sdProjectPage);
}
/***********************************
* 用途说明新增试验数据管理-试验任务管理
* 参数说明
* TsTask 试验任务管理
* 返回值说明: com.yfd.platform.config.ResponseResult 返回新增成功或者失败
***********************************/
@Log(module = "试验数据管理", value = "新增试验数据管理试验任务管理!",type = "1")
@PostMapping("/addtsTask")
@ApiOperation("新增试验数据管理试验任务管理")
@ResponseBody
@PreAuthorize("@el.check('add:tsTask')")
public ResponseResult addtsTask(@RequestBody TsTask tsTask) {
//对象不能为空
if (ObjUtil.isEmpty(tsTask)) {
return ResponseResult.error("参数为空");
}
Boolean isOk = tsTaskService.addSdproject(tsTask);
if (isOk) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
/**********************************
* 用途说明: 修改试验数据管理-试验任务管理
* 参数说明
* TsTask 试验任务管理
* 返回值说明: com.yfd.platform.config.ResponseResult 返回修改成功或者失败
***********************************/
@Log(module = "试验数据管理", value = "修改试验数据管理试验任务管理",type = "1")
@PostMapping("/updatetsTask")
@ApiOperation("修改试验数据管理试验任务管理")
@PreAuthorize("@el.check('update:tsTask')")
public ResponseResult updatetsTask(@RequestBody TsTask tsTask) {
//对象不能为空
if (ObjUtil.isEmpty(tsTask) && StrUtil.isBlank(tsTask.getId())) {
return ResponseResult.error("参数为空");
}
boolean isOk = tsTaskService.updatetsTask(tsTask);
if (isOk) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
/**********************************
* 用途说明: 根据ID试验数据管理-试验任务管理
* 参数说明 id 试验数据管理ID
* 返回值说明: com.yfd.platform.config.ResponseResult 返回删除成功或者失败
***********************************/
@Log(module = "试验数据管理", value = "根据ID删除试验数据管理试验任务管理",type = "1")
@PostMapping("/deleteTsTaskById")
@ApiOperation("根据ID删除试验数据管理试验任务管理")
@PreAuthorize("@el.check('del:tsTask')")
public ResponseResult deleteTsTaskById(@RequestParam String id) {
if (StrUtil.isBlank(id)) {
return ResponseResult.error("参数为空");
}
boolean isOk = tsTaskService.removeById(id);
if (isOk) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
/**********************************
* 用途说明: 批量删除试验数据管理-试验任务管理
* 参数说明 ids 试验数据管理id数组
* 返回值说明: com.yfd.platform.config.ResponseResult 返回批量删除成功或失败
***********************************/
@Log(module = "试验数据管理", value = "批量删除试验数据管理试验任务管理",type = "1")
@PostMapping("/deleteTsTaskByIds")
@ApiOperation("批量删除试验数据管理试验任务管理")
@PreAuthorize("@el.check('del:tsTask')")
public ResponseResult deleteTsTaskByIds(@RequestParam String ids) {
if (StrUtil.isBlank(ids)) {
return ResponseResult.error("参数为空");
}
String[] splitIds = ids.split(",");
// 数组转集合
List<String> dataset = Arrays.asList(splitIds);
boolean isOk = tsTaskService.removeByIds(dataset);
if (isOk) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
/***********************************
* 用途说明 查询所有试验数据管理-试验任务管理
* 参数说明
* 返回值说明: 试验数据管理试验任务管理
***********************************/
@PostMapping("/list")
@ApiOperation("查询所有试验数据管理试验任务管理")
@ResponseBody
//@PreAuthorize("@el.check('select:devicesignal')")
public ResponseResult listTsTask() {
List<TsTask> tsTasks = tsTaskService.list();
return ResponseResult.successData(tsTasks);
}
}

View File

@ -0,0 +1,18 @@
package com.yfd.platform.modules.experimentalData.domain;
import lombok.Data;
import java.util.List;
@Data
public class DualTreeResponse {
private List<TreeDTO> localTrees; // 本地树列表workPath
private List<TreeDTO> minioTrees; // Minio 树列表backupPath
// 添加带参数的构造函数
public DualTreeResponse(List<TreeDTO> localTrees, List<TreeDTO> minioTrees) {
this.localTrees = localTrees;
this.minioTrees = minioTrees;
}
}

View File

@ -0,0 +1,25 @@
package com.yfd.platform.modules.experimentalData.domain;
import lombok.Data;
@Data
public class FileCompareResult {
// 文件相对路径相对于对比根目录
private String relativePath;
// 文件状态
// LOCAL_MISSING - 本地缺失
// REMOTE_MISSING - MinIO缺失
// MD5_MISMATCH - MD5不一致
private String status;
// 本地文件的MD5哈希值
private String localMd5;
// MinIO文件的MD5哈希值
private String remoteMd5;
// 是否是目录
private boolean isDirectory;
}

View File

@ -0,0 +1,16 @@
package com.yfd.platform.modules.experimentalData.domain;
import lombok.Data;
import java.util.List;
@Data
public class MoveCopyFileFolderRequest {
private String newPath;
private String oldpaths;
private String parentId;
private String newFileName;
private String rename;
private String type;
}

View File

@ -0,0 +1,102 @@
package com.yfd.platform.modules.experimentalData.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.sql.Timestamp;
import java.util.List;
@Data
public class TreeDTO {
/**
* 文档ID
*/
private String id;
/**
* 节点ID
*/
private String nodeId;
/**
* 任务ID
*/
private String taskId;
/**
* 上级节点顶级00
*/
private String parentId;
/**
* 文件夹文件区分
*/
private String isFile;
/**
* 文件名称
*/
private String fileName;
/**
* M
*/
private String fileSize;
/**
* 工作空间存储路径
*/
private String workPath;
/**
* 备份空间存储路径
*/
private String backupPath;
/**
* 关键字
*/
private String keywords;
/**
* 文件描述
*/
private String description;
/**
* 上传时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Timestamp uploadTime;
/**
* 上传人
*/
private String uploader;
/**
* 修改时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Timestamp updateTime;
/**
* 访问路径URLTODO 增加用于前端展示
*/
@TableField(exist = false)
private String url;
/**
* 类型 FILE FOLDERTODO 增加用于前端展示
*/
@TableField(exist = false)
private String type;
// 路径字段
private String path;
// 子节点列表
private List<TreeDTO> children;
}

View File

@ -0,0 +1,189 @@
package com.yfd.platform.modules.experimentalData.domain;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.io.Serializable;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.yfd.platform.modules.storage.model.result.FileItemResult;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
* 试验任务文档表
* </p>
*
* @author LiMengNan
* @since 2025-01-21
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("ts_files")
public class TsFiles implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 文档ID
*/
@TableId(type = IdType.ASSIGN_UUID)
private String id;
/**
* 节点ID
*/
private String nodeId;
/**
* 任务ID
*/
private String taskId;
/**
* 上级节点顶级00
*/
private String parentId;
/**
* 文件夹文件区分
*/
private String isFile;
/**
* 文件名称
*/
private String fileName;
/**
* M
*/
private String fileSize;
/**
* 工作空间存储路径
*/
private String workPath;
/**
* 备份空间存储路径
*/
private String backupPath;
/**
* 关键字
*/
private String keywords;
/**
* 文件描述
*/
private String description;
/**
* 上传时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Timestamp uploadTime;
/**
* 上传人
*/
private String uploader;
/**
* 修改时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Timestamp updateTime;
/**
* 备份1
*/
private String custom1;
/**
* 备份2
*/
private String custom2;
/**
* 备份3
*/
private String custom3;
/**
* 访问路径URLTODO 增加用于前端展示
*/
@TableField(exist = false)
private String url;
/**
* 类型 FILE FOLDERTODO 增加用于前端展示
*/
@TableField(exist = false)
private String type;
// /**
// * 试验任务节点表 FOLDERTODO 增加用于前端展示
// */
// @TableField(exist = false)
// private List<TsNodes> tsNodesList;
// /**
// * 节点顺序
// */
// @TableField(exist = false)
// private Integer nodeOrder;
//
// /**
// * 节点名称
// */
// @TableField(exist = false)
// private String nodeName;
//
// /**
// * 创建时间
// */
// @TableField(exist = false)
// @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
// private Timestamp createTime;
//
// /**
// * 创建人
// */
// @TableField(exist = false)
// private String creator;
//
//
// /**
// * 检查本地有而 MinIO 没有的文件
// */
// @TableField(exist = false)
// private List<FileItemResult> localOnlyFiles;
//
//
// /**
// * 检查 MinIO 有而本地没有的文件
// */
// @TableField(exist = false)
// private List<FileItemResult> minioOnlyFiles;
//
//
// /**
// * 检查 MD5 不一致的文件
// */
// @TableField(exist = false)
// private List<FileItemResult> md5MismatchedFiles;
}

View File

@ -0,0 +1,83 @@
package com.yfd.platform.modules.experimentalData.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.io.Serializable;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
* 试验任务节点表
* </p>
*
* @author LiMengNan
* @since 2025-01-21
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("ts_nodes")
public class TsNodes implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 节点ID
*/
@TableId(type = IdType.ASSIGN_UUID)
private String nodeId;
/**
* 所属任务ID
*/
private String taskId;
/**
* 上级节点顶级00
*/
private String parentId;
/**
* 节点顺序
*/
private Integer nodeOrder;
/**
* 节点名称
*/
private String nodeName;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Timestamp createTime;
/**
* 创建人
*/
private String creator;
/**
* 备注1
*/
private String custom1;
/**
* 备注2
*/
private String custom2;
/**
* 备注3
*/
private String custom3;
}

View File

@ -0,0 +1,115 @@
package com.yfd.platform.modules.experimentalData.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.io.Serializable;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
* 试验任务表
* </p>
*
* @author LiMengNan
* @since 2025-01-21
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("ts_task")
public class TsTask implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 任务ID
*/
@TableId(type = IdType.ASSIGN_UUID)
private String id;
/**
* 任务编号
*/
private String taskCode;
/**
* 任务名称
*/
private String taskName;
/**
* 载体类型
*/
private String carrierType;
/**
* 载体名称
*/
private String carrierName;
/**
* 设备编号
*/
private String deviceCode;
/**
* 设备名称
*/
private String deviceName;
/**
* 任务开始时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Timestamp taskDate;
/**
* 任务地点
*/
private String taskPlace;
/**
* 任务人员
*/
private String taskPerson;
/**
* 可扩展的Json对象
*/
private String taskProps;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Timestamp createTime;
/**
* 创建人
*/
private String creator;
/**
* 备注1
*/
private String custom1;
/**
* 备注2
*/
private String custom2;
/**
* 备注3
*/
private String custom3;
}

View File

@ -0,0 +1,16 @@
package com.yfd.platform.modules.experimentalData.mapper;
import com.yfd.platform.modules.experimentalData.domain.TsFiles;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 试验任务文档表 Mapper 接口
* </p>
*
* @author LiMengNan
* @since 2025-01-21
*/
public interface TsFilesMapper extends BaseMapper<TsFiles> {
}

View File

@ -0,0 +1,16 @@
package com.yfd.platform.modules.experimentalData.mapper;
import com.yfd.platform.modules.experimentalData.domain.TsNodes;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 试验任务节点表 Mapper 接口
* </p>
*
* @author LiMengNan
* @since 2025-01-21
*/
public interface TsNodesMapper extends BaseMapper<TsNodes> {
}

View File

@ -0,0 +1,16 @@
package com.yfd.platform.modules.experimentalData.mapper;
import com.yfd.platform.modules.experimentalData.domain.TsTask;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 试验任务表 Mapper 接口
* </p>
*
* @author LiMengNan
* @since 2025-01-21
*/
public interface TsTaskMapper extends BaseMapper<TsTask> {
}

View File

@ -0,0 +1,153 @@
package com.yfd.platform.modules.experimentalData.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yfd.platform.config.ResponseResult;
import com.yfd.platform.modules.experimentalData.domain.DualTreeResponse;
import com.yfd.platform.modules.experimentalData.domain.MoveCopyFileFolderRequest;
import com.yfd.platform.modules.experimentalData.domain.TsFiles;
import com.baomidou.mybatisplus.extension.service.IService;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.List;
/**
* <p>
* 试验任务文档表 服务类
* </p>
*
* @author LiMengNan
* @since 2025-01-21
*/
public interface ITsFilesService extends IService<TsFiles> {
/**********************************
* 用途说明: 分页查询试验数据管理-文档内容
* 参数说明
* id id
* fileName 文件名称
* startDate (开始日期)
* endDate 结束日期
* keywords 关键字
*nodeId 节点ID
*taskId 任务ID
* pageNum 当前页
* 返回值说明: com.yfd.platform.config.ResponseResult 返回分页查询结果
***********************************/
Page<TsFiles> getTsFilesPage(String id,String fileName, String startDate, String endDate, String keywords, String nodeId, String taskId, String fileName1,String childNode, Page<TsFiles> page) throws Exception;
/***********************************
* 用途说明新增试验数据管理-文档内容
* 参数说明
* TsFiles 文档内容
* 返回值说明: com.yfd.platform.config.ResponseResult 返回新增成功或者失败
***********************************/
Boolean addTsFiles(TsFiles tsFiles);
/**********************************
* 用途说明: 修改试验数据管理-文档内容
* 参数说明
* TsFiles 文档内容
* 返回值说明: com.yfd.platform.config.ResponseResult 返回修改成功或者失败
***********************************/
ResponseResult updateTsFiles(TsFiles tsFiles);
/**********************************
* 用途说明: 批量删除试验数据管理-文档内容
* 参数说明 ids 文档内容id数组
* 返回值说明: com.yfd.platform.config.ResponseResult 返回批量删除成功或失败
***********************************/
String deleteTsFilesByIds(List<String> dataset);
/**********************************
* 用途说明: 压缩文件夹接口
* 参数说明 ids 文件id数组
* 参数说明 compressedFormat 压缩文件格式
* 参数说明 compressedName 压缩文件名称
* 参数说明 compressedPath 压缩文件路径
* 参数说明 covered 是否覆盖 0 覆盖更新updateTime时间 1提示文件存在
* 参数说明 parentId 父ID
* 返回值说明: com.yfd.platform.config.ResponseResult
***********************************/
String compressFolder(String ids,String compressedFormat,String compressedName,String compressedPath,String covered,String parentId) throws FileNotFoundException;
/**********************************
* 用途说明: 解压缩接口
* 参数说明 id 要解压的文件id
* 参数说明 decompressionPath 解压缩路径
* 参数说明 parentId 父ID
* 返回值说明: com.yfd.platform.config.ResponseResult
***********************************/
String decompressionFolder(String id,String decompressionPath,String parentId);
TsFiles compareDirectories(String localPath, String minioPath);
/**********************************
* 用途说明: 将文件上传到备份空间
* 参数说明 paths 路径集合
* 参数说明 names 文件名集合
* 参数说明 sizes 文件大小集合
* 返回值说明: com.yfd.platform.config.ResponseResult 返回成功或者失败
***********************************/
Boolean uploadToBackup(String paths, String names, String sizes);
/**********************************
* 用途说明: 从备份空间下载到工作空间
* 参数说明 paths 路径集合
* 参数说明 names 文件名集合
* 参数说明 sizes 文件大小集合
* 返回值说明: com.yfd.platform.config.ResponseResult 返回成功或者失败
***********************************/
Boolean downloadToLocal(String paths, String names, String sizes);
/***********************************
* 用途说明新增试验数据管理-文件夹
* 参数说明
* TsFiles 文档内容
* 返回值说明: com.yfd.platform.config.ResponseResult 返回新增成功或者失败
***********************************/
ResponseResult addTsFile(TsFiles tsFiles);
/**********************************
* 用途说明: 查询实验数据管理文件夹
* 参数说明
* pageNum 当前页
* 返回值说明: com.yfd.platform.config.ResponseResult 返回分页查询结果
***********************************/
List<TsFiles> getsListTsFiles(String id,String path);
/**
* 移动文件或文件夹
* 参数说明 newPath 新路径
* 参数说明 oldpaths 原路径
* 参数说明 ParentId 父ID
* 参数说明 newFileName 父ID
* 参数说明 Rename 重命名的文件名称
* 参数说明 type 覆盖还是重命名 0 1
*/
String moveFileFolder(MoveCopyFileFolderRequest request)throws IOException;
/**
* 复制文件或文件夹
* 参数说明 newPath 新路径
* 参数说明 oldpaths 原路径
* 参数说明 ParentId 父ID
* 参数说明 newFileName 父ID
* 参数说明 Rename 重命名的文件名称
* 参数说明 type 覆盖还是重命名 0 1
*/
String copyFileFolder(MoveCopyFileFolderRequest request)throws IOException;
/**********************************
* 用途说明: 查询本地和备份空间结构树
* 参数说明 taskId 节点ID
* 参数说明 nodeId 任务ID
* 返回值说明: com.yfd.platform.config.ResponseResult 返回双树数据
***********************************/
DualTreeResponse listLocalAndBackup(String taskId, String nodeId);
}

View File

@ -0,0 +1,49 @@
package com.yfd.platform.modules.experimentalData.service;
import com.yfd.platform.config.ResponseResult;
import com.yfd.platform.modules.experimentalData.domain.TsNodes;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
import java.util.Map;
/**
* <p>
* 试验任务节点表 服务类
* </p>
*
* @author LiMengNan
* @since 2025-01-21
*/
public interface ITsNodesService extends IService<TsNodes> {
/***********************************
* 用途说明获取试验任务节点 树形结构
* 参数说明
* nodeName 节点名称
* taskId 所属任务ID
* 返回值说明: 专项文档节点树形结构
***********************************/
List<Map<String, Object>> getTsNodesTree(String nodeName, String taskId);
/**********************************
* 用途说明: 增加试验任务节点
* 参数说明 nodes 专项文档节点信息
* 返回值说明: com.yfd.platform.config.ResponseResult 返回增加成功或者失败
***********************************/
ResponseResult addTsNodes(TsNodes tsnodes);
/**********************************
* 用途说明: 修改试验任务节点
* 参数说明 tsnodes 试验任务节点信息
* 返回值说明: com.yfd.platform.config.ResponseResult 返回修改成功或者失败
***********************************/
ResponseResult updateTsNodes(TsNodes tsnodes);
/**********************************
* 用途说明: 根据ID删除试验任务节点
* 参数说明 id 试验任务节点ID
* 返回值说明: com.yfd.platform.config.ResponseResult 返回删除成功或者失败
***********************************/
boolean deleteTsNodesById(String id);
}

View File

@ -0,0 +1,47 @@
package com.yfd.platform.modules.experimentalData.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yfd.platform.modules.experimentalData.domain.TsTask;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 试验任务表 服务类
* </p>
*
* @author LiMengNan
* @since 2025-01-21
*/
public interface ITsTaskService extends IService<TsTask> {
/**********************************
* 用途说明: 分页查询试验数据管理-试验任务管理
* 参数说明
* taskName 任务名称
* startDate (开始日期)
* endDate 结束日期
* taskPlace 任务地点
* taskPerson 任务人员
* carrierType 载体类型
* deviceCode 设备
* pageNum 当前页
* 返回值说明: com.yfd.platform.config.ResponseResult 返回分页查询结果
***********************************/
Page<TsTask> getTsTaskPage(String taskName, String startDate, String endDate, String taskPlace, String taskPerson, String carrierType, String deviceCode, Page<TsTask> page);
/***********************************
* 用途说明新增试验数据管理-试验任务管理
* 参数说明
* TsTask 试验任务管理
* 返回值说明: com.yfd.platform.config.ResponseResult 返回新增成功或者失败
***********************************/
Boolean addSdproject(TsTask tsTask);
/**********************************
* 用途说明: 修改试验数据管理-试验任务管理
* 参数说明
* TsTask 试验任务管理
* 返回值说明: com.yfd.platform.config.ResponseResult 返回修改成功或者失败
***********************************/
boolean updatetsTask(TsTask tsTask);
}

View File

@ -0,0 +1,564 @@
package com.yfd.platform.modules.experimentalData.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yfd.platform.config.ResponseResult;
import com.yfd.platform.modules.experimentalData.domain.TsFiles;
import com.yfd.platform.modules.experimentalData.domain.TsNodes;
import com.yfd.platform.modules.experimentalData.mapper.TsFilesMapper;
import com.yfd.platform.modules.experimentalData.mapper.TsNodesMapper;
import com.yfd.platform.modules.experimentalData.service.ITsNodesService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yfd.platform.modules.specialDocument.domain.Nodes;
import com.yfd.platform.modules.specialDocument.mapper.NodesMapper;
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.request.BatchDeleteRequest;
import com.yfd.platform.modules.storage.model.request.NewFolderRequest;
import com.yfd.platform.modules.storage.model.request.RenameFolderRequest;
import com.yfd.platform.modules.storage.service.base.AbstractBaseFileService;
import com.yfd.platform.system.domain.LoginUser;
import com.yfd.platform.utils.StringUtils;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.*;
/**
* <p>
* 试验任务节点表 服务实现类
* </p>
*
* @author LiMengNan
* @since 2025-01-21
*/
@Service
public class TsNodesServiceImpl extends ServiceImpl<TsNodesMapper, TsNodes> implements ITsNodesService {
private static final Logger LOGGER = LoggerFactory.getLogger(ChannelInboundHandlerAdapter.class);
//试验任务节点表 Mapper
@Resource
private TsNodesMapper tsNodesMapper;
//试验任务文档表 Mapper
@Resource
private TsFilesMapper tsFilesMapper;
//数据源Mapper
@Resource
private StorageSourceMapper storageSourceMapper;
@Resource
private StorageSourceContext storageSourceContext;
@Override
public List<Map<String, Object>> getTsNodesTree(String nodeName, String taskId) {
// 查询所有节点数据
List<Map<String, Object>> allNodes = getAllNodes(taskId);
// 查找所有根节点parentId为"00"的节点
List<Map<String, Object>> rootNodes = findRootNodes(allNodes, taskId);
// 如果未找到根节点返回空列表
if (rootNodes.isEmpty()) {
return new ArrayList<>();
}
// 存储最终结果
List<Map<String, Object>> result = new ArrayList<>();
// 如果 nodeName 为空返回所有根节点的完整树形结构
if (StringUtils.isEmpty(nodeName)) {
for (Map<String, Object> rootNode : rootNodes) {
result.addAll(buildFullTree(rootNode, allNodes));
}
return result;
}
// 否则返回从根节点到目标节点的树形结构
for (Map<String, Object> rootNode : rootNodes) {
List<Map<String, Object>> tree = buildTreeToTargetNode(rootNode, allNodes, nodeName);
if (!tree.isEmpty()) {
result.addAll(tree);
}
}
// 返回结果
return result;
}
/**
* 查询所有节点数据
*
* @param taskId 任务ID用于精确查询
* @return 返回所有节点列表
*/
private List<Map<String, Object>> getAllNodes(String taskId) {
// 创建查询条件
QueryWrapper<TsNodes> queryWrapper = new QueryWrapper<>();
queryWrapper.select(
"node_id as nodeId", // 节点ID
"node_name as nodeName", // 节点名称
"task_id as taskId", // 所属任务ID
"parent_id as parentId", // 父节点ID
"node_order as nodeOrder", // 节点顺序
"create_time as createTime", // 创建时间
"creator" // 创建人
);
// 如果任务ID不为空添加精确查询条件
if (StringUtils.isNotEmpty(taskId)) {
queryWrapper.eq("task_id", taskId);
}
// 按节点顺序升序排序
queryWrapper.orderByAsc("node_order");
// 查询所有符合条件的节点
return tsNodesMapper.selectMaps(queryWrapper);
}
/**
* 查找所有根节点parentId为"00"的节点
*
* @param allNodes 所有节点数据
* @param taskId 任务ID
* @return 返回所有根节点列表
*/
private List<Map<String, Object>> findRootNodes(List<Map<String, Object>> allNodes, String taskId) {
List<Map<String, Object>> rootNodes = new ArrayList<>();
for (Map<String, Object> node : allNodes) {
if ("00".equals(node.get("parentId").toString()) && taskId.equals(node.get("taskId").toString())) {
rootNodes.add(node);
}
}
return rootNodes;
}
/**
* 构建完整的树形结构
*
* @param currentNode 当前节点
* @param allNodes 所有节点数据
* @return 返回当前节点的子树
*/
private List<Map<String, Object>> buildFullTree(Map<String, Object> currentNode, List<Map<String, Object>> allNodes) {
// 查找当前节点的所有子节点
List<Map<String, Object>> children = findChildren(allNodes, currentNode.get("nodeId").toString());
// 递归构建子树
List<Map<String, Object>> tree = new ArrayList<>();
for (Map<String, Object> child : children) {
List<Map<String, Object>> childTree = buildFullTree(child, allNodes);
if (!childTree.isEmpty()) {
tree.addAll(childTree);
}
}
// 将当前节点加入树中
Map<String, Object> nodeWithChildren = new HashMap<>(currentNode);
if (!tree.isEmpty()) {
nodeWithChildren.put("children", tree);
}
return Collections.singletonList(nodeWithChildren);
}
/**
* 查找当前节点的所有子节点
*
* @param allNodes 所有节点数据
* @param parentId 父节点ID
* @return 返回所有子节点列表
*/
private List<Map<String, Object>> findChildren(List<Map<String, Object>> allNodes, String parentId) {
List<Map<String, Object>> children = new ArrayList<>();
for (Map<String, Object> node : allNodes) {
if (parentId.equals(node.get("parentId").toString())) {
children.add(node);
}
}
return children;
}
/**
* 构建从根节点到目标节点的树形结构
*
* @param currentNode 当前节点
* @param allNodes 所有节点数据
* @param nodeName 目标节点名称
* @return 返回从根节点到目标节点的树形结构
*/
private List<Map<String, Object>> buildTreeToTargetNode(Map<String, Object> currentNode, List<Map<String, Object>> allNodes, String nodeName) {
List<Map<String, Object>> result = new ArrayList<>();
// 查找当前节点的所有子节点
List<Map<String, Object>> children = findChildren(allNodes, currentNode.get("nodeId").toString());
// 递归查找目标节点
for (Map<String, Object> child : children) {
List<Map<String, Object>> childTree = buildTreeToTargetNode(child, allNodes, nodeName);
if (!childTree.isEmpty()) {
// 如果找到目标节点将当前节点加入树中并将其作为子节点
Map<String, Object> nodeWithChildren = new HashMap<>(currentNode);
nodeWithChildren.put("children", childTree);
result.add(nodeWithChildren); // 将当前节点加入结果列表
}
}
// 如果当前节点符合条件且没有被添加到result则将其添加
if (currentNode.get("nodeName") instanceof String && ((String) currentNode.get("nodeName")).contains(nodeName) && result.isEmpty()) {
result.add(currentNode); // 将当前节点添加到结果列表
}
// 返回包含所有符合条件的树结构的列表
return result;
// // 如果当前节点是目标节点返回当前节点
// if (currentNode.get("nodeName") instanceof String &&((String) currentNode.get("nodeName")).contains(nodeName)) {
// return Collections.singletonList(currentNode);
// }
//// if (nodeName.equals(currentNode.get("nodeName"))) {
//// return Collections.singletonList(currentNode);
//// }
//
// // 查找当前节点的所有子节点
// List<Map<String, Object>> children = findChildren(allNodes, currentNode.get("nodeId").toString());
//
// // 递归查找目标节点
// for (Map<String, Object> child : children) {
// List<Map<String, Object>> childTree = buildTreeToTargetNode(child, allNodes, nodeName);
// if (!childTree.isEmpty()) {
// // 如果找到目标节点将当前节点加入树中
// Map<String, Object> nodeWithChildren = new HashMap<>(currentNode);
// nodeWithChildren.put("children", childTree);
// return Collections.singletonList(nodeWithChildren);
// }
// }
//
// // 如果未找到目标节点返回空列表
// return new ArrayList<>();
}
/**********************************
* 用途说明: 增加试验任务节点
* 参数说明 nodes 专项文档节点信息
* 返回值说明: com.yfd.platform.config.ResponseResult 返回增加成功或者失败
***********************************/
@Override
@Transactional(rollbackFor = Exception.class) // 添加事务注解遇到异常时回滚
public ResponseResult addTsNodes(TsNodes tsnodes) {
// 差不多的流程 就是提出来 然后判断 如果两个 中有一个是true
//获取当前登录用户
UsernamePasswordAuthenticationToken authentication =
(UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
LoginUser loginuser = (LoginUser) authentication.getPrincipal();
//创建人是当前登录人
tsnodes.setCreator(loginuser.getUsername());
//当前操作时间
LocalDateTime now = LocalDateTime.now();
// 转换为 Timestamp
Timestamp currentTime = Timestamp.valueOf(now);
tsnodes.setCreateTime(currentTime);
//通过获取上级节点的条数 设置节点顺序
QueryWrapper<TsNodes> queryWrapperNodeOrder = new QueryWrapper<>();
int orderno = this.count(queryWrapperNodeOrder.eq("parent_id", tsnodes.getParentId())) + 1;
//判断节点名称是否存在
QueryWrapper<TsNodes> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("node_name", tsnodes.getNodeName());//名称
queryWrapper.eq("parent_id", tsnodes.getParentId());//父节点
int count = tsNodesMapper.selectCount(queryWrapper);
// 大于0说明 区域名称重复
if (count > 0) {
return ResponseResult.error("节点名称已存在!");
}
//序号
tsnodes.setNodeOrder(orderno);
//查询数据源
List<StorageSource> storageSources = storageSourceMapper.findAllOrderByOrderNum();
// 获取路径
List<String> pathNodes = new ArrayList<>();
TsNodes nodesData = tsNodesMapper.selectById(tsnodes.getParentId());
// 从当前节点向上遍历直到根节点
while (nodesData != null) {
pathNodes.add(nodesData.getNodeName());
// 如果父节点是 "00"说明已经到了根节点停止遍历
if ("00".equals(nodesData.getParentId())) {
break;
}
// 获取父节点
nodesData = tsNodesMapper.selectById(nodesData.getParentId()); // 修正 nodesData 中获取 parentId
}
// 反转路径使其从根节点到当前节点
Collections.reverse(pathNodes);
String path = "/" + String.join("/", pathNodes);
//判断 local或者minio有没有成功
List<Boolean> results = new ArrayList<>();
for (StorageSource storageSource : storageSources) {
//新增节点的时候 创建文件夹
NewFolderRequest newFolderRequest = new NewFolderRequest();
newFolderRequest.setName(tsnodes.getNodeName());//新建的文件夹名称,示例值(/a/b/c)
newFolderRequest.setPassword("");//文件夹密码, 如果文件夹需要密码才能访问则支持请求密码,示例值(123456)
newFolderRequest.setPath(path);//请求路径,示例值(/)
newFolderRequest.setStorageKey(storageSource.getType().toString());//存储源 key,示例值(local minio)
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(newFolderRequest.getStorageKey());
boolean flag = fileService.newFolder(newFolderRequest.getPath(), newFolderRequest.getName());
results.add(flag);
}
// 使用Java 8的Stream API检查列表中是否包含true
boolean hasTrue = results.stream().anyMatch(Boolean::booleanValue);
//如果是true 说明至少有一个生成了文件夹 下一步建立表数据
if (hasTrue) {
int valueAdded = tsNodesMapper.insert(tsnodes);
if (valueAdded == 1) {
LOGGER.info("local和minio新增成功表结构增加成功");
return ResponseResult.success();
} else {
LOGGER.error("local和minio新增成功表结构增加失败");
return ResponseResult.error();
}
} else {
LOGGER.error("local和minio新增失败");
return ResponseResult.error();
}
}
/**********************************
* 用途说明: 修改试验任务节点
* 参数说明 tsnodes 试验任务节点信息
* 返回值说明: com.yfd.platform.config.ResponseResult 返回修改成功或者失败
***********************************/
@Override
public ResponseResult updateTsNodes(TsNodes tsnodes) {
//查询没改之前的节点名称
TsNodes nodesold = tsNodesMapper.selectById(tsnodes.getNodeId());
//新的节点名称
String nodeName = tsnodes.getNodeName();
//老的节点名称
String nodeNameOld = null;
if (ObjUtil.isNotEmpty(nodesold)) {
nodeNameOld = nodesold.getNodeName();
}
//获取当前登录用户
UsernamePasswordAuthenticationToken authentication =
(UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
LoginUser loginuser = (LoginUser) authentication.getPrincipal();
//创建人是当前登录人
tsnodes.setCreator(loginuser.getUsername());
//判断节点名称是否存在
QueryWrapper<TsNodes> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("node_name", tsnodes.getNodeName());//名称
queryWrapper.eq("parent_id", tsnodes.getParentId());//父节点
int count = tsNodesMapper.selectCount(queryWrapper);
// 大于0说明 区域名称重复
if (count > 0) {
return ResponseResult.error("节点名称已存在!");
}
//查询数据源
List<StorageSource> storageSources = storageSourceMapper.findAllOrderByOrderNum();
List<String> pathNodes = new ArrayList<>();
TsNodes nodesData = tsNodesMapper.selectById(tsnodes.getParentId());
// 从当前节点向上遍历直到根节点
while (nodesData != null) {
pathNodes.add(nodesData.getNodeName());
// 如果父节点是 "00"说明已经到了根节点停止遍历
if ("00".equals(nodesData.getParentId())) {
break;
}
// 获取父节点
nodesData = tsNodesMapper.selectById(nodesData.getParentId()); // 修正 nodesData 中获取 parentId
}
// 反转路径使其从根节点到当前节点
Collections.reverse(pathNodes);
String path = String.join("/", pathNodes);
//判断 local或者minio有没有成功
List<Boolean> results = new ArrayList<>();
for (StorageSource storageSource : storageSources) {
//修改文件夹名称
RenameFolderRequest renameFolderRequest = new RenameFolderRequest();
renameFolderRequest.setName(nodeNameOld);//重命名的原文件夹名称,示例值(movie)
renameFolderRequest.setNewName(nodeName);// 重命名后的文件名称,示例值(music)
renameFolderRequest.setPassword("");//文件夹密码, 如果文件夹需要密码才能访问则支持请求密码,示例值(123456)
renameFolderRequest.setPath(path);//请求路径,示例值(/)
renameFolderRequest.setStorageKey(storageSource.getType().toString());//存储源 key,示例值(local minio)
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(renameFolderRequest.getStorageKey());
boolean flag = fileService.renameFolder(renameFolderRequest.getPath(), renameFolderRequest.getName(), renameFolderRequest.getNewName());
results.add(flag);
}
// 使用Java 8的Stream API检查列表中是否包含true
boolean hasTrue = results.stream().anyMatch(Boolean::booleanValue);
//如果是true 说明至少有一个生成了文件夹 下一步建立表数据
if (hasTrue) {
int valueAdded = tsNodesMapper.updateById(tsnodes);
if (valueAdded == 1) {
LOGGER.info("local和minio修改成功表结构增加成功");
return ResponseResult.success();
} else {
LOGGER.error("local和minio修改成功表结构增加失败");
return ResponseResult.error();
}
} else {
LOGGER.error("local和minio修改失败");
return ResponseResult.error();
}
}
/**********************************
* 用途说明: 根据ID删除试验任务节点
* 参数说明 id 试验任务节点ID
* 返回值说明: com.yfd.platform.config.ResponseResult 返回删除成功或者失败
***********************************/
@Override
public boolean deleteTsNodesById(String id) {
// try {
//根据ID 查询当前数据
TsNodes tsNodes = tsNodesMapper.selectById(id);
//删除之前 先拼路径 然后删除本地和minio的文件夹 最后删除表结构
// 删除当前节点
int deleteCount = tsNodesMapper.deleteById(id);
//删除当前节点的 文件
QueryWrapper<TsFiles> queryWrapper1 = new QueryWrapper<>();
queryWrapper1.eq("node_id", tsNodes.getNodeId());
queryWrapper1.eq("task_id", tsNodes.getTaskId());
tsFilesMapper.delete(queryWrapper1);
List<String> pathNodes = new ArrayList<>();
TsNodes nodesData = tsNodesMapper.selectById(tsNodes.getParentId());
// 从当前节点向上遍历直到根节点
while (nodesData != null) {
pathNodes.add(nodesData.getNodeName());
// 如果父节点是 "00"说明已经到了根节点停止遍历
if ("00".equals(nodesData.getParentId())) {
break;
}
// 获取父节点
nodesData = tsNodesMapper.selectById(nodesData.getParentId()); // 修正 nodesData 中获取 parentId
}
// 反转路径使其从根节点到当前节点
Collections.reverse(pathNodes);
String path = String.join("/", pathNodes);
List<BatchDeleteRequest.DeleteItem> deleteItemList = new ArrayList<>();
BatchDeleteRequest.DeleteItem deleteItemData = new BatchDeleteRequest.DeleteItem();
deleteItemData.setName(tsNodes.getNodeName());
deleteItemData.setPassword("");
deleteItemData.setPath(path);
deleteItemData.setType(FileTypeEnum.FOLDER);
deleteItemList.add(deleteItemData);
//查询数据源
List<StorageSource> storageSources = storageSourceMapper.findAllOrderByOrderNum();
//判断 local或者minio有没有成功
List<Boolean> results = new ArrayList<>();
for (StorageSource storageSource : storageSources) {
BatchDeleteRequest batchDeleteRequest = new BatchDeleteRequest();
batchDeleteRequest.setDeleteItems(deleteItemList);
batchDeleteRequest.setStorageKey(storageSource.getKey());
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(batchDeleteRequest.getStorageKey());
List<BatchDeleteRequest.DeleteItem> deleteItems = batchDeleteRequest.getDeleteItems();
int deleteSuccessCount = 0, deleteFailCount = 0, totalCount = CollUtil.size(deleteItems);
for (BatchDeleteRequest.DeleteItem deleteItem : deleteItems) {
boolean flag = false;
try {
if (deleteItem.getType() == FileTypeEnum.FILE) {
flag = fileService.deleteFile(deleteItem.getPath(), deleteItem.getName());
} else if (deleteItem.getType() == FileTypeEnum.FOLDER) {
flag = fileService.deleteFolder(deleteItem.getPath(), deleteItem.getName());
}
if (flag) {
deleteSuccessCount++;
} else {
deleteFailCount++;
}
} catch (Exception e) {
LOGGER.error("删除文件/文件夹失败, 文件路径: {}, 文件名称: {}", deleteItem.getPath(), deleteItem.getName(), e);
deleteFailCount++;
}
}
if (totalCount > 1) {
//return ResponseResult.success("批量删除 " + totalCount + " 个, 删除成功 " + deleteSuccessCount + " 个, 失败 " + deleteFailCount + " 个.");
LOGGER.error("批量删除 " + totalCount + " 个, 删除成功 " + deleteSuccessCount + " 个, 失败 " + deleteFailCount + " 个.");
} else {
//return totalCount == deleteSuccessCount ? ResponseResult.success("删除成功") : ResponseResult.error("删除失败");
LOGGER.error("批量删除 " + totalCount + " 个, 删除成功 " + deleteSuccessCount + " 个, 失败 " + deleteFailCount + " 个.");
}
//如果是1 说明成功删除
if (deleteSuccessCount >= 1) {
results.add(true);
} else {
results.add(false);
}
}
// 使用Java 8的Stream API检查列表中是否包含true
boolean hasTrue = results.stream().anyMatch(Boolean::booleanValue);
if (hasTrue) {
// 递归删除子节点
deleteChildren(tsNodes.getNodeId(), tsNodes.getTaskId());
}
return hasTrue;
// } catch (Exception e) {
// // 如果发生异常返回 false
// return false;
// }
}
/**
* 递归删除子节点
*
* @param parentId 父节点ID
*/
private void deleteChildren(String parentId, String taskId) {
// 使用 QueryWrapper 查询当前节点的所有子节点
QueryWrapper<TsNodes> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("parent_id", parentId); // parent_id = #{parentId}
queryWrapper.eq("task_id", taskId); // parent_id = #{parentId}
List<TsNodes> children = tsNodesMapper.selectList(queryWrapper);
// 递归删除每个子节点
for (TsNodes child : children) {
deleteChildren(child.getNodeId(), child.getTaskId()); // 递归删除子节点的子节点
tsNodesMapper.deleteById(child.getNodeId()); // 删除当前子节点
//批量文件的数据
QueryWrapper<TsFiles> queryWrapper1 = new QueryWrapper<>();
queryWrapper1.eq("node_id", parentId);
queryWrapper1.eq("task_id", taskId);
tsFilesMapper.delete(queryWrapper1);
}
}
}

View File

@ -0,0 +1,124 @@
package com.yfd.platform.modules.experimentalData.service.impl;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yfd.platform.modules.experimentalData.domain.TsTask;
import com.yfd.platform.modules.experimentalData.mapper.TsTaskMapper;
import com.yfd.platform.modules.experimentalData.service.ITsTaskService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yfd.platform.utils.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.sql.Timestamp;
import java.time.LocalDateTime;
/**
* <p>
* 试验任务表 服务实现类
* </p>
*
* @author LiMengNan
* @since 2025-01-21
*/
@Service
public class TsTaskServiceImpl extends ServiceImpl<TsTaskMapper, TsTask> implements ITsTaskService {
//试验任务Mapper
@Resource
private TsTaskMapper tsTaskMapper;
/**********************************
* 用途说明: 分页查询试验数据管理-试验任务管理
* 参数说明
* taskName 任务名称
* startDate (开始日期)
* endDate 结束日期
* taskPlace 任务地点
* taskPerson 任务人员
* carrierType 载体类型
* deviceCode 设备
* pageNum 当前页
* 返回值说明: com.yfd.platform.config.ResponseResult 返回分页查询结果
***********************************/
@Override
public Page<TsTask> getTsTaskPage(String taskName, String startDate, String endDate, String taskPlace, String taskPerson, String carrierType, String deviceCode, Page<TsTask> page) {
LambdaQueryWrapper<TsTask> queryWrapper = new LambdaQueryWrapper<>();
//如果任务名称 taskName 不为空
if (StringUtils.isNotEmpty(taskName)) {
queryWrapper.like(TsTask::getTaskName, taskName);
}
//如果任务地点 taskPlace 不为空
if (StringUtils.isNotEmpty(taskPlace)) {
queryWrapper.like(TsTask::getTaskPlace, taskPlace);
}
//如果任务人员 taskPerson 不为空
if (StringUtils.isNotEmpty(taskPerson)) {
queryWrapper.like(TsTask::getTaskPerson, taskPerson);
}
//如果操作类型 carrierType 不为空
if (StringUtils.isNotEmpty(carrierType)) {
queryWrapper.like(TsTask::getCarrierType, carrierType);
}
//如果设备 deviceCode 不为空
if (StringUtils.isNotEmpty(deviceCode)) {
queryWrapper.like(TsTask::getDeviceCode, deviceCode);
}
//开始时间startDate
DateTime parseStartDate = DateUtil.parse(startDate);
//时间endDate不为空
DateTime parseEndDate = DateUtil.parse(endDate);
//开始时间和结束时间不为空 查询条件>=开始时间 <结束时间
if (parseStartDate != null && parseEndDate != null) {
queryWrapper.ge(TsTask::getTaskDate, parseStartDate).lt(TsTask::getTaskDate, parseEndDate);
}
//分页查询
Page<TsTask> tsTaskPage = tsTaskMapper.selectPage(page, queryWrapper);
return tsTaskPage;
}
/***********************************
* 用途说明新增试验数据管理-试验任务管理
* 参数说明
* TsTask 试验任务管理
* 返回值说明: com.yfd.platform.config.ResponseResult 返回新增成功或者失败
***********************************/
@Override
public Boolean addSdproject(TsTask tsTask) {
// 设置当前时间
LocalDateTime now = LocalDateTime.now();
// 转换为 Timestamp
Timestamp currentTime = Timestamp.valueOf(now);
tsTask.setCreateTime(currentTime);
int valueAdded = tsTaskMapper.insert(tsTask);
if (valueAdded == 1) {
return true;
} else {
return false;
}
}
/**********************************
* 用途说明: 修改试验数据管理-试验任务管理
* 参数说明
* TsTask 试验任务管理
* 返回值说明: com.yfd.platform.config.ResponseResult 返回修改成功或者失败
***********************************/
@Override
public boolean updatetsTask(TsTask tsTask) {
int valueUpdate = tsTaskMapper.updateById(tsTask);
if (valueUpdate == 1) {
return true;
} else {
return false;
}
}
}

View File

@ -0,0 +1,147 @@
package com.yfd.platform.modules.specialDocument.controller;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yfd.platform.annotation.Log;
import com.yfd.platform.config.ResponseResult;
import com.yfd.platform.modules.specialDocument.domain.Files;
import com.yfd.platform.modules.specialDocument.service.IFilesService;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
/**
* <p>
* 专项文档表 前端控制器
* </p>
*
* @author LiMengNan
* @since 2025-01-20
*/
@RestController
@RequestMapping("/specialDocument/sd_files")
public class FilesController {
//专项文档服务类
@Resource
private IFilesService filesService;
/**********************************
* 用途说明: 分页查询专项文档管理-文档内容
* 参数说明
* fileName 文件名称
* startDate (开始日期)
* endDate 结束日期
* keywords 关键字
*nodeId 节点ID
*projectId 所属项目ID
* pageNum 当前页
* 返回值说明: com.yfd.platform.config.ResponseResult 返回分页查询结果
***********************************/
@GetMapping("/page")
@ApiOperation("分页查询专项文档管理文档内容")
@PreAuthorize("@el.check('select:files')")
public ResponseResult getFilesPage(String fileName, String startDate, String endDate, String keywords, String nodeId,String projectId, Page<Files> page) throws Exception {
//分页查询
Page<Files> filesPage = filesService.getFilesPage(fileName, startDate, endDate, keywords, nodeId, projectId, fileName, page);
return ResponseResult.successData(filesPage);
}
/***********************************
* 用途说明新增专项文档管理-文档内容
* 参数说明
* Files 文档内容
* 返回值说明: com.yfd.platform.config.ResponseResult 返回新增成功或者失败
***********************************/
@Log(module = "专项文档管理", value = "新增专项文档管理文档内容!",type = "1")
@PostMapping("/addFiles")
@ApiOperation("新增专项文档管理文档内容")
@ResponseBody
@PreAuthorize("@el.check('add:files')")
public ResponseResult addFiles(@RequestBody Files files) {
//对象不能为空
if (ObjUtil.isEmpty(files)) {
return ResponseResult.error("参数为空");
}
Boolean isOk = filesService.addFiles(files);
if (isOk) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
/**********************************
* 用途说明: 修改专项文档管理-文档内容
* 参数说明
* Files 文档内容
* 返回值说明: com.yfd.platform.config.ResponseResult 返回修改成功或者失败
***********************************/
@Log(module = "专项文档管理", value = "修改专项文档管理文档内容",type = "1")
@PostMapping("/updateFiles")
@ApiOperation("修改专项文档管理文档内容")
@PreAuthorize("@el.check('update:files')")
public ResponseResult updateFiles(@RequestBody Files files) {
//对象不能为空
if (ObjUtil.isEmpty(files) && StrUtil.isBlank(files.getId())) {
return ResponseResult.error("参数为空");
}
boolean isOk = filesService.updateFiles(files);
if (isOk) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
/**********************************
* 用途说明: 根据ID删除专项文档管理-文档内容
* 参数说明 id 文档内容ID
* 返回值说明: com.yfd.platform.config.ResponseResult 返回删除成功或者失败
***********************************/
@Log(module = "专项文档管理", value = "根据ID删除专项文档管理文档内容",type = "1")
@PostMapping("/deleteFilesById")
@ApiOperation("根据ID删除专项文档管理文档内容")
@PreAuthorize("@el.check('del:systemdevice')")
public ResponseResult deleteFilesById(@RequestParam String id) {
if (StrUtil.isBlank(id)) {
return ResponseResult.error("参数为空");
}
List<String> dataset = Arrays.asList(id);
return ResponseResult.success(filesService.deleteFilesByIds(dataset));
}
/**********************************
* 用途说明: 批量删除专项文档管理-文档内容
* 参数说明 ids 文档内容id数组
* 返回值说明: com.yfd.platform.config.ResponseResult 返回批量删除成功或失败
***********************************/
@Log(module = "专项文档管理", value = "批量删除专项文档管理文档内容",type = "1")
@PostMapping("/deleteFilesByIds")
@ApiOperation("批量删除专项文档管理文档内容")
@PreAuthorize("@el.check('del:systemdevice')")
public ResponseResult deleteFilesByIds(@RequestParam String ids) {
if (StrUtil.isBlank(ids)) {
return ResponseResult.error("参数为空");
}
String[] splitIds = ids.split(",");
// 数组转集合
List<String> dataset = Arrays.asList(splitIds);
return ResponseResult.success(filesService.deleteFilesByIds(dataset));
}
}

View File

@ -0,0 +1,131 @@
package com.yfd.platform.modules.specialDocument.controller;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.yfd.platform.annotation.Log;
import com.yfd.platform.config.ResponseResult;
import com.yfd.platform.modules.specialDocument.domain.Nodes;
import com.yfd.platform.modules.specialDocument.service.INodesService;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* <p>
* 专项文档节点表 前端控制器
* </p>
*
* @author LiMengNan
* @since 2025-01-20
*/
@RestController
@RequestMapping("/specialDocument/sd_nodes")
public class NodesController {
//专项文档节点服务类
@Resource
private INodesService nodesService;
/***********************************
* 用途说明获取专项文档节点 树形结构
* 参数说明
* nodeName 节点名称
* projectId 所属项目ID
* 返回值说明: 专项文档节点树形结构
***********************************/
@PostMapping("/getNodesTree")
@ApiOperation("获取专项文档节点树形结构")
@ResponseBody
@PreAuthorize("@el.check('select:nodes')")
public ResponseResult getNodesTree(String nodeName,String projectId) {
List<Map<String, Object>> list = nodesService.getNodesTree(nodeName,projectId);
return ResponseResult.successData(list);
}
/**********************************
* 用途说明: 增加专项文档节点
* 参数说明 nodes 专项文档节点信息
* 返回值说明: com.yfd.platform.config.ResponseResult 返回增加成功或者失败
***********************************/
@Log(module = "专项文档管理", value = "增加专项文档节点",type = "1")
@PostMapping("/addNodes")
@ApiOperation("增加专项文档节点")
@PreAuthorize("@el.check('add:nodes')")
public ResponseResult addNodes(@RequestBody Nodes nodes) {
//参数校验 对象 节点名称 所属项目ID
if (ObjUtil.isEmpty(nodes) && StrUtil.isBlank(nodes.getNodeName()) && StrUtil.isBlank(nodes.getProjectId()) ) {
return ResponseResult.error("参数为空");
}
return nodesService.addNodes(nodes);
}
/**********************************
* 用途说明: 修改专项文档节点
* 参数说明 nodes 专项文档节点信息
* 返回值说明: com.yfd.platform.config.ResponseResult 返回修改成功或者失败
***********************************/
@Log(module = "专项文档管理", value = "修改专项文档节点",type = "1")
@PostMapping("/updateNodes")
@ApiOperation("修改专项文档节点")
@PreAuthorize("@el.check('update:nodes')")
public ResponseResult updateNodes(@RequestBody Nodes nodes) {
//参数校验 对象 节点名称 所属项目ID id
if (ObjUtil.isEmpty(nodes) && StrUtil.isBlank(nodes.getNodeName()) && StrUtil.isBlank(nodes.getProjectId()) && StrUtil.isBlank(nodes.getId())) {
return ResponseResult.error("参数为空");
}
return nodesService.updateNodes(nodes);
}
/**********************************
* 用途说明: 根据ID删除专项文档节点
* 参数说明 id 专项文档节点ID
* 返回值说明: com.yfd.platform.config.ResponseResult 返回删除成功或者失败
***********************************/
@Log(module = "专项文档管理", value = "根据ID删除专项文档节点",type = "1")
@PostMapping("/deleteNodesById")
@ApiOperation("根据ID删除专项文档节点")
@PreAuthorize("@el.check('del:nodes')")
public ResponseResult deleteNodesById(@RequestParam String id) {
if (StrUtil.isBlank(id)) {
return ResponseResult.error("参数为空");
}
boolean isOk = nodesService.deleteNodesById(id);
if (isOk) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
// /**********************************
// * 用途说明: 批量删除专项文档节点
// * 参数说明 ids 专项文档节点id数组
// * 返回值说明: com.yfd.platform.config.ResponseResult 返回批量删除成功或失败
// ***********************************/
// @Log(module = "专项文档管理", value = "批量删除专项文档节点",type = "1")
// @PostMapping("/deleteNodesByIds")
// @ApiOperation("批量删除专项文档节点")
// @PreAuthorize("@el.check('del:nodes')")
// public ResponseResult deleteSdprojectByIds(@RequestParam String ids) {
// if (StrUtil.isBlank(ids)) {
// return ResponseResult.error("参数为空");
// }
// String[] splitIds = ids.split(",");
// // 数组转集合
// List<String> dataset = Arrays.asList(splitIds);
// boolean isOk = nodesService.removeByIds(dataset);
// if (isOk) {
// return ResponseResult.success();
// } else {
// return ResponseResult.error();
// }
// }
}

View File

@ -0,0 +1,165 @@
package com.yfd.platform.modules.specialDocument.controller;
import cn.hutool.core.util.ObjUtil;
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.annotation.Log;
import com.yfd.platform.config.ResponseResult;
import com.yfd.platform.modules.specialDocument.domain.Project;
import com.yfd.platform.modules.specialDocument.service.IProjectService;
import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* <p>
* 专项项目表 前端控制器
* </p>
*
* @author LiMengNan
* @since 2025-01-20
*/
@RestController
@RequestMapping("/specialDocument/project")
public class ProjectController {
//专项项目服务类
@Resource
private IProjectService projectService;
/**********************************
* 用途说明: 分页查询专项文档管理-项目管理
* 参数说明
* projectCode 项目编号
* projectType 项目类型
*projectName 项目名称
* pageNum 当前页
* 返回值说明: com.yfd.platform.config.ResponseResult 返回分页查询结果
***********************************/
@GetMapping("/page")
@ApiOperation("分页查询专项文档管理项目管理")
@PreAuthorize("@el.check('select:project')")
public ResponseResult getSdProjectPage(String projectCode, String projectType, String projectName, Page<Project> page) {
//分页查询
Page<Project> sdProjectPage = projectService.getSdProjectPage(projectCode, projectType, projectName, page);
return ResponseResult.successData(sdProjectPage);
}
/***********************************
* 用途说明新增专项文档管理-项目管理
* 参数说明
* Project 项目管理
* 返回值说明: com.yfd.platform.config.ResponseResult 返回新增成功或者失败
***********************************/
@Log(module = "专项文档管理", value = "新增专项文档管理项目管理!",type = "1")
@PostMapping("/addSdproject")
@ApiOperation("新增专项文档管理项目管理")
@ResponseBody
@PreAuthorize("@el.check('add:project')")
public ResponseResult addSdproject(@RequestBody Project project) {
//对象不能为空
if (ObjUtil.isEmpty(project)) {
return ResponseResult.error("参数为空");
}
Boolean isOk = projectService.addSdproject(project);
if (isOk) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
/**********************************
* 用途说明: 修改专项文档管理-项目管理
* 参数说明
* Project 项目管理
* 返回值说明: com.yfd.platform.config.ResponseResult 返回修改成功或者失败
***********************************/
@Log(module = "专项文档管理", value = "修改专项文档管理项目管理",type = "1")
@PostMapping("/updateSdproject")
@ApiOperation("修改专项文档管理项目管理")
@PreAuthorize("@el.check('update:project')")
public ResponseResult updateSdproject(@RequestBody Project project) {
//对象不能为空
if (ObjUtil.isEmpty(project) && StrUtil.isBlank(project.getId())) {
return ResponseResult.error("参数为空");
}
boolean isOk = projectService.updateSdproject(project);
if (isOk) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
/**********************************
* 用途说明: 根据ID删除专项文档管理-项目管理
* 参数说明 id 项目管理ID
* 返回值说明: com.yfd.platform.config.ResponseResult 返回删除成功或者失败
***********************************/
@Log(module = "专项文档管理", value = "根据ID删除专项文档管理项目管理",type = "1")
@PostMapping("/deleteSdprojectById")
@ApiOperation("根据ID删除专项文档管理项目管理")
@PreAuthorize("@el.check('del:project')")
public ResponseResult deleteSdprojectById(@RequestParam String id) {
if (StrUtil.isBlank(id)) {
return ResponseResult.error("参数为空");
}
boolean isOk = projectService.removeById(id);
if (isOk) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
/**********************************
* 用途说明: 批量删除专项文档管理-项目管理
* 参数说明 ids 项目管理id数组
* 返回值说明: com.yfd.platform.config.ResponseResult 返回批量删除成功或失败
***********************************/
@Log(module = "专项文档管理", value = "批量删除专项文档管理项目管理",type = "1")
@PostMapping("/deleteSdprojectByIds")
@ApiOperation("批量删除专项文档管理项目管理")
@PreAuthorize("@el.check('del:project')")
public ResponseResult deleteSdprojectByIds(@RequestParam String ids) {
if (StrUtil.isBlank(ids)) {
return ResponseResult.error("参数为空");
}
String[] splitIds = ids.split(",");
// 数组转集合
List<String> dataset = Arrays.asList(splitIds);
boolean isOk = projectService.removeByIds(dataset);
if (isOk) {
return ResponseResult.success();
} else {
return ResponseResult.error();
}
}
/***********************************
* 用途说明 查询所有专项文档管理-项目管理
* 参数说明
* 返回值说明: 专项文档管理项目管理数据
***********************************/
@PostMapping("/list")
@ApiOperation("查询所有专项文档管理项目管理")
@ResponseBody
//@PreAuthorize("@el.check('select:devicesignal')")
public ResponseResult listSdproject() {
List<Project> projects = projectService.list();
return ResponseResult.successData(projects);
}
}

View File

@ -0,0 +1,114 @@
package com.yfd.platform.modules.specialDocument.domain;
import java.math.BigDecimal;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.nio.file.Path;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.io.Serializable;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
* 专项文档表
* </p>
*
* @author LiMengNan
* @since 2025-01-20
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("sd_files")
public class Files implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 文档ID
*/
@TableId(type = IdType.ASSIGN_UUID)
private String id;
/**
* 所属项目ID
*/
private String projectId;
/**
* 节点ID
*/
private String nodeId;
/**
* 文件名称
*/
private String fileName;
/**
* 文件对象存储路径
*/
private String filePath;
/**
* 关键字
*/
private String keywords;
/**
* 文件描述
*/
private String description;
/**
* M
*/
private String fileSize;
/**
* 上传时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Timestamp uploadTime;
/**
* 上传人
*/
private String uploader;
/**
* 备份1
*/
private String custom1;
/**
* 备份2
*/
private String custom2;
/**
* 备份3
*/
private String custom3;
/**
* 访问路径URLTODO 增加用于前端展示
*/
@TableField(exist = false)
private String url;
/**
* 类型 FILE FOLDERTODO 增加用于前端展示
*/
@TableField(exist = false)
private String type;
}

View File

@ -0,0 +1,95 @@
package com.yfd.platform.modules.specialDocument.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.io.Serializable;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
* 专项文档节点表
* </p>
*
* @author LiMengNan
* @since 2025-01-20
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("sd_nodes")
public class Nodes implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 节点ID
*/
@TableId(type = IdType.ASSIGN_UUID)
private String id;
/**
* 所属项目ID
*/
private String projectId;
/**
* 项目父节点ID 00
*/
private String parentId;
/**
* 节点顺序
*/
private Integer nodeOrder;
/**
* 节点类型00-项目 01-子项 02-课题 03-年度 04-主题
*/
private String nodeType;
/**
* 节点名称
*/
private String nodeName;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Timestamp createTime;
/**
* 创建人
*/
private String creator;
/**
* 备用字段1
*/
private String custom1;
/**
* 备用字段2
*/
private String custom2;
/**
* 备用字段3
*/
private String custom3;
/**
* TODO路径用于拼接
*/
@TableField(exist = false)
private String overallPath;
}

View File

@ -0,0 +1,95 @@
package com.yfd.platform.modules.specialDocument.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.io.Serializable;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
* 专项项目表
* </p>
*
* @author LiMengNan
* @since 2025-01-20
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("sd_project")
public class Project implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 项目ID
*/
@TableId(type = IdType.ASSIGN_UUID)
private String id;
/**
* 项目编号
*/
private String projectCode;
/**
* 项目类型自定义
*/
private String projectType;
/**
* 项目名称
*/
private String projectName;
/**
* 项目描述
*/
private String description;
/**
* 可扩展的Json对象
*/
private String projectProps;
/**
* 项目启动时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Timestamp projectTime;
/**
* 创建时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Timestamp createTime;
/**
* 创建人
*/
private String creator;
/**
* 备用字段1
*/
private String custom1;
/**
* 备用字段2
*/
private String custom2;
/**
* 备用字段3
*/
private String custom3;
}

View File

@ -0,0 +1,16 @@
package com.yfd.platform.modules.specialDocument.mapper;
import com.yfd.platform.modules.specialDocument.domain.Files;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 专项文档表 Mapper 接口
* </p>
*
* @author LiMengNan
* @since 2025-01-20
*/
public interface FilesMapper extends BaseMapper<Files> {
}

View File

@ -0,0 +1,16 @@
package com.yfd.platform.modules.specialDocument.mapper;
import com.yfd.platform.modules.specialDocument.domain.Nodes;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 专项文档节点表 Mapper 接口
* </p>
*
* @author LiMengNan
* @since 2025-01-20
*/
public interface NodesMapper extends BaseMapper<Nodes> {
}

View File

@ -0,0 +1,16 @@
package com.yfd.platform.modules.specialDocument.mapper;
import com.yfd.platform.modules.specialDocument.domain.Project;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 专项项目表 Mapper 接口
* </p>
*
* @author LiMengNan
* @since 2025-01-20
*/
public interface ProjectMapper extends BaseMapper<Project> {
}

View File

@ -0,0 +1,58 @@
package com.yfd.platform.modules.specialDocument.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yfd.platform.modules.specialDocument.domain.Files;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
/**
* <p>
* 专项文档表 服务类
* </p>
*
* @author LiMengNan
* @since 2025-01-20
*/
public interface IFilesService extends IService<Files> {
/**********************************
* 用途说明: 分页查询专项文档管理-文档内容
* 参数说明
* fileName 文件名称
* startDate (开始日期)
* endDate 结束日期
* keywords 关键字
*nodeId 节点ID
*projectId 所属项目ID
* pageNum 当前页
* 返回值说明: com.yfd.platform.config.ResponseResult 返回分页查询结果
***********************************/
Page<Files> getFilesPage(String fileName, String startDate, String endDate, String keywords, String nodeId, String projectId, String fileName1, Page<Files> page) throws Exception;
/***********************************
* 用途说明新增专项文档管理-文档内容
* 参数说明
* Files 文档内容
* 返回值说明: com.yfd.platform.config.ResponseResult 返回新增成功或者失败
***********************************/
Boolean addFiles(Files files);
/**********************************
* 用途说明: 修改专项文档管理-文档内容
* 参数说明
* Files 文档内容
* 返回值说明: com.yfd.platform.config.ResponseResult 返回修改成功或者失败
***********************************/
boolean updateFiles(Files files);
/**********************************
* 用途说明: 根据ID删除专项文档管理-文档内容
* 参数说明 id 文档内容ID
* 返回值说明: com.yfd.platform.config.ResponseResult 返回删除成功或者失败
**********************************
* @return*/
String deleteFilesByIds(List<String> dataset);
}

View File

@ -0,0 +1,50 @@
package com.yfd.platform.modules.specialDocument.service;
import com.yfd.platform.config.ResponseResult;
import com.yfd.platform.modules.specialDocument.domain.Nodes;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
import java.util.Map;
/**
* <p>
* 专项文档节点表 服务类
* </p>
*
* @author LiMengNan
* @since 2025-01-20
*/
public interface INodesService extends IService<Nodes> {
/***********************************
* 用途说明获取专项文档节点 树形结构
* 参数说明
* nodeName 节点名称
* projectId 所属项目ID
* 返回值说明: 专项文档节点树形结构
***********************************/
List<Map<String, Object>> getNodesTree(String nodeName,String projectId);
/**********************************
* 用途说明: 增加专项文档节点
* 参数说明 nodes 专项文档节点信息
* 返回值说明: com.yfd.platform.config.ResponseResult 返回增加成功或者失败
***********************************/
ResponseResult addNodes(Nodes nodes);
/**********************************
* 用途说明: 修改专项文档节点
* 参数说明 nodes 专项文档节点信息
* 返回值说明: com.yfd.platform.config.ResponseResult 返回修改成功或者失败
***********************************/
ResponseResult updateNodes(Nodes nodes);
/**********************************
* 用途说明: 根据ID删除专项文档节点
* 参数说明 id 专项文档节点ID
* 返回值说明: com.yfd.platform.config.ResponseResult 返回删除成功或者失败
***********************************/
boolean deleteNodesById(String id);
}

View File

@ -0,0 +1,43 @@
package com.yfd.platform.modules.specialDocument.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yfd.platform.modules.specialDocument.domain.Project;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 专项项目表 服务类
* </p>
*
* @author LiMengNan
* @since 2025-01-20
*/
public interface IProjectService extends IService<Project> {
/**********************************
* 用途说明: 分页查询专项文档管理-项目管理
* 参数说明
* projectCode 项目编号
* projectType 项目类型
*projectName 项目名称
* pageNum 当前页
* 返回值说明: com.yfd.platform.config.ResponseResult 返回分页查询结果
***********************************/
Page<Project> getSdProjectPage(String projectCode, String projectType, String projectName, Page<Project> page);
/***********************************
* 用途说明新增专项文档管理-项目管理
* 参数说明
* Project 项目管理
* 返回值说明: com.yfd.platform.config.ResponseResult 返回新增成功或者失败
***********************************/
Boolean addSdproject(Project project);
/**********************************
* 用途说明: 修改专项文档管理-项目管理
* 参数说明
* Project 项目管理
* 返回值说明: com.yfd.platform.config.ResponseResult 返回修改成功或者失败
***********************************/
boolean updateSdproject(Project project);
}

View File

@ -0,0 +1,383 @@
package com.yfd.platform.modules.specialDocument.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yfd.platform.exception.file.InvalidStorageSourceException;
import com.yfd.platform.modules.config.model.request.FileListRequest;
import com.yfd.platform.modules.specialDocument.domain.Files;
import com.yfd.platform.modules.specialDocument.mapper.FilesMapper;
import com.yfd.platform.modules.specialDocument.service.IFilesService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
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.controller.file.FileController;
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.RenameFileRequest;
import com.yfd.platform.modules.storage.model.result.FileInfoResult;
import com.yfd.platform.modules.storage.model.result.FileItemResult;
import com.yfd.platform.modules.storage.service.StorageSourceService;
import com.yfd.platform.modules.storage.service.base.AbstractBaseFileService;
import com.yfd.platform.system.domain.LoginUser;
import com.yfd.platform.utils.StringUtils;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* <p>
* 专项文档表 服务实现类
* </p>
*
* @author LiMengNan
* @since 2025-01-20
*/
@Service
public class FilesServiceImpl extends ServiceImpl<FilesMapper, Files> implements IFilesService {
private static final Logger LOGGER = LoggerFactory.getLogger(ChannelInboundHandlerAdapter.class);
//专项文档表 Mapper
@Resource
private FilesMapper filesMapper;
@Autowired
private FileController fileController;
@Resource
private StorageSourceContext storageSourceContext;
@Resource
private StorageSourceService storageSourceService;
@Resource
private FileChain fileChain;
/**********************************
* 用途说明: 分页查询专项文档管理-文档内容
* 参数说明
* fileName 文件名称
* startDate (开始日期)
* endDate 结束日期
* keywords 关键字
*nodeId 节点ID
*projectId 所属项目ID
* pageNum 当前页
* 返回值说明: com.yfd.platform.config.ResponseResult 返回分页查询结果
***********************************/
@Override
public Page<Files> getFilesPage(String fileName, String startDate, String endDate, String keywords, String nodeId, String projectId, String fileName1, Page<Files> page) throws Exception {
//先查询路径下的所有文件
//首先通过项目ID 和节点ID去查询表 获取一个路径 如果不是空 就调用minio的获取文件列表接口 查询的数据放在集合中
FileInfoResult fileInfoResult = null;
QueryWrapper<Files> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("project_id", projectId);
queryWrapper.eq("node_id", nodeId);
List<Files> filess = filesMapper.selectList(queryWrapper);
String filePath = null;
if (filess != null && !filess.isEmpty()) {
for (Files files : filess) {
filePath = files.getFilePath();
if (filePath != null && !filePath.isEmpty()) {
break; // 如果找到非空的 filePath终止循环
}
}
}
if (filePath != null) {
FileListRequest fileListRequest = new FileListRequest();
fileListRequest.setOrderBy("time");
fileListRequest.setOrderDirection("desc");
fileListRequest.setPassword("");
fileListRequest.setPath(filePath);
fileListRequest.setStorageKey("minio");
String storageKey = fileListRequest.getStorageKey();
Integer storageId = storageSourceService.findIdByKey(storageKey);
if (storageId == null) {
throw new InvalidStorageSourceException("通过存储源 key 未找到存储源, key: " + storageKey);
}
// 处理请求参数默认值
fileListRequest.handleDefaultValue();
// 获取文件列表
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageId(storageId);
List<FileItemResult> fileItemList = fileService.fileList(fileListRequest.getPath());
// 执行责任链
FileContext fileContext = FileContext.builder()
.storageId(storageId)
.fileListRequest(fileListRequest)
.fileItemList(fileItemList).build();
fileChain.execute(fileContext);
fileInfoResult = new FileInfoResult(fileContext.getFileItemList(), fileContext.getPasswordPattern());
}
//分页查询专项文档管理-文档内容
LambdaQueryWrapper<Files> queryWrapperfiles = new LambdaQueryWrapper<>();
//如果文件名称 不为空
if (StringUtils.isNotEmpty(fileName)) {
queryWrapperfiles.like(Files::getFileName, fileName);
}
//如果关键字 不为空
if (StringUtils.isNotEmpty(keywords)) {
queryWrapperfiles.like(Files::getKeywords, keywords);
}
//开始时间startDate
DateTime parseStartDate = DateUtil.parse(startDate);
//时间endDate不为空
DateTime parseEndDate = DateUtil.parse(endDate);
//开始时间和结束时间不为空 查询条件>=开始时间 <结束时间
if (parseStartDate != null && parseEndDate != null) {
queryWrapperfiles.ge(Files::getUploadTime, parseStartDate).lt(Files::getUploadTime, parseEndDate);
}
queryWrapperfiles.eq(Files::getProjectId, projectId);//所属项目ID
queryWrapperfiles.eq(Files::getNodeId, nodeId);//节点ID
queryWrapperfiles.orderByDesc(Files::getUploadTime);//时间
//分页查询
Page<Files> filesPage = filesMapper.selectPage(page, queryWrapperfiles);
//处理文件内容
List<Files> records = filesPage.getRecords();
for (Files files : records) {
//循环从minio拿出来的数据 然后把url放到files里面
files.setUrl("");
files.setType("");
List<FileItemResult> filelist = fileInfoResult.getFiles();
if (filelist != null && !filelist.isEmpty()) {
for (FileItemResult fileItemResult : filelist) {
if (fileItemResult.getUrl() == null || fileItemResult.getUrl().isEmpty()) {
continue;
}
if (files.getFileName().equals(fileItemResult.getName())) {
files.setUrl(fileItemResult.getUrl());
files.setType(fileItemResult.getType().getValue());
break;
}
}
}
}
filesPage.setRecords(records);
return filesPage;
}
/***********************************
* 用途说明新增专项文档管理-文档内容
* 参数说明
* Files 文档内容
* 返回值说明: com.yfd.platform.config.ResponseResult 返回新增成功或者失败
***********************************/
@Override
public Boolean addFiles(Files files) {
Boolean value = false;
// String[] splitIds = ids.split(","); BigDecimal
List<String> names = Arrays.asList(files.getFileName().split(","));
List<String> sizes = Arrays.asList(files.getFileSize().split(","));
// 差不多的流程 就是提出来 然后判断 如果两个 中有一个是true
//获取当前登录用户 上传人是当前登录人
UsernamePasswordAuthenticationToken authentication =
(UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
LoginUser loginuser = (LoginUser) authentication.getPrincipal();
// 数据校验
if (names.size() != sizes.size()) {
LOGGER.error("文件名称和文件大小的列表长度不一致");
return false;
}
List<Files> filesToSave = new ArrayList<>();
// 设置当前时间
LocalDateTime now = LocalDateTime.now();
// 转换为 Timestamp
Timestamp currentTime = Timestamp.valueOf(now);
files.setUploadTime(currentTime);
for (int i = 0; i < names.size(); i++) {
String name = names.get(i).trim();
String sizeStr = sizes.get(i).trim();
// 校验文件大小是否可以转换成数值
try {
Files files1 = new Files();
files1.setProjectId(files.getProjectId());
files1.setNodeId(files.getNodeId());
files1.setFilePath(files.getFilePath());
files1.setKeywords(files.getKeywords());
files1.setDescription(files.getDescription());
files1.setUploadTime(files.getUploadTime());
files1.setUploader(loginuser.getUsername());
files1.setFileName(name);
files1.setFileSize(sizeStr);
filesToSave.add(files1);
} catch (NumberFormatException e) {
LOGGER.error("文件大小必须是有效的数字");
}
}
if(filesToSave.size()>0){
//循环新增
for(Files filess : filesToSave){
int valueAdded = filesMapper.insert(filess);
if (valueAdded == 1) {
value = true;
} else {
value = false;
}
}
}
return value;
}
/**********************************
* 用途说明: 修改专项文档管理-文档内容
* 参数说明
* Files 文档内容
* 返回值说明: com.yfd.platform.config.ResponseResult 返回修改成功或者失败
***********************************/
@Override
@Transactional(rollbackFor = Exception.class)// 添加事务注解遇到异常时回滚
public boolean updateFiles(Files files) {
// 修改之前查询表中的文件名是否修改如果发生变动先修改 minio 然后再修改表结构
Files filesData = filesMapper.selectById(files.getId());
// 判断文件名是否修改
if (!files.getFileName().equals(filesData.getFileName())) {
// 修改数据库
int valueUpdate = filesMapper.updateById(files);
if (valueUpdate != 1) {
LOGGER.error("表结构修改失败");
throw new RuntimeException("更新数据库失败");
}
// 修改 MinIO 文件名
boolean minioUpdateSuccess = updateMinioFileName(filesData, files);
if (!minioUpdateSuccess) {
// 如果 MinIO 修改失败抛出异常触发事务回滚
LOGGER.error("表结构修改成功MinIO 修改失败");
throw new RuntimeException("在MinIO中重命名文件失败.");
}
LOGGER.info("MinIO 和表结构都修改成功");
return true;
} else {
// 如果文件名没有修改仅更新数据库
int valueUpdate = filesMapper.updateById(files);
return valueUpdate == 1;
}
}
/**********************************
* 用途说明: 根据ID删除专项文档管理-文档内容
* 参数说明 id 文档内容ID
* 返回值说明: com.yfd.platform.config.ResponseResult 返回删除成功或者失败
**********************************
* @return*/
@Override
@Transactional(rollbackFor = Exception.class)// 添加事务注解遇到异常时回滚
public String deleteFilesByIds(List<String> dataset) {
List<Files> filesList = filesMapper.selectBatchIds(dataset);
int SuccessCount = 0, FailCount = 0, total = CollUtil.size(dataset);
//Todo 最直接的办法 循环出来 一条一条删除
for (Files files : filesList) {
List<BatchDeleteRequest.DeleteItem> deleteItemList = new ArrayList<>();
BatchDeleteRequest.DeleteItem deleteItemData = new BatchDeleteRequest.DeleteItem();
deleteItemData.setName(files.getFileName());
deleteItemData.setPassword("");
deleteItemData.setPath(files.getFilePath());
deleteItemData.setType(FileTypeEnum.FILE);
deleteItemList.add(deleteItemData);
//首先通过ID集合查询所有的内容 然后放到List<DeleteItem> deleteItems里面 放好以后删除数据库 然后删除minio
BatchDeleteRequest batchDeleteRequest = new BatchDeleteRequest();
batchDeleteRequest.setDeleteItems(deleteItemList);
batchDeleteRequest.setStorageKey("minio");
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(batchDeleteRequest.getStorageKey());
List<BatchDeleteRequest.DeleteItem> deleteItems = batchDeleteRequest.getDeleteItems();
int deleteSuccessCount = 0, deleteFailCount = 0, totalCount = CollUtil.size(deleteItems);
for (BatchDeleteRequest.DeleteItem deleteItem : deleteItems) {
boolean flag = false;
try {
if (deleteItem.getType() == FileTypeEnum.FILE) {
flag = fileService.deleteFile(deleteItem.getPath(), deleteItem.getName());
} else if (deleteItem.getType() == FileTypeEnum.FOLDER) {
flag = fileService.deleteFolder(deleteItem.getPath(), deleteItem.getName());
}
if (flag) {
deleteSuccessCount++;
} else {
deleteFailCount++;
}
} catch (Exception e) {
LOGGER.error("删除文件/文件夹失败, 文件路径: {}, 文件名称: {}", deleteItem.getPath(), deleteItem.getName(), e);
deleteFailCount++;
}
}
if (totalCount > 1) {
//return ResponseResult.success("批量删除 " + totalCount + " 个, 删除成功 " + deleteSuccessCount + " 个, 失败 " + deleteFailCount + " 个.");
LOGGER.error("批量删除 " + totalCount + " 个, 删除成功 " + deleteSuccessCount + " 个, 失败 " + deleteFailCount + " 个.");
} else {
//return totalCount == deleteSuccessCount ? ResponseResult.success("删除成功") : ResponseResult.error("删除失败");
LOGGER.error("批量删除 " + totalCount + " 个, 删除成功 " + deleteSuccessCount + " 个, 失败 " + deleteFailCount + " 个.");
}
//如果是1 说明成功删除
if (deleteSuccessCount == 1) {
int valueDelete = filesMapper.deleteById(files.getId());
if (valueDelete > 0) {
SuccessCount++;
LOGGER.info("表结构成功删除");
} else {
System.out.println("没有记录被删除");
}
} else {
FailCount++;
}
}
return "批量删除 " + total + " 个, 删除成功 " + SuccessCount + " 个, 失败 " + FailCount + " 个.";
}
// 修改 MinIO 文件名的方法
private boolean updateMinioFileName(Files filesData, Files files) {
try {
RenameFileRequest renameFileRequest = new RenameFileRequest();
renameFileRequest.setName(filesData.getFileName());
renameFileRequest.setNewName(files.getFileName());
renameFileRequest.setPassword("");
renameFileRequest.setPath(filesData.getFilePath());
renameFileRequest.setStorageKey("minio");
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(renameFileRequest.getStorageKey());
return fileService.renameFile(renameFileRequest.getPath(), renameFileRequest.getName(), renameFileRequest.getNewName());
} catch (Exception e) {
LOGGER.error("MinIO 修改文件名时发生异常", e);
return false;
}
}
}

View File

@ -0,0 +1,532 @@
package com.yfd.platform.modules.specialDocument.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yfd.platform.config.ResponseResult;
import com.yfd.platform.modules.experimentalData.domain.TsFiles;
import com.yfd.platform.modules.experimentalData.domain.TsNodes;
import com.yfd.platform.modules.specialDocument.domain.Files;
import com.yfd.platform.modules.specialDocument.domain.Nodes;
import com.yfd.platform.modules.specialDocument.mapper.FilesMapper;
import com.yfd.platform.modules.specialDocument.mapper.NodesMapper;
import com.yfd.platform.modules.specialDocument.mapper.ProjectMapper;
import com.yfd.platform.modules.specialDocument.service.INodesService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yfd.platform.modules.storage.context.StorageSourceContext;
import com.yfd.platform.modules.storage.controller.file.FileOperatorController;
import com.yfd.platform.modules.storage.model.enums.FileTypeEnum;
import com.yfd.platform.modules.storage.model.request.BatchDeleteRequest;
import com.yfd.platform.modules.storage.model.request.NewFolderRequest;
import com.yfd.platform.modules.storage.model.request.RenameFolderRequest;
import com.yfd.platform.modules.storage.service.base.AbstractBaseFileService;
import com.yfd.platform.system.domain.LoginUser;
import com.yfd.platform.system.domain.SysDictionaryItems;
import com.yfd.platform.utils.StringUtils;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.*;
/**
* <p>
* 专项文档节点表 服务实现类
* </p>
*
* @author LiMengNan
* @since 2025-01-20
*/
@Service
public class NodesServiceImpl extends ServiceImpl<NodesMapper, Nodes> implements INodesService {
private static final Logger LOGGER = LoggerFactory.getLogger(ChannelInboundHandlerAdapter.class);
//专项文档节点表 Mapper
@Resource
private NodesMapper nodesMapper;
//专项文档表 Mapper
@Resource
private FilesMapper filesMapper;
@Resource
private FileOperatorController fileOperatorController;
@Resource
private StorageSourceContext storageSourceContext;
/***********************************
* 用途说明获取专项文档节点 树形结构
* 参数说明
* nodeName 节点名称
* projectId 所属项目ID
* 返回值说明: 专项文档节点树形结构
***********************************/
@Override
public List<Map<String, Object>> getNodesTree(String nodeName, String projectId) {
// 查询所有节点数据
List<Map<String, Object>> allNodes = getAllNodes(projectId);
// 查找所有根节点parentId为"00"的节点
List<Map<String, Object>> rootNodes = findRootNodes(allNodes, projectId);
// 如果未找到根节点返回空列表
if (rootNodes.isEmpty()) {
return new ArrayList<>();
}
// 存储最终结果
List<Map<String, Object>> result = new ArrayList<>();
// 如果 nodeName 为空返回所有根节点的完整树形结构
if (StringUtils.isEmpty(nodeName)) {
for (Map<String, Object> rootNode : rootNodes) {
result.addAll(buildFullTree(rootNode, allNodes));
}
return result;
}
// 否则返回从根节点到目标节点的树形结构
for (Map<String, Object> rootNode : rootNodes) {
List<Map<String, Object>> tree = buildTreeToTargetNode(rootNode, allNodes, nodeName);
if (!tree.isEmpty()) {
result.addAll(tree);
}
}
// 返回结果
return result;
}
/**
* 构建完整的树形结构
*
* @param currentNode 当前节点
* @param allNodes 所有节点数据
* @return 返回当前节点的子树
*/
private List<Map<String, Object>> buildFullTree(Map<String, Object> currentNode, List<Map<String, Object>> allNodes) {
// 查找当前节点的所有子节点
List<Map<String, Object>> children = findChildren(allNodes, currentNode.get("id").toString());
// 递归构建子树
List<Map<String, Object>> tree = new ArrayList<>();
for (Map<String, Object> child : children) {
List<Map<String, Object>> childTree = buildFullTree(child, allNodes);
if (!childTree.isEmpty()) {
tree.addAll(childTree);
}
}
// 将当前节点加入树中
Map<String, Object> nodeWithChildren = new HashMap<>(currentNode);
if (!tree.isEmpty()) {
nodeWithChildren.put("children", tree);
}
return Collections.singletonList(nodeWithChildren);
}
/**
* 构建从根节点到目标节点的树形结构
*
* @param currentNode 当前节点
* @param allNodes 所有节点数据
* @param nodeName 目标节点名称
* @return 返回从根节点到目标节点的树形结构
*/
private List<Map<String, Object>> buildTreeToTargetNode(Map<String, Object> currentNode, List<Map<String, Object>> allNodes, String nodeName) {
List<Map<String, Object>> result = new ArrayList<>();
// 查找当前节点的所有子节点
List<Map<String, Object>> children = findChildren(allNodes, currentNode.get("id").toString());
// 递归查找目标节点
for (Map<String, Object> child : children) {
List<Map<String, Object>> childTree = buildTreeToTargetNode(child, allNodes, nodeName);
if (!childTree.isEmpty()) {
// 如果找到目标节点将当前节点加入树中并将其作为子节点
Map<String, Object> nodeWithChildren = new HashMap<>(currentNode);
nodeWithChildren.put("children", childTree);
result.add(nodeWithChildren); // 将当前节点加入结果列表
}
}
// 如果当前节点符合条件且没有被添加到result则将其添加
if (currentNode.get("nodeName") instanceof String && ((String) currentNode.get("nodeName")).contains(nodeName) && result.isEmpty()) {
result.add(currentNode); // 将当前节点添加到结果列表
}
// 返回包含所有符合条件的树结构的列表
return result;
// // 如果当前节点是目标节点返回当前节点
// if (currentNode.get("nodeName") instanceof String && ((String) currentNode.get("nodeName")).contains(nodeName)) {
// return Collections.singletonList(currentNode);
// }
//// if (nodeName.equals(currentNode.get("nodeName"))) {
//// return Collections.singletonList(currentNode);
//// }
// // 查找当前节点的所有子节点
// List<Map<String, Object>> children = findChildren(allNodes, currentNode.get("id").toString());
// // 递归查找目标节点
// for (Map<String, Object> child : children) {
// List<Map<String, Object>> childTree = buildTreeToTargetNode(child, allNodes, nodeName);
// if (!childTree.isEmpty()) {
// // 如果找到目标节点将当前节点加入树中
// Map<String, Object> nodeWithChildren = new HashMap<>(currentNode);
// nodeWithChildren.put("children", childTree);
// return Collections.singletonList(nodeWithChildren);
// }
// }
// // 如果未找到目标节点返回空列表
// return new ArrayList<>();
}
/**
* 查找当前节点的所有子节点
*
* @param allNodes 所有节点数据
* @param parentId 父节点ID
* @return 返回所有子节点列表
*/
private List<Map<String, Object>> findChildren(List<Map<String, Object>> allNodes, String parentId) {
List<Map<String, Object>> children = new ArrayList<>();
for (Map<String, Object> node : allNodes) {
if (parentId.equals(node.get("parentId").toString())) {
children.add(node);
}
}
return children;
}
/**
* 查找所有根节点parentId为"00"的节点
*
* @param allNodes 所有节点数据
* @param projectId 项目ID
* @return 返回所有根节点列表
*/
private List<Map<String, Object>> findRootNodes(List<Map<String, Object>> allNodes, String projectId) {
List<Map<String, Object>> rootNodes = new ArrayList<>();
for (Map<String, Object> node : allNodes) {
if ("00".equals(node.get("parentId").toString()) && projectId.equals(node.get("projectId").toString())) {
rootNodes.add(node);
}
}
return rootNodes;
}
/**
* 查询所有节点数据
*
* @param projectId 项目ID用于精确查询
* @return 返回所有节点列表
*/
private List<Map<String, Object>> getAllNodes(String projectId) {
// 创建查询条件
QueryWrapper<Nodes> queryWrapper = new QueryWrapper<>();
queryWrapper.select(
"id as id", // 节点ID
"node_name as nodeName", // 节点名称
"project_id as projectId", // 项目ID
"parent_id as parentId", // 父节点ID
"node_order as nodeOrder", // 节点顺序
"node_type as nodeType", // 节点类型
"create_time as createTime", // 创建时间
"creator" // 创建人
);
// 如果项目ID不为空添加精确查询条件
if (StringUtils.isNotEmpty(projectId)) {
queryWrapper.eq("project_id", projectId);
}
// 按节点顺序升序排序
queryWrapper.orderByAsc("node_order");
// 查询所有符合条件的节点
return nodesMapper.selectMaps(queryWrapper);
}
/**********************************
* 用途说明: 增加专项文档节点
* 参数说明 nodes 专项文档节点信息
* 返回值说明: com.yfd.platform.config.ResponseResult 返回增加成功或者失败
***********************************/
@Override
@Transactional(rollbackFor = Exception.class) // 添加事务注解遇到异常时回滚
public ResponseResult addNodes(Nodes nodes) {
//获取当前登录用户
UsernamePasswordAuthenticationToken authentication =
(UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
LoginUser loginuser = (LoginUser) authentication.getPrincipal();
//创建人是当前登录人
nodes.setCreator(loginuser.getUsername());
//当前操作时间
LocalDateTime now = LocalDateTime.now();
// 转换为 Timestamp
Timestamp currentTime = Timestamp.valueOf(now);
nodes.setCreateTime(currentTime);
//通过获取上级节点的条数 设置节点顺序
QueryWrapper<Nodes> queryWrapperNodeOrder = new QueryWrapper<>();
int orderno = this.count(queryWrapperNodeOrder.eq("parent_id", nodes.getParentId())) + 1;
//判断节点名称是否存在
QueryWrapper<Nodes> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("node_name", nodes.getNodeName());//名称
queryWrapper.eq("parent_id", nodes.getParentId());//父节点
int count = nodesMapper.selectCount(queryWrapper);
// 大于0说明 区域名称重复
if (count > 0) {
return ResponseResult.error("节点名称已存在!");
}
//序号
nodes.setNodeOrder(orderno);
int valueAdded = nodesMapper.insert(nodes);
if (valueAdded == 1) {
List<String> pathNodes = new ArrayList<>();
Nodes nodesData = nodesMapper.selectById(nodes.getParentId());
// 从当前节点向上遍历直到根节点
while (nodesData != null) {
pathNodes.add(nodesData.getNodeName());
// 如果父节点是 "00"说明已经到了根节点停止遍历
if ("00".equals(nodesData.getParentId())) {
break;
}
// 获取父节点
nodesData = nodesMapper.selectById(nodesData.getParentId()); // 修正 nodesData 中获取 parentId
}
// 反转路径使其从根节点到当前节点
Collections.reverse(pathNodes);
String path = "/" + String.join("/", pathNodes);
//新增节点的时候 创建文件夹
NewFolderRequest newFolderRequest = new NewFolderRequest();
newFolderRequest.setName(nodes.getNodeName());//新建的文件夹名称,示例值(/a/b/c)
newFolderRequest.setPassword("");//文件夹密码, 如果文件夹需要密码才能访问则支持请求密码,示例值(123456)
newFolderRequest.setPath(path);//请求路径,示例值(/)
newFolderRequest.setStorageKey("minio");//存储源 key,示例值(local minio)
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(newFolderRequest.getStorageKey());
boolean flag = fileService.newFolder(newFolderRequest.getPath(), newFolderRequest.getName());
if (flag) {
return ResponseResult.success();
} else {
LOGGER.error("节点新增成功但是minio创建文件失败");
return ResponseResult.error();
}
} else {
LOGGER.error("节点新增失败");
return ResponseResult.error();
}
}
/**********************************
* 用途说明: 修改专项文档节点
* 参数说明 nodes 专项文档节点信息
* 返回值说明: com.yfd.platform.config.ResponseResult 返回修改成功或者失败
***********************************/
@Override
@Transactional(rollbackFor = Exception.class) // 添加事务注解遇到异常时回滚
public ResponseResult updateNodes(Nodes nodes) {
//查询没改之前的节点名称
Nodes nodesold = nodesMapper.selectById(nodes.getId());
//新的节点名称
String nodeName = nodes.getNodeName();
//老的节点名称
String nodeNameOld = null;
if (ObjUtil.isNotEmpty(nodesold)) {
nodeNameOld = nodesold.getNodeName();
}
//获取当前登录用户
UsernamePasswordAuthenticationToken authentication =
(UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
LoginUser loginuser = (LoginUser) authentication.getPrincipal();
//创建人是当前登录人
nodes.setCreator(loginuser.getUsername());
//判断节点名称是否存在
QueryWrapper<Nodes> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("node_name", nodes.getNodeName());
queryWrapper.eq("parent_id", nodes.getParentId());//父节点
int count = nodesMapper.selectCount(queryWrapper);
// 大于0说明 区域名称重复
if (count > 0) {
return ResponseResult.error("节点名称已存在!");
}
int valueUpdate = nodesMapper.updateById(nodes);
if (valueUpdate == 1) {
List<String> pathNodes = new ArrayList<>();
Nodes nodesData = nodesMapper.selectById(nodes.getParentId());
// 从当前节点向上遍历直到根节点
while (nodesData != null) {
pathNodes.add(nodesData.getNodeName());
// 如果父节点是 "00"说明已经到了根节点停止遍历
if ("00".equals(nodesData.getParentId())) {
break;
}
// 获取父节点
nodesData = nodesMapper.selectById(nodesData.getParentId()); // 修正 nodesData 中获取 parentId
}
// 反转路径使其从根节点到当前节点
Collections.reverse(pathNodes);
String path = String.join("/", pathNodes);
//修改文件名称
RenameFolderRequest renameFolderRequest = new RenameFolderRequest();
renameFolderRequest.setName(nodeNameOld);//重命名的原文件夹名称,示例值(movie)
renameFolderRequest.setNewName(nodeName);// 重命名后的文件名称,示例值(music)
renameFolderRequest.setPassword("");//文件夹密码, 如果文件夹需要密码才能访问则支持请求密码,示例值(123456)
renameFolderRequest.setPath(path);//请求路径,示例值(/)
renameFolderRequest.setStorageKey("minio");//存储源 key,示例值(local minio)
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(renameFolderRequest.getStorageKey());
boolean flag = fileService.renameFolder(renameFolderRequest.getPath(), renameFolderRequest.getName(), renameFolderRequest.getNewName());
if (flag) {
return ResponseResult.success("重命名成功");
} else {
LOGGER.error("节点修改成功但是minio修改文件名失败");
return ResponseResult.error("重命名失败");
}
} else {
LOGGER.error("节点修改失败");
return ResponseResult.error();
}
}
/**********************************
* 用途说明: 根据ID删除专项文档节点
* 参数说明 id 专项文档节点ID
* 返回值说明: com.yfd.platform.config.ResponseResult 返回删除成功或者失败
***********************************/
@Override
public boolean deleteNodesById(String id) {
Boolean value = false;
//根据ID 查询当前数据
Nodes nodes = nodesMapper.selectById(id);
// 删除当前节点
int deleteCount = nodesMapper.deleteById(id);
//删除当前节点的 文件
QueryWrapper<Files> queryWrapper1 = new QueryWrapper<>();
queryWrapper1.eq("node_id", nodes.getId());
queryWrapper1.eq("task_id", nodes.getProjectId());
filesMapper.delete(queryWrapper1);
List<String> pathNodes = new ArrayList<>();
Nodes nodesData = nodesMapper.selectById(nodes.getParentId());
// 从当前节点向上遍历直到根节点
while (nodesData != null) {
pathNodes.add(nodesData.getNodeName());
// 如果父节点是 "00"说明已经到了根节点停止遍历
if ("00".equals(nodesData.getParentId())) {
break;
}
// 获取父节点
nodesData = nodesMapper.selectById(nodesData.getParentId()); // 修正 nodesData 中获取 parentId
}
// 反转路径使其从根节点到当前节点
Collections.reverse(pathNodes);
String path = String.join("/", pathNodes);
//删除minio准备数据
List<BatchDeleteRequest.DeleteItem> deleteItemList = new ArrayList<>();
BatchDeleteRequest.DeleteItem deleteItemData = new BatchDeleteRequest.DeleteItem();
deleteItemData.setName(nodes.getNodeName());
deleteItemData.setPassword("");
deleteItemData.setPath(path);
deleteItemData.setType(FileTypeEnum.FOLDER);
deleteItemList.add(deleteItemData);
BatchDeleteRequest batchDeleteRequest = new BatchDeleteRequest();
batchDeleteRequest.setDeleteItems(deleteItemList);
batchDeleteRequest.setStorageKey("minio");
AbstractBaseFileService<?> fileService = storageSourceContext.getByStorageKey(batchDeleteRequest.getStorageKey());
List<BatchDeleteRequest.DeleteItem> deleteItems = batchDeleteRequest.getDeleteItems();
int deleteSuccessCount = 0, deleteFailCount = 0, totalCount = CollUtil.size(deleteItems);
for (BatchDeleteRequest.DeleteItem deleteItem : deleteItems) {
boolean flag = false;
try {
if (deleteItem.getType() == FileTypeEnum.FILE) {
flag = fileService.deleteFile(deleteItem.getPath(), deleteItem.getName());
} else if (deleteItem.getType() == FileTypeEnum.FOLDER) {
flag = fileService.deleteFolder(deleteItem.getPath(), deleteItem.getName());
}
if (flag) {
deleteSuccessCount++;
} else {
deleteFailCount++;
}
} catch (Exception e) {
LOGGER.error("删除文件/文件夹失败, 文件路径: {}, 文件名称: {}", deleteItem.getPath(), deleteItem.getName(), e);
deleteFailCount++;
}
}
if (totalCount > 1) {
//return ResponseResult.success("批量删除 " + totalCount + " 个, 删除成功 " + deleteSuccessCount + " 个, 失败 " + deleteFailCount + " 个.");
LOGGER.error("批量删除 " + totalCount + " 个, 删除成功 " + deleteSuccessCount + " 个, 失败 " + deleteFailCount + " 个.");
} else {
//return totalCount == deleteSuccessCount ? ResponseResult.success("删除成功") : ResponseResult.error("删除失败");
LOGGER.error("批量删除 " + totalCount + " 个, 删除成功 " + deleteSuccessCount + " 个, 失败 " + deleteFailCount + " 个.");
}
//如果是1 说明成功删除
if (deleteSuccessCount >= 1) {
// 递归删除子节点
deleteChildren(nodes.getId(), nodes.getProjectId());
value = true;
} else {
value = false;
}
return value;
}
/**
* 递归删除子节点
*
* @param parentId 父节点ID
*/
private void deleteChildren(String parentId, String projectId) {
// 使用 QueryWrapper 查询当前节点的所有子节点
QueryWrapper<Nodes> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("parent_id", parentId);
queryWrapper.eq("project_id", projectId);
List<Nodes> children = nodesMapper.selectList(queryWrapper);
// 递归删除每个子节点
for (Nodes child : children) {
deleteChildren(child.getId(), child.getProjectId()); // 递归删除子节点的子节点
nodesMapper.deleteById(child.getId()); // 删除当前子节点
//批量文件的数据
QueryWrapper<Files> queryWrapper1 = new QueryWrapper<>();
queryWrapper1.eq("id", parentId);
queryWrapper1.eq("project_id", projectId);
filesMapper.delete(queryWrapper1);
}
//
//
//
// // 使用 QueryWrapper 查询当前节点的所有子节点
// QueryWrapper<Nodes> queryWrapper = new QueryWrapper<>();
// queryWrapper.eq("parent_id", parentId); // parent_id = #{parentId}
// List<Nodes> children = nodesMapper.selectList(queryWrapper);
//
// // 递归删除每个子节点
// for (Nodes child : children) {
// deleteChildren(child.getId()); // 递归删除子节点的子节点
// nodesMapper.deleteById(child.getId()); // 删除当前子节点
// }
}
}

View File

@ -0,0 +1,114 @@
package com.yfd.platform.modules.specialDocument.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yfd.platform.modules.specialDocument.domain.Project;
import com.yfd.platform.modules.specialDocument.mapper.ProjectMapper;
import com.yfd.platform.modules.specialDocument.service.IProjectService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yfd.platform.system.mapper.SysDictionaryItemsMapper;
import com.yfd.platform.utils.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.List;
/**
* <p>
* 专项项目表 服务实现类
* </p>
*
* @author LiMengNan
* @since 2025-01-20
*/
@Service
public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> implements IProjectService {
//专项项目表Mapper
@Resource
private ProjectMapper projectMapper;
/**********************************
* 用途说明: 分页查询专项文档管理-项目管理
* 参数说明
* projectCode 项目编号
* projectType 项目类型
*projectName 项目名称
* pageNum 当前页
* 返回值说明: com.yfd.platform.config.ResponseResult 返回分页查询结果
***********************************/
@Override
public Page<Project> getSdProjectPage(String projectCode, String projectType, String projectName, Page<Project> page) {
LambdaQueryWrapper<Project> queryWrapper = new LambdaQueryWrapper<>();
//如果项目编号 projectCode 不为空
if (StringUtils.isNotEmpty(projectCode)) {
queryWrapper.like(Project::getProjectCode, projectCode);
}
//如果项目类型 projectType 不为空
if (StringUtils.isNotEmpty(projectType)) {
queryWrapper.like(Project::getProjectType, projectType);
}
//如果项目名称 projectName 不为空
if (StringUtils.isNotEmpty(projectName)) {
queryWrapper.like(Project::getProjectName, projectName);
}
//根据创建时间排序
queryWrapper.orderByAsc(Project::getCreateTime);
//分页查询
Page<Project> sdProjectPage = projectMapper.selectPage(page, queryWrapper);
return sdProjectPage;
}
/***********************************
* 用途说明新增专项文档管理-项目管理
* 参数说明
* Project 项目管理
* 返回值说明: com.yfd.platform.config.ResponseResult 返回新增成功或者失败
***********************************/
@Override
public Boolean addSdproject(Project project) {
//TODO 01.21沟通以后说是先不用管重复校验问题
// //通过项目名称 项目编号查询 查看是否存在
// QueryWrapper<Project> queryWrapper = new QueryWrapper<>();
// if(project.getProjectCode() != null){
// queryWrapper.eq("project_code",project.getProjectCode());
// }
// if(project.getProjectName() != null){
// queryWrapper.eq("project_name",project.getProjectName());
// }
// List<Project> projects = projectMapper.selectList(queryWrapper);
// if(){
//
// }
// 设置当前时间
LocalDateTime now = LocalDateTime.now();
// 转换为 Timestamp
Timestamp currentTime = Timestamp.valueOf(now);
project.setCreateTime(currentTime);
int valueAdded = projectMapper.insert(project);
if (valueAdded == 1) {
return true;
} else {
return false;
}
}
/**********************************
* 用途说明: 修改专项文档管理-项目管理
* 参数说明
* Project 项目管理
* 返回值说明: com.yfd.platform.config.ResponseResult 返回修改成功或者失败
***********************************/
@Override
public boolean updateSdproject(Project project) {
int valueUpdate = projectMapper.updateById(project);
if (valueUpdate == 1) {
return true;
} else {
return false;
}
}
}

View File

@ -19,6 +19,7 @@ import java.util.Date;
@ApiModel(value="文件列表信息结果类") @ApiModel(value="文件列表信息结果类")
public class FileItemResult implements Serializable { public class FileItemResult implements Serializable {
@ApiModelProperty(value = "文件名", example = "a.mp4") @ApiModelProperty(value = "文件名", example = "a.mp4")
private String name; private String name;
@ -37,6 +38,10 @@ public class FileItemResult implements Serializable {
@ApiModelProperty(value = "下载地址", example = "http://www.example.com/a.mp4") @ApiModelProperty(value = "下载地址", example = "http://www.example.com/a.mp4")
private String url; private String url;
//用于对比Md5文件
private String locatMd5;
private String minioMd5;
/** /**
* 获取路径和名称的组合, 并移除重复的路径分隔符 /. * 获取路径和名称的组合, 并移除重复的路径分隔符 /.
* *

View File

@ -2,6 +2,7 @@ package com.yfd.platform.modules.storage.service.base;
import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.amazonaws.services.s3.model.S3Object;
import com.yfd.platform.exception.init.InitializeStorageSourceException; import com.yfd.platform.exception.init.InitializeStorageSourceException;
import com.yfd.platform.modules.storage.model.param.IStorageParam; import com.yfd.platform.modules.storage.model.param.IStorageParam;
import com.yfd.platform.utils.CodeMsg; import com.yfd.platform.utils.CodeMsg;
@ -92,4 +93,5 @@ public abstract class AbstractBaseFileService<P extends IStorageParam> implement
return false; return false;
} }
public abstract S3Object getObject(String bucketName, String key);
} }

View File

@ -13,12 +13,22 @@ import com.yfd.platform.modules.storage.model.enums.FileTypeEnum;
import com.yfd.platform.modules.storage.model.param.S3BaseParam; import com.yfd.platform.modules.storage.model.param.S3BaseParam;
import com.yfd.platform.modules.storage.model.result.FileItemResult; import com.yfd.platform.modules.storage.model.result.FileItemResult;
import com.yfd.platform.utils.StringUtils; import com.yfd.platform.utils.StringUtils;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.rmi.CORBA.Util;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URL; import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashSet; import java.util.HashSet;
@ -30,6 +40,9 @@ import java.util.List;
@Slf4j @Slf4j
public abstract class AbstractS3BaseFileService<P extends S3BaseParam> extends AbstractBaseFileService<P> { public abstract class AbstractS3BaseFileService<P extends S3BaseParam> extends AbstractBaseFileService<P> {
private static final Logger LOGGER = LoggerFactory.getLogger(ChannelInboundHandlerAdapter.class);
protected AmazonS3 s3Client; protected AmazonS3 s3Client;
public static final InputStream EMPTY_INPUT_STREAM = new ByteArrayInputStream(new byte[0]); public static final InputStream EMPTY_INPUT_STREAM = new ByteArrayInputStream(new byte[0]);
@ -42,10 +55,14 @@ public abstract class AbstractS3BaseFileService<P extends S3BaseParam> extends A
return s3FileList(folderPath); return s3FileList(folderPath);
} }
@Override
public List<FileItemResult> fileLists(String folderPath) {
return s3FileLists(folderPath);
}
/** /**
* 默认 S3 获取对象下载链接的方法, 如果指定了域名, 则替换为自定义域名. * 默认 S3 获取对象下载链接的方法, 如果指定了域名, 则替换为自定义域名.
* @return S3 对象访问地址 *
* @return S3 对象访问地址
*/ */
@Override @Override
public String getDownloadUrl(String pathAndName) { public String getDownloadUrl(String pathAndName) {
@ -80,8 +97,9 @@ public abstract class AbstractS3BaseFileService<P extends S3BaseParam> extends A
/** /**
* 获取 S3 指定目录下的对象列表 * 获取 S3 指定目录下的对象列表
* @param path 路径 *
* @return 指定目录下的对象列表 * @param path 路径
* @return 指定目录下的对象列表
*/ */
public List<FileItemResult> s3FileList(String path) { public List<FileItemResult> s3FileList(String path) {
String bucketName = param.getBucketName(); String bucketName = param.getBucketName();
@ -139,6 +157,88 @@ public abstract class AbstractS3BaseFileService<P extends S3BaseParam> extends A
return fileItemList; return fileItemList;
} }
public List<FileItemResult> s3FileLists(String path) {
String bucketName = param.getBucketName();
path = StringUtils.trimStartSlashes(path); // 去掉路径开头的斜杠
String fullPath = StringUtils.trimStartSlashes(StringUtils.concat(param.getBasePath(), path, ZFileConstant.PATH_SEPARATOR));
List<FileItemResult> fileItemList = new ArrayList<>();
// 调用递归方法获取文件列表
listFilesInDirectory(bucketName, fullPath, path, fileItemList);
return fileItemList;
}
private void listFilesInDirectory(String bucketName, String fullPath, String path, List<FileItemResult> fileItemList) {
ListObjectsRequest listObjectsRequest = new ListObjectsRequest()
.withBucketName(bucketName)
.withPrefix(fullPath) // 设置前缀为当前路径
.withMaxKeys(1000) // 每次最多返回 1000 个对象
.withDelimiter("/"); // 使用 "/" 作为分隔符
ObjectListing objectListing = s3Client.listObjects(listObjectsRequest);
boolean isFirstWhile = true;
do {
if (!isFirstWhile) {
objectListing = s3Client.listNextBatchOfObjects(objectListing); // 处理分页
}
// 处理文件
for (S3ObjectSummary s : objectListing.getObjectSummaries()) {
FileItemResult fileItemResult = new FileItemResult();
// 跳过当前目录本身
if (s.getKey().equals(fullPath)) {
continue;
}
// 获取文件名并去除前导斜杠
String fileName = s.getKey().substring(fullPath.length());
if (fileName.startsWith(ZFileConstant.PATH_SEPARATOR)) {
fileName = fileName.substring(1); // 去掉开头的斜杠
}
fileItemResult.setName(fileName);
fileItemResult.setSize(s.getSize());
fileItemResult.setTime(s.getLastModified());
fileItemResult.setType(FileTypeEnum.FILE);
fileItemResult.setPath(path); // 当前路径
// 构造完整路径并生成下载 URL
String fullPathAndName = StringUtils.concat(path, fileItemResult.getName());
fileItemResult.setUrl(getDownloadUrl(fullPathAndName));
fileItemList.add(fileItemResult);
}
// 处理文件夹
for (String commonPrefix : objectListing.getCommonPrefixes()) {
FileItemResult fileItemResult = new FileItemResult();
// 获取文件夹名称去掉前导路径并修正末尾斜杠
String folderName = commonPrefix.substring(fullPath.length(), commonPrefix.length() - 1);
if (StrUtil.isEmpty(folderName) || StrUtil.equals(folderName, StringUtils.DELIMITER_STR)) {
continue; // 跳过无效的文件夹名称
}
fileItemResult.setName(folderName);
fileItemResult.setType(FileTypeEnum.FOLDER);
fileItemResult.setPath(path); // 当前路径
fileItemList.add(fileItemResult);
// 递归处理子文件夹
String subFolderPath = path + folderName + ZFileConstant.PATH_SEPARATOR; // 修正路径拼接
String subFolderFullPath = commonPrefix; // 子文件夹的完整路径
listFilesInDirectory(bucketName, subFolderFullPath, subFolderPath, fileItemList);
}
isFirstWhile = false;
} while (objectListing.isTruncated()); // 处理分页
}
@Override @Override
public FileItemResult getFileItem(String pathAndName) { public FileItemResult getFileItem(String pathAndName) {
String fileName = FileUtil.getName(pathAndName); String fileName = FileUtil.getName(pathAndName);
@ -175,14 +275,171 @@ public abstract class AbstractS3BaseFileService<P extends S3BaseParam> extends A
return true; return true;
} }
// @Override
// public boolean deleteFolder(String path, String name) {
// String fullPath = StringUtils.concat(param.getBasePath(), path, name);
// fullPath = StringUtils.trimStartSlashes(fullPath);
// s3Client.deleteObject(param.getBucketName(), fullPath + '/');
// return true;
// }
//todo 改造以后的删除文件夹 上面是改造之前原本的
/**
* 删除文件夹
*
* @param path 文件夹路径
* @param name 文件夹名称
* @return 是否删除成功
*/
@Override @Override
public boolean deleteFolder(String path, String name) { public boolean deleteFolder(String path, String name) {
// 构造完整路径
String fullPath = StringUtils.concat(param.getBasePath(), path, name); String fullPath = StringUtils.concat(param.getBasePath(), path, name);
fullPath = StringUtils.trimStartSlashes(fullPath); fullPath = StringUtils.trimStartSlashes(fullPath);
s3Client.deleteObject(param.getBucketName(), fullPath + '/'); if (!fullPath.endsWith("/")) {
return true; fullPath += "/"; // 确保路径以 / 结尾
}
try {
// 删除本地文件夹及其内容
deleteLocalFolder(fullPath);
// 删除 Minio 文件夹及其内容
deleteMinioFolder(param.getBucketName(), fullPath);
return true;
} catch (Exception e) {
LOGGER.error("删除文件夹失败: " + e.getMessage(), e);
return false;
}
} }
// 递归删除本地文件夹及其内容
private void deleteLocalFolder(String fullPath) {
File folder = new File(fullPath);
if (folder.exists() && folder.isDirectory()) {
try {
deleteLocalFolderRecursive(folder);
LOGGER.info("本地文件夹删除成功: " + fullPath);
} catch (IOException e) {
LOGGER.error("本地文件夹删除失败: " + e.getMessage());
}
} else {
LOGGER.error("本地文件夹不存在,跳过删除: " + fullPath);
}
}
// 递归删除本地文件夹及其内容
private void deleteLocalFolderRecursive(File folder) throws IOException {
File[] files = folder.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
deleteLocalFolderRecursive(file); // 递归删除子文件夹
} else {
if (!file.delete()) {
throw new IOException("无法删除文件: " + file.getAbsolutePath());
}
}
}
}
if (!folder.delete()) {
throw new IOException("无法删除文件夹: " + folder.getAbsolutePath());
}
}
// 删除 Minio 文件夹及其内容
private void deleteMinioFolder(String bucketName, String folderPath) {
try {
// 列出文件夹下的所有对象
ListObjectsV2Request listRequest = new ListObjectsV2Request()
.withBucketName(bucketName)
.withPrefix(folderPath); // 前缀匹配文件夹路径
ListObjectsV2Result listResult;
List<DeleteObjectsRequest.KeyVersion> objectsToDelete = new ArrayList<>();
do {
listResult = s3Client.listObjectsV2(listRequest);
// 收集需要删除的对象
for (S3ObjectSummary objectSummary : listResult.getObjectSummaries()) {
objectsToDelete.add(new DeleteObjectsRequest.KeyVersion(objectSummary.getKey()));
}
// 如果对象数量超过单次请求限制继续分页列出
listRequest.setContinuationToken(listResult.getNextContinuationToken());
} while (listResult.isTruncated());
// 批量删除对象
if (!objectsToDelete.isEmpty()) {
DeleteObjectsRequest deleteRequest = new DeleteObjectsRequest(bucketName)
.withKeys(objectsToDelete);
s3Client.deleteObjects(deleteRequest);
LOGGER.info("Minio 文件夹删除成功: " + folderPath);
} else {
LOGGER.error("Minio 文件夹不存在,跳过删除: " + folderPath);
}
} catch (Exception e) {
LOGGER.error("Minio 文件夹删除失败: " + e.getMessage());
}
}
/**
*
* @param path
* 文件路径
*
* @param name
* 桶名称
*
* @param zipFile
* 新文件名称
*
* @return
*/
@Override
public boolean UploadFiles(String name, String path, File zipFile) {
PutObjectResult putObjectResult = s3Client.putObject( name, path, zipFile);
return putObjectResult != null;
}
/**
* 创建新文件夹
*
* @param bucketName
* 桶名称
*
* @param key
* 路径文件夹名称
*
* @return ObjectMetadata对象
*/
@Override
public ObjectMetadata getObjectMetadata(String bucketName, String key) {
ObjectMetadata objectMetadata = s3Client.getObjectMetadata(bucketName,key);
return objectMetadata;
}
/**
*
*
* @param bucketName
* 桶名称
*
* @param key
* 路径文件夹名称
*
* @return S3Object对象
*/
@Override
public S3Object getObject(String bucketName, String key) {
S3Object s3Object = s3Client.getObject(bucketName,key);
return s3Object;
}
@Override @Override
public boolean renameFile(String path, String name, String newName) { public boolean renameFile(String path, String name, String newName) {
String srcPath = StringUtils.concatTrimStartSlashes(param.getBasePath(), path, name); String srcPath = StringUtils.concatTrimStartSlashes(param.getBasePath(), path, name);
@ -194,11 +451,68 @@ public abstract class AbstractS3BaseFileService<P extends S3BaseParam> extends A
return true; return true;
} }
//todo 改造之前的重命名
// @Override
// public boolean renameFolder(String path, String name, String newName) {
// throw new UnsupportedOperationException("该存储类型不支持此操作");
// }
@Override @Override
public boolean renameFolder(String path, String name, String newName) { public boolean renameFolder(String path, String name, String newName) {
throw new UnsupportedOperationException("该存储类型不支持此操作"); try {
// 规范化路径
String oldPrefix = null;
String newPrefix = null;
if (StringUtils.isEmpty(path)) {
oldPrefix = path + name;
newPrefix = path + newName;
} else {
oldPrefix = path + "/" + name;
newPrefix = path + "/" + newName;
}
String bucketName = param.getBucketName();
// 打印路径检查是否正确
System.out.println("Old Prefix: " + oldPrefix);
System.out.println("New Prefix: " + newPrefix);
// 列出旧路径下的所有对象
ListObjectsV2Request request = new ListObjectsV2Request()
.withBucketName(bucketName)
.withPrefix(oldPrefix)
.withMaxKeys(500); // 每次查询最多返回 500 个对象
ListObjectsV2Result result;
do {
result = s3Client.listObjectsV2(request);
System.out.println("Object Summaries: " + result.getObjectSummaries());
// 遍历对象并重命名
for (S3ObjectSummary objectSummary : result.getObjectSummaries()) {
String oldKey = objectSummary.getKey();
String newKey = oldKey.replace(oldPrefix, newPrefix);
// 打印关键变量
System.out.println("Old Key: " + oldKey);
System.out.println("New Key: " + newKey);
// 获取源对象的元数据
ObjectMetadata metadata = s3Client.getObjectMetadata(bucketName, oldKey);
// 使用 CopyObjectRequest 复制对象
CopyObjectRequest copyObjectRequest = new CopyObjectRequest(bucketName, oldKey, bucketName, newKey)
.withNewObjectMetadata(metadata);
s3Client.copyObject(copyObjectRequest);
// 删除旧对象
s3Client.deleteObject(bucketName, oldKey);
}
// 如果对象数量超过单次查询限制继续查询下一页
request.setContinuationToken(result.getNextContinuationToken());
} while (result.isTruncated());
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
} }
@Override @Override
public String getUploadUrl(String path, String name, Long size) { public String getUploadUrl(String path, String name, Long size) {
String bucketName = param.getBucketName(); String bucketName = param.getBucketName();

View File

@ -1,9 +1,12 @@
package com.yfd.platform.modules.storage.service.base; package com.yfd.platform.modules.storage.service.base;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.S3Object;
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.result.FileItemResult; import com.yfd.platform.modules.storage.model.result.FileItemResult;
import java.io.File;
import java.util.List; import java.util.List;
/** /**
@ -215,4 +218,59 @@ public interface BaseFileService {
*/ */
StorageTypeEnum getStorageTypeEnum(); StorageTypeEnum getStorageTypeEnum();
/**
* 创建新文件夹
*
* @param name
* 桶名称
*
* @param path
* 文件夹名称
*
* @param zipFile
* 本地文件
*
* @return 是否创建成功
*/
boolean UploadFiles(String name, String path, File zipFile);
/**
* 创建新文件夹
*
* @param bucketName
* 桶名称
*
* @param key
* 路径文件夹名称
*
* @return ObjectMetadata对象
*/
ObjectMetadata getObjectMetadata(String bucketName, String key);
/**
* 创建新文件夹
*
* @param bucketName
* 桶名称
*
* @param key
* 路径文件夹名称
*
* @return ObjectMetadata对象
*/
S3Object getObject(String bucketName, String key);
/***
* 获取指定路径下的文件及文件夹
*
* @param folderPath
* 文件夹路径
*
* @return 文件及文件夹列表
*
* @throws Exception 获取文件列表中出现的异常
*/
List<FileItemResult> fileLists(String folderPath) throws Exception;
} }

View File

@ -5,6 +5,8 @@ import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil; import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.S3Object;
import com.yfd.platform.constant.ZFileConstant; import com.yfd.platform.constant.ZFileConstant;
import com.yfd.platform.exception.init.InitializeStorageSourceException; import com.yfd.platform.exception.init.InitializeStorageSourceException;
import com.yfd.platform.modules.storage.model.enums.FileTypeEnum; import com.yfd.platform.modules.storage.model.enums.FileTypeEnum;
@ -25,11 +27,9 @@ import org.springframework.http.*;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.io.BufferedOutputStream; import java.io.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -57,6 +57,8 @@ public class LocalServiceImpl extends AbstractProxyTransferService<LocalParam> {
} }
@Override @Override
public List<FileItemResult> fileList(String folderPath) throws FileNotFoundException { public List<FileItemResult> fileList(String folderPath) throws FileNotFoundException {
checkPathSecurity(folderPath); checkPathSecurity(folderPath);
@ -167,6 +169,94 @@ public class LocalServiceImpl extends AbstractProxyTransferService<LocalParam> {
return StorageTypeEnum.LOCAL; return StorageTypeEnum.LOCAL;
} }
@Override
public boolean UploadFiles(String name, String path, File zipFile) {
return false;
}
@Override
public ObjectMetadata getObjectMetadata(String name, String path) {
return null;
}
@Override
public S3Object getObject(String bucketName, String key) {
return null;
}
@Override
public List<FileItemResult> fileLists(String folderPath) throws Exception {
checkPathSecurity(folderPath);
List<FileItemResult> fileItemList = new ArrayList<>();
String fullPath = StringUtils.concat(param.getFilePath() + folderPath);
File file = new File(fullPath);
if (!file.exists()) {
throw new FileNotFoundException("文件不存在");
}
// 调用递归方法处理文件夹及其内容跳过第一个文件夹
listFilesInDirectory(file, folderPath, fileItemList, true);
return fileItemList;
}
private void listFilesInDirectory(File file, String folderPath, List<FileItemResult> fileItemList, boolean skipFirstFolder) throws IOException {
// 跳过第一个文件夹folderPath从它下面的内容开始处理
if (skipFirstFolder) {
// 如果当前文件是 folderPath, 直接跳过开始处理它的子文件夹
if (file.isDirectory()) {
File[] files = file.listFiles();
if (files != null) {
for (File f : files) {
// 递归进入下一级文件夹路径应该是 folderPath + 当前文件夹名
listFilesInDirectory(f, folderPath, fileItemList, false);
}
}
}
} else {
// 处理当前的文件夹或文件
if (file.isDirectory()) {
// 对于文件夹路径是 folderPath
fileItemList.add(fileToFileItems(file, folderPath));
// 递归处理当前文件夹内部的文件和文件夹
File[] files = file.listFiles();
if (files != null) {
for (File f : files) {
// 递归进入下一级文件夹路径是 folderPath + 当前文件夹名
String newPath = folderPath + file.getName();
listFilesInDirectory(f, newPath, fileItemList, false);
}
}
} else {
// 对于文件路径是 folderPath
fileItemList.add(fileToFileItems(file, folderPath));
}
}
}
//lilin增加
private FileItemResult fileToFileItems(File file, String folderPath) {
FileItemResult result = new FileItemResult();
result.setName(file.getName());
result.setPath(folderPath); // 这里返回的是父目录路径不包含文件名
// 使用 FileTypeEnum 设置文件类型
if (file.isDirectory()) {
result.setType(FileTypeEnum.FOLDER);
} else {
result.setType(FileTypeEnum.FILE);
}
result.setSize(file.length());
// 设置文件的修改时间为 Date 类型
result.setTime(new Date(file.lastModified()));
return result;
}
@Override @Override
public void uploadFile(String pathAndName, InputStream inputStream) { public void uploadFile(String pathAndName, InputStream inputStream) {

View File

@ -4,6 +4,7 @@ import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder; import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.s3.AmazonS3ClientBuilder; import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.ObjectMetadata;
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.MinIOParam; import com.yfd.platform.modules.storage.model.param.MinIOParam;
import com.yfd.platform.modules.storage.service.base.AbstractS3BaseFileService; import com.yfd.platform.modules.storage.service.base.AbstractS3BaseFileService;

View File

@ -258,5 +258,24 @@ public class SysDictionaryItemsController {
} }
} }
/***********************************
* 用途说明 根据父项编码查询数据字典项数据
* 参数说明
* parentcode 父项编码
* 返回值说明: 变电站信息
***********************************/
@PostMapping("/list")
@ApiOperation("根据父项编码查询数据字典项数据")
@ResponseBody
public ResponseResult listSysDictionaryItems(@RequestParam String parentcode) {
QueryWrapper<SysDictionaryItems> queryWrapper = new QueryWrapper<>();
if(parentcode != null){
queryWrapper.eq("parentcode",parentcode);
}
queryWrapper.orderByAsc("orderno");
List<Map<String, Object>> maps = sysDictionaryItemsService.listMaps(queryWrapper);
return ResponseResult.successData(maps);
}
} }

View File

@ -52,7 +52,7 @@ public class CodeGenerator {
// 全局配置 // 全局配置
GlobalConfig gc = new GlobalConfig(); GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir"); String projectPath = System.getProperty("user.dir")+"/java";
gc.setOutputDir(projectPath + "/src/main/java"); gc.setOutputDir(projectPath + "/src/main/java");
gc.setAuthor("LiMengNan"); gc.setAuthor("LiMengNan");
gc.setOpen(false); gc.setOpen(false);
@ -61,10 +61,10 @@ public class CodeGenerator {
// 数据源配置 // 数据源配置
DataSourceConfig dsc = new DataSourceConfig(); DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://43.138.168.68:3306/ehmsdb?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true"); dsc.setUrl("jdbc:mysql://121.37.111.42:3306/filemanagedb?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true");
dsc.setDriverName("com.mysql.cj.jdbc.Driver"); dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root"); dsc.setUsername("filemanagedb");
dsc.setPassword("ylfw20230626@"); dsc.setPassword("GAPchydbCKYFjjAa");
mpg.setDataSource(dsc); mpg.setDataSource(dsc);
// 包配置 // 包配置
@ -168,7 +168,7 @@ public class CodeGenerator {
//rca_project,rca_projectanalysisrd,rca_projectinvestigaterd,rca_projectreport,rca_projectsummary,rca_projecttarget,rca_projecttrackrd,rca_analysisguide,rca_eventeffect,rca_failurecase,rca_failurecause,rca_failureclass,rca_failuremode //rca_project,rca_projectanalysisrd,rca_projectinvestigaterd,rca_projectreport,rca_projectsummary,rca_projecttarget,rca_projecttrackrd,rca_analysisguide,rca_eventeffect,rca_failurecase,rca_failurecause,rca_failureclass,rca_failuremode
strategy.setInclude(scanner("表名,多个英文逗号分割").split(",")); strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));
strategy.setControllerMappingHyphenStyle(true); strategy.setControllerMappingHyphenStyle(true);
strategy.setTablePrefix("vis_"); strategy.setTablePrefix("");
mpg.setStrategy(strategy); mpg.setStrategy(strategy);
mpg.setTemplateEngine(new FreemarkerTemplateEngine()); mpg.setTemplateEngine(new FreemarkerTemplateEngine());
mpg.execute(); mpg.execute();

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yfd.platform.modules.experimentalData.mapper.FilesMapper">
</mapper>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yfd.platform.modules.experimentalData.mapper.NodesMapper">
</mapper>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yfd.platform.modules.experimentalData.mapper.TaskMapper">
</mapper>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yfd.platform.modules.experimentalData.mapper.TsFilesMapper">
</mapper>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yfd.platform.modules.experimentalData.mapper.TsNodesMapper">
</mapper>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yfd.platform.modules.experimentalData.mapper.TsTaskMapper">
</mapper>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!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.FilesMapper">
</mapper>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!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.NodesMapper">
</mapper>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!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>