feat(models): 模型目录与计费 - 按展示名分组并隔离管理员积分成本

This commit is contained in:
ddCat
2026-09-19 09:54:27 +08:00
parent 5ad05efb58
commit 237f2e2a6e
49 changed files with 802 additions and 276 deletions

View File

@@ -23,7 +23,7 @@ description: 影策后端核心持久化表与状态边界
容器内命令 `migrate-schema up` 应用缺失迁移,`migrate-schema status` 输出当前和期望版本,`migrate-schema verify` 只检查兼容性。`CANVAS_AUTO_MIGRATE=true` 仅用于开发和旧部署兼容;受管生产部署设置为 `false`,并由 Compose 的一次性 `migrate` 服务先完成迁移。后续迁移必须新增版本,不得修改已经发布迁移的实现或校验和。
当前结构版本为 26。版本 2 为 `schema_migrations.applied_at` 增加 `idx_schema_migrations_applied_at` 索引;版本 3 `asset_taxonomy_candidate_identity` 为资产候选增加规范化名称和来源,收敛资产分类,并为待确认候选建立项目内部分唯一索引;版本 4 `resource_upload_key` 为资源上传幂等补充 `resources.upload_key` 列和用户维度唯一索引;版本 5 `payment_topup` 创建积分充值、支付通知和对账所需结构;版本 6 `resource_playback_variant` 增加资源播放副本状态;版本 7 `asset_library_folders` 增加用户素材自定义分类及 `assets.folder_id`;版本 8 `logical_model_active_code` 将前台模型 code 的唯一约束限定为未归档记录;版本 9 `channel_presentation` 为渠道添加 `public_alias`(默认空字符串)与 `sort_order`(默认 0),为渠道模型添加 `sort_order`(默认 0),不重写既有凭据、价格或能力配置;版本 10 `creation_runtime` 创建创作运行与提交表,并为任务增加可空且唯一的 `creation_submission_id`,旧任务无需伪造提交标识即可继续使用;版本 11 `cloud_agent_runtime` 创建 `cloud_agent_executions`;版本 12 `agent_token_charge_limit` 为账单增加 Agent Token 收费上限;版本 13 `cloud_agent_canvas_mutation` 持久化 Agent 画布变更;版本 14 `cloud_agent_recovery_control` 增加运行恢复控制字段和旧运行回填;版本 15 `agent_profiles` 创建常驻偏好表;版本 16 `agent_lessons` 创建用户记忆表(含分类、路线 JSON、注入/查阅计数);版本 17 `agent_lessons_owner_index` 为 `(author_user_id, status)` 增加复合索引;版本 18 `agent_memory_settings` 创建按用户隔离的压缩周期与最近一次压缩任务状态;版本 19 `payment_plugin_version` 为已有 `payment_provider_configs` 和 `payment_orders` 补上 `plugin_version`,用于把配置和订单钉在具体插件版本上;版本 20 `banner_announcements` 创建首页常驻滚动通知表;版本 21 `banner_announcement_title_runs` 为通知标题增加样式分段;版本 22 `banner_announcement_notice_type` 增加通知类型底色;版本 23 `canvas_revision_history` 为既有画布回填 `revision = 1` 并新增历史快照与资源引用表。版本 24 `channel_model_label` 为渠道模型增加 `channel_label`(最长 80 字、非空、默认空字符串),不重写模型标识、上游 ID、价格或能力;版本 25 `video_token_formula_snapshot` 为账单增加视频公式用量及用量来源快照。版本 26 `channel_model_description` 为渠道模型增加 `description`(最长 500 字、非空、默认空字符串),供二级选项展示使用说明,不重写身份或价格。已发布版本的实现和校验和不得修改。
当前结构版本为 27。版本 2 为 `schema_migrations.applied_at` 增加 `idx_schema_migrations_applied_at` 索引;版本 3 `asset_taxonomy_candidate_identity` 为资产候选增加规范化名称和来源,收敛资产分类,并为待确认候选建立项目内部分唯一索引;版本 4 `resource_upload_key` 为资源上传幂等补充 `resources.upload_key` 列和用户维度唯一索引;版本 5 `payment_topup` 创建积分充值、支付通知和对账所需结构;版本 6 `resource_playback_variant` 增加资源播放副本状态;版本 7 `asset_library_folders` 增加用户素材自定义分类及 `assets.folder_id`;版本 8 `logical_model_active_code` 将前台模型 code 的唯一约束限定为未归档记录;版本 9 `channel_presentation` 为渠道添加 `public_alias`(默认空字符串)与 `sort_order`(默认 0),为渠道模型添加 `sort_order`(默认 0),不重写既有凭据、价格或能力配置;版本 10 `creation_runtime` 创建创作运行与提交表,并为任务增加可空且唯一的 `creation_submission_id`,旧任务无需伪造提交标识即可继续使用;版本 11 `cloud_agent_runtime` 创建 `cloud_agent_executions`;版本 12 `agent_token_charge_limit` 为账单增加 Agent Token 收费上限;版本 13 `cloud_agent_canvas_mutation` 持久化 Agent 画布变更;版本 14 `cloud_agent_recovery_control` 增加运行恢复控制字段和旧运行回填;版本 15 `agent_profiles` 创建常驻偏好表;版本 16 `agent_lessons` 创建用户记忆表(含分类、路线 JSON、注入/查阅计数);版本 17 `agent_lessons_owner_index` 为 `(author_user_id, status)` 增加复合索引;版本 18 `agent_memory_settings` 创建按用户隔离的压缩周期与最近一次压缩任务状态;版本 19 `payment_plugin_version` 为已有 `payment_provider_configs` 和 `payment_orders` 补上 `plugin_version`,用于把配置和订单钉在具体插件版本上;版本 20 `banner_announcements` 创建首页常驻滚动通知表;版本 21 `banner_announcement_title_runs` 为通知标题增加样式分段;版本 22 `banner_announcement_notice_type` 增加通知类型底色;版本 23 `canvas_revision_history` 为既有画布回填 `revision = 1` 并新增历史快照与资源引用表。版本 24 `channel_model_label` 为渠道模型增加 `channel_label`(最长 80 字、非空、默认空字符串),不重写模型标识、上游 ID、价格或能力;版本 25 `video_token_formula_snapshot` 为账单增加视频公式用量及用量来源快照。版本 26 `channel_model_description` 为渠道模型增加 `description`(最长 500 字、非空、默认空字符串),供二级选项展示使用说明,不重写身份或价格。版本 27 `channel_credit_cost` 为价格档添加管理员积分成本,并在账单保存执行线路的成本快照;成本不进入普通用户 API。已发布版本的实现和校验和不得修改。
历史发布曾使用版本 6 `asset_library_folders`,之后合并引入了上述 6/7 顺序冲突。迁移器仅在该历史记录的名称和校验和均精确匹配时选择历史顺序:保留版本 6 的素材目录记录及时间,在版本 7 应用 `resource_playback_variant`,再继续版本 8。新数据库及已采用“6 播放副本、7 素材目录”的数据库保持原顺序;状态检查与启动校验采用同一套识别规则。未知名称、被改动的校验和或冲突的版本 7 记录仍会拒绝迁移,不通过删除、改名或伪造已应用记录绕过检查。
@@ -188,10 +188,14 @@ docker compose -f docker-compose.deploy.yml up -d backend web
| 表 | 用途 | 关键边界 |
| --- | --- | --- |
| `model_channels` | 保存系统渠道与用户渠道的连接配置,以及系统渠道前台别名和排序 | 系统渠道密钥不进入公开目录;公开名称优先使用 `public_alias`,为空时使用原名;按 `sort_order, created_at, id` 升序展示 |
| `channel_models` | 保存系统渠道中的产品模型标识、上游模型 ID、显示名称、渠道展示名、模型描述、模型 Logo、排序、能力、协议和版本状态 | `channel_label` 最长 80 字,空值沿用渠道公开名称;`description` 最长 500 字、非空、默认空字符串,用于二级菜单说明;同一渠道内的产品模型标识仍唯一,跨渠道同能力同标识可在前端归组;模型排序独立保存,不递增价格或能力版本 |
| `model_channels` | 保存系统渠道与用户渠道的连接配置和排序 | 系统渠道密钥不进入公开目录;废弃渠道级前台名称,历史 `public_alias` 列保留但不再用于取名或 API 返回;按 `sort_order, created_at, id` 升序展示 |
| `channel_models` | 保存系统渠道中的调用标识、上游模型 ID、模型展示名、渠道展示名、描述、Logo、排序、能力、协议和版本状态 | 创作目录跨渠道按 `display_name` 分组一级,`channel_label` 为二级、最长 80 字、空值使用所属渠道名称;`description` 最长 500 字、非空、默认空字符串;同一渠道内调用标识唯一,跨渠道归组不依赖调用标识;模型排序不递增价格或能力版本 |
| `channel_model_price_tiers` | 保存系统模型按规格匹配的上游 SKU 与价格 | 价格档与渠道模型同事务保存;未启用或未完成定价的规格不进入普通用户目录。档位 `provider_model_key` 非空时优先于渠道模型上游键发往供应商;管理端修改模型级上游 ID 时,与旧值相同的档位键自动级联跟随,其余显式 SKU 保持不变 |
| `logical_models` | 保存前台模型的公开名称、Logo、能力类型和归档状态 | 前台模型与系统渠道模型分别维护展示信息;供应线路通过 revision 和 route 关联;`code` 仅在 `archived_at IS NULL` 的活动记录中唯一,归档后可用同 code 重建目录项 |
| `logical_models` | 保存逻辑模型的名称、Logo、能力类型和归档状态 | 不再作为创作端模型选择目录的数据源;既有任务与供应线路仍通过 revision 和 route 关联;`code` 仅在 `archived_at IS NULL` 的活动记录中唯一 |
schema v27 为 `channel_model_price_tiers` 和 `billing_orders` 添加 `cost_configured`(非空、默认 false)及 `cost_unit_price_microcredits`、`cost_input_token_price_microcredits`、`cost_output_token_price_microcredits`、`cost_cached_token_price_microcredits`(非空整数、默认 0)。账单另外保存 `cost_billing_mode`(默认空字符串)、`cost_quantity`、`cost_video_formula_tokens`(默认 0),构成下单时不可变成本快照。请求日志成本从内部账单快照计算,非持久字段 `creditCostMicrocredits` 仅供管理端投影;旧订单不反查新价格,不回填假零成本。已有售价、余额和结算金额不变。
部署需前后端与 schema v27 一起升级;关闭自动迁移时执行 `migrate-schema up`、`migrate-schema verify`。迁移只新增列,不删除旧数据,可重复校验;没有降级迁移,回滚使用匹配的数据库备份和程序版本,旧程序不记录成本快照。
所有视频协议开放 Token 定价。`channel_model_price_tiers.selector_json` 支持 `videoGenerateAudio: "true" | "false"`,省略表示任意音频;参考视频仍匹配 `operation: "video_to_video"`。视频仅使用输出 Token 单价,输入和缓存价必须为 0,明确配置的零价表示免费。schema v25 为 `billing_orders` 新增 `video_formula_tokens`(非空、默认 0,提交时固化不含余量的公式用量)及 `usage_source`(非空、默认空字符串,`provider` 或 `video_formula`)。缺少有效上游用量的新视频订单按公式快照结算并记录 `usage_available=false`,不伪造上游用量;历史快照为 0 的订单保持旧规则。价格档、费率、倍率、预留金额和既有账单不被迁移重算。前后端和 schema 一起升级,旧程序不支持新公式结算及非 Ark Token 配置,回滚需匹配数据库备份与二进制版本。完整算法见[视频 Token 计费](/docs/backend/video-token-billing)。

