From 1275906a1995389827e5acb8f1ede7a616210637 Mon Sep 17 00:00:00 2001 From: "2569718930@qq.com" <2569718930@qq.com> Date: Wed, 22 Apr 2026 23:47:28 +0800 Subject: [PATCH] Frame homepage map and auto-focus top opportunity --- .../components/dashboard/Dashboard.module.css | 56 +++++++++++++++++-- .../dashboard/PolyWeatherDashboard.tsx | 24 +++++++- 2 files changed, 75 insertions(+), 5 deletions(-) diff --git a/frontend/components/dashboard/Dashboard.module.css b/frontend/components/dashboard/Dashboard.module.css index a6718420..9b536c7a 100644 --- a/frontend/components/dashboard/Dashboard.module.css +++ b/frontend/components/dashboard/Dashboard.module.css @@ -67,12 +67,19 @@ /* ── Map ── */ .root :global(.map) { - width: 100%; - height: 100%; position: absolute; - top: 0; - left: 0; + top: calc(var(--header-height) + 16px); + right: 418px; + bottom: 128px; + left: calc(var(--sidebar-width) + 30px); z-index: 1; + overflow: hidden; + border: 1px solid rgba(34, 211, 238, 0.12); + border-radius: 22px; + background: #020617; + box-shadow: + 0 28px 80px rgba(0, 0, 0, 0.38), + inset 0 1px 0 rgba(255, 255, 255, 0.05); } .weatherAura { @@ -890,6 +897,31 @@ background: rgba(148, 163, 184, 0.1); } +.root :global(.home-top-opportunity-label) { + display: inline-flex; + align-self: flex-start; + align-items: center; + gap: 7px; + padding: 5px 8px; + border: 1px solid rgba(34, 211, 238, 0.18); + border-radius: 999px; + background: rgba(8, 145, 178, 0.1); + color: #67e8f9; + font-size: 10px; + font-weight: 900; + letter-spacing: 0.12em; + text-transform: uppercase; +} + +.root :global(.home-top-opportunity-label::before) { + content: ""; + width: 6px; + height: 6px; + border-radius: 999px; + background: #22c55e; + box-shadow: 0 0 12px rgba(34, 197, 94, 0.72); +} + .root :global(.home-card-titlebar) { display: flex; justify-content: space-between; @@ -1468,6 +1500,10 @@ } @media (max-width: 1360px) { + .root :global(.map) { + right: 18px; + } + .root :global(.home-intelligence-panel) { display: none; } @@ -1478,6 +1514,11 @@ } @media (max-width: 1020px) { + .root :global(.map) { + left: 18px; + bottom: 188px; + } + .root :global(.home-opportunity-strip) { left: 18px; grid-template-columns: 1fr; @@ -1489,6 +1530,13 @@ } @media (max-width: 720px) { + .root :global(.map) { + inset: var(--header-height) 0 0; + border-radius: 0; + border-left: 0; + border-right: 0; + } + .root :global(.home-opportunity-strip) { display: none; } diff --git a/frontend/components/dashboard/PolyWeatherDashboard.tsx b/frontend/components/dashboard/PolyWeatherDashboard.tsx index 6f111272..0a269985 100644 --- a/frontend/components/dashboard/PolyWeatherDashboard.tsx +++ b/frontend/components/dashboard/PolyWeatherDashboard.tsx @@ -2,7 +2,7 @@ import clsx from "clsx"; import dynamic from "next/dynamic"; import Link from "next/link"; -import { useEffect, useMemo } from "react"; +import { useEffect, useMemo, useRef } from "react"; import styles from "./Dashboard.module.css"; import detailChromeStyles from "./DetailPanelChrome.module.css"; import modalChromeStyles from "./ModalChrome.module.css"; @@ -122,7 +122,13 @@ function buildSnapshot( detail?.risk?.level; const hitRate = Number(city.deb_recent_hit_rate ?? 0); const sampleCount = Number(city.deb_recent_sample_count ?? 0); + const edgePercent = Number(detail?.market_scan?.edge_percent); + const normalizedEdge = + Number.isFinite(edgePercent) && Math.abs(edgePercent) <= 1 + ? edgePercent * 100 + : edgePercent; const score = + (Number.isFinite(normalizedEdge) ? 1000 + normalizedEdge * 10 : 0) + (RISK_SCORE[String(tier || "")] || 0) * 100 + hitRate * 100 + Math.min(sampleCount, 60) / 10; @@ -288,6 +294,10 @@ function HomeIntelligencePanel({ snapshots }: { snapshots: CitySnapshot[] }) { × +