全局中文化

This commit is contained in:
Cheng Zhou
2026-01-12 11:14:04 +08:00
parent 9021c7fe2b
commit 1338fa7e2b
103 changed files with 2443 additions and 1533 deletions
+4 -85
View File
@@ -1,85 +1,4 @@
export const auditDict: Record<
string,
{ label: string; actionText: string; targetLabel: string }
> = {
AE_CLOSED: {
label: "关闭 AE(不良事件)",
actionText: "关闭了 AE",
targetLabel: "不良事件",
},
SUBJECT_STATUS_CHANGED: {
label: "受试者状态变更",
actionText: "变更了受试者状态",
targetLabel: "受试者",
},
FINANCE_STATUS_CHANGED: {
label: "费用状态变更",
actionText: "变更了费用状态",
targetLabel: "费用记录",
},
ADMIN_RESET_PASSWORD: {
label: "重置用户密码",
actionText: "重置了用户密码",
targetLabel: "用户账号",
},
ISSUE_STATUS_CHANGED: {
label: "风险/问题状态变更",
actionText: "更新了风险/问题状态",
targetLabel: "风险/问题",
},
UNAUTHORIZED_ACTION_ATTEMPT: {
label: "越权操作尝试",
actionText: "尝试执行无权限操作",
targetLabel: "系统资源",
},
INVALID_STATE_TRANSITION_ATTEMPT: {
label: "非法状态流转尝试",
actionText: "尝试执行非法状态流转",
targetLabel: "业务对象",
},
PROJECT_MEMBER_UPDATED: {
label: "项目成员变更",
actionText: "调整了项目成员",
targetLabel: "项目成员",
},
SITE_CRA_BOUND: {
label: "中心 CRA 绑定",
actionText: "调整了中心与 CRA 的绑定",
targetLabel: "中心",
},
SITE_STATUS_CHANGED: {
label: "中心状态变更",
actionText: "更新了中心信息",
targetLabel: "中心",
},
AUDIT_EXPORT_SYSTEM: {
label: "导出系统审计",
actionText: "导出了系统审计日志",
targetLabel: "审计日志",
},
AUDIT_EXPORT_PROJECT: {
label: "导出项目审计",
actionText: "导出了项目审计日志",
targetLabel: "审计日志",
},
FINANCE_APPROVED: {
label: "费用审批",
actionText: "审批通过费用",
targetLabel: "费用",
},
FINANCE_REJECTED: {
label: "费用驳回",
actionText: "驳回了费用",
targetLabel: "费用",
},
IMP_CONFIRMED: {
label: "药品出入库确认",
actionText: "确认了药品出入库记录",
targetLabel: "药品交易",
},
QUERY_RESOLVED: {
label: "数据问题解决",
actionText: "标记数据问题已解决",
targetLabel: "数据问题",
},
};
import { TEXT } from "../locales";
export const auditDict: Record<string, { label: string; actionText: string; targetLabel: string }> =
TEXT.audit.eventDict;
+16 -14
View File
@@ -1,21 +1,23 @@
import { TEXT } from "../../locales";
export interface AuditExportColumn {
key: string;
label: string;
}
export const auditExportColumns: AuditExportColumn[] = [
{ key: "timestamp", label: "审计时间" },
{ key: "actorName", label: "操作人姓名" },
{ key: "actorId", label: "操作人账号" },
{ key: "actorRoleLabel", label: "操作人角色" },
{ key: "eventLabel", label: "操作类型" },
{ key: "targetTypeLabel", label: "操作对象类型" },
{ key: "targetIdentifier", label: "操作对象标识" },
{ key: "description", label: "操作描述" },
{ key: "beforeStatus", label: "操作前状态" },
{ key: "afterStatus", label: "操作后状态" },
{ key: "resultLabel", label: "操作结果" },
{ key: "reason", label: "拒绝原因" },
{ key: "ip", label: "IP 地址" },
{ key: "remark", label: "备注" },
{ key: "timestamp", label: TEXT.audit.exportColumns.timestamp },
{ key: "actorName", label: TEXT.audit.exportColumns.actorName },
{ key: "actorId", label: TEXT.audit.exportColumns.actorId },
{ key: "actorRoleLabel", label: TEXT.audit.exportColumns.actorRoleLabel },
{ key: "eventLabel", label: TEXT.audit.exportColumns.eventLabel },
{ key: "targetTypeLabel", label: TEXT.audit.exportColumns.targetTypeLabel },
{ key: "targetIdentifier", label: TEXT.audit.exportColumns.targetIdentifier },
{ key: "description", label: TEXT.audit.exportColumns.description },
{ key: "beforeStatus", label: TEXT.audit.exportColumns.beforeStatus },
{ key: "afterStatus", label: TEXT.audit.exportColumns.afterStatus },
{ key: "resultLabel", label: TEXT.audit.exportColumns.resultLabel },
{ key: "reason", label: TEXT.audit.exportColumns.reason },
{ key: "ip", label: TEXT.audit.exportColumns.ip },
{ key: "remark", label: TEXT.audit.exportColumns.remark },
];
@@ -1,6 +1,7 @@
import { getDictLabel, statusDict } from "../../dictionaries";
import type { AuditEvent } from "..";
import { auditExportColumns } from "./auditExportColumns";
import { TEXT } from "../../locales";
export interface AuditExportRow {
[key: string]: string;
@@ -19,11 +20,12 @@ export const formatAuditRow = (event: AuditEvent): AuditExportRow => {
descriptionParts.push(`${event.actorName} ${event.actionText}`);
if (event.targetTypeLabel || event.targetName || event.targetId) {
descriptionParts.push(
`对象:${event.targetTypeLabel || ""}${event.targetName ? `${event.targetName}` : `${event.targetId}`})`
`${TEXT.audit.objectLabel}${event.targetTypeLabel || ""}${
event.targetName ? `${event.targetName}` : `${event.targetId}`})`
);
}
if (event.diffText?.length) {
descriptionParts.push(`变更:${event.diffText.join("")}`);
descriptionParts.push(`${TEXT.audit.changeLabel}${event.diffText.join("")}`);
}
return {
+9 -8
View File
@@ -2,6 +2,7 @@ import { auditDict } from "./auditDict";
import { roleDict, getDictLabel, statusDict } from "../dictionaries";
import { useAuthStore } from "../store/auth";
import { useStudyStore } from "../store/study";
import { TEXT } from "../locales";
export interface AuditEvent {
eventType: string;
@@ -32,9 +33,9 @@ const buildDiffText = (before?: Record<string, any>, after?: Record<string, any>
const next = after[key];
if (prev === next) return;
if (key.toLowerCase().includes("status")) {
lines.push(`状态:${getDictLabel(statusDict, prev)}${getDictLabel(statusDict, next)}`);
lines.push(`${TEXT.audit.statusLabel}${getDictLabel(statusDict, prev)}${getDictLabel(statusDict, next)}`);
} else {
lines.push(`${key}${prev ?? "-"}${next ?? "-"}`);
lines.push(`${key}${prev ?? TEXT.audit.emptyValue}${next ?? TEXT.audit.emptyValue}`);
}
});
return lines;
@@ -42,9 +43,9 @@ const buildDiffText = (before?: Record<string, any>, after?: Record<string, any>
export const normalizeAuditEvent = (raw: any, userMap: Record<string, string>): AuditEvent => {
const dict = auditDict[raw.action] || {
label: "系统操作",
actionText: "执行了操作",
targetLabel: raw.entity_type || "对象",
label: TEXT.audit.eventFallback,
actionText: TEXT.audit.actionFallback,
targetLabel: raw.entity_type || TEXT.audit.targetFallback,
};
let detailObj: any = {};
if (raw.detail) {
@@ -74,7 +75,7 @@ export const normalizeAuditEvent = (raw: any, userMap: Record<string, string>):
diffText: Array.isArray(diffText) ? diffText : diffText ? [diffText] : [],
reason: detailObj.reason,
result: detailObj.result || "SUCCESS",
resultLabel: detailObj.result === "FAIL" ? "失败" : "成功",
resultLabel: detailObj.result === "FAIL" ? TEXT.audit.resultFail : TEXT.audit.resultSuccess,
timestamp: raw.created_at,
};
};
@@ -105,9 +106,9 @@ export const logAudit = async (eventType: string, payload: Record<string, any>)
const studyId = study.currentStudy?.id || null;
const log = {
action: eventType,
operator_id: user?.id || user?.username || "current_user",
operator_id: user?.id || user?.username || TEXT.audit.currentUser,
operator_role: user?.role || "",
entity_type: payload.targetType || "client",
entity_type: payload.targetType || TEXT.audit.localClient,
entity_id: payload.targetId || "",
created_at: new Date().toISOString(),
detail: JSON.stringify({