- docs/design:四张表字段设计 · 交互设计(方向层 + 细节层)· API 契约 · 同步引擎设计 - docs/upstream:sk-key 接口实证(430 行)· 接口范围(9 个接口) - README(全景入口)· AGENTS.md(AI 协作者指引) - 废弃旧稿已删除(不随仓库留存)
141 lines
11 KiB
Markdown
141 lines
11 KiB
Markdown
# 交互设计
|
||
|
||
> 本工具的界面与页面设计——**方向层**(页面集合 + 职责)+ **细节层**(跨页共性 + 逐页细节)。历史旧稿已删除(2026-09-14,内容已全部并入本文与 README / API 契约)。
|
||
|
||
| 项目 | 内容 |
|
||
|------|------|
|
||
| 状态 | 定稿(2026-09-13:方向层 + 跨页共性 10 条 + 逐页细节五节全部落定) |
|
||
| 关联 | `README.md`(决策与事实)· `docs/design/API契约.md`(数据形状依据) |
|
||
| 范围 | 方向层(页面集合 + 职责)+ 细节层(跨页共性 + 逐页细节) |
|
||
|
||
---
|
||
|
||
## 0. 大前提(2026-09-13)
|
||
|
||
### 0.1 路由分区与可见性
|
||
|
||
- **`/manage` 前缀 = 管理面**:管理通道的页面路由
|
||
- **无前缀 = 查看面**:给使用者直接查看的页面路由
|
||
- **管理面入口隐藏**:查看面不放任何指向管理面的入口——使用者无论拥有多少查看 / 统计功能,都无法从界面中进入管理面;直连管理面 URL 则由口令门帘拦截(两层:入口找不到 + 撞门要口令)
|
||
|
||
### 0.2 查看面职责:纯查询(对 key 只读)
|
||
|
||
- 查看面输入 key **仅用于查询**——凭手里已登记的 key 看用量;不再触发登记 / 轮询;输入未登记的 key → 提示「未收录」(措辞归细节层)
|
||
- key 的登记与启停全部在管理面完成——**写操作只发生在管理面**(2026-09-13 定,取代原「输入即注册」流程)
|
||
|
||
## 1. 页面集合(方向层 · 已收口)
|
||
|
||
### 1.1 查看面(无前缀)
|
||
|
||
| 页面 | 路由 | 职责 | 阶段 |
|
||
|------|------|------|------|
|
||
| 用量日志 | `/usage-log` | 指定时间范围查看模型请求日志(数据表格呈现);表格上方以数据卡片显示该时段累计用量、预估消费等汇总 | 一期 |
|
||
| 数据看板 | `/dashboard` | 固定时间窗口的统计视图(如模型消耗分布) | 二期候选(一期可不实现) |
|
||
|
||
- key 维度:输入式(一次可输入多个——延续核心需求「合并查询」);输入未登记的 key → 提示「未收录」
|
||
- 根路径 `/` 重定向到 `/usage-log`
|
||
- 卡片口径:累计用量与预估消费直接呈现折算数值(延续全项目「不标注币种」的基调)
|
||
|
||
### 1.2 管理面(`/manage` 前缀)
|
||
|
||
| 页面 | 路由 | 职责 |
|
||
|------|------|------|
|
||
| key 管理 | `/manage/api-keys` | 登记 / 清单 / 启停 |
|
||
| 购买记录 | `/manage/purchases` | 登记 / 编辑删除 / 核对提示 |
|
||
| 换算参数时间线 | `/manage/qpu` | 只读查看 |
|
||
|
||
- 根路径 `/manage` 重定向到 `/manage/api-keys`
|
||
- 能力边界见 API 契约 §2.2–2.4 与本文件 §3
|
||
|
||
## 2. 跨页共性(细节层,2026-09-13 起逐条推)
|
||
|
||
| # | 项 | 定法 | 状态 |
|
||
|---|----|------|------|
|
||
| 1 | 使用场景与适配 | **桌面优先**(使用者 2–3 人、以看报表为主);不做移动适配 | 已定 |
|
||
| 2 | 视觉基调 | **浅色单主题**(不做暗色切换);组件库默认主题 + 少量调色 | 已定 |
|
||
| 3 | UI 组件库 | **naive-ui**(2026-09-13 定)——成熟度 / 文档 / 主题变量系统更稳,表格与日期快捷选项能力已验证满足本项目;antdv-next 未采纳(社区新项目:上游为 React 版 antd 6、非 antdv 继任,生态与文档面未成熟) | 已定 |
|
||
| 4 | 时间显示格式 | **统一到秒**:`2026-09-11 19:37:12`(当天语境可简写 `HH:mm:ss`) | 已定 |
|
||
| 5 | 金额与数字格式 | **分层**:折算金额汇总 2 位小数 / 明细行 4 位小数;token 数与 quota 原值千分位(`53,939,847`);不标币种不变 | 已定 |
|
||
| 6 | 通用状态模式(加载 / 空 / 未收录 / 错误) | 见下方细则(2026-09-13 定) | 已定 |
|
||
| 7 | 导航 | 查看面:一期单页**不做导航**;管理面:**侧边栏菜单 + 内容区**(传统后台布局);「查看面 →」入口的位置形态随逐页细节 | 已定 |
|
||
| 8 | 表格通用交互 | **分页器**:页码器 + 每页条数选择(20/50/100/200,默认 50);**行详情**:展开行(`n-data-table` 内置),展示完整字段 | 已定 |
|
||
| 9 | 时间范围控件 | `n-date-picker type="datetimerange"` + 快捷项(今天 / 近 7 天 / 近 30 天);**默认 = 最近 7 天** | 已定 |
|
||
| 10 | key 输入控件与前端持久化 | 标签式(`n-dynamic-tags`),粘贴多行 / 逗号自动拆分;localStorage 记住上次输入、打开自动带出;**点「查询」才发请求** | 已定 |
|
||
|
||
**状态模式细则(#6,2026-09-13 定)**
|
||
|
||
| 状态 | 呈现 |
|
||
|------|------|
|
||
| 加载中 | 表格 `n-data-table` 内置 loading;卡片区 `n-skeleton` |
|
||
| 初始(未输入 key) | 页面中央引导「输入你的 key 开始查询」——不渲染卡片与表格 |
|
||
| 未收录 | 卡片区下方 warning 提示条:「以下 key 未收录:sk-…a1b2(请联系管理员登记)」;已收录部分照常展示 |
|
||
| 时段无记录 | 表格空态「该时段没有记录」;卡片数值显示 0 |
|
||
| 新 key 未首同步 | `data_until` 为 `null` → 卡片「数据截止」位显示「数据同步中…」 |
|
||
| 查询失败(网络 / 5xx) | 页面内 error 提示条「查询失败:<message>」+「重试」按钮 |
|
||
| 操作反馈(管理面) | `n-message` toast(登记 / 启停 / 保存的成功与失败) |
|
||
|
||
## 3. 逐页细节(细节层)
|
||
|
||
### 3.1 `/usage-log`(推导中)
|
||
|
||
**布局(2026-09-13 定)**
|
||
|
||
```
|
||
┌────────────────────────────────────────────────────────────┐
|
||
│ 筛选区:[key 标签输入框] [时间范围 datetimerange] [查询] │
|
||
├────────────────────────────────────────────────────────────┤
|
||
│ 卡片区:┌调用次数┐ ┌Token 用量┐ ┌预估消费┐ 数据截止 21:10:00 │
|
||
│ │ 1,873 │ │1,469,134│ │ 23.45 │ (小字 + 悬停明细)│
|
||
│ │消费·错误│ │ 缓存 89k │ │额度 53.9M│ │
|
||
├────────────────────────────────────────────────────────────┤
|
||
│ (如有)未收录提示条 │
|
||
├────────────────────────────────────────────────────────────┤
|
||
│ 明细表格(展开行详情) │
|
||
│ 分页器(页码 + 每页条数) │
|
||
└────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
- 「数据截止」不进卡片(它是注记不是指标):卡片区右端小字 + **悬停弹出 per-key 明细**(各 key 同步进度 / 未收录 / 已停用)——`meta` 信息完整呈现且不挤占卡片位
|
||
- 卡片主 / 副行:调用次数(主总行数,副「消费 X · 错误 Y」)· Token 用量(主 prompt+completion,副缓存命中)· 预估消费(主金额,副「额度记账」quota 原值,供对账)
|
||
|
||
**明细列与呈现(2026-09-13 定)**
|
||
|
||
- **默认 8 列**:时间(到秒)· key(`token_name`)· 模型 · 类型(Tag)· 输入 tokens · 输出 tokens · 消费(`amount_rmb`,4 位小数)· 耗时
|
||
- **展开行**(点行展开):完整字段——缓存 tokens · 流式 · `request_id` · `content`(错误详情)· 请求路径 · quota 原值 · **订阅归属完整组**
|
||
- **错误行**:类型列 `n-tag`(消费 = 中性 / 错误 = 红),**无整行底色**;错误详情在展开行
|
||
- **订阅归属**:默认列展示订阅名(`other.subscription_plan_title`,如「Max」);完整归属(额度实况 / 期间范围)在展开行——`purchases` §6 的「明细展示订阅归属」完整落地
|
||
|
||
### 3.2 `/manage/api-keys`(2026-09-13 推完)
|
||
|
||
- **清单 8 列**:key 名(`token_name`)· 状态徽章 · 累计已用 · 累计剩余(无限额度显示「不限」)· 到期 · 登记时间 · 数据截止 · 操作;其余字段(总额度 / 模型限制 / `consecutive_401s` / 额度新鲜度)归展开行
|
||
- **状态徽章三面孔**:运行中(绿)· 已停用(灰,`manual`)· 已失效(红,`auto_401`,tooltip 注明「连续 401 自动摘除」);数据未首同步的状态体现在「数据截止」列(「同步中」)
|
||
- **登记**:页头「+ 登记 key」→ `n-modal` 弹窗(粘贴 sk-key)→ 提交;三类失败各有文案——上游拒绝该 key / 该 key 已登记 / 上游暂不可用(稍后重试);成功后 toast + 清单插入新行(`log_synced_at: null` → 「同步中」)
|
||
- **启停**:行内按钮;**停用弹确认**(`n-popconfirm`,防误点);**启用直接执行**(安全动作,成功后 toast + 行内状态更新;失败按错误码提示)
|
||
- 「查看面 →」入口放侧边栏底部(低调,见 §2 #7)
|
||
|
||
### 3.3 其余页(待推)
|
||
|
||
| 页 | 重点 | 状态 |
|
||
|----|------|------|
|
||
| `/manage/purchases` | — | **2026-09-13 推完** |
|
||
| `/manage/qpu` | — | **2026-09-13 推完** |
|
||
| 口令门帘 | — | **2026-09-13 推完** |
|
||
|
||
**`/manage/purchases` 细节(2026-09-13 定)**
|
||
|
||
- **清单 8 列**:时间 · 类型(订阅 / 充值)· 实付金额 · 订阅(`#N`)· 期间 · 额度(`quota_granted`)· 备注 · 操作(编辑 · 删除;删除弹确认)
|
||
- **表单用右侧抽屉**(`n-drawer`):`kind` 单选 · `paid_at` · `paid_amount`(必填)· `quota_granted`(必填)· `subscription_id` · 期间(`period_end` 未结束可空)· `note`;校验含期间顺序(start < end)
|
||
- **核对提示与补录**:存在「观测到但未登记」时清单上方提示条「观测到 N 个未登记的订阅」;下方折叠区列出全部观测项(`#N` · 名称 · 日志条数 · 时间范围 · 观测额度 · 已登记 / 未登记);点「补录」开表单,**预填 `subscription_id` 与 `quota_granted`(观测值)**,期间不预填(观测范围 ≠ 订阅期间)
|
||
|
||
**`/manage/qpu` 细节(2026-09-13 定)**
|
||
|
||
- 表格两列:生效时间 · QPU 值(`id` 不显示);最新一行标「当前生效」
|
||
- 页首说明文案:「quota → 额度美元的换算比率历史;引擎自动采样、只记变化点;当前生效值 = 最近一行」
|
||
- 只有基线一行也属正常态(无特殊空态)
|
||
|
||
**口令门帘(2026-09-13 定)**
|
||
|
||
- 形态:访问 `/manage/*` 未验证时 → 全屏居中卡片(口令输入 + 「进入」);进入后跳转原目标页
|
||
- 校验:直接用任一管理面请求校验(401 即口令错)——**不需新端点**;口令存 **sessionStorage**(关标签即忘、刷新仍在),请求拦截器自动附加 `X-Manage-Token`
|
||
- 错误:401 → 输入框下方「口令不正确」;不做「记住我」
|