# QMTV 功能规格说明书（FSD）v1.0 · 总则

LLMS 索引： [llms.txt](/llms.txt)

---

> 上游文档：[prd-qmtv-v1.md](/qmtv/product/prd-qmtv-v1/)（需求与契约）。本文档以 **Go 实现代码**为事实基准（`backend/`，239/239 收官），按模块还原系统真实运转规则；与 PRD 的差异以 `> ⚠️ 差异 DIF-<批次>-<序号>` 注记并登记 [99-附录 B](/qmtv/fsd-qmtv/99-%E9%99%84%E5%BD%95/)。冻结版 Express（`qmtv/server/`）仅作差异对拍参照，不再单独展开。
> 功能 ID 规则：`F<m>.<两位序号>`（m = PRD 模块号 M1~M13）。ID 全局唯一、只增不改号；分册文件 `m<m>-<中文名>.md`。

## 0. 修订记录

| 版本 | 日期 | 对应 PRD 版本 | 修订说明 | 作者 |
|---|---|---|---|---|
| v1.0 | 2026-10-20 | prd-qmtv-v1（v1.14） | 骨架批：总则（术语/全局规则/模块清单）+ 99-附录（对照表/DIF 台账）+ 首批分册 M1 认证与用户（F1.01~，标杆册） | — |
| v1.1 | 2026-10-20 | prd-qmtv-v1（v1.14） | 创作主链三册：m02-任务与拆解（38）/m03-生成与素材（19）/m04-导出交付（10）；§2.3 计费链路 Go 实名化+评估规则下沉分册、§2.7 前缀示例勘正（t_/shot_）；DIF-29-1~24 入台账 | — |
| v1.2 | 2026-10-20 | prd-qmtv-v1（v1.14） | 工具生态五册：m09-剧本库与投稿（25）/m10-导演与融合（28）/m11-评估与工具（14）/m05-通知公告（4）/m13-火花计划（2）；DIF-30-1~2 入台账（m09）；§2.5 video 四状态帧勘正 | — |
| v1.3 | 2026-10-20 | prd-qmtv-v1（v1.14） | 商业管理四册：m06-组织协同（29）/m12-管理后台（39）/m07-分销提现（11）/m08-充值（8）——**13 册全量收官**；反向覆盖收口（场景清单「FSD 功能 ID」列回填+人工清单对账+分区页入口卡挂出）；DIF-31-1~6 入台账 | — |

### 0.1 文档定位

- **PRD** 管 to-be 契约（需求意图、模块边界、API 清单唯一权威）；**FSD** 记 as-is 实现（系统当前真实行为，以 Go 代码逐字取证）。
- 每个功能节标注「对应 PRD」模块；实现与 PRD 不一致处行内差异注记并登记附录 B（现状 file:line / PRD 期望 / 影响面）。**PRD §4 已登记的实现差异不重复立 DIF 条目，节内引用即可**——DIF 台账只收 FSD 撰写期新发现。
- 分册结构（沿 pms fsd-pms 形态）：`m01~m13` 共 13 册 + 本总则 + [99-附录](/qmtv/fsd-qmtv/99-%E9%99%84%E5%BD%95/)；跨文件一律以 F-ID 纯文本引用。
- 场景挂钩：功能节元数据行标注对应 E2E 场景 ID（`docs/test/e2e-qmtv-场景清单.md`），三十一期反向覆盖收口时回填场景清单「FSD 功能 ID」列。

## 1. 术语与数据字典

收录判据：PRD、界面文案、代码命名三方叫法不一致的词必收。表名列名权威在 数据库表设计-qmtv.md（保留冻结原名），此处只收易混术语。

| 界面/PRD 叫法 | 代码命名 | 本文统一叫法 | 说明 |
|---|---|---|---|
| 积分 | `credits`（users 列）/ `credit_records` | 积分 / 积分台账 | 整数语义，二十一期 ⑥ 起 DECIMAL(12,2) 存储、读侧 float64 |
| 拆解 | split / preprocess（旧版叫预处理） | 拆解 | v2 token 制（1000 tokens≈1 积分）为现行；旧版按次 20 积分仍在 |
| 镜数 | `shotCount`（wire 驼峰）/ shots 表 | 镜数 | **wire 是驼峰**（冻结 index.js:230 保真），误读蛇形 shot_count 是二十六期 A1 回归根因 |
| 分镜 | shot / director_shots 双表 | 分镜 | 双工作台双表通路（`shot._tbl` 约定），分册内标注归属表 |
| 火花计划 | spark / spark_submissions | 火花 | 三阶梯 100/150/200，加入奖励 +100 |
| 台账类型 | credit_records.type | 台账类型 | `TypeCredit` 等常量族（credits/model.go），描述文案「模块·动作（-N）」格式 |
| 工作台 | workbench（工具域）/ dashboard（拆解台） | 工作台工具 / 拆解台 | 界面两个「工作台」指向不同域：`/workbench`=M11 工具，`/dashboard`=M2 拆解 |
| 独立生成 | standalone（video/images 独立路由） | 独立生成 | M3 域内概念：不经任务链直出图片/视频 |
| 评估冻结-结算 | reserve（TypeReserve 台账） | 评估冻结 | 提交时冻结 100/300，完成结算、失败全额退 |

