# 设计规范(面板 = Magpie「用量」页的 1:1 复刻) > 这份文件是**实现契约**。子代理按它实现,Lead 按它验收。 > 任何与 Magpie 实际行为冲突的地方,以 `docs/MAGPIE-SPEC.md`(从它二进制里挖出来的真实算法)为准。 ## 0. 一句话目标 **扫一眼就知道:我现在用的是哪个套餐、还剩多少、什么时候用完、哪个账号出了问题。** 不追求好看,追求**密度、层级、诚实**——数字必须能被 Magpie 自己的页面验证。 ## 1. 信息层级(四层,从外到内) ``` 概览条 → 周期切换 / 汇总金额 / 调用数 / 刷新 状态条 → 偏低 N · 读取失败 N · 数据较旧 N(只在非零时出现) Provider 卡 → 一个 provider 一张卡(不是一账号一张卡) ├─ 卡头:图标 · 名称 · 账号数/套餐 · 「当前」徽标 ├─ 主账号(full):窗口条 + meta + 走势 + 脚注 ├─ 其余账号(brief):一行「● 账号名 · 窗口 剩余%」 └─ 展开/收起:「展开其余 N 个账号」↔「收起其余账号」 ``` ## 2. 卡解剖(唯一允许的结构) | 区域 | 内容 | 规则 | |---|---|---| | 卡头 | 22px 图标 + 名称(15/600)+ 账号数(12/caption)+ 套餐(12/caption,单账号时)+ 「当前」徽标 | 图标缺失回退品牌色字母块;「当前」**只出现一次** | | 主账号行 | 圆点 + 账号名 + 套餐 + 「当前」 | 多账号时显示;单账号时省略 | | 窗口块 | 标签 + 数值(15/600/tabular)+ 8px 进度条 + 一行 meta | 多窗口默认只显示**最紧张的 2 个** + 「展开其余 N 个窗口」 | | meta 行 | `重置于 … · N 小时后 · 配速 ±N% · 整窗 ≈ X tokens · ≈ ¥M` | **单行**,超长才折行;分隔符统一 ` · ` | | 走势 | 「剩余额度走势」+「按此速度,预计 X 用完」+ 跨度;40px 折线 + 预测虚线;轴左首点日期、右「现在」 | 无历史则不渲染整块,不留空白 | | 脚注 | `● 最紧张窗口 剩余%`(语义色圆点)+ `刚刚更新 / N 分钟前更新` | 右对齐 | ## 3. 状态(不能只靠颜色) | 状态 | 判定 | 视觉 | |---|---|---| | 正常 | 剩余 > 50% | 进度条 success 色 | | 偏低 | 剩余 ≤ 50% | 进度条 warn 色 + 数值后 `!` | | 耗尽 | 剩余 ≤ 20% | 进度条 error 色 + `!` | | 读取失败 | `status=error` | 灰色卡 + `!` + 错误原文(截断) | | 数据较旧 | `status=stale` | 数值降透明度 + 「数据较旧」徽标 | | 未接入 | `shape=none` | 「未接入」,不画空进度条 | ## 4. 排版(只有三档,禁止第四档) | 档 | 用途 | 值 | |---|---|---| | 主数值 | 剩余% / 余额 / 汇总金额 | 15–16px / 600 / `tabular-nums` / `label-primary` | | 正文 | 窗口标签、账号名、meta | 13px / 400 / `label-secondary` | | 注释 | 账号数、套餐、脚注时间、轴标签 | 11–12px / `label-caption` | 间距:卡内 padding `14/16`,块间 `10–12`,卡间 `12`;圆角 `--dsw-radius-lg`。 颜色:**只用 `--dsw-*` 令牌**;语义色只出现在进度条、圆点、`!` 徽标上。 ## 5. 交互 - **展开/收起**:账号(brief ↔ full)、窗口(前 2 个 ↔ 全部)。状态在会话内保持,不持久化。 - **已用 / 剩余**:分段控件,切换进度条与数值口径。 - **周期**:今天 / 7 天 / 30 天 / 全部,只影响「汇总与调用数」,不影响额度卡。 - **刷新**:手动触发;自动轮询按设置(默认 30s),页面不可见时暂停。 - **承载位**:同一份 `Overview` 在 dock / orb 两种容器里复用,不得各自实现一套。(底边栏已废弃:用户 2026-10-31 决定去掉。) ## 6. 诚实原则(硬约束) 1. Magpie 没暴露的,**不编**:不显示「配速」「过期日」这类它自己算的派生值——除非 `MAGPIE-SPEC.md` 给出了它的确切公式,那就按公式算,并注明口径。 2. `holds.tokens` / `holds.cost` 是**后端按 `routed×100/used` 算好的整窗估算**(见 MAGPIE-SPEC §2),标签写「整窗」;`holds.cost` 单位是 USD,必须按 `~/.cache/magpie/fxrate.json` 换算后再显示 ¥。 3. 每个数字都要能追到 Magpie 的原始字段;`npm run audit` 必须全绿。 4. 不确定的一律标「未确认」,不猜。 ## 7. 验收标准(Lead 逐条检查) 1. `node scripts/check-client.mjs` → `CHECK OK`,4 个槽位注册。 2. `npm test` 全绿;`npm run audit` 84+ 项全过。 3. 截图(900×760,明/暗):一屏 ≥2 张完整卡;WorkBuddy 一张卡内可见 1 full + N brief。 4. 「当前」徽标全屏只出现一次。 5. 关闭任一 prefs(bars/reset/usage/today/balance)后对应元素消失。 6. 图标:有原生图标的 provider 显示真图标,其余显示品牌色字母块;不得出现破图。 7. 「配速」「整窗」必须与 MAGPIE-SPEC 的公式一致(配速带真减号 U+2212;整窗金额按 fx 换算为 ¥)。未取证的字段(如 vendor 侧 runsOutAt)不得冒充。 ## 8. 面板拖动(浮层可移动) 点开后的面板(dock / orb 共用同一个 `SurfacePopover`)支持**拖动移动**: - **默认位置**:dock 面板水平**居中**于视口;orb 面板贴近悬浮球。不要贴着触发 chip 靠右。 - **拖动手柄**:面板头部整条(`.mq-panel-head`)。按下时排除 `button / a / input / select / textarea / [role="tab"]`,避免和「刷新 / 今天·7天·30天 / 已用·剩余」冲突。 - **交互**:`pointerdown` → `setPointerCapture`;移动时 `position: fixed` + `left/top`;拖动中 `cursor: grabbing`、`user-select: none`、关闭过渡动画。 - **边界**:始终限制在视口内,四边留 8px;窗口 resize 时重新夹取。 - **记忆**:松手写入 `localStorage['magpie-usage:panel-pos'] = {x,y}`;下次打开优先用它(若已超出视口则忽略并清除)。 - **复位**:双击头部 → 回到默认锚定位置并清除存储;也可在头部右侧出现一个「↺」小按钮(仅在拖动过之后显示)。 - **不误关**:拖动过程中不得触发「点击外部关闭」;松手后开关状态不变。 - **可达性**:头部 `tabindex=0` 时可聚焦,`Esc` 仍关闭;方向键可微调 8px(Shift=1px) - **不做**:不改变 `Overview` 的 props/签名;不做缩放(resize)——除非后续明确要求。