清理时区逻辑:TRADING_REGIONS→REGIONS,移除 detectLocalRegion/TZ fallback,用 CITY_REGION 硬编码替代

This commit is contained in:
2569718930@qq.com
2026-05-25 20:23:44 +08:00
parent 798e2d6cc2
commit 2cd43b607d
3 changed files with 32 additions and 65 deletions
@@ -27,9 +27,9 @@ import {
getGapColor,
getSignalLabel,
getSignalState,
resolveTradingRegionKey,
TRADING_REGIONS,
detectLocalRegion,
getCityRegion,
REGIONS,
getDefaultRegion,
} from "@/components/dashboard/scan-terminal/continent-grouping";
import { MobileCityCard } from "@/components/dashboard/scan-terminal/MobileCityCard";
import { MobileRegionTabs } from "@/components/dashboard/scan-terminal/MobileRegionTabs";
@@ -290,7 +290,7 @@ function PolyWeatherTerminal({
const filteredRegionRows = useMemo(() => {
return rows.filter(
(row) => resolveTradingRegionKey(row) === selectedRegionKey,
(row) => getCityRegion(row) === selectedRegionKey,
);
}, [rows, selectedRegionKey]);
@@ -504,7 +504,7 @@ function PolyWeatherTerminal({
<>
{/* Region tabs */}
<div className="flex shrink-0 items-center gap-1 overflow-x-auto rounded-[4px] border border-[#cfd6df] bg-white p-1 mb-2 scrollbar-none">
{TRADING_REGIONS.filter((r) => visibleRegions.has(r.key)).map((r) => ({
{REGIONS.filter((r) => visibleRegions.has(r.key)).map((r) => ({
key: r.key,
labelEn: r.labelEn.toUpperCase(),
labelZh: r.labelZh,
@@ -540,7 +540,7 @@ function PolyWeatherTerminal({
id="region-selector-popover"
className="hidden absolute right-0 top-full mt-1 z-50 bg-white border border-slate-200 rounded-lg shadow-lg p-2 min-w-[180px]"
>
{TRADING_REGIONS.map((r) => {
{REGIONS.map((r) => {
const checked = visibleRegions.has(r.key);
return (
<label
@@ -649,7 +649,7 @@ function ScanTerminalScreen() {
const stored = localStorage.getItem("polyweather_visible_regions");
if (stored) return new Set(JSON.parse(stored));
} catch {}
return new Set(TRADING_REGIONS.map((r) => r.key));
return new Set(REGIONS.map((r) => r.key));
});
const toggleRegion = useCallback((key: string) => {
setVisibleRegions((prev) => {
@@ -734,7 +734,7 @@ function ScanTerminalScreen() {
}, []);
useEffect(() => {
setSelectedRegionKey(detectLocalRegion());
setSelectedRegionKey(getDefaultRegion());
setLocalTimezoneOffsetSeconds(-new Date().getTimezoneOffset() * 60);
}, []);
@@ -13,7 +13,14 @@ import {
XAxis,
YAxis,
} from "recharts";
import type { AmosData, AirportCurrentConditions, CityDetail, ScanOpportunityRow } from "@/lib/dashboard-types";
import type {
AmosData,
AirportCurrentConditions,
CityDetail,
ScanOpportunityRow,
ForecastDay,
DailyModelForecast,
} from "@/lib/dashboard-types";
import { buildDebBaselinePath } from "@/lib/temperature-chart-paths";
import { Panel } from "@/components/dashboard/scan-terminal/Panel";
import { rowName, temp } from "@/components/dashboard/scan-terminal/utils";
@@ -1,6 +1,6 @@
import type { ScanOpportunityRow } from "@/lib/dashboard-types";
export const TRADING_REGIONS = [
export const REGIONS = [
{ key: "east_asia", labelEn: "East Asia", labelZh: "东亚", sort: 1 },
{ key: "southeast_asia", labelEn: "Southeast Asia", labelZh: "东南亚", sort: 2 },
{ key: "central_asia", labelEn: "Central / South Asia", labelZh: "中亚 / 南亚", sort: 3 },
@@ -10,23 +10,11 @@ export const TRADING_REGIONS = [
{ key: "north_america", labelEn: "North America", labelZh: "北美", sort: 7 },
] as const;
export type TradingRegionKey = (typeof TRADING_REGIONS)[number]["key"];
export type RegionKey = (typeof REGIONS)[number]["key"];
/** Map browser timezone offset (hours) to the closest trading region. */
export function detectLocalRegion(): TradingRegionKey {
const offset = -new Date().getTimezoneOffset() / 60; // UTC offset in hours
if (offset >= 8) return "east_asia";
if (offset >= 7) return "southeast_asia";
if (offset >= 4.5) return "central_asia";
if (offset >= 2) return "west_asia";
if (offset >= -2) return "europe_africa";
if (offset >= -4) return "south_america";
return "north_america";
}
const REGION_KEYS = new Set<string>(REGIONS.map((r) => r.key));
const TRADING_REGION_KEYS = new Set<string>(TRADING_REGIONS.map((region) => region.key));
const CITY_REGION_FALLBACK: Record<string, TradingRegionKey> = {
const CITY_REGION: Record<string, RegionKey> = {
beijing: "east_asia",
busan: "east_asia",
chengdu: "east_asia",
@@ -79,51 +67,23 @@ const CITY_REGION_FALLBACK: Record<string, TradingRegionKey> = {
wellington: "east_asia",
};
function normalizeRegionValue(value?: string | null) {
return String(value || "")
.trim()
.toLowerCase()
.replace(/[-\s]+/g, "_");
function normalizeCity(value?: string | null) {
return String(value || "").trim().toLowerCase()
.replace(/[_-]+/g, " ").replace(/\s+/g, " ");
}
function normalizeCityValue(value?: string | null) {
return String(value || "")
.trim()
.toLowerCase()
.replace(/[_-]+/g, " ")
.replace(/\s+/g, " ");
export function getCityRegion(row: ScanOpportunityRow): RegionKey | null {
const key = normalizeCity(row.city || row.city_display_name || row.display_name);
return CITY_REGION[key] || null;
}
function finiteNumber(value: unknown) {
const numeric = Number(value);
return Number.isFinite(numeric) ? numeric : null;
}
export function resolveTradingRegionKey(row: ScanOpportunityRow): TradingRegionKey | null {
const direct = normalizeRegionValue(row.trading_region);
if (TRADING_REGION_KEYS.has(direct)) return direct as TradingRegionKey;
const cityKey = normalizeCityValue(row.city || row.city_display_name || row.display_name);
const cityRegion = CITY_REGION_FALLBACK[cityKey];
if (cityRegion) return cityRegion;
const offset = finiteNumber(row.tz_offset_seconds);
if (offset !== null) {
const hours = offset / 3600;
if (hours >= 8) return "east_asia";
if (hours >= 7) return "southeast_asia";
if (hours >= 4.5) return "central_asia";
if (hours >= 2) return "west_asia";
if (hours >= -2) return "europe_africa";
if (hours >= -4) return "south_america";
return "north_america";
}
return null;
/** Default region on first load — East Asia. */
export function getDefaultRegion(): RegionKey {
return "east_asia";
}
export interface ContinentGroup {
key: TradingRegionKey | "active_signals";
key: RegionKey | "active_signals";
labelEn: string;
labelZh: string;
sort: number;
@@ -203,7 +163,7 @@ export function buildContinentGroups(rows: ScanOpportunityRow[], isEn: boolean):
const regionMap = new Map<string, ScanOpportunityRow[]>();
for (const row of rows) {
const region = resolveTradingRegionKey(row) || "unknown";
const region = getCityRegion(row) || "unknown";
if (!regionMap.has(region)) regionMap.set(region, []);
regionMap.get(region)!.push(row);
}
@@ -229,7 +189,7 @@ export function buildContinentGroups(rows: ScanOpportunityRow[], isEn: boolean):
});
}
for (const region of TRADING_REGIONS) {
for (const region of REGIONS) {
const regionRows = regionMap.get(region.key) || [];
if (regionRows.length === 0) continue;