View File

@@ -15,13 +15,13 @@ description: 信封、错误码与 OpenAPI
## 模型规格报价
`GET /model-catalog` 在 `source=system` 时返回 `channels[].models[]`。每项的 `modelKey` 是产品模型标识,`displayName` 是产品展示名,`icon` 是模型图标键,`channelLabel` 是可选的渠道展示名(默认空字符串)。后台渠道模型创建与更新请求使用相同的 `channelLabel` 字段;服务端去除首尾空白并限制为 80 字,空字符串表示恢复使用渠道公开名称。
`GET /model-catalog` 固定返回 `source=system`,直接查询所有启用系统渠道下的渠道模型,目录数据在 `channels[].models[]`,`models` 固定为空数组。不受逻辑模型开关影响,不反查逻辑模型或供应线路。每项的 `modelKey` 是调用标识,`displayName` 是模型展示名,`icon` 是模型图标键,`channelLabel` 是可选的渠道展示名(默认空字符串)。后台渠道模型创建与更新请求使用相同的 `channelLabel` 字段;服务端去除首尾空白并限制为 80 字,空字符串表示使用所属渠道名称。
渠道模型创建、更新、管理列表、公开目录和会话模型价格信息均使用 `description` 表达模型描述。服务端去除首尾空白后限制为 500 字,允许空字符串清除描述;无管理员权限或超长内容拒绝保存。创作端二级选项在悬浮、聚焦或选中时展示该字段,长内容可悬浮查看完整文本;未填写的系统模型不按名称生成宣传文案。描述区域保留固定行高,悬浮不改变菜单项尺寸。
创作端系统渠道按渠道聚合一级菜单,二级菜单保留该渠道内各模型的独立选择;选中值继续使用 `channelId::modelKey`,报价和生成请求保留该渠道身份。展示名、渠道展示名和 Logo 不参与路由、权限及计费。`source=frontend` 的逻辑模型目录继续按原逻辑模型身份工作,不将逻辑模型的供应线路公开成可选渠道。
创作端跨渠道按模型 `displayName` 分组为一级菜单,二级菜单使用每条模型的 `channelLabel`,例如 `MiniMax H3 → 秘塔(满血渠道)`。选中值继续使用 `channelId::modelKey`,报价和生成请求保留该渠道身份。展示字段不参与路由、权限及计费。系统渠道的“前台名称/前台显示别名”已移除,管理 API 不再接受或返回 `publicAlias`。
同一产品在不同渠道中的 `modelKey` 应保持一致,名称与 Logo 也应统一;不同产品版本使用不同标识。已有模型标识不会自动改写。一级顺序按后台渠道和模型排序首次出现的位置确定,二级保持后台渠道顺序;若历史配置的展示名或 Logo 不一致,以稳定渠道身份排序选取元数据,不随当前选择和渠道排序跳变。
同一产品在不同渠道中使用相同的模型展示名即可归组,`modelKey` 可以不同;相同 `modelKey` 但展示名不同会分为不同组。一级顺序与图标按后台渠道和模型排序首次出现的位置确定,二级保持后台渠道与模型顺序。即使二级展示名相同,也保留独立选项及各自能力、价格,不自动改写历史配置或交换两个展示字段。
以下接口需要登录 Cookie,返回 `data.quote`,仅校验和报价,不创建任务、账单或冻结余额,不调用供应商生成接口。
@@ -36,6 +36,14 @@ description: 信封、错误码与 OpenAPI
Token 报价的 `estimated` 为 `true`,`quantity` 是预留 Token 数。参考素材数量不包含时长信息,带参考视频时统一按 15 秒估算并返回 `referenceDurationEstimated: true`。所有视频协议均支持 Token 定价;10% 预留是平台策略,不是费用上限。成功后优先有效上游用量,无有效用量时按提交的公式快照结算,余量不计入公式费用。账单新增 `videoFormulaTokens` 及 `usageSource`(`provider` / `video_formula`),公式结算的 `usageAvailable` 为 `false`,`outputTokens` 表示公式数量。算法、配置与异常用量处理见[视频 Token 计费](/docs/backend/video-token-billing)。
## 管理员积分成本
`GET/POST /admin/channels/:id/models` 与 `PATCH /admin/channels/:id/models/:modelId` 的 `priceTiers[]` 增加 `costPricing`:`configured`、`unitPriceMicrocredits`、`inputTokenPriceMicrocredits`、`outputTokenPriceMicrocredits`、`cachedTokenPriceMicrocredits`。成本沿用该价格档的计费方式;按次/秒使用单位价,文本 Token 按输入/输出/缓存分别定价,视频 Token 只使用输出价。价格为整数微积分,范围为 0 到 1000000000000;`configured=false` 表示未配置,`true` 且价格为 0 表示显式零成本。
成本保存到下单时的内部账单快照,不受售价倍率或扣费上限影响,后续改价不重算旧订单。历史逻辑模型任务切换备用线路时,成本更新为实际执行线路的快照,独立于用户售价策略。管理员请求列表、详情与 CSV 同时展示销售金额及成本金额;JSON 增加 `creditCostConfigured` 和可选 `creditCostMicrocredits`。成功结算后按实际计费数量、Token 用量或视频公式快照核算;未结算、已退回、历史无快照或缺少有效用量时不编造成本金额。
成本字段仅通过经过管理员权限校验的接口显式返回;普通用户的模型目录、会话模型信息、报价、任务与账单 JSON 均不包含成本配置、成本快照或成本金额。底层价格档和账单成本字段禁止 JSON 序列化,不以页面隐藏代替接口隔离。
## 画布保存、历史与恢复
画布内容使用数据库递增的 `revision` 做乐观并发校验;`updatedAt` 仅用于展示,不作为版本依据。新建 `PUT /canvas-projects/:id` 的 `project.revision` 为 0,已有画布必须带上读取到的版本。数据库在同一次条件更新中匹配 ID、用户与版本,成功后返回 `data.project` 摘要及递增后的版本;缺失版本返回 428,陈旧版本返回 409,非法版本返回 400。客户端不能获取新版号后直接重发旧内容。

