Fix today analysis modal routing

This commit is contained in:
2569718930@qq.com
2026-04-17 20:40:17 +08:00
parent f98388ce69
commit bc09a3753c
4 changed files with 43 additions and 6 deletions
@@ -287,12 +287,18 @@ function getTrendMetricVisual(metric: {
return null; return null;
} }
function DailyTemperatureChart({ dateStr }: { dateStr: string }) { function DailyTemperatureChart({
dateStr,
forceToday = false,
}: {
dateStr: string;
forceToday?: boolean;
}) {
const store = useDashboardStore(); const store = useDashboardStore();
const { locale, t } = useI18n(); const { locale, t } = useI18n();
const detail = store.selectedDetail; const detail = store.selectedDetail;
const view = detail ? getFutureModalView(detail, dateStr, locale) : null; const view = detail ? getFutureModalView(detail, dateStr, locale) : null;
const isToday = detail ? dateStr === detail.local_date : false; const isToday = forceToday || (detail ? dateStr === detail.local_date : false);
const todayChartData = useMemo( const todayChartData = useMemo(
() => (detail && isToday ? getTemperatureChartData(detail, locale) : null), () => (detail && isToday ? getTemperatureChartData(detail, locale) : null),
[detail, isToday, locale], [detail, isToday, locale],
@@ -711,7 +717,9 @@ export function FutureForecastModal() {
}; };
}, [dateStr, detail]); }, [dateStr, detail]);
const isToday = dateStr === detail.local_date; const isToday =
store.forecastModalMode === "today" ||
(store.forecastModalMode == null && dateStr === detail.local_date);
const detailDepth = detail.detail_depth || "full"; const detailDepth = detail.detail_depth || "full";
const isFullDetailReady = detailDepth === "full"; const isFullDetailReady = detailDepth === "full";
const isStructureSyncing = store.loadingState.futureDeep || !isFullDetailReady; const isStructureSyncing = store.loadingState.futureDeep || !isFullDetailReady;
@@ -1713,7 +1721,7 @@ export function FutureForecastModal() {
: "今日气温路径(锚点观测 + 模型)"} : "今日气温路径(锚点观测 + 模型)"}
</h3> </h3>
</div> </div>
<DailyTemperatureChart dateStr={dateStr} /> <DailyTemperatureChart dateStr={dateStr} forceToday={isToday} />
<div className="future-v2-chart-thresholds"> <div className="future-v2-chart-thresholds">
<span>{locale === "en-US" ? "Base" : "基准"} · {baseCaseBucket || "--"}</span> <span>{locale === "en-US" ? "Base" : "基准"} · {baseCaseBucket || "--"}</span>
<span>{locale === "en-US" ? "Upside" : "上修"} · {intradayMeteorology.upside_bucket || "--"}</span> <span>{locale === "en-US" ? "Upside" : "上修"} · {intradayMeteorology.upside_bucket || "--"}</span>
@@ -1891,7 +1899,7 @@ export function FutureForecastModal() {
<section className="future-modal-section"> <section className="future-modal-section">
<h3>{t("future.targetTempTrend")}</h3> <h3>{t("future.targetTempTrend")}</h3>
<DailyTemperatureChart dateStr={dateStr} /> <DailyTemperatureChart dateStr={dateStr} forceToday={isToday} />
</section> </section>
<div className="future-modal-grid"> <div className="future-modal-grid">
@@ -1020,7 +1020,11 @@ export function ForecastTable() {
daily.map((day, index) => { daily.map((day, index) => {
const isToday = day.date === data.local_date || index === 0; const isToday = day.date === data.local_date || index === 0;
const isSelected = const isSelected =
store.futureModalDate === day.date || (isToday &&
store.forecastModalMode === "today" &&
Boolean(store.futureModalDate)) ||
(store.forecastModalMode !== "today" &&
store.futureModalDate === day.date) ||
store.selectedForecastDate === day.date; store.selectedForecastDate === day.date;
return ( return (
<button <button
@@ -1033,6 +1037,10 @@ export function ForecastTable() {
)} )}
onClick={() => { onClick={() => {
startTransition(() => { startTransition(() => {
if (isToday) {
store.openTodayModal();
return;
}
store.openFutureModal(day.date); store.openFutureModal(day.date);
}); });
}} }}
+18
View File
@@ -23,6 +23,7 @@ import {
CityListItem, CityListItem,
CitySummary, CitySummary,
DashboardState, DashboardState,
ForecastModalMode,
HistoryPoint, HistoryPoint,
HistoryPayload, HistoryPayload,
HistoryPayloadMeta, HistoryPayloadMeta,
@@ -40,6 +41,7 @@ interface DashboardStoreValue extends DashboardState {
force?: boolean, force?: boolean,
depth?: "panel" | "nearby" | "full", depth?: "panel" | "nearby" | "full",
) => Promise<CityDetail>; ) => Promise<CityDetail>;
forecastModalMode: ForecastModalMode | null;
futureModalDate: string | null; futureModalDate: string | null;
loadCities: () => Promise<void>; loadCities: () => Promise<void>;
openFutureModal: (dateStr: string, forceRefresh?: boolean) => Promise<void>; openFutureModal: (dateStr: string, forceRefresh?: boolean) => Promise<void>;
@@ -323,6 +325,8 @@ export function DashboardStoreProvider({
string | null string | null
>(null); >(null);
const [futureModalDate, setFutureModalDate] = useState<string | null>(null); const [futureModalDate, setFutureModalDate] = useState<string | null>(null);
const [forecastModalMode, setForecastModalMode] =
useState<ForecastModalMode | null>(null);
const [isMapInteracting, setIsMapInteracting] = useState(false); const [isMapInteracting, setIsMapInteracting] = useState(false);
const [loadingState, setLoadingState] = useState<LoadingState>( const [loadingState, setLoadingState] = useState<LoadingState>(
getInitialLoadingState, getInitialLoadingState,
@@ -761,6 +765,7 @@ export function DashboardStoreProvider({
setIsPanelOpen(true); setIsPanelOpen(true);
setSelectedForecastDate(null); setSelectedForecastDate(null);
setFutureModalDate(null); setFutureModalDate(null);
setForecastModalMode(null);
const summaryPromise = !citySummariesRef.current[cityName] const summaryPromise = !citySummariesRef.current[cityName]
? ensureCitySummary(cityName).catch(() => null) ? ensureCitySummary(cityName).catch(() => null)
@@ -1007,6 +1012,7 @@ export function DashboardStoreProvider({
closeFutureModal: () => { closeFutureModal: () => {
modalOpenSeqRef.current += 1; modalOpenSeqRef.current += 1;
setFutureModalDate(null); setFutureModalDate(null);
setForecastModalMode(null);
}, },
closeHistory: () => closeHistory: () =>
setHistoryState((current) => ({ ...current, isOpen: false })), setHistoryState((current) => ({ ...current, isOpen: false })),
@@ -1014,6 +1020,7 @@ export function DashboardStoreProvider({
setIsPanelOpen(false); setIsPanelOpen(false);
}, },
ensureCityDetail, ensureCityDetail,
forecastModalMode,
futureModalDate, futureModalDate,
historyState, historyState,
isPanelOpen, isPanelOpen,
@@ -1048,9 +1055,16 @@ export function DashboardStoreProvider({
"market", "market",
dateStr, dateStr,
); );
const todayDate =
cachedDetail?.local_date ||
cachedDetail?.forecast?.daily?.[0]?.date ||
null;
const modalMode: ForecastModalMode =
todayDate && dateStr === todayDate ? "today" : "future";
setSelectedForecastDate(dateStr); setSelectedForecastDate(dateStr);
setFutureModalDate(dateStr); setFutureModalDate(dateStr);
setForecastModalMode(modalMode);
if (!hasMarketCachedDetail || forceRefresh) { if (!hasMarketCachedDetail || forceRefresh) {
void ensureCityDetail(cityName, forceRefresh, "market").catch(() => {}); void ensureCityDetail(cityName, forceRefresh, "market").catch(() => {});
} }
@@ -1109,6 +1123,7 @@ export function DashboardStoreProvider({
if (targetDate) { if (targetDate) {
setSelectedForecastDate(targetDate); setSelectedForecastDate(targetDate);
setFutureModalDate(targetDate); setFutureModalDate(targetDate);
setForecastModalMode("today");
} }
if (!proAccess.subscriptionActive) return; if (!proAccess.subscriptionActive) return;
const needsDetailRefresh = const needsDetailRefresh =
@@ -1136,12 +1151,14 @@ export function DashboardStoreProvider({
if (!isLatestModalRequest()) return; if (!isLatestModalRequest()) return;
setSelectedForecastDate(detail.local_date); setSelectedForecastDate(detail.local_date);
setFutureModalDate(detail.local_date); setFutureModalDate(detail.local_date);
setForecastModalMode("today");
}) })
.catch(() => { .catch(() => {
if (!isLatestModalRequest()) return; if (!isLatestModalRequest()) return;
if (cachedDetail?.local_date) { if (cachedDetail?.local_date) {
setSelectedForecastDate(cachedDetail.local_date); setSelectedForecastDate(cachedDetail.local_date);
setFutureModalDate(cachedDetail.local_date); setFutureModalDate(cachedDetail.local_date);
setForecastModalMode("today");
} }
}) })
.finally(() => { .finally(() => {
@@ -1170,6 +1187,7 @@ export function DashboardStoreProvider({
cities, cities,
cityDetailsByName, cityDetailsByName,
citySummariesByName, citySummariesByName,
forecastModalMode,
futureModalDate, futureModalDate,
historyState, historyState,
isPanelOpen, isPanelOpen,
+3
View File
@@ -606,6 +606,8 @@ export interface ProAccessState {
error: string | null; error: string | null;
} }
export type ForecastModalMode = "today" | "future";
export interface DashboardState { export interface DashboardState {
cities: CityListItem[]; cities: CityListItem[];
cityDetailsByName: Record<string, CityDetail>; cityDetailsByName: Record<string, CityDetail>;
@@ -613,6 +615,7 @@ export interface DashboardState {
selectedCity: string | null; selectedCity: string | null;
isPanelOpen: boolean; isPanelOpen: boolean;
selectedForecastDate: string | null; selectedForecastDate: string | null;
forecastModalMode: ForecastModalMode | null;
loadingState: LoadingState; loadingState: LoadingState;
historyState: HistoryState; historyState: HistoryState;
proAccess: ProAccessState; proAccess: ProAccessState;