"use client"; import NetworkChartLoading from "@/app/[locale]/(main)/ClientComponents/NetworkChartLoading"; import { NezhaAPIMonitor, ServerMonitorChart, } from "@/app/[locale]/types/nezha-api"; import { BackIcon } from "@/components/Icon"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { ChartConfig, ChartContainer, ChartLegend, ChartLegendContent, ChartTooltip, ChartTooltipContent, } from "@/components/ui/chart"; import getEnv from "@/lib/env-entry"; import { formatTime, nezhaFetcher } from "@/lib/utils"; import { formatRelativeTime } from "@/lib/utils"; import { useLocale } from "next-intl"; import { useTranslations } from "next-intl"; import { useRouter } from "next/navigation"; import * as React from "react"; import { CartesianGrid, Line, LineChart, XAxis, YAxis } from "recharts"; import useSWR from "swr"; interface ResultItem { created_at: number; [key: string]: number | null; } export function NetworkChartClient({ server_id }: { server_id: number }) { const t = useTranslations("NetworkChartClient"); const { data, error } = useSWR( `/api/monitor?server_id=${server_id}`, nezhaFetcher, { refreshInterval: Number(getEnv("NEXT_PUBLIC_NezhaFetchInterval")) || 15000, }, ); if (error) { return ( <>

{error.message}

{t("chart_fetch_error_message")}

); } if (!data) return ; function transformData(data: NezhaAPIMonitor[]) { const monitorData: ServerMonitorChart = {}; data.forEach((item) => { const monitorName = item.monitor_name; if (!monitorData[monitorName]) { monitorData[monitorName] = []; } for (let i = 0; i < item.created_at.length; i++) { monitorData[monitorName].push({ created_at: item.created_at[i], avg_delay: item.avg_delay[i], }); } }); return monitorData; } const formatData = (rawData: NezhaAPIMonitor[]) => { const result: { [time: number]: ResultItem } = {}; // 获取所有时间点 const allTimes = new Set(); rawData.forEach((item) => { item.created_at.forEach((time) => allTimes.add(time)); }); const allTimeArray = Array.from(allTimes).sort((a, b) => a - b); // 遍历所有时间点,补全每个监控服务的数据 rawData.forEach((item) => { const { monitor_name, created_at, avg_delay } = item; // 初始化监控项在每个时间点的值 allTimeArray.forEach((time) => { if (!result[time]) { result[time] = { created_at: time }; } // 如果该时间点有数据,使用实际数据,否则补 null const timeIndex = created_at.indexOf(time); result[time][monitor_name] = timeIndex !== -1 ? avg_delay[timeIndex] : null; }); }); return Object.values(result).sort((a, b) => a.created_at - b.created_at); }; const transformedData = transformData(data); const formattedData = formatData(data); const initChartConfig = { avg_delay: { label: t("avg_delay"), }, } satisfies ChartConfig; const chartDataKey = Object.keys(transformedData); return ( ); } export function NetworkChart({ chartDataKey, chartConfig, chartData, serverName, formattedData, }: { chartDataKey: string[]; chartConfig: ChartConfig; chartData: ServerMonitorChart; serverName: string; formattedData: ResultItem[]; }) { const t = useTranslations("NetworkChart"); const router = useRouter(); const locale = useLocale(); const defaultChart = "All"; const [activeChart, setActiveChart] = React.useState(defaultChart); const handleButtonClick = (chart: string) => { if (chart === activeChart) { setActiveChart(defaultChart); } else { setActiveChart(chart); } }; const getColorByIndex = (chart: string) => { const index = chartDataKey.indexOf(chart); return `hsl(var(--chart-${(index % 10) + 1}))`; }; return (
{ router.push(`/${locale}/`); }} className="flex flex-none cursor-pointer items-center gap-0.5 text-xl" > {serverName} {chartDataKey.length} {t("ServerMonitorCount")}
{chartDataKey.map((key) => { return ( ); })}
formatRelativeTime(value)} /> `${value}ms`} /> { return formatTime(payload[0].payload.created_at); }} /> } /> {activeChart === defaultChart && ( } /> )} {activeChart !== defaultChart && ( )} {activeChart === defaultChart && chartDataKey.map((key) => ( ))}
); }