View File

@@ -93,7 +93,9 @@ description: 当前项目已实现的核心工作台能力与使用入口
## 系统渠道排序与前台别名
系统渠道模型选择器按产品模型分组:一级显示模型展示名和原色 Logo,二级显示各渠道的展示名及规格价格。管理员在渠道模型的“基本信息”中配置“渠道展示名”(例如“优惠渠道-993”);留空沿用渠道公开名称。同一能力下相同的产品模型标识跨渠道归为一组,调用仍保留用户选中的具体渠道。收起后显示“模型 · 渠道”,不因另一渠道更便宜而自动切换。图标优先使用图标库的原色版本,缺少彩色版本时使用单色版本;缺少配置时显示通用图标,不猜测产品品牌。
系统渠道模型选择器直接读取渠道下的模型列表:一级跨渠道按“模型展示名”分组并显示原色 Logo,二级显示该模型的“渠道展示名”及规格售价;留空使用所属渠道名称。模型调用标识不必相同,也不反查逻辑模型。系统渠道的“前台名称”已移除。调用保留用户选中的具体渠道,收起后显示“模型 · 渠道”,不因另一渠道更便宜而自动切换。图标优先使用图标库的原色版本,缺少彩色版本时使用单色版本;缺少配置时显示通用图标,不猜测产品品牌。
渠道模型价格档支持管理员单独配置积分成本价;后台请求记录同时显示销售金额和成本金额。成本按下单快照计算,不追随之后改价;普通用户页面及接口不返回成本字段。
后台系统渠道及渠道模型列表通过“设置排序”打开完整列表,支持拖动、上移和下移,点击“保存排序”统一生效;取消不会修改线上顺序。渠道行的“更多”菜单支持复制渠道,复制会生成独立的渠道、模型和价格档,并保留原连接配置与凭证。界面不显示内部排序数字,排序不受筛选及分页影响;并发修改会提示重新加载,避免覆盖其他管理员的调整。系统渠道模式下,用户端模型选择器沿用同一渠道及模型顺序。模型排序独立保存,不改变价格、能力版本或启用状态。

