From 155c2e30e1faf5104ca1f77f81bf7fd3dd2b209c Mon Sep 17 00:00:00 2001 From: imengying Date: Sun, 30 Aug 2026 11:33:34 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=B4=9F=E8=BD=BD=E5=9B=BE?= =?UTF-8?q?=E8=A1=A8=E6=98=BE=E7=A4=BA=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/chart.ts | 9 -------- frontend/src/components/NodeDetails.tsx | 28 ++++++++----------------- 2 files changed, 9 insertions(+), 28 deletions(-) diff --git a/frontend/src/chart.ts b/frontend/src/chart.ts index 01aab27..7652ee4 100644 --- a/frontend/src/chart.ts +++ b/frontend/src/chart.ts @@ -50,15 +50,6 @@ export function chartGapLimit(hours: number): number { return Math.max(5 * 60_000, (hours * 60 * 60_000) / 36); } -/** Fixed axis window so a partially populated range keeps its true scale. */ -export function chartTimeRange(hours: number, now = Date.now()) { - const start = now - hours * 60 * 60_000; - return { - domain: [start, now] as [number, number], - ticks: Array.from({ length: 5 }, (_, index) => start + ((now - start) * index) / 4), - }; -} - export function chartTimeLabel(timestamp: number, hours: number, locale: UiLocale): string { const date = new Date(timestamp); if (hours <= 1) return date.toLocaleTimeString(locale, { hour: "2-digit", minute: "2-digit", second: "2-digit", hour12: false }); diff --git a/frontend/src/components/NodeDetails.tsx b/frontend/src/components/NodeDetails.tsx index d2532d4..d939ba7 100644 --- a/frontend/src/components/NodeDetails.tsx +++ b/frontend/src/components/NodeDetails.tsx @@ -21,7 +21,7 @@ import { YAxis, } from "recharts"; import { api } from "../api"; -import { chartGapLimit, chartTimeLabel, chartTimeRange, insertTimelineGaps } from "../chart"; +import { chartGapLimit, chartTimeLabel, insertTimelineGaps } from "../chart"; import { demoHistory, demoLatencyHistory, demoLatencyTasks } from "../demo"; import { averageOf } from "../latency"; import { displayGpuDevices, formatBytes, formatCpuName, formatSpeed, formatUptime, isOnline, number } from "../format"; @@ -126,7 +126,6 @@ function mergeLatencySamples(current: LatencySample[], incoming: LatencySample[] interface LatencyChartPoint { timestamp: number; - label: string; value: number | null; } @@ -144,7 +143,7 @@ interface LoadChartPoint { function insertLatencyGaps(points: LatencyChartPoint[], hours: number): LatencyChartPoint[] { return insertTimelineGaps( points, - (timestamp) => ({ timestamp, label: "", value: null }), + (timestamp) => ({ timestamp, value: null }), { minGap: 10_000, maxGap: chartGapLimit(hours) }, ); } @@ -279,13 +278,6 @@ export function NodeDetails({ server, threshold, retentionDays, locale, demo = f () => insertLoadGaps(points, loadChartHours), [loadChartHours, points], ); - // 有时间范围时钉住整段窗口,部分数据也保持真实比例;实时档用 dataMin/dataMax - // 贴合数据(与延迟图、Komari 原版一致)。points 进 deps 是为了在数据落位后重算 - // domain,慢查询时末端不会被裁掉。 - const loadTimeRange = useMemo( - () => (loadHours === 0 ? null : chartTimeRange(loadChartHours)), - [loadChartHours, loadHours, points], - ); const latencySeries = useMemo(() => { return latencyTasks.map((task, index) => { const samples = latencyPoints.filter((point) => point.task_id === task.id); @@ -294,7 +286,6 @@ export function NodeDetails({ server, threshold, retentionDays, locale, demo = f .sort((left, right) => left.timestamp - right.timestamp) .map((sample) => ({ timestamp: sample.timestamp * 1000, - label: chartTimeLabel(sample.timestamp * 1000, hours, locale), value: sample.latency_ms >= 0 ? sample.latency_ms : null, })); return { @@ -306,7 +297,7 @@ export function NodeDetails({ server, threshold, retentionDays, locale, demo = f points: insertLatencyGaps(rawPoints, hours), }; }); - }, [hours, latencyPoints, latencyTasks, locale]); + }, [hours, latencyPoints, latencyTasks]); const visibleLatencySeries = useMemo( () => latencySeries.filter((series) => !hiddenLatencyTaskIds.has(series.id)), [hiddenLatencyTaskIds, latencySeries], @@ -321,7 +312,6 @@ export function NodeDetails({ server, threshold, retentionDays, locale, demo = f .sort((left, right) => left - right) .map((timestamp) => ({ timestamp, label: chartTimeLabel(timestamp, hours, locale) })); }, [hours, locale, latencySeries]); - const latencyTimeRange = useMemo(() => chartTimeRange(latencyHours), [latencyHours, latencyPoints]); const last = data[data.length - 1]; const pingEnabled = latencyTasks.length > 0; const toggleLatencyTask = (taskId: string) => { @@ -379,16 +369,16 @@ export function NodeDetails({ server, threshold, retentionDays, locale, demo = f {chartType === "load" && loadLoading ?
{ui(locale, "正在读取历史数据", "Loading history")}
: chartType === "latency" && latencyLoading ?
{ui(locale, "正在读取延迟数据", "Loading latency")}
: chartType === "load" && !data.length ?
{ui(locale, "暂无历史数据", "No history")}
: chartType === "load" ? (
- 0} tick={{ fontSize: 10 }} minTickGap={30} tickFormatter={(value) => chartTimeLabel(Number(value), loadChartHours, locale)} /> chartTimeLabel(Number(value), loadChartHours, locale)} formatter={(value) => [`${Number(value).toFixed(1)}%`, "CPU"]} /> + chartTimeLabel(Number(value), loadChartHours, locale)} /> chartTimeLabel(Number(value), loadChartHours, locale)} formatter={(value) => [`${Number(value).toFixed(1)}%`, "CPU"]} /> - 0} tick={{ fontSize: 10 }} minTickGap={30} tickFormatter={(value) => chartTimeLabel(Number(value), loadChartHours, locale)} /> formatBytes(Number(value), 0)} /> chartTimeLabel(Number(value), loadChartHours, locale)} formatter={(value) => [formatBytes(Number(value)), "内存"]} /> + chartTimeLabel(Number(value), loadChartHours, locale)} /> formatBytes(Number(value), 0)} /> chartTimeLabel(Number(value), loadChartHours, locale)} formatter={(value) => [formatBytes(Number(value)), "内存"]} /> - 0} tick={{ fontSize: 10 }} minTickGap={30} tickFormatter={(value) => chartTimeLabel(Number(value), loadChartHours, locale)} /> formatBytes(Number(value), 0)} /> chartTimeLabel(Number(value), loadChartHours, locale)} formatter={(value) => [formatBytes(Number(value)), "硬盘"]} /> + chartTimeLabel(Number(value), loadChartHours, locale)} /> formatBytes(Number(value), 0)} /> chartTimeLabel(Number(value), loadChartHours, locale)} formatter={(value) => [formatBytes(Number(value)), "硬盘"]} /> - 0} tick={{ fontSize: 10 }} minTickGap={30} tickFormatter={(value) => chartTimeLabel(Number(value), loadChartHours, locale)} /> formatBytes(Number(value), 0)} /> chartTimeLabel(Number(value), loadChartHours, locale)} formatter={(value, name) => [formatSpeed(Number(value)), name === "net_out" ? "上行" : "下行"]} /> + chartTimeLabel(Number(value), loadChartHours, locale)} /> formatBytes(Number(value), 0)} /> chartTimeLabel(Number(value), loadChartHours, locale)} formatter={(value, name) => [formatSpeed(Number(value)), name === "net_out" ? "上行" : "下行"]} />
) : ( @@ -416,9 +406,9 @@ export function NodeDetails({ server, threshold, retentionDays, locale, demo = f
{latencyData.length ? <> - + - chartTimeLabel(Number(value), latencyHours, locale)} /> + chartTimeLabel(Number(value), latencyHours, locale)} /> chartTimeLabel(Number(value), latencyHours, locale)} formatter={(value, name) => [value == null ? "--" : `${Number(value).toFixed(1)} ms`, name]} /> {visibleLatencySeries.map((series) => )}