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

diff --git a/jnpf-biz-common/jnpf-biz-common-audit/src/main/java/jnpf/bizcommon/audit/service/value/JnpfUserFieldValueResolver.java b/jnpf-biz-common/jnpf-biz-common-audit/src/main/java/jnpf/bizcommon/audit/service/value/JnpfUserFieldValueResolver.java
new file mode 100644
index 0000000..3401485
--- /dev/null
+++ b/jnpf-biz-common/jnpf-biz-common-audit/src/main/java/jnpf/bizcommon/audit/service/value/JnpfUserFieldValueResolver.java
@@ -0,0 +1,235 @@
+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;
+
+/**
+ * 鎶� {@code userSelect} 鎺т欢瀛樼殑鐢ㄦ埛 id 瑙f瀽鎴愩�岀湡瀹炲鍚�/璐﹀彿銆嶃��
+ *
+ * <p><b>涓轰粈涔堥渶瑕佸畠</b>锛歿@code userSelect} 鐨� valueType 鏄� {@code reference}锛堣
+ * {@link jnpf.bizcommon.audit.service.AuditFormRegistry} 鐨� valueType 鏄犲皠锛夛紝鑰�
+ * {@link jnpf.bizcommon.audit.service.AuditFieldDiffViewService} 瀵规病浜鸿棰嗙殑 reference 涓�寰嬪洖钀芥垚
+ * 銆屽悕绉版殏涓嶅彲鐢ㄣ�嶃�傛鍓嶅彧鏈夊瓧鍏歌В鏋愬櫒鍜岃楠屽崟涓撶敤瑙f瀽鍣紝鐢ㄦ埛 id 鏃犱汉璁ら鈥斺��2026-08-02
+ * 瀹炴祴鍒犻櫎鏍囬 {@code ys0001/ys0001淇敼涓嬪娉�/鍚嶇О鏆備笉鍙敤}锛屾渶鍚庨偅娈靛氨鏄彁浜や汉銆�
+ * <b>杩欐槸鏃㈡湁缂洪櫡鑰屼笉鏄垹闄ゅ満鏅紩鍏ョ殑</b>锛氫互鍓嶆爣棰樺彧鍕句簡缂栧彿鎵�浠ユ病鏆撮湶锛孌6 璁╁垪琛ㄥ嬀閫�
+ * 锛堝惈鎻愪氦浜猴級杩涙爣棰樻墠绗竴娆$幇褰€��
+ *
+ * <p><b>灞曠ず鏍煎紡璺熼殢鍓嶇</b>锛歿@code realName/account}锛堝銆岀鐞嗗憳/admin銆嶏級銆傚钩鍙拌嚜宸卞湪
+ * {@code FormInfoUtils}/{@code OnlineDevInfoUtils} 绛夊崄鍑犲閮芥槸杩欎釜鎷兼硶锛屽璁¢噷鎹釜鍐欐硶
+ * 鍙細璁╀汉鎬�鐤戞槸涓嶆槸鍙︿竴涓汉銆傚甫涓婅处鍙锋槸瀹¤鐨勫垰闇�鈥斺�旈噸鍚嶇殑涓や釜浜洪潬濮撳悕鍒嗕笉寮�銆�
+ *
+ * <p><b>涓嶈繃婊� f_delete_mark / f_enabled_mark</b>锛氬璁¤拷鐨勬槸銆屽綋鏃舵槸璋併�嶃�備汉绂昏亴浜嗐�佽处鍙�
+ * 鍋滅敤浜嗐�佺敤鎴疯鍒犱簡锛屼簨浠堕噷閭d釜 id 鎸囧悜鐨勪粛鐒舵槸鍚屼竴涓汉锛岃繖鏃跺�欐妸鍚嶅瓧鎹㈡垚銆屽悕绉版殏涓嶅彲鐢ㄣ��
+ * 鎭版伆鏄妸鏈�闇�瑕佽拷婧殑閭f潯璁板綍鍙樻垚涓嶅彲杩芥函銆傜鎴疯竟鐣屼粛鐒剁収绾︽潫鈥斺�旈偅鏄暟鎹殧绂伙紝涓嶆槸鍘嗗彶銆�
+ *
+ * <p>涓� {@link LimsQingyandanFieldValueResolver} 鐨勫垎宸ワ細閭d釜鏄〃涓撶敤瑙f瀽鍣紙{@code @Order}
+ * 鏇撮潬鍓嶏級锛寋@code lims_qingyandan.qingyan_ren} 鐢卞畠鎸夎嚜宸辩殑鏍煎紡瑙f瀽瀹岋紝鏈В鏋愬櫒鐪嬪埌
+ * display 宸茬粡鏈夊�煎氨涓嶅啀鎻掓墜锛坽@code displaysResolved}锛夛紝涓よ�呬笉浼氭墦鏋躲��
+ */
+@Slf4j
+@Component
+@Order(JnpfUserFieldValueResolver.ORDER)
+public class JnpfUserFieldValueResolver implements AuditFieldValueResolver {
+
+    /** 閫氱敤鍏滃簳瑙f瀽鍣紝鎺掑湪琛ㄤ笓鐢紙100锛変笌瀛楀吀锛�200锛変箣鍚庛�� */
+    public static final int ORDER = 300;
+
+    private static final String UNAVAILABLE = "鍚嶇О鏆備笉鍙敤";
+
+    /** 璁ら鐨勬帶浠剁被鍨嬶紙灏忓啓姣斿锛夈�傚彧璁や汉鍛橀�夋嫨鍣紝閮ㄩ棬/瑙掕壊/宀椾綅鍚勬湁鍚勭殑鍚嶇О琛紝涓嶅湪鏈被鑼冨洿銆� */
+    private static final String USER_COMPONENT = "userselect";
+
+    private final UserLookup lookup;
+
+    @Autowired
+    public JnpfUserFieldValueResolver(JdbcTemplate jdbcTemplate) {
+        this(new JdbcUserLookup(jdbcTemplate));
+    }
+
+    JnpfUserFieldValueResolver(UserLookup lookup) {
+        this.lookup = lookup;
+    }
+
+    @Override
+    public boolean supports(String targetTable) {
+        return true;   // userSelect 鏄钩鍙版帶浠讹紝鍝紶涓氬姟琛ㄩ兘鍙兘鏈�
+    }
+
+    @Override
+    public void resolve(AuditFieldValueContext context, List<AuditFieldDiffViewVO> fields) {
+        if (context == null || blank(context.getTenantId()) || fields == null || fields.isEmpty()) {
+            return;
+        }
+        Set<String> userIds = new LinkedHashSet<>();
+        for (AuditFieldDiffViewVO field : fields) {
+            if (!isUserField(field) || displaysResolved(field)) {
+                continue;
+            }
+            userIds.addAll(parseValues(field.getOldData()));
+            userIds.addAll(parseValues(field.getNewData()));
+        }
+        if (userIds.isEmpty()) {
+            return;
+        }
+
+        // 鏁存壒涓�娆� IN 鏌ヨ锛圫PI 绾﹀畾锛氬眰 0 璺戝湪 MQ 娑堣垂绾跨▼涓婏紝閫� id 鏌ヤ細鎷栧灝娑堣垂閫熺巼锛�
+        Map<String, String> names = lookup.names(context.getTenantId().trim(), userIds);
+        for (AuditFieldDiffViewVO field : fields) {
+            if (!isUserField(field)) {
+                continue;
+            }
+            if (field.getOldDisplay() == null) {
+                field.setOldDisplay(display(field.getOldData(), names));
+            }
+            if (field.getNewDisplay() == null) {
+                field.setNewDisplay(display(field.getNewData(), names));
+            }
+        }
+    }
+
+    /**
+     * 鍒ゆ嵁鏄�<b>鎺т欢绫诲瀷</b>鑰屼笉鏄瓧娈靛悕锛氬瓧娈靛悕鏄笟鍔¤捣鐨勶紙{@code tijiao_ren}/{@code fuhe_ren}/
+     * {@code qingyan_ren}鈥︼級锛岀┓涓句笉瀹岋紱{@code jnpfKey} 鎵嶆槸銆岃繖涓�鍒楀瓨鐨勬槸鐢ㄦ埛 id銆嶇殑鏉冨▉澹版槑銆�
+     */
+    private static boolean isUserField(AuditFieldDiffViewVO field) {
+        return field != null && field.getComponentType() != null
+                && USER_COMPONENT.equals(field.getComponentType().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> names) {
+        if (blank(raw)) {
+            return "";
+        }
+        List<String> ids = parseValues(raw);
+        if (ids.isEmpty()) {
+            return UNAVAILABLE;
+        }
+        List<String> result = new ArrayList<>(ids.size());
+        for (String id : ids) {
+            String name = names.get(id);
+            result.add(blank(name) ? UNAVAILABLE : name);
+        }
+        return String.join("銆�", result);
+    }
+
+    /** 澶氶�夛紙multiple=true锛夌殑 userSelect 瀛樼殑鏄� JSON 鏁扮粍锛屽崟閫夊瓨瑁� id銆� */
+    @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> 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();
+        }
+    }
+
+    /**
+     * 鍓嶇灞曠ず鏍煎紡鍗� {@code realName/account}锛堝銆岀鐞嗗憳/admin銆嶏級锛涚己涓�杈规椂閫�鍖栨垚杩樺墿鐨�
+     * 閭d竴杈癸紝涓嶇暀瀛ら浂闆剁殑鏂滄潬銆�
+     *
+     * <p>鏀惧湪澶栧眰绫昏�屼笉鏄� {@link JdbcUserLookup} 閲岋紝鏄负浜嗚鎺㈤拡澶熷緱鐫�鈥斺�旀牸寮忔湰韬氨鏄�
+     * 鏈淇鐨勯獙鏀舵爣鍑嗕箣涓�锛堛�屽垹闄ゆ爣棰橀噷鎻愪氦浜烘樉绀虹鐞嗗憳/admin銆嶏級锛屽煁鍦� JDBC 瀹炵幇閲�
+     * 灏卞彧鑳介潬绔埌绔墠楠屽緱鍑烘潵銆�
+     */
+    static String userDisplay(String realName, String account) {
+        if (blank(realName)) {
+            return blank(account) ? null : account.trim();
+        }
+        return blank(account) ? realName.trim() : realName.trim() + "/" + account.trim();
+    }
+
+    private static boolean blank(String value) {
+        return value == null || value.trim().isEmpty();
+    }
+
+    interface UserLookup {
+        Map<String, String> names(String tenantId, Set<String> ids);
+    }
+
+    /** 琛ㄥ悕鍜屽垪鍚嶅浐瀹氾紱id 涓庣鎴峰叏閮ㄥ弬鏁板寲銆� */
+    private static final class JdbcUserLookup implements UserLookup {
+        private final NamedParameterJdbcTemplate jdbc;
+
+        private JdbcUserLookup(JdbcTemplate jdbcTemplate) {
+            this.jdbc = new NamedParameterJdbcTemplate(jdbcTemplate);
+        }
+
+        @Override
+        public Map<String, String> names(String tenantId, Set<String> ids) {
+            if (ids.isEmpty()) {
+                return Collections.emptyMap();
+            }
+            try {
+                MapSqlParameterSource params = new MapSqlParameterSource()
+                        .addValue("ids", ids)
+                        .addValue("tenantId", tenantId);
+                List<Map<String, Object>> rows = jdbc.queryForList(
+                        "SELECT f_id, f_real_name, f_account FROM base_user "
+                                + "WHERE f_id IN (:ids) "
+                                + "AND COALESCE(NULLIF(f_tenant_id, ''), '0') = :tenantId",
+                        params);
+                Map<String, String> result = new LinkedHashMap<>();
+                for (Map<String, Object> row : rows) {
+                    String id = text(row.get("f_id"));
+                    String display = userDisplay(text(row.get("f_real_name")),
+                            text(row.get("f_account")));
+                    if (id != null && display != null) {
+                        result.put(id, display);
+                    }
+                }
+                return result;
+            } catch (RuntimeException ex) {
+                log.warn("[AUDIT-QUERY] 鐢ㄦ埛鍚嶇О鎵归噺瑙f瀽澶辫触 count={} err={}",
+                        ids.size(), ex.getClass().getSimpleName());
+                return Collections.emptyMap();
+            }
+        }
+
+        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