Files
cmhub/docs/routes.md
T

13 KiB
Raw Blame History

路由与页面结构

本项目含三类界面:用户端页面(Django 模板 SSR,终端用户自助)、对外 HTTP API(DRF,程序调用)、运营后台(django-admin)。本文约定各自路由与页面职责。 接口请求/响应合约以 api.md 为准。

用户端页面(Django 模板 SSR,session 登录)

路由 方法 职责 鉴权
/ GET 公开首页:项目介绍、四步上手、客户端下载入口、导入模板下载入口、API/控制台入口 公开
/signup /login /logout GET/POST 自助注册(免邮箱验证、注册即可用;注册成功一次性赠送 10 点试用点数)/登录/登出(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
/migration/confirm/{request_id} GET/POST 同账号确认当前设备的存量迁移 session
/migration/devices GET 查看本人已确认设备与凭证状态 session
/migration/credentials/{id}/revoke POST 自助解绑本人设备并吊销凭证 session + CSRF

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,到账后刷新余额。 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;无当前版本时显示「暂未发布」。T-610 已在同一下载区“下载客户端”右侧增加“下载导入模板”,模板由后台配置当前版本,匿名可下载;模板本地文件 URL 会转成当前站点绝对 URL,页面不暴露本地文件路径。

API 路由(对外,DRF)

路由 方法 职责 鉴权
/api/v1/generate/title POST 生成标题 API Key
/api/v1/analyze/images POST 理解一张或多张图片并同步返回文字 API Key
/api/v1/generate/image POST 生成图片(同步,支持单图 / 多图) API Key
/api/v1/generate/image/tasks POST 提交异步图片生成任务(支持单图 / 多图),返回 task_id API Key
/api/v1/generate/image/tasks/{task_id} GET 轮询异步图片生成任务状态和结果 API Key
/api/v1/balance GET 查询点数余额 API Key
/api/v1/models GET 查询可调用能力别名、能力和点数单价 API Key
/api/v1/client/devices/register POST 蝦皮圈设备登记,签发短期设备会话(仅观测) API Key
/api/v1/client/devices/heartbeat POST 上报已登记设备活跃状态(仅观测) Device session
/api/v1/client/migration-requests POST 存量客户端申请网页确认与一次性设备凭证 API Key + Device session
/api/v1/client/migration-requests/{request_id} GET 轮询当前设备的迁移确认状态 API Key + Device session
/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/T-609/T-617 已落地 /api/v1/client/releases/latest:公开匿名可访问,不需要 API Key,不读取用户账本,只返回当前 DownloadRelease 的版本、下载 URL、SHA256、发布说明、强制更新标记、文件大小字节数和发布时间;无当前版本返回 release:null。 T-614 已落地 /api/v1/generate/image/tasks 与 /api/v1/generate/image/tasks/{task_id}:新版桌面端可先提交异步生图任务,再轮询状态;旧 /api/v1/generate/image 同步接口继续保留。异步查询只允许同一用户访问自己的任务,跨用户按不存在处理。

T-619 已落地 /api/v1/analyze/images:使用独立 vision 操作和能力别名,同步接收有序多图并返回文字;不复用标题接口语义,也不改变现有标题 / 生图路由。

T-620 已扩展两个图生图路由:旧 image_url / image_base64 单图字段保持兼容;新 images 为有序列表,每项必须且只能提供其中一种来源,且不能和旧字段混用。服务端固定把第 1 张作为主商品图、后续图作为参考图;异步任务在后台可查看有序输入文件,不保存 base64 原文。

T-624/T-625 已新增设备登记 / 心跳及调用关联:登记接口继续只认 API Key,返回仅本次展示的短期设备会话;心跳接口只认 X-Device-Session。四个生成提交路由可选带同一会话,服务端仅关联 CallRecord 与白名单遥测;无头旧客户端与异步任务轮询保持原鉴权、响应和计费语义,尚未进入订阅授权拦截。 T-627 已新增迁移申请 / 轮询和网页登录确认:客户端必须同时提供旧 API Key 与当前设备会话,申请得到短时确认链接及只出现一次的凭证明文;同账号 session 在 /migration/confirm/{request_id} 确认后才绑定席位。用户可在 /migration/devices 查看并自助解绑本人凭证;未新增生成授权拦截。

运营后台(django-admin,/admin/)

后台用 Django Session 登录,按模型注册 Admin:

管理项 对应模型 运营能做什么
注册用户 User 查看/禁用注册用户;查看其钱包点数余额
点数钱包 UserWallet 查看余额;通过专用“手工调点”入口填写点数变动和原因,经计费层锁钱包并写 adjust 流水;余额字段本身只读
API Key ApiKey 查看 / 吊销用户的 Key(只显示 prefix 和 hash 摘要,不回显明文)
计费规则 PricingRule 配置「操作类型 × 能力别名(+ 可选分辨率)→ 点数单价」
汇率 ExchangeRate 配置金额→点数汇率
充值订单 RechargeOrder 检索订单、查看状态/金额/入账点数/支付流水号(只读)
点数流水 PointsLedger 按账号、类型、时间检索充值/消费/调整/冲正流水(只读,对账用)
调用记录 CallRecord 按账号、API Key、设备、时间、状态检索调用,查看别名/实际模型/消耗/错误(只读)
图片生成任务 ImageGenerationTask 查看异步生图任务状态、公开 task_id、关联调用记录、worker 租约、结果 URL 与错误信息(只读排障)
模型配置 AiModel 维护上游模型(url/model/api_key[加密脱敏]/api_type/capabilities/timeout)
能力别名 ModelAlias 维护对外别名 → 具体模型的映射;换供应商在此改指向
配置审计 AiConfigAuditLog 只读查看 AiModel / ModelAlias / 密钥变更:谁、何时、改了什么
客户端下载版本 DownloadRelease 上传安装包或填写外部下载地址,标记每个平台当前版本、是否强制更新和文件大小字节数;新增 / 编辑时必须填写 SHA256 与文件大小字节数;展示版本、SHA256、强制更新标记与发布说明
导入模板 ImportTemplate 上传导入模板或填写外部下载地址,标记当前模板;展示模板名称、SHA256 与说明
客户端设备 ClientDevice 只读检索蝦皮圈设备平台、版本、状态和最近活跃时间;设备摘要仅脱敏显示
设备会话 / 审计 DeviceSession / DeviceBindingAudit 只读查看会话有效期、吊销状态及登记/心跳审计;不展示会话令牌或安装公钥
软件套餐 SoftwarePlan 维护蝦皮圈套餐的时长、价格、设备数、宽限期与启停状态;修改不回写已有权益快照
软件权益 SoftwareEntitlement 只读查看用户权益和套餐快照;通过专用后台页面人工授予、续期或撤销,三种操作均必须填写原因并写授权事件
授权席位 / 授权事件 LicenseSeat / LicenseEvent 只读检索设备绑定、解绑时间和全部授权审计;不支持后台直接编辑席位或事件
存量迁移资格 LegacyMigrationGrant 通过专用后台入口按用户与套餐显式授予;资格快照、关联权益和原因只读,新注册用户不会自动创建
迁移请求 / 设备凭证 MigrationRequest / DeviceCredential 只读排查短时确认状态和凭证前缀 / 吊销时间;不展示令牌明文或 hash

后台职责约定

用户与账号管理

  • 用户自助注册;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 Key、设备、时间范围、类型/状态筛选与搜索;设备关联为空表示存量无头调用,不代表调用失败。

软件授权

  • T-626 的套餐、权益和席位只提供运营基础数据与人工操作,不新增公开接口、不接支付订单,也不改变通用生成 API 的授权结果。
  • 授予 / 续期 / 撤销一律调用 apps.licensing.services;原因必填并产生 LicenseEvent。不得在 admin 表单中直接修改权益状态、到期时间、席位绑定或历史事件。
  • 已授予权益读取自身套餐快照,不随 SoftwarePlan 后续价格、时长或设备数变化而变化;席位数量由授予时快照固定。
  • 不允许在后台修改或删除流水与调用记录(账目不可篡改)。

列表与检索

  • 充值订单、流水、调用记录默认按时间倒序,提供账号与状态筛选。

导航规则

  • 对外只暴露 /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 时,只有当前页面入口高亮;访问非充值页时「充值」不再固定高亮。