# Arbitrage Engine 前端页面说明
> 本文从“用户看到的界面”出发,按页面/导航顺序描述整个前端。
> 代码和数据层的详细结构,请参考 `docs/arbitrage-engine-full-spec.md`。
---
## 0. 全局框架与导航
### 0.1 布局
前端采用 Next.js App Router,根布局在 `frontend/app/layout.tsx` 中定义:
- 左侧:``
- 固定在左侧,白底,带边框,可折叠(桌面端)。
- 包含项目 Logo 和主导航按钮。
- 右侧:顶部为 ``,下面为当前页面内容:
- `AuthHeader` 只在桌面端显示,用于展示登录状态(邮箱/Admin 徽章/退出按钮)。
- 实际页面内容通过 `children` 渲染。
移动端(`md` 以下)顶栏和抽屉菜单也由 `Sidebar` 组件负责:
- 顶部条:左侧为 Logo,右侧为“登录/注册”或“退出”按钮 + 菜单汉堡按钮。
- 点击菜单按钮后,从左侧滑出抽屉式侧边栏,内容与桌面端导航一致。
### 0.2 顶部登录区(AuthHeader)
文件:`frontend/components/AuthHeader.tsx`
仅在桌面端显示(`hidden md:flex`)。
- 未登录:
- 右上角显示:
- `登录` 按钮:灰边,hover 变为蓝边。
- `注册` 按钮:蓝底白字主按钮。
- 点击分别跳转到 `/login` 与 `/register`。
- 已登录:
- 显示当前用户邮箱(`user.email`)。
- 如果 `user.role === "admin"`,在邮箱后显示一个黄色的 `Admin` 徽章。
- 右侧是 `退出` 按钮,点击调用 `logout()` 退出登录。
> 手机端的登录/注册/退出按钮由 `Sidebar` 内部负责,不走 `AuthHeader`。
### 0.3 侧边栏导航(Sidebar)
文件:`frontend/components/Sidebar.tsx`
- 顶部 Logo:
- 闪电图标(`Zap`)+ 文本 `Arbitrage Engine`(两行排版)。
- 导航项(`navItems`)定义如下:
```ts
const navItems = [
{ href: "/", label: "仪表盘", icon: LayoutDashboard },
{ href: "/trades", label: "成交流", icon: Activity },
{ href: "/live", label: "⚡ 实盘交易", icon: Bolt, section: "── 实盘 ──" },
{ href: "/strategy-plaza", label: "策略广场", icon: Zap, section: "── 策略 ──" },
{ href: "/strategy-plaza/deprecated", label: "废弃策略", icon: Archive },
{ href: "/server", label: "服务器", icon: Monitor },
{ href: "/about", label: "说明", icon: Info },
];
```
从用户视角,这些入口对应的主要功能是:
- `/` → **仪表盘**:资金费率实时监控与套利统计的首页。
- `/trades` → **成交流**:逐笔成交明细与交易流量分析。
- `/live` → **⚡ 实盘交易**:实盘风控与一键止血面板(L0/L1/L1.5 等区域)。
- `/strategy-plaza` → **策略广场**:V5.4 策略工厂的主入口,展示所有策略表现。
- `/strategy-plaza/deprecated` → **废弃策略**:已停用策略的列表视图。
- `/server` → **服务器**:服务器与 PM2 进程监控。
- `/about` → **说明**:策略原理、历史年化与风险说明。
> 账号相关页面 `/login`、`/register`、`/dashboard` 不在侧边栏中出现,通过右上角或跳转访问。
---
## 1. 首页 `/`(仪表盘)
文件:`frontend/app/page.tsx`
导出的组件名:`Dashboard`
### 1.1 页面目标
从用户视角,首页是一个**资金费率套利的总览仪表盘**,具备两个层次:
1. **未登录用户**:能看到 BTC/ETH 的实时资金费率、运行状态等,了解当前市场情况。
2. **已登录用户**:解锁完整的统计信息:
- 套利策略的历史统计(7天均值、年化、50/50组合等);
- 资金费率与价格的 K 线图;
- 历史费率明细表格;
- 已触发的资金费率“信号历史”;
- 策略原理说明。
首页不直接操作策略或模拟盘,更像是一个“观测面板 + 教程”,帮助用户理解当前资金费率环境和策略收益。
### 1.2 未登录状态下的展示
未登录逻辑由组件 `AuthGate` 控制:
- 上半部分(不受登录状态影响):
1. **标题行**
- 左侧:
- 主标题:`资金费率套利监控`
- 副标题(小字):`实时监控 BTC / ETH 永续合约资金费率`
- 右侧:
- 圆点状态灯:`运行中`(绿色) / `连接失败`(红色) / `加载中...`(灰色),根据 `/api/rates` 请求结果变化。
- “更新于 HH:MM:SS” 时间戳,表示最近一次成功更新资金费率的本地时间。
2. **资金费率卡片(RateCard)**
- 左卡:BTC,右卡:ETH。
- 每张卡展示:
- 当前资金费率;
- 标记价格、指数价格;
- 相关统计(具体字段由 `RateCard` 渲染)。
- 下半部分(被 `AuthGate` 包裹):
- 未登录时,`AuthGate` 渲染一个**模糊遮罩**效果:
- 内部真实内容会被 blur + 降低不透明度,作为背景。
- 上方覆盖一层白色半透明遮罩。
- 中间显示:
- 图标:`🔒`
- 文案:`登录后查看完整数据`
- 按钮:
- `登录`(蓝底按钮) → 跳转 `/login`
- `注册`(灰边按钮) → 跳转 `/register`
**结论**:未登录用户只能看到**实时费率卡片**和运行状态,不能查看历史统计、K 线和详细信号数据。
### 1.3 登录后的完整内容
当用户已登录且 `AuthGate` 放行时,首页显示以下完整模块:
1. **套利统计卡片(StatsCard,三张)**
- 在 `stats` 数据存在时渲染:
- `BTC 套利`:`mean7d` + `annualized`
- `ETH 套利`
- `50/50 组合`:BTC/ETH 各 50% 的组合年化表现
- 这些数据由 `/api/stats` 提供,用于给出近 7 天和年化收益的粗略估计。
2. **K 线大卡片(资金费率 & 标记价格)**
- 卡片标题:`K 线图`
- 币种切换按钮:`BTC` / `ETH`(控制 `symbol` 状态)。
- 内含两个子图:
1. **资金费率 K 线**
- 标题:`{symbol} 资金费率(万分之)`
- 顶部右侧 interval 选择器(`INTERVALS`),可选:
- `1m`, `5m`, `30m`, `1h`, `4h`, `8h`, `日(1d)`, `周(1w)`, `月(1M)`
- 使用 `MiniKChart` + `mode="rate"`,展示资金费率蜡烛图。
2. **标记价格 K 线**
- 标题:`{symbol} 标记价格(USD)`
- 使用同样的 interval 选择器,但 `mode="price"`,展示价格蜡烛图。
- 下层数据来源:`/api/kline?symbol=BTC&interval=...`(通过 `api.kline` 封装)。
3. **历史费率走势(7天双线图)**
- 标题:`历史费率走势(过去7天)`
- 使用 Recharts `LineChart` 绘制:
- X 轴:时间(按小时聚合,如 `MM-DD HH`)
- Y 轴:资金费率(百分比,格式化显示如 `0.1234%`)
- 两条线:
- `BTC`:蓝色;
- `ETH`:紫色;
- 中间有一条 `y=0` 的虚线参考线。
- 数据来自 `api.history()` 返回的 `HistoryResponse` 中的 `BTC` / `ETH` 历史 fundingRate 序列。
4. **历史费率明细表(左侧表格)**
- 标题:`历史费率明细(最近30条)`
- 表头:时间 / BTC / ETH
- 每行:
- 时间:`yyyy-MM-dd HH:mm`(字符串处理自 `timestamp`)
- BTC/ETH 列:
- 正值:绿色;
- 负值:红色;
- 无数据:灰色、显示 `--`。
- 数据来源同上(`HistoryResponse`),只是格式化和截取最近 30 条。
5. **信号历史表(右侧表格)**
- 标题:`信号历史`
- 表头:时间 / 币种 / 年化
- 内容:
- 当 `signals.length === 0`:显示提示行 `暂无信号(年化>10%时自动触发)`。
- 否则每行显示:
- 触发时间 `sent_at`(本地时间格式);
- 币种 `symbol`;
- 年化收益率 `annualized`(加 `%`)。
- 数据来源:`api.signalsHistory()`(封装了 `/api/signals/signal-history` 或类似接口)。
6. **策略原理说明卡片(蓝色 Info 区域)**
- 蓝色边框+淡蓝底的 info 卡片,标题 `策略原理:`
- 内容简述:
- 使用“现货多头 + 永续空头”构建无方向风险的套利组合;
- 每 8 小时收取资金费率作为收益;
- 核心是赚“费率”,不是赌方向。
整体上,登录后的首页是一个聚合视图,把“当前状态 + 历史表现 + 策略简介”集中在一个页面上。
### 1.4 首页依赖的主要 API
首页通过 `api` 封装(`frontend/lib/api`)访问后端,核心依赖至少包括:
- `GET /api/rates` → `api.rates()`
- 读取最新资金费率快照(BTC/ETH 的 markPrice/indexPrice/lastFundingRate 等)。
- `GET /api/stats` → `api.stats()`
- 返回 BTC/ETH 以及 50/50 组合的近 7 天均值与年化统计。
- `GET /api/history` → `api.history()`
- 返回过去若干天(如 7 天)的按小时聚合资金费率序列。
- `GET /api/signals/history` 或类似 → `api.signalsHistory()`
- 返回最近触发的资金费率套利信号(满足一定年化阈值)。
- `GET /api/stats/ytd` → `api.statsYtd()`
- 年初至今(YTD)的收益统计,用于 `RateCard` 等组件。
- `GET /api/kline?symbol=&interval=` → `api.kline(symbol, interval)`
- 提供资金费率和价格 K 线数据,用于首页的 K 线卡片。
这些接口的详细字段与 SQL 逻辑请以 `docs/arbitrage-engine-full-spec.md` 和 `backend/main.py` 中定义为准。
---
## 2. /trades(成交流)
文件:`frontend/app/trades/page.tsx`
导出的组件名:`TradesPage`
### 2.1 页面目标
`/trades` 页面从“逐笔成交”的角度,帮助用户观察:
- 当前市场是多方主动吃单更多,还是空方主动砸盘更多;
- 在过去一段时间内,不同时间粒度下买卖量的累积情况;
- 成交换手是否集中(成交量、最大单笔成交量等)。
它是一个 **成交流量分析工具页**,为信号研究和盘前/盘后复盘服务,不直接开仓/平仓。
### 2.2 登录要求与未登录展示
页面开头使用 `useAuth()` 判断登录状态:
- `loading === true`:显示“加载中...”占位。
- `!isLoggedIn`:渲染一个居中的锁屏提示:
- 图标:`🔒`
- 文案:`请先登录查看成交流数据`
- 按钮:
- `登录`(蓝底) → `/login`
- `注册`(灰边) → `/register`
只有登录用户可以看到实时成交流和图表。
### 2.3 页面主要区域布局
登录后,`TradesPage` 页面结构如下:
1. **标题 + 币种切换**
- 标题:`成交流分析`
- 副标题:`实时成交记录 + 买卖 Delta 分析`
- 右侧有一个币种选择按钮组:
- 支持四种:`BTC` / `ETH` / `XRP` / `SOL`
- 通过内部状态 `symbol` 切换,影响下方所有数据请求。
2. **实时成交 + 分析图 并排**
- 布局:`lg` 以上为两列,左侧实时成交,右侧流量分析;小屏则上下排列。
- 左侧组件:``
- 右侧组件:``
3. **读图说明 Info 卡片**
- 底部一块蓝色边框的说明区域:
- “读图方法”:解释 Delta 为正/负的含义(多方/空方占优)。
- “复盘思路”:建议用户结合 K 线大涨大跌时间点,回看前 15–30 分钟的 Delta 走势寻找前兆。
### 2.4 左侧:实时成交流列表(LiveTrades)
组件:`LiveTrades`
功能:展示选中币种的最新 20 条逐笔成交记录,实时滚动更新。
行为与布局:
- 加载逻辑:
- 使用 `authFetch("/api/trades/latest?symbol=...&limit=20")` 每 2 秒轮询一次。
- 首次加载时 `loading=true`,显示“加载中...”;
- 后续每次拉取:
- 根据返回的 `data.data` 更新本地 `trades` 列表;
- 新来的成交在顶部(最新在前),最多保留 20 条;
- 用 `agg_id` 去重,避免重复插入。
- 卡片顶部:
- 标题:`实时成交 · {symbol}/USDT`
- 右上角状态:
- 一个绿色闪烁的小圆点;
- 文案:`实时`。
- 下方说明:
- `▲ 绿 = 主动买(多方发动)`
- `▼ 红 = 主动卖(空方发动)`
- 表格内容:
- 表头:价格 / 数量 / 时间
- 每行表示一笔 agg_trade:
- 价格列:
- 用 `fmtPrice` 按数量级格式化;
- 根据 `is_buyer_maker` 渲染颜色和三角符号:
- `0` → 主动买:绿色、带 `▲`;
- `1` → 主动卖:红色、带 `▼`。
- 数量列:
- 大额数量(>= 1000)以 `K` 单位显示(如 `1.23K`);
- 不同币种有不同小数位(BTC 显示 4 位,小币种 3 位)。
- 时间列:
- 使用 `timeStr` 将 `time_ms` 格式化为北京时间 `HH:MM:SS`。
- 滚动与响应式:
- 桌面端:内部区域固定高度,启用垂直滚动(`lg:h-[420px]`)。
- 移动端:不限制高度,避免嵌套滚动影响体验,表头 sticky 仅在桌面端启用。
### 2.5 右侧:成交流量分析(FlowAnalysis)
组件:`FlowAnalysis`
功能:按时间聚合的买卖量与 Delta 分析图,帮助判断一段时间内多空力量对比。
行为与布局:
- 时间粒度切换:
- 顶部右侧有一组 interval 按钮:
- `1m`, `5m`, `15m`, `1h`
- 使用本地状态 `interval` 控制聚合粒度。
- 数据获取:
- 使用 `authFetch("/api/trades/summary?...")` 周期性拉取数据:
- 路径:`/api/trades/summary`
- 查询参数:
- `symbol`:当前币种(BTC/ETH/XRP/SOL)
- `start_ms`:根据 interval 动态计算(例如 1m 粒度时取过去 1 小时)
- `end_ms`:当前时间
- `interval`:`"1m" | "5m" | "15m" | "1h"`
- 接口返回 `data` 数组,每个元素为一个 `SummaryBar`:
- `buy_vol` / `sell_vol`:该时间段的主动买/卖量;
- `delta`:买-卖;
- `trade_count`:成交笔数;
- `vwap`:该段时间的成交量加权平均价;
- `time_ms`:该段开始时间。
- 首次加载时显示 loading 提示;
- 之后每 30 秒刷新一次数据,但不再显示 loading 动画,以避免视觉抖动。
- 上方摘要卡片:
- “统计时间窗口”:根据 interval 用人话表达:
- 1m → 过去 1 小时
- 5m → 过去 4 小时
- 15m → 过去 12 小时
- 1h → 过去 48 小时
- 四个小卡片:
1. 主动买量(绿色):总 buy_vol;
2. 主动卖量(红色):总 sell_vol;
3. Delta(买-卖):正值多头占优,负值空头占优;
4. 买方占比:
- 计算公式:`buy_vol / (buy_vol + sell_vol)`;
- 文案提示:
- >= 55%:强势买盘;
- 45–55%:买卖均衡;
- < 45%:强势卖盘。
- 中间图一:Delta + 价格双轴图
- 使用 `ComposedChart` 绘制:
- X 轴:时间(短格式,如 `HH:MM`);
- 左 Y 轴:Delta 数值;
- 右 Y 轴:价格(VWAP),带 ±0.3% 的缓冲区,自动压缩显示范围;
- 一条 `ReferenceLine` 表示 Delta = 0;
- `Area` 图展示 Delta 区域,颜色偏蓝;
- `Line` 图展示价格,右侧刻度以美元单位,并在大数值时转换成 `$xx.xk` 形式。
- Tooltip 中同时显示 Delta 和价格。
- 下方图二:主动买量 vs 主动卖量
- 再次使用 `ComposedChart`:
- X 轴:时间;
- Y 轴:成交量;
- 两个 `Area`:
- `buy`:绿色区域;
- `sell`:红色区域。
- Tooltip 展示各时间段买/卖量。
- 底部说明:
- 一行小字:`数据跨度约 X 分钟 · N 根K · 每30秒刷新`:
- `X` 为从当前时间到最早一根 bar 的跨度;
- `N` 为当前聚合出的 K 数量。
如果接口当前没有返回任何数据(例如新启动时),则展示一个“暂无数据,正在积累中”的占位说明,而不是空白图表。
### 2.6 /trades 依赖的主要 API
`/trades` 页面通过 `authFetch` 调用后端,需要登录状态。主要接口包括:
- `GET /api/trades/latest?symbol=&limit=20`
- 用于 `LiveTrades`;
- 返回最近的逐笔成交(agg_trades 快照)。
- `GET /api/trades/summary?symbol=&start_ms=&end_ms=&interval=`
- 用于 `FlowAnalysis`;
- 返回按时间粒度聚合的买卖量、Delta、VWAP 等。
接口的具体字段与实现细节以 `docs/arbitrage-engine-full-spec.md` 和 `backend/main.py` 中对应章节为准。
---
## 3. /live(⚡ 实盘交易)
文件:`frontend/app/live/page.tsx`
导出的组件名:`LiveTradingPage`
### 3.1 页面目标
`/live` 是实盘控制与风控中枢页面,主要功能:
- 全局监控:实盘账户的当前风险状态、R 预算、对账情况、系统健康;
- 快速止血:一键全平、禁新仓、恢复交易;
- 配置管理:在线调整实盘参数(每笔风险、杠杆、最大仓位数、启用策略等);
- 执行与对比:查看当前持仓、执行质量、实盘 vs 模拟盘表现差异。
整体设计成多层级面板(L0–L11),从“风险总览 → 止血按钮 → 配置 → 持仓 → 质量 → 对账 → 事件流 → 对比与历史”逐层深入。
### 3.2 登录要求与未登录展示
页面使用 `useAuth()` 进行访问控制:
- `loading === true`:显示简单的“加载中...”提示。
- `!isLoggedIn`:
- 显示锁屏提示:
- 图标:`🔒`
- 文案:`请先登录查看实盘`
- 按钮:`登录`(蓝底),跳转 `/login`
- 不提供注册入口(实盘页面假定仅对已有账号开放)。
只有登录用户可以访问 L0–L11 各层面板。
### 3.3 总体布局与层级概览
`LiveTradingPage` 登录后渲染顺序如下:
1. `L0_RiskBar`:顶部固定风险条(sticky)
2. 页面标题区:`⚡ 实盘交易` + 简短说明(V5.2 策略、币安 USDT 永续、测试网)
3. `L1_EmergencyPanel`:一键止血区(全平/禁新仓/恢复)
4. `L15_LiveConfig`:实盘配置(风险参数)
5. `L2_AccountOverview`:账户概览 8 卡片(权益、保证金、PnL、胜率等)
6. `L3_Positions`:当前持仓(实时价+风险指标)
7. `L4_ExecutionQuality`:执行质量统计
8. `L5_Reconciliation`:本地 vs 交易所对账
9. `L6_RiskStatus`:风控门槛状态
10. `L7_EventStream`:实时事件流
11. `L8_PaperComparison`:实盘 vs 模拟盘对照
12. `L9_EquityCurve`:权益曲线 + 回撤
13. `L10_TradeHistory`:历史交易表
14. `L11_SystemHealth`:系统健康(进程与数据新鲜度)
下面按层级简述关键行为和用途。
### 3.4 L0 风险条(L0_RiskBar)
功能:作为页面顶部的 sticky 风险指示条,始终可见,用于快速扫一眼当日风险与对账情况。
- 数据来源:
- 周期性轮询:
- `/api/live/risk-status`
- `/api/live/reconciliation`
- `/api/live/account`
- 每 5 秒刷新一次。
- 显示内容:
1. **交易状态**
- 彩色圆点 + 文案:
- `normal` → 绿色点 + `运行中`
- `circuit_break` → 红点 + `熔断` 提示(有表情符号)
- `warning` → 黄点 + `警告`
- 其它 → 灰色 + `未知`
- 标记:
- `禁新仓`:如果 `risk.block_new_entries` 为真;
- `只减仓`:如果 `risk.reduce_only` 为真。
2. **R 预算**
- 已实现 R:`today_realized_r`(正绿负红);
- 未实现 R:`today_unrealized_r`;
- 日限对比:`totalR = realized + min(unrealized, 0)`,显示为 `totalR/-5R`:
- 根据占用比例着色:<80% 绿,80–100% 黄,>=100% 红。
3. **对账与连亏**
- 对账状态:从 `/api/live/reconciliation` 的 `status` 推导:
- ok → 绿色小点 + `对账✓`
- 其它 → 红色小点 + `对账✗(差异条数)`
- 连续亏损次数:`risk.consecutive_losses`;
- 如果存在 `risk.circuit_break_reason`,在右侧以小字体显示熔断原因。
### 3.5 L1 一键止血区(L1_EmergencyPanel)
功能:提供三种紧急操作:
- `🔴 全平`:调用 `POST /api/live/emergency-close`;
- `🟡 禁新仓`:调用 `POST /api/live/block-new`;
- `✅ 恢复`:调用 `POST /api/live/resume`。
交互特点:
- 对危险操作(全平/禁新仓)增加二次确认:
- 首次点击显示“确认?” + 确认/取消按钮;
- 确认后才真正发起请求。
- 操作结果通过顶端一行小字提醒:成功/失败提示文本会显示数秒后自动消失。
使用场景:实盘出现异常时,快速全平或冻结新仓入口,降低风险暴露时间。
### 3.6 L1.5 实盘配置面板(L15_LiveConfig)
功能:展示并编辑实盘关键配置,用于调整风险参数与交易环境。
- 数据来源:
- 初始化时调用 `GET /api/live/config` 获取配置对象;
- 保存时调用 `PUT /api/live/config`,之后再 `GET` 一次以刷新展示。
- 配置项顺序(configOrder):
- `risk_per_trade_usd`:每笔风险金额(USDT),决定 1R 对应的资金;
- `initial_capital`:初始资金;
- `risk_pct`:每笔风险占比(%);
- `max_positions`:最大持仓数;
- `leverage`:杠杆倍数;
- `enabled_strategies`:启用的策略列表;
- `trade_env`:交易环境(正式/测试网等)。
- 展示形式:
- 标题:`⚙️ 实盘配置`,旁边强调 `1R = $X.XX`(从 `risk_per_trade_usd` 推导)。
- 每个配置项显示图标 + label + 当前值:
- windown 模式:显示只读值,如 `5%`、`10x`;
- 编辑模式:变成文本输入框。
- 编辑流程:
1. 点击“编辑”按钮 → 进入编辑模式,当前配置复制到 `draft`;
2. 修改各字段;
3. 点击“保存”:
- 发 `PUT /api/live/config`,体是 `draft`;
- 成功后重新拉配置并退出编辑模式;
4. 点击“取消” → 撤销编辑,恢复显示模式。
该面板是实盘风险参数的唯一修改入口,页面其他部分(仓位 R 计算等)会引用这里的 `risk_per_trade_usd`。
### 3.7 L2 账户概览(L2_AccountOverview)
功能:用 8 个小卡片概览账户与策略表现:
- 数据来源:
- `GET /api/live/account`:账户层面数据;
- `GET /api/live/summary?strategy=v52_8signals`:指定策略的汇总表现。
- 卡片内容示例:
1. 账户权益:`equity`(USDT)
2. 可用保证金:`available_margin`
3. 已用保证金:`used_margin`
4. 有效杠杆:`effective_leverage`(超过 10x 时高亮为红色)
5. 今日净 PnL:`today_realized_r` + 对应 USDT 金额(正绿负红)
6. 总净 PnL:`total_pnl_r` + `total_pnl_usdt`
7. 成本占比:费用 + 资金费率成本(`total_fee_usdt + total_funding_usdt`)
8. 胜率/PF:`win_rate` 和 `profit_factor`
这些卡片给出“当前实盘表现是否健康”的快速量化视图。
### 3.8 L3 当前持仓(L3_Positions)
功能:实时展示实盘持仓详情,包括价格、TP/SL、风险、执行质量等。
- 数据来源:
- 周期性轮询:
- `GET /api/live/positions?strategy=v52_8signals`:当前实盘持仓列表;
- `GET /api/live/reconciliation`:用于计算清算价与距离;
- `GET /api/live/config`:获取 `risk_per_trade_usd`。
- WebSocket 实时价格:
- 连接 `wss://fstream.binance.com/stream?streams=btcusdt@aggTrade/...`;
- 实时更新 `wsPrices[symbol]` 作为当前价。
- 每个持仓块显示信息包括:
- 头行:
- 标题:`🟢/🔴 {symbol} {LONG/SHORT}`(方向 + 币种),颜色区分多空;
- 评分与仓位档位:`评分 score · 加仓/标准`;
- 清算距离 badge:
- 从对账数据里计算 mark price 到 liquidation price 的距离百分比;
- 不同区间用不同颜色强调(例如 <8% 深色、8–12% 红色、12–20% 橙色、>20% 绿色)。
- 实时浮盈:
- 以 R 表示:`unrealR`(考虑 TP1 是否已触发,用全程 R 和 TP1 R 的组合);
- 以 USDT 表示:`unrealUsdt = unrealR * riskUsd`。
- 持仓时长:`holdMin` 分钟,超过 45/60 分钟用不同颜色提示。
- 价格行:
- 入场价、实际成交价、当前价(websocket/备选 current_price)、TP1/TP2/SL;
- TP1 打到时在 TP1 旁边标记 `✅`。
- 执行指标行:
- 滑点(bps);
- “裸奔时间”(保护下单前裸暴露时长);
- 信号→下单延迟(S→O)、下单→成交延迟(O→F);
- 交易所订单 ID。
- 根据阈值用红/黄/绿背景表达是否超出合理范围。
如果当前没有持仓,则显示一条“暂无活跃持仓”的提示卡片。
### 3.9 L4–L11 其他面板简述
1. **L4 执行质量(L4_ExecutionQuality)**
- 数据源:`GET /api/live/execution-quality`;
- 展示整体统计和按币种统计:
- 滑点、信号→下单延迟、下单→成交延迟、裸奔时间;
- 每项有 avg / P50 / P95 三个分位数;
- 根据 P95 与阈值比较决定颜色(绿/黄/红)。
2. **L5 对账面板(L5_Reconciliation)**
- 数据源:`GET /api/live/reconciliation`;
- 显示:
- 本地持仓列表 vs 交易所持仓列表;
- 挂单数量对比;
- 差异列表 `diffs`,按严重程度着色(critical 用红色,警告用橙色)。
3. **L6 风控状态(L6_RiskStatus)**
- 数据源:`GET /api/live/risk-status`;
- 将风控规则用几条检查项呈现:
- 单日亏损是否大于 -5R;
- 连续亏损是否小于 5 次;
- API 是否正常;
- 如存在 `circuit_break_reason` 和 `auto_resume_time`,以红色块形式显示熔断原因和预计恢复时间。
4. **L7 实时事件流(L7_EventStream)**
- 数据源:`GET /api/live/events?limit=30&level=...`(每 5 秒刷新);
- 支持按级别过滤:全部/严重/警告/信息;
- 每条事件包含:
- 时间(日期 + 时分秒);
- category(trade/risk/system/reconciliation 等);
- symbol(如 BTC/ETH);
- message 文本;
- 使用不同颜色和图标表示级别(info/warn/error/critical)。
5. **L8 实盘 vs 模拟盘(L8_PaperComparison)**
- 数据源:`GET /api/live/paper-comparison?limit=20`;
- 表格比较每笔实盘 vs 对应模拟盘交易:
- 入场价差(bps)、PnL 差异(R)等;
- 表头包括币种、方向、实盘/模拟入场、价差、PnL、R 差;
- 标题中显示平均 R 差。
6. **L9 权益曲线 + 回撤(L9_EquityCurve)**
- 数据源:`GET /api/live/equity-curve?strategy=v52_8signals`;
- 绘制以 R 为单位的累计 PnL 曲线,以及对应回撤曲线:
- 计算峰值与当前差值作为回撤;
- 以两条 Area 图显示(绿色累计 PnL、红色回撤)。
7. **L10 历史交易(L10_TradeHistory)**
- 数据源:`GET /api/live/trades?symbol=&result=&strategy=&limit=50`;
- 支持币种(全部/BTC/ETH/XRP/SOL)和结果(全部/盈/亏)筛选;
- 表格字段:
- 币种、方向、入场/出场价;
- Gross R、Fee R、FR R(资金费率)、Slip R;
- Net R(总盈亏);
- 状态(止盈/止损/保本/其他);
- 持仓时长(分钟)。
8. **L11 系统健康(L11_SystemHealth)**
- 数据源:`GET /api/live/health`;
- 展示:
- 各进程状态(online/offline、内存占用、重启次数等);
- 行情数据新鲜度(最近一次数据更新时间与状态)。
整体上,`/live` 将实盘运行过程中所有关键视角集中在一个页面里:
从风险和止血,到配置与持仓,再到执行质量、对账、事件和系统健康,方便在出现问题时快速定位和处理。
---
## 4. /strategy-plaza(策略广场)
主页面文件:`frontend/app/strategy-plaza/page.tsx`
废弃策略页面:`frontend/app/strategy-plaza/deprecated/page.tsx`
### 4.1 页面目标
`/strategy-plaza` 是 V5.4 策略工厂的“策略广场”,面向策略研究者,用来:
- 一眼看到当前所有策略的运行状态与收益表现;
- 对比不同策略(币种、CVD 周期、TP/SL 方案)的表现好坏;
- 快速进入单策略详情页(查看信号引擎 + 模拟盘全貌);
- 对策略进行管理:调整参数、追加余额、废弃/恢复。
从用户视角,它更像是一个“策略排行榜 + 控制台”,而不是直接操作信号详情的页面。
### 4.2 登录与加载行为
`StrategyPlazaPage` 顶部调用 `useAuth()`,用于确保身份信息已经加载(具体权限控制由后端决定)。
- 加载数据:
- 使用 `authFetch("/api/strategies")` 获取所有策略;
- 响应中取 `data.strategies` 填充本地 `strategies` 列表;
- 首次加载时显示“加载中...”;
- 之后每 30 秒自动刷新一次数据(定时调用 `fetchData`)。
这里的 `/api/strategies` 会返回当前所有策略实例(包括运行中和暂停中的,废弃策略则在 deprecated 页通过 `include_deprecated=true` 过滤)。
### 4.3 主页面结构(/strategy-plaza)
页面由三部分组成:
1. 顶部 Header
2. 策略卡片网格
3. 追加余额弹窗
#### 4.3.1 Header
- 标题区:
- 标题:`策略广场`
- 副标题:`点击策略名查看信号引擎和模拟盘详情`(提示点击行为会进入 `/strategy-plaza/[id]` 类页面)
- 右侧工具区:
- 最近更新时间:
- 一个绿色小圆点 + “HH:MM:SS” 本地时间,用 `lastUpdated` 来表示最近一次成功拉取 `/api/strategies` 的时间;
- “新增策略”按钮:
- 蓝色按钮,文案 `新增策略`;
- 点击跳转到 `/strategy-plaza/create`,进入新建策略表单。
#### 4.3.2 策略卡片网格
- 使用 `StrategyCardComponent` 渲染每个 `StrategyCard`(从 `/api/strategies` 得到的数据结构);
- 网格布局:
- 小屏:单列;
- 中屏:两列;
- 大屏:三列。
**每张卡片内容:**
1. **Header 行**
- 左侧:
- 策略名:`display_name`,点击标题会跳转到 `/strategy-plaza/{strategy_id}`(单策略详情页,展示信号+paper 详情);
- 状态徽章 `StatusBadge`:
- `running` → 绿色 “运行中”;
- `paused` → 橙色 “已暂停”;
- 其它 → 红色 “异常”;
- 币种标签:例如 `BTC` / `ETH`,从 `symbol.replace("USDT","")` 抽取。
- 右侧:
- 启动时长:`formatDuration(started_at)`,以“x天 x小时 / x小时 x分 / x分钟”形式显示策略持续运行时间。
2. **主要收益与余额**
- 左侧:
- 标题:`当前余额`;
- 数值:`current_balance`(USDT),大号字体。
- 右侧:
- 标题:`累计盈亏`;
- 数值:`net_usdt`:
- 正数加 `+` 号,并用绿色;
- 负数用红色。
3. **余额进度条**
- 显示当前余额相对于初始资金的百分比:
- `balancePct = current_balance / initial_balance * 100%`;
- 文字显示 `balancePct%` 和 `initial_balance`;
- 下方进度条宽度按百分比缩放,颜色随盈亏变动:
- 盈利 → 绿色;
- 亏损 → 红色。
4. **关键统计行**
- 三个小卡片:
1. 胜率:`win_rate%`,>50% 绿色,45–50% 橙色,<45% 红色;
2. 净 R:`net_r`,正值绿色、负值红色;
3. 交易数:`trade_count`。
5. **平均赢/亏**
- 左:绿色背景的“平均赢”,显示 `+avg_win_r R`;
- 右:红色背景的“平均亏”,显示 `avg_loss_r R`;
- 进一步帮助判断盈亏比是否合理。
6. **Footer 行:24 小时表现 + 持仓状态**
- 左侧:
- 24 小时 PnL:
- 图标 `TrendingUp` 或 `TrendingDown`;
- 文案:`24h +X U` 或 `24h -X U`,根据 `pnl_usdt_24h` 的正负着色(绿/红)。
- 右侧:
- 如果 `open_positions > 0`:
- 显示 `{open_positions} 仓持仓中`,着橙色强调;
- 否则:
- 显示最近一次交易时间:`上次: formatTime(last_trade_at)`(格式为 `MM-DD HH:mm`)。
7. **操作按钮行**
- 三个按钮,从左到右:
1. `调整参数`:
- 链接到 `/strategy-plaza/{strategy_id}/edit`;
- 进入策略编辑表单(修改权重、窗口、TP/SL 等配置)。
2. `追加余额`:
- 打开 `AddBalanceModal`;
- 输入追加金额(USDT),调用 `/api/strategies/{id}/add-balance`,更新初始资金与当前余额。
3. 红色垃圾桶按钮:
- 点击后调用 `onDeprecate`,触发废弃流程。
#### 4.3.3 底部空状态与追加余额弹窗
- 当 `strategies.length === 0`:
- 显示“暂无运行中的策略”提示;
- 提供 “创建第一个策略” 按钮,跳转 `/strategy-plaza/create`。
- `AddBalanceModal`:
- 显示当前选中策略名与输入框;
- 校验金额 > 0;
- 提交时调用 `POST /api/strategies/{sid}/add-balance`;
- 成功后关闭弹窗并重新拉取策略列表。
### 4.4 废弃策略页(/strategy-plaza/deprecated)
文件:`frontend/app/strategy-plaza/deprecated/page.tsx`
导出的组件名:`DeprecatedStrategiesPage`
功能:展示所有 `status="deprecated"` 的策略,并允许“重新启用”。
- 数据加载:
- 调用 `GET /api/strategies?include_deprecated=true`;
- 前端在得到的 `strategies` 中筛选 `status === "deprecated"`。
- 页面结构:
1. Header:
- 标题:`废弃策略`;
- 副标题:`数据永久保留,可随时重新启用`;
- 右侧链接:`← 返回策略广场`,跳转 `/strategy-plaza`。
2. 如果没有废弃策略:
- 显示“暂无废弃策略”。
3. 否则:
- 使用网格展示每个废弃策略卡片(布局类似主广场,但视觉上更淡一些)。
- 废弃策略卡片要点:
- Header:
- 策略名;
- “已废弃”灰色徽章;
- 右侧显示币种简称。
- PnL 与余额:
- 展示“废弃时余额”和累计盈亏;
- 余额进度条同样显示当前余额与初始资金的比例(但整体卡片透明度略低,以示已停用)。
- 统计卡片:
- 胜率、净 R、交易数。
- Footer:
- 左侧:最近废弃时间 `废弃于 {deprecated_at}`;
- 右侧:`重新启用` 按钮:
- 点击前二次确认:“确认重新启用策略,将继续使用原有余额和历史数据。”;
- 调用 `POST /api/strategies/{sid}/restore`;
- 成功后刷新列表。
### 4.5 主要依赖的 API
`/strategy-plaza` 和 `/strategy-plaza/deprecated` 主要依赖以下后端接口:
- `GET /api/strategies`
- 返回所有非废弃策略;
- 前端使用:策略广场卡片列表;
- 数据中包含策略 ID、展示名、币种、状态、余额、PnL、胜率、平均盈亏、近 24 小时表现等。
- `GET /api/strategies?include_deprecated=true`
- 返回包括废弃策略在内的完整列表;
- 前端从中筛出 `status="deprecated"` 用于“废弃策略”页面。
- `POST /api/strategies/{sid}/deprecate`
- 废弃策略:将 `status` 设为 `deprecated`,停止策略运行但保留数据;
- 前端在废弃前弹出确认对话框。
- `POST /api/strategies/{sid}/restore`
- 恢复废弃策略为运行状态;
- 保持原有余额和历史记录。
- `POST /api/strategies/{sid}/add-balance`
- 向指定策略追加模拟资金;
- 影响 `initial_balance` 和 `current_balance`,并在 card 上体现。
单个策略的详细行为(信号引擎配置、模拟盘表现)由 `/strategy-plaza/[id]` 下的页面承载,这里作为入口不展开细节;实现上这部分是 V5.4 Strategy Factory 的前端展示层。
---
## 5. /server(服务器监控)
文件:`frontend/app/server/page.tsx`
导出的组件名:`ServerPage`
### 5.1 页面目标
`/server` 页面用来监控部署 Arbitrage Engine 的服务器与关键进程状态,帮助你:
- 了解 CPU / 内存 / 硬盘 / 网络使用情况;
- 看到 PM2 管理的各个进程是否正常(arb-web / arb-api / signal-engine / collectors 等);
- 观察 PostgreSQL 数据库的体量和各 symbol 数据覆盖范围;
- 了解回补任务是否在运行。
它的目标是提供运维层的**健康检查面板**,方便在出现延迟、缺数据或者服务挂掉时快速判断是资源问题还是进程问题。
### 5.2 登录要求与数据刷新
- 使用 `useAuth()` 判断登录状态:
- 未登录:显示提示“请先登录查看服务器状态”,并给出 `登录` / `注册` 按钮;
- 已登录:开始加载 `/api/server/status`。
- 刷新策略:
- 初次加载时调用 `fetchData()`;
- 之后每 10 秒自动轮询一次;
- `loading` 为真时显示“加载中...”;如果请求失败则显示“获取失败”。
接口返回的数据结构在前端定义为 `ServerStatus`,包含 CPU/内存/磁盘/负载/网络/PM2 列表/Postgres 信息/回补标志等。
### 5.3 页面布局概览
登录且成功获取数据后,布局为:
1. 顶部标题行;
2. 系统概览四张卡片(CPU / 内存 / 硬盘 / 系统);
3. PM2 进程表格;
4. PostgreSQL 概览与数据覆盖范围;
5. 底部说明提示。
### 5.4 顶部标题行
- 标题:`服务器监控`;
- 副标题:`GCP asia-northeast1-b · 每10秒自动刷新`(标明部署区域和刷新频率);
- 右侧状态标记:
- 当 `data.backfill_running === true` 时,显示:
- 蓝色小圆点 + 文案 `回补运行中`;
- 提示当前 CPU/网络负载偏高可能是正常的回补行为。
### 5.5 系统概览四卡片
使用一个 2x2 或 4 列的网格展示四个方面:
1. **CPU**
- 显示:
- 核数:`data.cpu.cores`;
- 当前使用率:`data.cpu.percent%`;
- 下方以 `ProgressBar` 表示 CPU 利用率,>70% 黄色,>90% 红色;
- 一行 load 信息:`load1 / load5 / load15`。
2. **内存**
- 显示:
- 占用:`used_gb / total_gb`;
- 当前使用率百分比;
- `ProgressBar` 显示利用率;
- 如果 `swap_percent > 0`,额外显示 Swap 使用率,以橙色提示。
3. **硬盘**
- 显示:
- 可用空间:`free_gb`;
- 使用率百分比 + `ProgressBar`;
- 已用/总容量:`used_gb / total_gb`。
4. **系统运行时间与网络**
- 显示:
- 运行时间:`uptime_hours`(小时),超过 24 小时时会用“X天”的形式;
- 网络:
- 上行总量:`bytes_sent_gb`;
- 下行总量:`bytes_recv_gb`。
### 5.6 PM2 进程表格
功能:查看每个 PM2 管理的进程状态,确认关键服务是否在线。
- 数据来源:`data.pm2` 数组,每个元素 `PM2Proc` 包含:
- `name`:进程名(例如 arb-web/arb-api/signal-engine 等);
- `status`:`online` 或其他;
- `cpu`:CPU 使用率;
- `memory_mb`:内存使用 MB;
- `restarts`:重启次数;
- `uptime_ms`:运行时长。
- 表格列:
- 名称(等宽字体显示);
- 状态:
- 使用圆点 + badge 样式:
- `online` → 绿色背景圆角标;
- 其他状态 → 红色背景圆角标;
- CPU 百分比;
- 内存 MB;
- 重启次数;
- 运行时间:通过 `uptimeStr` 格式化为 `Xd Yh` 或 `Xh Ym`。
这部分是判断“某个服务是不是挂了 / 频繁重启”的第一视角。
### 5.7 PostgreSQL 概览
功能:监控数据库大小、关键表数据量以及各交易对的历史数据覆盖范围。
数据来自 `data.postgres`:
- 上半部分卡片:
1. 数据库大小:
- `db_size_mb`,> 1024 MB 时以 GB 显示;
2. `agg_trades` 行数:
- `agg_trades_count`,以千分位格式化(如 89,000,000);
3. `rate_snapshots` 行数:
- `rate_snapshots_count`;
4. 回补状态:
- 使用 `data.backfill_running` 显示 “运行中” 或 “已停止”,并用颜色区分。
- 下半部分数据覆盖范围:
- `data.postgres.symbols` 是一个记录,键为 symbol(如 BTCUSDT/ETHUSDT 等),值包含:
- `earliest_ms`:最早一条数据的时间戳;
- `latest_ms`:最新一条数据时间戳;
- `span_hours`:时间跨度(小时)。
- 对每个 symbol,展示:
- 左侧:symbol 名,等宽字体;
- 右侧:时间范围:
- `earliest_ms` → `latest_ms`,使用 `bjtStr` 转换为北京时间(简短日期+时间);
- 下一行显示 `span_hours`,如果 >24 小时,则用“X.X 天”,否则“X.X 小时”。
这部分帮助确认“数据从什么时候开始积累、到什么时候为止、是否有断档”。
### 5.8 底部说明
最后是一个蓝色 Info 卡片,说明:
- 数据每 10 秒自动刷新;
- PM2 进程状态实时反映服务运行情况;
- 回补运行中时 CPU 和网络负载偏高属于正常现象,不一定是异常。
### 5.9 依赖的主要 API
`/server` 页面只依赖一个后端接口:
- `GET /api/server/status`
- 返回 `ServerStatus` 结构;
- 包含:
- CPU/内存/磁盘/负载信息;
- uptime 和网络流量;
- PM2 进程列表;
- Postgres 概览(整体大小、表行数、各 symbol 的数据覆盖范围);
- 回补任务状态标记。
具体字段定义与计算方式以 `docs/arbitrage-engine-full-spec.md` 和 `backend/main.py` 中对应接口描述为准。
---
## 6. /about(策略说明与风险)
文件:`frontend/app/about/page.tsx`
导出的组件名:`AboutPage`
### 6.1 页面目标
`/about` 页面是一个纯信息页,用来向用户解释:
- 资金费率套利策略的基本原理(现货多 + 永续空,对冲方向风险,收资金费率);
- 历史年化收益数据(基于长期统计的 BTC/ETH/组合毛年化和净年化);
- 策略的主要风险点及其等级。
这个页面不依赖登录状态、不调用任何 API,主要用于教育和风险披露。
### 6.2 页面结构
页面宽度限制在 `max-w-3xl`,内容自上而下分为三块:
1. 标题区;
2. 策略原理说明;
3. 历史年化数据;
4. 风险说明。
#### 6.2.1 标题区
- 主标题:`策略说明`
- 副标题:`资金费率套利原理与历史数据`
用于告诉用户:本页不是实时数据,而是解释策略设计与历史表现。
#### 6.2.2 策略原理卡片
第一块白底卡片标题:`策略原理`。
内容用通俗文字说明永续合约资金费率机制和套利思路:
- 永续合约每 8 小时结算一次资金费率;
- 多头多时,资金费率为正,多头付钱给空头;
- 空头多时,资金费率为负,空头付钱给多头。
套利做法用一段高亮文字说明:
- “套利做法:现货买入 + 永续做空,完全对冲币价风险,净收资金费率(USDT 结算)。”
下面有一个小示例框(等宽字体):
- 买入 1 BTC 现货(例如 96,000 美元);
- 做空 1 BTC 永续(同样 96,000 美元,1 倍杠杆);
- 分隔线;
- 结论:
- `BTC 涨跌:两边对冲,净盈亏 = 0`;
- `资金费率:每 8 小时直接收 USDT`。
这个例子帮助用户在不看数学公式的情况下理解“赚费率、不赌方向”的本质。
#### 6.2.3 历史年化数据卡片
第二块白底卡片标题:
`历史年化数据(2019-2026,露露×小周15轮验证)`
内容是一个简单表格,列出:
- 资产:BTC / ETH / 50/50 组合;
- 全周期毛年化;
- PM 净年化(考虑 Portfolio Margin 下的资金利用率和费用);
- 负费率占比(BTC/ETH)。
表格中的示例数值(固定写死在前端):
- BTC:
- 全周期毛年化:12.33%;
- PM 净年化:11.67%;
- 负费率占比:13.07%。
- ETH:
- 全周期毛年化:14.87%;
- PM 净年化:14.09%;
- 负费率占比:12.17%。
- 50/50 组合:
- 全周期毛年化:13.81%;
- PM 净年化:13.08%;
- 负费率占比:`—`(组合没有单独统计)。
表格下面有一行小字说明:
- `PM = Portfolio Margin 模式,资金利用率约 95%。数据来源:Binance fapi/v1/fundingRate 官方 API`
这块内容用于给出“如果长期做这个套利,大致收益区间在哪”的历史参考,但没有和当前系统直接联动。
#### 6.2.4 风险说明卡片
第三块白底卡片标题:`风险说明`。
以列表形式列出若干风险点,每一行包括:
- 风险等级:例如 `🟡 中` 或 `🟢 低`;
- 风险类型:如“市场周期”、“费率持续为负”、“交易所对手方”、“爆仓风险”、“基差波动”等;
- 简短说明文本。
示例风险点:
- 市场周期(中):熊市年化可降至 0–4%,但本金不亏;
- 费率持续为负(低):历史负费率占比仅 12–13%,长期均值为正;
- 交易所对手方(中):有交易所倒闭风险(FTX 教训),建议资金分散;
- 爆仓风险(低):1 倍杠杆 + 对冲,理论需要 BTC 翻倍才触发爆仓;
- 基差波动(低):长期持有不影响盈亏,只影响平仓时机。
整块卡片通过背景色和图标表达“这是一份认真写过的风险披露”,帮助用户建立合理预期。
### 6.3 依赖的 API 与状态
`/about` 页面完全静态:
- 不依赖任何远端 API;
- 不区分登录/未登录展示;
- 所有数据都写死在前端代码中(作为文案与示例数值)。
因此,它更像是项目内置的“策略白皮书摘要”,是用户理解系统的背景材料,也可以为将来的 AI 提供策略语义上的上下文。
---
## 7. 账号相关页面(/login /register /dashboard)
相关文件:
- 登录:`frontend/app/login/page.tsx`(`LoginPage`)
- 注册:`frontend/app/register/page.tsx`(`RegisterPage`)
- 我的账户:`frontend/app/dashboard/page.tsx`(`DashboardPage`)
### 7.1 /login(登录页)
目标:为已有账号提供登录入口,获取 JWT 后进入系统。
- 表单字段:
- 邮箱(必填,type=email);
- 密码(必填,type=password)。
- 提交逻辑:
- 使用 `useAuth().login(email, password)` 调用后端登录接口;
- 成功后 `router.push("/")` 返回首页;
- 失败时在表单下方显示错误信息文本(`err.message` 或 “登录失败”)。
- 布局/交互:
- 全屏居中白卡片,标题为 `⚡ Arbitrage Engine` + “登录您的账户”;
- 提交按钮文案:
- 未提交:`登录`;
- 提交中:`登录中...`,按钮禁用且透明度降低;
- 卡片底部有引导文案:
- `没有账户? 注册` → 点击跳转 `/register`。
### 7.2 /register(注册页)
目标:在邀请码机制下创建新账户。
- 表单字段:
- 邀请码(必填,字符串,自动转换为大写);
- 邮箱(必填,type=email);
- 密码(必填,type=password,至少 6 位)。
- 提交逻辑:
- 提交前本地校验密码长度:
- 如果 `< 6`,直接显示 “密码至少6位”,不发送请求;
- 调用 `useAuth().register(email, password, inviteCode)`;
- 成功后重定向到首页 `/`;
- 失败时在表单下显示错误信息(`err.message` 或 “注册失败”)。
- 布局/交互:
- 布局与登录页相似,标题同样是 `⚡ Arbitrage Engine`;
- 副标题提示:`注册新账户(需要邀请码)`;
- 提交按钮文案:
- 未提交:`注册`;
- 提交中:`注册中...`;
- 卡片底部提供:
- `已有账户? 登录` 链接回 `/login`。
### 7.3 /dashboard(我的账户)
目标:展示当前登录用户的账号信息、推送设置与订阅等级,并提供登出入口。
- 访问控制:
- 使用 `useAuth()`:
- 如果 `loading` 还未结束,暂时显示“加载中...”;
- 如果 `!isLoggedIn`,直接 `router.push("/login")`;
- 数据加载:
- 使用 `authFetch("/api/auth/me")` 获取当前用户信息;
- 如果请求失败,回退到 `/login`。
- 用户信息结构(前端视角):
- `id`:用户 ID;
- `email`:邮箱;
- `discord_id`:绑定的 Discord 用户 ID(可空);
- `subscription`:
- `tier`:订阅等级("free" / "pro" / "premium" 等);
- `expires_at`:到期时间(可空,空则视为“永久免费”)。
- 页面结构:
1. 顶部标题与登出按钮
- 标题:`我的账户`;
- 右侧:`退出` 按钮,调用 `logout()`。
2. 账户信息卡片
- 展示:
- 邮箱;
- 订阅等级:
- 使用 `tierLabel` 将内部值映射为 “免费版” / “Pro” / “Premium”;
- 未识别的 tier 值直接原样显示;
- 到期时间:
- 有值时转为本地日期显示;
- 无值时显示“永久免费”。
3. Discord 信号推送卡片
- 说明:绑定 Discord ID 后,当套利信号触发时会自动 @ 用户;
- 输入框:
- 绑定的 Discord 用户 ID(18 位数字),初始值为后端返回的 `discord_id`;
- “绑定”按钮:
- 点击调用 `POST /api/user/bind-discord`:
- body:`{ discord_id }`;
- 提交中按钮禁用,文本为 “保存中...”;
- 完成后:
- 成功:显示 “绑定成功”(绿字),并更新本地 user 对象;
- 失败:显示错误提示(红字);
- 下方有一条小字说明如何在 Discord 客户端中获取用户 ID(开启开发者模式后右键复制)。
4. 升级订阅卡片
- 展示三个订阅档位的静态信息:
- Free:`¥0`,功能如“实时费率面板”;
- Pro:`¥99/月`,功能如“实时费率面板 + 信号 Discord 推送 + 历史数据”;
- Premium:`¥299/月`,功能如“Pro 全部功能 + 定制阈值 + 优先客服”。
- 当前 tier 对应的卡片会用高亮边框显示;
- 对于非当前档位且不为 Free 的卡片,会展示一个 `升级(即将开放)` 的占位按钮(目前仅为 UI 提示,不实际发请求)。
整体上,`/dashboard` 是一个账号控制面板,主要用于查看订阅信息、管理 Discord 推送绑定、执行登出操作。