// EventTable — K8s 事件列表(时间/次数/类型/原因/对象/来源/消息)// Logan.Li // v2: 虚拟滚动,移除 maxRows 限制,支持万级事件流畅渲染 import { useState, useRef } from 'react'; import { useVirtualizer } from '@tanstack/react-virtual'; import { Badge } from '@/components/ui/badge'; import { Loader2 } from 'lucide-react'; import { type NormalizedEvent, formatEventRepeatSpan, formatEventTimeCell, } from './k8s-event-utils'; interface EventTableProps { events: NormalizedEvent[]; loading?: boolean | string; emptyText?: string; /** @deprecated 虚拟滚动后不再需要截断,保留参数向后兼容但忽略 */ maxRows?: number; showNamespace?: boolean; /** 虚拟滚动容器高度 */ scrollHeight?: number; } const ROW_HEIGHT = 52; const COLS_NS = '148px 148px 64px 80px 80px 112px minmax(120px,1fr) 96px 112px minmax(200px,1.5fr)'; const COLS = '148px 148px 64px 80px 80px 112px minmax(120px,1fr) 112px minmax(200px,1.5fr)'; const MIN_W_NS = '1080px'; const MIN_W = '980px'; export function EventTable({ events, loading = false, emptyText = '暂无事件', showNamespace = false, scrollHeight = 600, }: EventTableProps) { const [expandedRow, setExpandedRow] = useState(null); const isLoading = loading === true || loading === 'events'; const scrollRef = useRef(null); const gridCols = showNamespace ? COLS_NS : COLS; const minWidth = showNamespace ? MIN_W_NS : MIN_W; const headers = showNamespace ? ['最后时间', '首次时间', '次数', '重复', '类型', '原因', '对象', '命名空间', '来源', '消息'] : ['最后时间', '首次时间', '次数', '重复', '类型', '原因', '对象', '来源', '消息']; const virtualizer = useVirtualizer({ count: events.length, getScrollElement: () => scrollRef.current, estimateSize: () => ROW_HEIGHT, overscan: 10, }); const virtualRows = virtualizer.getVirtualItems(); const totalHeight = virtualizer.getTotalSize(); return (
{/* 表头 — sticky 固定 */}
{headers.map((h, i) => ( {h} ))}
{/* 虚拟滚动体 */}
{isLoading ? (
) : events.length === 0 ? (
{emptyText}
) : (
{virtualRows.map((vr) => { const e = events[vr.index]; if (!e) return null; const rowKey = `${e.name || e.object}-${vr.index}`; const isExpanded = expandedRow === rowKey; const isWarning = e.type === 'Warning'; const last = formatEventTimeCell(e.lastTime); const first = formatEventTimeCell(e.firstTime); return (
setExpandedRow(isExpanded ? null : rowKey)} > {/* 最后时间 */}
{last.absolute}
{last.relative}
{/* 首次时间 */}
{first.absolute}
{first.relative}
{/* 次数 */}
{e.count}
{/* 重复跨度 */}
{formatEventRepeatSpan(e.firstTime, e.lastTime, e.count)}
{/* 类型 */}
{e.type}
{/* 原因 */}
{e.reason}
{/* 对象 */}
{e.objectKind ? ( {e.objectKind}/{e.objectName || e.object.split('/').pop()} ) : e.object}
{/* 命名空间(可选) */} {showNamespace &&
{e.namespace || '-'}
} {/* 来源 */}
{e.source}
{/* 消息 */}
{e.message}
{isExpanded && e.name && (
事件名: {e.name}
)}
); })}
)}
{/* 行数统计 */} {events.length > 0 && (
共 {events.length} 条事件 {events.length > 500 && '· 虚拟滚动渲染'}
)}
); }