fix: 审计事件详情

This commit is contained in:
luo
2026-08-10 14:44:59 +08:00
parent 9f7f619083
commit 373ad4c2a5
3 changed files with 101 additions and 33 deletions

View File

@@ -99,32 +99,11 @@
><AuditInvestigationLinks
:refs="detail.investigation_refs"
:current-event-id="detail.event_id"
:show-resources="false"
/></ElCard>
<ElCard shadow="never" class="section-card">
<template #header>相关资源与快照</template>
<ElTable :data="detail.resources || []" :row-key="resourceRowKey">
<ElTableColumn type="expand" width="48">
<template #default="{ row }">
<div class="resource-snapshot-grid">
<section>
<h4>身份快照</h4>
<pre>{{ auditJson(row.identity_snapshot) }}</pre>
</section>
<section>
<h4>变更前</h4>
<pre>{{ auditJson(row.before_data) }}</pre>
</section>
<section>
<h4>变更后</h4>
<pre>{{ auditJson(row.after_data) }}</pre>
</section>
<section>
<h4>主体安全数据</h4>
<pre>{{ auditJson(row.subject_data) }}</pre>
</section>
</div>
</template>
</ElTableColumn>
<ElTableColumn
prop="display_name"
label="资源"
@@ -141,7 +120,7 @@
auditResourceRelationLabels[row.relation] || row.relation
}}</template>
</ElTableColumn>
<ElTableColumn prop="role" label="业务角色" min-width="150" />
<ElTableColumn prop="role" label="业务角色" min-width="160" show-overflow-tooltip />
<ElTableColumn label="主体可见性" min-width="150">
<template #default="{ row }">{{
auditSubjectVisibilityLabels[row.subject_visibility] ||
@@ -160,6 +139,19 @@
row.created_at ? formatDateTime(row.created_at) : '-'
}}</template>
</ElTableColumn>
<ElTableColumn label="操作" width="220" fixed="right">
<template #default="{ row }">
<ElButton link type="primary" @click="openSnapshotDialog(row)">查看快照</ElButton>
<ElButton
link
type="primary"
:disabled="!row.resource_id"
@click="openResourceTimeline(row)"
>
资源审计时间线
</ElButton>
</template>
</ElTableColumn>
</ElTable>
</ElCard>
<ElCard v-if="userStore.isSuperAdmin" shadow="never">
@@ -170,6 +162,37 @@
<ElEmpty v-else-if="!loading" description="未找到审计事件" />
</div>
</ElCard>
<ElDialog
v-model="snapshotDialogVisible"
:title="snapshotDialogTitle"
width="min(960px, calc(100% - 32px))"
destroy-on-close
>
<div v-if="selectedResource" class="resource-snapshot-grid">
<ElCollapse class="resource-snapshot-section">
<ElCollapseItem title="身份快照" name="identity">
<pre>{{ auditJson(selectedResource.identity_snapshot) }}</pre>
</ElCollapseItem>
</ElCollapse>
<ElCollapse class="resource-snapshot-section">
<ElCollapseItem title="主体安全数据" name="subject">
<pre>{{ auditJson(selectedResource.subject_data) }}</pre>
</ElCollapseItem>
</ElCollapse>
<section class="resource-snapshot-diff">
<ElCollapse class="resource-snapshot-section">
<ElCollapseItem title="变更前" name="before">
<pre>{{ auditJson(selectedResource.before_data) }}</pre>
</ElCollapseItem>
</ElCollapse>
<ElCollapse class="resource-snapshot-section">
<ElCollapseItem title="变更后" name="after">
<pre>{{ auditJson(selectedResource.after_data) }}</pre>
</ElCollapseItem>
</ElCollapse>
</section>
</div>
</ElDialog>
</div>
</template>
@@ -195,6 +218,7 @@
import { formatDateTime } from '@/utils/business/format'
import { useUserStore } from '@/store/modules/user'
import AuditInvestigationLinks from '@/components/business/audit/AuditInvestigationLinks.vue'
import { openAuditInvestigation } from '@/components/business/audit/investigationController'
defineOptions({ name: 'AuditEventDetail' })
const route = useRoute()
@@ -202,6 +226,14 @@
const userStore = useUserStore()
const loading = ref(false)
const detail = ref<AuditEventDetail>()
const snapshotDialogVisible = ref(false)
const selectedResource = ref<AuditResourceView>()
const snapshotDialogTitle = computed(() => {
const resource = selectedResource.value
if (!resource) return '资源快照'
const type = auditResourceTypeLabels[resource.resource_type] || resource.resource_type
return `资源快照 · ${resource.display_name || resource.resource_id || type}`
})
const scopeDisplay = computed(() => {
if (!detail.value) return '-'
const type = auditScopeTypeLabels[detail.value.scope_type] || detail.value.scope_type
@@ -223,6 +255,18 @@
[row.resource_type, row.resource_id || row.resource_key || row.sort_order || row.display_name]
.filter((item) => item !== null && item !== undefined && item !== '')
.join(':')
const openSnapshotDialog = (row: AuditResourceView) => {
selectedResource.value = row
snapshotDialogVisible.value = true
}
const openResourceTimeline = (row: AuditResourceView) => {
if (!row.resource_id) return
openAuditInvestigation({
mode: 'resource',
resourceType: row.resource_type,
id: row.resource_id
})
}
onMounted(async () => {
const id = String(route.params.eventId || '')
if (!id) return
@@ -279,14 +323,22 @@
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 16px;
padding: 8px 16px 16px;
padding: 8px 0;
}
.resource-snapshot-grid h4 {
margin: 0 0 8px;
font-size: 14px;
font-weight: 600;
color: var(--el-text-color-primary);
.resource-snapshot-diff {
display: grid;
grid-column: 1 / -1;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 16px;
}
.resource-snapshot-section {
min-width: 0;
}
.resource-snapshot-section :deep(.el-collapse-item__content) {
padding-bottom: 0;
}
.resource-snapshot-grid pre {
@@ -319,5 +371,9 @@
.resource-snapshot-grid {
grid-template-columns: 1fr;
}
.resource-snapshot-diff {
grid-template-columns: 1fr;
}
}
</style>