修复温度走势图不显示:移除 IntersectionObserver 延迟渲染

问题:图表只在 IntersectionObserver 检测到视口交叉后才渲染
- 卡片折叠时图表区域永远不可见,IntersectionObserver 不触发
- 小屏幕/快速滚动时图表可能来不及渲染

修复:
- 移除 IntersectionObserver 懒加载逻辑
- 图表始终立即渲染(useChart 在挂载时初始化)
- Chart.js animation:false 确保快速渲染,无性能代价
- 清理未使用的 useState/useEffect 导入
This commit is contained in:
2569718930@qq.com
2026-05-10 18:34:00 +08:00
parent eed0345045
commit 13a67cdc85
@@ -1,5 +1,5 @@
import type { ChartConfiguration } from "chart.js";
import { useEffect, useMemo, useRef, useState } from "react";
import { useMemo, useRef } from "react";
import { BarChart3 } from "lucide-react";
import type { CityDetail } from "@/lib/dashboard-types";
import { useChart } from "@/hooks/useChart";
@@ -64,15 +64,14 @@ function buildTemperatureChartSignature(detail: CityDetail) {
export function AiCityTemperatureChart({ detail }: { detail: CityDetail }) {
const { locale } = useI18n();
const sectionRef = useRef<HTMLElement | null>(null);
const [shouldRenderChart, setShouldRenderChart] = useState(false);
const cityKey = `${detail.name || detail.display_name || ""}:${detail.local_date || ""}`;
const chartSignature = useMemo(
() => (shouldRenderChart ? buildTemperatureChartSignature(detail) : ""),
[detail, shouldRenderChart],
() => buildTemperatureChartSignature(detail),
[detail],
);
const computedChartData = useMemo(
() => (shouldRenderChart ? getTemperatureChartData(detail, locale) : null),
[chartSignature, detail, locale, shouldRenderChart],
() => getTemperatureChartData(detail, locale),
[chartSignature, detail, locale],
);
const lastChartDataRef = useRef<{
cityKey: string;
@@ -233,26 +232,6 @@ export function AiCityTemperatureChart({ detail }: { detail: CityDetail }) {
observationLabel,
]);
useEffect(() => {
if (shouldRenderChart) return;
if (typeof window === "undefined" || !("IntersectionObserver" in window)) {
setShouldRenderChart(true);
return;
}
const target = sectionRef.current;
if (!target) return;
const observer = new IntersectionObserver(
(entries) => {
if (!entries.some((entry) => entry.isIntersecting)) return;
setShouldRenderChart(true);
observer.disconnect();
},
{ rootMargin: "220px 0px" },
);
observer.observe(target);
return () => observer.disconnect();
}, [shouldRenderChart]);
return (
<section className="scan-ai-city-section chart" ref={sectionRef}>
<div className="scan-ai-city-section-title">
@@ -260,13 +239,7 @@ export function AiCityTemperatureChart({ detail }: { detail: CityDetail }) {
<span>{locale === "en-US" ? "Evidence · intraday path" : "证据 · 今日日内路径"}</span>
</div>
<div className="scan-ai-city-chart">
{shouldRenderChart ? (
<canvas ref={canvasRef} />
) : (
<div className="scan-ai-city-chart-placeholder">
{locale === "en-US" ? "Chart will render when visible" : "图表进入视口后再渲染"}
</div>
)}
<canvas ref={canvasRef} />
</div>
{chartData ? (
<div className="scan-ai-city-chart-legend">