From 3d361502b66e00474a42ef03569664956ed8f748 Mon Sep 17 00:00:00 2001 From: gulongcheng <474084054@qq.com> Date: Wed, 4 Feb 2026 15:22:46 +0800 Subject: [PATCH 1/7] =?UTF-8?q?fix:=E4=BC=98=E5=8C=96=E6=A0=87=E7=AD=BE?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../impl/MinioFileIDataFileServiceImpl.java | 43 +++++++++++++------ 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/data/src/main/java/com/sdm/data/service/impl/MinioFileIDataFileServiceImpl.java b/data/src/main/java/com/sdm/data/service/impl/MinioFileIDataFileServiceImpl.java index 5479b288..8cf9b7d8 100644 --- a/data/src/main/java/com/sdm/data/service/impl/MinioFileIDataFileServiceImpl.java +++ b/data/src/main/java/com/sdm/data/service/impl/MinioFileIDataFileServiceImpl.java @@ -2118,7 +2118,9 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService { /** * 批量填充文件标签信息到 FileMetadataInfoResp * 从 file_tag_rel 和 simulation_data_dictionary 查询标签,按 dictClass 分组 - * 格式:disciplineTypeDictClass: DISCIPLINE_TYPE, disciplineDictValue: '流体,机器人,动画' + * 格式: + * disciplineTypeDictClass: DISCIPLINE_TYPE, + * disciplineDictValue: '流体,机器人,动画' * * @param dtoList 文件元数据响应列表 */ @@ -2139,12 +2141,14 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService { return; } - // 2. 批量查询 file_tag_rel 获取文件对应的 tagId - List fileTagRels = fileTagRelService.lambdaQuery() - .eq(FileTagRel::getTenantId, tenantId) - .in(FileTagRel::getFileId, fileIds) - .select(FileTagRel::getFileId, FileTagRel::getTagId) - .list(); + // 2. 批量查询 file_tag_rel 获取文件对应的 tagId(数据库层去重) + // 注意:因为冗余记录了祖先父目录id,会导致 (fileId, tagId) 组合重复,需要在查询时去重 + List fileTagRels = fileTagRelService.getBaseMapper().selectList( + Wrappers.query() + .select("DISTINCT fileId, tagId") + .eq("tenantId", tenantId) + .in("fileId", fileIds) + ); if (CollectionUtils.isEmpty(fileTagRels)) { return; @@ -2183,16 +2187,11 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService { (v1, v2) -> v1 )); - // 6. 构建 fileId -> tagIds 的映射(tagId 去重) + // 6. 构建 fileId -> tagIds 的映射(数据库已去重,直接使用 toList) Map> fileToTagsMap = fileTagRels.stream() .collect(Collectors.groupingBy( FileTagRel::getFileId, - Collectors.mapping(FileTagRel::getTagId, Collectors.toSet()) - )) - .entrySet().stream() - .collect(Collectors.toMap( - Map.Entry::getKey, - entry -> new ArrayList<>(entry.getValue()) + Collectors.mapping(FileTagRel::getTagId, Collectors.toList()) )); // 7. 为每个文件填充标签信息 @@ -2554,6 +2553,22 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService { fileMetadataInfo.setUpdateTime(LocalDateTime.now()); fileMetadataInfo.setUpdaterId(ThreadLocalContext.getUserId()); fileMetadataInfo.setFileType(req.getFileType()); + + //绑定文件和工况库的关系 + if (CollectionUtils.isNotEmpty(req.getSimulationPoolInfoList())) { + // 先删除原先所有的文件绑定关系 + fileSimulationMappingService.lambdaUpdate().eq(FileSimulationMapping::getFileId, fileMetadataInfo.getId()).remove(); + for (SimulationPoolInfo simulationPoolInfo : req.getSimulationPoolInfoList()) { + for (String simulationPoolTaskId : simulationPoolInfo.getSimulationPoolTaskIds()) { + FileSimulationMapping fileSimulationMapping = new FileSimulationMapping(); + fileSimulationMapping.setFileId(fileMetadataInfo.getId()); + fileSimulationMapping.setSimulationPoolId(simulationPoolInfo.getSimulationPoolId()); + fileSimulationMapping.setSimulationPoolVersion(simulationPoolInfo.getSimulationPoolVersion()); + fileSimulationMapping.setSimulationPoolTaskId(simulationPoolTaskId); + fileSimulationMappingService.save(fileSimulationMapping); + } + } + } // 更新标签(如果有) if (CollectionUtils.isNotEmpty(req.getDictTags())) { From 08ffd8bc65ab245a5082874932eaddb4277eba3a Mon Sep 17 00:00:00 2001 From: gulongcheng <474084054@qq.com> Date: Wed, 4 Feb 2026 15:57:36 +0800 Subject: [PATCH 2/7] =?UTF-8?q?fix:=E5=B0=81=E8=A3=85=E6=A0=87=E7=AD=BE?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/model/dto/FileDictTagsAggDTO.java | 31 +++ .../service/IFileDictTagQueryService.java | 21 ++ .../impl/FileDictTagQueryServiceImpl.java | 139 +++++++++++ .../impl/MinioFileIDataFileServiceImpl.java | 224 +++++------------- 4 files changed, 244 insertions(+), 171 deletions(-) create mode 100644 data/src/main/java/com/sdm/data/model/dto/FileDictTagsAggDTO.java create mode 100644 data/src/main/java/com/sdm/data/service/IFileDictTagQueryService.java create mode 100644 data/src/main/java/com/sdm/data/service/impl/FileDictTagQueryServiceImpl.java diff --git a/data/src/main/java/com/sdm/data/model/dto/FileDictTagsAggDTO.java b/data/src/main/java/com/sdm/data/model/dto/FileDictTagsAggDTO.java new file mode 100644 index 00000000..21800907 --- /dev/null +++ b/data/src/main/java/com/sdm/data/model/dto/FileDictTagsAggDTO.java @@ -0,0 +1,31 @@ +package com.sdm.data.model.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; + +/** + * 文件字典标签聚合结果(按 fileId 聚合) + */ +@Data +@Schema(name = "FileDictTagsAggDTO", description = "文件字典标签聚合结果(按 fileId 聚合)") +public class FileDictTagsAggDTO implements Serializable { + private static final long serialVersionUID = 1L; + + @Schema(description = "文件ID") + private Long fileId; + + @Schema(description = "文件类型字典类") + private String fileTypeDictClass; + + @Schema(description = "文件类型字典值(逗号分隔)") + private String fileTypeDictValue; + + @Schema(description = "学科类型字典类") + private String disciplineTypeDictClass; + + @Schema(description = "学科类型字典值(逗号分隔)") + private String disciplineDictValue; +} + diff --git a/data/src/main/java/com/sdm/data/service/IFileDictTagQueryService.java b/data/src/main/java/com/sdm/data/service/IFileDictTagQueryService.java new file mode 100644 index 00000000..04379bde --- /dev/null +++ b/data/src/main/java/com/sdm/data/service/IFileDictTagQueryService.java @@ -0,0 +1,21 @@ +package com.sdm.data.service; + +import com.sdm.data.model.dto.FileDictTagsAggDTO; + +import java.util.List; +import java.util.Map; + +/** + * 文件字典标签聚合查询服务 + * 输入 fileIds,返回每个文件对应的 dictClass/dictValue 聚合结果 + */ +public interface IFileDictTagQueryService { + + /** + * 按文件ID批量查询并聚合字典标签 + * @param fileIds 文件ID列表 + * @return fileId -> 聚合结果 + */ + Map queryByFileIds(List fileIds); +} + diff --git a/data/src/main/java/com/sdm/data/service/impl/FileDictTagQueryServiceImpl.java b/data/src/main/java/com/sdm/data/service/impl/FileDictTagQueryServiceImpl.java new file mode 100644 index 00000000..5c7c147b --- /dev/null +++ b/data/src/main/java/com/sdm/data/service/impl/FileDictTagQueryServiceImpl.java @@ -0,0 +1,139 @@ +package com.sdm.data.service.impl; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.sdm.common.common.SdmResponse; +import com.sdm.common.common.ThreadLocalContext; +import com.sdm.common.entity.bo.DataDictionary; +import com.sdm.common.entity.enums.FileDictTagEnum; +import com.sdm.common.entity.req.system.DictTagReq; +import com.sdm.common.feign.inter.system.ISysConfigFeignClient; +import com.sdm.data.model.dto.FileDictTagsAggDTO; +import com.sdm.data.model.entity.FileTagRel; +import com.sdm.data.service.IFileDictTagQueryService; +import com.sdm.data.service.IFileTagRelService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * 文件字典标签聚合查询服务实现 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class FileDictTagQueryServiceImpl implements IFileDictTagQueryService { + + private final IFileTagRelService fileTagRelService; + private final ISysConfigFeignClient sysConfigFeignClient; + + @Override + public Map queryByFileIds(List fileIds) { + if (CollectionUtils.isEmpty(fileIds)) { + return Collections.emptyMap(); + } + + Long tenantId = ThreadLocalContext.getTenantId(); + + // 1) file_tag_rel: DISTINCT fileId, tagId(因冗余祖先目录导致重复) + List fileTagRels = fileTagRelService.getBaseMapper().selectList( + Wrappers.query() + .select("DISTINCT fileId, tagId") + .eq("tenantId", tenantId) + .in("fileId", fileIds) + ); + if (CollectionUtils.isEmpty(fileTagRels)) { + return Collections.emptyMap(); + } + + // 2) 提取 tagId 并批量查字典 + List tagIds = fileTagRels.stream() + .map(FileTagRel::getTagId) + .filter(Objects::nonNull) + .distinct() + .toList(); + if (CollectionUtils.isEmpty(tagIds)) { + return Collections.emptyMap(); + } + + DictTagReq.BatchDictQueryReq batchReq = new DictTagReq.BatchDictQueryReq(); + batchReq.setItems(tagIds.stream().map(tagId -> { + DictTagReq req = new DictTagReq(); + req.setDictId(tagId); + return req; + }).collect(Collectors.toList())); + + SdmResponse> response = sysConfigFeignClient.batchQueryDictionaries(batchReq); + if (response == null || !response.isSuccess() || CollectionUtils.isEmpty(response.getData())) { + log.warn("Batch query dictionaries failed or returned empty, fileIds: {}", fileIds); + return Collections.emptyMap(); + } + + Map tagIdToDictMap = response.getData().stream() + .filter(d -> d != null && d.id != null) + .collect(Collectors.toMap( + d -> d.id, + Function.identity(), + (v1, v2) -> v1 + )); + + // 3) fileId -> (dictClass -> Set) + Map>> agg = new HashMap<>(); + for (FileTagRel rel : fileTagRels) { + if (rel == null || rel.getFileId() == null || rel.getTagId() == null) { + continue; + } + DataDictionary dict = tagIdToDictMap.get(rel.getTagId()); + if (dict == null || dict.dictClass == null || dict.dictValue == null) { + continue; + } + if (!FileDictTagEnum.isConfigured(dict.dictClass)) { + continue; + } + agg.computeIfAbsent(rel.getFileId(), k -> new HashMap<>()) + .computeIfAbsent(dict.dictClass, k -> new LinkedHashSet<>()) + .add(dict.dictValue); + } + + if (agg.isEmpty()) { + return Collections.emptyMap(); + } + + // 4) 转为 DTO(目前只输出枚举配置的两类字段) + Map result = new HashMap<>(); + for (Map.Entry>> e : agg.entrySet()) { + Long fileId = e.getKey(); + Map> classMap = e.getValue(); + if (classMap == null || classMap.isEmpty()) { + continue; + } + + FileDictTagsAggDTO dto = new FileDictTagsAggDTO(); + dto.setFileId(fileId); + + for (Map.Entry> classEntry : classMap.entrySet()) { + String dictClass = classEntry.getKey(); + String dictValues = String.join(",", classEntry.getValue()); + FileDictTagEnum tagEnum = FileDictTagEnum.getByDictClass(dictClass); + if (tagEnum == null) { + continue; + } + if (tagEnum == FileDictTagEnum.FILE_TYPE) { + dto.setFileTypeDictClass(tagEnum.getDictClass()); + dto.setFileTypeDictValue(dictValues); + } else if (tagEnum == FileDictTagEnum.DISCIPLINE_TYPE) { + dto.setDisciplineTypeDictClass(tagEnum.getDictClass()); + dto.setDisciplineDictValue(dictValues); + } + } + result.put(fileId, dto); + } + + return result; + } +} + diff --git a/data/src/main/java/com/sdm/data/service/impl/MinioFileIDataFileServiceImpl.java b/data/src/main/java/com/sdm/data/service/impl/MinioFileIDataFileServiceImpl.java index 8cf9b7d8..88b4f132 100644 --- a/data/src/main/java/com/sdm/data/service/impl/MinioFileIDataFileServiceImpl.java +++ b/data/src/main/java/com/sdm/data/service/impl/MinioFileIDataFileServiceImpl.java @@ -12,14 +12,12 @@ import com.google.common.collect.Sets; import com.sdm.common.common.SdmResponse; import com.sdm.common.common.ThreadLocalContext; import com.sdm.common.entity.ExportExcelFormat; -import com.sdm.common.entity.bo.DataDictionary; import com.sdm.common.entity.constants.NumberConstants; import com.sdm.common.entity.constants.PermConstants; import com.sdm.common.entity.enums.*; import com.sdm.common.entity.pojo.task.TaskBaseInfo; import com.sdm.common.entity.req.data.*; import com.sdm.common.entity.req.project.SpdmNodeListReq; -import com.sdm.common.entity.req.system.DictTagReq; import com.sdm.common.entity.req.system.LaunchApproveReq; import com.sdm.common.entity.req.system.UserListReq; import com.sdm.common.entity.req.system.UserQueryReq; @@ -28,7 +26,6 @@ import com.sdm.common.entity.resp.data.*; import com.sdm.common.entity.resp.project.SimulationNodeResp; import com.sdm.common.entity.resp.system.CIDUserResp; import com.sdm.common.feign.impl.project.SimulationNodeFeignClientImpl; -import com.sdm.common.feign.impl.system.SysConfigFeignClientImpl; import com.sdm.common.feign.impl.system.SysUserFeignClientImpl; import com.sdm.common.feign.inter.project.ISimulationNodeFeignClient; import com.sdm.common.feign.inter.system.IApproveFeignClient; @@ -40,6 +37,7 @@ import com.sdm.common.utils.excel.ExcelUtil; import com.sdm.data.aop.PermissionCheckAspect; import com.sdm.data.model.bo.ApprovalFileDataContentsModel; import com.sdm.data.model.dto.ExportKnowledgeDto; +import com.sdm.data.model.dto.FileDictTagsAggDTO; import com.sdm.data.model.entity.*; import com.sdm.data.model.enums.ApproveFileActionENUM; import com.sdm.data.model.req.*; @@ -137,6 +135,9 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService { @Autowired private IFileTagRelService fileTagRelService; + @Autowired + private IFileDictTagQueryService fileDictTagQueryService; + @Autowired ISimulationParameterLibraryCategoryObjectService paramObjectService; @@ -890,9 +891,8 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService { dto.setKnowledgeBaseName(knowledgeBaseName); return dto; }).collect(Collectors.toList()); - - // 批量填充文件标签信息 - fillFileTags(dtoList); + + fillFileTagsToDtos(dtoList); PageInfo page1 = new PageInfo<>(dtoList); page1.setTotal(total); return PageUtils.getJsonObjectSdmResponse(dtoList, page1); @@ -2115,187 +2115,69 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService { } } + + + /** + * 批量填充文件标签信息到 dtoList(只处理 dataType=FILE 的 dto) + */ + private void fillFileTagsToDtos(List dtoList) { + if (CollectionUtils.isEmpty(dtoList)) { + return; + } + + List fileIdsForTagQuery = dtoList.stream() + .filter(dto -> dto != null && dto.getId() != null && DataTypeEnum.FILE.getValue() == dto.getDataType()) + .map(FileMetadataInfoResp::getId) + .distinct() + .toList(); + + Map fileIdToTagsMap = fillFileTags(fileIdsForTagQuery); + if (MapUtils.isEmpty(fileIdToTagsMap)) { + return; + } + + for (FileMetadataInfoResp dto : dtoList) { + if (dto == null || dto.getId() == null || DataTypeEnum.FILE.getValue() != dto.getDataType()) { + continue; + } + FileDictTagsAggDTO tags = fileIdToTagsMap.get(dto.getId()); + if (tags == null) { + continue; + } + dto.setFileTypeDictClass(tags.getFileTypeDictClass()); + dto.setFileTypeDictValue(tags.getFileTypeDictValue()); + dto.setDisciplineTypeDictClass(tags.getDisciplineTypeDictClass()); + dto.setDisciplineDictValue(tags.getDisciplineDictValue()); + } + } + /** * 批量填充文件标签信息到 FileMetadataInfoResp * 从 file_tag_rel 和 simulation_data_dictionary 查询标签,按 dictClass 分组 * 格式: * disciplineTypeDictClass: DISCIPLINE_TYPE, * disciplineDictValue: '流体,机器人,动画' - * - * @param dtoList 文件元数据响应列表 + * + * @param fileIds 文件ID列表 + * @return fileId -> 标签聚合结果 */ - private void fillFileTags(List dtoList) { - if (CollectionUtils.isEmpty(dtoList)) { - return; - } - - Long tenantId = ThreadLocalContext.getTenantId(); - - // 1. 提取所有文件ID(只包含文件类型,排除目录) - List fileIds = dtoList.stream() - .filter(dto -> DataTypeEnum.FILE.getValue()==(dto.getDataType())) - .map(FileMetadataInfoResp::getId) - .collect(Collectors.toList()); - + private Map fillFileTags(List fileIds) { if (CollectionUtils.isEmpty(fileIds)) { - return; + return Collections.emptyMap(); } - - // 2. 批量查询 file_tag_rel 获取文件对应的 tagId(数据库层去重) - // 注意:因为冗余记录了祖先父目录id,会导致 (fileId, tagId) 组合重复,需要在查询时去重 - List fileTagRels = fileTagRelService.getBaseMapper().selectList( - Wrappers.query() - .select("DISTINCT fileId, tagId") - .eq("tenantId", tenantId) - .in("fileId", fileIds) - ); - - if (CollectionUtils.isEmpty(fileTagRels)) { - return; - } - - // 3. 提取所有 tagId - List tagIds = fileTagRels.stream() - .map(FileTagRel::getTagId) + List idList = fileIds.stream() + .filter(Objects::nonNull) .distinct() .toList(); - // 4. 批量查询 simulation_data_dictionary 获取标签详情 - List dictTagReqs = tagIds.stream() - .map(tagId -> { - DictTagReq req = new DictTagReq(); - req.setDictId(tagId); - return req; - }) - .collect(Collectors.toList()); - - DictTagReq.BatchDictQueryReq batchReq = new DictTagReq.BatchDictQueryReq(); - batchReq.setItems(dictTagReqs); - SdmResponse> response = sysConfigFeignClient.batchQueryDictionaries(batchReq); - - if (!response.isSuccess() || CollectionUtils.isEmpty(response.getData())) { - log.warn("Batch query dictionaries failed or returned empty"); - return; + if (CollectionUtils.isEmpty(idList)) { + return Collections.emptyMap(); } - // 5. 构建 tagId -> 字典信息的映射 - Map tagIdToDictMap = response.getData().stream() - .filter(dict -> dict.id != null) - .collect(Collectors.toMap( - dict -> dict.id, - dict -> dict, - (v1, v2) -> v1 - )); - - // 6. 构建 fileId -> tagIds 的映射(数据库已去重,直接使用 toList) - Map> fileToTagsMap = fileTagRels.stream() - .collect(Collectors.groupingBy( - FileTagRel::getFileId, - Collectors.mapping(FileTagRel::getTagId, Collectors.toList()) - )); - - // 7. 为每个文件填充标签信息 - for (FileMetadataInfoResp dto : dtoList) { - if (!(DataTypeEnum.FILE.getValue()==(dto.getDataType()))) { - continue; - } - - List fileTags = fileToTagsMap.get(dto.getId()); - if (CollectionUtils.isEmpty(fileTags)) { - continue; - } - - // 按 dictClass 分组,聚合 dictValue(只处理配置的 dictClass) - Map> classToDictValuesMap = new HashMap<>(); - - for (Integer tagId : fileTags) { - DataDictionary dictInfo = tagIdToDictMap.get(tagId); - if (dictInfo == null) { - continue; - } - - String dictClass = dictInfo.dictClass; - String dictValue = dictInfo.dictValue; - - // 只处理枚举中配置的 dictClass - if (dictClass != null && dictValue != null && FileDictTagEnum.isConfigured(dictClass)) { - classToDictValuesMap - .computeIfAbsent(dictClass, k -> new ArrayList<>()) - .add(dictValue); - } - } - - // 设置到 DTO 中(使用枚举配置) - for (Map.Entry> entry : classToDictValuesMap.entrySet()) { - String dictClass = entry.getKey(); - String dictValues = String.join(",", entry.getValue()); - - // 根据枚举配置设置对应的字段 - FileDictTagEnum tagEnum = FileDictTagEnum.getByDictClass(dictClass); - if (tagEnum != null) { - setDictTagFieldsByEnum(dto, tagEnum, dictValues); - } - } - } + Map map = fileDictTagQueryService.queryByFileIds(idList); + return MapUtils.isEmpty(map) ? Collections.emptyMap() : map; } - /** - * 根据枚举配置设置字典标签字段(推荐使用) - * 直接使用枚举配置的完整字段名,无需拼接 - * - * @param dto FileMetadataInfoResp 对象 - * @param tagEnum 字典标签枚举 - * @param dictValues 字典值(逗号分隔) - */ - private void setDictTagFieldsByEnum(FileMetadataInfoResp dto, FileDictTagEnum tagEnum, String dictValues) { - if (tagEnum == null || dictValues == null) { - return; - } - - String dictClass = tagEnum.getDictClass(); - String dictClassFieldName = tagEnum.getDictClassFieldName(); - String dictValueFieldName = tagEnum.getDictValueFieldName(); - - try { - // 设置 dictClass 字段 - Field dictClassField = findField(FileMetadataInfoResp.class, dictClassFieldName); - if (dictClassField != null) { - dictClassField.setAccessible(true); - dictClassField.set(dto, dictClass); - } else { - log.warn("Field '{}' not found in FileMetadataInfoResp, please add field for dictClass: {}", - dictClassFieldName, dictClass); - } - - // 设置 dictValue 字段 - Field dictValueField = findField(FileMetadataInfoResp.class, dictValueFieldName); - if (dictValueField != null) { - dictValueField.setAccessible(true); - dictValueField.set(dto, dictValues); - } else { - log.warn("Field '{}' not found in FileMetadataInfoResp, please add field for dictClass: {}", - dictValueFieldName, dictClass); - } - } catch (Exception e) { - log.warn("Failed to set dict tag fields for dictClass: {}, error: {}", dictClass, e.getMessage()); - } - } - - /** - * 在类及其父类中查找字段 - */ - private Field findField(Class clazz, String fieldName) { - while (clazz != null && clazz != Object.class) { - try { - return clazz.getDeclaredField(fieldName); - } catch (NoSuchFieldException e) { - clazz = clazz.getSuperclass(); - } - } - return null; - } - - private void bindSimulationPool(UploadFilesReq req, FileMetadataInfo fileInfo) { if (CollectionUtils.isEmpty(req.getSimulationPoolInfoList())) { return; From 3544bb704d87e367bdd2721150fba45a7b388d6d Mon Sep 17 00:00:00 2001 From: 15195 Date: Wed, 4 Feb 2026 15:59:07 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=E4=BF=AE=E6=94=B9=EF=BC=9Ahpc=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E5=A2=9E=E5=8A=A0=E4=BB=BB=E5=8A=A1=E6=AD=A3=E5=88=99?= =?UTF-8?q?=E7=AD=89=E7=9B=B8=E5=85=B3=E5=AD=97=E6=AE=B5=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/sdm/pbs/model/entity/SimulationJob.java | 6 +++--- .../com/sdm/pbs/service/impl/PbsServiceDecorator.java | 9 +++++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/pbs/src/main/java/com/sdm/pbs/model/entity/SimulationJob.java b/pbs/src/main/java/com/sdm/pbs/model/entity/SimulationJob.java index 172a3b77..bb896d3a 100644 --- a/pbs/src/main/java/com/sdm/pbs/model/entity/SimulationJob.java +++ b/pbs/src/main/java/com/sdm/pbs/model/entity/SimulationJob.java @@ -173,15 +173,15 @@ public class SimulationJob implements Serializable { @TableField("dirId") private Long dirId; - @Schema(description = "输入主文件正则") + @Schema(description = "输入主文件正则,params里取的base64的字符串") @TableField("inputFormat") private String inputFormat; - @Schema(description = "输入从文件正则") + @Schema(description = "输入从文件正则的base64的字符串") @TableField("slaveFormat") private String slaveFormat; - @Schema(description = "输出文件正则") + @Schema(description = "输出文件正则的base64的字符串") @TableField("outputFormat") private String outputFormat; diff --git a/pbs/src/main/java/com/sdm/pbs/service/impl/PbsServiceDecorator.java b/pbs/src/main/java/com/sdm/pbs/service/impl/PbsServiceDecorator.java index 18bf758d..805efd5c 100644 --- a/pbs/src/main/java/com/sdm/pbs/service/impl/PbsServiceDecorator.java +++ b/pbs/src/main/java/com/sdm/pbs/service/impl/PbsServiceDecorator.java @@ -288,8 +288,6 @@ public class PbsServiceDecorator implements IPbsServiceDecorator { simulationJob.setRunName(req.getRunName()); // 软件及文件关联 simulationJob.setSoftwareId(req.getSoftwareId()); - // 下面的待定 - // simulationJob.setInputFileId(null); simulationJob.setJobId(jobId); // 没必要要 // simulationJob.setJobDetailId(""); @@ -325,6 +323,13 @@ public class PbsServiceDecorator implements IPbsServiceDecorator { simulationJob.setUpdateTime(LocalDateTime.now()); // 当前节点minio的文件夹id simulationJob.setDirId(req.getDirId()); + + simulationJob.setInputFileId(req.getInputFileId()); + simulationJob.setInputFormat(req.getInputFormat()); + simulationJob.setSlaveFormat(req.getSlaveFormat()); + simulationJob.setOutputFormat(req.getOutputFormat()); + simulationJob.setProcessDefinitionId(req.getProcessDefinitionId()); + simulationJob.setProcessInstanceId(req.getProcessInstanceId()); simulationJobService.save(simulationJob); } } From 53c5d2f197d69b9a0ba9d52ff333a96c93488384 Mon Sep 17 00:00:00 2001 From: gulongcheng <474084054@qq.com> Date: Wed, 4 Feb 2026 16:48:24 +0800 Subject: [PATCH 4/7] =?UTF-8?q?fix:=E5=B0=81=E8=A3=85=E6=A0=87=E7=AD=BE?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/sdm/common/entity/resp/BaseResp.java | 15 ++++ .../resp/data/FileMetadataInfoResp.java | 15 ---- .../service/IFileDictTagQueryService.java | 16 ++-- .../service/impl/DataAnalysisServiceImpl.java | 10 ++- .../service/impl/DataStorageAnalysisImpl.java | 8 ++ .../impl/FileDictTagQueryServiceImpl.java | 77 ++++++++++++++++++- .../impl/MinioFileIDataFileServiceImpl.java | 72 +++-------------- 7 files changed, 122 insertions(+), 91 deletions(-) diff --git a/common/src/main/java/com/sdm/common/entity/resp/BaseResp.java b/common/src/main/java/com/sdm/common/entity/resp/BaseResp.java index 788163f4..8beb1f5a 100644 --- a/common/src/main/java/com/sdm/common/entity/resp/BaseResp.java +++ b/common/src/main/java/com/sdm/common/entity/resp/BaseResp.java @@ -56,4 +56,19 @@ public class BaseResp { @Schema(description= "文件业务类型(1:模型文件 2:仿真报告、3:计算文件、4:曲线文件、5:云图文件,6:网格文件,7:计算过程文件)") @TableField("fileType") private Integer fileType; + + // ---------------------------------------------------------------- + // 很重要,用于设置标签 + @Schema(description = "文件类型字典类") + private String fileTypeDictClass; + @Schema(description = "文件类型字典值") + private String fileTypeDictValue; + + @Schema(description = "学科类型字典类") + private String disciplineTypeDictClass; + + @Schema(description = "学科类型字典值") + private String disciplineDictValue; + + // ---------------------------------------------------------------- } diff --git a/common/src/main/java/com/sdm/common/entity/resp/data/FileMetadataInfoResp.java b/common/src/main/java/com/sdm/common/entity/resp/data/FileMetadataInfoResp.java index bba5aaeb..b7d85f38 100644 --- a/common/src/main/java/com/sdm/common/entity/resp/data/FileMetadataInfoResp.java +++ b/common/src/main/java/com/sdm/common/entity/resp/data/FileMetadataInfoResp.java @@ -63,21 +63,6 @@ public class FileMetadataInfoResp extends BaseResp implements Serializable { @Schema(description= "文件业务类型(1:模型文件 2:仿真报告、3:计算文件、4:曲线文件、5:云图文件,6:网格文件,7:计算过程文件)") private Integer fileType; - // ---------------------------------------------------------------- - // 很重要,用于设置标签 - @Schema(description = "文件类型字典类") - private String fileTypeDictClass; - @Schema(description = "文件类型字典值") - private String fileTypeDictValue; - - @Schema(description = "学科类型字典类") - private String disciplineTypeDictClass; - - @Schema(description = "学科类型字典值") - private String disciplineDictValue; - - // ---------------------------------------------------------------- - @Schema(description = "数据类型:1-文件,2-文件夹") private Integer dataType; diff --git a/data/src/main/java/com/sdm/data/service/IFileDictTagQueryService.java b/data/src/main/java/com/sdm/data/service/IFileDictTagQueryService.java index 04379bde..f9cc8541 100644 --- a/data/src/main/java/com/sdm/data/service/IFileDictTagQueryService.java +++ b/data/src/main/java/com/sdm/data/service/IFileDictTagQueryService.java @@ -1,9 +1,7 @@ package com.sdm.data.service; -import com.sdm.data.model.dto.FileDictTagsAggDTO; - import java.util.List; -import java.util.Map; +import java.util.function.Function; /** * 文件字典标签聚合查询服务 @@ -12,10 +10,14 @@ import java.util.Map; public interface IFileDictTagQueryService { /** - * 按文件ID批量查询并聚合字典标签 - * @param fileIds 文件ID列表 - * @return fileId -> 聚合结果 + * 泛型方法:为包含标签字段的响应对象列表批量填充文件字典标签 + * 要求 T 至少包含如下字段的 getter/setter: + * - getId() + * - setFileTypeDictClass(String) + * - setFileTypeDictValue(String) + * - setDisciplineTypeDictClass(String) + * - setDisciplineDictValue(String) */ - Map queryByFileIds(List fileIds); + void fillFileTagsForRespList(List respList, Function idGetter); } diff --git a/data/src/main/java/com/sdm/data/service/impl/DataAnalysisServiceImpl.java b/data/src/main/java/com/sdm/data/service/impl/DataAnalysisServiceImpl.java index d415173c..2089792d 100644 --- a/data/src/main/java/com/sdm/data/service/impl/DataAnalysisServiceImpl.java +++ b/data/src/main/java/com/sdm/data/service/impl/DataAnalysisServiceImpl.java @@ -21,10 +21,7 @@ import com.sdm.data.model.entity.FileStorage; import com.sdm.common.entity.req.data.GetSimulationTaskFileReq; import com.sdm.data.model.req.QueryBigFileReq; import com.sdm.common.entity.resp.data.SimulationTaskResultCurveResp; -import com.sdm.data.service.DataStorageAnalysis; -import com.sdm.data.service.IDataAnalysisService; -import com.sdm.data.service.IFileMetadataInfoService; -import com.sdm.data.service.IMinioService; +import com.sdm.data.service.*; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; @@ -60,6 +57,9 @@ public class DataAnalysisServiceImpl implements IDataAnalysisService { @Autowired private ExportOperate exportOperate; + @Autowired + IFileDictTagQueryService fileDictTagQueryService; + @Override public SdmResponse>> getSimulationTaskFile(GetSimulationTaskFileReq getSimulationTaskFileReq) { // 1. 构造查询条件 @@ -102,6 +102,8 @@ public class DataAnalysisServiceImpl implements IDataAnalysisService { FileMetadataHierarchyHelper::setFileHierarchy ); + fileDictTagQueryService.fillFileTagsForRespList(finalResultList, SimulationTaskResultCurveResp::getId); + // 4. 构造分页信息并返回 PageInfo pageInfo = new PageInfo<>(); pageInfo.setTotal(pageDataResp.getTotal()); diff --git a/data/src/main/java/com/sdm/data/service/impl/DataStorageAnalysisImpl.java b/data/src/main/java/com/sdm/data/service/impl/DataStorageAnalysisImpl.java index 80c4d643..2d4de926 100644 --- a/data/src/main/java/com/sdm/data/service/impl/DataStorageAnalysisImpl.java +++ b/data/src/main/java/com/sdm/data/service/impl/DataStorageAnalysisImpl.java @@ -31,6 +31,7 @@ import com.sdm.data.model.req.QueryBigFileReq; import com.sdm.data.model.resp.FileStorageQuotaResp; import com.sdm.data.model.resp.ListBigFileResp; import com.sdm.data.service.*; +import com.sdm.data.service.IFileDictTagQueryService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; @@ -77,6 +78,9 @@ public class DataStorageAnalysisImpl implements DataStorageAnalysis { @Autowired IFileTagRelService fileTagRelService; + @Autowired + IFileDictTagQueryService fileDictTagQueryService; + /** * 根据节点类型获取存储空间占用(支持批量查询) */ @@ -442,6 +446,9 @@ public class DataStorageAnalysisImpl implements DataStorageAnalysis { FileMetadataHierarchyHelper::setFileHierarchy ); + // 2.1 批量填充文件字典标签(文件类型、学科类型) + fileDictTagQueryService.fillFileTagsForRespList(finalResultList, ListBigFileResp::getId); + // 3. 构造分页信息并返回 PageInfo pageInfo = new PageInfo<>(); pageInfo.setTotal(pageDataResp.getTotal()); @@ -451,6 +458,7 @@ public class DataStorageAnalysisImpl implements DataStorageAnalysis { return PageUtils.getJsonObjectSdmResponse(finalResultList, pageInfo); } + @Override public SdmResponse>> listBigFile(QueryBigFileReq queryBigFileReq) { PageInfo fileStorages = getFileStorages(queryBigFileReq); diff --git a/data/src/main/java/com/sdm/data/service/impl/FileDictTagQueryServiceImpl.java b/data/src/main/java/com/sdm/data/service/impl/FileDictTagQueryServiceImpl.java index 5c7c147b..06676932 100644 --- a/data/src/main/java/com/sdm/data/service/impl/FileDictTagQueryServiceImpl.java +++ b/data/src/main/java/com/sdm/data/service/impl/FileDictTagQueryServiceImpl.java @@ -14,6 +14,7 @@ import com.sdm.data.service.IFileTagRelService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.MapUtils; import org.springframework.stereotype.Service; import java.util.*; @@ -31,8 +32,7 @@ public class FileDictTagQueryServiceImpl implements IFileDictTagQueryService { private final IFileTagRelService fileTagRelService; private final ISysConfigFeignClient sysConfigFeignClient; - @Override - public Map queryByFileIds(List fileIds) { + private Map queryByFileIds(List fileIds) { if (CollectionUtils.isEmpty(fileIds)) { return Collections.emptyMap(); } @@ -135,5 +135,76 @@ public class FileDictTagQueryServiceImpl implements IFileDictTagQueryService { return result; } -} + @Override + public void fillFileTagsForRespList(List respList, Function idGetter) { + if (CollectionUtils.isEmpty(respList)) { + return; + } + + // 收集文件ID + List fileIds = respList.stream() + .map(idGetter) + .filter(Objects::nonNull) + .distinct() + .toList(); + if (CollectionUtils.isEmpty(fileIds)) { + return; + } + + // 查询聚合标签 + Map fileIdToTagsMap = queryByFileIds(fileIds); + if (MapUtils.isEmpty(fileIdToTagsMap)) { + return; + } + + // 通过反射,将标签字段填充到 Resp 对象中(基于 FileDictTagEnum 的配置) + for (T resp : respList) { + Long fileId = idGetter.apply(resp); + if (fileId == null) { + continue; + } + FileDictTagsAggDTO tags = fileIdToTagsMap.get(fileId); + if (tags == null) { + continue; + } + for (FileDictTagEnum tagEnum : FileDictTagEnum.values()) { + String dictValues = getDictValuesByEnum(tags, tagEnum); + if (dictValues == null) { + continue; + } + String dictClass = tagEnum.getDictClass(); + String dictClassFieldName = tagEnum.getDictClassFieldName(); + String dictValueFieldName = tagEnum.getDictValueFieldName(); + try { + // setXxxDictClass + String classSetterName = "set" + Character.toUpperCase(dictClassFieldName.charAt(0)) + dictClassFieldName.substring(1); + resp.getClass().getMethod(classSetterName, String.class) + .invoke(resp, dictClass); + // setXxxDictValue + String valueSetterName = "set" + Character.toUpperCase(dictValueFieldName.charAt(0)) + dictValueFieldName.substring(1); + resp.getClass().getMethod(valueSetterName, String.class) + .invoke(resp, dictValues); + } catch (Exception e) { + log.warn("填充文件标签信息失败, fileId: {}, respClass: {}, dictClass: {}, error: {}", + fileId, resp.getClass().getName(), dictClass, e.getMessage()); + } + } + } + } + + /** + * 根据枚举类型,从聚合结果中取出对应的字典值 + */ + private String getDictValuesByEnum(FileDictTagsAggDTO tags, FileDictTagEnum tagEnum) { + if (tags == null || tagEnum == null) { + return null; + } + if (tagEnum == FileDictTagEnum.FILE_TYPE) { + return tags.getFileTypeDictValue(); + } else if (tagEnum == FileDictTagEnum.DISCIPLINE_TYPE) { + return tags.getDisciplineDictValue(); + } + return null; + } +} diff --git a/data/src/main/java/com/sdm/data/service/impl/MinioFileIDataFileServiceImpl.java b/data/src/main/java/com/sdm/data/service/impl/MinioFileIDataFileServiceImpl.java index 88b4f132..b4bae003 100644 --- a/data/src/main/java/com/sdm/data/service/impl/MinioFileIDataFileServiceImpl.java +++ b/data/src/main/java/com/sdm/data/service/impl/MinioFileIDataFileServiceImpl.java @@ -806,6 +806,11 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService { dto.setKnowledgeBaseName(extractRelativePath(fileMetadataInfoService.lambdaQuery().eq(FileMetadataInfo::getId, dto.getParentId()).one())); return dto; }).collect(Collectors.toList()); + // 批量填充文件标签信息(仅对文件类型生效) + List fileDtos = dtoList.stream() + .filter(dto -> dto != null && dto.getDataType() != null && DataTypeEnum.FILE.getValue() == dto.getDataType()) + .toList(); + fileDictTagQueryService.fillFileTagsForRespList(fileDtos, FileMetadataInfoResp::getId); PageDataResp> pageDataResp = searchResult.getData(); PageInfo page = new PageInfo(); page.setPageNum(pageDataResp.getCurrentPage()); @@ -892,7 +897,11 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService { return dto; }).collect(Collectors.toList()); - fillFileTagsToDtos(dtoList); + // 批量填充文件标签信息(仅对文件类型生效) + List fileDtos = dtoList.stream() + .filter(dto -> dto != null && dto.getDataType() != null && DataTypeEnum.FILE.getValue() == dto.getDataType()) + .toList(); + fileDictTagQueryService.fillFileTagsForRespList(fileDtos, FileMetadataInfoResp::getId); PageInfo page1 = new PageInfo<>(dtoList); page1.setTotal(total); return PageUtils.getJsonObjectSdmResponse(dtoList, page1); @@ -2117,67 +2126,6 @@ public class MinioFileIDataFileServiceImpl implements IDataFileService { - /** - * 批量填充文件标签信息到 dtoList(只处理 dataType=FILE 的 dto) - */ - private void fillFileTagsToDtos(List dtoList) { - if (CollectionUtils.isEmpty(dtoList)) { - return; - } - - List fileIdsForTagQuery = dtoList.stream() - .filter(dto -> dto != null && dto.getId() != null && DataTypeEnum.FILE.getValue() == dto.getDataType()) - .map(FileMetadataInfoResp::getId) - .distinct() - .toList(); - - Map fileIdToTagsMap = fillFileTags(fileIdsForTagQuery); - if (MapUtils.isEmpty(fileIdToTagsMap)) { - return; - } - - for (FileMetadataInfoResp dto : dtoList) { - if (dto == null || dto.getId() == null || DataTypeEnum.FILE.getValue() != dto.getDataType()) { - continue; - } - FileDictTagsAggDTO tags = fileIdToTagsMap.get(dto.getId()); - if (tags == null) { - continue; - } - dto.setFileTypeDictClass(tags.getFileTypeDictClass()); - dto.setFileTypeDictValue(tags.getFileTypeDictValue()); - dto.setDisciplineTypeDictClass(tags.getDisciplineTypeDictClass()); - dto.setDisciplineDictValue(tags.getDisciplineDictValue()); - } - } - - /** - * 批量填充文件标签信息到 FileMetadataInfoResp - * 从 file_tag_rel 和 simulation_data_dictionary 查询标签,按 dictClass 分组 - * 格式: - * disciplineTypeDictClass: DISCIPLINE_TYPE, - * disciplineDictValue: '流体,机器人,动画' - * - * @param fileIds 文件ID列表 - * @return fileId -> 标签聚合结果 - */ - private Map fillFileTags(List fileIds) { - if (CollectionUtils.isEmpty(fileIds)) { - return Collections.emptyMap(); - } - List idList = fileIds.stream() - .filter(Objects::nonNull) - .distinct() - .toList(); - - if (CollectionUtils.isEmpty(idList)) { - return Collections.emptyMap(); - } - - Map map = fileDictTagQueryService.queryByFileIds(idList); - return MapUtils.isEmpty(map) ? Collections.emptyMap() : map; - } - private void bindSimulationPool(UploadFilesReq req, FileMetadataInfo fileInfo) { if (CollectionUtils.isEmpty(req.getSimulationPoolInfoList())) { return; From e0c52e0507ea216cde67665e48d21ba7c76bd3fe Mon Sep 17 00:00:00 2001 From: gulongcheng <474084054@qq.com> Date: Wed, 4 Feb 2026 17:09:44 +0800 Subject: [PATCH 5/7] =?UTF-8?q?fix:=E5=B0=81=E8=A3=85=E6=A0=87=E7=AD=BE?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/entity/enums/FileDictTagEnum.java | 13 ++- .../com/sdm/common/entity/resp/BaseResp.java | 6 ++ .../data/model/dto/FileDictTagsAggDTO.java | 6 ++ .../impl/FileDictTagQueryServiceImpl.java | 80 ++++++++++++++++--- 4 files changed, 88 insertions(+), 17 deletions(-) diff --git a/common/src/main/java/com/sdm/common/entity/enums/FileDictTagEnum.java b/common/src/main/java/com/sdm/common/entity/enums/FileDictTagEnum.java index 6eea230f..752ff2f8 100644 --- a/common/src/main/java/com/sdm/common/entity/enums/FileDictTagEnum.java +++ b/common/src/main/java/com/sdm/common/entity/enums/FileDictTagEnum.java @@ -8,8 +8,8 @@ import lombok.Getter; * 固定配置文件元数据响应中需要填充的字典标签字段映射关系 * * 映射关系: - * - disciplineTypeDictClass/disciplineDictValue → DISCIPLINE_TYPE - * - fileTypeDictClass/fileTypeDictValue → ALL_FILE_TYPE + * - disciplineTypeDictClass/disciplineDictValue/disciplineDictName → DISCIPLINE_TYPE + * - fileTypeDictClass/fileTypeDictValue/fileTypeDictName → ALL_FILE_TYPE */ @Getter @AllArgsConstructor @@ -20,14 +20,14 @@ public enum FileDictTagEnum { * 字段: disciplineTypeDictClass, disciplineDictValue * dictClass: DISCIPLINE_TYPE */ - DISCIPLINE_TYPE("DISCIPLINE_TYPE", "disciplineTypeDictClass", "disciplineDictValue"), + DISCIPLINE_TYPE("DISCIPLINE_TYPE", "disciplineTypeDictClass", "disciplineDictValue", "disciplineDictName"), /** * 文件类型标签 * 字段: fileTypeDictClass, fileTypeDictValue * dictClass: ALL_FILE_TYPE */ - FILE_TYPE("ALL_FILE_TYPE", "fileTypeDictClass", "fileTypeDictValue"); + FILE_TYPE("ALL_FILE_TYPE", "fileTypeDictClass", "fileTypeDictValue", "fileTypeDictName"); /** * 字典分类(对应数据库中的 dictClass) @@ -43,6 +43,11 @@ public enum FileDictTagEnum { * dictValue 字段名(完整字段名,如 disciplineDictValue) */ private final String dictValueFieldName; + + /** + * dictName 字段名(完整字段名,如 disciplineDictName) + */ + private final String dictNameFieldName; /** * 根据 dictClass 获取对应的枚举 diff --git a/common/src/main/java/com/sdm/common/entity/resp/BaseResp.java b/common/src/main/java/com/sdm/common/entity/resp/BaseResp.java index 8beb1f5a..0560df23 100644 --- a/common/src/main/java/com/sdm/common/entity/resp/BaseResp.java +++ b/common/src/main/java/com/sdm/common/entity/resp/BaseResp.java @@ -64,11 +64,17 @@ public class BaseResp { @Schema(description = "文件类型字典值") private String fileTypeDictValue; + @Schema(description = "文件类型字典名称") + private String fileTypeDictName; + @Schema(description = "学科类型字典类") private String disciplineTypeDictClass; @Schema(description = "学科类型字典值") private String disciplineDictValue; + @Schema(description = "学科类型字典名称") + private String disciplineDictName; + // ---------------------------------------------------------------- } diff --git a/data/src/main/java/com/sdm/data/model/dto/FileDictTagsAggDTO.java b/data/src/main/java/com/sdm/data/model/dto/FileDictTagsAggDTO.java index 21800907..7350d477 100644 --- a/data/src/main/java/com/sdm/data/model/dto/FileDictTagsAggDTO.java +++ b/data/src/main/java/com/sdm/data/model/dto/FileDictTagsAggDTO.java @@ -22,10 +22,16 @@ public class FileDictTagsAggDTO implements Serializable { @Schema(description = "文件类型字典值(逗号分隔)") private String fileTypeDictValue; + @Schema(description = "文件类型字典名称(逗号分隔)") + private String fileTypeDictName; + @Schema(description = "学科类型字典类") private String disciplineTypeDictClass; @Schema(description = "学科类型字典值(逗号分隔)") private String disciplineDictValue; + + @Schema(description = "学科类型字典名称(逗号分隔)") + private String disciplineDictName; } diff --git a/data/src/main/java/com/sdm/data/service/impl/FileDictTagQueryServiceImpl.java b/data/src/main/java/com/sdm/data/service/impl/FileDictTagQueryServiceImpl.java index 06676932..b9a63558 100644 --- a/data/src/main/java/com/sdm/data/service/impl/FileDictTagQueryServiceImpl.java +++ b/data/src/main/java/com/sdm/data/service/impl/FileDictTagQueryServiceImpl.java @@ -81,8 +81,8 @@ public class FileDictTagQueryServiceImpl implements IFileDictTagQueryService { (v1, v2) -> v1 )); - // 3) fileId -> (dictClass -> Set) - Map>> agg = new HashMap<>(); + // 3) fileId -> (dictClass -> 聚合数据:Set + Set) + Map> agg = new HashMap<>(); for (FileTagRel rel : fileTagRels) { if (rel == null || rel.getFileId() == null || rel.getTagId() == null) { continue; @@ -94,9 +94,13 @@ public class FileDictTagQueryServiceImpl implements IFileDictTagQueryService { if (!FileDictTagEnum.isConfigured(dict.dictClass)) { continue; } - agg.computeIfAbsent(rel.getFileId(), k -> new HashMap<>()) - .computeIfAbsent(dict.dictClass, k -> new LinkedHashSet<>()) - .add(dict.dictValue); + DictAggData data = agg + .computeIfAbsent(rel.getFileId(), k -> new HashMap<>()) + .computeIfAbsent(dict.dictClass, k -> new DictAggData()); + data.getDictValues().add(dict.dictValue); + if (dict.dictName != null) { + data.getDictNames().add(dict.dictName); + } } if (agg.isEmpty()) { @@ -105,9 +109,9 @@ public class FileDictTagQueryServiceImpl implements IFileDictTagQueryService { // 4) 转为 DTO(目前只输出枚举配置的两类字段) Map result = new HashMap<>(); - for (Map.Entry>> e : agg.entrySet()) { + for (Map.Entry> e : agg.entrySet()) { Long fileId = e.getKey(); - Map> classMap = e.getValue(); + Map classMap = e.getValue(); if (classMap == null || classMap.isEmpty()) { continue; } @@ -115,9 +119,16 @@ public class FileDictTagQueryServiceImpl implements IFileDictTagQueryService { FileDictTagsAggDTO dto = new FileDictTagsAggDTO(); dto.setFileId(fileId); - for (Map.Entry> classEntry : classMap.entrySet()) { + for (Map.Entry classEntry : classMap.entrySet()) { String dictClass = classEntry.getKey(); - String dictValues = String.join(",", classEntry.getValue()); + DictAggData data = classEntry.getValue(); + if (data == null || data.getDictValues().isEmpty()) { + continue; + } + String dictValues = String.join(",", data.getDictValues()); + String dictNames = data.getDictNames().isEmpty() + ? null + : String.join(",", data.getDictNames()); FileDictTagEnum tagEnum = FileDictTagEnum.getByDictClass(dictClass); if (tagEnum == null) { continue; @@ -125,9 +136,11 @@ public class FileDictTagQueryServiceImpl implements IFileDictTagQueryService { if (tagEnum == FileDictTagEnum.FILE_TYPE) { dto.setFileTypeDictClass(tagEnum.getDictClass()); dto.setFileTypeDictValue(dictValues); + dto.setFileTypeDictName(dictNames); } else if (tagEnum == FileDictTagEnum.DISCIPLINE_TYPE) { dto.setDisciplineTypeDictClass(tagEnum.getDictClass()); dto.setDisciplineDictValue(dictValues); + dto.setDisciplineDictName(dictNames); } } result.put(fileId, dto); @@ -170,21 +183,31 @@ public class FileDictTagQueryServiceImpl implements IFileDictTagQueryService { } for (FileDictTagEnum tagEnum : FileDictTagEnum.values()) { String dictValues = getDictValuesByEnum(tags, tagEnum); - if (dictValues == null) { + String dictNames = getDictNamesByEnum(tags, tagEnum); + if (dictValues == null && dictNames == null) { continue; } String dictClass = tagEnum.getDictClass(); String dictClassFieldName = tagEnum.getDictClassFieldName(); String dictValueFieldName = tagEnum.getDictValueFieldName(); + String dictNameFieldName = tagEnum.getDictNameFieldName(); try { // setXxxDictClass String classSetterName = "set" + Character.toUpperCase(dictClassFieldName.charAt(0)) + dictClassFieldName.substring(1); resp.getClass().getMethod(classSetterName, String.class) .invoke(resp, dictClass); // setXxxDictValue - String valueSetterName = "set" + Character.toUpperCase(dictValueFieldName.charAt(0)) + dictValueFieldName.substring(1); - resp.getClass().getMethod(valueSetterName, String.class) - .invoke(resp, dictValues); + if (dictValues != null) { + String valueSetterName = "set" + Character.toUpperCase(dictValueFieldName.charAt(0)) + dictValueFieldName.substring(1); + resp.getClass().getMethod(valueSetterName, String.class) + .invoke(resp, dictValues); + } + // setXxxDictName(如果存在) + if (dictNames != null) { + String nameSetterName = "set" + Character.toUpperCase(dictNameFieldName.charAt(0)) + dictNameFieldName.substring(1); + resp.getClass().getMethod(nameSetterName, String.class) + .invoke(resp, dictNames); + } } catch (Exception e) { log.warn("填充文件标签信息失败, fileId: {}, respClass: {}, dictClass: {}, error: {}", fileId, resp.getClass().getName(), dictClass, e.getMessage()); @@ -207,4 +230,35 @@ public class FileDictTagQueryServiceImpl implements IFileDictTagQueryService { } return null; } + + /** + * 根据枚举类型,从聚合结果中取出对应的字典名称 + */ + private String getDictNamesByEnum(FileDictTagsAggDTO tags, FileDictTagEnum tagEnum) { + if (tags == null || tagEnum == null) { + return null; + } + if (tagEnum == FileDictTagEnum.FILE_TYPE) { + return tags.getFileTypeDictName(); + } else if (tagEnum == FileDictTagEnum.DISCIPLINE_TYPE) { + return tags.getDisciplineDictName(); + } + return null; + } + + /** + * 内部聚合数据结构:同时持有 dictValue 和 dictName 的去重集合 + */ + private static class DictAggData { + private final LinkedHashSet dictValues = new LinkedHashSet<>(); + private final LinkedHashSet dictNames = new LinkedHashSet<>(); + + public LinkedHashSet getDictValues() { + return dictValues; + } + + public LinkedHashSet getDictNames() { + return dictNames; + } + } } From a50cc19463d2fbeaa6dffe619ad149f3ce01e19c Mon Sep 17 00:00:00 2001 From: gulongcheng <474084054@qq.com> Date: Wed, 4 Feb 2026 17:10:50 +0800 Subject: [PATCH 6/7] =?UTF-8?q?fix:=E5=B0=81=E8=A3=85=E6=A0=87=E7=AD=BE?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/src/main/java/com/sdm/common/entity/resp/BaseResp.java | 1 + 1 file changed, 1 insertion(+) diff --git a/common/src/main/java/com/sdm/common/entity/resp/BaseResp.java b/common/src/main/java/com/sdm/common/entity/resp/BaseResp.java index 0560df23..e90a5abe 100644 --- a/common/src/main/java/com/sdm/common/entity/resp/BaseResp.java +++ b/common/src/main/java/com/sdm/common/entity/resp/BaseResp.java @@ -61,6 +61,7 @@ public class BaseResp { // 很重要,用于设置标签 @Schema(description = "文件类型字典类") private String fileTypeDictClass; + @Schema(description = "文件类型字典值") private String fileTypeDictValue; From 1343667b8afd1d77cd54e5d2277ed9c64827fb43 Mon Sep 17 00:00:00 2001 From: 15195 Date: Wed, 4 Feb 2026 17:57:45 +0800 Subject: [PATCH 7/7] =?UTF-8?q?=E4=BF=AE=E6=94=B9=EF=BC=9Alyric=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E8=A7=86=E5=9B=BE=E5=BA=93=E6=96=B0=E8=83=BD=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/sdm/outbridge/config/CommonConfig.java | 2 +- .../outbridge/config/DataSourcePreWarmer.java | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/outbridge/src/main/java/com/sdm/outbridge/config/CommonConfig.java b/outbridge/src/main/java/com/sdm/outbridge/config/CommonConfig.java index 48e6cd9f..f9b6373d 100644 --- a/outbridge/src/main/java/com/sdm/outbridge/config/CommonConfig.java +++ b/outbridge/src/main/java/com/sdm/outbridge/config/CommonConfig.java @@ -21,7 +21,7 @@ import java.util.Map; */ @Configuration @PropertySource( - value = "classpath:common-${spring.profiles.active:lyric}.yml", + value = "classpath:common-${spring.profiles.active:}.yml", factory = CommonConfig.YamlPropertySourceFactory.class ) public class CommonConfig { diff --git a/outbridge/src/main/java/com/sdm/outbridge/config/DataSourcePreWarmer.java b/outbridge/src/main/java/com/sdm/outbridge/config/DataSourcePreWarmer.java index faec997f..8c64db0e 100644 --- a/outbridge/src/main/java/com/sdm/outbridge/config/DataSourcePreWarmer.java +++ b/outbridge/src/main/java/com/sdm/outbridge/config/DataSourcePreWarmer.java @@ -21,7 +21,7 @@ public class DataSourcePreWarmer { @Qualifier("secondDataSource") DataSource secondDataSource) { return args -> { try (Connection conn = secondDataSource.getConnection()) { - log.info("✅ secondDataSource 预热成功,连接已建立: {}", conn); + log.info("✅ secondDataSource 预热成功,连接已建立: {}", conn.getMetaData().getURL()); } catch (Exception e) { log.error("❌ secondDataSource 预热失败", e); throw new RuntimeException(e); @@ -29,6 +29,20 @@ public class DataSourcePreWarmer { }; } + @Bean + public ApplicationRunner thirdDataSourcePreWarmer( + @Qualifier("thirdDataSource") DataSource thirdDataSource) { + return args -> { + try (Connection conn = thirdDataSource.getConnection()) { + log.info("✅ thirdDataSource 预热成功,连接已建立: {}", conn.getMetaData().getURL()); + } catch (Exception e) { + log.error("❌ thirdDataSource 预热失败", e); + throw new RuntimeException(e); + } + }; + } + + // @Bean // public ApplicationRunner mainDataSourcePreWarmer( // @Qualifier("masterDataSource") DataSource master,