View File

@@ -5,6 +5,15 @@ description: 当前项目已实现功能的手工验证清单与未确认边界
# 待测试
## 模型展示名归组与管理员积分成本
创作目录固定直接读取系统渠道模型,一级按模型展示名跨渠道分组,二级按各模型的渠道展示名展示;删除渠道级“前台名称”,不反查逻辑模型。成本配置限定在管理员价格档编辑,按下单快照核算,后台请求记录与 CSV 显示销售价、成本价;普通用户目录、报价和账单不返回成本字段。
- [x] 前端生产构建(含类型检查)与 35 项专项通过,覆盖跨渠道展示名分组、独立调用身份、成本回填与微积分换算。后端数据库、仓储、HTTP handler 全套回归通过;全包编译与成本/目录专项通过,覆盖管理员权限、用户接口字段隔离、历史快照、精确用量核算、迁移幂等和备用线路成本切换。
- [ ] 在真实后台对调历史填反的模型展示名/渠道展示名,确认 MiniMax H3 一级下显示秘塔(满血渠道);同名模型跨渠道归组,不同调用 ID 保持独立。
- [ ] 在 PostgreSQL 部署验证 schema v27,编辑按次、按秒、Token 成本后刷新回填;生成成功后核对销售金额与成本金额,改价不得影响旧订单。
- [ ] 用普通用户登录检查网络响应,确认没有成本配置、快照或成本金额;对管理员成本接口的读写均应被拒绝。
## 画布删除不再预加载关联素材
登录后的画布删除直接按 ID 请求服务端,不再先进入编辑加载流程,避免历史素材的 MIME 等字段校验阻塞删除。保留账号会话检查、服务端删除失败上抛及成功后清理本地缓存的顺序。
@@ -33,7 +42,7 @@ description: 当前项目已实现功能的手工验证清单与未确认边界
## 产品模型分组与渠道展示名
系统渠道目录按能力与产品模型标识分组,二级展示独立渠道名称和价格;后台新增“渠道展示名”,留空使用渠道公开名称。选中值仍为渠道 ID 与模型标识,逻辑模型及个人渠道保持原选择合同。模型 Logo 按需加载原色版本,移除菜单位置染色。
系统渠道目录按模型展示名分组,二级展示独立渠道名称和价格;“渠道展示名”留空使用所属渠道名称。选中值仍为渠道 ID 与模型调用标识,个人渠道保持原选择合同。模型 Logo 按需加载原色版本,移除菜单位置染色。
- [x] 前端专项覆盖同产品多个渠道、价格透传、名称变化不改调用身份、能力隔离、排序时元数据稳定,以及逻辑模型和个人渠道边界。
- [x] 后端 SQLite 专项覆盖字段保存、公开目录及会话投影、长度与管理员校验;版本 24 迁移重复执行保留旧记录的身份和价格。