# 管理与展示 UI 模块 ## 1. 定位 UI 模块负责把数据、计费、Key 路由、配额和诊断能力投影成可使用的页面。信息架构和统计展示主要参考 `cpa-usage-keeper`,Key 套餐与金额操作参考 `cpa-plugin-key-billing`。 UI 不计算价格、不重新聚合账本、不保存业务真相。页面中的所有数字都来自 [api.md](api.md) 定义的权限化查询 API;UI 不直接读取 Repository 或 CPA Auth 原文。 ## 2. 两种视图必须分离 ### 2.1 用户视图 用户通过自己的 API Key 登录,只能看到与该 Key 所属账户有关的数据。根据已经确定的产品原则,用户可见的计费核心单位只有金额: - 总额度; - 已消费金额; - 剩余金额; - 本周期起止; - 今日/本月消费; - 按日金额趋势; - 最近请求的模型、时间、状态和最终金额; - Key 状态和到期时间。 用户界面不显示 Token 数、credits、倍率、每百万 Token 价格、上游账户配额或内部核算字段。金额统一显示 settlement currency,并使用服务器返回的格式化字符串/定点值,不能由浏览器 float 重算。 ### 2.2 管理员视图 管理员拥有完整运维与审计能力,可以查看: - 金额及 Token 明细; - 价格和 Fast/long-context 规则; - 下游账户、Key、套餐和余额; - 上游账号、订阅、配额和健康状态; - 请求/执行、重试、实际路由与失败; - 统计分析、同步状态、数据库和插件诊断。 管理员页面中的“用户花费”和“上游配额”必须视觉与命名分离,避免把两种额度混为一谈。 本项目采用请求结束后结算的软金额额度。用户页必须写“软额度/请求后结算”,不得宣传“绝不超额”;余额很低时仍可能由最后一个在途请求产生有限负余额。 ## 3. 管理员信息架构 主要沿用 usage-keeper 的七个区域,并加入本项目的计费/路由管理: ### 3.1 总览 Overview 首屏回答“现在系统是否正常、花了多少钱、谁在使用”: - 今日/本周期总金额、请求数、成功率; - RPM、金额/分钟;管理员可切换查看 TPM/Token; - 日均请求、日均金额; - 金额、请求、缓存命中率时间序列; - Recent Activity 活动格; - 实时请求速率、金额速率、TTFT/Latency P50/P95; - 当前模型、下游账户/Key、上游账户 Top; - 上游账户即将耗尽、Key 已阻断、未定价事件、采集延迟告警。 参考组件:`StatCards`、`RecentActivityPanel`、`OverviewRealtimePanel`。 ### 3.2 分析 Analysis - 金额和 Token 时间序列; - 金额分项:输入、cache read、cache write、output; - 模型效率:每请求金额、输出量、缓存率; - Top models; - TTFT/Latency 分布和异常点; - 下游账户/Key、模型、Auth File、AI Provider 构成; - Key×模型热力图; - Fast 使用金额与占比; - strict/preferred 路由命中和 fallback 分析。 参考 `analysis/AnalysisPanel.tsx`。金额始终使用已经入账的 `ChargedAmount`,不能按当前价格重算历史。 ### 3.3 请求 Events 可分页、筛选、排序和导出。管理员可配置显示列: - 时间、RequestID、Key/账户; - requested/upstream/billing model 与 alias; - requested/reported/effective service tier; - success/failure/canceled/rejected; - endpoint、stream、reasoning effort; - TTFT、Latency、速度; - Token 各分项与缓存率; - 最终金额、价格版本、倍率、核算质量; - 期望上游账户、实际账户、retry/fallback; - 请求日志受控查看/下载入口。 参考 `RequestEventsDetailsCard` 的列偏好、分页、筛选、导出和 request log 交互。默认不展示 Prompt/Response;查看 CPA 请求日志必须显式授权、短期 token、审计记录和脱敏。 ### 3.4 下游账户与 Key 这是本项目相对 keeper 的核心新增页: - 账户名称、状态、套餐、本期额度/已用/剩余金额; - 所属 Key、preview、alias、状态、有效期、最近使用; - 创建/轮换/禁用/撤销 Key; - 绑定/解绑套餐、充值、扣减、重置周期; - 模型、endpoint、Fast 使用权限; - route mode 与指定上游账户/池; - 实际路由与 fallback 最近记录; - 批量操作和 CPA Key 同步。 额度操作必须二次确认,并展示变更前后金额及将写入的账本原因。 ### 3.5 上游账户 Auth Files / Providers 沿用 usage-keeper 两个独立 tab: - Auth Files:OAuth/Codex 账户; - AI Provider:配置型 API Key provider。 展示身份别名、provider、状态、priority、disabled、订阅层级/有效期、首次/最近使用、成功失败、用量、当前配额窗口和重置时间。支持: - provider 筛选、分页、排序; - 编辑本地别名; - 刷新单个或当前页配额; - Codex quota inspection; - 可用时执行 quota reset; - 查看哪些下游 Key 严格/优先绑定到该账户。 - 显示 `scheduler-visible/bindable`;MVP 阻止绑定不在最高可用 priority tier 的 Auth,并解释当前 CPA scheduler 只能看到该 tier。 不要在 UI 返回上游 token、完整文件内容或 API Key。 ### 3.6 价格与套餐 Settings - 模型价格目录、来源、版本和生效时间; - 同步预览、确认发布、管理员覆盖; - Fast 2.5x、long-context 和条件规则; - 未定价模型告警; - 套餐金额、周期、绑定账户数量; - 安全/readiness 设置、数据库备份和保留策略;当前无插件管理 session,不把 Management Key 持久化。 参考 keeper 的 `PriceSettingsCard`、pricing rules,以及 key-billing 的 Plans/Prices 页面。禁止后台同步后无确认地改变生产计价。 ### 3.7 系统诊断 - 插件版本、CPA ABI/RPC schema 与兼容状态; - SQLite 路径、大小、WAL、最近备份和 integrity; - runtime topology(callback-driven/sidecar/worker soak status)、required-plugin readiness 和 sentinel/gateway 状态(不显示 secret); - pending request 数、采集/写入队列深度; - 各 aggregation checkpoint lag; - 未定价、missing、partial、inconsistent 计数; - CPA identity/model/quota 最近同步结果; - 插件运行事件和错误。 诊断日志与账本分开;清理诊断日志不会清除金额、请求事实或累计。 ## 4. 用户页面布局 用户页面保持极简: ```text [当前 Key / 状态] [退出] [本周期额度 $20.00] [已消费 $7.25] [剩余 $12.75] [周期结束 8/31] [金额趋势:今天 / 7 天 / 本月 / 自定义] [最近请求] 时间 | 模型 | 状态 | 金额 ``` 可以参考 usage-keeper 的 `KeyOverviewPage`、`StatCards`、`RecentActivityPanel` 与 realtime 交互,但将 Token/RPM/TPM/cache 等内容替换成用户需要的金额、请求和可用状态。 ## 5. 交互原则 - 时间范围统一支持 today、yesterday、7/30 天、本月和自定义; - Overview 可在页面可见时每 10 秒刷新,隐藏时暂停; - Events 第一页可自动刷新,其他页保持稳定; - 大表支持列显示/排序偏好、分页和导出; - 空状态、加载、部分加载、数据延迟和价格不可用必须分别表达; - Analysis 的慢查询分区并行加载,某一区失败不遮挡其他已完成卡片; - 桌面和移动端都可用,表格横向滚动、tooltip 可键盘访问; - 支持明暗主题和中英文,但第一版中文优先; - 金额、时间、百分比由统一 formatter 处理。 ## 6. 技术承载方式 第一版建议构建静态 React/Vite bundle,使用 `go:embed` 打入动态库,通过 CPA `management_api` 注册: - 受 CPA Management Key 保护的 JSON API 位于 `/v0/management/plugins//...`; - browser resource 位于 `/v0/resource/plugins//...`;CPA 当前只支持未经过 Management Key 的精确 GET resource 路径; - 管理员数据必须由受保护 Management API 获取,不能嵌入公开 resource HTML; - MVP 用户页只注册少量只读 resource GET JSON 路径,由插件自行校验 `Authorization: Bearer ` 并按 Credential scope 返回金额投影; - 用户 Key 只保存在页面内存,不进入 URL、cookie 日志或 localStorage;刷新后需要重新输入; - 当前 CPA plugin route 不足以安全实现完整的用户 POST API 和 HttpOnly 登录 session。需要这些能力时应增加独立 sidecar/public API 或扩展 CPA 的 authenticated user plugin routes; - HTML/JSON/CSV 导出全部转义,响应设置 CSP、`nosniff` 和 `no-store`(敏感接口)。 resource 只支持 exact GET,因此前端构建必须遵守: - Vite 使用相对 `base`,build manifest 中每个 JS/CSS/font 都注册成独立 ResourceRoute; - 页面路由使用 HashRouter,不依赖 history fallback; - 第一版不注册 service worker,避免公开资源或敏感 JSON 被离线缓存; - CSP 禁止 inline 时使用独立资源或固定 hash; - 用户 JSON 设置 `Cache-Control: no-store` 和 `Vary: Authorization`。 公开 resource shell 不会自动获得 CPA Management Key。管理员首次进入时手工输入 Key,只保存在当前页面 JS 内存,刷新即失效;不得读取或复用 CPA 控制面板的 localStorage/sessionStorage。用户 Key 采用相同的“当前页面内存”原则,但只调用用户只读 resource GET。 当前 CPA Management adapter 会对 JSON 字符串做 HTML entity 转义。客户端对服务端 JSON 字符串最多执行一次兼容性 entity decode,然后仍由 React text node 渲染;禁止 `dangerouslySetInnerHTML`。测试必须覆盖 `A & B ` 写入/读取往返。CSV 导出还要防 `= + - @` 开头的公式注入,不能把 HTML escape 当成 CSV 安全。 不能照搬 key-billing 在浏览器 session state 中借用 Management Key 的方式作为最终安全模型。 CPA `home.enabled` 时 Management 和 resource route 都返回 404,因此 cpa-ext 第一版整体不支持 Home;页面不能把它表现成普通“暂无数据”。 ## 7. API 投影原则 - 用户 API 只返回自己的金额投影,不先返回管理员对象再让前端隐藏字段; - 管理员 API 返回 Token/价格/上游身份等完整审计字段; - 所有列表使用服务端分页、筛选和稳定游标; - 图表 API 返回预聚合,不把几十万条事件交给浏览器计算; - API 金额返回 currency + micros + display,前端不得自行从 Token 算钱; - realtime、overview、analysis、events 独立接口,避免一个慢请求阻塞整个页面。 ## 8. MVP 与后续 MVP 页面: 1. 用户金额总览; 2. 管理员 Overview; 3. 下游账户/Key/套餐/账户路由; 4. 请求明细; 5. 上游 Codex 账户与配额; 6. 价格; 7. 系统诊断。 后续补齐 Analysis、复杂热力图、排名、更多 provider、导出与 request log。底层数据/API 契约从第一版就应容纳它们。 ## 9. 参考路径 `cpa-usage-keeper` 为主要 UI 参考: - `web/src/pages/UsagePage.tsx`; - `web/src/pages/KeyOverviewPage.tsx`; - `web/src/components/usage/StatCards.tsx`; - `RecentActivityPanel.tsx`、`OverviewRealtimePanel.tsx`; - `RequestEventsDetailsCard.tsx`; - `analysis/AnalysisPanel.tsx`; - `credentials/`; - `PriceSettingsCard.tsx`、`ApiKeySettingsCard.tsx`; - `web/src/lib/api.ts`、`types.ts`。 `cpa-plugin-key-billing` 参考: - `internal/plugin/ui.html`; - `internal/plugin/management.go`; - `internal/billing/keys.go`、`log.go`。 ## 10. 验收标准 - 用户登录后只能看到本账户且只有金额计费单位; - 管理员能完成 Key、套餐、余额、路由、价格和上游账户管理; - Overview、Events、上游配额与账本数字一致; - 历史金额不因当前价格变化而改变; - 权限校验在服务端执行; - 页面不泄露下游/上游秘密、Prompt 或完整 Response; - Management Key/用户 Key 只驻留当前页面内存,刷新失效,用户 JSON 不缓存; - exact resource assets、HashRouter、CSP 和 entity-decode 往返测试通过; - Home 模式由 readiness 明确拒绝,不显示误导性的空页面; - 大数据量下使用分页和聚合,UI 不冻结; - 关键动作有确认、审计、错误反馈和可恢复路径。