From a37c7248abc57dcc6ccd3ed43ed581a7cc6c5471 Mon Sep 17 00:00:00 2001
From: tangwei
+ * 使用示例: + * // 在查询方法末尾调用: + * dictCodeToNameConverter.convertCodeToName(voList, CODE_TO_NAME_META_LIST); + *+ */ + private static final List
+ * 用于配置 VO 中某个 code 字段如何转换为对应的 name 字段, + * 支持静态字典(SYS_DICTIONARY / SYS_DICTIONARY_ITEMS)和动态字典(业务表)。 + *
+ * + *
+ * 使用示例:
+ * // 静态字典:将 vo.typeCode 转为 vo.typeName,字典编码为 "PROJECT_TYPE"
+ * CodeToNameMetadataBo.builder()
+ * .codeProperty("typeCode")
+ * .modifyProperty("typeName")
+ * .dictType("STATIC")
+ * .dictSource("PROJECT_TYPE")
+ * .build();
+ *
+ * // 动态字典:将 vo.engCode 转为 vo.engName,查 SD_ENGINFO_B_H 表
+ * CodeToNameMetadataBo.builder()
+ * .codeProperty("engCode")
+ * .modifyProperty("engName")
+ * .dictType("DYNAMIC")
+ * .dictSource("SD_ENGINFO_B_H")
+ * .codeColumn("STCD")
+ * .nameColumn("ENNM")
+ * .filter("NVL(IS_DELETED, 0) = 0")
+ * .build();
+ *
+ *
+ * @author Generated
+ * @since 2025-05-18
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class CodeToNameMetadataBo implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 编码属性名(VO 中存放 code 的字段名)
+ */
+ private String codeProperty;
+
+ /**
+ * 名称属性名(VO 中需要设置 name 的字段名)
+ */
+ private String modifyProperty;
+
+ /**
+ * 字典类型:STATIC(静态字典)或 DYNAMIC(动态字典)
+ */
+ private String dictType;
+
+ /**
+ * 字典来源:
+ * - 静态字典:SYS_DICTIONARY 表中的 DICTCODE
+ * - 动态字典:业务表名
+ */
+ private String dictSource;
+
+ /**
+ * 动态字典:表中编码列名(静态字典不需要)
+ */
+ private String codeColumn;
+
+ /**
+ * 动态字典:表中名称列名(静态字典不需要)
+ */
+ private String nameColumn;
+
+ /**
+ * 额外过滤条件(可选)
+ * - 静态字典:SYS_DICTIONARY_ITEMS 的额外 WHERE 条件
+ * - 动态字典:业务表的额外 WHERE 条件
+ */
+ private String filter;
+
+ /**
+ * 是否多选(code 值为逗号分隔的多个编码)
+ */
+ @Builder.Default
+ private boolean isMulti = false;
+}
\ No newline at end of file
diff --git a/backend/src/main/java/com/yfd/platform/utils/DictCodeToNameConverter.java b/backend/src/main/java/com/yfd/platform/utils/DictCodeToNameConverter.java
new file mode 100644
index 00000000..a7db357d
--- /dev/null
+++ b/backend/src/main/java/com/yfd/platform/utils/DictCodeToNameConverter.java
@@ -0,0 +1,350 @@
+package com.yfd.platform.utils;
+
+import cn.hutool.core.util.StrUtil;
+import com.yfd.platform.common.MicroservicDynamicSQLMapper;
+import com.yfd.platform.system.domain.SysDictionary;
+import com.yfd.platform.system.domain.SysDictionaryItems;
+import com.yfd.platform.system.mapper.SysDictionaryItemsMapper;
+import com.yfd.platform.system.mapper.SysDictionaryMapper;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.lang.reflect.Field;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
+
+/**
+ * 字典代码转名称转换器
+ * + * 支持静态字典(SYS_DICTIONARY / SYS_DICTIONARY_ITEMS)和动态字典(业务表查询), + * 将 VO 中的 code 字段值转换为对应的 name 字段值。 + *
+ * + *
+ * // 1. 在 ServiceImpl 中注入
+ * @Resource
+ * private DictCodeToNameConverter dictCodeToNameConverter;
+ *
+ * // 2. 定义元数据列表(通常放在 static 静态代码块中)
+ * private static final List<CodeToNameMetadataBo> CODE_TO_NAME_META_LIST = List.of(
+ * CodeToNameMetadataBo.builder()
+ * .codeProperty("stationType")
+ * .modifyProperty("stationTypeName")
+ * .dictType("STATIC")
+ * .dictSource("STATION_TYPE")
+ * .build(),
+ * CodeToNameMetadataBo.builder()
+ * .codeProperty("engCode")
+ * .modifyProperty("engName")
+ * .dictType("DYNAMIC")
+ * .dictSource("SD_ENGINFO_B_H")
+ * .codeColumn("STCD")
+ * .nameColumn("ENNM")
+ * .filter("NVL(IS_DELETED, 0) = 0")
+ * .build()
+ * );
+ *
+ * // 3. 在查询方法中调用转换
+ * public DataSourceResult<MyVo> queryList(DataSourceRequest request) {
+ * // ... 查询数据得到 voList ...
+ * dictCodeToNameConverter.convertCodeToName(voList, CODE_TO_NAME_META_LIST);
+ * // ... 返回结果 ...
+ * }
+ *
+ *
+ * @author Generated
+ * @since 2025-05-18
+ */
+@Slf4j
+@Component
+public class DictCodeToNameConverter {
+
+ @Resource
+ private SysDictionaryMapper sysDictionaryMapper;
+
+ @Resource
+ private SysDictionaryItemsMapper sysDictionaryItemsMapper;
+
+ @Resource
+ private MicroservicDynamicSQLMapper> microservicDynamicSQLMapper;
+
+ /**
+ * 静态字典缓存:dictCode -> Map
+ */
+ private final Map> dynamicDictCache = new ConcurrentHashMap<>();
+
+ /**
+ * 批量转换:根据元数据配置,将 VO 列表中的 code 字段转换为对应的 name 字段
+ *
+ * @param voList VO 对象列表
+ * @param metadataList 元数据配置列表
+ * @param VO 类型
+ */
+ public void convertCodeToName(List voList, List metadataList) {
+ if (voList == null || voList.isEmpty() || metadataList == null || metadataList.isEmpty()) {
+ return;
+ }
+
+ for (CodeToNameMetadataBo metadata : metadataList) {
+ try {
+ Map codeNameMap = loadCodeNameMap(metadata);
+ if (codeNameMap.isEmpty()) {
+ continue;
+ }
+ applyCodeToName(voList, metadata, codeNameMap);
+ } catch (Exception e) {
+ log.error("字典转换失败: codeProperty={}, dictSource={}", metadata.getCodeProperty(), metadata.getDictSource(), e);
+ }
+ }
+ }
+
+ /**
+ * 加载静态字典映射
+ *
+ * @param dictCode 字典编码
+ * @return Map
+ */
+ public Map loadStaticDictMap(String dictCode) {
+ return staticDictCache.computeIfAbsent(dictCode, key -> {
+ Map map = new LinkedHashMap<>();
+ try {
+ SysDictionary dict = sysDictionaryMapper.selectOne(
+ new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper()
+ .eq(SysDictionary::getDictCode, key)
+ );
+ if (dict == null) {
+ log.warn("静态字典未找到: dictCode={}", key);
+ return map;
+ }
+ List items = sysDictionaryItemsMapper.selectList(
+ new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper()
+ .eq(SysDictionaryItems::getDictId, dict.getId())
+ .orderByAsc(SysDictionaryItems::getOrderNo)
+ );
+ for (SysDictionaryItems item : items) {
+ if (StrUtil.isNotBlank(item.getItemCode())) {
+ map.put(item.getItemCode(), StrUtil.nullToDefault(item.getDictName(), item.getItemCode()));
+ }
+ }
+ } catch (Exception e) {
+ log.error("加载静态字典失败: dictCode={}", key, e);
+ }
+ return map;
+ });
+ }
+
+ /**
+ * 加载动态字典映射(从业务表查询)
+ *
+ * @param tableName 表名
+ * @param codeColumn 编码列名
+ * @param nameColumn 名称列名
+ * @param filter 额外过滤条件
+ * @return Map
+ */
+ public Map loadDynamicDictMap(String tableName, String codeColumn, String nameColumn, String filter) {
+ String cacheKey = tableName + "|" + codeColumn + "|" + nameColumn + "|" + StrUtil.nullToDefault(filter, "");
+ return dynamicDictCache.computeIfAbsent(cacheKey, key -> {
+ Map map = new LinkedHashMap<>();
+ try {
+ StringBuilder sql = new StringBuilder();
+ sql.append("SELECT ").append(codeColumn).append(" AS code, ")
+ .append(nameColumn).append(" AS name ")
+ .append("FROM ").append(tableName)
+ .append(" WHERE 1=1 ");
+ if (StrUtil.isNotBlank(filter)) {
+ sql.append("AND ").append(filter).append(" ");
+ }
+ Map params = new HashMap<>();
+ List