QMTV 功能规格说明书(FSD)v1.0 · 总则
上游文档:prd-qmtv-v1.md(需求与契约)。本文档以 Go 实现代码为事实基准(
backend/,239/239 收官),按模块还原系统真实运转规则;与 PRD 的差异以> ⚠️ 差异 DIF-<批次>-<序号>注记并登记 99-附录 B。冻结版 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-附录;跨文件一律以 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 计费唯一链路(三条铁律之二)
- 基础价(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_atUTC。
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-认证与用户 | 二十八期首落 |
| M2 任务与拆解 | index.js + routes2/3(task 段) | 38 | F2.01~ | m02-任务与拆解 | 二十九期首落 |
| M3 生成与素材 | index.js + routes2/3(生成段) | 19 | F3.01~ | m03-生成与素材 | 二十九期首落 |
| M4 导出交付 | index.js + routes2/3(导出段) | 10 | F4.01~ | m04-导出交付 | 二十九期首落 |
| M5 通知公告 | index.js | 4 | F5.01~ | m05-通知公告 | 三十期首落 |
| M6 组织协同 | index.js(组织段)+ enterprise.js | 29 | F6.01~ | m06-组织协同 | 三十一期首落 |
| M7 分销提现 | index.js(:598-:638/:708-:737) | 11 | F7.01~ | m07-分销提现 | 三十一期首落 |
| M8 充值 | recharge.js | 8 | F8.01~ | m08-充值 | 三十一期首落 |
| M9 剧本库与投稿 | scriptlib.js + studio.js | 25 | F9.01~ | m09-剧本库与投稿 | 三十期首落 |
| M10 导演与融合 | director.js + fusion.js | 28 | F10.01~ | m10-导演与融合 | 三十期首落 |
| M11 评估与工具 | evaluation.js + workbench.js + viral | 14 | F11.01~ | m11-评估与工具 | 三十期首落 |
| M12 管理后台 | index.js(admin) + llmroutes.js + routes2(admin) | 39 | F12.01~ | m12-管理后台 | 三十一期首落 |
| M13 火花计划 | index.js:739-766 | 2 | F13.01~ | m13-火花计划 | 三十期首落 |
端点合计:基础 3 + 9+38+19+10+4+29+11+8+25+28+14+39+2 = 239(对账 PRD §3 合计行——注意「基础」3 条〔SSE 事件流/健康检查/发布模式〕是独立行,M1M13 直加 236,勿漏)。分批:二十九期 M2M4(创作主链 67)/三十期 M5+M9M11+M13(工具生态 73)/三十一期 M6M8+M12(商业管理 87)+反向覆盖收口——13 册全量收官。