fix:数据查询支持列头无关联,基于tag查询 查询
This commit is contained in:
@@ -61,22 +61,4 @@ public class GetSimulationTaskFileReq extends BaseReq {
|
||||
|
||||
@Schema(description = "标签筛选参数")
|
||||
private TagReq tagReq;
|
||||
|
||||
@Schema(description = "项目级 dirId 列表")
|
||||
private List<Long> projectDirIds;
|
||||
|
||||
@Schema(description = "阶段级 dirId 列表")
|
||||
private List<Long> phaseDirIds;
|
||||
|
||||
@Schema(description = "机台级 dirId 列表")
|
||||
private List<Long> machineDirIds;
|
||||
|
||||
@Schema(description = "工位级 dirId 列表")
|
||||
private List<Long> workspaceDirIds;
|
||||
|
||||
@Schema(description = "任务级 dirId 列表")
|
||||
private List<Long> taskDirIds;
|
||||
|
||||
@Schema(description = "算例级 dirId 列表")
|
||||
private List<Long> runDirIDs;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.sdm.data.service.impl;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import com.sdm.common.common.SdmResponse;
|
||||
@@ -13,12 +15,11 @@ 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.utils.FileSizeUtils;
|
||||
import com.sdm.common.utils.PageUtils;
|
||||
import com.sdm.common.utils.SystemOperate;
|
||||
import com.sdm.data.bo.ExportOperate;
|
||||
import com.sdm.data.model.entity.FileMetadataInfo;
|
||||
import com.sdm.data.model.entity.FileStorage;
|
||||
import com.sdm.data.model.entity.FileTagRel;
|
||||
import com.sdm.common.entity.req.data.GetSimulationTaskFileReq;
|
||||
import com.sdm.data.model.req.QueryBigFileReq;
|
||||
import com.sdm.common.entity.resp.data.SimulationTaskResultCurveResp;
|
||||
@@ -48,9 +49,6 @@ public class DataAnalysisServiceImpl implements IDataAnalysisService {
|
||||
@Autowired
|
||||
private IFileMetadataInfoService fileMetadataInfoService;
|
||||
|
||||
@Autowired
|
||||
private DataStorageAnalysis dataStorageAnalysis;
|
||||
|
||||
@Autowired
|
||||
private IMinioService MinIOService;
|
||||
|
||||
@@ -60,117 +58,194 @@ public class DataAnalysisServiceImpl implements IDataAnalysisService {
|
||||
@Autowired
|
||||
private ExportOperate exportOperate;
|
||||
|
||||
@Autowired
|
||||
private IFileTagRelService fileTagRelService;
|
||||
|
||||
|
||||
@Override
|
||||
public SdmResponse<PageDataResp<List<SimulationTaskResultCurveResp>>> getSimulationTaskFile(GetSimulationTaskFileReq getSimulationTaskFileReq) {
|
||||
// 1. 构造查询条件
|
||||
QueryBigFileReq queryBigFileReq = new QueryBigFileReq();
|
||||
BeanUtils.copyProperties(getSimulationTaskFileReq, queryBigFileReq);
|
||||
|
||||
// 步骤 1: 收集所有直接传入的 dirId(兼容旧参数)
|
||||
Set<Long> allDirIds = new HashSet<>();
|
||||
if (CollectionUtils.isNotEmpty(getSimulationTaskFileReq.getProjectDirIds())) {
|
||||
allDirIds.addAll(getSimulationTaskFileReq.getProjectDirIds());
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(getSimulationTaskFileReq.getPhaseDirIds())) {
|
||||
allDirIds.addAll(getSimulationTaskFileReq.getPhaseDirIds());
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(getSimulationTaskFileReq.getMachineDirIds())) {
|
||||
allDirIds.addAll(getSimulationTaskFileReq.getMachineDirIds());
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(getSimulationTaskFileReq.getWorkspaceDirIds())) {
|
||||
allDirIds.addAll(getSimulationTaskFileReq.getWorkspaceDirIds());
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(getSimulationTaskFileReq.getTaskDirIds())) {
|
||||
allDirIds.addAll(getSimulationTaskFileReq.getTaskDirIds());
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(getSimulationTaskFileReq.getRunDirIDs())) {
|
||||
allDirIds.addAll(getSimulationTaskFileReq.getRunDirIDs());
|
||||
}
|
||||
|
||||
// 步骤 2: 收集所有需要转换的 UUID(tagReq + 旧参数兼容)
|
||||
Set<String> allUuids = new HashSet<>();
|
||||
TagReq tagReq = getSimulationTaskFileReq.getTagReq();
|
||||
if (ObjectUtils.isNotEmpty(tagReq)) {
|
||||
collectTagUuids(allUuids, tagReq.getTag1(), tagReq.getTag2(), tagReq.getTag3(), tagReq.getTag4(), tagReq.getTag5(),
|
||||
tagReq.getTag6(), tagReq.getTag7(), tagReq.getTag8(), tagReq.getTag9(), tagReq.getTag10(),
|
||||
tagReq.getTaskId(), tagReq.getRunId());
|
||||
}
|
||||
|
||||
|
||||
// 步骤 3: 兼容处理旧的单个 uuid 和 dirId 字段,uuid 优先
|
||||
if (ObjectUtils.isNotEmpty(getSimulationTaskFileReq.getUuid())) {
|
||||
allUuids.add(getSimulationTaskFileReq.getUuid());
|
||||
FileMetadataInfo fileMetadataInfo = fileMetadataInfoService.lambdaQuery()
|
||||
.eq(FileMetadataInfo::getRelatedResourceUuid, getSimulationTaskFileReq.getUuid())
|
||||
.eq(FileMetadataInfo::getTenantId, ThreadLocalContext.getTenantId())
|
||||
.one();
|
||||
if (ObjectUtils.isNotEmpty(fileMetadataInfo)) {
|
||||
queryBigFileReq.setDirId(fileMetadataInfo.getId());
|
||||
} else {
|
||||
log.error("未找到对应的 UUID 对应的目录");
|
||||
public SdmResponse<PageDataResp<List<SimulationTaskResultCurveResp>>> getSimulationTaskFile(GetSimulationTaskFileReq req) {
|
||||
// level=task 保留现有目录直查逻辑
|
||||
if (NodeTypeEnum.TASK.getValue().equals(req.getLevel())) {
|
||||
Long taskDirId = resolveTaskDirId(req);
|
||||
if (ObjectUtils.isEmpty(taskDirId)) {
|
||||
return PageUtils.getJsonObjectSdmResponse(new ArrayList<>(), new PageInfo<>());
|
||||
}
|
||||
} else if (ObjectUtils.isNotEmpty(getSimulationTaskFileReq.getDirId())) {
|
||||
allDirIds.add(getSimulationTaskFileReq.getDirId());
|
||||
QueryBigFileReq queryBigFileReq = new QueryBigFileReq();
|
||||
queryBigFileReq.setDirId(taskDirId);
|
||||
return getTaskLevelFile(req, queryBigFileReq);
|
||||
}
|
||||
|
||||
// 步骤 4: 批量转换所有收集到的 UUID 并合并
|
||||
if (CollectionUtils.isNotEmpty(allUuids)) {
|
||||
List<Long> dirIdsFromUuids = fileMetadataInfoService.lambdaQuery()
|
||||
.in(FileMetadataInfo::getRelatedResourceUuid, allUuids)
|
||||
.eq(FileMetadataInfo::getTenantId, ThreadLocalContext.getTenantId())
|
||||
.list().stream().map(FileMetadataInfo::getId).collect(Collectors.toList());
|
||||
|
||||
// 因为是交集查询,如果传入了任何UUID,但一个对应的目录都找不到,那么最终结果必定为空。
|
||||
// 直接返回空集可以避免无效的数据库查询。
|
||||
if (CollectionUtils.isEmpty(dirIdsFromUuids)) {
|
||||
log.warn("根据传入的 UUIDs 未找到任何对应的目录: {}", allUuids);
|
||||
List<Long> fileIdsByDictTags = null;
|
||||
if (CollectionUtils.isNotEmpty(req.getDictTags())) {
|
||||
fileIdsByDictTags = extractFileIdsByTags(req);
|
||||
if (CollectionUtils.isEmpty(fileIdsByDictTags)) {
|
||||
return PageUtils.getJsonObjectSdmResponse(new ArrayList<>(), new PageInfo<>());
|
||||
}
|
||||
allDirIds.addAll(dirIdsFromUuids);
|
||||
}
|
||||
|
||||
queryBigFileReq.setDirIds(allDirIds);
|
||||
if (CollectionUtils.isNotEmpty(allDirIds)) {
|
||||
queryBigFileReq.setDirIdsCount(allDirIds.size());
|
||||
}
|
||||
|
||||
// 查询层级是task 只查task目录下的直系文件
|
||||
if (NodeTypeEnum.TASK.getValue().equals(getSimulationTaskFileReq.getLevel())) {
|
||||
return getTaskLevelFile(getSimulationTaskFileReq, queryBigFileReq);
|
||||
PageHelper.startPage(req.getCurrent(), req.getSize());
|
||||
var wrapper = fileMetadataInfoService.lambdaQuery()
|
||||
.eq(FileMetadataInfo::getTenantId, ThreadLocalContext.getTenantId())
|
||||
.isNull(FileMetadataInfo::getDeletedAt)
|
||||
.eq(FileMetadataInfo::getIsLatest, true);
|
||||
|
||||
if (CollectionUtils.isNotEmpty(fileIdsByDictTags)) {
|
||||
wrapper.in(FileMetadataInfo::getId, fileIdsByDictTags);
|
||||
}
|
||||
|
||||
// 2. 调用大文件查询服务
|
||||
SdmResponse<PageDataResp<List<FileStorage>>> searchResult = dataStorageAnalysis.listBigFile(queryBigFileReq);
|
||||
PageDataResp<List<FileStorage>> pageDataResp = searchResult.getData();
|
||||
List<FileStorage> fileStorages = pageDataResp.getData();
|
||||
|
||||
// 如果数据为空,提前返回
|
||||
if (CollectionUtils.isEmpty(fileStorages)) {
|
||||
return PageUtils.getJsonObjectSdmResponse(new ArrayList<>(), new PageInfo<>());
|
||||
if (StringUtils.isNotBlank(req.getFileName())) {
|
||||
wrapper.like(FileMetadataInfo::getOriginalName, req.getFileName());
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(req.getUploadUserId())) {
|
||||
wrapper.in(FileMetadataInfo::getCreatorId, req.getUploadUserId());
|
||||
}
|
||||
if (ObjectUtils.isNotEmpty(req.getStartTime())) {
|
||||
wrapper.ge(FileMetadataInfo::getCreateTime, req.getStartTime());
|
||||
}
|
||||
if (ObjectUtils.isNotEmpty(req.getEndTime())) {
|
||||
wrapper.le(FileMetadataInfo::getCreateTime, req.getEndTime());
|
||||
}
|
||||
|
||||
// 3. 一站式处理:获取文件元数据、构建父目录缓存、转换为响应对象并设置层级信息
|
||||
List<Long> fileIdList = fileStorages.stream().map(FileStorage::getFileId).toList();
|
||||
List<SimulationTaskResultCurveResp> finalResultList = hierarchyHelper.processFileHierarchy(
|
||||
fileIdList,
|
||||
SimulationTaskResultCurveResp.class,
|
||||
(resp, folder, ownType) -> {
|
||||
}
|
||||
);
|
||||
// 所属项目、阶段、机台、工位、任务、算列
|
||||
applyTagFilters(wrapper, req.getTagReq());
|
||||
|
||||
setTagReqForSimulationResult(finalResultList, fileIdList);
|
||||
List<FileMetadataInfo> fileMetadataInfos = wrapper.orderByDesc(FileMetadataInfo::getCreateTime).list();
|
||||
PageInfo<FileMetadataInfo> page = new PageInfo<>(fileMetadataInfos);
|
||||
|
||||
// 4. 构造分页信息并返回
|
||||
PageInfo<FileMetadataInfo> pageInfo = new PageInfo<>();
|
||||
pageInfo.setTotal(pageDataResp.getTotal());
|
||||
pageInfo.setPageNum(pageDataResp.getCurrentPage());
|
||||
pageInfo.setPageSize(pageDataResp.getPageSize());
|
||||
List<SimulationTaskResultCurveResp> finalResultList = fileMetadataInfos.stream().map(file -> {
|
||||
SimulationTaskResultCurveResp resp = new SimulationTaskResultCurveResp();
|
||||
BeanUtils.copyProperties(file, resp);
|
||||
hierarchyHelper.setTagReqFromFileMetadata(file, resp);
|
||||
return resp;
|
||||
}).toList();
|
||||
|
||||
PageInfo<SimulationTaskResultCurveResp> pageInfo = new PageInfo<>(finalResultList);
|
||||
pageInfo.setTotal(page.getTotal());
|
||||
pageInfo.setPageNum(page.getPageNum());
|
||||
pageInfo.setPageSize(page.getPageSize());
|
||||
|
||||
return PageUtils.getJsonObjectSdmResponse(finalResultList, pageInfo);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 复用listBigFile的逻辑:在目录范围内根据dictTags筛出文件ID
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
Set<Integer> tagIds = new HashSet<>();
|
||||
for (Map<String, Integer> valueMap : dictIdMap.values()) {
|
||||
tagIds.addAll(valueMap.values());
|
||||
}
|
||||
if (CollectionUtils.isEmpty(tagIds)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return fileTagRelService.lambdaQuery()
|
||||
.eq(FileTagRel::getTenantId, ThreadLocalContext.getTenantId())
|
||||
.in(FileTagRel::getTagId, tagIds)
|
||||
.select(FileTagRel::getFileId)
|
||||
.list()
|
||||
.stream()
|
||||
.map(FileTagRel::getFileId)
|
||||
.distinct()
|
||||
.toList();
|
||||
}
|
||||
|
||||
private void applyTagFilters(LambdaQueryChainWrapper<FileMetadataInfo> wrapper, TagReq tagReq) {
|
||||
if (ObjectUtils.isEmpty(tagReq)) {
|
||||
return;
|
||||
}
|
||||
// tag1-tag10 可能是逗号拼接链,按“最后一个值是当前层级值”过滤
|
||||
inByCurrentLevelCsv(wrapper, FileMetadataInfo::getTag1, tagReq.getTag1());
|
||||
inByCurrentLevelCsv(wrapper, FileMetadataInfo::getTag2, tagReq.getTag2());
|
||||
inByCurrentLevelCsv(wrapper, FileMetadataInfo::getTag3, tagReq.getTag3());
|
||||
inByCurrentLevelCsv(wrapper, FileMetadataInfo::getTag4, tagReq.getTag4());
|
||||
inByCurrentLevelCsv(wrapper, FileMetadataInfo::getTag5, tagReq.getTag5());
|
||||
inByCurrentLevelCsv(wrapper, FileMetadataInfo::getTag6, tagReq.getTag6());
|
||||
inByCurrentLevelCsv(wrapper, FileMetadataInfo::getTag7, tagReq.getTag7());
|
||||
inByCurrentLevelCsv(wrapper, FileMetadataInfo::getTag8, tagReq.getTag8());
|
||||
inByCurrentLevelCsv(wrapper, FileMetadataInfo::getTag9, tagReq.getTag9());
|
||||
inByCurrentLevelCsv(wrapper, FileMetadataInfo::getTag10, tagReq.getTag10());
|
||||
|
||||
// task/run 按普通IN过滤
|
||||
inByCsv(wrapper, FileMetadataInfo::getTaskId, tagReq.getTaskId());
|
||||
inByCsv(wrapper, FileMetadataInfo::getRunId, tagReq.getRunId());
|
||||
}
|
||||
|
||||
/**
|
||||
* 同列多选:IN;用于普通单值字段(taskId/runId)
|
||||
*/
|
||||
private <R> void inByCsv(LambdaQueryChainWrapper<FileMetadataInfo> wrapper,
|
||||
SFunction<FileMetadataInfo, R> column,
|
||||
String csvValue) {
|
||||
List<String> values = parseCsv(csvValue);
|
||||
if (CollectionUtils.isNotEmpty(values)) {
|
||||
wrapper.in(column, values);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* tag字段可能存为 "a,b,c",当前层级值是最后一个 c
|
||||
* 过滤条件:column = v OR column LIKE '%,v'
|
||||
*/
|
||||
private <R> void inByCurrentLevelCsv(LambdaQueryChainWrapper<FileMetadataInfo> wrapper,
|
||||
SFunction<FileMetadataInfo, R> column,
|
||||
String csvValue) {
|
||||
List<String> values = parseCsv(csvValue);
|
||||
if (CollectionUtils.isEmpty(values)) {
|
||||
return;
|
||||
}
|
||||
|
||||
wrapper.and(q -> {
|
||||
for (int i = 0; i < values.size(); i++) {
|
||||
String value = values.get(i);
|
||||
if (i > 0) {
|
||||
q.or();
|
||||
}
|
||||
q.and(one -> one.eq(column, value).or().likeLeft(column, "," + value));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private List<String> parseCsv(String value) {
|
||||
if (StringUtils.isBlank(value)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return Arrays.stream(value.split(","))
|
||||
.map(String::trim)
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.distinct()
|
||||
.toList();
|
||||
}
|
||||
|
||||
private Long resolveTaskDirId(GetSimulationTaskFileReq req) {
|
||||
if (ObjectUtils.isNotEmpty(req.getDirId())) {
|
||||
return req.getDirId();
|
||||
}
|
||||
TagReq tagReq = req.getTagReq();
|
||||
if (ObjectUtils.isNotEmpty(tagReq) && StringUtils.isNotBlank(tagReq.getTaskId())) {
|
||||
List<String> taskIds = parseCsv(tagReq.getTaskId());
|
||||
String targetTaskId = CollectionUtils.isNotEmpty(taskIds) ? taskIds.get(taskIds.size() - 1) : null;
|
||||
if (StringUtils.isNotBlank(targetTaskId)) {
|
||||
FileMetadataInfo fileMetadataInfo = fileMetadataInfoService.lambdaQuery()
|
||||
.eq(FileMetadataInfo::getTenantId, ThreadLocalContext.getTenantId())
|
||||
.eq(FileMetadataInfo::getRelatedResourceUuid, targetTaskId)
|
||||
.isNull(FileMetadataInfo::getDeletedAt)
|
||||
.one();
|
||||
if (ObjectUtils.isNotEmpty(fileMetadataInfo)) {
|
||||
return fileMetadataInfo.getId();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void setTagReqForSimulationResult(List<SimulationTaskResultCurveResp> resultList, List<Long> fileIdList) {
|
||||
if (CollectionUtils.isEmpty(resultList) || CollectionUtils.isEmpty(fileIdList)) {
|
||||
return;
|
||||
@@ -196,25 +271,6 @@ public class DataAnalysisServiceImpl implements IDataAnalysisService {
|
||||
}
|
||||
}
|
||||
|
||||
private void collectTagUuids(Set<String> allUuids, String... values) {
|
||||
if (ObjectUtils.isEmpty(values)) {
|
||||
return;
|
||||
}
|
||||
for (String value : values) {
|
||||
parseUuidChain(value).forEach(allUuids::add);
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> parseUuidChain(String uuidChain) {
|
||||
if (StringUtils.isBlank(uuidChain)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return Arrays.stream(uuidChain.split(","))
|
||||
.map(String::trim)
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.toList();
|
||||
}
|
||||
|
||||
private SdmResponse<PageDataResp<List<SimulationTaskResultCurveResp>>> getTaskLevelFile(GetSimulationTaskFileReq req, QueryBigFileReq queryBigFileReq) {
|
||||
// level=task,查task下的交付物文件夹 再根据fileType查具体的云图文件、曲线文件夹下的文件
|
||||
List<FileMetadataInfo> deliverableFileInfoList = fileMetadataInfoService.lambdaQuery()
|
||||
|
||||
@@ -360,8 +360,11 @@ public class FileMetadataHierarchyHelper {
|
||||
|
||||
for (int i = 1; i <= 10; i++) {
|
||||
String tagValue = tagValues.get(i - 1);
|
||||
String currentUuid = getLastUuid(tagValue);
|
||||
String tagName = uuidNameMap.get(currentUuid);
|
||||
List<String> uuidChain = parseUuidChain(tagValue);
|
||||
String tagName = uuidChain.stream()
|
||||
.map(uuidNameMap::get)
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.collect(Collectors.joining("-"));
|
||||
tagReqClass.getMethod("setTag" + i + "Name", String.class).invoke(tagReq, tagName);
|
||||
}
|
||||
tagReqClass.getMethod("setTaskName", String.class).invoke(tagReq, uuidNameMap.get(taskId));
|
||||
@@ -386,15 +389,4 @@ public class FileMetadataHierarchyHelper {
|
||||
.toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取逗号拼接uuid链中的最后一个uuid(当前节点)
|
||||
*/
|
||||
private String getLastUuid(String uuidChain) {
|
||||
List<String> uuids = parseUuidChain(uuidChain);
|
||||
if (CollectionUtils.isEmpty(uuids)) {
|
||||
return null;
|
||||
}
|
||||
return uuids.get(uuids.size() - 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user