diff --git a/apps/web/src/pages/system/audit-logs/AuditLogTable.tsx b/apps/web/src/pages/system/audit-logs/AuditLogTable.tsx index 99f7afb..eeb4343 100644 --- a/apps/web/src/pages/system/audit-logs/AuditLogTable.tsx +++ b/apps/web/src/pages/system/audit-logs/AuditLogTable.tsx @@ -5,7 +5,7 @@ import type { AuditLogItem } from '@lingxi/shared'; import { notifyError, notifySuccess, PageEmpty } from '@lingxi/ui'; import { IconCheck, IconCopy, IconRefresh } from '@lingxi/ui/icons'; import type { ReactNode } from 'react'; -import { useEffect, useState } from 'react'; +import { useEffect, useRef, useState } from 'react'; import { copyToClipboard } from './audit-clipboard'; import { @@ -19,7 +19,6 @@ import { export interface AuditLogTableProps { items: readonly AuditLogItem[]; loading: boolean; - refreshing?: boolean; isFetchingNextPage: boolean; hasNextPage: boolean; /** 追加分页失败时的提示(保留已有数据) */ @@ -27,7 +26,6 @@ export interface AuditLogTableProps { onOpen: (logId: string) => void; onLoadMore: () => void; onRetryMore: () => void; - onRefresh: () => void; onClearFilters: () => void; } @@ -92,17 +90,29 @@ function useNarrowTable(): boolean { export function AuditLogTable({ items, loading, - refreshing = false, isFetchingNextPage, hasNextPage, errorMessage = null, onOpen, onLoadMore, onRetryMore, - onRefresh, onClearFilters, }: AuditLogTableProps): ReactNode { const narrow = useNarrowTable(); + const wrapRef = useRef(null); + const [tableHeight, setTableHeight] = useState(360); + useEffect(() => { + const element = wrapRef.current; + if (element === null || typeof ResizeObserver === 'undefined') return undefined; + const observer = new ResizeObserver((entries) => { + const height = Math.floor(entries[0]?.contentRect.height ?? 0); + if (height > 0) setTableHeight(Math.max(160, height - 40)); + }); + observer.observe(element); + return () => { + observer.disconnect(); + }; + }, []); const columns: ColumnProps[] = [ { title: '时间', @@ -250,21 +260,7 @@ export function AuditLogTable({ return (
-
- 日志列表 - {pagerText} -
-
-
- -
+
className="lx-audit-table" columns={visibleColumns} @@ -273,7 +269,7 @@ export function AuditLogTable({ pagination={false} loading={loading} size="middle" - scroll={{ x: narrow ? 760 : '100%' }} + scroll={{ x: '100%', y: tableHeight }} empty={emptyState(onClearFilters)} onRow={(record) => record === undefined @@ -297,7 +293,7 @@ export function AuditLogTable({
- 游标分页 · 按操作时间倒序 + {pagerText} · 游标分页 · 按操作时间倒序 {errorMessage === null ? null : ( · {errorMessage} )} diff --git a/apps/web/src/pages/system/audit-logs/AuditLogsPage.tsx b/apps/web/src/pages/system/audit-logs/AuditLogsPage.tsx index 1b9e839..6262c7b 100644 --- a/apps/web/src/pages/system/audit-logs/AuditLogsPage.tsx +++ b/apps/web/src/pages/system/audit-logs/AuditLogsPage.tsx @@ -2,7 +2,7 @@ import { Button, Modal } from '@douyinfe/semi-ui-19'; import { Permission } from '@lingxi/shared'; import { ErrorState } from '@lingxi/ui'; -import { IconAlert, IconDownload, IconLock } from '@lingxi/ui/icons'; +import { IconAlert, IconDownload, IconLock, IconRefresh } from '@lingxi/ui/icons'; import type { ReactNode } from 'react'; import { useMemo, useState } from 'react'; import { useNavigate, useSearchParams } from 'react-router'; @@ -113,6 +113,17 @@ export function AuditLogsPage(): ReactNode {

关键操作留痕 · 只读 · append-only

+ {canExport ? ( <> @@ -181,7 +192,6 @@ export function AuditLogsPage(): ReactNode { { void logs.fetchNextPage(); }} - onRefresh={() => { - void logs.refetch(); - }} onClearFilters={resetFilters} /> )} diff --git a/apps/web/src/styles/audit.css b/apps/web/src/styles/audit.css index f42c5e4..0b74ed2 100644 --- a/apps/web/src/styles/audit.css +++ b/apps/web/src/styles/audit.css @@ -202,47 +202,22 @@ box-shadow: var(--lx-shadow-panel); } -.lx-audit-table-card__head { - display: flex; - flex: 0 0 auto; - align-items: center; - gap: 10px; - min-height: 48px; - padding: 0 16px; - border-bottom: 1px solid var(--lx-color-border); -} - -.lx-audit-table-card__head b { - font-size: var(--lx-font-size-sm); - font-weight: 600; -} - -.lx-audit-table-card__count { - color: var(--lx-color-text-tertiary); - font-size: var(--lx-font-size-xs); - font-variant-numeric: tabular-nums; -} - -.lx-audit-table-card__tools { - margin-left: auto; -} - .lx-audit-table-wrap { min-height: 0; flex: 1; - overflow: auto; -} - -.lx-audit-table .semi-table { - min-width: 1080px; + overflow: hidden; } .lx-audit-table .semi-table-thead > .semi-table-row > .semi-table-row-head { + position: sticky; + top: 0; + z-index: 3; height: 40px; background: var(--lx-color-bg-subtle); color: var(--lx-color-text-tertiary); font-size: var(--lx-font-size-xs); font-weight: 500; + box-shadow: inset 0 -1px 0 var(--lx-color-border); } .lx-audit-table .semi-table-tbody > .semi-table-row > .semi-table-row-cell {