fix:优化数据标签

This commit is contained in:
2026-03-16 16:19:10 +08:00
parent 5d4b701d4c
commit 0dfae61ea0
6 changed files with 94 additions and 235 deletions

View File

@@ -11,48 +11,18 @@ public class BaseResp {
@Schema(description = "格式化后的文件大小")
private String formatFileSize;
@Schema(description = "所属项目")
String ownProjectName;
@Schema(description = "所属项目id")
private String ownProjectId;
@Schema(description = "所属阶段")
String ownPhaseName;
@Schema(description = "所属阶段id")
private String ownPhaseId;
@Schema(description = "所属学科")
String ownDisciplineName;
@Schema(description = "所属学科id")
private String ownDisciplineId;
@Schema(description = "所属机器")
private String ownMachineName;
@Schema(description = "所属机器id")
private String ownMachineId;
@Schema(description = "所属工作空间")
private String ownWorkspaceName;
@Schema(description = "所属工作空间id")
private String ownWorkspaceId;
@Schema(description = "所属工况任务")
String owntaskName;
@Schema(description = "所属工况任务id")
private String owntaskId;
@Schema(description = "所属算列")
String ownRunName;
@Schema(description = "所属算列id")
private String ownRunId;
@Schema(description= "文件业务类型1模型文件 2仿真报告、3计算文件、4曲线文件、5云图文件6网格文件7计算过程文件")
@TableField("fileType")
private Integer fileType;

View File

@@ -126,7 +126,7 @@ public class FileMetadataInfoResp extends BaseResp implements Serializable {
private String knowledgeBaseName;
private String approvalStatus;
private String approveType;
private Integer approveType;
private String tempMetadata;
private String cidFlowId;
private String uploadTaskId;

View File

@@ -15,6 +15,8 @@ import com.sdm.common.entity.req.data.TagReq;
import com.sdm.common.entity.req.export.FileAnalysisExportExcelFormat;
import com.sdm.common.entity.req.export.FileAnalysisExportExcelParam;
import com.sdm.common.entity.resp.PageDataResp;
import com.sdm.common.entity.resp.data.FileMetadataInfoResp;
import com.sdm.common.utils.DictTagHelper;
import com.sdm.common.utils.FileSizeUtils;
import com.sdm.common.utils.PageUtils;
import com.sdm.common.utils.SystemOperate;
@@ -34,6 +36,7 @@ import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
@@ -65,6 +68,9 @@ public class DataAnalysisServiceImpl implements IDataAnalysisService {
@Autowired
IFileDictTagQueryService fileDictTagQueryService;
@Resource
private DictTagHelper dictTagHelper;
@Override
public SdmResponse<PageDataResp<List<SimulationTaskResultCurveResp>>> getSimulationTaskFile(GetSimulationTaskFileReq req) {
@@ -126,18 +132,11 @@ public class DataAnalysisServiceImpl implements IDataAnalysisService {
List<FileMetadataInfo> fileMetadataInfos = wrapper.list();
PageInfo<FileMetadataInfo> page = new PageInfo<>(fileMetadataInfos);
List<SimulationTaskResultCurveResp> finalResultList = fileMetadataInfos.stream().map(file -> {
SimulationTaskResultCurveResp resp = new SimulationTaskResultCurveResp();
BeanUtils.copyProperties(file, resp);
if (ObjectUtils.isNotEmpty(file.getFileSize())) {
resp.setFormatFileSize(FileSizeUtils.formatFileSize(BigDecimal.valueOf(file.getFileSize())));
}
// 设置tag1-tag10
List<SimulationTaskResultCurveResp> finalResultList = hierarchyHelper.processFileHierarchyFromFileMetadata(fileMetadataInfos,SimulationTaskResultCurveResp.class);
hierarchyHelper.setTagReqFromFileMetadataBatch(finalResultList, SimulationTaskResultCurveResp::getId);
hierarchyHelper.setTagReqFromFileMetadata(file, resp);
return resp;
}).collect(Collectors.toList());
// 填充children的文件类型标签信息
// 填充文件类型标签信息
fileDictTagQueryService.fillFileTagsForRespList(finalResultList, SimulationTaskResultCurveResp::getId);
sortByTagFieldInCurrentPage(finalResultList, req.getOrderBy(), req.getOrderType());
@@ -156,9 +155,13 @@ public class DataAnalysisServiceImpl implements IDataAnalysisService {
*/
private List<Long> extractFileIdsByTags(GetSimulationTaskFileReq req) {
Map<String, Map<String, Integer>> dictIdMap = req.getDictTagIdsCache();
if (ObjectUtils.isEmpty(dictIdMap)) {
log.warn("Dict tags cache is empty, cannot extract file ids by tags");
return null;
if (dictIdMap == null || dictIdMap.isEmpty()) {
log.warn("Dict tags cache is empty for update, trying to query manually");
dictIdMap = dictTagHelper.queryAndCacheDictTagIds(req);
if (dictIdMap.isEmpty()) {
log.warn("No dictionary ids found for tags update");
return null;
}
}
Set<Integer> tagIds = new HashSet<>();
@@ -269,57 +272,7 @@ public class DataAnalysisServiceImpl implements IDataAnalysisService {
return null;
}
private void setTagReqForSimulationResult(List<SimulationTaskResultCurveResp> resultList, List<Long> fileIdList) {
if (CollectionUtils.isEmpty(resultList) || CollectionUtils.isEmpty(fileIdList)) {
return;
}
List<FileMetadataInfo> metadataInfos = fileMetadataInfoService.lambdaQuery()
.in(FileMetadataInfo::getId, fileIdList)
.eq(FileMetadataInfo::getTenantId, ThreadLocalContext.getTenantId())
.isNull(FileMetadataInfo::getDeletedAt)
.list();
if (CollectionUtils.isEmpty(metadataInfos)) {
return;
}
Map<Long, FileMetadataInfo> fileIdMap = metadataInfos.stream()
.collect(Collectors.toMap(FileMetadataInfo::getId, t -> t, (left, right) -> left));
for (SimulationTaskResultCurveResp resp : resultList) {
FileMetadataInfo metadataInfo = fileIdMap.get(resp.getId());
if (ObjectUtils.isNotEmpty(metadataInfo)) {
hierarchyHelper.setTagReqFromFileMetadata(metadataInfo, resp);
}
}
}
private void fillFormatFileSizeForTaskLevel(List<SimulationTaskResultCurveResp> resultList, List<Long> fileIdList) {
if (CollectionUtils.isEmpty(resultList) || CollectionUtils.isEmpty(fileIdList)) {
return;
}
List<FileMetadataInfo> metadataInfos = fileMetadataInfoService.lambdaQuery()
.in(FileMetadataInfo::getId, fileIdList)
.eq(FileMetadataInfo::getTenantId, ThreadLocalContext.getTenantId())
.isNull(FileMetadataInfo::getDeletedAt)
.select(FileMetadataInfo::getId, FileMetadataInfo::getFileSize)
.list();
if (CollectionUtils.isEmpty(metadataInfos)) {
return;
}
Map<Long, Long> fileSizeMap = metadataInfos.stream()
.collect(Collectors.toMap(FileMetadataInfo::getId, FileMetadataInfo::getFileSize, (left, right) -> left));
for (SimulationTaskResultCurveResp resp : resultList) {
Long fileSize = fileSizeMap.get(resp.getId());
if (ObjectUtils.isNotEmpty(fileSize)) {
resp.setFormatFileSize(FileSizeUtils.formatFileSize(BigDecimal.valueOf(fileSize)));
}
}
}
private void sortByTagFieldInCurrentPage(List<SimulationTaskResultCurveResp> data, String orderBy, String orderType) {
if (CollectionUtils.isEmpty(data) || StringUtils.isBlank(orderBy)) {
@@ -409,18 +362,11 @@ public class DataAnalysisServiceImpl implements IDataAnalysisService {
PageInfo<FileMetadataInfo> page = new PageInfo<>(fileMetadataInfoList);
long total = page.getTotal();
List<Long> fileIdList = fileMetadataInfoList.stream().map(FileMetadataInfo::getId).toList();
List<SimulationTaskResultCurveResp> finalResultList = hierarchyHelper.processFileHierarchy(
fileIdList,
SimulationTaskResultCurveResp.class,
(resp, folder, ownType) -> {
}
);
// 设置tag1-tag10
List<SimulationTaskResultCurveResp> finalResultList = hierarchyHelper.processFileHierarchyFromFileMetadata(fileMetadataInfoList, SimulationTaskResultCurveResp.class);
hierarchyHelper.setTagReqFromFileMetadataBatch(finalResultList, SimulationTaskResultCurveResp::getId);
setTagReqForSimulationResult(finalResultList, fileIdList);
fillFormatFileSizeForTaskLevel(finalResultList, fileIdList);
// 填充children的文件类型标签信息
// 填充的文件类型标签信息
fileDictTagQueryService.fillFileTagsForRespList(finalResultList, SimulationTaskResultCurveResp::getId);
sortByTagFieldInCurrentPage(finalResultList, req.getOrderBy(), req.getOrderType());

View File

@@ -441,11 +441,8 @@ public class DataStorageAnalysisImpl implements DataStorageAnalysis {
// 2. 一站式处理:获取文件元数据、构建父目录缓存、转换为响应对象并设置层级信息
List<Long> fileIdList = fileStorages.stream().map(FileStorage::getFileId).toList();
List<ListBigFileResp> finalResultList = hierarchyHelper.processFileHierarchy(
fileIdList,
ListBigFileResp.class,
FileMetadataHierarchyHelper::setFileHierarchy
);
List<ListBigFileResp> finalResultList = hierarchyHelper.processFileHierarchy(fileIdList, ListBigFileResp.class);
hierarchyHelper.setTagReqFromFileMetadataBatch(finalResultList, ListBigFileResp::getId);
// 2.1 批量填充文件字典标签(文件类型、学科类型)
fileDictTagQueryService.fillFileTagsForRespList(finalResultList, ListBigFileResp::getId);

View File

@@ -2,6 +2,7 @@ package com.sdm.data.service.impl;
import com.sdm.common.common.ThreadLocalContext;
import com.sdm.common.entity.enums.NodeTypeEnum;
import com.sdm.common.entity.resp.data.FileMetadataInfoResp;
import com.sdm.common.utils.FileSizeUtils;
import com.sdm.data.model.entity.FileMetadataInfo;
import com.sdm.data.service.IFileMetadataInfoService;
@@ -19,7 +20,7 @@ import java.util.stream.Collectors;
/**
* 文件元数据层级信息帮助类
* 用于递归查询父目录信息并设置层级关系
* 用于设置tag1-tag10文件标签信息
*/
@Slf4j
@Component
@@ -43,14 +44,12 @@ public class FileMetadataHierarchyHelper {
*
* @param fileIdList 文件ID列表
* @param respClass 响应类型
* @param hierarchySetter 层级信息设置器
* @param <T> 响应类型
* @return 响应对象列表
*/
public <T> List<T> processFileHierarchy(
List<Long> fileIdList,
Class<T> respClass,
HierarchySetter<T> hierarchySetter) {
Class<T> respClass) {
if (CollectionUtils.isEmpty(fileIdList)) {
return new ArrayList<>();
@@ -63,11 +62,54 @@ public class FileMetadataHierarchyHelper {
return new ArrayList<>();
}
// 2. 构建父目录缓存
Map<Long, FileMetadataInfo> parentCacheMap = buildParentCacheMap(currentFiles);
return currentFiles.stream().map(file -> {
try {
T resp = respClass.getDeclaredConstructor().newInstance();
BeanUtils.copyProperties(file, resp);
// 3. 转换为响应对象并设置层级信息
return convertToRespWithHierarchy(currentFiles, parentCacheMap, respClass, hierarchySetter);
// 设置格式化文件大小
if (file.getFileSize() != null) {
setFormatFileSize(resp, file.getFileSize());
}
return resp;
} catch (Exception e) {
log.error("转换文件元数据到响应对象失败", e);
throw new RuntimeException("转换失败", e);
}
}).toList();
}
/**
* 一站式方法根据文件ID列表获取文件元数据构建层级缓存转换为响应对象并设置层级信息
*
* @param currentFiles 文件元数据列表
* @param respClass 响应类型
* @param <T> 响应类型
* @return 响应对象列表
*/
public <T> List<T> processFileHierarchyFromFileMetadata(
List<FileMetadataInfo> currentFiles,
Class<T> respClass) {
if (CollectionUtils.isEmpty(currentFiles)) {
return new ArrayList<>();
}
return currentFiles.stream().map(file -> {
try {
T resp = respClass.getDeclaredConstructor().newInstance();
BeanUtils.copyProperties(file, resp);
// 设置格式化文件大小
if (file.getFileSize() != null) {
setFormatFileSize(resp, file.getFileSize());
}
return resp;
} catch (Exception e) {
log.error("转换文件元数据到响应对象失败", e);
throw new RuntimeException("转换失败", e);
}
}).toList();
}
/**
@@ -179,72 +221,6 @@ public class FileMetadataHierarchyHelper {
return parentCacheMap;
}
/**
* 将文件列表转换为响应对象列表,并设置层级信息
*
* @param currentFiles 当前文件列表
* @param parentCacheMap 父目录缓存Map
* @param respClass 响应类型
* @param hierarchySetter 层级信息设置器
* @param <T> 响应类型
* @return 响应对象列表
*/
public <T> List<T> convertToRespWithHierarchy(
List<FileMetadataInfo> currentFiles,
Map<Long, FileMetadataInfo> parentCacheMap,
Class<T> respClass,
HierarchySetter<T> hierarchySetter) {
if (CollectionUtils.isEmpty(currentFiles)) {
return new ArrayList<>();
}
return currentFiles.stream().map(file -> {
try {
T resp = respClass.getDeclaredConstructor().newInstance();
BeanUtils.copyProperties(file, resp);
// 设置格式化文件大小
if (file.getFileSize() != null) {
setFormatFileSize(resp, file.getFileSize());
}
// 从 parentCacheMap 中回溯,设置层级信息
backtrackAndSetHierarchy(file, parentCacheMap, resp, hierarchySetter);
return resp;
} catch (Exception e) {
log.error("转换文件元数据到响应对象失败", e);
throw new RuntimeException("转换失败", e);
}
}).toList();
}
/**
* 回溯父目录并设置层级信息
*/
public <T> void backtrackAndSetHierarchy(
FileMetadataInfo file,
Map<Long, FileMetadataInfo> parentCacheMap,
T resp,
HierarchySetter<T> hierarchySetter) {
Long pid = file.getParentId();
int limit = 0;
// 这里的循环完全在内存中进行,速度极快且不产生日志
while (pid != null && parentCacheMap.containsKey(pid) && limit < BACKTRACK_LIMIT) {
FileMetadataInfo folder = parentCacheMap.get(pid);
String ownType = folder.getRelatedResourceUuidOwnType();
// 调用层级信息设置器
hierarchySetter.setHierarchyInfo(resp, folder, ownType);
pid = folder.getParentId();
limit++;
}
}
/**
* 通过反射设置格式化文件大小
*/
@@ -259,52 +235,6 @@ public class FileMetadataHierarchyHelper {
}
}
/**
* 层级信息设置器函数式接口
*
* @param <T> 响应类型
*/
@FunctionalInterface
public interface HierarchySetter<T> {
/**
* 设置层级信息
*
* @param resp 响应对象
* @param folder 父文件夹元数据
* @param ownType 节点类型
*/
void setHierarchyInfo(T resp, FileMetadataInfo folder, String ownType);
}
public static <T> void setFileHierarchy(T resp, FileMetadataInfo folder, String ownType) {
try {
if (NodeTypeEnum.PROJECT.getValue().equals(ownType)) {
resp.getClass().getMethod("setOwnProjectName", String.class).invoke(resp, folder.getOriginalName());
resp.getClass().getMethod("setOwnProjectId", String.class).invoke(resp, folder.getRelatedResourceUuid());
} else if (NodeTypeEnum.PHASE.getValue().equals(ownType)) {
resp.getClass().getMethod("setOwnPhaseName", String.class).invoke(resp, folder.getOriginalName());
resp.getClass().getMethod("setOwnPhaseId", String.class).invoke(resp, folder.getRelatedResourceUuid());
} else if (NodeTypeEnum.MACHINE.getValue().equals(ownType)) {
resp.getClass().getMethod("setOwnMachineName", String.class).invoke(resp, folder.getOriginalName());
resp.getClass().getMethod("setOwnMachineId", String.class).invoke(resp, folder.getRelatedResourceUuid());
}if (NodeTypeEnum.WORKSPACE.getValue().equals(ownType)) {
resp.getClass().getMethod("setOwnWorkspaceName", String.class).invoke(resp, folder.getOriginalName());
resp.getClass().getMethod("setOwnWorkspaceId", String.class).invoke(resp, folder.getRelatedResourceUuid());
} else if (NodeTypeEnum.TASK.getValue().equals(ownType)) {
resp.getClass().getMethod("setOwntaskName", String.class).invoke(resp, folder.getOriginalName());
resp.getClass().getMethod("setOwntaskId", String.class).invoke(resp, folder.getRelatedResourceUuid());
} else if (NodeTypeEnum.RUN.getValue().equals(ownType)) {
resp.getClass().getMethod("setOwnRunName", String.class).invoke(resp, folder.getOriginalName());
resp.getClass().getMethod("setOwnRunId", String.class).invoke(resp, folder.getRelatedResourceUuid());
}
} catch (Exception e) {
log.warn("设置ListBigFile层级信息失败", e);
}
}
/**
* 批量为响应对象设置tagReq合并单条逻辑避免重复查询
*

View File

@@ -954,7 +954,6 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
// 使用 hierarchyHelper 获取文件元数据和父目录缓存
FileMetadataHierarchyHelper.FileHierarchyResult hierarchyResult = hierarchyHelper.getFilesWithParentCache(fileIdList);
List<FileMetadataInfo> files = hierarchyResult.getFiles();
Map<Long, FileMetadataInfo> parentCacheMap = hierarchyResult.getParentCacheMap();
// 设置审批状态
if(CollectionUtils.isNotEmpty(files)){
files.stream().forEach(x -> {
@@ -975,8 +974,9 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
setAnalysisDirectionName(files);
setSimulationPoolAndTaskInfo(files);
List<FileMetadataInfoResp> dtoList = hierarchyHelper.convertToRespWithHierarchy(files, parentCacheMap, FileMetadataInfoResp.class, FileMetadataHierarchyHelper::setFileHierarchy)
.stream().map(dto -> {
List<FileMetadataInfoResp> respList = hierarchyHelper.processFileHierarchyFromFileMetadata(files, FileMetadataInfoResp.class);
hierarchyHelper.setTagReqFromFileMetadataBatch(respList, FileMetadataInfoResp::getId);
List<FileMetadataInfoResp> dtoList = respList.stream().map(dto -> {
//计算当前用户对该文件的综合权限位
// 对于列表查询,如果层级很深,频繁递归会有性能问题。
dto.setPermissionValue(fileUserPermissionService.getMergedPermission(dto.getId(), ThreadLocalContext.getUserId()));
@@ -1027,9 +1027,10 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
}
if (DataTypeEnum.FILE.getValue() == fileMetadataInfo.getDataType()) {
List<FileMetadataInfo> list = Arrays.asList(fileMetadataInfo);
List<FileMetadataInfo> list = List.of(fileMetadataInfo);
setProjectName(list);
setCreatorNames(list);
setSimulationPoolAndTaskInfo(list);
fileMetadataInfo = list.get(0);
FileMetadataInfo dirMetadataInfo = fileMetadataInfoService.lambdaQuery().eq(FileMetadataInfo::getId, fileMetadataInfo.getParentId()).one();
String knowledgeBaseName = extractRelativePath(dirMetadataInfo);
@@ -1045,9 +1046,24 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService {
fileUserPermissionService.getMergedPermission(fileMetadataInfo.getId(), ThreadLocalContext.getUserId())
);
// 设置审批状态
fileMetadataInfoResp.setApprovalStatus(ApproveFileDataTypeEnum.getStatusStr(fileMetadataInfoResp.getApproveType()));
// 假如是pending 数据创建人和当前查询人不是一个人,则这是操作修改或者删除了,对于当前查询人展示的就是未变更的数据,那就是审核完成状态
Long userId = ThreadLocalContext.getUserId();
if(!Objects.isNull(userId)){
if(Objects.equals(fileMetadataInfoResp.getApprovalStatus(), ApprovalFileDataStatusEnum.PENDING.getKey())&&
!Objects.equals(userId,fileMetadataInfoResp.getCreatorId())){
// 完成态
fileMetadataInfoResp.setApprovalStatus("approved");
}
}
// 填充文件ta1-tag10的信息
hierarchyHelper.setTagReqFromFileMetadata(fileMetadataInfo,fileMetadataInfoResp);
// 填充文件类型标签信息
fileDictTagQueryService.fillFileTagsForRespList(List.of(fileMetadataInfoResp), FileMetadataInfoResp::getId);
return SdmResponse.success(fileMetadataInfoResp);
}