## 2. 全局规则

### 2.1 权限模型

| 层 | 载体 | 覆盖面 |
|---|---|---|
| 登录态 | `AuthMiddleware`（gateway/auth.go:120，全站默认） | 除公开面（login/register/health/style-presets/faq/showcase 公开段等）外全部端点 |
| 管理员 | `AdminMiddleware`（gateway/auth.go:133，校验 role='admin'） | `/admin/*` 面与 M12 全域；非 admin 403 |
| 组织属主 | org 域内 ownerOnly / adminOrOwner 两判定（勿混用） | M6 组织面：owner target 特判（如 material-perms「所有者默认拥有全部权限」400） |
| 数据属主 | 各域 service 内 user_id 过滤（WHERE 拼接） | 越权访问统一 404「资源不存在」形态（不暴露存在性），个别 403（组织/导演面） |

三角色入口可见性（前端）：普通用户无管理后台入口且直访 `/admin` 被路由守卫顶回；组织功能导航按 `org_id` 条件可见。

### 2.2 错误信封与哨兵

- 统一信封：成功 `200 {"ok":true,"data":<业务体>}`（gateway.OK，middleware.go:44）/ 失败 `<状态码> {"error":"<中文哨兵文案>"}`（gateway.Err，middleware.go:52——错误键是 `error` 非 `message`，文案截 300 rune 镜像冻结 `slice(0,300)`）；HTTP 状态码语义化（400/401/402/403/404/500/502/503）。
- **哨兵机制**：各域定义哨兵 error（如 `task.ErrNotFound`），`errRespond`（auth_handlers.go:39）集中映射哨兵→HTTP 状态+文案。**文案逐字节对齐冻结版**（前端直接展示 message）。
- 关键横切状态码：积分不足=`402`（credits.ErrInsufficient→MsgInsufficientCrd）；降级模式业务请求=`503`「数据库未配置」（requireDB）；生成 Provider 失败=`502`（内部已退款）。
- 404 vs 400 取舍原则：属主不存在/无权访问→404（不暴露存在性）；参数校验失败/状态不合法→400 带动态文案（如 distribution「不允许从「X」流转到「Y」」）。

### 2.3 计费唯一链路（三条铁律之二）

```mermaid
flowchart LR
  A["业务动作"] --> B["credits.Service.TryDeduct<br/>（冻结 util.tryDeduct）<br/>基础价 COSTS + settings 可调双层"]
  B -->|余额不足| C["402 ErrInsufficient"]
  B -->|扣成功| D["generation.Service.SmartVideo / provider.GenerateImage<br/>（冻结 providers.videoSmart/imageSmart）<br/>真实供应商或内置 Mock"]
  D -->|失败| E["generation 内部统一退款 RefundGenError<br/>调用方不得重复退款"]
  D -->|成功| F["产物落库 + 台账 credit_records"]
```

- 基础价（credits/billing.go）：图 10 / 2K 预览 15 / 独立视频 50 / 重新拆解 20 / 爆款 5；token 制 1000 tokens≈1 积分；注册赠 200。settings 键可调项以管理后台「计费配置」为准。
- 台账：每笔扣/退一行 `credit_records`（type 常量 + 描述「模块·动作（-N）」）；域内台账流转（如评估冻结-结算）归各分册（§1 词条兜底）。
- 退款唯一口在生成域内部（`RefundGenError` 文案组装 + `ClaimVideoRefund` 防重认领）与各域显式退款函数（二十一期 ③ Refund 收口）；审批到账（充值）走 credits.Add。

### 2.4 Mock 优先架构

- 未配置模型接入时全站走内置 Mock：前端项目**零环境变量接 AI**；真实供应商由管理后台 `model_endpoints` 表配置（OpenAI 兼容），字段不全自动回退 Mock。
- Mock 行为是**契约的一部分**（同步 done、确定性输出、进度事件照发），e2e 断言册全量依赖；分册内 Mock 分支行为照实登记，不标「临时代码」。

