操作审计(Audit Log)
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
import { auditDict } from "./auditDict";
|
||||
import { roleDict, getDictLabel, statusDict } from "../dictionaries";
|
||||
|
||||
export interface AuditEvent {
|
||||
eventType: string;
|
||||
eventLabel: string;
|
||||
actorId: string;
|
||||
actorName: string;
|
||||
actorRole: string;
|
||||
actorRoleLabel: string;
|
||||
targetType: string;
|
||||
targetTypeLabel: string;
|
||||
targetId: string;
|
||||
targetName?: string;
|
||||
actionText: string;
|
||||
before?: Record<string, any>;
|
||||
after?: Record<string, any>;
|
||||
diffText?: string[];
|
||||
result: "SUCCESS" | "FAIL";
|
||||
resultLabel: string;
|
||||
timestamp: string;
|
||||
}
|
||||
|
||||
const buildDiffText = (before?: Record<string, any>, after?: Record<string, any>) => {
|
||||
if (!before || !after) return [];
|
||||
const lines: string[] = [];
|
||||
Object.keys({ ...before, ...after }).forEach((key) => {
|
||||
const prev = before[key];
|
||||
const next = after[key];
|
||||
if (prev === next) return;
|
||||
if (key.toLowerCase().includes("status")) {
|
||||
lines.push(`状态:${getDictLabel(statusDict, prev)} → ${getDictLabel(statusDict, next)}`);
|
||||
} else {
|
||||
lines.push(`${key}:${prev ?? "-"} → ${next ?? "-"}`);
|
||||
}
|
||||
});
|
||||
return lines;
|
||||
};
|
||||
|
||||
export const normalizeAuditEvent = (raw: any, userMap: Record<string, string>): AuditEvent => {
|
||||
const dict = auditDict[raw.action] || {
|
||||
label: "系统操作",
|
||||
actionText: "执行了操作",
|
||||
targetLabel: raw.entity_type || "对象",
|
||||
};
|
||||
let detailObj: any = {};
|
||||
if (raw.detail) {
|
||||
try {
|
||||
detailObj = JSON.parse(raw.detail);
|
||||
} catch {
|
||||
detailObj = { description: raw.detail };
|
||||
}
|
||||
}
|
||||
const before = detailObj.before;
|
||||
const after = detailObj.after;
|
||||
const diffText = detailObj.diffText || buildDiffText(before, after);
|
||||
return {
|
||||
eventType: raw.action,
|
||||
eventLabel: dict.label,
|
||||
actorId: raw.operator_id,
|
||||
actorName: userMap[raw.operator_id] || raw.operator_id,
|
||||
actorRole: raw.operator_role,
|
||||
actorRoleLabel: getDictLabel(roleDict, raw.operator_role),
|
||||
targetType: raw.entity_type || "",
|
||||
targetTypeLabel: dict.targetLabel,
|
||||
targetId: raw.entity_id || "",
|
||||
targetName: detailObj.targetName,
|
||||
actionText: dict.actionText,
|
||||
before,
|
||||
after,
|
||||
diffText: Array.isArray(diffText) ? diffText : diffText ? [diffText] : [],
|
||||
result: detailObj.result || "SUCCESS",
|
||||
resultLabel: detailObj.result === "FAIL" ? "失败" : "成功",
|
||||
timestamp: raw.created_at,
|
||||
};
|
||||
};
|
||||
|
||||
export { auditDict };
|
||||
|
||||
// 前端占位的 logAudit:不修改后端逻辑,失败不影响主流程
|
||||
export const logAudit = async (_eventType: string, _payload: Record<string, any>) => Promise.resolve();
|
||||
Reference in New Issue
Block a user