新增终端城市大洲分组设计文档

覆盖桌面端 9 列分区分组表格、移动端 Tab+卡片流布局方案。
所有数据字段已就绪,无需后端改动。
@
This commit is contained in:
2569718930@qq.com
2026-05-25 01:35:07 +08:00
parent 7e9d7a4b59
commit 637b580bbd
@@ -0,0 +1,137 @@
# 终端城市表格按大洲分组 — 设计文档
日期: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 — 数据异常/缺失/延迟
```
## 验收标准
1. 桌面端:7 时区 + Active Signals 分组,可折叠,9 列表格
2. 移动端:Tab 切换 + 卡片流
3. Gap 颜色按语义映射,非简单正负色
4. Market 列显示价格格式(Y XX¢)
5. 默认折叠规则:Active Signals 展开、有机遇展开、无机遇折叠
6. 双主题(dark/lightCSS 适配
7. TypeScript 类型检查通过
8. `npm run build` 通过