From 59e099a56dd071576bf9e285e7474d2f191bed3b Mon Sep 17 00:00:00 2001 From: "2569718930@qq.com" <2569718930@qq.com> Date: Wed, 6 May 2026 16:34:19 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20AI=20=E6=8A=A5=E6=96=87?= =?UTF-8?q?=E8=A7=A3=E8=AF=BB=E7=BC=93=E5=AD=98=E6=9C=AA=E5=9C=A8=E9=A6=96?= =?UTF-8?q?=E5=B8=A7=E7=94=9F=E6=95=88=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 此前 useState 初始化为 idle,useEffect 异步读缓存后才切到 ready, 导致重新打开城市卡片时先闪烁"等待 AI 解读..."再跳转到缓存数据。 现在用 lazy initializer 在首帧同步读取缓存,命中则直接渲染 ready 状态,零闪烁。 --- .../scan-terminal/use-ai-city-forecast.ts | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/frontend/components/dashboard/scan-terminal/use-ai-city-forecast.ts b/frontend/components/dashboard/scan-terminal/use-ai-city-forecast.ts index c1574a11..e6970734 100644 --- a/frontend/components/dashboard/scan-terminal/use-ai-city-forecast.ts +++ b/frontend/components/dashboard/scan-terminal/use-ai-city-forecast.ts @@ -30,15 +30,20 @@ export function useAiCityForecast({ locale: string; report: string; }) { - const [aiForecast, setAiForecast] = useState({ - status: "idle", - }); const [aiRefreshToken, setAiRefreshToken] = useState(0); const aiForecastKey = useMemo( () => buildAiCityForecastKey({ detail, detailCityName, locale, report }), [detail, detailCityName, locale, report], ); + const [aiForecast, setAiForecast] = useState(() => { + if (!enabled || !aiForecastKey) return { status: "idle" }; + const cacheKey = buildAiCityForecastCacheKey(aiForecastKey); + const cached = readReadyCachedAiForecastState(cacheKey, 0); + if (cached) return cached; + return { status: "idle" }; + }); + useEffect(() => { if (!enabled || !aiForecastKey) { setAiForecast({ status: "idle" }); @@ -47,16 +52,16 @@ export function useAiCityForecast({ let cancelled = false; const cacheKey = buildAiCityForecastCacheKey(aiForecastKey); const requestKey = buildAiCityForecastRequestKey(cacheKey, aiRefreshToken); - const readyCachedState = readReadyCachedAiForecastState( - cacheKey, - aiRefreshToken, - ); - if (readyCachedState) { - setAiForecast(readyCachedState); - return () => { - cancelled = true; - }; + + // If cache was loaded into initial state and no force refresh, skip + if (aiRefreshToken === 0) { + const cached = readReadyCachedAiForecastState(cacheKey, 0); + if (cached) { + setAiForecast(cached); + return () => { cancelled = true; }; + } } + const loadingState = buildAiCityLoadingForecastState({ cacheKey, detail,