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/LimsQingyandanFieldValueResolver.java |  350 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 350 insertions(+), 0 deletions(-)

diff --git a/jnpf-biz-common/jnpf-biz-common-audit/src/main/java/jnpf/bizcommon/audit/service/value/LimsQingyandanFieldValueResolver.java b/jnpf-biz-common/jnpf-biz-common-audit/src/main/java/jnpf/bizcommon/audit/service/value/LimsQingyandanFieldValueResolver.java
new file mode 100644
index 0000000..f09c073
--- /dev/null
+++ b/jnpf-biz-common/jnpf-biz-common-audit/src/main/java/jnpf/bizcommon/audit/service/value/LimsQingyandanFieldValueResolver.java
@@ -0,0 +1,350 @@
+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;
+
+/**
+ * 璇烽獙鍗曞瓧娈电殑鏄惧紡涓氬姟瑙f瀽鍣紱寮曠敤琛ㄥ拰灞曠ず鍒楀潎涓哄浐瀹氱櫧鍚嶅崟銆�
+ *
+ * <p><b>{@code @Order} 涓嶆槸瑁呴グ</b>锛�2026-08-02 鍔狅級锛氳В鏋愬櫒鎸夋敞鍏ラ『搴忎覆琛屾墽琛岋紝鍏堝啓涓�
+ * display 鐨勯偅涓浜嗙畻锛堝悗缁В鏋愬櫒涓�寰� {@code if (display == null)} 鎵嶅姩鎵嬶級銆傝〃涓撶敤瑙f瀽鍣�
+ * 蹇呴』鎺掑湪閫氱敤瑙f瀽鍣ㄤ箣鍓嶏紝鍚﹀垯 {@code qingyan_ren} 浼氳
+ * {@link JnpfUserFieldValueResolver} 鎸夐�氱敤鏍煎紡锛坮ealName/account锛夋姠鍏堣В鏋愭帀锛�
+ * 鏈被涓哄畠瀹氱殑鏍煎紡锛堝彧鏄剧ず濮撳悕锛夊氨姘歌繙涓嶇敓鏁堛�係pring 瀵规病鏍囨敞鐨� bean 涓�寰嬫寜
+ * {@code LOWEST_PRECEDENCE} 澶勭悊銆佷繚鐣欐壂鎻忓簭鈥斺�旈偅鏄被鍚嶅瓧姣嶅簭鐨勫壇浜у搧锛屼笉璇ユ嬁瀹冨綋濂戠害銆�
+ */
+@Slf4j
+@Component
+@Order(LimsQingyandanFieldValueResolver.ORDER)
+public class LimsQingyandanFieldValueResolver implements AuditFieldValueResolver {
+
+    /** 琛ㄤ笓鐢ㄨВ鏋愬櫒锛屾渶鍏堣窇銆� */
+    public static final int ORDER = 100;
+
+    private static final String TABLE = "lims_qingyandan";
+    private static final String UNAVAILABLE = "鍚嶇О鏆備笉鍙敤";
+    private static final Map<String, String> BIZ_STATUS = labels(
+            "created", "宸插垱寤�", "confirmed", "宸叉彁浜�", "pending_fetch", "寰呭彇鏍�",
+            "deleted", "宸插簾寮�", "cancelled", "宸叉挙鍥�", "fetched", "宸插彇鏍�",
+            "pending_receive", "寰呮帴鏍�", "received", "宸叉帴鏍�", "rejected", "宸查��鍥�");
+    private static final Map<String, String> BIZ_TYPE = labels("CP", "鎴愬搧");
+    private static final Map<String, String> JIANCE_FANGSHI = labels(
+            "quanjian", "鍏ㄦ", "bufenjian", "閮ㄥ垎妫�", "mianjian", "鍏嶆");
+
+    private final ReferenceLookup lookup;
+
+    @Autowired
+    public LimsQingyandanFieldValueResolver(JdbcTemplate jdbcTemplate) {
+        this(new JdbcReferenceLookup(jdbcTemplate));
+    }
+
+    LimsQingyandanFieldValueResolver(ReferenceLookup lookup) {
+        this.lookup = lookup;
+    }
+
+    @Override
+    public boolean supports(String targetTable) {
+        return targetTable != null && TABLE.equals(targetTable.trim().toLowerCase(Locale.ROOT));
+    }
+
+    @Override
+    public void resolve(AuditFieldValueContext context, List<AuditFieldDiffViewVO> fields) {
+        if (fields == null || fields.isEmpty()) {
+            return;
+        }
+        applyBusinessEnums(fields);
+        Set<String> projectIds = new LinkedHashSet<>();
+        Set<String> standardIds = new LinkedHashSet<>();
+        Set<String> userIds = new LinkedHashSet<>();
+        Set<String> productIds = new LinkedHashSet<>();
+
+        for (AuditFieldDiffViewVO field : fields) {
+            String name = normalized(field.getField());
+            if ("jiance_xiangmu".equals(name)) {
+                setMissingSemantics(field, "multiReference", "checkbox");
+                collect(projectIds, field.getOldData());
+                collect(projectIds, field.getNewData());
+            } else if ("jianyan_biaozhun".equals(name)) {
+                setMissingSemantics(field, "reference", "select");
+                collect(standardIds, field.getOldData());
+                collect(standardIds, field.getNewData());
+            } else if ("qingyan_ren".equals(name)) {
+                setMissingSemantics(field, "reference", "userSelect");
+                collect(userIds, field.getOldData());
+                collect(userIds, field.getNewData());
+            } else if ("chanpin_id".equals(name)) {
+                setMissingSemantics(field, "reference", "popupSelect");
+                field.setTechnical(Boolean.TRUE);
+                collect(productIds, field.getOldData());
+                collect(productIds, field.getNewData());
+            }
+        }
+
+        if (context == null || blank(context.getTenantId())) {
+            return;
+        }
+        String tenantId = context.getTenantId().trim();
+        Map<String, String> projects = projectIds.isEmpty()
+                ? Collections.emptyMap() : lookup.projects(tenantId, projectIds);
+        Map<String, String> standards = standardIds.isEmpty()
+                ? Collections.emptyMap() : lookup.standards(tenantId, standardIds);
+        Map<String, String> users = userIds.isEmpty()
+                ? Collections.emptyMap() : lookup.users(tenantId, userIds);
+        Map<String, String> products = productIds.isEmpty()
+                ? Collections.emptyMap() : lookup.products(tenantId, productIds);
+
+        for (AuditFieldDiffViewVO field : fields) {
+            String name = normalized(field.getField());
+            if ("jiance_xiangmu".equals(name)) {
+                apply(field, projects, true);
+            } else if ("jianyan_biaozhun".equals(name)) {
+                apply(field, standards, false);
+            } else if ("qingyan_ren".equals(name)) {
+                apply(field, users, false);
+            } else if ("chanpin_id".equals(name)) {
+                apply(field, products, false);
+            }
+        }
+    }
+
+    private static void applyBusinessEnums(List<AuditFieldDiffViewVO> fields) {
+        for (AuditFieldDiffViewVO field : fields) {
+            String name = normalized(field.getField());
+            if ("biz_status".equals(name)) {
+                applyEnum(field, BIZ_STATUS, "select");
+            } else if ("biz_type".equals(name)) {
+                applyEnum(field, BIZ_TYPE, "select");
+            } else if ("jiance_fangshi".equals(name)) {
+                applyEnum(field, JIANCE_FANGSHI, "radio");
+            }
+        }
+    }
+
+    private static void applyEnum(AuditFieldDiffViewVO field, Map<String, String> labels,
+                                  String componentType) {
+        setMissingSemantics(field, "enum", componentType);
+        if (field.getOldDisplay() == null) {
+            field.setOldDisplay(enumDisplay(field.getOldData(), labels));
+        }
+        if (field.getNewDisplay() == null) {
+            field.setNewDisplay(enumDisplay(field.getNewData(), labels));
+        }
+    }
+
+    private static String enumDisplay(String raw, Map<String, String> labels) {
+        if (blank(raw)) {
+            return "";
+        }
+        return labels.get(raw.trim());
+    }
+
+    private static Map<String, String> labels(String... values) {
+        Map<String, String> labels = new LinkedHashMap<>();
+        for (int i = 0; i + 1 < values.length; i += 2) {
+            labels.put(values[i], values[i + 1]);
+        }
+        return Collections.unmodifiableMap(labels);
+    }
+
+    private static void setMissingSemantics(AuditFieldDiffViewVO field,
+                                            String valueType, String componentType) {
+        if (blank(field.getValueType())) {
+            field.setValueType(valueType);
+        }
+        if (blank(field.getComponentType())) {
+            field.setComponentType(componentType);
+        }
+    }
+
+    private static void apply(AuditFieldDiffViewVO field, Map<String, String> names, boolean multiple) {
+        if (field.getOldDisplay() == null) {
+            field.setOldDisplay(display(field.getOldData(), names, multiple));
+        }
+        if (field.getNewDisplay() == null) {
+            field.setNewDisplay(display(field.getNewData(), names, multiple));
+        }
+    }
+
+    private static String display(String raw, Map<String, String> names, boolean multiple) {
+        if (blank(raw)) {
+            return "";
+        }
+        List<String> ids = multiple ? parseIds(raw) : Collections.singletonList(raw.trim());
+        if (ids.isEmpty()) {
+            return UNAVAILABLE;
+        }
+        List<String> display = new ArrayList<>(ids.size());
+        for (String id : ids) {
+            String name = names.get(id);
+            display.add(blank(name) ? UNAVAILABLE : name);
+        }
+        return String.join("銆�", display);
+    }
+
+    private static void collect(Set<String> target, String raw) {
+        target.addAll(parseIds(raw));
+    }
+
+    @SuppressWarnings("unchecked")
+    private static List<String> parseIds(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> ids = new ArrayList<>();
+            for (Object value : (Collection<Object>) parsed) {
+                if (value != null && !String.valueOf(value).trim().isEmpty()) {
+                    ids.add(String.valueOf(value).trim());
+                }
+            }
+            return ids;
+        } catch (Throwable ignored) {
+            return Collections.emptyList();
+        }
+    }
+
+    private static String normalized(String field) {
+        return field == null ? null : field.trim().toLowerCase(Locale.ROOT);
+    }
+
+    private static boolean blank(String value) {
+        return value == null || value.trim().isEmpty();
+    }
+
+    interface ReferenceLookup {
+        Map<String, String> projects(String tenantId, Set<String> ids);
+
+        Map<String, String> standards(String tenantId, Set<String> ids);
+
+        Map<String, String> users(String tenantId, Set<String> ids);
+
+        Map<String, String> products(String tenantId, Set<String> ids);
+    }
+
+    /** 姣忕寮曠敤鍥哄畾涓�鏉� IN 鏌ヨ锛汼QL 琛ㄥ悕鍜屽垪鍚嶄笉鎺ュ彈澶栭儴杈撳叆銆� */
+    private static final class JdbcReferenceLookup implements ReferenceLookup {
+        private final NamedParameterJdbcTemplate jdbc;
+
+        private JdbcReferenceLookup(JdbcTemplate jdbcTemplate) {
+            this.jdbc = new NamedParameterJdbcTemplate(jdbcTemplate);
+        }
+
+        @Override
+        public Map<String, String> projects(String tenantId, Set<String> ids) {
+            return query("projects", ids, tenantId,
+                    "SELECT f_id, jianyan_xiangmu_mingcheng AS display_name "
+                            + "FROM zhiliang_biaozhun_guanli_zixiang "
+                            + "WHERE f_id IN (:ids) "
+                            + "AND COALESCE(NULLIF(f_tenant_id, ''), '0') = :tenantId",
+                    row -> text(row.get("display_name")));
+        }
+
+        @Override
+        public Map<String, String> standards(String tenantId, Set<String> ids) {
+            return query("standards", ids, tenantId,
+                    "SELECT f_id, biaozhun_bianhao, mingcheng FROM zhiliang_biaozhun_guanli "
+                            + "WHERE f_id IN (:ids) "
+                            + "AND COALESCE(NULLIF(f_tenant_id, ''), '0') = :tenantId",
+                    row -> join(text(row.get("biaozhun_bianhao")), text(row.get("mingcheng"))));
+        }
+
+        @Override
+        public Map<String, String> users(String tenantId, Set<String> ids) {
+            return query("users", ids, tenantId,
+                    "SELECT f_id, f_real_name, f_account FROM base_user "
+                            + "WHERE f_id IN (:ids) "
+                            + "AND COALESCE(NULLIF(f_tenant_id, ''), '0') = :tenantId",
+                    row -> first(text(row.get("f_real_name")), text(row.get("f_account"))));
+        }
+
+        @Override
+        public Map<String, String> products(String tenantId, Set<String> ids) {
+            return query("products", ids, tenantId,
+                    "SELECT f_id, mingcheng, bianma FROM yangpin_guanli "
+                            + "WHERE f_id IN (:ids) "
+                            + "AND COALESCE(NULLIF(f_tenant_id, ''), '0') = :tenantId",
+                    row -> product(text(row.get("mingcheng")), text(row.get("bianma"))));
+        }
+
+        private Map<String, String> query(String resolverName, Set<String> ids, String tenantId,
+                                          String sql, DisplayFactory factory) {
+            if (ids.isEmpty()) {
+                return Collections.emptyMap();
+            }
+            try {
+                MapSqlParameterSource params = new MapSqlParameterSource()
+                        .addValue("ids", ids)
+                        .addValue("tenantId", tenantId);
+                List<Map<String, Object>> rows = jdbc.queryForList(sql, params);
+                Map<String, String> result = new LinkedHashMap<>();
+                for (Map<String, Object> row : rows) {
+                    String id = text(row.get("f_id"));
+                    String display = factory.display(row);
+                    if (id != null && display != null) {
+                        result.put(id, display);
+                    }
+                }
+                return result;
+            } catch (RuntimeException ex) {
+                log.warn("[AUDIT-QUERY] 瀛楁寮曠敤鎵归噺瑙f瀽澶辫触 resolver={} count={} err={}",
+                        resolverName, ids.size(), ex.getClass().getSimpleName());
+                return Collections.emptyMap();
+            }
+        }
+
+        private interface DisplayFactory {
+            String display(Map<String, Object> row);
+        }
+
+        private static String join(String code, String name) {
+            if (code == null) {
+                return name;
+            }
+            return name == null ? code : code + " 路 " + name;
+        }
+
+        private static String product(String name, String code) {
+            if (name == null) {
+                return code;
+            }
+            return code == null ? name : name + "锛�" + code + "锛�";
+        }
+
+        private static String first(String first, String second) {
+            return first == null ? second : first;
+        }
+
+        private static String text(Object value) {
+            if (value == null) {
+                return null;
+            }
+            String text = String.valueOf(value).trim();
+            return text.isEmpty() ? null : text;
+        }
+    }
+}

--
Gitblit v1.8.0