- docs/delivery/部署文档.md:前置条件 / 环境变量 / 一条命令链 / systemd 与 Nginx 示例 / 首次运行检查 / 运行约束(后端单实例 · 3 天窗口 · 主密钥 · 401 摘除)/ 升级 / 排查 - 从零端到端走查:清库 → db:push → 启动(空转 + QPU 基线)→ 管理面登记 → 引擎立即补一轮(984 条)→ 查看面查询(未折算「—」)→ 补录购买记录 → 金额出现 → 换算参数时间线;无 pageerror - 8 篇设计文档状态 → 已实现(2026-09-15) - README:状态行 / 文档地图(含 delivery)/ 下一步(部署 + 待补验与裁决清单) - AGENTS.md:项目速览更新
11 KiB
11 KiB
交互设计
本工具的界面与页面设计——方向层(页面集合 + 职责)+ 细节层(跨页共性 + 逐页细节)。历史旧稿已删除(2026-09-14,内容已全部并入本文与 README / API 契约)。
| 项目 | 内容 |
|---|---|
| 状态 | 已实现(2026-09-15) |
| 关联 | 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 提示条「查询失败:」+「重试」按钮 |
| 操作反馈(管理面) | 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 → 输入框下方「口令不正确」;不做「记住我」