5.1 KiB
5.1 KiB
终端城市表格按大洲分组 — 设计文档
日期:2026-05-25 状态:已确认
目标
将扫描终端(Scan Terminal)的城市列表从平铺表格改造为按时区分组、按交易信号优先的金融终端风格布局。
数据
所有字段已在 /api/scan/terminal 响应的 ScanOpportunityRow 中就绪,无需后端改动。
列 → 字段映射
| 列名 | 字段 | 类型 |
|---|---|---|
| City | city, airport, local_time |
string |
| Obs | current_temp |
number | null |
| High | current_max_so_far |
number | null |
| DEB | deb_prediction |
number | null |
| Gap | signed_gap / gap_to_target |
number | null |
| Market | midpoint, bid, ask |
number | null |
| Edge | edge_percent |
number | null |
| Spr/Liq | spread, book_liquidity |
number | null |
| Signal | signal_status, ai_decision |
string | null |
时区分组
后端 scan_terminal_filters.py 按 UTC 偏移量划分 7 个交易区域:
| 排序 | 区域键 | 英文 | 中文 | UTC 条件 |
|---|---|---|---|---|
| 1 | east_asia | East Asia | 东亚 | >= +8 |
| 2 | southeast_asia | Southeast Asia | 东南亚 | >= +7 |
| 3 | central_asia | Central / South Asia | 中亚/南亚 | >= +5 |
| 4 | west_asia | West Asia / Middle East | 西亚/中东 | >= +3 |
| 5 | europe_africa | Europe / Africa | 欧洲/非洲 | >= 0 |
| 6 | south_america | Latin America | 拉美 | >= -5 |
| 7 | north_america | North America | 北美 | < -5 |
桌面端布局(≥ 768px)
虚拟分组:"Active Signals"
在 7 个时区分组上方插入一个虚拟分组,聚合当前最重要的信号:
- 筛选条件:
ai_decision === "approve"、tradable === true、peak、rising、超预期 - 标题行显示:城市数量、Hot 城市、更新时间
- 格式:
▼ Active Signals 活跃信号 6 · Hot: Tokyo · Updated 14:32
时区分组标题行
- 显示:折叠箭头、中英文名、城市数、active 数、watch 数、本地时间
- 热门城市标注
- 格式:
▼ East Asia 东亚 5 · Active 2 · Watch 1 · LT 14:20 - 可折叠,默认规则:
- Active Signals 始终展开
- 包含 active/watch 的时区展开
- 无机会的时区折叠
表格行
- 9 列:City | Obs | High | DEB | Gap | Market | Edge | Spr/Liq | Signal
- Market 列显示价格格式:
Y 72¢/N 28¢ - Signal 列显示:
◆ Active/● Watch/○ Closed(文字+图标)
Gap 列颜色语义
| 状态 | 颜色 | 含义 |
|---|---|---|
| 已突破/超预期 | 绿色 #22c55e |
对市场方向有利 |
| 接近目标未突破 | 橙色 #f59e0b |
Peak Watch |
| 明显低于目标 | 蓝灰 #64748b |
尚不到位 |
| 追不上/时间不够 | 灰色 #94a3b8 |
机会减弱 |
| 数据异常/风险 | 红色 #ef4444 |
需关注 |
移动端布局(< 768px)
Tab 栏
横向滚动,包含:All | Active | 东亚 | 东南亚 | 中亚南亚 | 西亚 | 欧洲非洲 | 北美 | 拉美
当前时区 Tab 默认选中。
信号卡片流
每张卡片两行信息:
┌──────────────────────────────┐
│ Tokyo · ◆ Active │
│ Obs 28.1°C · Gap -0.8°C · Y 72¢ │
│ High 29.3°C · DEB 30.0°C │
└──────────────────────────────┘
卡片字段:City、Signal、Obs、Gap、Market(第一行),High、DEB(第二行)
文件变更范围
主要文件
| 文件 | 变更 | 说明 |
|---|---|---|
components/dashboard/ScanTerminalDashboard.tsx |
重构 | 拆分 MarketTable、KoyfinWeatherTerminal,新增分组和卡片组件 |
components/dashboard/scan-terminal/ |
新增 | ContinentGroupHeader.tsx、ActiveSignalsGroup.tsx、MobileCityCard.tsx、MobileRegionTabs.tsx |
components/dashboard/scan-terminal/continent-grouping.ts |
新增 | 分组逻辑:按 trading_region 分桶、Active Signals 筛选、折叠状态管理 |
components/dashboard/scan-terminal/decision-utils.ts |
修改 | 补充排序逻辑,Active Signals 置顶 |
components/dashboard/ScanTerminalDashboard.module.css |
修改 | 新增分组标题行、卡片流、Tab 栏样式 |
components/dashboard/ScanTerminalLightTheme.module.css |
新增/修改 | 浅色主题适配 |
不改的文件
- 后端 API:所有字段已就绪
ScanOpportunityRow类型定义:字段充足- 数据获取 hooks:
useScanTerminalQuery保持不变
信号状态枚举
◆ Active — approve / tradable + active
● Watch — watch / monitor / peak_watch
○ Closed — veto / closed / inactive
! Data — 数据异常/缺失/延迟
验收标准
- 桌面端:7 时区 + Active Signals 分组,可折叠,9 列表格
- 移动端:Tab 切换 + 卡片流
- Gap 颜色按语义映射,非简单正负色
- Market 列显示价格格式(Y XX¢)
- 默认折叠规则:Active Signals 展开、有机遇展开、无机遇折叠
- 双主题(dark/light)CSS 适配
- TypeScript 类型检查通过
npm run build通过