diff --git a/frontend/components/dashboard/FutureForecastModal.tsx b/frontend/components/dashboard/FutureForecastModal.tsx index 26f9485d..249b6a34 100644 --- a/frontend/components/dashboard/FutureForecastModal.tsx +++ b/frontend/components/dashboard/FutureForecastModal.tsx @@ -715,69 +715,6 @@ export function FutureForecastModal() { {settlementBucketLabel} - -
-
- - 📊 {locale === "en-US" ? "Core Edge" : "核心测算"} - - 0 - ? "positive" - : "negative", - )} - > - ({marketEdge}) - -
-
-
- - {locale === "en-US" ? "Model Prob:" : "模型概率:"} - - - {modelProbability} - -
-
- - {locale === "en-US" - ? "Market Prob:" - : "市场概率:"} - - - {marketMidpoint} - -
-
-
- - - {/* Layer 2: Order Book */} -
-
- 📈 {locale === "en-US" ? "Order Book" : "订单簿报价"} -
-
- YES: - - {marketYesBuy} /{" "} - {marketYesSell} - - - ({locale === "en-US" ? "Spread" : "价差"}{" "} - {marketSpread}) - -
-
- NO: - - {marketNoBuy} /{" "} - {marketNoSell} - -
{/* Layer 3: Context */} diff --git a/frontend/components/dashboard/PanelSections.tsx b/frontend/components/dashboard/PanelSections.tsx index c7c55200..8034e398 100644 --- a/frontend/components/dashboard/PanelSections.tsx +++ b/frontend/components/dashboard/PanelSections.tsx @@ -552,8 +552,8 @@ export function ModelForecast({ }) { const { locale, t } = useI18n(); const view = getModelView(detail, targetDate); - const modelEntries = Object.entries(view.models).filter(([, value]) => - Number.isFinite(Number(value)), + const modelEntries = Object.entries(view.models).filter( + ([, value]) => value !== null && value !== undefined && Number.isFinite(Number(value)), ); const numericValues = modelEntries.map(([, value]) => Number(value)); const comparisonValues = @@ -567,9 +567,7 @@ export function ModelForecast({ const range = Math.max(maxValue - minValue, 1); const getModelDisplayName = (name: string) => { if (String(name).trim().toLowerCase() === "meteoblue") { - return locale === "en-US" - ? "Meteoblue (Daily Max)" - : "Meteoblue (日最高温)"; + return "Meteoblue"; } return name; }; diff --git a/frontend/lib/dashboard-utils.ts b/frontend/lib/dashboard-utils.ts index ee71f40d..3583090b 100644 --- a/frontend/lib/dashboard-utils.ts +++ b/frontend/lib/dashboard-utils.ts @@ -330,28 +330,34 @@ export function getProbabilityView(detail: CityDetail, targetDate?: string | nul } export function getModelView(detail: CityDetail, targetDate?: string | null) { + const toFiniteNumber = (value: unknown): number | null => { + if (value === null || value === undefined || value === "") return null; + const numeric = Number(value); + return Number.isFinite(numeric) ? numeric : null; + }; + const pickMeteoblueForDate = (dateStr: string) => { const meteoblue = detail.source_forecasts?.meteoblue; if (!meteoblue) return null; const dates = detail.forecast?.daily?.map((item) => item.date) || []; const index = dates.findIndex((date) => date === dateStr); + const todayHigh = toFiniteNumber(meteoblue.today_high); + + // Today must always use Meteoblue daily max (today_high) first. + if (dateStr === detail.local_date && todayHigh != null) { + return todayHigh; + } const dailyHighs = Array.isArray(meteoblue.daily_highs) ? meteoblue.daily_highs : []; if (index >= 0) { - const byDailyHigh = Number(dailyHighs[index]); - if (Number.isFinite(byDailyHigh)) return byDailyHigh; + const byDailyHigh = toFiniteNumber(dailyHighs[index]); + if (byDailyHigh != null) return byDailyHigh; } - const todayHigh = Number(meteoblue.today_high); - if ( - Number.isFinite(todayHigh) && - (dateStr === detail.local_date || index === 0) - ) { - return todayHigh; - } + if (index === 0 && todayHigh != null) return todayHigh; return null; }; @@ -361,11 +367,14 @@ export function getModelView(detail: CityDetail, targetDate?: string | null) { dateStr: string, ) => { const nextModels = { ...models }; - if (!Number.isFinite(Number(nextModels.Meteoblue))) { + const existing = toFiniteNumber(nextModels.Meteoblue); + if (existing == null) { const meteoblueVal = pickMeteoblueForDate(dateStr); - if (Number.isFinite(Number(meteoblueVal))) { - nextModels.Meteoblue = Number(meteoblueVal); + if (meteoblueVal != null) { + nextModels.Meteoblue = meteoblueVal; } + } else { + nextModels.Meteoblue = existing; } return nextModels; };