发布 0.1.0:通知渠道、告警规则与多项体验修复
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { NButton, NDataTable, NModal, NSelect, useMessage, type DataTableColumns } from 'naive-ui'
|
||||
import { computed, h, onMounted, reactive, ref, watch } from 'vue'
|
||||
import { NButton, NDataTable, NModal, type DataTableColumns } from 'naive-ui'
|
||||
import { computed, h, onMounted, reactive, ref } from 'vue'
|
||||
|
||||
import { getAuditEventDetail, listAuditEvents } from '@/api/tenant'
|
||||
import DetailFieldList, { type DetailRow } from '@/components/DetailFieldList.vue'
|
||||
@@ -11,17 +11,21 @@ import StatusBadge from '@/components/StatusBadge.vue'
|
||||
import { eventLabel } from '@/composables/useEventLabel'
|
||||
import { fmtTime } from '@/composables/useFormat'
|
||||
import type { AuditEvent } from '@/types/api'
|
||||
import { useToast } from '@/composables/useToast'
|
||||
|
||||
const props = defineProps<{ cfgId: number }>()
|
||||
const message = useMessage()
|
||||
const message = useToast()
|
||||
|
||||
const hours = ref(24)
|
||||
const hourOptions = [
|
||||
{ label: '近 1 小时', value: 1 },
|
||||
{ label: '近 6 小时', value: 6 },
|
||||
{ label: '近 24 小时', value: 24 },
|
||||
{ label: '近 72 小时', value: 72 },
|
||||
]
|
||||
const loading = ref(false)
|
||||
const loadingMore = ref(false)
|
||||
const error = ref('')
|
||||
const rows = ref<AuditEvent[]>([])
|
||||
// 服务端分窗回溯游标:空且 exhausted 表示已到 365 天保留期尽头
|
||||
const cursor = ref('')
|
||||
const exhausted = ref(false)
|
||||
|
||||
const pageCount = computed(() => Math.max(1, Math.ceil(rows.value.length / pagination.pageSize)))
|
||||
const hasMore = computed(() => cursor.value !== '' && !exhausted.value)
|
||||
|
||||
/** 受控分页:字面量对象会在重渲染时被重建导致页大小切换失效 */
|
||||
const pagination = reactive({
|
||||
@@ -29,8 +33,13 @@ const pagination = reactive({
|
||||
pageSize: 20,
|
||||
showSizePicker: true,
|
||||
pageSizes: [20, 50, 100],
|
||||
prefix: () =>
|
||||
`已加载 ${rows.value.length} 条 · ` +
|
||||
(loadingMore.value ? '正在加载更早…' : exhausted.value ? '已到 365 天保留期尽头' : '翻到末页自动加载更早'),
|
||||
onUpdatePage: (p: number) => {
|
||||
pagination.page = p
|
||||
// 懒加载触发点:翻到已加载数据的最后一页即向后端续取一批
|
||||
if (p >= pageCount.value) void fetchBatch()
|
||||
},
|
||||
onUpdatePageSize: (ps: number) => {
|
||||
pagination.pageSize = ps
|
||||
@@ -38,55 +47,48 @@ const pagination = reactive({
|
||||
},
|
||||
})
|
||||
|
||||
const loading = ref(false)
|
||||
const loadingMore = ref(false)
|
||||
const error = ref('')
|
||||
const rows = ref<AuditEvent[]>([])
|
||||
const truncated = ref(false)
|
||||
const nextPage = ref('')
|
||||
// 本次查询的绝对时间窗:续查游标绑定查询参数,必须原样带回
|
||||
const win = ref<{ start: string; end: string } | null>(null)
|
||||
|
||||
/** 重置信息流:回到最新一批 */
|
||||
async function load() {
|
||||
loading.value = true
|
||||
error.value = ''
|
||||
rows.value = []
|
||||
cursor.value = ''
|
||||
exhausted.value = false
|
||||
pagination.page = 1
|
||||
try {
|
||||
const r = await listAuditEvents(props.cfgId, { hours: hours.value })
|
||||
rows.value = r.items
|
||||
truncated.value = r.truncated
|
||||
nextPage.value = r.nextPage ?? ''
|
||||
win.value = { start: r.start, end: r.end }
|
||||
pagination.page = 1
|
||||
} catch (e) {
|
||||
error.value = e instanceof Error ? e.message : '查询失败'
|
||||
await fetchBatch(true)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 截断续查:同一绝对窗带游标断点续翻,追加去重后按时间重排 */
|
||||
async function loadMore() {
|
||||
if (!win.value || !nextPage.value || loadingMore.value) return
|
||||
/** 向更早方向续取一批(~100 条):追加去重后按时间重排;
|
||||
* 末页不满且还有更早数据时自动补一批,避免首屏残页 */
|
||||
async function fetchBatch(first = false) {
|
||||
if (loadingMore.value || (!first && !hasMore.value)) return
|
||||
loadingMore.value = true
|
||||
try {
|
||||
const r = await listAuditEvents(props.cfgId, { ...win.value, page: nextPage.value })
|
||||
const r = await listAuditEvents(props.cfgId, { cursor: cursor.value || undefined })
|
||||
const seen = new Set(rows.value.map((e) => e.eventId))
|
||||
rows.value = [...rows.value, ...r.items.filter((e) => !seen.has(e.eventId))].sort((a, b) =>
|
||||
(b.eventTime ?? '').localeCompare(a.eventTime ?? ''),
|
||||
)
|
||||
truncated.value = r.truncated
|
||||
nextPage.value = r.nextPage ?? ''
|
||||
cursor.value = r.cursor ?? ''
|
||||
exhausted.value = r.exhausted
|
||||
} catch (e) {
|
||||
// 追加失败不清空已有列表;游标过期时提示重新查询
|
||||
message.error(e instanceof Error ? e.message : '继续加载失败,请刷新重新查询')
|
||||
if (first) {
|
||||
error.value = e instanceof Error ? e.message : '查询失败'
|
||||
} else {
|
||||
// 追加失败不清空已有列表;游标过期时提示刷新重来
|
||||
message.error(e instanceof Error ? e.message : '继续加载失败,请刷新重新查询')
|
||||
}
|
||||
} finally {
|
||||
loadingMore.value = false
|
||||
}
|
||||
if (hasMore.value && rows.value.length < pagination.pageSize) void fetchBatch()
|
||||
}
|
||||
|
||||
onMounted(() => void load())
|
||||
// 切换时间窗自动重查并回到第一页
|
||||
watch(hours, () => void load())
|
||||
|
||||
// ---- 行点击详情:原始 JSON 懒取(命中服务端缓存秒开,过期走小窗重查) ----
|
||||
const detail = ref<AuditEvent | null>(null)
|
||||
@@ -202,16 +204,8 @@ const columns: DataTableColumns<AuditEvent> = [
|
||||
<div class="panel">
|
||||
<div class="flex flex-wrap items-center gap-2.5 border-b border-line-soft px-4.5 py-3">
|
||||
<div class="text-sm font-semibold">审计日志</div>
|
||||
<template v-if="truncated">
|
||||
<StatusBadge kind="warn" label="结果已截断" />
|
||||
<NButton v-if="nextPage" size="tiny" :loading="loadingMore" @click="loadMore">
|
||||
继续加载更早
|
||||
</NButton>
|
||||
</template>
|
||||
<StatusBadge v-if="exhausted" kind="run" label="已加载全部保留期数据" :dot="false" />
|
||||
<div class="flex-1" />
|
||||
<div class="w-32 max-md:w-full">
|
||||
<NSelect v-model:value="hours" size="small" :options="hourOptions" />
|
||||
</div>
|
||||
<NButton size="small" :loading="loading" @click="load()">刷新</NButton>
|
||||
</div>
|
||||
|
||||
@@ -235,7 +229,7 @@ const columns: DataTableColumns<AuditEvent> = [
|
||||
OCI Audit 免费且默认开启,事件保留 365 天,无需在云端做任何配置 ·
|
||||
实时查询不入库,事件通常延迟数分钟可见 ·
|
||||
已默认过滤遥测噪声(SummarizeMetricsData)与内网地址发起的服务互调 ·
|
||||
单次最多翻 10 页,截断时点「继续加载更早」断点续查 · 点击行查看完整详情
|
||||
从最新事件起每批约 100 条,翻到末页自动向更早加载,空档期自动扩窗回溯 · 点击行查看完整详情
|
||||
</FootNote>
|
||||
|
||||
<NModal v-model:show="showDetail" preset="card" closable :style="{ width: '720px', maxWidth: 'calc(100vw - 24px)' }">
|
||||
|
||||
Reference in New Issue
Block a user