刘光辉
3 小时以前 06f314545ac3514d7ce28939920866ae8188d31c
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
package jnpf.dmsIntegration.audit;
 
import jnpf.audit.AuditConsts;
import jnpf.audit.diff.AuditFieldDiff;
import jnpf.audit.model.AuditEventDTO;
import jnpf.audit.sdk.AuditClient;
import jnpf.util.JsonUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.web.context.request.RequestContextHolder;
 
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
 
/** DMS 后端直接变更的审计;不再次记录原生表单的创建/编辑。 */
@Component
@RequiredArgsConstructor
public class DmsBusinessChangeAudit {
    private final ObjectProvider<AuditClient> clients;
    private final DmsSystemAudit systemAudit;
 
    /** 调用方在实际写入成功后提交旧/新事实;SDK 在事务提交后投递,回滚不投递。 */
    public void record(String tenantId, String action, String label, String table, String id,
                       Map<String, Object> before, Map<String, Object> after,
                       String reason, Map<String, Object> context) {
        String differences = AuditFieldDiff.diff(before, after, Collections.emptySet());
        if ("[]".equals(differences)) return;
        AuditEventDTO event = AuditEventDTO.builder()
                .tenantId(tenantId).eventType(AuditConsts.TYPE_DATA_CHANGE)
                .actionCode(action).actionLabel(label).bizModule("DMS").bizType("DMS_BUSINESS_CHANGE")
                .bizCode(id).targetTable(table).targetId(id).recordTitle(label + " · " + id)
                .fieldDiffs(differences).dataSnapshot(JsonUtil.getObjectToString(after))
                .reason(reason).extra(JsonUtil.getObjectToString(context))
                .relatedSigns(DmsAuditRequestSignResolver.resolve(context)).sourceLayer(3).build();
        if (RequestContextHolder.getRequestAttributes() == null) {
            // 自动执行者与批准来源分开;批准人等来源身份由调用方放在 context。
            event.setOperatorId("0");
            event.setOperatorName("系统自动执行");
            systemAudit.record(event);
        } else {
            clients.ifAvailable(client -> client.record(event));
        }
    }
 
    /** 允许空值,保持旧/新事实中未设置的字段;调用方只选取本次业务变化字段。 */
    public static Map<String, Object> values(Object... pairs) {
        if (pairs.length % 2 != 0) throw new IllegalArgumentException("审计字段必须成对");
        Map<String, Object> result = new LinkedHashMap<>();
        for (int i = 0; i < pairs.length; i += 2) result.put((String) pairs[i], pairs[i + 1]);
        return result;
    }
}