### 2.5 SSE 事件总线

`GET /api/events`（query token 兜底）单进程事件总线，五类事件（notification/hub.go:21-25）：`video`（生成进度）/`split`（拆解 done/fallback）/`recharge`（充值到账，仅发本人）/`workbench`（工作台 done/failed）/`eval`（评估 stage/done/failed）。**审片/通知无 SSE**（前端轮询）。分册内「零 SSE 零通知」标注=该域刻意不走事件面。

### 2.6 认证与 token

- 自实现 HMAC JWT + refreshToken；`QMTV_JWT_SECRET` 环境变量优先，缺省持久化 `data/.jwt_secret`（与冻结版同文件，存量 token 跨运行时有效）。
- **refresh 真轮换（F1）**：`POST /api/auth/refresh` 返回新 refreshToken，旧 token 复刷 401——与冻结版差异（冻结 refresh 恒 401 无新字段），已登记 PRD 差异⑤族。
- query token 兜底仅两处：SSE `/api/events?token=`、`GET /api/images/:id?token=`（EventStream/img 标签带不了自定义头）。
- 时间形态双轨（刻意不同源勿统一）：auth 域 `LocalTime`（注册/登录时间，冻结 `dayjs` 本地形态）vs 审批类 `reviewed_at` UTC。

### 2.7 wire 形态与 ID 前缀

- wire 键**按域登记不全局统一**：任务/生成域驼峰（`shotCount`/`taskType`）、spark me 投影蛇形（`next_tier`）、导出端点蛇形——前端按域消费，改名即回归（shotCount 事故教训）。分册内端点响应示例照实标键形。
- 业务 ID 一律 `ids.go` 前缀 + 随机段（51 前缀全量对拍守卫钉死：`u_`/`t_`/`shot_`/`as_`/`ro_`/`wk_`…），前缀即域归属判别。

## 3. 功能模块清单

| 模块 | 冻结源文件 | 端点数 | F-ID 段 | 分册 | 状态 |
|---|---|---|---|---|---|
| 基础 | index.js（SSE/health/release-mode） | 3 | —（横切面，见总则 §2.2/§2.5） | 无独立分册 | 总则已覆盖 |
| M1 认证与用户 | index.js（认证段） | 9 | F1.01~ | [m01-认证与用户](/qmtv/fsd-qmtv/m01-%E8%AE%A4%E8%AF%81%E4%B8%8E%E7%94%A8%E6%88%B7/) | **二十八期首落** |
| M2 任务与拆解 | index.js + routes2/3（task 段） | 38 | F2.01~ | [m02-任务与拆解](/qmtv/fsd-qmtv/m02-%E4%BB%BB%E5%8A%A1%E4%B8%8E%E6%8B%86%E8%A7%A3/) | **二十九期首落** |
| M3 生成与素材 | index.js + routes2/3（生成段） | 19 | F3.01~ | [m03-生成与素材](/qmtv/fsd-qmtv/m03-%E7%94%9F%E6%88%90%E4%B8%8E%E7%B4%A0%E6%9D%90/) | **二十九期首落** |
| M4 导出交付 | index.js + routes2/3（导出段） | 10 | F4.01~ | [m04-导出交付](/qmtv/fsd-qmtv/m04-%E5%AF%BC%E5%87%BA%E4%BA%A4%E4%BB%98/) | **二十九期首落** |
| M5 通知公告 | index.js | 4 | F5.01~ | [m05-通知公告](/qmtv/fsd-qmtv/m05-%E9%80%9A%E7%9F%A5%E5%85%AC%E5%91%8A/) | **三十期首落** |
| M6 组织协同 | index.js（组织段）+ enterprise.js | 29 | F6.01~ | [m06-组织协同](/qmtv/fsd-qmtv/m06-%E7%BB%84%E7%BB%87%E5%8D%8F%E5%90%8C/) | **三十一期首落** |
| M7 分销提现 | index.js（:598-:638/:708-:737） | 11 | F7.01~ | [m07-分销提现](/qmtv/fsd-qmtv/m07-%E5%88%86%E9%94%80%E6%8F%90%E7%8E%B0/) | **三十一期首落** |
| M8 充值 | recharge.js | 8 | F8.01~ | [m08-充值](/qmtv/fsd-qmtv/m08-%E5%85%85%E5%80%BC/) | **三十一期首落** |
| M9 剧本库与投稿 | scriptlib.js + studio.js | 25 | F9.01~ | [m09-剧本库与投稿](/qmtv/fsd-qmtv/m09-%E5%89%A7%E6%9C%AC%E5%BA%93%E4%B8%8E%E6%8A%95%E7%A8%BF/) | **三十期首落** |
| M10 导演与融合 | director.js + fusion.js | 28 | F10.01~ | [m10-导演与融合](/qmtv/fsd-qmtv/m10-%E5%AF%BC%E6%BC%94%E4%B8%8E%E8%9E%8D%E5%90%88/) | **三十期首落** |
| M11 评估与工具 | evaluation.js + workbench.js + viral | 14 | F11.01~ | [m11-评估与工具](/qmtv/fsd-qmtv/m11-%E8%AF%84%E4%BC%B0%E4%B8%8E%E5%B7%A5%E5%85%B7/) | **三十期首落** |
| M12 管理后台 | index.js(admin) + llmroutes.js + routes2(admin) | 39 | F12.01~ | [m12-管理后台](/qmtv/fsd-qmtv/m12-%E7%AE%A1%E7%90%86%E5%90%8E%E5%8F%B0/) | **三十一期首落** |
| M13 火花计划 | index.js:739-766 | 2 | F13.01~ | [m13-火花计划](/qmtv/fsd-qmtv/m13-%E7%81%AB%E8%8A%B1%E8%AE%A1%E5%88%92/) | **三十期首落** |

