From 8f6aa262a32cb320c2e4b27afd35c9c8aecd8306 Mon Sep 17 00:00:00 2001 From: "2569718930@qq.com" <2569718930@qq.com> Date: Thu, 23 Apr 2026 04:10:50 +0800 Subject: [PATCH] Fix homepage opportunity and focus panel layout --- .../components/dashboard/Dashboard.module.css | 103 +++++++++--- .../dashboard/PolyWeatherDashboard.tsx | 154 ++++++++++-------- 2 files changed, 173 insertions(+), 84 deletions(-) diff --git a/frontend/components/dashboard/Dashboard.module.css b/frontend/components/dashboard/Dashboard.module.css index 5b05ec9a..24472d3b 100644 --- a/frontend/components/dashboard/Dashboard.module.css +++ b/frontend/components/dashboard/Dashboard.module.css @@ -1146,7 +1146,6 @@ } .root :global(.home-pro-card) { - margin-top: auto; display: flex; align-items: center; justify-content: space-between; @@ -1665,12 +1664,15 @@ } .root :global(.home-card-section.intraday) { - border-color: rgba(34, 211, 238, 0.18); + border-color: rgba(34, 211, 238, 0.2); + background: + radial-gradient(circle at 0% 35%, rgba(34, 211, 238, 0.12), transparent 44%), + linear-gradient(180deg, rgba(7, 14, 26, 0.94), rgba(9, 17, 30, 0.82)); } .root :global(.home-intraday-chart) { position: relative; - padding: 10px 0 0; + padding: 6px 0 0; } .root :global(.home-intraday-chart svg) { @@ -1742,6 +1744,37 @@ font-weight: 700; } +.root :global(.home-intraday-reports) { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 7px; + margin-top: 8px; +} + +.root :global(.home-intraday-reports span) { + min-width: 0; + display: flex; + align-items: center; + justify-content: space-between; + gap: 6px; + padding: 7px 8px; + border: 1px solid rgba(34, 211, 238, 0.12); + border-radius: 10px; + background: rgba(2, 8, 18, 0.55); +} + +.root :global(.home-intraday-reports b) { + color: rgba(148, 163, 184, 0.9); + font-size: 10px; + font-weight: 800; +} + +.root :global(.home-intraday-reports strong) { + color: #e0f2fe; + font-size: 11px; + font-weight: 900; +} + .root :global(.home-card-section.forecast) { border-color: rgba(99, 102, 241, 0.24); } @@ -1806,33 +1839,40 @@ } .root :global(.home-card-section.probability) { - border-color: rgba(115, 137, 161, 0.16); + border-color: rgba(251, 113, 133, 0.18); + background: + radial-gradient(circle at 100% 0%, rgba(251, 113, 133, 0.08), transparent 42%), + linear-gradient(180deg, rgba(7, 14, 26, 0.94), rgba(9, 17, 30, 0.82)); } -.root :global(.home-probability-list) { +.root :global(.home-probability-list), +.root :global(.home-probability-ladder) { display: grid; gap: 8px; } -.root :global(.home-probability-row) { +.root :global(.home-probability-row), +.root :global(.home-probability-ladder-row) { display: grid; - grid-template-columns: 58px 1fr; + grid-template-columns: 58px minmax(0, 1fr) 42px; align-items: center; - gap: 10px; + gap: 9px; color: rgba(226, 232, 240, 0.95); font-size: 12px; font-weight: 850; } -.root :global(.home-probability-row div) { +.root :global(.home-probability-row div), +.root :global(.home-probability-track) { position: relative; - height: 18px; + height: 14px; overflow: hidden; border-radius: 999px; background: rgba(115, 137, 161, 0.12); } -.root :global(.home-probability-row i) { +.root :global(.home-probability-row i), +.root :global(.home-probability-track i) { position: absolute; inset: 0 auto 0 0; border-radius: inherit; @@ -1840,22 +1880,31 @@ box-shadow: 0 0 10px rgba(34, 211, 238, 0.14); } -.root :global(.home-probability-row:nth-child(3) i) { +.root :global(.home-probability-row:nth-child(3) i), +.root :global(.home-probability-ladder-row:nth-child(3) i) { background: linear-gradient(90deg, #f59e0b, #fbbf24); } -.root :global(.home-probability-row:nth-child(n + 4) i) { +.root :global(.home-probability-row:nth-child(n + 4) i), +.root :global(.home-probability-ladder-row:nth-child(n + 4) i) { background: linear-gradient(90deg, #ef4444, #fb7185); } -.root :global(.home-probability-row strong) { +.root :global(.home-probability-row strong), +.root :global(.home-probability-ladder-row strong) { position: relative; z-index: 1; display: block; - padding-left: 12px; color: #f8fafc; font-size: 12px; - line-height: 18px; + line-height: 1; + text-align: right; +} + +.root :global(.home-probability-threshold) { + color: rgba(226, 232, 240, 0.95); + font-size: 12px; + font-weight: 900; } .root :global(.home-card-empty) { @@ -2033,7 +2082,7 @@ } .root :global(.home-summary-card) { - min-height: 118px; + min-height: 106px; display: flex; flex-direction: column; justify-content: space-between; @@ -2145,8 +2194,8 @@ min-width: 0; display: flex; flex-direction: column; - gap: 12px; - min-height: 122px; + gap: 9px; + min-height: 132px; padding: 14px; border: 1px solid rgba(148, 163, 184, 0.14); border-radius: 16px; @@ -2247,6 +2296,7 @@ font-size: 11px; text-overflow: ellipsis; white-space: nowrap; + min-height: 16px; } .root :global(.opportunity-yes) { @@ -2267,6 +2317,21 @@ font-weight: 800; } +.root :global(.opportunity-sparkline) { + width: 100%; + height: 28px; + margin-top: auto; +} + +.root :global(.opportunity-sparkline polyline) { + fill: none; + stroke: #18e6d4; + stroke-width: 2; + stroke-linecap: round; + stroke-linejoin: round; + filter: drop-shadow(0 0 8px rgba(34, 211, 238, 0.22)); +} + /* Market-closed opportunity card — dimmed state */ .root :global(.opportunity-card.market-closed) { opacity: 0.6; diff --git a/frontend/components/dashboard/PolyWeatherDashboard.tsx b/frontend/components/dashboard/PolyWeatherDashboard.tsx index 1b297752..e19884b6 100644 --- a/frontend/components/dashboard/PolyWeatherDashboard.tsx +++ b/frontend/components/dashboard/PolyWeatherDashboard.tsx @@ -28,7 +28,6 @@ import { getWeatherSummary, } from "@/lib/dashboard-utils"; import { normalizeObservationSourceLabel } from "@/lib/source-labels"; -import { Expand, Thermometer, CloudRain, Wind } from "lucide-react"; const loadHistoryModal = () => import("@/components/dashboard/HistoryModal").then( @@ -227,6 +226,11 @@ type HomeTrendChart = { forecastPath: string; legendText: string; observationDots: Array<{ cx: number; cy: number; key: string }>; + hourlyReports: Array<{ + key: string; + label: string; + temperatureText: string; + }>; hoverPoints: Array<{ cx: number; cy: number; @@ -399,32 +403,6 @@ function HomeMapToolbar() { -
-
- - - -
- -
@@ -962,6 +972,8 @@ function HomeIntelligencePanel({ snapshots }: { snapshots: CitySnapshot[] }) {
+ {proCard} +
{formatTemperature(currentTemp, symbol)} @@ -1007,8 +1019,8 @@ function HomeIntelligencePanel({ snapshots }: { snapshots: CitySnapshot[] }) { {trendChart ? (

- {locale === "en-US" ? "Intraday trend" : "今日日内走势"}{" "} - {locale === "en-US" ? "compact" : "简版"} + {locale === "en-US" ? "Hourly reports" : "小时准点报"}{" "} + {locale === "en-US" ? "1h cadence" : "1h 级别"}

) : null}
+ {trendChart.hourlyReports.length ? ( +
+ {trendChart.hourlyReports.map((report) => ( + + {report.label} + {report.temperatureText} + + ))} +
+ ) : null}
) : null} @@ -1087,23 +1109,25 @@ function HomeIntelligencePanel({ snapshots }: { snapshots: CitySnapshot[] }) {

- {probabilityTitle} ({dayMaxLabel}) + {probabilityTitle} {dayMaxLabel}

{displayedProbabilities.length ? ( -
+
{displayedProbabilities.map((bucket, index) => { const probability = Number(bucket.probability ?? 0); const width = Math.max(6, Math.min(100, probability * 100)); return (
- {getProbabilityLabel(bucket, symbol)} -
+ + {getProbabilityLabel(bucket, symbol)} + +
- {formatProbability(probability)}
+ {formatProbability(probability)}
); })} @@ -1182,27 +1206,6 @@ function HomeIntelligencePanel({ snapshots }: { snapshots: CitySnapshot[] }) {

{observationSource}

-
-
- {proLabel} - - {isPro - ? locale === "en-US" - ? "Open today intraday analysis first. History review and future-day workflow stay available after that." - : "先打开今日日内分析,历史复盘和未来日工作流仍可继续查看。" - : locale === "en-US" - ? "History review and future dates stay paid." - : "历史复盘和未来日期保持付费。"} - -
- {isPro ? ( - - ) : ( - {locale === "en-US" ? "Upgrade" : "升级"} - )} -
); } @@ -1265,8 +1268,8 @@ function OpportunityStrip({ snapshots }: { snapshots: CitySnapshot[] }) { {locale === "en-US" - ? "Sorted by score and risk" - : "按综合评分排序"} + ? "Market question · YES/NO · Edge · Trend" + : "市场问题 · YES/NO 价格 · Edge · 小趋势线"}
@@ -1291,6 +1294,23 @@ function OpportunityStrip({ snapshots }: { snapshots: CitySnapshot[] }) { summary?.risk?.level || detail?.risk?.level; const marketClosed = !tradableOpportunity; + const marketBucket = detail?.market_scan?.temperature_bucket; + const marketQuestion = + detail?.market_scan?.primary_market?.question || + `${getProbabilityLabel(marketBucket || {}, symbol)} ${ + detail?.market_scan?.selected_date || + detail?.local_date || + "" + }`; + const opportunitySparkline = buildSparklinePoints( + detail?.market_scan?.sparkline?.length + ? detail.market_scan.sparkline + : [ + Number(summary?.current?.temp ?? detail?.current?.temp ?? 0), + Number(debPrediction ?? 0), + Number(detail?.forecast?.today_high ?? debPrediction ?? 0), + ], + ); return (
- > {formatTemperature(debPrediction, symbol)}{" "} - {locale === "en-US" ? "target" : "目标"} + {marketQuestion} {marketClosed && ( {" · "} @@ -1338,6 +1357,11 @@ function OpportunityStrip({ snapshots }: { snapshots: CitySnapshot[] }) { {formatEdge(getMarketEdgeValue(detail))}
+ ); },