From 2e021336967191637755fc8158919a40fe5f3e55 Mon Sep 17 00:00:00 2001
From: "2569718930@qq.com" <2569718930@qq.com>
Date: Sat, 16 May 2026 20:14:05 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=9B=BE=E8=A1=A8=E6=97=B6?=
=?UTF-8?q?=E9=97=B4=E8=BD=B4=E4=B8=8D=E5=85=A8=E4=B8=8E=E5=9F=8E=E5=B8=82?=
=?UTF-8?q?=E5=86=B3=E7=AD=96=E5=8D=A1=E6=A8=A1=E5=9E=8B=E8=A1=A5=E9=BD=90?=
=?UTF-8?q?=E5=8D=A1=E9=A1=BF?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 后端 Open-Meteo 请求加 past_days=1,小时数据从 00:00 开始
- 前端图表层填充完整 00:00-23:00 时间轴,缺失时段置空
- 城市深度分析门槛从 >1 降为 >=1,单模型城市不再被拦
- hydration 队列加最大重试 3 次,防止永久卡在等待模型补齐
- 移除右侧面板历史对账按钮
---
frontend/components/dashboard/DetailPanel.tsx | 35 +++----------------
.../scan-terminal/city-detail-utils.ts | 4 +--
.../use-ai-pinned-city-workspace.ts | 19 ++++++++--
frontend/lib/chart-utils.ts | 16 ++++++---
src/data_collection/nws_open_meteo_sources.py | 1 +
5 files changed, 37 insertions(+), 38 deletions(-)
diff --git a/frontend/components/dashboard/DetailPanel.tsx b/frontend/components/dashboard/DetailPanel.tsx
index 8ba0690b..4cb74a55 100644
--- a/frontend/components/dashboard/DetailPanel.tsx
+++ b/frontend/components/dashboard/DetailPanel.tsx
@@ -6,7 +6,6 @@ import { useRouter } from "next/navigation";
import { useEffect, useMemo, useRef, useState } from "react";
import { ForecastTable } from "@/components/dashboard/PanelSections";
import {
- useDashboardHistory,
useDashboardModal,
useDashboardStore,
useProAccess,
@@ -38,7 +37,6 @@ export function DetailPanel({
} = {}) {
const store = useDashboardStore();
const modal = useDashboardModal();
- const history = useDashboardHistory();
const { proAccess } = useProAccess();
const { locale, t } = useI18n();
const router = useRouter();
@@ -76,7 +74,7 @@ export function DetailPanel({
);
const [heavyContentReady, setHeavyContentReady] = useState(false);
const isOverlayOpen =
- Boolean(modal.futureModalDate) || history.historyState.isOpen;
+ Boolean(modal.futureModalDate);
const isVisible = isRail
? Boolean(store.selectedCity) && !isOverlayOpen
: store.isPanelOpen && Boolean(store.selectedCity) && !isOverlayOpen;
@@ -139,24 +137,20 @@ export function DetailPanel({
}
};
- const handleFeatureAccess = (feature: "today" | "history") => {
+ const handleTodayAccess = () => {
blurActiveElement();
if (!isPro) {
trackAppEvent("paywall_feature_clicked", {
entry: "detail_panel",
- feature,
+ feature: "today",
city: store.selectedCity,
user_state: isAuthenticated ? "logged_in" : "guest",
});
}
if (isPro) {
- if (feature === "today") {
- void modal.openTodayModal();
- return;
- }
- void history.openHistory();
+ void modal.openTodayModal();
return;
}
@@ -165,11 +159,7 @@ export function DetailPanel({
return;
}
- if (feature === "today") {
- void modal.openTodayModal();
- return;
- }
- void history.openHistory();
+ void modal.openTodayModal();
};
useEffect(() => {
@@ -348,21 +338,6 @@ export function DetailPanel({
{locale === "en-US" ? "Market" : "市场页"}
) : null}
-
diff --git a/frontend/components/dashboard/scan-terminal/city-detail-utils.ts b/frontend/components/dashboard/scan-terminal/city-detail-utils.ts
index 89a389dd..a9cee629 100644
--- a/frontend/components/dashboard/scan-terminal/city-detail-utils.ts
+++ b/frontend/components/dashboard/scan-terminal/city-detail-utils.ts
@@ -47,8 +47,8 @@ export function isFullEnoughForDeepAnalysis(detail?: CityDetail | null) {
return false;
}
return (
- countDetailModels(detail, detail.local_date) > 1 &&
- countDetailForecastDays(detail) > 1
+ countDetailModels(detail, detail.local_date) >= 1 &&
+ countDetailForecastDays(detail) >= 1
);
}
diff --git a/frontend/components/dashboard/scan-terminal/use-ai-pinned-city-workspace.ts b/frontend/components/dashboard/scan-terminal/use-ai-pinned-city-workspace.ts
index 57c8b98e..d13e7a05 100644
--- a/frontend/components/dashboard/scan-terminal/use-ai-pinned-city-workspace.ts
+++ b/frontend/components/dashboard/scan-terminal/use-ai-pinned-city-workspace.ts
@@ -30,6 +30,7 @@ export function useAiPinnedCityWorkspace({
const aiFullHydrationRef = useRef>(new Set());
const aiHydrationQueueRef = useRef([]);
const aiHydrationRunningRef = useRef(false);
+ const aiHydrationRetriesRef = useRef