端点合计：基础 3 + 9+38+19+10+4+29+11+8+25+28+14+39+2 = **239**（对账 PRD §3 合计行——注意「基础」3 条〔SSE 事件流/健康检查/发布模式〕是独立行，M1~M13 直加 236，勿漏）。分批：二十九期 M2~M4（创作主链 67）/三十期 M5+M9~M11+M13（工具生态 73）/三十一期 M6~M8+M12（商业管理 87）+反向覆盖收口——**13 册全量收官**。

---

反链：

- [功能规格（FSD）](/qmtv/fsd-qmtv/)
- [FSD 附录 · PRD 对照 / 代码域索引 / 差异台账](/qmtv/fsd-qmtv/99-%E9%99%84%E5%BD%95/)
- [FSD M1 · 认证与用户](/qmtv/fsd-qmtv/m01-%E8%AE%A4%E8%AF%81%E4%B8%8E%E7%94%A8%E6%88%B7/)
- [FSD M2 · 任务与拆解](/qmtv/fsd-qmtv/m02-%E4%BB%BB%E5%8A%A1%E4%B8%8E%E6%8B%86%E8%A7%A3/)
- [FSD M3 · 生成与素材](/qmtv/fsd-qmtv/m03-%E7%94%9F%E6%88%90%E4%B8%8E%E7%B4%A0%E6%9D%90/)
- [FSD M4 · 导出交付](/qmtv/fsd-qmtv/m04-%E5%AF%BC%E5%87%BA%E4%BA%A4%E4%BB%98/)
- [FSD M5 · 通知公告](/qmtv/fsd-qmtv/m05-%E9%80%9A%E7%9F%A5%E5%85%AC%E5%91%8A/)
- [FSD M6 · 组织协同](/qmtv/fsd-qmtv/m06-%E7%BB%84%E7%BB%87%E5%8D%8F%E5%90%8C/)
- [FSD M7 · 分销提现](/qmtv/fsd-qmtv/m07-%E5%88%86%E9%94%80%E6%8F%90%E7%8E%B0/)
- [FSD M8 · 充值](/qmtv/fsd-qmtv/m08-%E5%85%85%E5%80%BC/)
- [FSD M9 · 剧本库与投稿](/qmtv/fsd-qmtv/m09-%E5%89%A7%E6%9C%AC%E5%BA%93%E4%B8%8E%E6%8A%95%E7%A8%BF/)
- [FSD M10 · 导演与融合](/qmtv/fsd-qmtv/m10-%E5%AF%BC%E6%BC%94%E4%B8%8E%E8%9E%8D%E5%90%88/)
- [FSD M11 · 评估与工具](/qmtv/fsd-qmtv/m11-%E8%AF%84%E4%BC%B0%E4%B8%8E%E5%B7%A5%E5%85%B7/)
- [FSD M12 · 管理后台](/qmtv/fsd-qmtv/m12-%E7%AE%A1%E7%90%86%E5%90%8E%E5%8F%B0/)
- [FSD M13 · 火花计划](/qmtv/fsd-qmtv/m13-%E7%81%AB%E8%8A%B1%E8%AE%A1%E5%88%92/)
- [人工测试清单(QMTV QA 走查底稿)](/qmtv/manual/%E4%BA%BA%E5%B7%A5%E6%B5%8B%E8%AF%95%E6%B8%85%E5%8D%95/)
