This commit is contained in:
2026-08-14 16:06:30 +08:00
parent 1c1c48f8d3
commit d1b4a4d3f3
26 changed files with 187 additions and 29 deletions
+4 -3
View File
@@ -11,19 +11,20 @@ describe('platform audit api', () => {
beforeEach(() => vi.clearAllMocks())
it('queries the selected customer and preserves long ids as strings', async () => {
vi.mocked(http.get).mockResolvedValue({ data: { records: [{ id: '2082813911786024961', accountId: '8', operatorTenantId: '0', userId: '9', resourceId: '8', eventId: 'evt', eventType: 'PLATFORM_TENANT_UPDATE', resourceType: 'TENANT', description: '编辑客户', username: 'admin', appCode: 'ADMIN', clientType: 'WEB', requestId: null, traceId: null, serviceName: 'iam-service', success: true, errorCode: null, errorMessage: null, occurredAt: '2026-08-13T01:00:00Z', createdAt: '2026-08-13T09:00:00' }], page: 1, size: 20, total: 1, pages: 1 } })
vi.mocked(http.get).mockResolvedValue({ data: { records: [{ id: '2082813911786024961', accountId: '8', operatorTenantId: '0', userId: '9', resourceId: '8', eventId: 'evt', eventType: 'PLATFORM_TENANT_UPDATE', resourceType: 'TENANT', description: '编辑客户', username: 'admin', appCode: 'ADMIN', clientType: 'WEB', clientIp: '127.0.0.1', requestId: null, traceId: null, serviceName: 'iam-service', success: true, errorCode: null, errorMessage: null, occurredAt: '2026-08-13T01:00:00Z', createdAt: '2026-08-13T09:00:00' }], page: 1, size: 20, total: 1, pages: 1 } })
const result = await listPlatformAuditLogs({ accountId: '8', page: 1, size: 20 })
expect(http.get).toHaveBeenCalledWith('/platform/v1/audit/logs', { params: { accountId: '8', page: 1, size: 20 } })
expect(result.records[0].id).toBe('2082813911786024961')
expect(result.records[0].clientIp).toBe('127.0.0.1')
expect(result.total).toBe(1)
expect(result.pages).toBe(1)
})
it('preserves the server total when the current page has fewer records', async () => {
vi.mocked(http.get).mockResolvedValue({ data: {
records: [{ id: '1', accountId: '8', operatorTenantId: '0', userId: '9', resourceId: '8', eventId: 'evt', eventType: 'PLATFORM_TENANT_UPDATE', resourceType: 'TENANT', description: '编辑客户', username: 'admin', appCode: 'ADMIN', clientType: 'WEB', requestId: null, traceId: null, serviceName: 'iam-service', success: true, errorCode: null, errorMessage: null, occurredAt: '2026-08-13T01:00:00Z', createdAt: '2026-08-13T09:00:00' }],
records: [{ id: '1', accountId: '8', operatorTenantId: '0', userId: '9', resourceId: '8', eventId: 'evt', eventType: 'PLATFORM_TENANT_UPDATE', resourceType: 'TENANT', description: '编辑客户', username: 'admin', appCode: 'ADMIN', clientType: 'WEB', clientIp: '127.0.0.1', requestId: null, traceId: null, serviceName: 'iam-service', success: true, errorCode: null, errorMessage: null, occurredAt: '2026-08-13T01:00:00Z', createdAt: '2026-08-13T09:00:00' }],
page: 1, size: 20, total: 13, pages: 1,
} })
@@ -50,7 +51,7 @@ describe('platform audit api', () => {
})
it('loads one audit detail', async () => {
vi.mocked(http.get).mockResolvedValue({ data: { id: '1', accountId: '8', operatorTenantId: '0', userId: '9', resourceId: '8', eventId: 'evt', eventType: 'PLATFORM_TENANT_UPDATE', resourceType: 'TENANT', description: '编辑客户', username: 'admin', appCode: 'ADMIN', clientType: 'WEB', requestId: null, traceId: null, serviceName: 'iam-service', success: true, errorCode: null, errorMessage: null, occurredAt: '2026-08-13T01:00:00Z', createdAt: '2026-08-13T09:00:00', httpMethod: 'PUT', requestUri: '/tenants/8', clientIp: '127.0.0.1', durationMs: 12, beforeData: '{}', afterData: '{"name":"new"}' } })
vi.mocked(http.get).mockResolvedValue({ data: { id: '1', accountId: '8', operatorTenantId: '0', userId: '9', resourceId: '8', eventId: 'evt', eventType: 'PLATFORM_TENANT_UPDATE', resourceType: 'TENANT', description: '编辑客户', username: 'admin', appCode: 'ADMIN', clientType: 'WEB', clientIp: '127.0.0.1', requestId: null, traceId: null, serviceName: 'iam-service', success: true, errorCode: null, errorMessage: null, occurredAt: '2026-08-13T01:00:00Z', createdAt: '2026-08-13T09:00:00', httpMethod: 'PUT', requestUri: '/tenants/8', durationMs: 12, beforeData: '{}', afterData: '{"name":"new"}' } })
const result = await getPlatformAuditLog('1')
expect(http.get).toHaveBeenCalledWith('/platform/v1/audit/logs/1')
+1
View File
@@ -13,6 +13,7 @@ export interface PlatformAuditLogListItem {
username: string | null
appCode: string | null
clientType: string | null
clientIp: string | null
requestId: string | null
traceId: string | null
serviceName: string | null
@@ -10,7 +10,7 @@ import CustomerAuditLogsPanel from './CustomerAuditLogsPanel.vue'
vi.mock('../api/platformAudit', () => ({ getPlatformAuditLog: vi.fn(), listPlatformAuditLogs: vi.fn() }))
const row = { id: '1', eventId: 'evt', eventType: 'PLATFORM_TENANT_UPDATE', resourceType: 'TENANT', resourceId: '8', description: '编辑客户', accountId: '8', operatorTenantId: '0', userId: '9', username: 'platform_admin', appCode: 'ADMIN', clientType: 'WEB', requestId: 'req', traceId: 'trace', serviceName: 'iam-service', success: true, errorCode: null, errorMessage: null, occurredAt: '2026-08-13T01:00:00Z', createdAt: '2026-08-13T09:00:00' }
const row = { id: '1', eventId: 'evt', eventType: 'PLATFORM_TENANT_UPDATE', resourceType: 'TENANT', resourceId: '8', description: '编辑客户', accountId: '8', operatorTenantId: '0', userId: '9', username: 'platform_admin', appCode: 'ADMIN', clientType: 'WEB', clientIp: '127.0.0.1', requestId: 'req', traceId: 'trace', serviceName: 'iam-service', success: true, errorCode: null, errorMessage: null, occurredAt: '2026-08-13T01:00:00Z', createdAt: '2026-08-13T09:00:00' }
function mountPanel(permissions: string[]) {
const pinia = createPinia(); setActivePinia(pinia)
@@ -26,6 +26,7 @@ describe('CustomerAuditLogsPanel', () => {
const wrapper = mountPanel(['platform:audit:list']); await flushPromises()
expect(listPlatformAuditLogs).toHaveBeenCalledWith({ accountId: '8', page: 1, size: 20 })
expect(wrapper.text()).toContain('编辑客户')
expect(wrapper.text()).toContain('127.0.0.1')
})
it('shows the server total instead of the current page row count', async () => {
@@ -36,6 +36,7 @@ const queryFields: QueryField[] = [
const columns: DataTableColumn[] = [
{ key: 'actions', label: '操作', width: 92, fixed: 'left', slotName: 'actions' },
{ key: 'description', label: '操作内容', minWidth: 190, slotName: 'description' },
{ key: 'clientIp', label: 'IP 地址', width: 140, slotName: 'clientIp' },
{ key: 'eventType', prop: 'eventType', label: '事件类型', minWidth: 220 },
{ key: 'username', label: '操作人', width: 140, slotName: 'username' },
{ key: 'serviceName', label: '来源服务', width: 150, slotName: 'serviceName' },
@@ -132,6 +133,7 @@ watch([page, pageSize], ([nextPage, nextSize], [previousPage, previousSize]) =>
<DataTable v-else v-model:page="page" v-model:page-size="pageSize" :data="rows" :columns="columns" :loading="loading" :total="total" row-key="id" aria-label="客户操作日志列表" empty-text="当前客户暂无操作日志" preference-key="customer-audit-logs" border stripe>
<template #actions="{ row }"><el-button link type="primary" :aria-label="`查看操作日志${(row as PlatformAuditLogListItem).id}详情`" @click="openDetail(row as PlatformAuditLogListItem)"><Eye :size="15" />详情</el-button></template>
<template #description="{ row }">{{ display((row as PlatformAuditLogListItem).description) }}</template>
<template #clientIp="{ row }">{{ display((row as PlatformAuditLogListItem).clientIp) }}</template>
<template #username="{ row }">{{ display((row as PlatformAuditLogListItem).username) }}</template>
<template #serviceName="{ row }">{{ display((row as PlatformAuditLogListItem).serviceName) }}</template>
<template #success="{ row }"><el-tag :type="(row as PlatformAuditLogListItem).success ? 'success' : 'danger'">{{ (row as PlatformAuditLogListItem).success ? '成功' : '失败' }}</el-tag></template>