Files
cmhub/docs/routes.md
T

102 lines
9.8 KiB
Markdown
Raw Normal View History

2026-07-01 17:42:10 +08:00
# 路由与页面结构
> 本项目含三类界面:**用户端页面**(Django 模板 SSR,终端用户自助)、**对外 HTTP API**(DRF,程序调用)、**运营后台**(django-admin)。本文约定各自路由与页面职责。
> 接口请求/响应合约以 [`api.md`](api.md) 为准。
## 用户端页面(Django 模板 SSR,session 登录)
| 路由 | 方法 | 职责 | 鉴权 |
| --- | --- | --- | --- |
2026-07-08 16:01:31 +08:00
| `/` | GET | 公开首页:项目介绍、四步上手、客户端下载入口、导入模板下载入口、API/控制台入口 | 公开 |
2026-07-18 15:00:04 +08:00
| `/signup` `/login` `/logout` | GET/POST | 自助注册(**免邮箱验证、注册即可用**;注册成功一次性赠送 10 点试用点数)/登录/登出(Django auth/allauth) | 公开 |
2026-07-01 17:42:10 +08:00
| `/dashboard` | GET | 个人中心:剩余点数、充值总额、快捷入口 | session |
| `/recharge` | GET/POST | 发起充值:选金额→展示支付二维码→轮询到账 | session |
| `/records/recharge` | GET | 充值记录 | session |
| `/records/usage` | GET | 点数使用(消费/调用)记录 | session |
2026-07-03 11:51:46 +08:00
| `/apikeys` | GET/POST | API Key 管理:列表 / 生成 / 删除(删除即吊销,明文只显示一次) | session |
2026-07-04 10:14:16 +08:00
| `/models` | GET | 可用模型:只读展示可调用能力别名、能力、是否需要原图和点数单价 | session |
2026-07-01 17:42:10 +08:00
2026-07-18 15:00:04 +08:00
T-501/T-608 已落地 `/signup`、`/login`、`/logout` 与 `/dashboard`:注册成功后经计费层一次性发放 10 点试用点数并写 `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`,到账后刷新余额。
2026-07-04 10:14:16 +08:00
T-601 已落地 `/models`:登录用户可查看当前公开可调用别名、能力、是否需要原图和点数单价;页面不展示底层 SKU、模型 URL、provider key、`api_key_encrypted` 或 `extra_body`。
2026-07-08 16:29:48 +08:00
T-606 已落地 `/` 公开首页:匿名访问返回 200,不再重定向到 `/dashboard`;匿名用户看到注册 / 登录 / 下载入口,登录用户看到「进入控制台」。首页下载区读取 `DownloadRelease(platform=windows, is_current=True)`,优先使用 `external_url`,否则使用后台上传文件的 `file.url`;无当前版本时显示「暂未发布」。T-610 已在同一下载区“下载客户端”右侧增加“下载导入模板”,模板由后台配置当前版本,匿名可下载;模板本地文件 URL 会转成当前站点绝对 URL,页面不暴露本地文件路径。
2026-07-03 11:27:45 +08:00
2026-07-01 17:42:10 +08:00
## API 路由(对外,DRF)
| 路由 | 方法 | 职责 | 鉴权 |
| --- | --- | --- | --- |
| `/api/v1/generate/title` | POST | 生成标题 | API Key |
2026-07-16 14:13:19 +08:00
| `/api/v1/analyze/images` | POST | 理解一张或多张图片并同步返回文字 | API Key |
2026-07-17 15:55:38 +08:00
| `/api/v1/generate/image` | POST | 生成图片(同步,支持单图 / 多图) | API Key |
| `/api/v1/generate/image/tasks` | POST | 提交异步图片生成任务(支持单图 / 多图),返回 `task_id` | API Key |
2026-07-08 22:08:48 +08:00
| `/api/v1/generate/image/tasks/{task_id}` | GET | 轮询异步图片生成任务状态和结果 | API Key |
2026-07-01 17:42:10 +08:00
| `/api/v1/balance` | GET | 查询点数余额 | API Key |
2026-07-04 10:14:16 +08:00
| `/api/v1/models` | GET | 查询可调用能力别名、能力和点数单价 | API Key |
2026-07-07 08:33:49 +08:00
| `/api/v1/client/releases/latest` | GET | 桌面端检查最新客户端版本(公开发布元数据) | 公开 |
2026-07-01 17:42:10 +08:00
| `/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`) |
2026-07-13 17:04:59 +08:00
T-607/T-609/T-617 已落地 `/api/v1/client/releases/latest`:公开匿名可访问,不需要 API Key,不读取用户账本,只返回当前 `DownloadRelease` 的版本、下载 URL、SHA256、发布说明、强制更新标记、文件大小字节数和发布时间;无当前版本返回 `release:null`。
2026-07-08 22:08:48 +08:00
T-614 已落地 `/api/v1/generate/image/tasks` 与 `/api/v1/generate/image/tasks/{task_id}`:新版桌面端可先提交异步生图任务,再轮询状态;旧 `/api/v1/generate/image` 同步接口继续保留。异步查询只允许同一用户访问自己的任务,跨用户按不存在处理。
2026-07-07 08:33:49 +08:00
2026-07-16 14:13:19 +08:00
T-619 已落地 `/api/v1/analyze/images`:使用独立 `vision` 操作和能力别名,同步接收有序多图并返回文字;不复用标题接口语义,也不改变现有标题 / 生图路由。
2026-07-17 15:55:38 +08:00
T-620 已扩展两个图生图路由:旧 `image_url` / `image_base64` 单图字段保持兼容;新 `images` 为有序列表,每项必须且只能提供其中一种来源,且不能和旧字段混用。服务端固定把第 1 张作为主商品图、后续图作为参考图;异步任务在后台可查看有序输入文件,不保存 base64 原文。
2026-07-01 17:42:10 +08:00
## 运营后台(django-admin,`/admin/`)
后台用 Django Session 登录,按模型注册 Admin:
| 管理项 | 对应模型 | 运营能做什么 |
| --- | --- | --- |
| 注册用户 | User | 查看/禁用注册用户;查看其钱包点数余额 |
2026-07-03 16:36:06 +08:00
| 点数钱包 | UserWallet | 查看余额;通过专用“手工调点”入口填写点数变动和原因,经计费层锁钱包并写 `adjust` 流水;余额字段本身只读 |
2026-07-02 15:06:00 +08:00
| API Key | ApiKey | 查看 / 吊销用户的 Key(只显示 prefix 和 hash 摘要,不回显明文) |
2026-07-01 17:42:10 +08:00
| 计费规则 | PricingRule | 配置「操作类型 × 能力别名(+ 可选分辨率)→ 点数单价」 |
| 汇率 | ExchangeRate | 配置金额→点数汇率 |
2026-07-03 16:36:06 +08:00
| 充值订单 | RechargeOrder | 检索订单、查看状态/金额/入账点数/支付流水号(只读) |
| 点数流水 | PointsLedger | 按账号、类型、时间检索充值/消费/调整/冲正流水(只读,对账用) |
| 调用记录 | CallRecord | 按账号、API Key、时间、状态检索调用,查看别名/实际模型/消耗/错误(只读) |
2026-07-08 22:08:48 +08:00
| 图片生成任务 | ImageGenerationTask | 查看异步生图任务状态、公开 task_id、关联调用记录、worker 租约、结果 URL 与错误信息(只读排障) |
2026-07-01 17:42:10 +08:00
| 模型配置 | AiModel | 维护上游模型(url/model/api_key[加密脱敏]/api_type/capabilities/timeout) |
| 能力别名 | ModelAlias | 维护对外别名 → 具体模型的映射;换供应商在此改指向 |
2026-07-02 11:42:39 +08:00
| 配置审计 | AiConfigAuditLog | 只读查看 AiModel / ModelAlias / 密钥变更:谁、何时、改了什么 |
| 客户端下载版本 | DownloadRelease | 上传安装包或填写外部下载地址,标记每个平台当前版本、是否强制更新和文件大小字节数;新增 / 编辑时必须填写 SHA256 与文件大小字节数;展示版本、SHA256、强制更新标记与发布说明 |
2026-07-08 16:01:31 +08:00
| 导入模板 | ImportTemplate | 上传导入模板或填写外部下载地址,标记当前模板;展示模板名称、SHA256 与说明 |
2026-07-01 17:42:10 +08:00
## 后台职责约定
### 用户与账号管理
- 用户自助注册;API Key 由用户在用户端自助生成(服务端生成、哈希存储、明文只显示一次),运营侧只能查看 prefix / 吊销,不回显明文。
2026-07-03 11:51:46 +08:00
- 禁用用户或吊销 Key 后,相关调用返回 403;无效、缺失或不存在的 Key 返回 401。
2026-07-03 16:36:06 +08:00
- T-401 已实现运营手工调点:后台从 `UserWallet` 进入专用表单,必须填写非 0 点数变动和原因;服务层 `adjust_wallet_points()` 在事务内锁 `UserWallet`、拒绝扣成负数,并写 `PointsLedger(change_type=adjust)`;不允许直接编辑 `points_balance` 字段。
2026-07-01 17:42:10 +08:00
### 模型与别名管理
- AiModel 的 `api_key` 加密存储,列表/详情脱敏显示,不回显明文。
- 换供应商:改 `ModelAlias` 的指向即可,对外别名与计费规则不变。
2026-07-02 11:42:39 +08:00
- AiModel / ModelAlias / 密钥的后台变更写入 `AiConfigAuditLog`(谁、何时、改了什么),日志只读;密钥变更只记录 empty/set 状态,不记录明文或密文。
2026-07-01 17:42:10 +08:00
### 流水 / 调用记录
- 只读列表,支持按账号、时间范围、类型/状态筛选与搜索。
- 不允许在后台修改或删除流水与调用记录(账目不可篡改)。
### 列表与检索
- 充值订单、流水、调用记录默认按时间倒序,提供账号与状态筛选。
## 导航规则
- 对外只暴露 `/api/v1/*`;`/admin/` 仅限运营,生产环境建议限制来源或加额外保护。
- 未授权访问 admin 跳转登录;API 未授权返回 401,不静默失败。
2026-07-04 10:47:35 +08:00
- 用户端顶部导航的深色 / 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` 时,只有当前页面入口高亮;访问非充值页时「充值」不再固定高亮。