From 34981c30a78e8bbd7791131059a9210f9928b62c Mon Sep 17 00:00:00 2001
From: 刘光辉 <347230014@qq.com>
Date: 星期四, 17 九月 2026 09:24:09 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master' into master

---
 jnpf-biz-common/jnpf-biz-common-audit/src/main/java/jnpf/bizcommon/audit/service/value/JnpfDictionaryFieldValueResolver.java |  233 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 233 insertions(+), 0 deletions(-)

diff --git a/jnpf-biz-common/jnpf-biz-common-audit/src/main/java/jnpf/bizcommon/audit/service/value/JnpfDictionaryFieldValueResolver.java b/jnpf-biz-common/jnpf-biz-common-audit/src/main/java/jnpf/bizcommon/audit/service/value/JnpfDictionaryFieldValueResolver.java
new file mode 100644
index 0000000..02fa248
--- /dev/null
+++ b/jnpf-biz-common/jnpf-biz-common-audit/src/main/java/jnpf/bizcommon/audit/service/value/JnpfDictionaryFieldValueResolver.java
@@ -0,0 +1,233 @@
+package jnpf.bizcommon.audit.service.value;
+
+import com.alibaba.fastjson.JSON;
+import jnpf.bizcommon.audit.entity.model.AuditFieldDiffViewVO;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.annotation.Order;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
+import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * 鎸� JNPF dictionaryType 鎵归噺瑙f瀽瀛楀吀椤癸紱涓�娆¤鎯呰嚦澶氭墽琛屼竴鏉″瓧鍏告煡璇€��
+ *
+ * <p>{@code @Order} 鐨勫惈涔夎 {@link LimsQingyandanFieldValueResolver} 鐨勭被娉ㄩ噴銆�
+ */
+@Slf4j
+@Component
+@Order(JnpfDictionaryFieldValueResolver.ORDER)
+public class JnpfDictionaryFieldValueResolver implements AuditFieldValueResolver {
+
+    /** 骞冲彴閫氱敤瑙f瀽鍣紝鎺掑湪琛ㄤ笓鐢紙100锛変箣鍚庛�佺敤鎴峰厹搴曪紙300锛変箣鍓嶃�� */
+    public static final int ORDER = 200;
+
+    private static final String UNAVAILABLE = "鍚嶇О鏆備笉鍙敤";
+
+    private final DictionaryLookup lookup;
+
+    @Autowired
+    public JnpfDictionaryFieldValueResolver(JdbcTemplate jdbcTemplate) {
+        this(new JdbcDictionaryLookup(jdbcTemplate));
+    }
+
+    JnpfDictionaryFieldValueResolver(DictionaryLookup lookup) {
+        this.lookup = lookup;
+    }
+
+    @Override
+    public boolean supports(String targetTable) {
+        return true;
+    }
+
+    @Override
+    public void resolve(AuditFieldValueContext context, List<AuditFieldDiffViewVO> fields) {
+        if (context == null || blank(context.getTenantId()) || fields == null || fields.isEmpty()
+                || context.getDictionaryTypes().isEmpty()) {
+            return;
+        }
+        Set<String> dictionaryTypes = new LinkedHashSet<>();
+        Set<String> values = new LinkedHashSet<>();
+        for (AuditFieldDiffViewVO field : fields) {
+            String dictionaryType = dictionaryType(context, field);
+            if (dictionaryType == null || displaysResolved(field)) {
+                continue;
+            }
+            dictionaryTypes.add(dictionaryType);
+            values.addAll(parseValues(field.getOldData()));
+            values.addAll(parseValues(field.getNewData()));
+        }
+        if (dictionaryTypes.isEmpty() || values.isEmpty()) {
+            return;
+        }
+
+        Map<String, Map<String, String>> labels = lookup.labels(
+                context.getTenantId().trim(), dictionaryTypes, values);
+        for (AuditFieldDiffViewVO field : fields) {
+            String dictionaryType = dictionaryType(context, field);
+            Map<String, String> dictionary = dictionaryType == null
+                    ? null : labels.get(dictionaryType);
+            if (dictionary == null) {
+                continue;
+            }
+            boolean multiple = "multiEnum".equals(field.getValueType())
+                    || startsWithArray(field.getOldData()) || startsWithArray(field.getNewData());
+            if (blank(field.getValueType())) {
+                field.setValueType(multiple ? "multiEnum" : "enum");
+            }
+            if (field.getOldDisplay() == null) {
+                field.setOldDisplay(display(field.getOldData(), dictionary));
+            }
+            if (field.getNewDisplay() == null) {
+                field.setNewDisplay(display(field.getNewData(), dictionary));
+            }
+        }
+    }
+
+    private static String dictionaryType(AuditFieldValueContext context, AuditFieldDiffViewVO field) {
+        if (field == null || blank(field.getField())) {
+            return null;
+        }
+        return context.getDictionaryTypes().get(field.getField().trim().toLowerCase(Locale.ROOT));
+    }
+
+    private static boolean displaysResolved(AuditFieldDiffViewVO field) {
+        return (blank(field.getOldData()) || field.getOldDisplay() != null)
+                && (blank(field.getNewData()) || field.getNewDisplay() != null);
+    }
+
+    private static String display(String raw, Map<String, String> labels) {
+        if (blank(raw)) {
+            return "";
+        }
+        List<String> values = parseValues(raw);
+        if (values.isEmpty()) {
+            return UNAVAILABLE;
+        }
+        List<String> result = new ArrayList<>(values.size());
+        for (String value : values) {
+            String label = labels.get(value);
+            result.add(blank(label) ? UNAVAILABLE : label);
+        }
+        return String.join("銆�", result);
+    }
+
+    @SuppressWarnings("unchecked")
+    private static List<String> parseValues(String raw) {
+        if (blank(raw)) {
+            return Collections.emptyList();
+        }
+        String trimmed = raw.trim();
+        if (!trimmed.startsWith("[")) {
+            return Collections.singletonList(trimmed);
+        }
+        try {
+            Object parsed = JSON.parse(trimmed);
+            if (!(parsed instanceof Collection)) {
+                return Collections.emptyList();
+            }
+            List<String> result = new ArrayList<>();
+            for (Object value : (Collection<Object>) parsed) {
+                if (value != null && !String.valueOf(value).trim().isEmpty()) {
+                    result.add(String.valueOf(value).trim());
+                }
+            }
+            return result;
+        } catch (RuntimeException ignored) {
+            return Collections.emptyList();
+        }
+    }
+
+    private static boolean startsWithArray(String raw) {
+        return raw != null && raw.trim().startsWith("[");
+    }
+
+    private static boolean blank(String value) {
+        return value == null || value.trim().isEmpty();
+    }
+
+    interface DictionaryLookup {
+        Map<String, Map<String, String>> labels(String tenantId, Set<String> dictionaryTypes,
+                                                Set<String> values);
+    }
+
+    /** 琛ㄥ悕鍜屽垪鍚嶅浐瀹氾紱dictionaryType銆佸�煎拰绉熸埛鍏ㄩ儴鍙傛暟鍖栥�� */
+    private static final class JdbcDictionaryLookup implements DictionaryLookup {
+        private final NamedParameterJdbcTemplate jdbc;
+
+        private JdbcDictionaryLookup(JdbcTemplate jdbcTemplate) {
+            this.jdbc = new NamedParameterJdbcTemplate(jdbcTemplate);
+        }
+
+        @Override
+        public Map<String, Map<String, String>> labels(
+                String tenantId, Set<String> dictionaryTypes, Set<String> values) {
+            try {
+                MapSqlParameterSource params = new MapSqlParameterSource()
+                        .addValue("dictionaryTypes", dictionaryTypes)
+                        .addValue("values", values)
+                        .addValue("tenantId", tenantId);
+                List<Map<String, Object>> rows = jdbc.queryForList(
+                        "SELECT t.f_id AS type_id, t.f_en_code AS type_code, "
+                                + "d.f_id AS data_id, d.f_en_code AS data_code, d.f_full_name AS data_name "
+                                + "FROM base_dictionary_data d "
+                                + "JOIN base_dictionary_type t ON t.f_id = d.f_dictionary_type_id "
+                                + "WHERE (t.f_id IN (:dictionaryTypes) OR t.f_en_code IN (:dictionaryTypes)) "
+                                + "AND (d.f_id IN (:values) OR d.f_en_code IN (:values)) "
+                                + "AND COALESCE(NULLIF(t.f_tenant_id, ''), '0') = :tenantId "
+                                + "AND COALESCE(NULLIF(d.f_tenant_id, ''), '0') = :tenantId "
+                                + "AND COALESCE(t.f_delete_mark, 0) = 0 "
+                                + "AND COALESCE(d.f_delete_mark, 0) = 0",
+                        params);
+                Map<String, Map<String, String>> result = new LinkedHashMap<>();
+                for (Map<String, Object> row : rows) {
+                    String typeId = text(row.get("type_id"));
+                    String typeCode = text(row.get("type_code"));
+                    String dataId = text(row.get("data_id"));
+                    String dataCode = text(row.get("data_code"));
+                    String label = text(row.get("data_name"));
+                    put(result, typeId, dataId, dataCode, label);
+                    put(result, typeCode, dataId, dataCode, label);
+                }
+                return result;
+            } catch (RuntimeException ex) {
+                log.warn("[AUDIT-QUERY] JNPF 瀛楀吀鎵归噺瑙f瀽澶辫触 typeCount={} valueCount={} err={}",
+                        dictionaryTypes.size(), values.size(), ex.getClass().getSimpleName());
+                return Collections.emptyMap();
+            }
+        }
+
+        private static void put(Map<String, Map<String, String>> result, String type,
+                                String dataId, String dataCode, String label) {
+            if (type == null || label == null) {
+                return;
+            }
+            Map<String, String> values = result.computeIfAbsent(type, key -> new LinkedHashMap<>());
+            if (dataId != null) {
+                values.put(dataId, label);
+            }
+            if (dataCode != null) {
+                values.put(dataCode, label);
+            }
+        }
+
+        private static String text(Object value) {
+            if (value == null) {
+                return null;
+            }
+            String result = String.valueOf(value).trim();
+            return result.isEmpty() ? null : result;
+        }
+    }
+}

--
Gitblit v1.8.0