From a25716c861f2672378eb05d39682b7bf5133286b Mon Sep 17 00:00:00 2001 From: xy Date: Thu, 24 Sep 2026 22:29:10 +0800 Subject: [PATCH] =?UTF-8?q?feat(audit):=20=E5=AE=8C=E6=88=90=E5=AE=A1?= =?UTF-8?q?=E8=AE=A1=E6=97=A5=E5=BF=97=E9=A1=B5=E9=9D=A2=E7=AD=9B=E9=80=89?= =?UTF-8?q?=E4=B8=8E=E5=AF=BC=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- clinical-web/src/api/management/audit.ts | 31 +- clinical-web/src/api/management/types.ts | 12 +- clinical-web/src/utils/mock-flags.ts | 4 +- .../src/views/management/MenuResourceView.vue | 1 + .../src/views/management/audit/index.vue | 577 ++++++++++++++++++ 5 files changed, 618 insertions(+), 7 deletions(-) create mode 100644 clinical-web/src/views/management/audit/index.vue diff --git a/clinical-web/src/api/management/audit.ts b/clinical-web/src/api/management/audit.ts index c79c218..857d974 100644 --- a/clinical-web/src/api/management/audit.ts +++ b/clinical-web/src/api/management/audit.ts @@ -12,8 +12,7 @@ import type { BackendPage, } from './types' -// 审计日志当前只用于签署留痕,跟随签署工作台的开关;后续有独立页面时再拆出来。 -const useMockData = mockFlags.signing +const useMockData = mockFlags.audit function formatDateTime(value: string) { const date = new Date(value) @@ -36,8 +35,10 @@ function mapAuditLog(dto: AuditLogResponseDto): AuditLogRecord { id: dto.id, action: dto.action, resourceType: dto.resourceType, - resourceId: dto.resourceId, - operatorId: dto.operatorId, + resourceId: dto.resourceId ?? '', + operatorId: dto.operatorId ?? '', + operatorName: dto.operatorName ?? (dto.operatorId ? '未知' : '系统'), + operatorRoles: dto.operatorRoles ?? '—', clientIp: dto.clientIp ?? '—', userAgent: dto.userAgent ?? '—', detailsJson: dto.detailsJson ?? '', @@ -74,6 +75,11 @@ export function getAuditLogs(query: AuditLogQuery): Promise>>('/v1/audit-logs', { params }) .then(unwrapApiResponse) @@ -82,3 +88,20 @@ export function getAuditLogs(query: AuditLogQuery): Promise { + const params: Record = { + page: Math.max(query.page, 1), + size: Math.min(Math.max(query.pageSize, 1), 200), + } + if (query.keyword?.trim()) params.keyword = query.keyword.trim() + if (query.createdFrom) params.createdFrom = query.createdFrom + if (query.createdTo) params.createdTo = query.createdTo + if (query.operator?.trim()) params.operator = query.operator.trim() + if (query.module) params.module = query.module + + return request.get('/v1/audit-logs/export', { + params, + responseType: 'blob', + }) +} diff --git a/clinical-web/src/api/management/types.ts b/clinical-web/src/api/management/types.ts index 3b0a376..0180468 100644 --- a/clinical-web/src/api/management/types.ts +++ b/clinical-web/src/api/management/types.ts @@ -886,14 +886,20 @@ export type TemplatePermissionMatrixResponse = PageResult = { 'system/role/index': defineAsyncComponent(() => import('@/views/management/roles/index.vue')), 'doc/library/index': defineAsyncComponent(() => import('@/views/management/documents/index.vue')), 'report/index': defineAsyncComponent(() => import('@/views/management/reports/index.vue')), + 'monitor/audit/index': defineAsyncComponent(() => import('@/views/management/audit/index.vue')), 'report/sign/overview/index': defineAsyncComponent( () => import('@/views/reports/overview/index.vue'), ), diff --git a/clinical-web/src/views/management/audit/index.vue b/clinical-web/src/views/management/audit/index.vue new file mode 100644 index 0000000..c548d60 --- /dev/null +++ b/clinical-web/src/views/management/audit/index.vue @@ -0,0 +1,577 @@ + + + + +