刘帅
2026-09-22 652951bd0ce1eebcae43221e50d4cfda99c10aba
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package com.dsh.guns.modular.system.audit;
 
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.ApiModelProperty;
import cn.mb.cloud.common.core.util.SpringContextHolder;
 
import java.lang.reflect.Field;
import java.util.LinkedHashMap;
import java.util.Map;
 
/** 审计数据统一脱敏并将常用字段名转换为中文,供日志页面直接展示。 */
public final class AuditDataFormatter {
    private static final Map<String, String> FIELD_NAMES = new LinkedHashMap<String, String>();
    static {
        FIELD_NAMES.put("id", "ID"); FIELD_NAMES.put("ids", "ID列表");
        FIELD_NAMES.put("name", "名称"); FIELD_NAMES.put("username", "用户名"); FIELD_NAMES.put("userName", "用户名");
        FIELD_NAMES.put("account", "账号"); FIELD_NAMES.put("phone", "手机号"); FIELD_NAMES.put("mobile", "手机号");
        FIELD_NAMES.put("password", "密码"); FIELD_NAMES.put("oldPwd", "旧密码"); FIELD_NAMES.put("newPwd", "新密码");
        FIELD_NAMES.put("idCard", "身份证号"); FIELD_NAMES.put("identity", "身份信息");
        FIELD_NAMES.put("status", "状态"); FIELD_NAMES.put("state", "状态"); FIELD_NAMES.put("type", "类型");
        FIELD_NAMES.put("birthday", "生日"); FIELD_NAMES.put("sex", "性别"); FIELD_NAMES.put("roleid", "角色ID");
        FIELD_NAMES.put("deptid", "部门ID"); FIELD_NAMES.put("avatar", "头像"); FIELD_NAMES.put("jstime", "入职时间");
        FIELD_NAMES.put("email", "邮箱"); FIELD_NAMES.put("objectType", "归属类型"); FIELD_NAMES.put("objectId", "归属对象ID");
        FIELD_NAMES.put("remark", "备注"); FIELD_NAMES.put("reason", "原因"); FIELD_NAMES.put("content", "内容");
        FIELD_NAMES.put("operatorId", "运营商ID"); FIELD_NAMES.put("storeId", "门店ID");
        FIELD_NAMES.put("userId", "用户ID"); FIELD_NAMES.put("roleId", "角色ID"); FIELD_NAMES.put("roleIds", "角色ID列表");
        FIELD_NAMES.put("cityId", "城市ID"); FIELD_NAMES.put("courseId", "课程ID");
        FIELD_NAMES.put("createdAt", "创建时间"); FIELD_NAMES.put("updateTime", "更新时间");
    }
 
    private AuditDataFormatter() { }
 
    public static String format(Object value) {
        return format(value, null);
    }
 
    /** entityType 非空时,字段中文名完全由实体注解决定。 */
    public static String format(Object value, Class<?> entityType) {
        if (value == null) return null;
        Object json = value instanceof String ? parse((String) value) : JSON.toJSON(value);
        return mask(JSON.toJSONString(localize(json, entityType)));
    }
 
    private static Object parse(String value) {
        try { return JSON.parse(value); } catch (Exception ignored) { return value; }
    }
 
    private static Object localize(Object value, Class<?> entityType) {
        if (value instanceof JSONObject) {
            JSONObject source = (JSONObject) value;
            JSONObject target = new JSONObject(true);
            for (Map.Entry<String, Object> entry : source.entrySet()) {
                target.put(displayName(entry.getKey(), entityType), localize(entry.getValue(), null));
            }
            return target;
        }
        if (value instanceof Map) {
            JSONObject target = new JSONObject(true);
            for (Object item : ((Map<?, ?>) value).entrySet()) {
                Map.Entry<?, ?> entry = (Map.Entry<?, ?>) item;
                target.put(displayName(String.valueOf(entry.getKey()), entityType), localize(entry.getValue(), null));
            }
            return target;
        }
        if (value instanceof JSONArray) {
            JSONArray target = new JSONArray();
            for (Object item : (JSONArray) value) target.add(localize(item, null));
            return target;
        }
        return value;
    }
 
    private static String displayName(String field, Class<?> entityType) {
        String annotated = annotationName(entityType, field);
        if (annotated != null) return annotated;
        String name = FIELD_NAMES.get(field);
        return name == null ? field : name;
    }
 
    private static String annotationName(Class<?> entityType, String fieldName) {
        if (entityType == null) return null;
        for (Class<?> type = entityType; type != null && type != Object.class; type = type.getSuperclass()) {
            try {
                Field field = type.getDeclaredField(fieldName);
                AuditField audit = field.getAnnotation(AuditField.class);
                if (audit != null) return audit.value();
                ApiModelProperty api = field.getAnnotation(ApiModelProperty.class);
                if (api != null && api.value() != null && !api.value().trim().isEmpty()) return api.value();
            } catch (NoSuchFieldException ignored) { }
        }
        try {
            String comment = SpringContextHolder.getBean(AuditColumnCommentResolver.class).resolve(entityType).get(fieldName);
            if (comment != null && !comment.trim().isEmpty()) return comment;
        } catch (Exception ignored) {
            // 审计展示名解析失败时回退字段名,不能影响业务。
        }
        return null;
    }
 
    private static String mask(String text) {
        return text.replaceAll("(?i)(\\\"?(password|oldpwd|newpwd|token|authorization|secret|idcard|identity|bank(card)?|mobile|phone|密码|手机号|身份证号)\\\"?\\s*[:=]\\s*)\\\"[^\\\"]*\\\"", "$1\\\"***\\\"");
    }
}