启动脚本+数据总览

This commit is contained in:
2025-11-12 11:01:10 +08:00
parent ebf4e9a6b2
commit e0f9af2d9e
42 changed files with 204 additions and 199 deletions

View File

@@ -3,17 +3,21 @@ package com.sdm.data.controller;
import com.sdm.common.common.SdmResponse;
import com.sdm.common.entity.req.data.CreateDirReq;
import com.sdm.data.model.entity.FileMetadataInfo;
import com.sdm.data.model.req.*;
import com.sdm.data.service.IDimensionTemplateService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 数据总览
*
@@ -35,7 +39,7 @@ public class DataOverviewController {
*/
@PostMapping("/getSimulationNodeTree")
@Operation(summary = "根据数据显示维度展示左侧节点树")
public SdmResponse getSimulationNodeTree(@RequestBody GetSimulationNodeTreeReq req) {
public SdmResponse<List<FileMetadataInfo>> getSimulationNodeTree(@RequestBody GetSimulationNodeTreeReq req) {
return dimensionTemplateService.getSimulationNodeTree(req);
}
@@ -43,7 +47,7 @@ public class DataOverviewController {
* 根据数据显示维度查询当前节点下的文件夹和文件
*/
@PostMapping("/listSimulationNodeFiles")
@Operation(summary = "dimensionTemplateId+chooseUuid+chooseNodeType根据数据显示维度查询当前节点下的文件夹和文件dimensionTemplateId+fileId支持进入普通文件夹和节点文件夹查询下一层,支持分页查询")
@Operation(summary = "dimensionTemplateId+fileId支持进入文件夹和节点文件夹查询下一层,支持分页查询")
public SdmResponse listSimulationNodeFiles(@RequestBody ListSimulationNodeTreeReq req) {
return dimensionTemplateService.listSimulationNodeFiles(req);
}
@@ -60,9 +64,9 @@ public class DataOverviewController {
/**
* 数据总览上传文件到节点文件夹
*/
@PostMapping("/uploadSimulationNodeFiles")
@PostMapping(value = "/uploadSimulationNodeFiles",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@Operation(summary = "数据总览上传文件到节点文件夹")
public SdmResponse uploadSimulationNodeFiles(@RequestBody UploadFilesReq req) {
public SdmResponse uploadSimulationNodeFiles(UploadFilesReq req) {
return dimensionTemplateService.uploadSimulationNodeFiles(req);
}

View File

@@ -15,6 +15,6 @@ import java.util.List;
* @since 2025-09-05
*/
public interface FileMetadataInfoMapper extends BaseMapper<FileMetadataInfo> {
List<FileMetadataInfo> listSimulationNodeFiles(@Param("parentId") Long parentId,@Param("uuids") List<String> uuids);
List<FileMetadataInfo> listSimulationNodeFiles(@Param("parentId") Long parentId,@Param("fileIds") List<Long> fileIds);
}

View File

@@ -14,15 +14,7 @@ public class GetSimulationNodeTreeReq {
private Long dimensionTemplateId;
/**
* 选择的节点ID
* 文件ID
*/
@Schema(description = "选择的节点ID选中节点时才同时传chooseNodeId和chooseNodeType")
private String chooseUuid;
/**
* 选择的节点类型
*/
@Schema(description = "选择的节点类型选中节点时才同时传chooseNodeId和chooseNodeType")
private String chooseNodeType;
private Long fileId;
}

View File

@@ -13,18 +13,6 @@ public class ListSimulationNodeTreeReq extends BaseReq {
@NotEmpty(message = "数据展示维度模版ID不能为空")
private Long dimensionTemplateId;
/**
* 选择的节点ID
*/
@Schema(description = "选择的节点ID选中节点时才同时传chooseNodeId和chooseNodeType")
private String chooseUuid;
/**
* 选择的节点类型
*/
@Schema(description = "选择的节点类型选中节点时才同时传chooseNodeId和chooseNodeType")
private String chooseNodeType;
/**
* 文件夹ID
*/

View File

@@ -4,9 +4,12 @@ import com.sdm.common.common.SdmResponse;
import com.sdm.common.entity.req.data.CreateDirReq;
import com.sdm.data.model.entity.DimensionTemplate;
import com.baomidou.mybatisplus.extension.service.IService;
import com.sdm.data.model.entity.FileMetadataInfo;
import com.sdm.data.model.req.*;
import com.sdm.data.model.req.dimensionTemplate.TemplateCreationRequest;
import java.util.List;
/**
* <p>
* 维度模板主表 服务类
@@ -26,7 +29,7 @@ public interface IDimensionTemplateService extends IService<DimensionTemplate> {
SdmResponse deleteTemplateWithHierarchies(Long id);
SdmResponse getSimulationNodeTree(GetSimulationNodeTreeReq req);
SdmResponse<List<FileMetadataInfo>> getSimulationNodeTree(GetSimulationNodeTreeReq req);
/**
* 根据数据显示维度展示左侧节点树

View File

@@ -16,5 +16,5 @@ import java.util.List;
* @since 2025-09-05
*/
public interface IFileMetadataInfoService extends IService<FileMetadataInfo> {
List<FileMetadataInfo> listSimulationNodeFiles(Long parentId,List<String> uuids);
List<FileMetadataInfo> listSimulationNodeFiles(Long parentId,List<Long> fileIds);
}

View File

@@ -5,15 +5,12 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sdm.common.common.SdmResponse;
import com.sdm.common.entity.constants.NumberConstants;
import com.sdm.common.entity.enums.DataTypeEnum;
import com.sdm.common.entity.enums.DirTypeEnum;
import com.sdm.common.entity.enums.FileIsLastEnum;
import com.sdm.common.entity.req.data.CreateDirReq;
import com.sdm.common.entity.req.data.DelDirReq;
import com.sdm.common.entity.req.project.DelNodeReq;
import com.sdm.common.entity.resp.AllNodeByProjectIdAndTypeResp;
import com.sdm.common.entity.resp.PageDataResp;
import com.sdm.common.feign.impl.project.SimulationNodeFeignClientImpl;
import com.sdm.common.utils.PageUtils;
import com.sdm.data.model.entity.DimensionTemplate;
@@ -161,16 +158,16 @@ public class DimensionTemplateServiceImpl extends ServiceImpl<DimensionTemplateM
@Override
public SdmResponse getSimulationNodeTree(GetSimulationNodeTreeReq req) {
public SdmResponse<List<FileMetadataInfo>> getSimulationNodeTree(GetSimulationNodeTreeReq req) {
// 根据展示维度获取展示节点类型顺序
Long dimensionTemplateId = req.getDimensionTemplateId();
LambdaQueryWrapper<DimensionTemplateHierarchy> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(DimensionTemplateHierarchy::getTemplateId, dimensionTemplateId).orderByAsc(DimensionTemplateHierarchy::getSortOrder);
List<String> dimensionNodeTyepOrderList = dimensionTemplateHierarchyService.list(queryWrapper).stream().map(DimensionTemplateHierarchy::getDisplayName).toList();
String chooseUuid = req.getChooseUuid();
String chooseNodeType = req.getChooseNodeType();
if (ObjectUtils.isEmpty(chooseUuid)) {
List<String> uuids = null;
List<FileMetadataInfo> resultDir = new ArrayList<>();
if (ObjectUtils.isEmpty(req.getFileId())) {
// 选中维度了,没有选节点,按照模版,展示模版的第一层节点数据
String rootNodeType = dimensionNodeTyepOrderList.get(0);
SdmResponse<List<AllNodeByProjectIdAndTypeResp>> allNodeByNodeTypeResponse = simuluationNodeFeignClient.getAllNodeByNodeType(null, rootNodeType);
@@ -179,28 +176,57 @@ public class DimensionTemplateServiceImpl extends ServiceImpl<DimensionTemplateM
return SdmResponse.success();
}
return allNodeByNodeTypeResponse;
uuids = allNodeByNodeTypeResponse.getData().stream().map(AllNodeByProjectIdAndTypeResp::getUuid).toList();
} else {
// 从dimensionNodeTyepOrderList中获取chooseNodeType下一个位置的数据有可能chooseNodeType所在位置就是最后一层节点,SdmResponse返回空数据
int index = dimensionNodeTyepOrderList.indexOf(chooseNodeType);
if (index == -1) {
return SdmResponse.failed("选中节点类型不在数据展示维度中");
}
// 选中维度了,也选中了节点,按照模版,展示该节点的下一层节点文件夹和普通文件夹
Long fileId = req.getFileId();
if (index == dimensionNodeTyepOrderList.size() - 1) {
//尾节点,直接返回空数据
return SdmResponse.success();
}
// 先获取普通文件夹
List<FileMetadataInfo> dirInfos = fileMetadataInfoService
.lambdaQuery()
.eq(FileMetadataInfo::getParentId, fileId)
.eq(FileMetadataInfo::getDataType, DataTypeEnum.DIRECTORY.getValue())
.isNull(FileMetadataInfo::getRelatedResourceUuid)
.list();
resultDir.addAll(dirInfos);
// 再获取节点文件夹
FileMetadataInfo nodeDirInfo = fileMetadataInfoService.getById(fileId);
String chooseUuid = nodeDirInfo.getRelatedResourceUuid();
String chooseNodeType = nodeDirInfo.getRelatedResourceUuidOwnType();
// chooseUuid和chooseNodeType不为空才是节点文件夹才需要查询子节点文件夹文件
if (ObjectUtils.isNotEmpty(chooseUuid) && ObjectUtils.isNotEmpty(chooseNodeType)) {
// 从dimensionNodeTyepOrderList中获取chooseNodeType下一个位置的数据有可能chooseNodeType所在位置就是最后一层节点,SdmResponse返回空数据
int index = dimensionNodeTyepOrderList.indexOf(chooseNodeType);
if (index == -1) {
return SdmResponse.failed("选中节点类型不在数据展示维度中");
}
if (index == dimensionNodeTyepOrderList.size() - 1) {
//尾节点,直接返回空数据
return SdmResponse.success();
}
// 获取dimensionNodeTyepOrderList的index+1位置的节点类型
String nextNodeType = dimensionNodeTyepOrderList.get(index + 1);
SdmResponse<List<AllNodeByProjectIdAndTypeResp>> allNodeByProjectIdAndType = simuluationNodeFeignClient.getAllNodeByProjectIdAndType(chooseUuid, nextNodeType);
if (!allNodeByProjectIdAndType.isSuccess()) {
return SdmResponse.success();
// 获取dimensionNodeTyepOrderList的index+1位置的节点类型
String nextNodeType = dimensionNodeTyepOrderList.get(index + 1);
SdmResponse<List<AllNodeByProjectIdAndTypeResp>> allNodeByProjectIdAndType = simuluationNodeFeignClient.getAllNodeByProjectIdAndType(chooseUuid, nextNodeType);
if (!allNodeByProjectIdAndType.isSuccess()) {
return SdmResponse.success();
}
uuids = allNodeByProjectIdAndType.getData().stream().map(AllNodeByProjectIdAndTypeResp::getUuid).toList();
}
return allNodeByProjectIdAndType;
}
if (ObjectUtils.isEmpty(uuids)) {
return SdmResponse.success(resultDir);
}
List<FileMetadataInfo> nodeDirInfos = fileMetadataInfoService.lambdaQuery().in(FileMetadataInfo::getRelatedResourceUuid, uuids).list();
resultDir.addAll(nodeDirInfos);
return SdmResponse.success(resultDir);
}
@Override
@@ -208,48 +234,31 @@ public class DimensionTemplateServiceImpl extends ServiceImpl<DimensionTemplateM
// 按照显示维度展示后,会打乱原本的文件夹父子关系,需要重新构建父子关系:
// 1、先调用 getSimulationNodeTree 按照维度查询项目子节点node根据node-uuid获取fileId
// 2、再查询原本的普通文件夹信息需要isProjectDimension=true 只查询普通文件夹,不查询节点文件夹,union all 查询node的fileId 后 分页查询
Long parentId;
List<String> uuids = null;
String relatedResourceUuid = null;
String relatedResourceUuidOwnType = null;
Long parentDirId;
List<Long> dirInfos = null;
if (ObjectUtils.isNotEmpty(req.getFileId())) {
//fileId 不为空,是右侧点击进入文件夹下一层级查询
parentId = req.getFileId();
Optional<FileMetadataInfo> parentDirInfo = fileMetadataInfoService.lambdaQuery().eq(FileMetadataInfo::getId, parentId).oneOpt();
parentDirId = req.getFileId();
Optional<FileMetadataInfo> parentDirInfo = fileMetadataInfoService.lambdaQuery().eq(FileMetadataInfo::getId, parentDirId).oneOpt();
if (!parentDirInfo.isPresent()) {
return SdmResponse.failed("父文件夹不存在");
}
relatedResourceUuid = parentDirInfo.get().getRelatedResourceUuid();
relatedResourceUuidOwnType = parentDirInfo.get().getRelatedResourceUuidOwnType();
} else if (ObjectUtils.isNotEmpty(req.getChooseUuid()) && ObjectUtils.isNotEmpty(req.getChooseNodeType())) {
// chooseUuid 和 chooseNodeType不为空是左侧点击树节点后查询当前节点文件下的文件信息
relatedResourceUuid = req.getChooseUuid();
relatedResourceUuidOwnType = req.getChooseNodeType();
Optional<FileMetadataInfo> parentDirInfo = fileMetadataInfoService.lambdaQuery().eq(FileMetadataInfo::getRelatedResourceUuid, relatedResourceUuid).oneOpt();
if (!parentDirInfo.isPresent()) {
return SdmResponse.failed("父文件夹不存在");
}
parentId = parentDirInfo.get().getId();
} else {
return SdmResponse.success();
}
// relatedResourceUuid和relatedResourceUuidOwnType不为空才是节点文件夹才需要查询子节点文件夹文件
if (ObjectUtils.isNotEmpty(relatedResourceUuid) && ObjectUtils.isNotEmpty(relatedResourceUuidOwnType)) {
GetSimulationNodeTreeReq getSimulationNodeTreeReq = new GetSimulationNodeTreeReq();
getSimulationNodeTreeReq.setDimensionTemplateId(req.getDimensionTemplateId());
getSimulationNodeTreeReq.setChooseUuid(relatedResourceUuid);
getSimulationNodeTreeReq.setChooseNodeType(relatedResourceUuidOwnType);
SdmResponse<List<AllNodeByProjectIdAndTypeResp>> allNodeByProjectIdAndType = getSimulationNodeTree(getSimulationNodeTreeReq);
if (allNodeByProjectIdAndType.isSuccess() && ObjectUtils.isNotEmpty(allNodeByProjectIdAndType.getData())) {
uuids = allNodeByProjectIdAndType.getData().stream().map(AllNodeByProjectIdAndTypeResp::getUuid).toList();
}
GetSimulationNodeTreeReq getSimulationNodeTreeReq = new GetSimulationNodeTreeReq();
getSimulationNodeTreeReq.setDimensionTemplateId(req.getDimensionTemplateId());
getSimulationNodeTreeReq.setFileId(parentDirId);
SdmResponse<List<FileMetadataInfo>> nodeDirInfos = getSimulationNodeTree(getSimulationNodeTreeReq);
if (nodeDirInfos.isSuccess() && ObjectUtils.isNotEmpty(nodeDirInfos.getData())) {
dirInfos = nodeDirInfos.getData().stream().map(FileMetadataInfo::getId).toList();
}
PageHelper.startPage(req.getCurrent(), req.getSize());
List<FileMetadataInfo> fileMetadataInfos = fileMetadataInfoService.listSimulationNodeFiles(parentId, uuids);
List<FileMetadataInfo> fileMetadataInfos = fileMetadataInfoService.listSimulationNodeFiles(parentDirId, dirInfos);
PageInfo<FileMetadataInfo> page = new PageInfo<>(fileMetadataInfos);
return PageUtils.getJsonObjectSdmResponse(fileMetadataInfos, page);

View File

@@ -22,7 +22,7 @@ import java.util.List;
@Service
public class FileMetadataInfoServiceImpl extends ServiceImpl<FileMetadataInfoMapper, FileMetadataInfo> implements IFileMetadataInfoService {
@Override
public List<FileMetadataInfo> listSimulationNodeFiles(Long parentId, List<String> uuids) {
return this.baseMapper.listSimulationNodeFiles(parentId,uuids);
public List<FileMetadataInfo> listSimulationNodeFiles(Long parentId, List<Long> fileIds) {
return this.baseMapper.listSimulationNodeFiles(parentId,fileIds);
}
}

View File

@@ -121,14 +121,17 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
@Transactional(rollbackFor = Exception.class)
public SdmResponse createDir(CreateDirReq req) {
if (req == null || !StringUtils.hasText(req.getDirName())) {
log.error("创建目录失败, 目录名称为空");
return SdmResponse.failed("目录名称不能为空");
}
try {
// 处理根目录创建逻辑(知识库根目录创建逻辑和项目节点目录创建)
if (ObjectUtils.isEmpty(req.getParDirId()) && ObjectUtils.isEmpty(req.getParentUuId())) {
log.info("创建根目录");
return createRootDir(req);
} else {
// 处理子目录创建逻辑
log.info("创建子目录");
return createChildDir(req);
}
} catch (Exception e) {
@@ -243,11 +246,13 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
public SdmResponse<?> createRootDir(CreateDirReq req) {
if(ObjectUtils.isEmpty(req.getDirType())){
log.error("请选择目录类型:1 知识库文件夹2 项目节点文件夹3 头像库文件夹4 仿真参数库文件夹,5 训练模型文件夹");
return SdmResponse.failed("请选择目录类型:1 知识库文件夹2 项目节点文件夹3 头像库文件夹4 仿真参数库文件夹,5 训练模型文件夹");
}
DirTypeEnum dirTypeByValue = DirTypeEnum.getDirTypeByValue(req.getDirType());
if (dirTypeByValue == null) {
log.error("请选择正确的目录类型:1 知识库文件夹2 项目节点文件夹3 头像库文件夹4 仿真参数库文件夹,5 训练模型文件夹");
return SdmResponse.failed("请选择正确的目录类型:1 知识库文件夹2 项目节点文件夹3 头像库文件夹4 仿真参数库文件夹,5 训练模型文件夹");
}
@@ -256,6 +261,7 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
Optional<FileMetadataInfo> fileMetadataInfoByObjectKey = getFileMetadataInfoByObjectKey(rootDirMinioObjectKey);
// 检查目录是否已存在
if (!fileMetadataInfoByObjectKey.isPresent()) {
log.error("知识库、项目根目录不存在,等待initSystemDirectory 初始化完成");
return SdmResponse.failed("知识库、项目根目录不存在,等待initSystemDirectory 初始化完成");
}
@@ -271,6 +277,7 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
try {
// 检查目录是否已存在
if (getFileMetadataInfoByObjectKey(dirMinioObjectKey).isPresent()) {
log.error("目录已存在");
return SdmResponse.failed("目录已存在");
}
@@ -284,6 +291,7 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
// 创建默认权限记录
createDirectoryPermission(dirInfo.getId());
log.error("根目录创建成功");
return SdmResponse.success("根目录创建成功");
} catch (Exception dbException) {
log.error("创建根目录失败", dbException);
@@ -307,6 +315,10 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
Long parDirId = null;
if (req.getParentUuId() != null) {
FileMetadataInfo node = fileMetadataInfoService.lambdaQuery().eq(FileMetadataInfo::getRelatedResourceUuid, req.getParentUuId()).one();
if (ObjectUtils.isEmpty(node)) {
log.error("上级节点目录不存在");
return SdmResponse.failed("上级节点目录不存在");
}
parDirId = node.getId();
} else {
parDirId = req.getParDirId();
@@ -314,6 +326,7 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
FileMetadataInfo parDirInfo = fileMetadataInfoService.lambdaQuery().eq(FileMetadataInfo::getId, parDirId).one();
if (ObjectUtils.isEmpty(parDirInfo)) {
log.error("上级目录不存在");
return SdmResponse.failed("上级目录不存在");
}
@@ -322,11 +335,13 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
// 检查子目录是否已存在
if (getFileMetadataInfoByObjectKey(childDirMinioObjectKey).isPresent()) {
log.error("目录已存在");
return SdmResponse.failed("目录已存在");
}
boolean hasWritePermission = fileUserPermissionService.hasFilePermission(parDirId, ThreadLocalContext.getUserId(), FilePermissionEnum.WRITE);
if (!hasWritePermission) {
log.error("没有写入权限");
return SdmResponse.failed("没有写入权限");
}
@@ -341,6 +356,7 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
// 创建默认权限记录
createDirectoryPermission(dirInfo.getId());
log.info("子目录创建成功");
return SdmResponse.success("子目录创建成功");
} catch (Exception dbException) {

View File

@@ -1,3 +1,3 @@
spring:
profiles:
active: dev
active: local

View File

@@ -42,4 +42,4 @@ fi
# 启动项目
echo "正在启动项目..."
nohup java ${JVM_OPTS} -jar "${FULL_JAR_PATH}" > "${LOG_FILE}" 2>&1 &
nohup java ${JVM_OPTS} -Dspring.profiles.active=dev -jar "${FULL_JAR_PATH}" > "${LOG_FILE}" 2>&1 &

View File

@@ -2,22 +2,22 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sdm.data.dao.FileMetadataInfoMapper">
<select id="listSimulationNodeFiles" resultType="com.sdm.data.model.entity.FileMetadataInfo">
<!-- 第一个子查询(必执行) -->
<!-- 第一个子查询文件(必执行) -->
SELECT *
FROM file_metadata_info
WHERE parentId = #{parentId}
AND relatedResourceUuid IS NULL
AND dataType = 2
AND isLatest = true
<!-- 动态判断uuids 不为空且有元素时,才拼接 UNION ALL + 第二个子查询 -->
<if test="uuids != null">
<!-- 动态判断uuids 不为空且有元素时,才拼接 UNION ALL + 第二个子查询普通文件夹和节点文件夹 -->
<if test="fileIds != null">
UNION ALL
(
SELECT *
FROM file_metadata_info
WHERE relatedResourceUuid IN (
<foreach collection="uuids" item="uuid" separator=",">
#{uuid}
WHERE id IN (
<foreach collection="fileIds" item="fileId" separator=",">
#{fileId}
</foreach>
)
)