Load terminal chart canvas eagerly
This commit is contained in:
@@ -1,13 +1,12 @@
|
||||
"use client";
|
||||
|
||||
import clsx from "clsx";
|
||||
import dynamic from "next/dynamic";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import type { ScanOpportunityRow } from "@/lib/dashboard-types";
|
||||
import { useLatestPatch, useSseResyncVersion } from "@/hooks/use-sse-patches";
|
||||
import { Panel } from "@/components/dashboard/scan-terminal/Panel";
|
||||
import { ModelCurvesSummary } from "@/components/dashboard/scan-terminal/ModelCurvesSummary";
|
||||
import { TemperatureChartCanvasFallback } from "@/components/dashboard/scan-terminal/TemperatureChartCanvasFallback";
|
||||
import { TemperatureChartCanvas } from "@/components/dashboard/scan-terminal/TemperatureChartCanvas";
|
||||
import { TemperatureRunwayDetails } from "@/components/dashboard/scan-terminal/TemperatureRunwayDetails";
|
||||
import { TemperatureStatsBars } from "@/components/dashboard/scan-terminal/TemperatureStatsBars";
|
||||
import { rowName } from "@/components/dashboard/scan-terminal/utils";
|
||||
@@ -63,32 +62,10 @@ const DEFERRED_DETAIL_LOAD_DELAY_MS = 1_200;
|
||||
const DEFERRED_DETAIL_LOAD_GROUP_SIZE = 3;
|
||||
const DEFERRED_DETAIL_LOAD_WAVE_STEP_MS = 900;
|
||||
|
||||
let temperatureChartCanvasModulePromise: Promise<
|
||||
typeof import("@/components/dashboard/scan-terminal/TemperatureChartCanvas")
|
||||
> | null = null;
|
||||
|
||||
function loadTemperatureChartCanvasModule() {
|
||||
temperatureChartCanvasModulePromise ??= import(
|
||||
"@/components/dashboard/scan-terminal/TemperatureChartCanvas"
|
||||
);
|
||||
return temperatureChartCanvasModulePromise;
|
||||
}
|
||||
|
||||
export function preloadTemperatureChartCanvas() {
|
||||
return loadTemperatureChartCanvasModule().then(() => undefined, () => undefined);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const TemperatureChartCanvas = dynamic(
|
||||
() =>
|
||||
loadTemperatureChartCanvasModule().then(
|
||||
(mod) => mod.TemperatureChartCanvas,
|
||||
),
|
||||
{
|
||||
ssr: false,
|
||||
loading: () => <TemperatureChartCanvasFallback />,
|
||||
},
|
||||
);
|
||||
|
||||
function peakGlowLabel(state: keyof typeof PEAK_GLOW_PANEL_CLASS, isEn: boolean) {
|
||||
if (state === "watch") return isEn ? "Watch" : "关注";
|
||||
if (state === "near_peak") return isEn ? "Near peak" : "接近峰值";
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
export function TemperatureChartCanvasFallback({ compact }: { compact?: boolean }) {
|
||||
const horizontalLines = compact ? 5 : 7;
|
||||
const verticalLines = compact ? 5 : 8;
|
||||
const minChartHeight = compact === false ? 220 : 120;
|
||||
|
||||
return (
|
||||
<div
|
||||
className="relative flex-1 overflow-hidden rounded-sm border border-slate-100 bg-white"
|
||||
style={{ minHeight: minChartHeight }}
|
||||
>
|
||||
<div className="absolute inset-x-3 bottom-7 top-4 rounded-sm border border-slate-100">
|
||||
{Array.from({ length: horizontalLines }).map((_, index) => (
|
||||
<span
|
||||
key={`h-${index}`}
|
||||
className="absolute left-0 right-0 border-t border-dashed border-sky-100"
|
||||
style={{ top: `${(index / Math.max(1, horizontalLines - 1)) * 100}%` }}
|
||||
/>
|
||||
))}
|
||||
{Array.from({ length: verticalLines }).map((_, index) => (
|
||||
<span
|
||||
key={`v-${index}`}
|
||||
className="absolute bottom-0 top-0 border-l border-dashed border-sky-100"
|
||||
style={{ left: `${(index / Math.max(1, verticalLines - 1)) * 100}%` }}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div className="absolute inset-0 grid place-items-center">
|
||||
<div className="flex items-center gap-2 rounded border border-slate-200 bg-white px-3 py-2 text-xs font-semibold text-slate-500 shadow-sm">
|
||||
<span className="h-3 w-3 animate-spin rounded-full border-2 border-blue-200 border-t-blue-500" />
|
||||
加载图表
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -73,9 +73,14 @@ export async function runTests() {
|
||||
"selected city chart should consume SSE patches and use a 2-minute no-patch fallback",
|
||||
);
|
||||
assert(
|
||||
chartSource.includes("loadTemperatureChartCanvasModule") &&
|
||||
chartSource.includes("preloadTemperatureChartCanvas"),
|
||||
"terminal chart canvas should expose a preload hook for the dynamic chart chunk",
|
||||
chartSource.includes("preloadTemperatureChartCanvas"),
|
||||
"terminal chart canvas should expose a preload hook for first-paint optimization",
|
||||
);
|
||||
assert(
|
||||
chartSource.includes('from "@/components/dashboard/scan-terminal/TemperatureChartCanvas"') &&
|
||||
!chartSource.includes("next/dynamic") &&
|
||||
!chartSource.includes("TemperatureChartCanvasFallback"),
|
||||
"terminal chart canvas should be loaded with the terminal route instead of showing a second-stage dynamic chunk fallback",
|
||||
);
|
||||
assert(
|
||||
dashboardSource.includes("preloadTemperatureChartCanvas") &&
|
||||
|
||||
@@ -97,11 +97,10 @@ export function runTests() {
|
||||
"terminal dashboard must lazy-load the training analytics tab so Recharts stays out of the default terminal path",
|
||||
);
|
||||
assert(
|
||||
chartSource.includes('from "next/dynamic"') &&
|
||||
chartSource.includes("TemperatureChartCanvasFallback") &&
|
||||
chartSource.includes("import(\"@/components/dashboard/scan-terminal/TemperatureChartCanvas\")") &&
|
||||
!chartSource.includes('import { TemperatureChartCanvas } from "@/components/dashboard/scan-terminal/TemperatureChartCanvas";'),
|
||||
"terminal temperature charts must lazy-load the Recharts canvas behind a lightweight fallback",
|
||||
chartSource.includes('import { TemperatureChartCanvas } from "@/components/dashboard/scan-terminal/TemperatureChartCanvas";') &&
|
||||
!chartSource.includes("TemperatureChartCanvasFallback") &&
|
||||
!chartSource.includes("import(\"@/components/dashboard/scan-terminal/TemperatureChartCanvas\")"),
|
||||
"terminal temperature charts must load the Recharts canvas with the terminal route so visible cards do not sit behind a second-stage fallback",
|
||||
);
|
||||
assert(
|
||||
chartSource.includes("setLiveTemp(null);") &&
|
||||
|
||||
Reference in New Issue
Block a user