'use client'; import Link from 'next/link'; import { useQuery } from '@tanstack/react-query'; import { RankChart } from '@/components/data/rank-chart'; import { TrendChart } from '@/components/data/trend-chart'; import { EmptyState } from '@/components/feedback/empty-state'; import { ErrorState } from '@/components/feedback/error-state'; import { LoadingState } from '@/components/feedback/loading-state'; import { AppCard } from '@/components/ui/app-card'; import { StatusBadge } from '@/components/ui/status-badge'; import { getDashboardOverview } from '@/features/dashboard/api/overview'; import type { DashboardNodeHealth } from '@/features/dashboard/types'; import { WorldStage } from '@/features/dashboard/components/world-stage'; import { getNodeStatusLabel, getNodeStatusVariant, getOpenrestyStatusLabel, getOpenrestyStatusVariant, isWSConnectedLastSeen, } from '@/features/nodes/utils'; import { formatDateTime, formatRelativeTime } from '@/lib/utils/date'; import { formatBytes, formatBytesPerSecond, formatPercent, } from '@/lib/utils/metrics'; function getErrorMessage(error: unknown) { return error instanceof Error ? error.message : '请求失败,请稍后重试。'; } function formatTrendHour(value: string) { const date = new Date(value); if (Number.isNaN(date.getTime())) { return '—'; } return `${date.getHours().toString().padStart(2, '0')}:00`; } function buildNodeDetailHref(id?: number | null) { if (!id) { return '/node'; } return `/node/detail?id=${id}`; } function buildNodeRankItems( nodes: DashboardNodeHealth[], selector: (node: DashboardNodeHealth) => number, limit = 5, ) { return [...nodes] .sort((left, right) => { const leftValue = selector(left); const rightValue = selector(right); if (leftValue === rightValue) { return left.name.localeCompare(right.name, 'zh-CN'); } return rightValue - leftValue; }) .slice(0, limit) .filter((node) => selector(node) > 0) .map((node) => ({ label: node.name, value: selector(node), })); } function NodeHealthRow({ node }: { node: DashboardNodeHealth }) { return (
{node.name}
{node.node_id}
CPU
{formatPercent(node.cpu_usage_percent)}
内存
{formatPercent(node.memory_usage_percent)}
最近窗口请求
{node.request_count.toLocaleString('zh-CN')}
活动异常
{node.active_event_count}
当前版本:{node.current_version || '未应用'}
最近心跳: {isWSConnectedLastSeen(node.last_seen_at) ? ' WS 已连接' : node.last_seen_at ? ` ${formatRelativeTime(node.last_seen_at)} · ${formatDateTime(node.last_seen_at)}` : ' 暂无'}
流量最高节点
容量压力节点