diff --git a/MD/MODULE_INDEX.md b/MD/MODULE_INDEX.md index 675755168..f716cfbc6 100644 --- a/MD/MODULE_INDEX.md +++ b/MD/MODULE_INDEX.md @@ -1,6 +1,7 @@ # HealthLink-HIS 代码模块索引 > 供 LLM 快速定位代码。每个模块列出 Controller → Service → Mapper 关键文件。 +> 最后更新: 2026-06-13 12:00 (298 个 Controller) ## 关键词 → 模块速查 diff --git a/healthlink-his-server/core-common/src/main/java/com/core/common/utils/DictUtils.java b/healthlink-his-server/core-common/src/main/java/com/core/common/utils/DictUtils.java index 71f0fb838..64aaaaf3a 100755 --- a/healthlink-his-server/core-common/src/main/java/com/core/common/utils/DictUtils.java +++ b/healthlink-his-server/core-common/src/main/java/com/core/common/utils/DictUtils.java @@ -1,13 +1,14 @@ package com.core.common.utils; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; +import com.alibaba.fastjson2.JSONArray; import com.core.common.constant.CacheConstants; import com.core.common.core.domain.entity.SysDictData; import com.core.common.core.redis.RedisCache; import com.core.common.utils.spring.SpringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.Collection; import java.util.List; @@ -17,6 +18,7 @@ import java.util.List; * @author system */ public class DictUtils { + private static final Logger log = LoggerFactory.getLogger(DictUtils.class); /** * 分隔符 */ @@ -39,24 +41,39 @@ public class DictUtils { * @return dictDatas 字典数据列表 */ public static List getDictCache(String key) { - Object cached = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key)); - if (StringUtils.isNull(cached)) { + try { + Object cached = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key)); + if (cached == null) { + return null; + } + if (cached instanceof JSONArray arrayCache) { + return arrayCache.toList(SysDictData.class); + } + if (cached instanceof List list) { + // Redis缓存可能已反序列化为List,尝试逐个转换 + java.util.ArrayList result = new java.util.ArrayList<>(list.size()); + for (Object item : list) { + if (item instanceof SysDictData dictData) { + result.add(dictData); + } else { + // 尝试通过JSON转换 + String json = com.alibaba.fastjson2.JSON.toJSONString(item); + result.add(com.alibaba.fastjson2.JSON.parseObject(json, SysDictData.class)); + } + } + return result; + } + log.warn("字典缓存key={}的数据类型异常: {}, 清除缓存", key, cached.getClass().getName()); + removeDictCache(key); + return null; + } catch (Exception e) { + log.warn("获取字典缓存异常key={}, 清除缓存: {}", key, e.getMessage()); + try { + removeDictCache(key); + } catch (Exception ignored) { + } return null; } - // 如果已经是目标类型,直接返回 - if (cached instanceof List && ((List) cached).stream().allMatch(e -> e instanceof SysDictData)) { - @SuppressWarnings("unchecked") - List result = (List) cached; - return result; - } - com.fasterxml.jackson.core.type.TypeReference> typeRef = - new com.fasterxml.jackson.core.type.TypeReference>() {}; - ObjectMapper mapper = new ObjectMapper() - .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); - if (cached instanceof JsonNode jsonNode) { - return mapper.convertValue(jsonNode, typeRef); - } - return mapper.convertValue(cached, typeRef); } /** diff --git a/healthlink-his-server/healthlink-his-common/src/main/java/com/healthlink/his/common/aspectj/DictAspect.java b/healthlink-his-server/healthlink-his-common/src/main/java/com/healthlink/his/common/aspectj/DictAspect.java index 1b677f0e5..93a6a9012 100755 --- a/healthlink-his-server/healthlink-his-common/src/main/java/com/healthlink/his/common/aspectj/DictAspect.java +++ b/healthlink-his-server/healthlink-his-common/src/main/java/com/healthlink/his/common/aspectj/DictAspect.java @@ -9,14 +9,16 @@ import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; @Aspect @Component @@ -24,137 +26,154 @@ public class DictAspect { private static final Logger log = LoggerFactory.getLogger(DictAspect.class); - @Autowired - private JdbcTemplate jdbcTemplate; // 使用 JdbcTemplate 执行 SQL + private final JdbcTemplate jdbcTemplate; + + public DictAspect(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } @Around("@annotation(org.springframework.web.bind.annotation.GetMapping) || " + "@annotation(org.springframework.web.bind.annotation.PostMapping)") public Object aroundController(ProceedingJoinPoint joinPoint) throws Throwable { - Object result = joinPoint.proceed(); // 执行原方法 + Object result = joinPoint.proceed(); - if (result instanceof R response) { - Object data = response.getData(); // 获取 R 中的实际数据 - - if (data instanceof Page) { - // 如果数据是 Page 类型,处理分页数据 - Page page = (Page)data; - List records = page.getRecords(); - if (!records.isEmpty()) { + try { + if (result instanceof R response) { + Object data = response.getData(); + if (data instanceof Page page) { + List records = page.getRecords(); for (Object obj : records) { - processDict(obj); // 处理每个 DTO 对象 + processDict(obj, new HashSet<>()); } - } - } else if (data instanceof List list) { - if (!list.isEmpty()) { + } else if (data instanceof List list) { for (Object obj : list) { - processDict(obj); // 处理每个 DTO 对象 + processDict(obj, new HashSet<>()); } + } else if (data != null) { + processDict(data, new HashSet<>()); } - } else { - // 如果数据是单个 DTO 对象,直接处理 - processDict(data); } + } catch (Exception e) { + log.warn("字典翻译处理异常,跳过字典处理", e); } return result; } - private void processDict(T dto) throws IllegalAccessException { + private void processDict(Object dto, Set visited) { if (dto == null) { return; } - // 检查对象是否是 DTO 类(即是否有 @Dict 注解的字段) - boolean isDto = false; - for (Field field : dto.getClass().getDeclaredFields()) { + int identityHash = System.identityHashCode(dto); + if (!visited.add(identityHash)) { + return; + } + + Class clazz = dto.getClass(); + if (clazz.isPrimitive() || clazz.getName().startsWith("java.lang.") + || dto instanceof java.math.BigDecimal || dto instanceof java.util.Date + || dto instanceof java.time.temporal.TemporalAccessor + || dto instanceof byte[] || dto instanceof char[]) { + return; + } + + List allFields = collectFields(clazz); + boolean hasDict = false; + for (Field field : allFields) { if (field.isAnnotationPresent(Dict.class)) { - isDto = true; + hasDict = true; break; } } - // 如果不是 DTO 类,直接返回 - if (!isDto) { + if (!hasDict) { return; } - // 获取 DTO 类的所有字段 - for (Field field : dto.getClass().getDeclaredFields()) { - field.setAccessible(true); // 设置字段可访问 - Object fieldValue = field.get(dto); // 获取字段值 + + for (Field field : allFields) { + field.setAccessible(true); + Object fieldValue; + try { + fieldValue = field.get(dto); + } catch (IllegalAccessException e) { + log.debug("无法访问字段 {}.{}", clazz.getSimpleName(), field.getName()); + continue; + } if (fieldValue == null) { - continue; // 如果字段值为空,跳过 + continue; } - // 如果字段是 List 类型,递归处理其中的每个元素 if (fieldValue instanceof List list) { for (Object item : list) { - processDict(item); // 递归处理 List 中的每个元素 + processDict(item, visited); } } else if (field.isAnnotationPresent(Dict.class)) { - // 如果字段带有 @Dict 注解,处理字典值 Dict dictAnnotation = field.getAnnotation(Dict.class); String dictCode = dictAnnotation.dictCode(); String dictText = dictAnnotation.dictText(); String dictTable = dictAnnotation.dictTable(); String deleteFlag = dictAnnotation.deleteFlag(); - // 检查 _dictText 字段是否已被手动填充(如控制器方法中预先查询设置) - // 如果已非空则跳过 SQL 查询,避免覆盖有效值 String textFieldName = field.getName() + "_dictText"; try { - Field existingTextField = dto.getClass().getDeclaredField(textFieldName); + Field existingTextField = clazz.getDeclaredField(textFieldName); existingTextField.setAccessible(true); Object existingValue = existingTextField.get(dto); if (existingValue != null && !existingValue.toString().isEmpty()) { - continue; // _dictText 已有值,跳过 + continue; } - } catch (NoSuchFieldException e) { - // _dictText 字段不存在,继续正常流程 + } catch (NoSuchFieldException | IllegalAccessException e) { + // _dictText field not present, proceed normally } - // 查询字典值 - String dictLabel = queryDictLabel(dictTable, dictCode, dictText, deleteFlag, fieldValue.toString()); - if (dictLabel != null && !dictLabel.isEmpty()) { - // 动态生成 _dictText 字段名 - try { - Field textField = dto.getClass().getDeclaredField(textFieldName); - textField.setAccessible(true); - textField.set(dto, dictLabel); // 设置 _dictText 字段的值 - } catch (NoSuchFieldException e) { - // 如果 _dictText 字段不存在,忽略错误 - log.debug("字段 {} 不存在,跳过字典翻译", textFieldName); + try { + String dictLabel = queryDictLabel(dictTable, dictCode, dictText, deleteFlag, fieldValue.toString()); + if (dictLabel != null && !dictLabel.isEmpty()) { + try { + Field textField = clazz.getDeclaredField(textFieldName); + textField.setAccessible(true); + textField.set(dto, dictLabel); + } catch (NoSuchFieldException | IllegalAccessException e) { + log.debug("字段 {} 不存在或无法访问,跳过字典翻译", textFieldName); + } } + } catch (Exception e) { + log.debug("字典翻译异常, 字段={}, dictCode={}, 跳过: {}", field.getName(), dictCode, e.getMessage()); } } else { - processDict(fieldValue); // 递归处理 Dto 中的每个元素 + processDict(fieldValue, visited); } } } + private List collectFields(Class clazz) { + List fields = new ArrayList<>(); + Class current = clazz; + while (current != null && current != Object.class) { + for (Field field : current.getDeclaredFields()) { + fields.add(field); + } + current = current.getSuperclass(); + } + return fields; + } + private String queryDictLabel(String dictTable, String dictCode, String dictText, String deleteFlag, String dictValue) { if (!StringUtils.hasText(dictTable)) { - // 场景 1:默认字典走DictUtils缓存(dictTable 为空时) return DictUtils.getDictLabel(dictCode, dictValue); - } else { - // 场景 2:查询指定表(dictTable 有值时) - // 必须同时有 dictTable 和 dictText 才能执行 SQL 查询 - if (!StringUtils.hasText(dictText)) { - // 如果 dictText 为空,回退到字典缓存查询 - return DictUtils.getDictLabel(dictCode, dictValue); - } - // 构建SQL,支持 delete_flag 过滤 - StringBuilder sqlBuilder = new StringBuilder(); - sqlBuilder.append(String.format("SELECT %s FROM %s WHERE %s::varchar = ?", dictText, dictTable, dictCode)); - // 如果指定了 deleteFlag 字段名,添加过滤条件 - if (StringUtils.hasText(deleteFlag)) { - sqlBuilder.append(String.format(" AND %s = '0'", deleteFlag)); - } - sqlBuilder.append(" LIMIT 1"); - String sql = sqlBuilder.toString(); - try { - return jdbcTemplate.queryForObject(sql, String.class, dictValue); - } catch (DataAccessException e) { - // 如果查询结果为空,返回 空字符串 - return ""; - } + } + if (!StringUtils.hasText(dictText)) { + return DictUtils.getDictLabel(dictCode, dictValue); + } + StringBuilder sqlBuilder = new StringBuilder(); + sqlBuilder.append(String.format("SELECT %s FROM %s WHERE %s::varchar = ?", dictText, dictTable, dictCode)); + if (StringUtils.hasText(deleteFlag)) { + sqlBuilder.append(String.format(" AND %s = '0'", deleteFlag)); + } + sqlBuilder.append(" LIMIT 1"); + try { + return jdbcTemplate.queryForObject(sqlBuilder.toString(), String.class, dictValue); + } catch (DataAccessException e) { + return ""; } } -} \ No newline at end of file +}