From 30f33bcf903c46ccf22cb2c12675ea201ec3cc31 Mon Sep 17 00:00:00 2001 From: "2569718930@qq.com" <2569718930@qq.com> Date: Thu, 23 Apr 2026 04:38:05 +0800 Subject: [PATCH] Simplify homepage focus card modules --- .../components/dashboard/Dashboard.module.css | 101 ++++++++++++- frontend/components/dashboard/HeaderBar.tsx | 37 +++++ .../dashboard/PolyWeatherDashboard.tsx | 135 +++++------------- 3 files changed, 164 insertions(+), 109 deletions(-) diff --git a/frontend/components/dashboard/Dashboard.module.css b/frontend/components/dashboard/Dashboard.module.css index 24472d3b..87fdcb05 100644 --- a/frontend/components/dashboard/Dashboard.module.css +++ b/frontend/components/dashboard/Dashboard.module.css @@ -73,6 +73,42 @@ linear-gradient(180deg, #040914 0%, #02050d 100%); } +:global(html.light) .root { + --bg-primary: #edf5ff; + --bg-secondary: #f7fbff; + --bg-card: #ffffff; + --bg-glass: rgba(248, 252, 255, 0.84); + --border-glass: rgba(48, 77, 112, 0.18); + --border-subtle: rgba(48, 77, 112, 0.1); + --text-primary: #0b1726; + --text-secondary: #42546c; + --text-muted: #6b7b91; + background: #edf5ff; + color: #0b1726; + background-image: + radial-gradient(circle at 18% 18%, rgba(14, 165, 233, 0.16), transparent 25%), + radial-gradient(circle at 82% 12%, rgba(59, 130, 246, 0.12), transparent 22%), + linear-gradient(180deg, #f8fbff 0%, #e9f3ff 100%); +} + +:global(html.light) .root :global(.header), +:global(html.light) .root :global(.city-list), +:global(html.light) .root :global(.home-intelligence-panel.full), +:global(html.light) .root :global(.home-opportunity-strip), +:global(html.light) .root :global(.home-summary-card), +:global(html.light) .root :global(.opportunity-card), +:global(html.light) .root :global(.home-deb-card), +:global(html.light) .root :global(.home-card-section) { + background: rgba(255, 255, 255, 0.86); + color: #0b1726; + border-color: rgba(48, 77, 112, 0.18); +} + +:global(html.light) .root :global(.map) { + background: #dbeafe; + filter: saturate(0.95) brightness(1.12); +} + /* ── Map ── */ .root :global(.map) { position: absolute; @@ -1217,6 +1253,9 @@ transparent 32% ), linear-gradient(165deg, rgba(3, 10, 22, 0.96), rgba(5, 18, 38, 0.94)); + box-shadow: + inset 1px 0 0 rgba(255, 255, 255, 0.04), + -10px 0 34px rgba(0, 0, 0, 0.18); } .root :global(.home-intelligence-panel.full::-webkit-scrollbar) { @@ -1348,32 +1387,82 @@ .root :global(.home-weather-hero) { display: grid; - grid-template-columns: 1fr 92px; - gap: 8px 16px; + grid-template-columns: minmax(0, 1fr) 130px; + gap: 14px; align-items: center; + padding: 16px; + border: 1px solid rgba(34, 211, 238, 0.14); + border-radius: 18px; + background: + radial-gradient(circle at 88% 24%, rgba(245, 158, 11, 0.12), transparent 24%), + linear-gradient(180deg, rgba(8, 16, 30, 0.62), rgba(4, 10, 22, 0.36)); } -.root :global(.home-weather-hero strong) { +.root :global(.home-weather-main strong) { + display: block; color: #f8fafc; - font-size: 58px; + font-size: 62px; font-weight: 900; line-height: 0.96; letter-spacing: -0.08em; } -.root :global(.home-weather-hero span) { +.root :global(.home-weather-label), +.root :global(.home-weather-sub), +.root :global(.home-weather-stat span), +.root :global(.home-weather-stat small) { display: block; - margin-top: 8px; color: rgba(148, 163, 184, 0.88); font-size: 12px; } +.root :global(.home-weather-label) { + margin-bottom: 8px; + color: #67e8f9; + font-size: 10px; + font-weight: 900; + letter-spacing: 0.14em; + text-transform: uppercase; +} + +.root :global(.home-weather-sub) { + margin-top: 10px; +} + +.root :global(.home-weather-side) { + display: grid; + justify-items: end; + gap: 10px; +} + .root :global(.home-weather-icon) { position: relative; width: 88px; height: 76px; } +.root :global(.home-weather-stat) { + min-width: 118px; + padding: 9px 10px; + border: 1px solid rgba(148, 163, 184, 0.12); + border-radius: 12px; + background: rgba(2, 8, 18, 0.35); + text-align: right; +} + +.root :global(.home-weather-stat strong) { + display: block; + margin-top: 3px; + color: #f8fafc; + font-size: 18px; + font-weight: 900; +} + +.root :global(.home-weather-stat small) { + margin-top: 2px; + font-size: 10px; +} + .root :global(.home-weather-icon .sun), .root :global(.home-weather-icon .mist), .root :global(.home-weather-icon .wind), diff --git a/frontend/components/dashboard/HeaderBar.tsx b/frontend/components/dashboard/HeaderBar.tsx index a8d49a20..bfbb3a87 100644 --- a/frontend/components/dashboard/HeaderBar.tsx +++ b/frontend/components/dashboard/HeaderBar.tsx @@ -9,7 +9,10 @@ import { RotateCw, BookOpen, MoreHorizontal, + Moon, + Sun, } from "lucide-react"; +import { useEffect, useState } from "react"; import { useDashboardStore } from "@/hooks/useDashboardStore"; import { useI18n } from "@/hooks/useI18n"; @@ -37,6 +40,7 @@ export function HeaderBar({ const store = useDashboardStore(); const { locale, t } = useI18n(); const pathname = usePathname(); + const [theme, setTheme] = useState<"dark" | "light">("dark"); const isAuthenticated = store.proAccess.authenticated; const docsHref = "/docs/intro"; const docsActive = pathname?.startsWith("/docs"); @@ -119,6 +123,25 @@ export function HeaderBar({ ? `Pro ${Math.max(expiryInfo?.daysLeft || 0, 0)}d left` : `Pro 还剩 ${Math.max(expiryInfo?.daysLeft || 0, 0)} 天`; + useEffect(() => { + const savedTheme = + typeof window !== "undefined" + ? window.localStorage.getItem("polyweather_theme") + : null; + const nextTheme = savedTheme === "light" ? "light" : "dark"; + setTheme(nextTheme); + document.documentElement.classList.toggle("dark", nextTheme === "dark"); + document.documentElement.classList.toggle("light", nextTheme === "light"); + }, []); + + const toggleTheme = () => { + const nextTheme = theme === "dark" ? "light" : "dark"; + setTheme(nextTheme); + document.documentElement.classList.toggle("dark", nextTheme === "dark"); + document.documentElement.classList.toggle("light", nextTheme === "light"); + window.localStorage.setItem("polyweather_theme", nextTheme); + }; + return (
@@ -160,6 +183,20 @@ export function HeaderBar({ + + import("@/components/dashboard/HistoryModal").then( @@ -181,21 +180,6 @@ function formatEdge(value: number | null | undefined) { return `${sign}${normalized.toFixed(1)}%`; } -function getModelLabels(detail?: CityDetail | null) { - const date = detail?.local_date || ""; - const dailyModels = date ? detail?.multi_model_daily?.[date]?.models : null; - const modelMap = dailyModels || detail?.multi_model || {}; - const labels = Object.keys(modelMap) - .filter((key) => Number.isFinite(Number(modelMap[key]))) - .map((key) => - key - .replace(/^open_meteo_/i, "") - .replace(/_/g, " ") - .replace(/\b\w/g, (letter) => letter.toUpperCase()), - ); - return ["DEB", ...labels].slice(0, 6); -} - function buildSparklinePoints(values: number[] | undefined) { if (!values?.length) return ""; const width = 92; @@ -724,13 +708,6 @@ function HomeIntelligencePanel({ snapshots }: { snapshots: CitySnapshot[] }) { city.risk_level || summary?.risk?.level || detail?.risk?.level; - const deviation = summary?.deviation_monitor || detail?.deviation_monitor; - const observationSource = normalizeObservationSourceLabel( - summary?.current?.settlement_source_label || - detail?.current?.settlement_source_label || - city.settlement_source_label, - "METAR", - ); const probabilityBuckets = detail?.probabilities?.distribution || (detail?.local_date @@ -738,7 +715,6 @@ function HomeIntelligencePanel({ snapshots }: { snapshots: CitySnapshot[] }) { : undefined) || []; const displayedProbabilities = probabilityBuckets.slice(0, 4); - const modelLabels = getModelLabels(detail); const marketScan = detail?.market_scan; const marketBucket = marketScan?.temperature_bucket || marketScan?.top_buckets?.[0] || null; @@ -772,9 +748,7 @@ function HomeIntelligencePanel({ snapshots }: { snapshots: CitySnapshot[] }) { maxTime, localTime, riskLevel, - observationSource, displayedProbabilities, - modelLabels, marketScan, showOpportunityLabel: !marketScan || spotlight.tradableOpportunity, marketLabel: marketBucket @@ -823,29 +797,6 @@ function HomeIntelligencePanel({ snapshots }: { snapshots: CitySnapshot[] }) { ? "Pro locked" : "PRO 锁定", forecastDays: buildHomeForecastDays(detail, locale), - keySignals: [ - { - active: Number(marketEdge) > 0, - label: - locale === "en-US" ? "DEB > Market implied" : "DEB 高于市场隐含", - tone: "green", - }, - { - active: - deviation?.trend === "expanding" || deviation?.direction === "hot", - label: locale === "en-US" ? "Rising temps trend" : "升温趋势", - tone: "green", - }, - { - active: Boolean(detail?.peak?.hours?.length), - label: detail?.peak?.hours?.length - ? `${locale === "en-US" ? "High impact window" : "高影响窗口"} ${detail.peak.hours[0]}-${detail.peak.hours[detail.peak.hours.length - 1]}` - : locale === "en-US" - ? "High impact window pending" - : "高影响窗口待确认", - tone: "amber", - }, - ], }; }, [ locale, @@ -867,9 +818,7 @@ function HomeIntelligencePanel({ snapshots }: { snapshots: CitySnapshot[] }) { maxTime, localTime, riskLevel, - observationSource, displayedProbabilities, - modelLabels, marketScan, tradableOpportunity, showOpportunityLabel, @@ -897,7 +846,6 @@ function HomeIntelligencePanel({ snapshots }: { snapshots: CitySnapshot[] }) { marketModelLabel, proLabel, forecastDays, - keySignals, } = spotlightView; const subtitle = `${cityCode} · ${localizedAirportName}`; const proCard = ( @@ -975,34 +923,38 @@ function HomeIntelligencePanel({ snapshots }: { snapshots: CitySnapshot[] }) { {proCard}
-
+
+ + {locale === "en-US" ? "Observed now" : "当前实况"} + {formatTemperature(currentTemp, symbol)} - - {locale === "en-US" ? "Feels like" : "体感接近"}{" "} + + {locale === "en-US" ? "Feels near" : "体感接近"}{" "} {formatTemperature(currentTemp, symbol)}
- -
- {locale === "en-US" ? "Max so far" : "当前最高"} - - {formatTemperature(maxSoFar, symbol)} {maxTime} - +
+ +
+ {locale === "en-US" ? "Day high" : "日内高点"} + {formatTemperature(maxSoFar, symbol)} + {maxTime} +
@@ -1095,18 +1047,6 @@ function HomeIntelligencePanel({ snapshots }: { snapshots: CitySnapshot[] }) {
) : null} -
-

{locale === "en-US" ? "Model stack" : "模型栈"}

-
- {modelLabels.map((label) => ( - - - {label} - - ))} -
-
-

{probabilityTitle} {dayMaxLabel} @@ -1145,7 +1085,8 @@ function HomeIntelligencePanel({ snapshots }: { snapshots: CitySnapshot[] }) { )}

-
+ {tradableOpportunity ? ( +

{marketTitle} @@ -1191,20 +1132,8 @@ function HomeIntelligencePanel({ snapshots }: { snapshots: CitySnapshot[] }) { {locale === "en-US" ? "Unlock market layer" : "解锁市场层"} ) : null} -

- -
-

{locale === "en-US" ? "Key signals" : "关键信号"}

-
    - {keySignals.map((signal) => ( -
  • - {signal.label} - -
  • - ))} -
-

{observationSource}

-
+
+ ) : null} );