From 6a8b4d0128eb2f2477ba3f3e51e966e1437270f2 Mon Sep 17 00:00:00 2001 From: argszero Date: Sat, 22 Aug 2026 08:04:24 +0800 Subject: [PATCH] docs: README language switcher + Powered by EMRG + concise current-state docs (rants 2026-08-22T07:46:46/07:49:58/07:51:36) --- CONTRIBUTING.md | 10 + README.en.md | 6 + README.md | 6 + docs/architecture.md | 218 +++++++------------- docs/plan-api-matrix.md | 140 ++----------- docs/user-stories.md | 433 +++++----------------------------------- 6 files changed, 165 insertions(+), 648 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c681733..412be29 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -57,3 +57,13 @@ - 大改动(新模块、架构调整)请先开 Issue 讨论,再动手 - 提交代码即视为同意 MIT License 下分发 + +## 开发流程(Powered by EMRG) + +本项目由 [EMRG](https://emrg.ai)(演化式多实例系统)驱动开发: + +1. 需求/反馈以 **rant**(吐槽)形式提交到项目队列 +2. EMRG 自动实现 → 本地测试全绿 → 提交 PR(引用 rant 时间戳) +3. 人工评审 → merge → 发版时打 tag(镜像随 tag 发布) + +外部贡献者同样欢迎:开 Issue 或直接 PR,遵循上文分支 / commit / 测试规范即可。 diff --git a/README.en.md b/README.en.md index 6efc524..3fdd15a 100644 --- a/README.en.md +++ b/README.en.md @@ -1,5 +1,7 @@ # AITokenPool — Shared AI Token Pool +[English](README.en.md) | [简体中文](README.md) + > **Don't let your token plan go to waste.** > Subscribed to Claude / ChatGPT / GLM / DeepSeek and can't use it all? Share your quota to earn points — and spend them on models from others when you need to. @@ -65,6 +67,10 @@ OpenAI-compatible endpoints: `POST /v1/chat/completions`, `POST /v1/responses`, | [CHANGELOG.md](CHANGELOG.md) | Version history | | [CONTRIBUTING.md](CONTRIBUTING.md) | Contribution guide | +## Powered by EMRG + +This project is developed by [EMRG](https://emrg.ai) (Evolutionary Multi-instance Reasoning System) — requirements are filed as rants, and EMRG implements, tests, and submits PRs automatically, with human review before merge. + ## License [MIT](LICENSE) diff --git a/README.md b/README.md index 2d0a07c..e42d71a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # AITokenPool — AI Token 共享池 +[English](README.en.md) | [简体中文](README.md) + > **不要让 token plan 白白浪费。** > 订阅了 Claude / ChatGPT / GLM / DeepSeek 的额度用不完?共享出去赚点数,需要时也能用别人的。 @@ -65,6 +67,10 @@ OpenAI 兼容网关端点:`POST /v1/chat/completions`、`POST /v1/responses` | [CHANGELOG.md](CHANGELOG.md) | 版本历史 | | [CONTRIBUTING.md](CONTRIBUTING.md) | 贡献指南 | +## Powered by EMRG + +本项目由 [EMRG](https://emrg.ai)(演化式多实例系统)驱动开发——需求以 rant 形式提交,由 EMRG 自动实现、测试并提交 PR,人工评审后合入。 + ## License [MIT](LICENSE) diff --git a/docs/architecture.md b/docs/architecture.md index f9fda90..c7e9ff3 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -1,158 +1,90 @@ -# AITokenPool 架构设计 +# AITokenPool 架构 -> v0.3(2026-08-18)· 落地 P0(A/B/C)与 P1 后端实现:axum 网关(OpenAI/Anthropic 双协议 + SSE 流式)、7 条路由规则落地、计量账本闭环、AES-256-GCM 上游 key 加密、点数规则(每日赠送/有效期/先赠后永扣减)、管理员充值 API;补齐 API 一览与数据库实表结构 -> v0.2(2026-08-15)· 新增 4.2.1 路由与故障转移策略(随机初始选择 / 粘性 / 静默故障转移 / 3 次切换上限 / 5 秒健康冷却 / 健康优先) -> v0.1(2026-08-13)· 基于 openlocalrouter 演进 +> 本文说明**现状**:现在是什么、能干什么、将来怎么走(历史变更见 [CHANGELOG.md](../CHANGELOG.md))。 ## 1. 定位 -开源的 AI Token 共享平台,双模式: -- **企业版**:私有部署,公司 key 池 + 员工点数配额(配额凭证,单向) -- **公共版**:共享市场,用户分享闲置 key 赚点数、消费别人 key(交换媒介,双向) - -一套核心平台,两种部署。 - -## 2. 核心定论(多轮讨论结论) +开源的 AI Token 共享平台 / 多模型网关,双模式共用同一套核心: -### 2.1 中心化架构(方案 A) -- **平台托管 key + 平台执行调用**——平台是唯一可信执行者 -- 计量可信(平台精确记账)、响应真实(平台直连上游)、无篡改作弊空间 -- 分享者一次性上传 key,零负担(可离线) -- **方案 B(边缘代理)否决**:key 在分享者机器 → 篡改作弊无解、伪造响应无解 +- **企业版**:私有部署,公司 key 池 + 员工点数配额(配额凭证,单向) +- **公共版**:共享市场,用户分享闲置 key 赚点数、消费他人 key(交换媒介,双向) -### 2.2 中心化的工程问题(要解决) -- IP 封禁 → 多地节点部署,某节点被封切流量 -- 地域限制(国内 IP 访问 ChatGPT)→ 地域匹配路由(海外 key → 海外节点) -- key 安全 → 加密存储、最小权限、定期轮换、审计 -- 平台信任 → 开源代码 + 可审计 + 明确隐私政策 +**中心化架构**:平台托管 key + 平台执行调用——平台是唯一可信执行者,计量可信、响应真实。 -## 3. 技术栈 +## 2. 技术栈(现状) -- **Rust**(宿主有 openlocalrouter 积累) -- axum + hyper + tokio(高吞吐 HTTP 网关/流式转发) -- SQLite(本地/单机)→ PostgreSQL(公共版/多节点) -- Redis(缓存/限流/会话,公共版) -- reqwest + rustls(上游调用 + TLS) -- argon2 + sha2(key 哈希/加密) -- 前端:Web 管理台(React/Vite)+ 可选 Tauri 桌面端(复用 openlocalrouter) +| 层 | 选型 | +|---|---| +| 后端 | **Rust**(`rust-version 1.86`)+ axum + tokio + rusqlite | +| 数据库 | **SQLite**(单文件,`data/aitokenpool.db`,迁移 v10) | +| 加密 | AES-256-GCM(上游 key,`src/crypto.rs`)、argon2(密码哈希) | +| 上游调用 | reqwest(非流式)+ SSE 流式转发(`src/sse.rs` 跨协议转换) | +| 前端 | **原生 JS** 静态页(`ui/`,无构建步骤;i18n 中英双语) | +| 部署 | Docker(多阶段构建,非 root)或 `cargo run` | -## 4. 模块架构 +## 3. 模块(src/) -``` -┌──────────────────────────────────────────────────────┐ -│ 平台 │ -│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌──────────┐ │ -│ │ 网关层 │ │ 账本层 │ │ 市场层 │ │ 管理台 │ │ -│ │ (axum) │ │ (点数) │ │ (共享) │ │ (Web) │ │ -│ └────┬────┘ └────┬────┘ └────┬────┘ └──────────┘ │ -│ ┌────▼─────┐ ┌───▼────┐ ┌───▼────┐ │ -│ │ Key 池 │ │ 计量引擎│ │ 撮合路由│ │ -│ │ (加密托管)│ │ (token) │ │ (定价) │ │ -│ └────┬─────┘ └───┬────┘ └───┬────┘ │ -│ ┌────▼───────────▼──────────▼────┐ │ -│ │ 数据库 │ │ -│ └────────────────────────────────┘ │ -└──────────────────────────────────────────────────────┘ -``` +| 模块 | 职责 | +|---|---| +| `router.rs` | 网关路由:多 Provider 选择、粘性、静默故障转移(3 次上限、5 秒健康冷却) | +| `protocol.rs` | OpenAI Chat / Responses / Anthropic Messages 三协议**双向互转** | +| `sse.rs` | 流式 SSE 跨协议转换 + usage 计量 | +| `billing.rs` | 计量计费:token → 价格 → CNY 锚定点数(1 点 = 1 元,5 位小数);高峰时段计价 | +| `gift.rs` | 新人每日赠送(注册起 10 天,当日有效,惰性过期清理) | +| `auth.rs` / `mail.rs` | Bearer 认证(API Key)+ argon2;SMTP 验证码(重试 3 次) | +| `db.rs` | SQLite 建表 + 幂等迁移 + seed(仅测试) | +| `dao.rs` | 数据访问层 | +| `routes/` | 认证 / 钱包 / 交易 / 仪表盘 / 共享 / 管理 / 运营者 API | -### 4.1 网关层(P0-B/C 已实现,Rust axum 自研) -- 统一 API 端点:**OpenAI Chat Completions**(`POST /v1/chat/completions`)+ **Anthropic Messages**(`POST /anthropic/v1/messages`),覆盖国内主流 Coding Plan 与下游工具(Cursor / Claude Code / Cline / OpenCode) -- **流式转发(SSE)**:`stream:true` 分支逐块透传(`text/event-stream`),OpenAI 流尾 usage / Anthropic `message_start`+`message_delta` 计入账本;客户端断开不入账(finalize 随 body drop) -- **余额预检**:上游调用前检查**可用余额**(赠送 + 永久,P1 口径),≤ 0 → 402「余额不足」 -- 多 Provider 路由、故障转移(见 4.2.1,`src/router.rs` 落地:粘性 / 健康冷却 / 3 次切换上限) -- **API 一览**(`src/routes/mod.rs`): - - `GET /healthz` — 健康检查(返回版本号) - - `POST /api/auth/login` — 邮箱 + argon2 口令 → 分发 key(`atk_live_` 前缀,get-or-create) - - `POST/GET /api/api-keys` — 分发 key 生成 / 脱敏列表(Bearer 认证) - - `POST /v1/chat/completions` / `POST /anthropic/v1/messages` — 网关(非流式 + SSE) - - `GET /api/models` — 模型市场(含可用性/价格) - - `POST/GET /api/sharings` + `PATCH /api/sharings/:id` — key 上架 / 列表(脱敏)/ 暂停·下线 - - `GET /api/wallet` / `GET /api/transactions?type=` / `GET /api/dashboard` — 钱包(双余额)/ 交易分页 / 仪表盘聚合 - - `POST /api/admin/credits` / `GET /api/admin/users` / `GET /api/admin/usage` — 管理员充值 / 成员列表 / 用量报表(role=admin) - -### 4.2 Key 池 -- 上游 key **AES-256-GCM 加密存储**(P0-C 实现,`src/crypto.rs`):密文格式 `v1::`;主密钥来源 env `ATP_MASTER_KEY` → config `server.master_key`(hex 32 字节)→ 缺省 dev 随机密钥并告警(重启后旧密文不可解);启动时 `migrate_key_encryption` 自动迁移历史明文 -- 企业:管理员配 key → 分发子 key 给员工 -- 公共:分享者上传 key → 进共享池 -- key 状态:可用/失效/限额/撤销;转发前解密,解密失败判 key 不可用 -- **管理入口(v1.11 定案)**:无独立 Key 池管理界面——管理员与普通用户一样通过**「上架」**(共享管理页:选厂商 → Plan → 模型、填 key、声明额度、可用时间段)配置上游 key;共享列表即 key 池视图(可暂停 / 删除)。「Key 池」保留为数据层概念(平台持有的上游 key 集合),UI 侧不再单独暴露。 - -#### 4.2.1 路由与故障转移策略(v0.2,宿主 2026-08-14 定案) - -当消费者请求某模型 M 时,网关从多个分享者提供的该模型 key 中选择(公共版共享池;企业版 key 池同规则)。定案规则共 7 条: - -1. **初始选择(随机)**:用户首次请求模型 M 时,从 M 的**健康** key 池中**随机**选择一个(如 B1 或 B2); -2. **粘性(Sticky)**:选定后,该用户**后续请求都复用这个 key**,直到它不可用; -3. **不可用判定**:key 下架(分享者删除 / 暂停)、key 报错(上游错误 / 鉴权失败 / 额度用尽)等; -4. **故障转移(静默)**:当前 key 不可用时,**静默**选择下一个健康 key(用户无感,不打断请求); -5. **切换上限**:**每次路由最多允许 3 次切换**;3 次都失败 → 报错返回(如「该模型暂无可用 key」); -6. **健康标记**:任何**在用的 key 报错 → 标记为「非健康」5 秒**(5 秒内不参与选择); -7. **健康优先**:选择 key 时**优先选择当前健康**的 key(非健康 key 排除,5 秒冷却后可重新进入候选)。 - -**示例流程**:A 请求模型 M → 随机选 B1(健康)→ A 的后续请求粘性复用 B1 → B1 报错(额度用尽)→ 静默切换 B2(第 1 次)→ B2 也报错 → 切换 B3(第 2 次)→ 成功返回;若 B1/B2/B3 均失败(第 3 次也失败)→ 返回「该模型暂无可用 key」。B1 报错后标记非健康 5 秒,冷却后可重新参与选择。 - -### 4.3 计量引擎(P0-B 已实现,`src/billing.rs`) -- 每次调用记录:用户、模型、输入/输出 token、成本(`usage_records`) -- **点数计算**:`成本 = 输入token×input_per_m/1e6 + 输出token×output_per_m/1e6`(models 表单价,config.toml `[[models]]` 唯一真源)→ 折算到锚定货币 CNY(USD 价按 `CNY_PER_USD=7.2`)→ × `points_per_unit`(1 点 = 1 CNY;点数可为小数,最多保留 5 位,`billing::round5`) -- **高峰时段计价(v0.7.3)**:`[[models]]` 可选 `peak_input_per_m / peak_output_per_m / peak_cache_hit_input_per_m`(缺省 0 = 不启用);按北京时间(固定 Asia/Shanghai,UTC+8 无夏令时)判定高峰 9:00-12:00、14:00-18:00(周一至周日),命中则用高峰价(DeepSeek 官方高峰价 = 空闲价 ×2) -- **入账(事务性)**:`settle` 在成功响应后调用——扣消费者 → 加分享者 90% → 两条 transactions(consume/earn)→ usage_records → keys.used;任一步失败整体回滚(失败不入账) - -### 4.4 账本层(P1 点数规则已落地) -- **点数账户拆分**:`quotas.balance` = 永久点数(分享收益 / 管理员充值);`quotas.gift_balance` = 当前有效赠送点数总额 -- **新人每日赠送**(`src/gift.rs`):注册(users.created_at)起**连续 10 天**每天 1 点,**当日有效**(expires_at = 当天 23:59:59);懒加载 `ensure_daily_gift`(wallet/dashboard/网关预检前)补发当日点数;**惰性过期清理**——查询时把过期 active 记录标 expired 并从 gift_balance 扣减(无需定时任务),余额自愈对齐 -- **扣减顺序**:消费**先扣最早到期的赠送点数**(gift_grants 按 expires_at ASC 逐条扣,标 used),不足再扣永久 balance;可用余额 = gift + permanent(网关预检与 settle 同口径) -- **分享收益**:分享者得 **90%**(平台抽成 10%,`SHARE_RATIO=0.9`),永久有效 -- **管理员充值**:`POST /api/admin/credits` → 永久 balance 增加 + 写 transactions(type=topup,counterpart=管理员) -- 交易流水(可对账):`transactions` 全量记录 consume / earn / topup - -### 4.5 市场层(公共版) -- 分享者上架闲置 key(声明额度/价格) -- 消费者按点数购买使用 -- 撮合/路由(价格/可用性/地域) -- 信誉体系(滥用惩罚、成功率) - -### 4.6 管理台 -- 企业:key 管理、员工点数、用量报表 -- 公共:市场浏览、钱包(点数余额)、交易记录 -- **管理员 API(P1 已实现,`src/routes/admin.rs`)**:角色经 `AuthUser.role` 判定(Bearer key 关联 users.role),非 admin → 403;**v0.6.0 起生产库不预置任何种子账号**(首次部署 = 干净空库,测试用 demo/admin/ops 账号仅存在于 `#[cfg(test)]` 的 `seed_test_users`) -- role=ops 端点(平台运营者)留 P2,暂与 admin 合并权限位 - -## 5. 数据库设计(实表,`src/db.rs` 迁移 v3) +## 4. 数据流(一次调用) ``` -users — 用户(email/password_hash[argon2]/name/role/created_at) -keys — 上游 key(provider/plan/model/状态/属主/加密密文/额度/已用/可用时间段/备注) -api_keys — 分发 key(绑定用户、atk_live_ 前缀、状态、last_used) -models — 模型价格(provider/model/currency/input_per_m/output_per_m/cache_hit_input_per_m/peak_input_per_m/peak_output_per_m/peak_cache_hit_input_per_m) -quotas — 点数账户(balance 永久 + gift_balance 有效赠送) -gift_grants — 赠送明细(amount/granted_at/expires_at/status: active|used|expired) -transactions — 交易(counterpart/key_id/model/tokens/pts/type: consume|earn|topup/status/time) -usage_records— 调用明细(api_key_id/key_id/model/tokens/cost/time) -schema_version— 迁移版本(SCHEMA_VERSION=3,幂等迁移:ensure_column 补列 + CREATE TABLE IF NOT EXISTS) +客户端 → POST /v1/chat/completions(或 /v1/responses、/anthropic/v1/messages) + → auth 校验(Bearer atk_* key → 用户) + → 余额预检(可用 = gift + permanent,≤0 → 402) + → 路由选 key(健康优先 → 随机 → 粘性复用) + → 上游请求(解密 key,非流式或 SSE 转发) + → 成功后 settle:扣消费者 → 加分享者 90% → 写 transactions + usage_records + keys.used ``` -## 6. 部署 - -- 企业版:Docker 单机(网关+账本+管理台),内网 -- 公共版:云部署 + 多地节点(地域路由)+ 前端市场 -- 配置:`config/config.toml`(server addr/db_path/master_key、points 锚定货币与粒度、providers/plans 端点、价格覆盖);`cargo run -- --config ` - -## 7. 路线 - -1. ~~**P0**:从 openlocalrouter 复用核心~~ → **已完成(v0.1.0→v0.2.2,PR #71–#74)**:Rust axum 自研骨架 + 认证 + API Key + 网关双协议 + 路由故障转移 + 计量账本 + SSE 流式 + key 加密 + 共享/钱包/交易 API -2. ~~**P1**:点数/账本系统~~ → **已完成(v0.3.0,PR #75)**:每日赠送/有效期/先赠后永扣减/管理员充值 -3. **P2**:Web 管理台(UI 原型已 v1.20,前端静态页先行走在前面;后端角色 ops 端点) -4. **P3**:公共版共享市场深化(上架/撮合/结算) -5. **P4**:多地节点/地域路由 - -## 8. 竞品(2026-08-13 调研) - -| 项目 | 模式 | 架构 | 结算 | 状态 | -|---|---|---|---|---| -| one-api (36K⭐) | B2C 分发 | 中心化 | 卡密/订阅 | 成熟 | -| new-api (45K⭐) | B2C 分发 | 中心化 | 卡密/订阅 | 成熟 | -| coai (9.3K⭐) | B2C 多租户 | 中心化 | 计费/卡密 | 成熟 | -| **Asale** | **C2C 共享** | **边缘代理(B)** | **USDT** | alpha/用户少 | -| **AITokenPool** | **企业+公共** | **中心化(A)** | **点数** | 构想→立项 | - -差异化:中心化(无正文暴露风险,Asale 有)+ 企业版先行(Asale 无)+ 点数(无币合规简单)。 +## 5. 数据库(实表) + +| 表 | 说明 | +|---|---| +| `users` | 用户(email / password_hash / name / role / verified) | +| `keys` | 上游 key(provider / plan / model / 加密密文 / 额度 / 可用时间段 / note) | +| `api_keys` | 分发 key(`atk_live_` 前缀,绑定用户,可撤销) | +| `models` | 模型价格(input / output / cache_hit,可选高峰价;config `[[models]]` 为唯一真源) | +| `quotas` | 点数账户(balance 永久 + gift_balance 有效赠送) | +| `gift_grants` | 赠送明细(amount / expires_at / status: active\|used\|expired) | +| `transactions` | 交易流水(type: consume\|earn\|topup\|gift;含 token 明细列) | +| `usage_records` | 调用明细(tokens 拆 input / cached / output) | +| `departments` / `raise_requests` | 部门 + 成员加额申请(企业版) | + +## 6. API 一览 + +- `GET /healthz` — 健康检查(返回版本号) +- `POST /api/auth/register` / `login` / `verify` / `resend-code` / `forgot` / `change-password` +- `GET /api/me` — 当前用户 +- `POST/GET/DELETE /api/api-keys` — 分发 key 生成 / 列表 / 撤销 +- `GET /api/models` — 模型列表(含可用 key 与价格) +- `POST /v1/chat/completions` / `/v1/responses` / `/anthropic/v1/messages` — 网关(非流式 + SSE) +- `GET /api/wallet` / `/api/transactions` / `/api/dashboard` — 钱包 / 交易(summary + 明细)/ 仪表盘 +- `POST/GET/PATCH /api/sharings` — key 上架 / 列表 / 暂停下线 +- `POST /api/admin/credits` / `GET /api/admin/users` / `usage` / `models` CRUD — 管理(role=admin) +- `GET /api/ops/runtime` / `credits` / `users` — 运营者视图(role=ops) +- `GET /api/config` — 前端动态配置(public_url 等) + +## 7. 部署 + +- Docker:`docker compose up -d --build`,或镜像 `ghcr.io/argszero/aitokenpool:`(**镜像随版本 tag 发布**,latest 指向最新发版) +- 数据目录统一在 `ATP_DATA_DIR`(默认 `./data`:config.toml + db + logs/) +- 生产必设 `ATP_MASTER_KEY`(上游 key 加密);首次启动自动创建初始管理员(随机密码打印在日志) + +## 8. Roadmap(规划,未实现) + +- **P2**:前端深化(chat-modal 流式接网关、SSE 续传、key 缓存) +- **P3**:公共版共享市场深化(撮合 / 信誉体系) +- **P4**:多地节点 / 地域路由 / PostgreSQL / Redis(当前为单机 SQLite,无外部依赖) + +> 注:早期文档中提及的 React / Vite / Tauri 桌面端、PostgreSQL 均**未实现**——前端为原生 JS 静态页,数据库为 SQLite。 diff --git a/docs/plan-api-matrix.md b/docs/plan-api-matrix.md index d954864..791e028 100644 --- a/docs/plan-api-matrix.md +++ b/docs/plan-api-matrix.md @@ -1,135 +1,35 @@ -# 国内主流 Token Plan / Code Plan 调研:API 协议与 Base URL +# AITokenPool 协议支持现状 -> v0.1(2026-08-13)· browser-harness 实抓官方文档 + Google 官方文档源 +> 网关对外暴露的协议、支持的客户端与上游接入现状(历史调研细节见 CHANGELOG / git 历史)。 -## 0. 核心结论 +## 1. 对外协议(网关已实现) -国内主流 Coding Plan / Token Plan **全部走两条协议**: -1. **OpenAI 兼容协议**(Chat Completions,`/chat/completions`)——接 Cursor、Cline、Roo Code、OpenCode 等 -2. **Anthropic 兼容协议**(Messages,`/v1/messages`)——接 Claude Code、Goose、OpenClaw 等 - -**没有一家当前原生支持 OpenAI Responses API**(`/responses`),只有 DeepSeek/智谱按量付费 API 支持。Coding Plan 的专属端点基本只暴露 OpenAI Chat + Anthropic Messages 两种。 - -**关键设计含义**:AITokenPool 网关层**第一版只需实现两个协议适配器**: -- OpenAI Chat Completions(`/chat/completions`,含 SSE 流式) -- Anthropic Messages(`/v1/messages`,含 SSE 流式) - -即可覆盖国内全部主流 Coding Plan 的上游接入,以及大多数下游客户端(Cursor/Claude Code/Cline…)。 - ---- - -## 1. 各家 Plan 的协议与 Base URL - -### 1.1 阿里云百炼 Token Plan(个人版/团队版) -- **产品**:Token Plan,Credits 统一计量,一份订阅多工具通用(Claude Code/Cursor/Qwen Code/Qoder/OpenClaw/Cline…) -- **Key**:专属 key,前缀 `sk-sp-`(普通按量 `sk-` 会 401) -- **限制**:仅限交互式编程工具,禁止自动化批量调用(后端服务) - -| 协议 | Base URL | -|---|---| -| OpenAI 兼容 | `https://token-plan.cn-beijing.maas.aliyuncs.com/compatible-mode/v1` | -| Anthropic 兼容 | `https://token-plan.cn-beijing.maas.aliyuncs.com/apps/anthropic` | - -- 模型:qwen3.8-max、qwen3.7-plus、qwen3.7-flash、deepseek-v4-pro、kimi-k3、glm-5.2、MiniMax-M3 等(多厂商三方直供) - -### 1.2 智谱 GLM Coding Plan(个人版/团队版) -- **产品**:GLM Coding Plan,套餐抵扣 -- **Key**:智谱开放平台专属 API Key - -| 协议 | Base URL | -|---|---| -| OpenAI 兼容 | `https://open.bigmodel.cn/api/coding/paas/v4` | -| Anthropic 兼容 | `https://open.bigmodel.cn/api/anthropic` | - -- 模型:glm-5.2、glm-5.2[1m]、glm-4.7 等 -- Claude Code 用 `ANTHROPIC_BASE_URL` + `ANTHROPIC_AUTH_TOKEN` - -### 1.3 字节火山方舟 Coding Plan / Agent Plan -- **产品**:方舟 Coding Plan(编码专属)、Agent Plan(Agent 开发) -- **Key**:方舟控制台专属 Key - -| 协议 | Base URL | -|---|---| -| OpenAI 兼容(Agent Plan) | `https://ark.cn-beijing.volces.com/api/plan/v3` | -| Anthropic 兼容(Agent Plan) | `https://ark.cn-beijing.volces.com/api/plan` | -| OpenAI 兼容(Coding Plan) | `https://ark.cn-beijing.volces.com/api/coding/v3` | -| Anthropic 兼容(Coding Plan) | `https://ark.cn-beijing.volces.com/api/coding` | - -- 模型:doubao-seed-2.1-pro/turbo、doubao-seed-2.0-code、Seed-2.1-Turbo 等 - -### 1.4 Kimi(月之暗面)Kimi Code 会员 -- **产品**:Kimi Code 会员(¥39/¥79/¥159 档) -- **Key**:Kimi Code 专属 Key(与开放平台 `api.moonshot.cn` 不通用) - -| 协议 | Base URL | -|---|---| -| OpenAI 兼容 | `https://api.kimi.com/coding/v1` | -| Anthropic 兼容 | `https://api.kimi.com/coding/` | - -- 模型:kimi-for-coding(自动升级别名)、kimi-for-coding-highspeed、kimi-k3 - -### 1.5 MiniMax Coding Plan -- **产品**:MiniMax Coding Plan($10/月起,M2.5/M2.7/M3) -- **Key**:Coding Plan 专属 Key(`sk-cp...` 前缀,与普通按量不通用) - -| 协议 | 国际站 | 国内站 | +| 协议 | 端点 | 流式 | |---|---|---| -| Anthropic 兼容 | `https://api.minimax.io/anthropic` | `https://api.minimaxi.com/anthropic` | -| OpenAI 兼容 | `https://api.minimax.io/v1` | `https://api.minimaxi.com/v1` | - -### 1.6 DeepSeek(无订阅 Plan,纯按量 API) -- **产品**:无 Coding Plan,只有按量付费 API(充多少用多少) -- **Key**:普通 `sk-` 开放平台 Key - -| 协议 | Base URL | -|---|---| -| OpenAI 兼容 | `https://api.deepseek.com`(Chat Completions) | -| Anthropic 兼容 | `https://api.deepseek.com/anthropic` | -| **Responses API** | `https://api.deepseek.com`(`/responses`,唯一支持者) | +| OpenAI Chat Completions | `POST /v1/chat/completions` | ✅ SSE | +| OpenAI Responses | `POST /v1/responses` | ✅ SSE | +| Anthropic Messages | `POST /anthropic/v1/messages` | ✅ SSE | -- 模型:deepseek-v4-pro[1m](主模型)、deepseek-v4-flash(子代理) -- 说明:DeepSeek 是少数**原生支持 Responses API** 的国内厂商 +三协议**双向转换**(`src/protocol.rs` + `src/sse.rs`):客户端只需对接一个 OpenAI 兼容端点,网关按上游实际协议转发。流式场景同样跨协议转换(如 Anthropic → OpenAI SSE)。 ---- +## 2. 客户端接入 -## 2. API 协议类型清单(本项目需要覆盖的) - -| 协议 | 端点路径 | 流式 | 国内 Plan 支持度 | -|---|---|---|---| -| OpenAI Chat Completions | `POST /chat/completions` | SSE | ✅ 全部支持 | -| OpenAI Responses | `POST /responses` | SSE | ⚠️ 仅 DeepSeek/智谱按量 | -| Anthropic Messages | `POST /v1/messages` | SSE | ✅ 全部支持 | - -> 注:多数 Coding Plan 的 Anthropic 端点会自动拼 `/v1/messages`,故工具侧只需填 `.../anthropic` 或 `.../coding` 即可。 - ---- - -## 3. 下游客户端协议偏好(决定网关要暴露什么) - -| 客户端 | 首选协议 | 说明 | +| 客户端 | 首选协议 | 配置方式 | |---|---|---| | Claude Code | Anthropic | `ANTHROPIC_BASE_URL` + `ANTHROPIC_AUTH_TOKEN` | | Cursor | OpenAI | Override OpenAI Base URL | -| Cline / Roo Code | OpenAI 兼容 | Provider 设 OpenAI Compatible | -| Qwen Code / Qoder / OpenClaw / Kilo CLI | OpenAI 或 Anthropic | 视配置 | -| Codex | OpenAI Responses | 若接 Codex 需 Responses 适配 | - ---- +| Cline / Roo Code | OpenAI 兼容 | Provider 设为 OpenAI Compatible | +| Codex | OpenAI Responses | 用 Responses 端点 | -## 4. 对 AITokenPool 网关层的落地结论 +Base URL 统一由 AITokenPool 提供(`[server].public_url` 配置),设置页展示;`GET /v1/models` 返回模型与可用 key 列表。 -1. **第一版网关只做两个协议**:OpenAI Chat + Anthropic Messages(含 SSE 流式透传)。 -2. **Base URL 统一由 AITokenPool 提供**,下游客户端只需指向 AITokenPool 的单一端点,由网关按路由规则转发到具体上游 Plan 的端点。 -3. **上游协议映射表**(provider × plan 类型 → base url + 协议),作为 `providers`/`plans` 表的配置数据。 -4. **Responses API 后置**:除非要接 Codex 客户端,否则 P0 不做。 +## 3. 上游接入现状 ---- +- 上游 key 在「共享管理」页上架(provider + plan + model + key + 额度 + 可用时段) +- 模型价格由 `config/config.example.toml` 的 `[[models]]` 定义(唯一真源,启动 seed 入 `models` 表) +- 内置 DeepSeek 官方 CNY 定价(含高峰时段价);其余厂商可按同格式配置 +- 支持的 provider:deepseek、zhipu(glm)、openai、anthropic、google、bytedance、minimax、aliyun 等(随 `[[models]]` 配置扩展,无需改代码) -## 5. 参考数据源 +## 4. 模型目录 -- DeepSeek 官方定价页(已实抓):确认 OpenAI/Anthropic/Responses 三端点 -- 阿里云百炼 Token Plan 官方文档(Base URL 总览 / 快速开始) -- 智谱 Coding Plan 官方文档(接入工具) -- 火山方舟官方文档(接入三方工具 / Agent Plan) -- Kimi Code 会员指南 / MiniMax 官方文档 -- OpenRouter `/api/v1/models`(409 模型结构化定价,作国际厂商参考) +当前内置 13 个模型(DeepSeek / GLM / GPT / Claude / Gemini / 豆包 / MiniMax / 通义等),含 context window、vision 支持、缓存价与高峰价字段。模型列表可经管理端「模型管理」页 CRUD(需 admin 角色)。 diff --git a/docs/user-stories.md b/docs/user-stories.md index d545298..f012e8c 100644 --- a/docs/user-stories.md +++ b/docs/user-stories.md @@ -1,389 +1,52 @@ -# AITokenPool — 产品用户故事(Product User Stories) +# AITokenPool 产品能力 -> **本文档以中文撰写**(用户故事主体、验收标准、流程说明均为中文;关键术语保留中英对照)。 -> -> **v1.13(2026-08-17)· UI 演化约束:尽量少用弹窗 / modal.** 新增「UI 约定」章节(§1.1):优先行内(inline)交互(行内展开表单 / 可折叠面板 / 就地编辑),弹窗仅限真正需要聚焦 / 阻塞的场景(如删除确认),**禁止弹窗嵌套**;存量 modal(充值 topup-modal、申请加额 raise-modal、模型消费 chat-modal)标记改造优先级,后续迭代分批改为行内形态。部门添加/编辑已由弹层改为**行内展开表单**(`#dept-form-card`)。 -> -> **v1.14(2026-08-17)· 充值 / 加额改行内(P1 完成).** 按 UI 美化与 UE 优化 rant(`2026-08-17T15:50:05`)「少弹窗改造(优先)」:充值(原 topup-modal)与申请加额(原 raise-modal)改为钱包页**行内展开卡片**(`#topup-card` / `#raise-card`,点按钮原地展开、两卡互斥、取消即收起),替代弹层;P1 存量 modal 清零,仅剩 P2 模型消费聊天(chat-modal)。 -> -> **v1.15(2026-08-17)· A 视觉美化(rant `2026-08-17T15:50:05`).** 侧边栏导航 emoji → **统一内联 SVG 线性图标**(同尺寸、currentColor、hover/active 态);卡片 hover 微交互(阴影/边框轻提升);表格斑马纹 + 行 hover 高亮;**空状态组件**(图标 + 文案 + 行动按钮:市场清除筛选 / 共享上架新 key / 设置生成 key / 部门清除搜索);状态徽章加**语义色点**(ok/warn/danger/dim 一眼可辨);响应式加固(窄屏侧边栏折叠配合 SVG 图标、表格横向滚动)。 -> -> **v1.16(2026-08-17)· B 交互(UE)优化(rant `2026-08-17T15:50:05`).** **toast 分级**(成功 success / 错误 error / 信息 info,39 个调用点全部分级着色);**按钮 loading 态**(充值 / 加额 / 部门确认 / 上架提交 → 转圈 + 禁用,模拟反馈后恢复);**API Key 复制反馈**(复制后按钮短暂变「已复制 ✓」,1.2s 恢复,降级路径「请 Ctrl+C」);**键盘可达**(充值金额 / 加额金额·原因 / 部门名称·配额 Enter 提交;topup/raise/dept 行内卡片 Esc 关闭;打开时自动聚焦)。**rant 15:50:05 全部验收项满足,UI 美化与 UE 优化波收官(PR #38/#39/#40,docs v1.14→v1.16)。** -> **v1.17(2026-08-17)· 多角度 UI/UE 深化(rant `2026-08-17T16:57:17`,分批 PR).** **A. 清除原生弹窗 ✓(PR #41)**:约 5 处原生确认/输入弹窗(key 删除、共享下架、部门删除、API Key 新建/改名、运营者/成员充值)全部改为**行内二次确认**(按钮变「确认删除?」红色态,3 秒无操作或 Esc 还原,再次点击执行)与**行内编辑**(行内展开输入框,Enter 确认 / Esc 取消);抽象可复用 `confirmInline` / `inlineForm` 组件全站统一;`grep ui/` 无原生弹窗残留。**B. 相对时间显示 ✓(PR #42)**:新增 `timeAgo` 格式化(`刚刚 / N 分钟前 / N 小时前 / 昨天 / MM-DD`,hover `title` 显示完整绝对时间),交易列表、加额申请列表、共享列表(新增「上架时间」列)与 API Key 最近使用时间统一使用。**C. 数字列对齐 ✓(PR #43)**:价格 / 点数 / 已用 / 额度 / 余额等**数字列统一右对齐 + 等宽字体**(`--mono` + `tabular-nums`,新增 `.table .num` 类,覆盖市场输入/输出价与上下文、交易 Token 用量/点数、共享已用/额度·单价·收益、成员配额/剩余、部门成员数·月分配·已用·剩余、运营者余额、加额申请点数),时间列 / 状态列保持左对齐;金额统一 `D.fmt`(整数千分位、小数 2 位)全覆盖检查无遗漏。其余 D–G(`:focus-visible` 与快捷键、行内校验错误、视图过渡、细节一致性)分批落地。**D. 键盘可达性 / 无障碍 ✓(PR #44)**:全局 `:focus-visible` 焦点环(accent 色 outline,Tab 导航清晰可见;输入类控件沿用边框高亮不叠加);**全局快捷键**:`/` 聚焦市场搜索框(输入框内不触发)、数字 **1-7** 切换侧边栏视图(仪表盘/市场/共享/钱包/交易/管理/设置,带 title 与右侧键位角标提示,Cmd/Ctrl+数字 不劫持)、Esc 关闭行内新建 Key;侧边栏导航按钮补 `title`(快捷键提示)。**E. 表单行内校验错误 ✓(PR #45)**:新增 `setFieldError(input, msg)` / `clearFieldError(input)`(输入框**红边框** + 字段下方**红字小号行内文案**,输入修正自动清除,打开表单时重置);覆盖**充值金额**(自定义金额非法)、**申请加额**(点数/原因)、**部门表单**(名称/配额/重名)、**共享上架表单**(API Key/厂商·Plan·模型·额度),提交失败不再仅依赖 toast,聚焦首个错误字段。**F. 视图切换过渡 ✓(PR #46)**:页面切换加轻量动画(`.view:not(.hidden)` **fade + 轻微上移 6px,150ms** `viewIn`,替代生硬切换);数据表格更新无闪烁(`.table tbody` **fade-in** `tbodyIn`,新增 `pulseTbody` 在静态 tbody 重渲染后重启动画,动态表格整表重建自动生效)。**G. 细节一致性 ✓(PR #47)**:一致性审计确认——**所有数字/金额统一 `D.fmt`(千分位/2 位小数)**(侧边栏余额、统计卡、表格、钱包点数格式一致)、已用/额度展示统一;表格操作按钮统一小号样式(`padding:4px 10px;font-size:12px`);**行内编辑校验统一走行内错误**(inlineForm 校验失败由 toast 改为 `setFieldError` 红边框+行内文案,API Key 改名/运营者充值/成员充值 3 处对齐 item E);子文本字号统一(11px→12px);上架 toast 单价措辞统一「点/1M(自动)」;移除 3 处「(未生效)」残留文案。**rant 16:57:17 全部验收项满足(A–G 七项,PR #41–#47),UI/UE 深化波收官。** -> **v1.20(2026-08-17)· UI/UE 第五轮多角度深化(rant `2026-08-17T20:46:57`,分批 PR,进行中).** **A. 新用户首次引导 ✓(PR #63)**:首次登录(localStorage `atp-tour-done` 未标记)触发**轻量引导 tour**——4 步依次高亮:① 仪表盘(余额/趋势)→ ② 模型市场(浏览/使用)→ ③ 共享管理(上架赚点数)→ ④ 钱包/设置(充值、API Key、接入端点);实现为**非 modal 浮层**(`#tour-overlay` 半透明遮罩 + `#tour-ring` 目标 **accent 描边高亮环**(`tour-pulse` 呼吸动画,`prefers-reduced-motion` 下静止)+ `#tour-pop` 气泡卡片:右上「跳过」、底部「上一步/下一步/完成」(末步变完成)、步骤计数 `n / 4`);**步骤自动切视图**(`switchView(view, {sync:false})` 不入历史)并按目标 `getBoundingClientRect` 定位高亮环与气泡(视口内钳制);**Esc / 点浮层外 / 跳过 / 完成 均可关闭**,关闭即写 `atp-tour-done=1`(之后登录不再出现);设置页加**「重新查看引导」**按钮(`#tour-replay-btn`,`startTour()` 重放)。**B. 复制 Key 后下一步引导 ✓(待合入)**:复制 API Key **成功后**的 toast 变为**可交互**——文案 + 内嵌**「配置接入端点 →」按钮**(`toast()` 扩展 `opts.action = { label, onClick }`:innerHTML 渲染按钮 + 展示时长从 2.6s 延长至 **6s**,给用户留点击时间;普通 toast 零改动);点击按钮 → **`gotoEndpointCard()`**:`switchView("settings")`(已在设置页则幂等保持)+ `#endpoint-card` **高亮闪烁**(`.ep-flash`,accent 光圈 ×2 次 0.8s)+ `scrollIntoView` 滚动到卡片;配合 20:44:18 的端点卡片形成「复制 → 配置端点」完整链路。**C. 表格密度切换 ✓(PR #66)**:设置页「偏好」区新增**「表格密度」**两档单选(`input[name="density"]`,`#density-comfortable` **舒适(默认)** / `#density-compact` **紧凑**,`.density-options` 纵向小字布局,accent 圆点);**localStorage `atp-density` 记忆**(默认 `comfortable`),启动时还原并勾选对应 radio;切换即时生效——`#app` 加/移 **`.density-compact` 修饰类**,全站 `.table` 统一收紧:`th/td` padding 10px/8px→**4px 8px**、`td` 字号 12px、表头 11px、行内按钮 11px(舒适档维持原样,零改动);适合 Key 列表/交易明细等长表格提升信息密度。**D. 市场「最近使用」✓(PR #67)**:市场工具栏下新增**「最近使用」行**(`#mk-recent`,工具栏计数下方、表格上方):**localStorage `atp-recent-models`** 记录最近 **5 个去重**模型 id(复用模型即**置顶去重**,最旧溢出),**复用 `.chip` 药丸**(hover accent 高亮、`--mono` 模型名 + title 显示厂商);**点击 chip 直接打开该模型聊天**(复用 openChat,同「使用 / 消费」主操作;游客点击提示先登录);「清空」小按钮(`data-mk-recent-clear`)一键清空记录并隐藏该行;`openChat` 内即时 `renderRecent()`(使用后 chips 立即更新),进入市场页(`renderMarketplace`)时从 storage 还原;行内删除/重置不破坏数据。**E. 交易记录导出 CSV ✓(PR #68)**:交易页 tab 下方新增右对齐 **「导出 CSV」按钮**(`#tx-export-btn`,ghost 小按钮,title 说明「导出当前筛选的交易记录」);`exportTxCsv()` 把**当前筛选可见的交易**(tab 过滤 + 列筛选 `filterRows`,与表格/汇总条同一数据源)导出为 CSV:**UTF-8 BOM**(`\uFEFF`,Excel 中文不乱码)+ `\r\n` 换行 + 表头「时间,类型,模型 / Key,Token 用量,点数,状态」(类型映射 `TX_TYPE` 中文,点数带正负号原值,字段含 `,`/`"`/换行时按 RFC4180 双引号转义);**Blob + `a[download]`**(`URL.createObjectURL` → 临时 `` click → 移除 → 1s 后 revoke);文件名 **`aitokenpool-transactions-YYYYMMDD.csv`**;无数据时 toast「没有可导出的交易记录」不导出;导出成功 toast「已导出 N 条交易记录」。**F. 数据表格键盘导航 ✓(PR #69)**:所有数据表格(市场 / 共享 / API Key / 员工 / 部门 / 运营者 / 交易记录,`KBD_TABLE_IDS`)支持**纯键盘操作**——点击任意行激活(或直接 Tab 进表格后按方向键):**↑/↓ 行高亮 `.row-active`**(accent 左侧竖条 + 柔光底,随行 `scrollIntoView`,自动跳过展开详情行 `.mk-detail`,未激活时 ↓ 从首行 / ↑ 从末行开始),**Enter 触发该行主操作按钮**(行内第一个可用 `button.btn`,排除行展开 `+/-`;市场=使用/消费、API Key=复制、部门=编辑、运营者=充值…disabled 按钮不触发),**Esc 清除高亮**(无高亮时 Esc 落到原有逻辑:关帮助/关行内表单等);表格间切换自动跟随点击/焦点所在表格(`kbdContainerFrom` 沿 closest tbody/table 解析,`#tx-table` 这类包 table 的容器也识别);点击行内任何按钮同时激活该行,快捷键 `?` 帮助面板与 1-7 视图切换不受影响(先过 typing/meta 守卫)。**G. 品牌与登录页氛围 ✓(PR #70)**:登录页加**渐变网格背景**(`.login-view::before` 44px 淡色网格,径向 mask 边缘淡出)+ **微光浮动**(`.login-view::after` accent 微光圆,`login-float` 10s 位移+缩放交替动画,`prefers-reduced-motion` 静止由全局规则覆盖)+ 卡片 `z-index:1` 浮于氛围层之上;**logo 渐变描边/发光**(`.logo` 加 accent 描边 ring + 14px 外发光,`::after` 顶部内高光/底部内阴影,登录页与侧边栏统一);**favicon inline SVG data URI**(`` 渐变圆角方块 + AT 文字,零外部文件)。**rant 20:46:57 全部验收项满足(A–G 七项,PR #63/#65/#66/#67/#68/#69/#70),UI/UE 第五轮深化波收官,docs v1.20。** -> -> **v1.22.1(2026-08-19)· 设置页 API Key 修复(rant `2026-08-19T18:06:25`,PR #95).** **① 标题去重**:zh 包 `settings.apikey` 误写「API Key API keys」→ 改「API Key」。**② 复制 key 随时可用**:后端 `GET /api/api-keys` 列表新增**属主可见 `full_key` 字段**(展示仍用脱敏 `key`,复制取完整值);前端 `copyKey()` 改为从列表数据取 `full_key`,**删除**「完整 key 仅在生成时展示一次,请重新生成」逻辑与 `Live.fullKeys` 会话缓存(刷新/重进页面仍可复制);删除 i18n `settings.ak.copy.once`(zh/en);复制失败时防御性退化为复制脱敏 key。**验收**:设置页标题不重复;生成 key 后刷新页面点复制 → 成功复制完整 key。**rant 18:06:25 全部验收项满足,docs v1.22.1。** -> **v1.19(2026-08-17)· 设置页「API 接入端点」卡片(rant `2026-08-17T20:44:18`).** 设置页新增**「接入方式 / API 端点」卡片**(`#endpoint-card`,放在 API Key 卡片**上方**——先看端点再生成 key):**OpenAI 兼容** `https://gateway.aitokenpool.local/v1`(Chat Completions · Cursor / Cline / Roo Code / OpenCode / OpenAI SDK)与 **Anthropic 兼容** `https://gateway.aitokenpool.local/anthropic`(Messages API · Claude Code / Goose / OpenClaw)各一行——协议标签(accent 药丸)+ **等宽可整段选中** URL(`user-select:all`)+ **复制按钮**(复用 copyKey 降级链:clipboard API → `execCommand("copy")` → 提示 Ctrl+C,带「已复制 ✓」flash)+ 说明小字;URL 旁小注「部署后替换为你的网关域名」(原型占位);卡片内**使用步骤** ① 生成 API Key → ② 工具 Base URL 填端点 → ③ 填 key;端点为 **UI 静态常量** `API_ENDPOINTS`(注释标明真实值来自部署配置,后端实现时接入 `config.server.base_url`);窄屏端点行纵向堆叠 + URL 自动换行。 -> **v1.19(2026-08-17)· UI/UE 第四轮多角度深化(rant `2026-08-17T20:39:30`,分批 PR,进行中).****A. URL hash 路由 ✓(PR #55)**:视图与地址栏 hash 联动——`#/marketplace`、`#/wallet` 等视图 hash 可**直接收藏 / 分享 / 刷新恢复**;规则:① 视图切换(导航 / 快捷键 1-7 / 登录恢复)同步 `history.pushState` 更新 hash(已相同不重复入栈,不触发 hashchange 回环);② **前进 / 后退**(hashchange)视图跟随切换;③ **非法 hash** 回退仪表盘视图但**不重写 URL**(避免 pushState 污染历史、后退需两次);④ 空 hash 不动作(无 hash 时保持默认行为);⑤ 刷新后登录自动恢复 hash 对应视图(游客浏览 / 未登录态无冲突);⑥ 游客受限视图 hash 被拦截时保持原视图、不入栈。**B. 交易记录汇总条 ✓(PR #56)**:交易页卡片顶部加**紧凑汇总条**(`.tx-summary`,三列 inline:总收入 / 总支出 / 净变化,+绿 −红,零值中性显示 `0`);**随 tab 过滤联动**——「全部 / 消费 / 收益」tab 切换即时重算,且**与表格列筛选一致**(抽公共 `filterRows(rows, columns, filters)` 供 `buildDataTable` 与汇总共用,汇总反映与表格可见行相同的过滤集,不受分页影响);窄屏自动换行收窄。**C. 原生 select 美化 ✓(待合入)**:全站 `select` 去掉浏览器原生箭头,改**自定义 SVG 下拉箭头**(`--select-arrow` CSS 变量,内联 data-URI,深/亮主题各一色),`appearance:none` + `padding-right` 预留箭头空间;**hover / focus 边框同 input**(`var(--accent)`,focus 加 1px 光圈);`disabled` 态降透明度;覆盖全部 select 来源——静态 `.input`(市场筛选 `#mk-provider`/`#mk-sort`、共享表单 `#sf-provider/plan/model`、设置语言/默认模型)、动态 `select.th-filter`(表格列筛选)、`select[data-page-size]`(分页每页条数);`option` 深色背景与 `input-error` 错误态保留。**D. toast 队列堆叠 ✓(待合入)**:单例 toast 改为**队列容器** `#toast-wrap`(固定底部居中,纵向堆叠,`gap:10px`,`pointer-events:none` 不拦截点击);`toast(msg, type)` 每次**创建独立元素**(不再覆盖旧消息),**最多同时 3 条**(超限立即移除最旧一条腾位),每条**独立生命周期**——到时(2.6s)加 `.out` 淡出(0.2s `toast-out` 动画)后移除,互不影响;**分级样式保留**(success/error/info 边框色与文字色不变,39 个调用点零改动);toast 自身 `pointer-events:auto` 为后续可交互 toast 预留。**E. 快捷键帮助面板 ✓(待合入)**:按 **`?`**(或 `Shift+/`)在右上角弹出**行内卡片**(`#help-panel`,非 modal、无遮罩、不阻塞页面)展示快捷键速查:`/` 聚焦市场搜索、`1–7` 切换视图、`Esc` 关闭/取消、`?` 开合面板;**Esc 或再按 `?` 关闭**(帮助打开时 Esc 优先于行内表单,不会误关「新建 Key」);面板底部显示**当前上下文**(当前视图 + 亮/深色主题);输入框内按 `?` 不劫持(typing 守卫,正常输入字符);关闭按钮 ×;窄屏(≤560px)全宽贴顶。**F. 市场模型行展开详情 ✓(待合入)**:市场表格每行首列加 **`+`/`−` 展开按钮**(`.row-expand`,hover accent);点击在 **tr 下追加详情行**(`.mk-detail`,`colspan=7` 浅底网格,行内展开不弹窗)展示:**Max tokens**(单次输出上限,模型未公布显示「未公布」)、**价格换算**(`1M tokens ≈ N 点` 按输出价 + 输入价/1M)、**上下文长度**、**可用性**(可用/繁忙 + 成功率)、**多 key 自动故障转移说明**(仅 `multi` 模型显示,架构 v0.2 路由策略);**仅展开当前行**(点其它行自动收起,再点收起),展开态存 `mkExpanded` 数据(搜索/筛选重渲染后保留)。**G. 登录页 polish ✓(待合入)**:登录卡片视觉微调——**logo 加大**(52px + 渐变微光 `0 0 18px rgba(78,205,196,.35)`)、**品牌标题层次**(h1 22px + 副文案行高)、**输入框聚焦光晕**(`0 0 0 3px var(--accent-soft)`,双主题适配);**空邮箱/密码提交行内错误**(复用 `field-error` 组件:红边框 + 行内文案,聚焦首个错误字段,输入修正自动清除,`novalidate` 自管校验);**「记住我」checkbox**(`#login-remember`,localStorage `atp-remember` 记忆,加载时还原)+ **演示模式说明小字**(`demo-hint`:demo@aitokenpool.local / demo1234)。**rant 20:39:30 全部验收项满足(A–G 七项,PR #55–#61),UI/UE 第四轮深化波收官,docs v1.19。** -> **v1.18(2026-08-17)· UI/UE 第三轮多角度深化(rant `2026-08-17T18:06:09`,分批 PR).** **A. 仪表盘数据可视化 ✓(PR #48)**:纯 SVG sparkline(零外部依赖,手写 path,颜色用现有 CSS 变量):「本月点数变化」卡片按天聚合近 7 日净变化画迷你折线图(渐变填充,每点 `` hover 显示当天数值);「我的共享」卡显示共享收益累计趋势 sparkline(`--ok` 色),无上架 key 时保留空状态不画图。**B. 亮色主题 ✓(PR #49)**:CSS 变量重构——新增 `:root[data-theme="light"]` 全套变量重定义(--bg/--bg-card/--border/--text 等),并把原先硬编码颜色(表格行边框/斑马纹、卡片 hover 阴影、确认态、spinner、遮罩)抽为语义变量(--table-row-border/--table-stripe/--card-hover-border/--card-shadow/--danger-soft/--danger-text/--spin-track/--overlay)双主题共用;侧边栏加**日/月 SVG 切换按钮**(按当前主题显隐图标),**localStorage 记忆**(atp-theme),首次加载尊重 **`prefers-color-scheme`**;两主题对比度均达标(正文/次要文字/边框层次清晰)。**C. 移动端表格卡片化 ✓(PR #50)**:`@media (max-width: 560px)` 下关键表格(市场/共享/交易/管理/设置 API Key)**隐藏表头**,每行渲染为**卡片**(`label: value` 布局,`td::before` 取 `data-label`),不再横向滚动;卡片内主字段加粗、状态徽章保留、操作按钮整行宽(`flex: 1 1 45%` 换行);全部表格 td 补齐 `data-label`(含 buildDataTable 动态列用 col.title)。**D. 搜索增强 ✓(PR #51)**:全部搜索框(市场 `#mk-search` / API Key `#ak-search` / 部门 `#od-search` / 运营者用户 `#ops-search`)统一接入 **~150ms 输入防抖**(避免每次按键整表重绘闪烁,连续输入只渲染一次);渲染结果对匹配关键词**大小写不敏感 `<mark>` 高亮**(先 HTML 转义再包裹,`--accent-soft` 底 + `--accent-text` 字,双主题对比度达标;清空后自动清除);搜索框加**「清空 ×」小按钮**(有内容时显示,点击清空立即重绘并聚焦输入框;空状态「清除搜索/清除筛选」按钮同样同步 × 态)。**E. 动效与系统偏好 ✓(PR #52)**:按钮 **`:active` 轻微下压**(`scale(0.98)`,disabled 不触发);统计卡 **hover 微抬升**(`translateY(-2px)` + 边框/阴影提升,与卡片 hover 语言一致);**数字/点数变化轻微跳动动画**(新增 `bump(el)` 助手——remove→reflow→add `.bump` 类重放 `numJump`(`translateY(-3px) scale(1.02)`,0.35s);接入 4 处余额变化点:钱包充值(侧边栏+钱包余额)、聊天消费扣款、加额批准、运营者给自己充值);**尊重 `prefers-reduced-motion: reduce`**——全局 `animation-duration/transition-duration` 压到 0.01ms,禁用过渡/动画但保留全部功能。**F. 动态文档标题 ✓(PR #53)**:`document.title` **跟随视图切换**(`switchView` 内统一设置「视图标题 · AITokenPool」,如「模型市场 Marketplace · AITokenPool」;`VIEW_TITLE` 7 个视图全覆盖;未知视图回退「AITokenPool」);**默认「AITokenPool」**——首次加载(DOMContentLoaded)与登录页/无视图态回默认标题,HTML `<title>` 同步改为「AITokenPool」;游客受限视图被拦截时标题保持不变。**G. 其他细节 ✓(验证确认,PR #54 收尾)**:① **视图切换滚动复位**——`switchView` 内 `$("#main").scrollTop = 0`(`.main` 即 `overflow-y:auto` 滚动容器,渲染后复位,多次切换均生效,DOM 冒烟验证);② **复制按钮「已复制 ✓」态**——`copyKey` 的 flash 反馈(复制成功按钮短暂变「已复制 ✓」并禁用,1.2s 恢复;降级路径「请 Ctrl+C」;v1.16 已实现,DOM 冒烟验证)。**rant 18:06:09 全部验收项满足(A–G 七项,PR #48–#54),UI/UE 第三轮深化波收官,docs v1.18。** -> **v1.12(2026-08-17)· 移除「组织设置 Organization settings」表单.** 组织管理页只保留部门列表(部门 CRUD + 每月点数分配),删除底部「组织设置」表单(组织名称 / 默认成员配额 / 开关)。「关闭外部注册」属**部署配置项,不在 UI 中设置**(US-16 标注);「成员自助申请加额需管理员审批」开关移除后,申请加额流程**默认需审批**(US-20 说明)。 -> **v1.11(2026-08-17)· 管理视图移除独立「Key 池」管理,统一走「上架 key」.** 管理员与普通用户一样通过**共享管理页「上架新 key」**(选厂商 → Plan → 模型、填 key、声明额度、可用时间段)配置上游 key——企业场景下管理员上架、员工消费,本质上就是 key 池;不再有独立的管理员 Key 池界面。移除 Admin「Key 池」tab(成员管理 / 用量报表 / 组织管理 / 平台运营保留)。「Key 池」保留为**数据层概念**(平台持有的上游 key 集合,见 docs/architecture.md 4.2)。更新 US-12 / 企业流程 / 对齐表。 -> **v1.10(2026-08-17)· 上架表单"可用时间段"结构化.** 上架 key 的可用时间段改为**正式字段**(星期多选 + 起止时间,可多选;留空 = 全天不限),后端可解析生效;**备注只作纯文本**,不承载任何逻辑。共享列表展示可用时间段(如「周一~周五 09:00-18:00」),未设置显示「全天」。更新 US-8 / US-9 AC。 -> **v1.9(2026-08-17)· 上架流程改为「厂商 → Plan → 模型」.** 分享者上架时选择的是**厂商的 Plan**(而不是厂商/模型):大多数分享的是自己的 Plan 订阅(如阿里 Token Plan、Kimi Code),同一厂商不同 Plan 的 Base URL 可能不同。上架表单改为三级联动「选厂商 → 选 Plan → 选该 Plan 支持的模型」,Plan 下拉中「API(按量)」代表按量计价的 key,其余为订阅 Plan;内置国内已知 Plan 清单(阿里云百炼 / 智谱 / 火山方舟 / Kimi 月之暗面 / MiniMax / DeepSeek,每家至少一个「API(按量)」项)。共享列表展示「厂商 · Plan / 模型」。更新 US-8 / US-9 / 核心机制表「上架 Listing」行。 -> **v1.8(2026-08-17)· 移除面向用户文案中的防薅表述,文档措辞中性化.** 「防薅羊毛」是产品内部设计动机,不应出现在面向用户的界面文案中(UI 侧已同步移除)。本文档中的设计备注措辞中性化:「防薅动机」改为「设计意图」(如每日赠送机制的设计意图是**鼓励每日活跃**,同时降低集中注册多号的收益)。面向用户可见的赠送规则保持「每日赠送 1 点(当日有效)· 连续 10 天」。更新核心机制表「赠送点数」行措辞。 -> **v1.7(2026-08-15)· 平台收益抽成 10%.** 平台从分享者收益中抽取 **10%**:消费者支付 N 点 → 分享者获得 **N × 90%**(按小数点数规则,保留 2 位小数)、**N × 10% 归平台**。示例:A 消费 B 的 key 10 点 → A 扣 10 点、B 收益 9 点、平台分 1 点。核心机制表新增「平台抽成 Platform fee」;分享者收益相关 AC 更新(收益 = 消费点数 × 90%);新增边界场景 **E-16**(小数抽成精度,如消费 3 点 → 收益 2.7 点);平台运营者角色补充:平台分成是运营收入来源。 -> **v1.6(2026-08-15)· 点数锚定改为人民币(CNY).** **1 点 ≈ 1 元人民币**(替代旧规则 1 USD = 1,000 点);**消费点数可为小数**(按 token 用量 × 模型单价精确计费,可能产生小数点数;余额与交易金额保留 2 位小数,四舍五入)。模型定价:**CNY 模型直接 1 元 = 1 点**(如 GLM-5.2 输出 28 元/百万 → 28 点/百万);**USD 模型按 ~7.2 汇率折算为人民币点数**(如 OpenAI 输出 $25/百万 ≈ 180 点/百万)。更新 US-1 / US-2 / US-6 / US-23 / 对齐表;新增 **E-15**(小数计费精度)。 -> **v1.5(2026-08-15)· 改用中文撰写.** 全文主体改为中文:产品模型、角色定义、用户故事(「作为〈角色〉,我希望〈能力〉,以便〈价值〉」格式)、关键流程、边界场景等均以中文书写;关键术语中英对照(点数 Points、Key 池 Key pool、上架 Listing、消费 Consumption、收益 Earnings、API Key);用户故事与验收标准(AC)用中文;保留 mermaid 流程图(图中文字中文化)。**内容与 v1.4 完全一致,仅语言变化,不引入新机制。** -> **v1.4(2026-08-15)· 修正新人赠送机制.** 旧的「注册即送 10 点(1 周有效)」**替换**为**每日赠送机制**:**每天送 1 点**(每日 1 点),每次赠送的点数**有效期 1 天**(当日有效,过期清零),**注册起连续 10 个自然日**每天发放 1 点(10 天后停止);用户需**每天登录 / 回来**才能领取当日 1 点——未领取日的点数**不发、不积累**。不变:分享收益点数永久有效;未来充值点数永久有效;消费扣减顺序先扣有有效期的点数。设计意图:鼓励每日活跃,降低集中注册多号的收益。更新 US-3 / US-22 / US-23 / 流程 J-1 / 边界场景 E-13;新增 **E-14**(当日赠送未领取)。 -> **v1.3(2026-08-14)· 明确平台运营者角色(运营者 = 宿主本人).** 运营者是**部署者 / 拥有者(宿主本人)**,职责仅两项:**① 查看平台运行情况**(运行状态 / 用户数 / 共享 key 数 / 交易量 / 点数流动)和 **② 给指定用户充值点数**(永久有效点数,产生交易记录)。内容审核 / 违规处理 / 市场调节**明确排除**——保持最小。新增 US-运营1 / US-运营2(替换「规划中 Planned」占位)。 -> **v1.2(2026-08-14)· 点数机制定案(纯分享经济).** 每个注册用户赠送 **10 点**(新人体验券)有效 **1 周**;分享收益点数**永久有效**;未来充值点数**永久有效**。消费**先扣有有效期的(赠送)点数**。新增 US-22/23/24 与边界场景 E-13(赠送点数过期)。 -> **v1.1(2026-08-14)· 结构调整.** 文档改为**先按部署场景、再按用户类型**组织(场景 → 用户类型 → 故事):`## 公共场景 Public` / `## 企业场景 Enterprise`,每个场景下列出其用户类型及 Goals / Pain points / User stories / Key flows。复用 v1.0 内容,将归属重新按场景划分。 -> **v1.0(2026-08-14)· 初始版本**(平铺的角色布局)。 -> 核心产品设计文档。UI / 后端实现均以此文档为准。与 [docs/architecture.md](./architecture.md) 及 [`ui/`](../ui/) 中的 UI 原型对齐。 +> 简明版:角色、核心流程、能力清单(详细的访谈式用户故事已收敛,历史见 git)。 ---- +## 1. 角色 -## 1. 产品模型与术语(Product Model & Terminology) - -**一套产品,两种部署场景**(不是两套功能): - -- **公共版(Public edition)** — 部署在公网。任何人都能注册、分享闲置 API key 赚点数、用点数消费别人共享的模型。新注册用户进入**每日赠送机制**:**每天 1 点赠送点数**(仅当日有效),**注册起连续 10 个自然日**——详见下方核心机制表。 -- **企业版(Enterprise edition)** — 部署在企业内网。管理员(IT)把采购的 key 放进 key 池,给成员分配每月点数配额。 - -功能集合**完全相同**;差异只在*谁有动力分享*(公共版人人可分享;企业版只有管理员)。**角色是权限差异,不是产品差异**——管理员额外拥有管理视图(key 池 / 成员 / 用量报表 / 组织),普通用户没有。 - -### 1.1 UI 约定:尽量少用弹窗(UI Principles) - -> **v1.13 定案**(宿主 2026-08-17 指示,rant `2026-08-17T14:34:19`):整个系统**尽量少用弹窗 / modal**。 - -- **优先行内(inline)交互**:表单、编辑、确认等操作优先在当前页面 / 区域内展开(行内展开表单、可折叠面板、就地编辑),而非弹窗; -- **弹窗仅限真正需要聚焦 / 阻塞的场景**:如必须确认的重要操作(删除)、需要专注输入的少量场景;**禁止弹窗嵌套**(弹窗内不得再开弹窗); -- **替代形态**:表单 / 编辑 → 行内展开、抽屉(drawer / 侧滑)、或就地编辑;确认 → 行内二次确认(按钮变「确认?」态)或轻量 toast + 撤销;选择 / 搜索 → 行内下拉或独立页面; -- **存量 modal 改造进度**(rant `2026-08-17T15:50:05` 系统性 UI/UE 优化波,分批推进): - - **P0 高频 ✓**:上架表单(`#share-form-card` 行内卡片)、部门添加/编辑(`#dept-form-card` 行内卡片) - - **P1 ✓(2026-08-17)**:充值(`#topup-card` 行内卡片,替代 topup-modal)、申请加额(`#raise-card` 行内卡片,替代 raise-modal)——钱包页点按钮原地展开,两卡互斥 - - **P2**:模型消费聊天(chat-modal → 独立页或行内面板,待后续迭代) -- **原生弹窗清零 ✓(rant `2026-08-17T16:57:17` A,v1.17)**:删除/下架/部门删除等确认一律走**行内二次确认**(按钮变「确认删除?」红色态,3 秒无操作或 Esc 还原);新建/改名/充值等输入一律走**行内编辑**(输入框 Enter 确认 / Esc 取消);抽象复用 `confirmInline` / `inlineForm` 组件,`grep ui/` 无原生 confirm/prompt 残留。 -- 该原则约束后续所有 UI 演化;与 UI 原型(`ui/`)对齐。 - -### 核心机制(Core mechanism) - -| 术语 Term | 定义 Definition | -|---|---| -| **点数 Point** | 平台的计价单位。**1 点 ≈ 1 元人民币(CNY)**(替代旧规则 1 USD = 1,000 点)。**消费点数可为小数**——按 token 用量 × 模型单价精确计费,可能产生小数点数(如一次消费 0.37 点);余额与交易金额显示保留 **2 位小数**(四舍五入)。 | -| **模型定价 Model pricing** | **CNY 模型直接 1 元 = 1 点**(如 GLM-5.2 输出 28 元/百万 tokens → 28 点/百万);**USD 模型按 ~7.2 汇率折算为人民币点数**(如 OpenAI 输出 $25/百万 tokens ≈ 180 点/百万)。参考单价 = 模型输出价(点数 / 1M tokens)。 | -| **赠送点数 Gift points** | 新用户**每日赠送机制**:**每天 1 点**(每日 1 点),**注册起连续 10 个自然日**;每次赠送的点数**有效期 1 天**(当日有效,过期清零)。用户需**当天登录 / 回来领取**——未领取日的点数**不发、不积累**,第 10 天后停止赠送。设计意图:鼓励每日活跃,集中注册多号收益低。 | -| **收益点数 Earned points** | 分享 key 赚取的点数;**永久有效**——无有效期。 | -| **充值点数 Top-up points** | 未来充值获得的点数;**永久有效**(充值功能当前暂不支持,但规则先定)。 | -| **扣减顺序 Deduction order** | 消费**先扣有有效期的(赠送)点数**,再扣永久点数——有效期内点数不浪费,永久点数不会因过期竞争而损失。 | -| **Key 池 Key pool** | 平台托管的模型上游 API key(静态加密存储)。企业版:管理员上传;公共版:分享者上传。 | -| **上架 Listing** | 分享者上架一个闲置 key(选择**厂商 → Plan → 模型**,Plan 下拉中「API(按量)」代表按量计价的 key,其余为订阅 Plan;内置国内已知 Plan 清单)并声明配额。**单价不由分享者设定**——平台按模型价格表自动定价(参考单价 = 模型输出价,点数 / 1M tokens)。 | -| **消费 Consumption** | 用户花点数通过平台调用模型(聊天 / API)。 | -| **收益 Earnings** | 有人通过分享者的 key 消费时,分享者赚取点数(消费点数 × 90%,见「平台抽成」)。 | -| **平台抽成 Platform fee** | 平台从分享者每笔收益中抽取 **10%**:消费者支付 N 点 → 分享者获得 **N × 90%**、**N × 10% 归平台**。示例:消费 10 点 → 分享者得 9 点、平台分 1 点。抽成后金额按小数点数规则保留 2 位小数(如消费 3 点 → 收益 2.7 点)。平台分成是运营收入来源。 | -| **API Key (atk_)** | 平台签发的 key(`atk_live_…`),让用户 / 脚本调用平台 API。在设置页管理。 | -| **配额 / 分配 Quota / allocation** | 企业版:每个部门、每个成员的每月点数配额。 | -| **管理视图 Admin view** | 仅角色可见的视图:key 池管理、成员管理、用量报表、组织(部门)管理。 | - -### 架构(Architecture,from docs/architecture.md) - -集中式(方案 A):**平台托管 key 并执行调用**——平台是唯一可信执行者。计量可信、响应真实(直连上游)、无篡改 / 作弊面。分层:网关 Gateway(axum)· Key 池(加密)· 计量引擎(token 计数)· 账本 Ledger(点数)· 市场 Marketplace(分享)· 管理控制台 Admin console(Web)。 - ---- - -## 2. 公共场景(Public Scenario) - -> **场景说明**: 公共版部署在**公网**——任何人都能注册、分享闲置 key、用点数消费模型。**人人都有分享动机**(把闲置订阅配额变现),所以分享市场是这个场景的核心。注册开放;角色由账号决定(平台运营者 = 宿主本人,见 §2.4,职责最小化仅两项)。功能集合与企业版相同;只有*谁分享*不同。**点数模型(v1.6): 1 点 ≈ 1 元 CNY,消费点数可为小数;公共版当前无充值渠道——新用户靠每日赠送机制(1 点 / 天,1 天有效,连续 10 天)起步,长期点数靠分享(永久有效)。** - -### 2.1 用户类型 A — 访客 / 新用户(Visitor / New User:未注册,浏览了解) - -#### 目标(Goals) - -- 了解 AITokenPool 是什么、点数怎么运作、有哪些模型、价格如何。 -- 以最小摩擦注册 / 登录并开始使用平台。 - -#### 痛点(Pain points) - -- 不知道 AI token 共享怎么运作;担心泄露自己的 API key;定价不透明;注册摩擦大(还没看到任何东西就先要选套餐)。 - -#### 用户故事(User Stories) - -- **US-1** 作为访客,我希望注册前先浏览模型市场,以便评估模型与价格再决定是否加入。 - - AC:市场无需登录即可浏览;搜索、厂商筛选、排序(价格 / 上下文)可用;价格以点数展示(CNY 锚定,1 点 ≈ 1 元),USD 模型按汇率折算展示人民币参考。 -- **US-2** 作为访客,我希望看到点数机制的清晰说明(1 点 ≈ 1 元人民币),以便决定是否加入。 - - AC:落地页 / 登录页可见点数机制说明;锚定关系(1 点 ≈ 1 元 CNY)明确写出;说明消费点数可为小数(按 token 用量精确计费)。 -- **US-3** 作为新用户,我希望用邮箱注册 / 登录,以便开始使用平台。 - - AC:单一登录入口(登录时不做公共 / 企业二选一);注册创建的账号进入**每日赠送机制(1 点 / 天,1 天有效,连续 10 天)**;角色(管理员 vs 用户)由账号决定。 - -#### 关键流程(Key Flow)— 浏览 → 了解 → 注册 - -```mermaid -flowchart LR - A[进入平台] --> B[免登录浏览模型市场] - B --> C[了解点数机制] - C --> D[注册 / 登录] - D --> E[账号创建 + 每日赠送机制启动:连续 10 天每天 1 点] -``` - -1. 访客进入登录页,先浏览模型与价格(US-1、US-2)。 -2. 用邮箱注册 → 账号进入每日赠送机制(US-3、US-22);继续进入普通用户流程(J-1)。 - -### 2.2 用户类型 B — 普通用户 / 消费者(Regular User / Consumer:注册,用点数消费模型) - -#### 目标(Goals) - -- 获取点数(充值 / 赚取)、浏览市场、用点数消费模型(聊天或 API)、跟踪余额与交易。 - -#### 痛点(Pain points) - -- 任务中途余额耗尽;没有单一入口看支出 vs 收益;昂贵旗舰模型快速消耗点数;不确定哪个共享 key 可靠。 - -#### 用户故事(User Stories) - -- **US-4** 作为普通用户,我希望充值点数,以便消费模型。 - - AC:钱包显示当前余额与点数来源(赠送 / 收益 / 充值);充值流程是占位(按当前原型:充值 / 提现暂不支持,「即将上线」)——公共版尚无充值渠道;新用户靠每日赠送机制(US-22)。 -- **US-5** 作为普通用户,我希望搜索 / 筛选 / 排序市场,以便快速找到需要的模型。 - - AC:按模型 / 厂商搜索;按厂商筛选;按输入价升 / 降序与上下文大小降序排序;显示可用性。 -- **US-6** 作为普通用户,我希望用点数消费模型(聊天 / API),以便不拥有上游 key 也能使用模型。 - - AC:选择可用模型打开聊天 / API 入口;消费按计量 tokens × 模型价格扣点(**可为小数**,如 -0.37 点,保留 2 位小数);产生「消费」交易记录;余额不足时阻断请求并给出清晰提示。 -- **US-7** 作为普通用户,我希望查看我的交易记录,以便核对支出与收益。 - - AC:交易记录页是消费 / 收益 / 充值 / 提现的**唯一明细来源**;Tab(全部 / 消费 / 收益)+ MRT 风格表格(列排序、列筛选、分页);钱包页链接到它。 -- **US-22** 作为新注册用户,我希望收到每日赠送点数,以便立刻体验模型消费。 - - AC:注册启动**每日赠送机制**——**连续 10 个自然日每天 1 点**;每次赠送的点数**有效期 1 天**(当天有效,过期清零),需当天登录领取(未领取日**不发、不积累**);钱包显示来源「赠送(gift)」与当前天数(如「今日赠送 +1 · 连续第 N 天 / 共 10 天」)。 -- **US-23** 作为普通用户,我希望看到点数的来源与有效期,以便规划使用。 - - AC:钱包 / 交易记录能区分**赠送 / 收益 / 充值**点数来源及其有效期(如「赠送 +1 · 有效期至今日」「收益 320 · 永久」);金额显示**保留 2 位小数**(如 0.37、320.00);消费先扣有有效期的(赠送)点数。 - -#### 关键流程(Key Flow)— J-1: 注册 → 首次消费 - -```mermaid -flowchart LR - A[访客浏览市场] --> B[注册 / 登录] - B --> C[每日赠送机制:+1 点 · 1 天有效 · 连续 10 天] - C --> D[市场:搜索 / 筛选 / 排序] - D --> E[选模型 - 可用性 OK] - E --> F[消费:聊天或 API] - F --> G[扣点 - 先扣赠送,记录消费交易] - G --> H[查看余额 + 交易记录] -``` - -1. 访客进入登录页,先浏览模型与价格(US-1、US-2)。 -2. 用邮箱注册 → 账号进入每日赠送机制——连续 10 天每天 1 点(1 天有效)(US-3、US-22)。 -3. 公共版尚无充值渠道(US-4 占位);用赠送点数起步。 -4. 搜索 / 筛选 / 排序市场(US-5)。 -5. 选择可用模型,通过聊天 / API 消费(US-6)。 -6. 按计量 tokens 扣点——先扣赠送点数;到交易记录页核对(US-7、US-23)。 - -### 2.3 用户类型 C — 分享者(Sharer:普通用户的行为角色,上架闲置 key 赚点数) - -#### 目标(Goals) - -- 几秒内上架一个闲置 key(厂商 / 模型 / 声明配额 / key——仅此而已),让平台定价,别人消费时赚点数,监控收益,随时暂停 / 恢复 / 重新上架 / 删除。 - -#### 痛点(Pain points) - -- 担心 key 安全(平台必须加密、绝不对他人明文展示);担心一个用户耗尽配额;想随时停止分享;想清楚知道赚了多少、为什么。 - -#### 用户故事(User Stories) - -- **US-8** 作为分享者,我希望选择「厂商 → Plan → 模型」就能上架一个闲置 key(大多数分享的是自己的 Plan 订阅),以便以最小成本开始赚点数。 - - AC:上架表单为三级联动「选厂商 → 选 Plan → 选该 Plan 支持的模型」,Plan 下拉中「API(按量)」代表按量计价的 key,其余为订阅 Plan;内置国内已知 Plan 清单(阿里云百炼 / 智谱 / 火山方舟 / Kimi 月之暗面 / MiniMax / DeepSeek,每家至少一个「API(按量)」项);选择 Plan 后展示对应提示(key 前缀 / 专属端点);**可用时间段为结构化可选字段(星期多选 + 起止时间,留空 = 全天不限),后端可解析生效;备注为纯文本,不解析**;必填 API key(密码输入)、声明配额;参考价按模型价格表自动计算(模型无定价数据时按「默认价」兜底,不报错);平台加密存储 key;key 绝不对他人明文展示。 -- **US-9** 作为分享者,我希望看到我的上架列表(脱敏 key、配额用量、收益),以便监控表现。 - - AC:分享页显示统计 + 我的上架列表(key 脱敏如 `sk-****1234`);每行显示「厂商 · Plan / 模型」(如「智谱 · GLM Coding Plan / glm-5.2」)、**可用时间段(设置了显示如「周一~周五 09:00-18:00」,未设置显示「全天」)**、已用 / 配额、单价、累计收益、状态。 -- **US-10** 作为分享者,我希望暂停 / 恢复 / 重新上架 / 删除上架,以便控制我的 key 何时被消费。 - - AC:暂停 = 停止接单,可恢复;删除 = 从平台永久移除,不可逆,需确认;重新上架可激活已暂停 / 已下架的上架。 -- **US-11** 作为分享者,我希望知道我的 key 何时被消费,以便看到收益累积。 - - AC:每次消费产生一条「收益」交易(对方模型、tokens、+点数 = 消费点数 × 90%,扣除 10% 平台分成);设置页有通知开关(「共享 key 被消费时通知」)。 -- **US-24** 作为分享者,我希望收益点数永久有效,以便从分享中积累长期价值。 - - AC:收益点数(收益点数)永不过期;钱包显示「收益点数 · 永久」;只在所有有有效期的(赠送)点数被扣完后才被扣减。收益金额 = 消费点数 × 90%(已扣 10% 平台抽成)。 - -#### 关键流程(Key Flow)— J-2: 上传 key → 首次收益 - -```mermaid -flowchart LR - A[共享:上架一个 key] --> B[选择厂商 / 模型] - B --> C[输入 API key + 声明配额] - C --> D[平台自动定价、加密 key] - D --> E[市场上架生效] - E --> F[别人通过我的 key 消费] - F --> G[记录收益交易] - G --> H[查看收益;随时暂停 / 删除] -``` - -1. 打开共享页 →「+ 添加 / 上架新 key」(US-8)。 -2. 选择厂商 / 模型,粘贴 API key(密码输入框),声明配额;参考价自动计算。 -3. 平台加密存储 key;上架生效;key 仅脱敏展示(US-9)。 -4. 其他用户消费 → 分享者赚点数,产生 `earn` 交易 + 通知(US-11)。 -5. 分享者监控收益;随时暂停 / 恢复 / 重新上架 / 删除(US-10)。 - -### 2.4 用户类型 D — 平台运营者(Platform Operator:宿主本人 / 部署者) - -> **身份**: 平台运营者 = **宿主本人**(deployer / owner of this deployment)。该角色已定义,**目前没有其他特殊操作**(不做内容审核、不做违规处理、不做市场调节等,规划中也无需加入,保持最小)。平台从分享者收益中抽取的 **10% 分成是运营收入来源**。 - -#### 目标(Goals) - -1. **查看平台运行情况** — 查看平台健康度:在线状态、用户数、共享 key 数、交易量、点数流动(运行状态 / 数据概览)。 -2. **给指定用户充值点数** — 直接给某个用户的余额加点数(如客服补偿、活动发放)。 - -> **明确排除**: 内容审核、违规处理、市场调节——均不属于运营者职责,现在与规划中都无需加入。 - -#### 痛点(Pain points) - -- 无法一眼看到平台健康度;无法直接给用户加点数用于补偿 / 活动。 - -#### 用户故事(User Stories) - -- **US-运营1** 作为平台运营者,我希望查看平台运行概览,以便了解平台健康状况。 - - AC:运营视图显示关键运行指标——在线状态、用户数、共享 key 数、交易量、点数流动(用户 / 共享 / 交易 / 点数)。 -- **US-运营2** 作为平台运营者,我希望给指定用户充值点数,以便处理补偿 / 活动发放。 - - AC:按用户名 / 邮箱定位用户;输入点数金额;确认后该用户余额增加**永久有效点数**;产生一条交易记录。 - -#### 关键流程(Key Flow)— 运营者登录 → 查看概览 / 定位用户 → 充值点数 - -```mermaid -flowchart LR - A[运营者登录] --> B[查看运行概览] - B --> C{需要发点数?} - C -->|否| D[监控 / 退出] - C -->|是| E[按用户名 / 邮箱定位用户] - E --> F[输入点数金额] - F --> G[确认 - 增加永久点数] - G --> H[记录交易] -``` - -1. 运营者(宿主本人)登录并打开运营视图(US-运营1)。 -2. 查看运行概览——在线状态、用户、共享 key、交易、点数流动。 -3. 如需补偿 / 活动发放,按用户名 / 邮箱定位用户(US-运营2)。 -4. 输入点数金额并确认 → 用户余额增加**永久有效点数**,并产生一条交易记录。 - ---- - -## 3. 企业场景(Enterprise Scenario) - -> **场景说明**: 企业版部署在**内网**。管理员(IT)采购模型套餐、把 key 放进 key 池、给部门 / 成员分配每月点数配额。**只有管理员有分享(提供 key)动机**;成员用分配的点数通过一个入口消费。外部注册可关闭,保持部署仅内网。功能集合与公共版相同;管理视图按角色门控。 - -### 3.1 用户类型 A — 企业管理员(Enterprise Admin:IT,配置 key 池、部门管理、成员管理、用量报表) - -#### 目标(Goals) - -- 配置 key 池(添加 / 撤销上游 key)、管理部门(CRUD + 每月点数分配)、管理成员(充值、改部门)、按模型 / 成员查看用量报表以控制成本。 - -#### 痛点(Pain points) - -- 少数重度用户导致成本超支;成员被分错部门;key 撞配额无人发现;看不到哪个模型在烧预算;新成员没有部门。 - -#### 用户故事(User Stories) - -- **US-12** 作为企业管理员,我希望通过「上架 key」配置上游 key(与普通用户同一入口 / 界面),以便成员能使用已购模型。 - - AC:管理员在共享管理页「上架新 key」(选厂商 → Plan → 模型、填 key、声明额度、可用时间段)配置上游 key;key 脱敏展示;共享列表即 key 池视图,可暂停 / 删除(撤销);无独立的管理员 Key 池界面。 -- **US-13** 作为企业管理员,我希望管理部门(CRUD + 每月点数分配),以便按组织结构分配预算。 - - AC:组织 Tab:部门列表(成员数、每月分配、已用、剩余、状态);部门增删改查;删除部门后其成员变为「未分配」——见 E-03。 -- **US-14** 作为企业管理员,我希望管理成员(充值 / 改部门),以便个人获得正确的配额与权限。 - - AC:成员 Tab:下拉改部门(现有部门 + 「未分配」);任意金额充值带**正整数校验**;新注册成员默认「未分配」。 -- **US-15** 作为企业管理员,我希望按模型与成员查看用量报表,以便控制成本、发现重度用户。 - - AC:用量 Tab 显示按模型、按成员的点数消费;数字与账本一致。 -- **US-16** 作为企业管理员,我希望可选地关闭外部注册,以便企业部署保持仅内网。 - - AC:**部署配置项,不在 UI 中设置**(企业内网部署时在部署配置中关闭外部注册);开启后仅受邀 / 已有账号可登录。 - -#### 关键流程(Key Flow)— J-3: key 池 → 员工使用模型 - -```mermaid -flowchart LR - A[管理员登录] --> B[Key 池:添加上游 key] - B --> C[组织:创建部门 + 每月分配] - C --> D[成员:分配部门 / 充值] - D --> E[员工登录,看到配额] - E --> F[员工消费模型] - F --> G[用量报表:按模型 / 按成员] - G --> H[管理员按需调整分配] -``` - -1. 管理员登录并打开管理视图(角色门控)(US-12)。 -2. 通过共享管理页「上架新 key」配置上游 key;暂停 / 删除即撤销(US-12)。 -3. 创建部门并分配每月点数(US-13)。 -4. 把成员分配到部门 / 充值;新成员默认未分配(US-14)。 -5. 员工登录,看到分配配额(US-17),通过市场消费(US-18)。 -6. 管理员查看按模型 / 成员的用量报表并重新平衡预算(US-15)。 - -### 3.2 用户类型 B — 企业成员 / 员工(Enterprise Member / Employee:用管理员分配的点数消费、查看交易、申请加额) - -#### 目标(Goals) - -- 用分配的点数通过一个入口使用模型、查看交易、余额低时申请更多点数。 - -#### 痛点(Pain points) - -- 不知道自己有多少点;配额用完时工作被打断;不知道如何申请更多;没有支出记录。 - -#### 用户故事(User Stories) - -- **US-17** 作为企业成员,我希望登录后看到我的分配点数,以便了解预算。 - - AC:仪表盘 / 钱包显示余额 = 分配 − 已消费;每月分配可见。 -- **US-18** 作为企业成员,我希望通过同一套市场界面消费模型,以便用一个入口使用 key 池里的任何模型。 - - AC:与公共版相同的市场 / 聊天 / API 流程;消费从成员点数中扣减;余额不足阻断并清晰提示。 -- **US-19** 作为企业成员,我希望查看我的交易记录,以便知道何时花了多少。 - - AC:交易记录页列出消费记录(及管理员充值调整)带时间戳。 -- **US-20** 作为企业成员,我希望余额低时申请更多点数,以便继续工作。 - - AC:申请流程(默认需管理员审批——原「需审批」开关随组织设置表单移除);申请到达管理员。 - -#### 关键流程(Key Flow)— J-4: 登录 → 消费 → 申请更多点数 - -```mermaid -flowchart LR - A[员工登录] --> B[仪表盘:配额可见] - B --> C[通过市场 / API 消费] - C --> D[扣点,记录交易] - D --> E{余额低?} - E -->|否| C - E -->|是| F[低余额提醒] - F --> G[申请加额] - G --> H[管理员审批 / 充值] - H --> I[员工继续] -``` - -1. 员工登录;仪表盘显示余额(分配 − 已用)(US-17)。 -2. 通过同一套市场界面消费(US-18)。 -3. 每次消费扣点并出现在交易记录中(US-19)。 -4. 余额低时触发通知;员工申请更多点数(US-20)。 -5. 管理员充值或调整配额;员工继续(US-14)。 - ---- - -## 4. 跨场景通用能力(Cross-Scene Shared Capability:两个场景共有) - -### 4.1 API Key 管理(API Key Management:所有用户) - -- **US-21** 作为任意用户,我希望管理平台 API key(增删改查 + 一键复制),以便安全地集成工具 / 脚本。 - - AC:设置 → API Key:生成时带名字;改名;删除需确认(「删除后该 key 立即失效」);按名字搜索;列表脱敏展示(`atk_live_****xxxx`);复制提供完整值,剪贴板 API 受限(`file://`)时降级为选中 + Ctrl/Cmd+C。 - -> 适用场景: **公共 + 企业**(公共版用户与企业管理员的平台 API Key 都走同一设置页)。 - ---- - -## 5. 边界 / 异常场景(Edge & Exception Scenarios) - -> 标注所属场景:**【公共】** 公共场景 · **【企业】** 企业场景 · **【通用】** 两个场景通用。 - -| # | 场景 Scenario | 所属场景 Scene | 预期行为 Expected behavior | -|---|---|---|---| -| E-01 | **Key 失效 / 被撤销**(Key invalid / revoked) | 【通用】 | 上架显示状态(公共:off / paused;企业:revoked);请求绕开它;消费者看到「key 不可用」而不是错误循环;分享者 / 管理员可重新上传或移除。 | -| E-02 | **额度用尽**(Quota exhausted) | 【通用】 | Key 池状态 → `exhausted` / 上架停止接单;不再尝试扣费;管理员看到 limit / exhausted 状态以便重新配置;消费者得到清晰的「额度用尽,换一个」提示。 | -| E-03 | **部门被删除**(Department deleted) | 【企业】 | 被删部门的成员变为**未分配**;不计入任何部门汇总;管理员可重新分配;其点数余额不受影响。 | -| E-04 | **点数不足**(Insufficient points) | 【通用】 | 任何上游调用前先阻断请求;清晰提示当前余额与所需点数;不允许负余额;引导用户充值 / 申请更多。 | -| E-05 | **API Key 泄露 / 失陷**(API key leak / compromise) | 【通用】 | 设置:立即删除 key(带确认,「删除后该 key 立即失效」);平台签发的 key 可撤销且即时生效;鼓励用户轮换;上游 key 在 UI 任何位置都不明文展示。 | -| E-06 | **新成员未分配**(New member, no department) | 【企业】 | 新注册默认**未分配**;仍获得默认成员配额;管理员之后分配。 | -| E-07 | **模型无定价数据**(Model with no pricing data) | 【公共】 | 上架仍成功,使用「默认价」兜底;市场显示该价格;后续迭代可补充定价。 | -| E-08 | **非法充值金额**(Top-up with invalid amount) | 【企业】 | 管理员任意金额充值校验**正整数**;零 / 负 / 非数字输入被拒绝并提示。 | -| E-09 | **剪贴板受限(file://)**(Clipboard restricted) | 【通用】 | 一键复制降级为选中 key + Ctrl/Cmd+C 指引,用户仍能拿到完整 key。 | -| E-10 | **单个重度用户耗尽预算**(Single heavy user draining budget) | 【企业】 | 用量报表(按成员)暴露问题;管理员可充值 / 调整或改部门分配;低余额提醒帮助成员自我调节。 | -| E-11 | **可用性抖动**(Availability flapping) | 【公共】 | 无就绪 key 的模型在市场显示 `busy` 可用性;提供重试 / 换一个的指引;不静默失败。 | -| E-12 | **同一 key 重复 / 冲突上架**(Duplicate / conflicting listings) | 【公共】 | 平台检测同一上游 key 被上架两次并警告分享者;防止同一配额被重复计费。 | -| E-13 | **每日赠送点数过期**(Daily gift point expired) | 【公共】 | 每次每日赠送的点数有效期 **1 天**(当日有效)——当日未用点数在当天结束时过期 / 清零。有效期可见(如「有效期至今日」)。消费**先扣有有效期的(赠送)点数**,再扣永久点数,所以每日赠送点数会被先用掉、永久点数永不因过期竞争而损失。 | -| E-14 | **当日赠送未领取**(Daily gift not claimed) | 【公共】 | 赠送机制**注册起连续 10 个自然日**、每天 1 点;若用户某天未登录,当日点数**不发、不积累**(不积累、不补发)——机制仍在第 10 天后结束。 | -| E-15 | **小数计费精度**(Fractional billing precision) | 【通用】 | 消费按 token 用量 × 模型单价精确计算,结果可为小数;金额与余额**统一保留 2 位小数、四舍五入**(如 0.374 → 0.37、0.375 → 0.38);交易记录与钱包显示一致,避免「显示 0.37 实际扣 0.374」的歧义。 | -| E-16 | **小数抽成精度**(Fractional platform-fee precision) | 【公共】 | 分享者收益 = 消费点数 × 90%,结果可为小数;收益金额**保留 2 位小数、四舍五入**(如消费 3 点 → 收益 2.7 点、平台分 0.3 点;消费 1 点 → 收益 0.9 点)。平台抽成与分享者收益之和始终等于消费者支付金额(四舍五入误差按平台侧吸收,保证分享者所得准确)。 | - ---- - -## 6. 与 UI 原型 / 架构对齐(Alignment with UI Prototype & Architecture) - -| 方面 Aspect | 事实来源 Source of truth | 对齐 Alignment | +| 角色 | 说明 | 关键能力 | |---|---|---| -| 页面 / 导航 | `ui/index.html`(仪表盘 / 市场 / 共享 / 钱包 / 交易记录 / 设置 + 管理视图) | 每个故事映射到具体页面;管理视图按角色门控,其余共用。 | -| 点数与定价 | `ui/js/data.js`(**1 点 ≈ 1 元 CNY**;CNY 模型直接 1 元 = 1 点,USD 模型按 ~7.2 汇率折算;参考价 = 输出价 点数/1M) | US-1、US-2、US-8 使用同一套规则;没有分享者自定定价;消费点数可为小数(保留 2 位)。 | -| 点数有效期与扣减顺序 | `docs/user-stories.md` v1.7(每日赠送 1 点 / 1 天有效 / 连续 10 天;收益与充值永久;先扣赠送;金额保留 2 位小数;分享收益扣 10% 平台分成) | US-22、US-23、US-24、E-13、E-14、E-15、E-16 一致;UI mock 显示今日赠送(+1)、有效期与连续天数计数,收益按 90% 计入。 | -| Key 脱敏与安全 | `ui/js/data.js`、`ui/README.md`(脱敏 key、加密托管、删除确认) | US-8、US-9、US-21、E-05 一致。 | -| 企业语义 | `ui/js/data.js`(上架 key(SHARINGS)、部门、成员未分配;无独立 key 池管理) | US-12…US-16、E-03、E-06 一致。 | -| 集中式架构 | `docs/architecture.md`(平台托管 key、计量引擎、账本) | 全文基于集中式执行假设;消费 / 收益都流经平台账本。 | -| 交易记录唯一明细 | PR #8(钱包 / 交易记录去重) | US-7:交易记录页是唯一明细入口;钱包页链接过去。 | - -> **后续迭代说明**: 若任何 UI / 后端改动与本文档产生分歧,必须在此说明分歧(追加带日期的记录)并更新文档,因为实现以此文档为准。 +| 访客 / 新用户 | 未注册 | 浏览市场 / 模型列表 / 登录注册 | +| 普通用户 | 注册并邮箱验证 | 自助注册、每日赠送、调用模型、钱包 / 交易记录 | +| 分享者 | 普通用户的行为角色 | 上架闲置 key 赚点数(分成 90/10) | +| 管理员 | 部署者 / 企业 IT | 成员管理、充值、用量报表、模型管理、部门 | +| 运营者 | 平台运营 | 运行时状态、点数流水、用户列表(独立运营视图) | + +## 2. 核心流程 + +### 注册 → 首次消费 +1. 登录页自助注册(邮箱验证码激活,未验证不可登录;验证码可重发,SMTP 失败重试 3 次) +2. 首次登录获得每日赠送点数(注册起 10 天 × 1 点/天,当日有效) +3. 选择模型 → 网关调用(余额预检 → 路由选 key → 计费) +4. 交易记录查看明细:模型 / Key 列 + 输入(非缓存) / 缓存 / 输出 / 总 Token 四列 + +### 上架 → 分享收益 +1. 共享管理页上架 key(provider / plan / model + 额度 + 可用时段 + 备注) +2. 他人消费该 key → 分享者得 90% 点数(永久),写 earn 交易 +3. key 可暂停 / 下线;状态、额度、用量实时可见 + +### 企业管控 +1. 管理员配置 key 池(同上架机制)+ 部门 / 成员管理 +2. 员工消费按点数计费;部门用量报表一目了然 +3. 成员可提交加额申请,管理员审批 + +## 3. 能力清单(对照 README 特性) + +- **多协议网关**:OpenAI Chat / Responses / Anthropic Messages + SSE 流式互转 +- **透明计费**:输入 / 缓存命中 / 输出 token 明细;DeepSeek 官方 CNY 价;高峰时段计价 +- **点数体系**:每日赠送、分享分成、管理员充值、自助注册 + 邮箱验证、找回密码 +- **企业管控**:部门、成员点数、用量报表、运营者视图、模型管理 CRUD +- **安全**:上游 key AES-256-GCM 加密、argon2 哈希、角色隔离、主密钥机制 +- **中英双语前端**:市场 / 钱包 / 交易 / 共享 / 管理 / 设置全页面 + +## 4. UI 约定 + +- **尽量少用弹窗**:操作反馈用 toast,复杂表单用内联区域 +- 数据表格支持列筛选、排序、分页、键盘导航与 CSV 导出 +- 登录态绝不 fallback 到 mock 数据——加载失败显示空态 + 重试 + +## 5. 规划(未实现) + +- chat-modal 流式接入网关、SSE 续传、key 缓存 +- 公共版共享市场深化(撮合 / 信誉体系) +- 多节点部署 / PostgreSQL / Redis(当前单机 SQLite)