'use client'; import Link from 'next/link'; import { useQuery, useQueryClient } from '@tanstack/react-query'; import { useEffect, useMemo, useState } from 'react'; import { EmptyState } from '@/components/feedback/empty-state'; import { ErrorState } from '@/components/feedback/error-state'; import { InlineMessage } from '@/components/feedback/inline-message'; import { LoadingState } from '@/components/feedback/loading-state'; import { PageHeader } from '@/components/layout/page-header'; import { AppCard } from '@/components/ui/app-card'; import { StatusBadge } from '@/components/ui/status-badge'; import { getApplyLogs } from '@/features/apply-logs/api/apply-logs'; import type { ApplyLogItem } from '@/features/apply-logs/types'; import { PrimaryButton, ResourceInput, SecondaryButton, } from '@/features/shared/components/resource-primitives'; import { formatDateTime, formatRelativeTime } from '@/lib/utils/date'; const applyLogsQueryKey = (nodeId: string) => ['apply-logs', nodeId] as const; function getErrorMessage(error: unknown) { return error instanceof Error ? error.message : '请求失败,请稍后重试。'; } function getResultMeta(result: string) { if (result === 'success') { return { label: '成功', variant: 'success' as const }; } return { label: '失败', variant: 'danger' as const }; } function buildSummary(logs: ApplyLogItem[]) { const nodeIds = new Set(logs.map((item) => item.node_id)); return [ { label: '记录总数', value: logs.length }, { label: '成功', value: logs.filter((item) => item.result === 'success').length }, { label: '失败', value: logs.filter((item) => item.result !== 'success').length }, { label: '节点数', value: nodeIds.size }, ]; } export function ApplyLogsPage() { const queryClient = useQueryClient(); const [nodeFilterInput, setNodeFilterInput] = useState(''); const [nodeFilter, setNodeFilter] = useState(''); const [selectedLogId, setSelectedLogId] = useState(null); const [feedback, setFeedback] = useState(null); const logsQuery = useQuery({ queryKey: applyLogsQueryKey(nodeFilter), queryFn: () => getApplyLogs(nodeFilter), }); const logs = useMemo(() => logsQuery.data ?? [], [logsQuery.data]); const summary = useMemo(() => buildSummary(logs), [logs]); useEffect(() => { if (logs.length === 0) { setSelectedLogId(null); return; } if (!logs.some((item) => item.id === selectedLogId)) { setSelectedLogId(logs[0].id); } }, [logs, selectedLogId]); const selectedLog = logs.find((item) => item.id === selectedLogId) ?? null; const handleSearch = () => { setFeedback(null); setNodeFilter(nodeFilterInput.trim()); }; const handleReset = () => { setFeedback(null); setNodeFilter(''); setNodeFilterInput(''); }; return (
返回节点页 } /> {feedback ? : null}
{summary.map((item) => (

{item.label}

{item.value}

))}
void queryClient.invalidateQueries({ queryKey: applyLogsQueryKey(nodeFilter) })} > 刷新 } >
setNodeFilterInput(event.target.value)} placeholder='输入 node_id 过滤应用记录' className='lg:max-w-md' />
筛选 清空
{logsQuery.isLoading ? ( ) : logsQuery.isError ? ( ) : logs.length === 0 ? ( ) : (
{logs.map((log) => { const resultMeta = getResultMeta(log.result); return ( ); })}
Node ID 版本 结果 时间 详情
{log.node_id} {log.version}

{formatDateTime(log.created_at)}

{formatRelativeTime(log.created_at)}

{ setSelectedLogId(log.id); setFeedback(`已选中节点 ${log.node_id} 的版本 ${log.version} 记录。`); }} className='px-3 py-2 text-xs' > 查看详情
)}
{selectedLog ? (

创建时间

{formatDateTime(selectedLog.created_at)}

相对时间

{formatRelativeTime(selectedLog.created_at)}

应用信息

{selectedLog.message || '无附加信息'}

) : ( )}
); }