Files
cmhub/docs/routes.md
T
2026-07-08 15:13:23 +08:00

92 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 路由与页面结构
> 本项目含三类界面:**用户端页面**(Django 模板 SSR,终端用户自助)、**对外 HTTP API**(DRF,程序调用)、**运营后台**(django-admin)。本文约定各自路由与页面职责。
> 接口请求/响应合约以 [`api.md`](api.md) 为准。
## 用户端页面(Django 模板 SSR,session 登录)
| 路由 | 方法 | 职责 | 鉴权 |
| --- | --- | --- | --- |
| `/` | GET | 公开首页:项目介绍、四步上手、客户端下载入口、API/控制台入口 | 公开 |
| `/signup` `/login` `/logout` | GET/POST | 自助注册(**免邮箱验证、注册即可用**;注册成功一次性赠送 100 点试用点数)/登录/登出(Django auth/allauth) | 公开 |
| `/dashboard` | GET | 个人中心:剩余点数、充值总额、快捷入口 | session |
| `/recharge` | GET/POST | 发起充值:选金额→展示支付二维码→轮询到账 | session |
| `/records/recharge` | GET | 充值记录 | session |
| `/records/usage` | GET | 点数使用(消费/调用)记录 | session |
| `/apikeys` | GET/POST | API Key 管理:列表 / 生成 / 删除(删除即吊销,明文只显示一次) | session |
| `/models` | GET | 可用模型:只读展示可调用能力别名、能力、是否需要原图和点数单价 | session |
T-501/T-608 已落地 `/signup`、`/login`、`/logout` 与 `/dashboard`:注册成功后经计费层一次性发放 100 点试用点数并写 `signup_bonus` 流水,注册限流由 allauth signup rate limit 执行。T-502 已落地 `/apikeys`:登录用户只能管理自己的 Key,生成后明文只显示一次,列表只显示 prefix,删除为吊销 `revoked`。T-503/T-505/T-608 已扩展 `/dashboard` 为个人中心汇总,并落地 `/records/recharge` 与 `/records/usage`:充值总额按已支付订单统计,注册赠点 / 入账 / 消费 / 退款点数按 `PointsLedger` 统计,记录页只查询当前登录用户数据并分页展示。T-504/T-505 已落地 `/recharge`:登录用户可选择金额和支付方式创建 pending 充值订单,页面用本地 static 自托管 qrcode.js 展示二维码票据并轮询 `/api/v1/recharge/status`,到账后刷新余额。
T-601 已落地 `/models`:登录用户可查看当前公开可调用别名、能力、是否需要原图和点数单价;页面不展示底层 SKU、模型 URL、provider key、`api_key_encrypted` 或 `extra_body`。
T-606 已落地 `/` 公开首页:匿名访问返回 200,不再重定向到 `/dashboard`;匿名用户看到注册 / 登录 / 下载入口,登录用户看到「进入控制台」。首页下载区读取 `DownloadRelease(platform=windows, is_current=True)`,优先使用 `external_url`,否则使用后台上传文件的 `file.url`;无当前版本时显示「暂未发布」。
## API 路由(对外,DRF)
| 路由 | 方法 | 职责 | 鉴权 |
| --- | --- | --- | --- |
| `/api/v1/generate/title` | POST | 生成标题 | API Key |
| `/api/v1/generate/image` | POST | 生成图片(同步) | API Key |
| `/api/v1/balance` | GET | 查询点数余额 | API Key |
| `/api/v1/models` | GET | 查询可调用能力别名、能力和点数单价 | API Key |
| `/api/v1/client/releases/latest` | GET | 桌面端检查最新客户端版本(公开发布元数据) | 公开 |
| `/api/v1/recharge/create` | POST | 用户端发起充值(weixin/alipay),下单取二维码 | Session(用户端) |
| `/api/v1/recharge/status` | GET | 轮询订单状态(前端每秒) | Session(用户端) |
| `/api/v1/recharge/callback/wechat` | POST | 微信 V3 异步回调 | 验签(`@csrf_exempt`) |
| `/api/v1/recharge/callback/alipay` | POST | 支付宝异步回调 | 验签(`@csrf_exempt`) |
T-607 已落地 `/api/v1/client/releases/latest`:公开匿名可访问,不需要 API Key,不读取用户账本,只返回当前 `DownloadRelease` 的版本、下载 URL、SHA256、发布说明和发布时间;无当前版本返回 `release:null`。
## 运营后台(django-admin,`/admin/`)
后台用 Django Session 登录,按模型注册 Admin:
| 管理项 | 对应模型 | 运营能做什么 |
| --- | --- | --- |
| 注册用户 | User | 查看/禁用注册用户;查看其钱包点数余额 |
| 点数钱包 | UserWallet | 查看余额;通过专用“手工调点”入口填写点数变动和原因,经计费层锁钱包并写 `adjust` 流水;余额字段本身只读 |
| API Key | ApiKey | 查看 / 吊销用户的 Key(只显示 prefix 和 hash 摘要,不回显明文) |
| 计费规则 | PricingRule | 配置「操作类型 × 能力别名(+ 可选分辨率)→ 点数单价」 |
| 汇率 | ExchangeRate | 配置金额→点数汇率 |
| 充值订单 | RechargeOrder | 检索订单、查看状态/金额/入账点数/支付流水号(只读) |
| 点数流水 | PointsLedger | 按账号、类型、时间检索充值/消费/调整/冲正流水(只读,对账用) |
| 调用记录 | CallRecord | 按账号、API Key、时间、状态检索调用,查看别名/实际模型/消耗/错误(只读) |
| 模型配置 | AiModel | 维护上游模型(url/model/api_key[加密脱敏]/api_type/capabilities/timeout) |
| 能力别名 | ModelAlias | 维护对外别名 → 具体模型的映射;换供应商在此改指向 |
| 配置审计 | AiConfigAuditLog | 只读查看 AiModel / ModelAlias / 密钥变更:谁、何时、改了什么 |
| 客户端下载版本 | DownloadRelease | 上传安装包或填写外部下载地址,标记每个平台当前版本;展示版本、SHA256 与发布说明 |
## 后台职责约定
### 用户与账号管理
- 用户自助注册;API Key 由用户在用户端自助生成(服务端生成、哈希存储、明文只显示一次),运营侧只能查看 prefix / 吊销,不回显明文。
- 禁用用户或吊销 Key 后,相关调用返回 403;无效、缺失或不存在的 Key 返回 401。
- T-401 已实现运营手工调点:后台从 `UserWallet` 进入专用表单,必须填写非 0 点数变动和原因;服务层 `adjust_wallet_points()` 在事务内锁 `UserWallet`、拒绝扣成负数,并写 `PointsLedger(change_type=adjust)`;不允许直接编辑 `points_balance` 字段。
### 模型与别名管理
- AiModel 的 `api_key` 加密存储,列表/详情脱敏显示,不回显明文。
- 换供应商:改 `ModelAlias` 的指向即可,对外别名与计费规则不变。
- AiModel / ModelAlias / 密钥的后台变更写入 `AiConfigAuditLog`(谁、何时、改了什么),日志只读;密钥变更只记录 empty/set 状态,不记录明文或密文。
### 流水 / 调用记录
- 只读列表,支持按账号、时间范围、类型/状态筛选与搜索。
- 不允许在后台修改或删除流水与调用记录(账目不可篡改)。
### 列表与检索
- 充值订单、流水、调用记录默认按时间倒序,提供账号与状态筛选。
## 导航规则
- 对外只暴露 `/api/v1/*`;`/admin/` 仅限运营,生产环境建议限制来源或加额外保护。
- 未授权访问 admin 跳转登录;API 未授权返回 401,不静默失败。
- 用户端顶部导航的深色 / active 样式应表示“当前所在页面”,不能固定给某个入口。若保留“充值”作为常驻 CTA,应使用与当前页 active 明确区分的样式,避免用户误以为仍停留在充值页。
### 导航 active 状态
- 已修复:`apps/portal/templates/portal/base.html` 基于 `request.resolver_match.url_name` 判断当前页面,只给当前页面入口使用 `btn-primary` 与 `aria-current="page"`。
- 非当前页面入口使用 `btn-outline-secondary`;`/records/recharge` 与 `/records/usage` 分别高亮对应记录入口。
- 已补 portal 测试:登录后访问 `/models`、`/recharge`、`/apikeys`、`/records/recharge`、`/records/usage`、`/dashboard` 时,只有当前页面入口高亮;访问非充值页时「充值」不再固定高亮。