跳转到主要内容

这是本节的多页打印视图。 .

返回本页常规视图.

产品

项目导览、PRD、系统设计方案、前端技术对比与功能规划。

1 - 00 · 交接导览(先读我)

本目录是 QMTV 项目开发文档集,面向开发/运维的同事。建议按顺序阅读,全程约 30 分钟即可建立完整认知并跑起项目。

项目速览卡

项值
项目名QMTV — AI 短剧智能生产线
位置D:\WORK\GAE\qmtv(本目录)
技术栈Node.js 22 + Express 5 + better-sqlite3(后端);Vue 3 + Vue Router 4 + Vite 8(前端);无 UI 框架,自研主题
启动npm install → npm start(后端 :3300 并托管前端 dist)→ npm run build(构建前端)
数据库data/qmtv.db(SQLite WAL,49 张表,免安装)
规模后端 24 个模块 / 5436 行,239 个 API;前端 24 个页面 / 约 9000 行
设计文档(历史全量)D:\WORK\GAE\QMTV网站设计文档.md(22 节,按 v1→v22 版本演进记录每一步设计决策与实测结论)

文档地图

文档内容什么时候读
01-系统设计方案.md产品定位、功能全景、各模块设计方案、数据模型、计费模型、AI 链路设计、视觉体系想理解"为什么这样设计"
02-系统架构介绍.md技术栈、目录结构、后端模块职责、前端结构、49 张表清单、关键机制(SSE/供应商适配/启动恢复)、构建部署想理解"代码怎么组织的"
03-系统开发说明.md环境准备、启动步骤、账号、日常开发操作指南(加页面/加接口/加表)、验证方法、踩坑清单、运维注意动手开发前必读
04-待开发功能与规划.md真实模型接入清单、已知欠账与改进项、建议优先级排后续开发计划
05-API接口速查手册.md全部 239 个 API 按模块分组写代码时当字典查

30 分钟上手路径

  1. (5 分钟)读本文档 + 02-系统架构介绍.md 的目录结构一节
  2. (5 分钟)npm install,两个终端分别 npm start 和 npm run dev(前端热更 :5173,代理到 :3300)
  3. (5 分钟)用制片账号登录 producer@xingmang.cn / demo123456,把主导航每一页点一遍;再用管理员 admin@qmtv.com / admin123456 看管理后台
  4. (10 分钟)读 03-系统交接说明.md 的「常见开发任务怎么做」与「踩坑清单」
  5. (5 分钟)浏览 04-待开发功能与规划.md,确定你的第一个任务

三条最重要的经验(先记住再说)

  1. 发中文请求调试一律写 Node 脚本(仓库里有大量 verify_*.js 可参照),不要用 curl/heredoc——Git Bash 下中文会 GBK 损坏,曾数次被误判为 bug。
  2. 数据库是SQLite 单文件,改表结构统一走 server/db.js 的 migrations 数组(ALTER TABLE ... ADD COLUMN,try/catch 幂等),不要手改已有 CREATE TABLE。
  3. 所有生成动作都走积分:先 tryDeduct 再调 providers.imageSmart/videoSmart,失败退款由 providers 内部统一负责,调用方不要重复退款。生成类入口只此一个约定,接手时务必遵守。

2 - QMTV 移植契约规格(PRD)v1

文档定位:本文是 qmtv 后端 Go+MySQL 移植的需求契约唯一权威——以冻结版 Node 实现(qmtv/server/,2026-10-17)的实际行为为基准逐条登记,外加已裁决的修正项。Go 版若与本文不符,以本文为准;本文与冻结代码不符处=修正项章节。上游设计参照:qmtv/docs/01-系统设计方案.md(冻结)。

后续 FSD 以 Go 实现代码为事实基准反向对账本文;本文修订走版本记录(§0.1)。

0.1 修订记录

版本日期修订说明作者
v12026-10-17初版:239 端点全清单 + 6 修正项 + 全局契约Claude
v1.12026-10-17前端项目立项:新建 frontend/(初始复制 qmtv 前端,行为对等),演进轨道 vue-query/vitest/TS(§1 前端行更新 + 新增 §7);C3/C4/§2.1 token query 表述按冻结实际行为修正(全局兜底,非白名单)Claude
v1.22026-10-18P1 期首核查勘误 + 裁决落册:C4/§2.1 修正为冻结三分事实(v1.1 的「全局兜底、与冻结一致」表述被核查证伪——冻结 authRequired 仅 Bearer/events 纯 query/images/:id query 优先)+ 登记 Go 裁决(FromRequest 保持 Bearer 优先 + query 全局兜底);F1 兼容影响改写(前端 api.js:24 补丁须同期);F2 谓词微调;新增 F7(邮箱校验统一)/F8(素材对象存储);M1 端点数 6→9(补登 logout/credit-records);§2.2 rr_ 共用注记Claude
v1.32026-10-18P2 立项定稿:F2 尾注更新(RunWithRetry 实测不引入——CAS 谓词仅 credits>=? 下 affected=0 ⇔ 余额不足,qmtv/pms 双侧零生产调用);F8 补 file_path 布局差异(ObjectKey 日期子目录 vs 冻结扁平);新增 F9(退款防重唯一口,修冻结双退款漏洞);§6 启动恢复注记 P2 范围拆分(workbench 随 M11);跨聚合扣款时序定稿(§6,不引 actor/outbox 对齐冻结同步流)Claude
v1.3-pending2026-10-18W10 对账预告(pending,正文暂不改):M2 端点数实测 38(routes.go M2 组实装口径),§3 表 :33/§4 :118/合计 :45 的「66」系 P0 统计残留——W10 收尾时三处一并校准;增量端点逐条清单移 docs/API-增量.md 累加Claude
v1.3-pending2026-10-18C1 裁决落地(storage 默认面):dev 模板默认直连 MinIO(192.168.50.190:9000+bucket qmtv+public_base,凭据 LAN 实例默认不入生产);F8 增记:MinIO 模式落库 file_path=终态绝对 URL(pathOfFunc 写路径拼 public_base,前端逐字消费;桶/域迁移需一次性 UPDATE file_path),local 模式仍 /files/ 相对(=冻结形态)——F8 原文「落库相对+出站现场拼」按此修订Claude
v1.3-pending2026-10-18W10 对账预告(M3,pending,正文暂不改):M3 端点数实测 19(index.js 9+routes2 3+routes3 7),§3 表/§4 标题的「38」系 P0 统计残留——render-all 实属 M4、retry 无用户端点;/api/models/active 归属补登 M3(PRD 全文未列该端点,W10 一并补登)Claude
v1.3-pending2026-10-18M3 实现差异登记(W4 期首核查 B5/B6 补录,W10 入正文):①expires_at=C7 例外全达成(冻结 toISOString() 入库透传;Go ISOTime 响应 ISO,落库仍 DATETIME(3))②SmartVideo ⑩ 分辨率白名单外值(如 480p)冻结原样透传 vs Go 归一 1080p、ratio null 冻结传 null vs Go 归一 16:9(Go 收紧向,安全)③SSE progress 冻结每次 fetch 前发 vs Go fetch 后发(tries 命中集合相同)④tag 打标价冻结固定 COSTS.image=10 vs Go 随 F6 settings 覆盖价Claude
v1.3-pending2026-10-18M4 实现差异登记(W5 期首核查补录,W10 入正文):①history 响应 v.* 列序:冻结 created_at 在 error 之后(db.js CREATE 后 ALTER 折叠序)vs Go DDL/struct 排末位——键集一致、前端按键取值无感,严格逐字节对拍不齐;②assets-deliver 条目名 index_no=0:冻结 JS truthy→asset_ vs Go 原指针非 nil→shot000_,W6 期已修对齐(!= nil && !=0);③export repo 接口实为 16 方法(基线「17」系计数漂移)Claude
v1.3-pending2026-10-18W6/W8 实现差异登记(期首核查 B2 + W8 集成抽样补录,W10 入正文):①W6 逐段容错差异——冻结 videos 段无 catch(异常即崩启动,SQLite 同步 API 副作用非设计)vs Go 统一逐段容错不挡启动;②workbench finished_at 冻结 datetime('now','localtime') vs Go NOW(3)(方言惯例);③§6 :196「workbench_tasks 扫描随 M11 落地」已过时——W6 已内联实现(正文 W10 校准一并改);④W8 集成抽样抓获:task 恢复扫描 SELECT * 遇可空列 NULL 整段静默 no-op(Task 宽结构体 5 个非指针可空列),已修窄投影 SplitRecoverRow(语义等价);同族脆弱仍在 task.Task/Shot 宽扫描面(生产 InsertTask 全列写不可达,人工/迁移行可达)——指针化 vs 维持全列写纪律待裁决;⑤seed Go 版一步到位差异:producer@xingmang.cn 独立账号(referral_code=QMXINGMANG01,与 demo 并存)+ 台账单笔 init(沿 SQL seed 惯例;冻结 demo 为 0 元 register 形态)Claude
v1.3-pending2026-10-18A1 落地(W8 十续期首核查,行④同族首例生产可达已裁决根治):seed.go 部分列 INSERT 沿冻结 seed.js:46 形态致 producer 示例任务 5 可空列落 NULL——ListByUser/ByID 宽扫描 500(集成实测红坐实);用户裁决 DDL 收紧:delta/0002 tasks 5 列+shots 2 列 UPDATE 回填+MODIFY NOT NULL(MySQL TEXT 无字面 DEFAULT——漏写列 strict mode 显式红=守卫语义)+seed INSERT 补列+full 重拼;C7 例外不动:videos.prompt/error 保持 *string NULL 透传(冻结语义);director_shots(M10)/workbench_tasks(M11)待域落地随域裁决;行④「生产不可达」陈述由本行取代;同票:prompt_templates 补种 5 行(对齐冻结 ensureSeed 存储面,Go prompts 内置不接线产物无差)Claude
v1.42026-10-18W10 对账落地(十一续期首核查后收尾,pending 行 :15-:21 内容全部入正文,行本身保留不改写):①端点数校准——M2 66→38、M3 38→19(routes.go 实装亲数口径,storyboard/generate 归 M2 组、models/active 补登 M3、M4 勘误「GET /api/export」实为 GET /api/export/:id 轮询面),合计 242→239(模块数直加恰合 v1/CLAUDE.md 实测冻结 239——原表直加 286 从未自洽),§3 表新增「Go 已实现」列(基础 3+M1M4 76=79,M5M12 全零=未排期);②M9 归属勘误(scriptlib.js 9+studio.js 16=25,二十五端点并非全在 scriptlib.js)+M9 节 Go 现状注记(404 系排期现状非回归);③M3/M4 实现差异、W6 容错与 NOW(3) 方言、恢复扫描窄投影、A1 DDL 收紧与 seed 一步到位差异全部入 §4/§5/§6 正文;④正文 pending 字样转正(§2.2 au_ 勘误/F8 定稿);⑤§6 workbench「随 M11」过时注记修正(W6 已四扫描全落地)Claude
v1.52026-10-18M9 落地 + uid 前缀全量复核(十三续):§3 表 M9 行 Go 已实现 25(合计 79→104);§2.2 uid 前缀表全量复核回填(冻结 47 前缀亲数——P0 误写 8 处勘误:lib_→sl_/nar_→na_/dp_→dpr_/rch_→ro_/rc_→cm_/wd_→w_/af_→fd_/w_→wk_ 错位,补缺 7 个 an_/ex_/ih_/inv_/me_/oa_/om_,ids_test.go 全量对拍守卫钉死);M9 实现差异七项入 §4 M9 节(upload 修复语义等);narrations type=‘video’ 扣 30 走 F9 同源 TryDeduct(taskId 空串=冻结 null)Claude
v1.62026-10-18十四续期首核查回写(A2B7C2→修复落地):§2.2 补登 pt_(B1,原 46/47);§4 M9 差异增 ⑧writers search TrimSpace 保持+登记(B5 用户裁决)/⑨narrations 台账 task_id '' vs null(B7)——二十一期⑤收口(0003 列 NULL 化):credits 域 INSERT 绑定 ''→NULL 单点收口,无关联台账行恒 NULL 对齐冻结 `taskId
v1.72026-10-19十五续(M12 管理后台落地 + 期首核查勘误):①期首核查 2026101823(A0B2C0)勘正——API-增量「admin 8」→9 两处(B-新1)、NEXT-SESSION「25 mutation」→24 口径(B-新2,归档段不回改);②M12 亲数勘误 36→39(41 物理 admin 路由 − withdrawals 2 归 M7;instruction-versions 通配展开+DELETE 漏登补齐),§3 合计 239→242(v1.3 校准时 M12 残留未清;v1 原合计 242 系巧合重合),根 CLAUDE.md 规模基线行同步;③M12 域落地 internal/domain/admin 39 端点(A 用户积分 8/B 生成审计 3/C 公告 3/D 组织审批 3/F 计费配置 4/G 模型接入 6/H 提示词中心 12;死端点 model-settings×2+instruction-versions/active 照抄;ErrNoUser 吞形保冻结信封;api_key 明文回显照抄+安全注记;instruction-versions DELETE 按修后语义打 prompt_templates——冻结查死表 instruction_versions 恒 404,F3 同制登记);④存量真 bug 修复:modelCfg.setting() key 未反引号恒 ERROR 1064(P0 起读侧模型配置链 LLMConfig/endpointByPurpose/genBilling.models 全哑,Mock 优先架构掩盖)——集成链「读侧即时生效」断言首证抓获,反引号一处修复;⑤跨域共表写归主域:task.AdminRetrySplit(retry-split 不删根资产=冻结原样)/generation.ClaimManualRelease(CAS+CONCAT(COALESCE) 一步);E1 面零改动,migrations 53 不变,delta 无 0003Claude
v1.82026-10-19十六续(期首核查 A1B2C0 修复 + M7 分销提现落地 + 亲数勘误):①期首核查 2026101900(十五续 bc216dd)——A1 ResetPassword 校验顺序与冻结相反(Go 先判长度后查存在 vs 冻结 index.js:140-142 先查存在),用户裁决修序对齐(admin/service.go + service_test 用例先红后绿);B1 §4 M12 补登记 ⑨providers/publish 反向死调用不实现=echo 404 兜底(上期计划承诺「PRD 登记一句」漏落);B2 根 CLAUDE.md 勘正日期微疵;②M7 亲数勘误 12→11(冻结 index.js :598-:638/:708-:737 亲数恰 11、§4 清单自列即 11——P0 统计残留第四例),§3 合计 242→241(上期 239→242 勘误时 M7 残留未清,亲数为准),M7 冻结源文件列勘正(11 条全在 index.js,recharge.js 仅承载返佣写入属 M8 链)、API-增量 合计节与根 CLAUDE.md 基线行同步;③M7 域落地 internal/domain/distribution 11 端点全量(integration 第七链 DistributionChain;零 credits 依赖/零 DDL/零 SSE;W_FLOW 严格邻接禁跳转;available「cancelled/rejected 不释放」冻结谎言照抄+集成双断言钉死;settings 双回退 shape/980 硬编码/exchanges 死态 quirks 逐字;差异 ①~⑩ 入 §4 M7 节);AdminView 提现 tab 404 面转绿(前端零改动);migrations 53 不变,delta 无 0003Claude
v1.92026-10-19十七续(期首核查 A0B2C0 回写 + M8 充值返佣落地 + 亲数勘误):①期首核查 2026101903(十六续 c2b2a29)——A 类 0 项;B1「service_test 13 场景」实为 10 测试函数(断言点无缺失,计数漂移,本段起以 10 为权威口径);B2 integCleanup 未扩 distribution 四表(M8 链落地时收口);②M8 亲数勘误 5→8(recharge.js 亲数恰 8、§4 清单自列即 8——P0 统计残留第五例,§4 清单一直正确而标题/§3 行少算,与 M7 同型反向),§3 合计 241→244(十六续 242→241 勘误时 M8 残留未清,亲数为准),根 CLAUDE.md 基线行同步;③M8 域落地 internal/domain/recharge 8 端点全量(integration 第八链 RechargeChain:config 对拍/下单 rate 换算/凭证真 multipart 落盘/approve 到账对账+两级返佣 8·2/资格联动 ≥980+已开不重复/reject 双截断/admin list 过滤/403/404;commission_records 唯一写入方收口=M7 差异①;approveOrder 冻结死导出不建恢复链;差异 ①~⑧ 入 §4 M8 节);integCleanup 扩 distribution 四表+recharge_orders(B2 收口);RechargeView/AdminView 充值面 404 转绿(前端零改动);migrations 53 不变,delta 无 0003Claude
v1.102026-10-19十八续(期首核查 A1B2C0 修复 + M6 组织协同落地 + 亲数勘误):①期首核查 2026101907(十七续 f27cd9a)——A1 recharge service_test 宣称 12 函数实为 11+三处承诺断言面缺失(rel2 缺失正向对拍/SSE payload/round2 小数域),补强至 12 函数(恰合宣称口径,历史段无需回改)+负样本演练两发先红后绿;B1 API-增量 头注「241」漏勘(本期随 235 一并收口);B2 归档计划「85」旧口径(append-only 登记权威口径,十七续段 82 为准);②M6 亲数勘误 38→29(冻结 index.js 组织段 9+enterprise.js 20=29、§4 清单自列即 29——P0 统计残留第六例,与 M7 同型「标题多算清单对」),§3 合计 244→235,根 CLAUDE.md 基线行「四轮亲数勘误」;③M6 域落地 internal/domain/org 单包多文件七件 29 端点全量(四零域:零 admin/零上传/零扣费/零 SSE 零通知;join 三写禁事务直译;权限分层 owner 严格 vs adminOrOwner 唯一面;normalizeMaterialPerms 联动纯函数;invite code crypto/rand 8 位大写 base36;integration 第九链 OrgChain:approve 建组织→invite/join→角色三哨兵→dashboard available==balance 钉死→material-perms 联动→showcase 恒 ok→share/search/401;integCleanup 扩组织八表+users.org_id 复位先于删 users,孤儿终验五零;执行期抓获 service percent 公式错(×1000 应 ×10——测试先红抓获即修);gorp 嵌套 struct 平铺教训两发〔Org 平铺/OrgMemRef 补 db tag〕);OrganizationView 等五视图 404 面转绿(前端零改动);差异 ①~⑩ 入 §4 M6 节;migrations 53 不变,delta 无 0003Claude
v1.112026-10-19十九续(期首核查 A3B4C1 修复 + C1 补投影 + M10 导演与融合落地):①期首核查 2026101908(十八续 9cab5dd)——A1 projectRank wire 键 json:"amount-kind" 勘误 kind(前端 OrganizationView「类型」列恒空白;wire 键集断言守卫自此入惯例:结构体字段断言不走 json tag);A2「孤儿终验五零」宣称无载体——TestIntegration_IntegCleanupLeavesNoOrphans 守卫落地(负样本注释清理 SQL 先红坐实);A3 perms_test 补非空无 view 归空正向用例+用例名勘误;B1 测试计数宣称漂移两处(service_test 实 20 函数/perms_test 实 2 函数 14 用例)本段为权威口径;B4 冻结底册 05 手册头注 239 旧口径+/api/api/ 双前缀 9 处记遗留(冻结区不回写);②C1 用户裁决补齐 shared-projects script_text 投影(冻结 dp.* 全列)+A4 勘正十八续误加谓词(projectRank task_id != ''/shared-projects video_id != ''——冻结 IS NOT NULL 对空串放行,「独立生成 / 工具」聚合行曾被整行挡掉;MySQL NOT NULL 列上 IS NOT NULL 即冻结字面);M6 差异 ⑪ 入 §4(assign 响应 null vs “");③M10 亲数复核 28 清点清白(director.js 11+fusion.js 17——§4 清单补列 convert/:eid 文字漏列而合计自洽);④M10 域落地 internal/domain/director 单包多文件 28 端点全量(integration 第十链 DirectorChain 扣费对账贯穿;双表通路 generation.ShotView.Tbl 显式传递+DirectorShotVideo;执行期抓获 InsertShot 冻结字面 0 错位存量 bug〔F3 同族——MySQL strict 恒 1265,修后语义登记〕+gorp 无字段列投影教训〔AssetJoined 实修〕;splitEpisodes 双阈值/fusion cost=3/convert 裸 pid 等 quirk 逐字);差异 ①~⑭ 入 §4 M10 节;integCleanup 扩 director 三表+孤儿终验扩七零;§3 Go 已实现 191→219(剩 M5 4/M11 12 共 16);migrations 53 不变,delta 无 0003Claude
v1.142026-10-19二十六期(期首核查 A1B3C0 修复 + e2e 基建 + spark 缺口补齐):①期首核查 2026101923(二十五期 6ee480f)——A1 shotCount「修后登记」实为回归(GET /tasks wire=驼峰 shotCount〔TaskWithCount json:“shotCount”,冻结 index.js:230 map 增强同源〕,二十五期误改蛇形 t.shot_count 恒显 0 镜;types Task 接口同错;DashboardView.test fixture 键 shotCount 反证;先红后绿修复+grep 守卫入 ci 3.6)+B 类 3 项回写(二十五期段「镜数恒空显」定性错误权威勘误/eslint+ci.sh 头注标签过时/interface 计数 86 口径);②e2e 基建(Playwright 双配置断言册+截图管线/dev-up env 参数化 qmtv_e2e:3301/e2e-verify 六项自检/docs/test/ 两册/冒烟 8 场景 13 用例全绿);③M13 spark 域补齐(internal/domain/spark 三件+routes 2 条+errRespond 哨兵+service_test/repo_gorp_test/integration 第十六链 SparkChain——e2e 巡检抓获的移植缺口,P0 统计残留第八例,合计 237→239+根 CLAUDE.md 基线行「八轮亲数勘误」);④SparkView faqs 死块填充真实文案(用户裁决);⑤ci 第四档 –e2e(显式 opt-in)Claude
v1.132026-10-19二十一期(期首核查 A3B4C0 修复 + 质量轨六项全裁落地):①期首核查 2026101920(二十续 dd0e1eb)——A1 Mock 评分 content 维整数除法截断(冻结 Math.round)/A2 runEval SSE done 帧 total 恒 0(Mock int 断言丢失)/A3 评估报告生成时间带时区后缀(%v 打 LocalTime 走 time.Time.String())三处先红后绿修复+B 类回写(API-增量首句 235→237 第三次同型+守卫、PRD M11 ⑧⑭ 补登、stale 注释);②质量轨六项(用户裁决):②api_key 明文回显收敛 json:"-"(前端零消费实证,M12 ④注记更新);③Refund 唯一口形态收口(task refundImage/evaluation 两处/admin ReleaseVideo 域外 release Add 归零+grep 守卫);④Task.ScriptText 指针化(0002 后唯一残余可空列);⑤delta 0003 credit_records.task_id NULL 化(credits 域 ''→NULL 绑定收口,M9 ⑨ 同步终结,打破「无 0003」边界正当推翻);⑥delta 0004 积分/佣金全链 DECIMAL(12,2) 七列(pay 佣金原值入台账亦入余额对齐冻结 REAL 亲和,M8 ①/M7 ⑥ 终结;credits 台账边界 float64 化,billing 价格整数面不动);⑦promptcenter 模板接线收口(shot_image/shot_video/asset_*×3 单级+eval_deep/eval_quick,split 三级沿 SplitTemplate 勿并;差异⑪/M10 ⑪/M11 ⑤ 终结,集成链「配置即生效」断言);集成对账 assertBal InDelta 化+⑤ NULL 行端到端断言;守卫③「gorp 禁指针 db 字段」下 Record.TaskID 保持值类型+COALESCE 读侧Claude
v1.122026-10-19二十续(期首核查 A3B4C1 修复 + 第七例亲数勘误 + M11/M5 收官落地):①期首核查 2026101910(十九续 bde1232)——A1 ref-videos 上传绑定结构体漏 form tag(multipart 恒不命中,前端当前未消费);A2 batch-generate ids:[] MySQL IN () 语法错 500 vs 冻结 400「所选资产均已生成」(SQLite 空列表容忍的方言边界);A3 episodes 详情 404 ’episode not found’ vs 冻结 :116 专属 ’not found’(共享哨兵分叉——仅此路由映射);B1 service_test 计数漂移(宣称 15 实 18)+B2 perms_test 口径 14→15(A3 补行未联动)+B3 孤儿终验口径三说并存+B4 M10 差异 ⑮ 补登(NULL vs ’’ 形态+Mock 台账 desc 参数化);②M11 亲数勘误 12→14(viral-analysis 2 条 index.js:490-513 无模块行认领而 §4 清单自列——P0 统计残留第七例,与 M8 同型反向),§3 合计 235→237,根 CLAUDE.md 基线行「五轮亲数勘误」Claude

1. 系统概览

AI 短剧内容生产线(拆解-出图-成片)+ 内容社区 + 积分商业化。单体后端,角色三档:游客(公开面)/ 用户(user)/ 管理员(admin)。

项值
Go 后端backend/,监听 :3300(与冻结版同端口,前端/代理零改动)
数据库MySQL 8 单库 qmtv_main(utf8mb4/InnoDB)
前端frontend/ 独立项目(v1.1 立项):初始 = 复制 qmtv/src 原样(行为对等零改动),dev :5173(vite proxy /api /files → :3300);终态 Go :3300 托管 frontend/dist。qmtv/ 冻结区转为对照基准,演进轨道见 §7
静态/files/* ← 素材目录(maxAge 1h);/* ← dist SPA fallback
模型接入管理后台注册 OpenAI 兼容端点(model_endpoints 表),无 Key 全站 Mock,零环境变量接 AI

模块编号 M1M13(v1.14 起含 M13 火花计划——原 M1M12 对齐冻结代码 12 个路由文件,spark 2 条系漏登第八例补入,全文引用)。「端点数」列 = 冻结目标口径(v1.3 W10 校准:M2/M3 的 P0 统计残留已按冻结实存改;v1.7 十五续:M12 36→39 亲数勘误——冻结三文件 41 条物理 admin 路由,withdrawals 2 条归 M7;v1.8 十六续:M7 12→11 亲数勘误——P0 统计残留第四例;v1.9 十七续:M8 5→8 亲数勘误——P0 统计残留第五例,§4 清单自列 8 而标题/本表少算,与 M7 同型反向;v1.10 十八续:M6 38→29 亲数勘误——P0 统计残留第六例,冻结 index.js 组织段 9+enterprise.js 20=29、§4 清单自列即 29 而标题/本表多算 9,与 M7 同型「标题多算」;v1.12 二十续:M11 12→14 亲数勘误——P0 统计残留第七例,viral-analysis 2 条(index.js:490-513)物理夹在 M5 通知段与 M6 组织段之间不属于任何模块行、§4 M11 清单自列 6+6+2=14——与 M8 同型反向;v1.14 二十六期:新增 M13 火花计划 2 条——e2e 全站巡检抓获 Go 零 spark 路由回溯冻结源码,index.js:739-766「火花计划」段 2 条端点从未入任何模块行亦未计入历史合计(P0 统计残留第八例,与第七例同型「无模块行认领」);「Go 已实现」列 = backend/cmd/server/routes.go 实装口径(2026-10-19 亲数):

模块冻结源文件端点数Go 已实现职责
M1 认证与用户index.js(认证段)99(P1)注册/登录/refresh/登出/me/积分流水分页/改密/改邮箱/工作台状态(v1.2 清点修正:原漏登 logout 与 credit-records)
M2 任务与拆解index.js + routes2 + routes3(task 段)3838(P2 W3)任务 CRUD、双引擎拆解、资产/分镜/重拆/场次(v1.3 W10 校准:66 系 P0 统计残留,实存 38——含 POST /api/images/storyboard/generate,routes.go 沿冻结物理段归 M2 组)
M3 生成与素材index.js + routes2 + routes3(生成段)1919(P2 W4)图片/视频生成、打标、独立工具、音频配音(v1.3 W10 校准:38 系 P0 统计残留,实存 19——含公开面 style-presets/faq 与 GET /api/models/active 补登;storyboard/generate 归 M2 组,剪映属 M4)
M4 导出交付index.js + routes2 + routes3(导出段)1010(P2 W5)ZIP 交付/剪映草稿/导出任务
M5 通知公告index.js44(W20)通知/未读数/已读/公告(读侧并入 notification 包——hub 同包零新建)
M6 组织协同index.js(组织段 :513-:597)+ enterprise.js2929(P2 W17)组织/成员/素材库/成员组/权限组/看板/作品墙/搜索(v1.10 十八续勘误 38→29:冻结亲数恰 29 条〔组织段 9+企业面 20〕、§4 清单自列即 29——原 38 系 P0 统计残留第六例,与 M2/M3/M12/M7/M8 同型「标题多算」)
M7 分销提现index.js(v1.8 勘误:11 条端点全在 index.js :598-:638/:708-:737,recharge.js 仅承载返佣写入逻辑属 M8 approve 链)1111(P2 W15)分销关系/返佣/提现状态机/兑换(v1.8 十六续勘误 12→11:亲数恰 11 条、§4 清单自列即 11——原 12 系 P0 统计残留,与 M2/M3/M12 同型第四例)
M8 充值recharge.js(8 条全在此文件 :28-:120,挂载点 index.js:27 app.use('/api', recharge.router),admin 4 条系 router 内写死 /admin/ 前缀拼出)88(P2 W16)订单/凭证/收款码/审核+两级返佣写入链(v1.9 十七续勘误 5→8:亲数恰 8 条、§4 清单自列即 8——原 5 系 P0 统计残留第五例,与 M2/M3/M12/M7 同型;§4 清单 8 条一直正确而标题少算,与 M7「标题多算」同型反向)
M9 剧本库与投稿scriptlib.js + studio.js2525(P2 W13)剧本市集/投稿工作流/编剧档案/解说成片(亲数核验:scriptlib.js 9 + studio.js 16 = 25,v1.3 W10 归属勘误——二十五端点并非全在 scriptlib.js)
M10 导演与融合director.js + fusion.js2828(W18)导演工作台/分集分镜/项目资源中心/融合生图
M11 评估与工具evaluation.js + workbench.js + index.js:490-513(viral——v1.12 勘正归入)1414(W20)剧本评估流水线/工作台工具/审片/爆款分析(v1.12:12→14 亲数勘误第七例)
M12 管理后台index.js(admin) + llmroutes.js + routes2(admin)3939(P2 W14)用户/积分/公告/组织审批/提现审核/模型接入/计费配置/提示词中心(v1.7 十五续勘误 36→39:41 物理路由 − withdrawals 2 归 M7,instruction-versions 通配展开+DELETE 漏登补齐——原 36 系 P0 统计残留,与 M2/M3 同型;withdrawals 2 端点随 M7 期落地)
M13 火花计划index.js:739-766(火花计划段——v1.14 补登)22(W26)join 报名(置位+台账+100+通知)/me 激励投影(submissions 三计数+三阶梯+环形 next_tier)(v1.14:PRD 清单从未登记——P0 统计残留第八例,与第七例同型「无模块行认领」)
基础index.js(SSE/health/release-mode)33(P0)SSE 事件流/健康检查/发布模式
合计239239(v1.14 二十六期校准:M13 火花计划 2 条补登后模块数直加=239〔3+9+38+19+10+4+29+11+8+25+39+28+14+2〕;v1.12 直加=237 系 spark 2 条未入任何模块行的第八例残留——亲数为准。Go 已实现 239 = 全量收官(W26 spark 2 落地;另有 SPA fallback 非 API);v1.10 直加=235 系 viral 2 条未入任何模块行的第七例残留——亲数为准。v1.12「Go 已实现 237=全量收官」系第八例残留口径(v1.14 勘误作废——W20 时 spark 2 条未在册);v1.9「直加=244」含 M6 统计残留未清——亲数为准。Go 已实现 219 = 基础 3 + M1~M4 76 + M6 29(W17)+ M7 11(W15)+ M8 8(W16)+ M9 25 + M10 28(W18)+ M12 39;另有 SPA fallback 非 API)

2. 全局契约(Go 版逐字节兼容面)

#契约规格违反后果
C1响应信封成功 {"ok":true,"data":<业务数据>};失败 HTTP 4xx/5xx + {"error":"<中文消息>"}。前端 api.js 解包 .data、抛 {status,message}前端全面崩
C2健康检查GET /api/health 裸 {"ok":true,"name":"QMTV"}(不走信封)监控误判
C3鉴权Authorization: Bearer <token>;token query 兜底与公开面见 §2.1401 面
C4token query冻结实为三分(v1.2 勘误):一般端点 authRequired 仅 Bearer(util.js:49,不认 query);GET /api/events 纯 query(index.js:151);GET /api/images/:id query 优先+Bearer 兜底(index.js:427,单端点内联)。Go 裁决(C3,2026-10-18):FromRequest 统一 Bearer 优先 + query 兜底(全局)——/api/events?token=(SSE)与 /api/images/:id?token=(img 无法带 header)单通道请求全兼容;行为面略宽于冻结(一般端点也接受 query),差异显式登记,守卫 scripts/frozen_contract_check.py 断言三分事实素材 401
C5SSEGET /api/events:text/event-stream,先发 event: connected\ndata: {}\n\n,25s 心跳 : hb\n\n,帧 event: <name>\ndata: <JSON>\n\n;五类事件 video/split/recharge/workbench/eval(payload 见 §4 各模块)实时进度失效
C6uid 格式<前缀>+UUIDv4(带连字符);前端存在 slice 截取依赖(routes2.js:368、enterprise.js:40)。前缀常量表见 §2.2前端截取错位
C7时间格式YYYY-MM-DD HH:MM:SS 本地时间字符串(SQLite 遗产,前端按此渲染)。Go 用 DATETIME(3)+DSN parseTime=true&loc=Local+LocalTime 类型序列化,禁 RFC3339时间显示错
C8密码哈希scrypt N=16384,r=8,p=1,keyLen=32,salt=16B hex,存储 salt:hash存量账号无法登录
C9错误文案中文消息有前端正则依赖(如 /所有者/、/密码/、429 操作过于频繁,请稍后再试、402 积分不足);错误码面(401/402/403/404/429/500/502)与冻结版一致前端提示错乱
C10限流内存桶:register 5 次/h/IP、login 20 次/min/IP(Go 版保持内存实现,集群期集中化)行为漂移
C11上传multipart,fixFilename latin1→utf8 文件名修复必须移植;模块限额:index 20MB/routes3 50MB/fusion 60MB/workbench 80MB/recharge 8MB/evaluation 10MB/scriptlib 2MB×20/llmroutes 2MB/director zip 20MB;JSON body 5MB中文文件名乱码
C12JWT三段标准 HS256(新签发,exp 秒)+ 两段 legacy 解析兼容(exp>1e12 按毫秒),claims {uid,rol,exp};secret:jwt.secret 配置优先,缺省生成持久化 data/.jwt_secret 等价物(bin 外持久文件)全员掉线

2.1 鉴权矩阵

级别端点
公开POST /api/auth/register、POST /api/auth/login、POST /api/auth/refresh、GET /api/health、GET /api/system/release-mode、GET /api/announcements/active、GET /api/style-presets、GET /api/support/faq
token query(Go:FromRequest 统一 Bearer 优先+query 兜底;此二端点为最小依赖端点)GET /api/events、GET /api/images/:id
Bearer(user)其余全部
Bearer + admin/api/admin/* 全部 + 提现审核/充值审核/组织审批/投稿审核等 admin 端点(各模块表内标注 🔒)

2.2 uid 前缀常量表(infra/ids 集中定义)

u_ 用户、t_ 任务、shot_ 分镜、as_ 资产、img_ 图片、si_ 分镜图槽(index.js:249/:289)、v_ 视频、vid_ Mock 视频落盘文件名(assets.js:39,与行 id v_ 解耦)、cr_ 积分流水、nt_ 通知、rt_ 刷新令牌、e_ 导出(v1.5 勘误:原写 ex_,冻结 index.js:458 实证)、wb_ 工作台任务(workbench.js:55)、ev_ 评估项目(evaluation.js:248)、dpr_ 导演项目(v1.5 勘误:原写 dp_,冻结 director.js:274 + fusion.js:230 实证;含 dir_+projectId 伪外键挂 assets.task_id)、dsh_ 导演分镜(director.js:68)、dep_ 导演分集(director.js:99 + fusion.js:235)、ih_ 图片历史(index.js:324/:356 + director.js:214)、sl_ 剧本库(v1.5 勘误:原写 lib_,冻结 scriptlib.js:131/:222/:247 + studio.js:146 实证)、su_ 剧本使用记录(scriptlib.js:206)、sub_ 投稿(studio.js:53)、wp_ 写手档案(studio.js:90/:143)、na_ 解说任务(v1.5 勘误:原写 nar_,冻结 studio.js:167 实证)、ro_ 充值单(v1.5 勘误:原写 rch_,冻结 recharge.js:40 实证)、up_ 上传文件、fu_ 融合项(fusion.js:160)、rv_ 参考视频(fusion.js:210 + workbench.js:193)、au_ 音频(v1.3 勘误:P0 误写 aud_,冻结 routes3.js:391 实证)、vo_ 配音、tts_ TTS(assets.js:65)、wk_ 作品(v1.5 勘误:原写 w_,冻结 enterprise.js:69 works 实证)、cm_ 佣金(v1.5 勘误:原写 rc_,冻结 recharge.js:72 实证)、w_ 提现(v1.5 勘误:原写 wd_,冻结 index.js:621 实证——w_/wk_ 曾错位)、ex_ 佣金兑换(index.js:634)、va_ 爆款分析(index.js:507)、org_ 组织、pg_ 权限组、pt_ 提示词模板(promptCenter.js:36 冻结实证;Go prompts 内置不读表,存储面见 prompt_templates 补种注记——十四续 B1 补登)、mg_ 成员组、fd_ 素材夹(v1.5 勘误:原写 af_,冻结 enterprise.js:93 实证)、al_ 资产库(routes3.js:75)、an_ 公告(seed.js:24 + index.js:678)、inv_ 组织邀请(index.js:539)、me_ 自定义模型(models.js:19/:61)、oa_ 组织申请(index.js:516)、om_ 组织成员(index.js:547/:698)、st_ 风格(静态 id)、rr_ 审片报告(与 referral_relations 共用前缀——冻结两表均 uid('rr_'),UUID 空间无冲突,v1.2 注记)。

v1.5 已按 grep -ohE "uid\('[a-z_0-9]+'\)" qmtv/server/*.js | sort -u 全量复核回填(冻结 47 前缀亲数),Go 侧 51 常量(含基建 4)以 backend/internal/infra/ids/ids_test.go 全量对拍守卫钉死(TestPrefixes_FrozenContract)。

3. 修正项(冻结行为 → Go 行为)

#项冻结行为Go 行为兼容影响
F1refreshToken 真轮换refresh_tokens 从不 INSERT,/api/auth/refresh 恒 401(靠 72h access token 掩盖)登录签发 refreshToken 落库(SHA-256 hash 唯一);刷新=校验(未撤销未过期)→撤销旧+签发新(轮换,replaced_by 串链);登出/改密撤销全部;refresh 响应增 refreshToken 字段refresh 端点从必 401 变可用;前端 api.js:24 须消费轮换返回的新 refreshToken——P1 同期补丁(W9a):冻结版前端刷新后复用旧值,真轮换下首次刷新即撤销旧 token,旧前端将在 72h 后被强制登出;存量用户重登一次
F2原子扣款tryDeduct check-then-set(SELECT 后 UPDATE)非原子,并发可透支为负单条 CAS:UPDATE users SET credits=credits-?, version=version+1 WHERE id=? AND credits>=?(version 仅自增不入谓词——MySQL 行锁下 credits 谓词已原子防超扣,v1.2 微调),affected=0 判余额不足。v1.3 尾注(P1 实测+P2 定稿):该谓词下 affected=0 ⇔ 余额不足,不存在版本冲突路径——optimistic.RunWithRetry 不引入(qmtv/pms 双侧零生产调用,无原型);跨聚合时序定稿见 §6前端无感;并发下不再超扣
F3export_tasks.shot_countINSERT 引用该列但建表缺失(新库导出必报错的存量 bug)建表含 shot_count INT NOT NULL DEFAULT 0修复
F4providers 死表建表但无任何代码读写裁剪不建无
F5JWT 标准化两段式 body.sig、exp 毫秒、!== 非常量时间比对三段 HS256、exp 秒、hmac.Equal 常量时间;双格式解析一个发布周期(两段+exp>1e12 判毫秒)新旧 token 并存过期(≤72h 自然过渡)
F6计费双层口径统一入口util.COSTS(老接口硬编码)与 system_settings(routes2 覆盖价)并存,视频价两套保留双层语义但统一经 billing 服务读取(COSTS=代码兜底默认,settings 键存在则覆盖);键名清单冻结:trial_credits,text_tokens_per_credit,image_generation,video_pull,video_per_second,image_model,video_model,text_model,image_model_fallback,provider_routing(v1.7 勘误:image_model_fallback 冻结 routes2.js:34 原文名,本行曾误写 image_fallback_model)+ 评估价 eval_quick,eval_deep老接口价格若有 settings 覆盖则行为变化(对齐管理端配置的预期语义,PRD 评审已确认)
F7邮箱校验统一(v1.2 新增)register 用损坏正则 /^[^@s]+@[^@s]+.[^@s]+$/(index.js:80——\s 丢失反斜杠,实际仅要求「@ 后非空」,垃圾邮箱可注册);PUT /api/auth/email 用严格版(index.js:130)统一严格版 /^[^@\s]+@[^@\s]+\.[^@\s]+$/(单一校验器,register/email 共用)垃圾邮箱注册被拒;正常邮箱无感(用户裁决 2026-10-18)
F8素材对象存储(v1.2 新增,C4 裁决;v1.3 按落库终态定稿)本地磁盘 data/files + /files 无鉴权 static + file_path 落库存 /files/... 相对 URLinfra/storage 三实现:MinIO(192.168.50.190 共享实例,独立 bucket qmtv)/本地磁盘(files.dir 兜底)/Noop(endpoint 空降级 ErrNotConfigured);落库 file_path:MinIO 模式 public_base 非空=终态绝对 URL(C1 裁决,前端逐字消费;桶/域迁移需一次性 UPDATE file_path),public_base 空=相对 /{bucket}/{key};local 模式=/files/ 相对(=冻结形态);ObjectKey 日期分目录+随机 hex 防穿越。v1.3 布局差异登记:冻结产物扁平落 files/(img_x.svg),Go ObjectKey 产 files/yyyyMMdd/x.svg 日期子目录(同 LocalDir 混居)——前端只整串消费 URL 无感,/files 静态映射目录树天然可达前端 URL 消费不变;备份语义变「DB+桶」两件套(DEPLOY 同步);P1 无 HTTP 消费者(M8 留后续期),接口本期定型
F9退款防重唯一口(v1.3 新增,修冻结漏洞)退款=addCredits(cost,'release') 散布 providers 三处+启动恢复+管理端;videos.refunded 置位仅覆盖 Mock 失败与轮询失败两路——视频提交失败(providers.js:129)与启动恢复(index.js:800)退款不置位,其后仍满足管理端 status='failed' AND NOT refunded 条件可二次退款;images 无防重列(同步路径天然无二次退款面,维持不设防)新增 credits.Refund 唯一退款口:videos 路径先 CAS UPDATE videos SET refunded=1 WHERE id=? AND refunded=0(affected=0 ⇒ 已退,幂等跳过)再退积分;全部失败路径(providers 提交/轮询/下载失败、启动恢复)收口于此。置位与退款两步无事务(禁事务铁律),中断窗口=补偿式一致性既有边界修复双退款漏洞;存量演示库若有「已 failed 未置位」行,启动恢复首跑会补置位+补退款(风险登记 P2 计划)

4. 端点契约清单(M1~M13 + 基础)

表列:方法 路径|鉴权(默认 Bearer,🔒=admin,公开面标注 ○)|一句话契约。请求/响应字段以冻结代码为准,FSD 阶段逐模块细化(含字段表/校验规则/错误码)。

基础

端点鉴权契约
GET /api/health○C2 裸格式
GET /api/eventstoken querySSE 流(C5),连接先发 connected
GET /api/system/release-mode○{ok,data:{mode:'stable'}}

M1 认证与用户(9,v1.2 清点修正)

端点鉴权契约
POST /api/auth/register○ 限流5/h送 200 积分(trial_credits 可配,F6 Billing 读取——冻结硬编码不读 settings,属刻意差异);invite_code 命中建分销关系+邀得 50 积分;referral_code=QM+6位随机大写;F7 邮箱严格版
POST /api/auth/login○ 限流20/min返回 {token,refreshToken,user}(F1:refreshToken 真实签发)
POST /api/auth/refresh○F1 真轮换;响应含新 refreshToken;停用用户 401(安全收敛)
GET /api/auth/meBearerpublicUser 字段集:id/email/nickname/role/credits/org_id/workspace_version/referral_code/affiliate_enabled/created_at
POST /api/auth/logoutBearer冻结无服务端状态清除;Go F1:撤销该用户全部 refreshToken(v1.2 补登)
GET /api/auth/credit-recordsBearer全局积分流水分页(size 20,{list,total,page},created_at DESC,id DESC)(v1.2 补登)
POST /api/auth/change-passwordBearer改密后撤销全部 refreshToken
PUT /api/auth/emailBearer需密码确认;F7 严格版
PUT /api/auth/workspace-stateBearer工作台版本状态存 users.workspace_version

M2 任务与拆解(38,v1.3 W10 校准:标题「66」系 P0 统计残留)

端点实装清单见 docs/API-增量.md M2 节(38 条逐条)。归组注记(v1.3 W10):POST /api/images/storyboard/generate 物理位于冻结 index.js 生成段,routes.go 沿冻结分组归 M2 组(:141)——本节正文按实装口径收录。

CRUD:GET/POST /api/tasks、GET/PUT(title)/DELETE /api/tasks/:id、POST /api/tasks/:id/duplicate。 拆解双引擎:POST /api/tasks/v2(llm.isAvailable→异步 LLM 拆解/Mock 同步,split_status 状态机 idle/processing/done/failed/fallback——注〔三十期〕:idle/fallback 两态冻结与 Go 均无写入点,实现差异见 FSD m02 F2.03 §6;实际三态 done/processing/failed,DDL 默认 done)、POST /api/tasks/:id/resplit(20 积分)、POST /api/tasks/:id/restart、POST /api/tasks/:id/continue(对缺图镜头按 image_cost 补扣)、POST /api/tasks/:id/mark-failed 🔒、POST /api/tasks/:id/scenes/auto-generate(+ /cancel)。 资产:POST /api/tasks/:id/assets/extract 与 /extract2(2K,image_cost×N)、PUT /api/tasks/:id/extract-settings、POST /api/assets/:id/image/upload、POST /api/assets/:id/regenerate、POST /api/assets/:id/derive(衍生变体,parent_id)。 分镜:GET /api/tasks/:id/full 与 /full2(尾帧参考版)、GET /api/tasks/:id/scenes2、PUT/DELETE /api/tasks/:id/scenes/:groupNo、PUT /api/shots/:id、DELETE /api/shots/:id、POST /api/shots/:id/slots、DELETE /api/shot-images/:slotId、GET /api/shots/:id/histories、PUT /api/shots2/:id/params、POST /api/tasks/:id/storyboard-batch(批量补图)、POST /api/images/storyboard/generate(单镜补图,v1.3 W10 归组注记见上)。 资产库联动:GET/POST /api/asset-library、POST /api/asset-library/:id/share、DELETE /api/asset-library/:id、POST /api/tasks/:id/library-apply/:libId。 积分明细:GET /api/tasks/:id/credit-records。

M3 生成与素材(19,v1.3 W10 校准:标题「38」系 P0 统计残留——render-all 实属 M4、retry 无用户端点)

端点实装清单见 docs/API-增量.md M3 节(19 条逐条)。POST /api/images/storyboard/generate 归 M2 组(见 M2 归组注记)。

图片:POST /api/images/generate(COSTS.image,失败 providers 内部退款)、GET/DELETE /api/images/:id、GET /api/images、POST /api/images/upload。 视频:POST /api/videos/generate(COSTS.video)、POST /api/videos/generate-v2(videoCost(secs)=video_pull+per_second×secs,secs 1-15,reso 720p/1080p)、POST /api/videos/:id/cancel(cancelled 不退款)、POST /api/videos/tag(10×镜数)、GET /api/videos、GET /api/standalone-videos。 音频:GET/POST /api/audios、DELETE /api/audios/:id、POST/GET /api/videos/:id/voiceover(Mock WAV 字节级兼容)。 公开/辅助面:GET /api/style-presets ○(19 种风格预设)、GET /api/support/faq ○(静态 6 条)、GET /api/models/active(getBilling 投影——v1.3 W10 补登,PRD 原文全篇未列该端点;消费方 DashboardView/VideoView/Director3DView 三处〔三十期勘正,Director3DView 系 M10 落地后新增〕)。 异步契约:有 Key 时 video 提交→轮询(8s 首查/10s 步进/90 次上限)→SSE video 事件(done/progress/failed);失败 refunded=1 防重退款。

实现差异(v1.3 W10 入正文,Go 实装 vs 冻结行为,全部显式登记):①expires_at=C7 例外全达成(冻结 toISOString() 入库透传;Go ISOTime 响应 ISO、落库仍 DATETIME(3));②SmartVideo ⑩ 分辨率白名单外值(如 480p)冻结原样透传 vs Go 归一 1080p、ratio null 冻结传 null vs Go 归一 16:9(Go 收紧向,安全);③SSE progress 冻结每次 fetch 前发 vs Go fetch 后发(tries 命中集合相同);④tag 打标价冻结固定 COSTS.image=10 vs Go 随 F6 settings 覆盖价。

M4 导出交付(10)

POST /api/export(2 积分×完成段数,shot_count)、GET /api/export/:id(导出任务轮询面)、GET /api/export/task/:taskId(查重防重复扣费)、GET /api/tasks/:id/export/assets-deliver(2K 资产 ZIP)、GET /api/tasks/:id/export/deliver(全量 ZIP)、POST /api/tasks/:id/export/tag-all、POST /api/tasks/:id/export/render-all(Σ videoCost 批量渲染)、GET /api/tasks/:id/export/history、PUT /api/tasks/:id/export/scenes/:sid、GET /api/tasks/:id/jianying-draft(剪映草稿 JSON)。

实现差异(v1.3 W10 入正文):①history 响应 v.* 列序——冻结 created_at 在 error 之后(db.js CREATE 后 ALTER 折叠序)vs Go DDL/struct 排末位:键集一致、前端按键取值无感,严格逐字节对拍不齐;②assets-deliver 条目名 index_no=0——冻结 JS truthy→asset_ vs Go != nil && != 0→shot000_(W6 期已修对齐冻结 truthy 语义);③export repo 接口实为 16 方法(W5 基线「17」系计数漂移);④F3 修正兑现——冻结 export_tasks 无 shot_count 列而 INSERT 显式引用(导出必报错存量 bug),Go DDL 含该列按修后语义(P0 裁决)。勘误(v1.3 W10):本节原列「GET /api/export」系 P0 清单误计——冻结实存的是 GET /api/export/:id 轮询端点,无列表端点。

M5 通知公告(4)

GET /api/notifications、GET /api/notifications/unread-count、POST /api/notifications/read、GET /api/announcements/active(○;前端 localStorage qmtv_dismissed 由前端自理)。

✅ M5 落地(2026-10-19 W20,internal/domain/notification 读侧——hub 同包零新建):App.vue 铃铛三面/AccountView 摘要 404 转绿(前端零改动)。实现差异登记:①read MySQL 保留字全 SQL 反引号(auth/repo.go:130 先例同制);②POST read 无 id=整用户全标已读+恒 ok(true) 无 404 面(id 不属于自己也静默——冻结 :480-483 quirk 照抄);③announcements/active 公开端点无 amw(冻结 :485 无 authRequired);④通知零 SSE(前端 60s 轮询 unread-count)+读侧行形态兼容五源写入(auth/admin/recharge/seed/evaluation 自持 INSERT)。 | Claude |

M6 组织协同(29,v1.10 十八续勘误:标题「38」系 P0 统计残留——冻结亲数恰 29 条〔index.js 组织段 9 + enterprise.js 20〕,下清单即全量;与 M7 12→11 同型「标题多算清单对」第六例)

组织:POST /api/organizations/applications、GET /api/organizations/me、PUT /api/organizations/me/credit-allocation-mode(pooled/independent)、POST /api/organizations/me/invites、POST /api/organizations/join、DELETE /api/organizations/me/members/:memberId、PUT /api/organizations/me/members/:memberId/role(非 owner 拒,文案含「所有者」)、POST /api/director3d/:id/share、GET /api/organizations/shared-projects。 企业:GET /api/organizations/me/dashboard(冻结积分+14 天趋势+双排行)、GET/POST /api/showcase、DELETE /api/showcase/:id、素材库目录树 GET/POST /api/organizations/me/material/folders(+DELETE :id)、GET /api/organizations/me/materials、POST /api/organizations/me/material/assign、成员组 GET/POST /api/organizations/me/groups(+DELETE)、权限组 GET/POST/PUT/DELETE /api/organizations/me/perm-groups*、PUT /api/organizations/me/members/:memberId/assign、GET/PUT /api/organizations/me/material-perms*、GET /api/search(全站搜索)。 容量:素材 10GB 配额(images.file_size/audios.size 聚合)。

✅ M6 落地(2026-10-19,backend/internal/domain/org 单包多文件七件 29 端点全量):integration 第九链 OrgChain(M12 approve 建组织→invite/join 全链→角色面三哨兵→dashboard available==balance 钉死→material-perms 联动端到端→showcase 恒 ok→share/search/401 面)。实现差异登记:①credit-allocation-mode 死端点照抄(前端零消费方,mode 非 independent 一律 pooled);②dashboard available 恒=balance 无任何过滤+frozen 仅 eval_projects status=‘running’(M11 未落地恒 0)+projectRank dir_ 前缀死分支(实产 dpr_ 永不命中且 slice(4) 偏移亦错)——三处冻结谎言/死分支照抄不修,集成链钉死;③works.cover_path/asset_folders.org_id/member_groups.leader_id 等 Go DDL NOT NULL DEFAULT ’’ vs 冻结可空——读侧 NULLIF 还原 null(recharge ⑦ 先例);④素材 10GB 配额系估算法非真 SUM(images.sum(file_size)+NULL 数×80KB+audios.sum(size)+videos 数×2MB 系数硬编码,plan 恒「基础档」,percent toFixed(1) 等价 Round(pct×10)/10);⑤org_applications company/contact/reason 冻结不 slice 不 trim——Go VARCHAR(128) strict 溢出报错(SQLite 动态类型照收),超长输入行为差异;⑥invite code 冻结 Math.random base36 截 8 位大写 vs Go crypto/rand 同字母表(形态等价 ^[A-Z0-9]{8}$,值域随机性不属契约面);⑦organizations.credits/org_members.quota/credit_allocation_mode 三列冻结无读写消费方(pooled/independent 分账完全未接线)——空转照抄;⑧DELETE /showcase/:id 与 DELETE /organizations/me/groups/:id 不查行数恒 ok:true(删他人/不存在均静默);groups DELETE 无 404 面(403 后恒 ok);⑨members target 不存在与 target 是 owner 合并同一 400「无法移除」(非 404 quirk);⑩invites 文案「仅组织管理员可邀请」而判定 role=‘owner’ 严格(quirk 照抄,:553 移除面同款);⑪PUT members/:memberId/assign 响应 group_id/perm_group_id 缺省时冻结回 null vs Go 回 ""(响应面未走读侧 NULLIF 还原——前端 assign 后重拉列表非回归,十九续 B3 登记)。十九续勘正(2026-10-19):dashboard projectRank 谓词十八续误加 task_id != '' 曾把空串消耗聚合行(冻结 :37 IS NOT NULL 放行,以缺省名「独立生成 / 工具」kind=工具 GROUP BY 上榜)整行挡掉——已还原逐字+集成钉守(A4);shared-projects video_id 谓词同批还原 IS NOT NULL(MySQL NOT NULL 列上即冻结字面);shared-projects 投影补 script_text(冻结 dp.* 全列,组织共享面下发全剧本即冻结语义,用户裁决补齐);projectRank wire 键 json:"amount-kind" 勘误 kind(A1,前端 OrganizationView 「类型」列曾恒空白——wire 键集断言守卫自此入惯例)。 | Claude |

M7 分销提现(11,v1.8 十六续勘误:标题「12」系 P0 统计残留——冻结亲数恰 11 条〔下清单即全量〕,与 M2 66→38/M3 38→19/M12 36→39 同型第四例)

GET /api/distribution/overview、GET /api/distribution/downlines、GET /api/distribution/records、GET/POST /api/distribution/withdrawals(状态机 pending→reviewing→topay→paid→done / rejected / cancelled)、POST /api/distribution/withdrawals/:id/cancel、POST /api/distribution/withdrawals/:id/confirm、GET/POST /api/distribution/exchanges、PUT /api/admin/withdrawals/:id 🔒、GET /api/admin/withdrawals 🔒。返佣:充值到账两级返佣(commission_rate/level2_rate 可配,默认 8%/2%);满 980 元自动开 affiliate_enabled。

✅ M7 落地(2026-10-19,backend/internal/domain/distribution 单包多文件 11 端点全量):integration 第七链 DistributionChain(seed 对拍 40 佣金/0.08-0.02-100/状态机全迁移/cancelled·rejected 不释放额度端到端钉死/exchanges 占扣/403/404 面)。实现差异登记:①withdrawals/exchanges 冻结的是佣金台账而非 users.credits——POST 两写面不触 credits/credit_records/通知/SSE,域零 credits 依赖(返佣写入方在 M8 approve 链,未落地前仅 seed 行可达);②available 分母 SUM(withdrawals.credits) 无 status 过滤——cancelled/rejected 工单永不释放额度,:715 note「收益已解锁」与行为相悖系冻结谎言照抄不修(集成链 ⑨⑩ 双断言钉死);③overview pending_withdraw 冻结双 IN 冗余(四态 AND 三态)→ Go 等价单 IN 三态(结果逐位一致,repo 注释钉行号);④settings 回退三体 quirk:overview 无行回退 {0.2,0.05,100}(无 id 键)与 POST 提现面回退仅 {min_withdraw:100} 各自独立(Go 两 shape 不共用),种子行 0.08/0.02/100 覆盖表默认;⑤affiliate_threshold 硬编码 980(非 system_settings affiliate_threshold_cny,与 recharge.js:25 不同源)照抄;⑥credits 请求绑定 float64(冻结 +req.body.credits 强转)入库 int64(MySQL BIGINT 舍入 vs SQLite 动态类型可存小数——前端常态整数无差)——二十一期⑥ DECIMAL(12,2) 收口(0004):withdrawals/exchanges credits 原值入库,差异终结;⑦reviewed_at 冻结 now()=UTC ‘YYYY-MM-DD HH:MM:SS’ 字符串 → Go time.Now().UTC() 显式(与 auth LocalTime 本地时先例刻意不同源);⑧admin PUT 状态机 W_FLOW 严格邻接校验禁跳转(终态无键恒 400),动态文案 不允许从「X」流转到「Y」 W_ZH miss 原样回显英文态;⑨exchanges.status 恒 ‘pending’(全冻结无 UPDATE,死态照抄);⑩withdrawals 2 条 admin 端点在本域(M12 裁决归 M7),AdminView 提现 tab 404 面转绿。

M8 充值(8,v1.9 十七续勘误:标题「5」系 P0 统计残留第五例——清单自列恰 8 条而标题少算,与 M7「标题多算」同型反向)

✅ M8 落地(2026-10-19,backend/internal/domain/recharge 单包多文件 8 端点全量):integration 第八链 RechargeChain(config 对拍/下单 rate 换算/凭证真 multipart 落盘/approve 到账对账+两级返佣 8·2/资格联动 ≥980 自动开通+已开不重复/reject 双截断/admin list status 过滤/403/404 面);integCleanup 扩 distribution 四表+recharge_orders(十七续 B2 收口,M8 链起共享清尾)。前端零改动(RechargeView/AdminView 充值面 404 转绿)。实现差异登记:①commission_records 唯一写入方在本域 approve 链(M7 差异①就此收口),order_amount/commission 绑定 float64→MySQL BIGINT round——冻结 SQLite INTEGER 列收 REAL 靠亲和性存原值(如 33 元二级佣金冻结存 0.66 并入账 0.66)——二十一期⑥ DECIMAL(12,2) 全链收口(0004):pay 佣金原值入台账亦入余额,差异终结;②reviewed_at/reviewed_by——冻结 now()=UTC ‘YYYY-MM-DD HH:MM:SS’(recharge.js:93 与 M7 同源)→Go time.Now().UTC() 显式(M7 差异⑦同制);③credits.Add ErrNoUser 显式 vs 冻结 addCredits 静默(util.js:66)——approve 链容错对齐(返佣 inviter 不存在冻结照写台账继续),其余 DB 错误照冻结 throw 传播;④settings 值非数字冻结 NaN→JSON null,Go 回退默认(settings 经 admin 白名单管理常态数字串不可达);⑤affiliate_threshold 读 system_settings affiliate_threshold_cny 默认 980——与 M7 overview 硬编码 980 两处刻意不同源(M7 差异⑤),勿统一;⑥approveOrder 冻结导出「供重启复用」系死代码零消费方——Go 不建恢复链;⑦proof_path Go DDL NOT NULL DEFAULT ’’ vs 冻结可空——读侧 NULLIF 还原 null 透传(export normalizeExportTask 先例同制);⑧二级返佣 from_user_id 恒=充值人(冻结 :78/:80 两级 pay 均传 o.user_id,非链上级)。

GET /api/recharge/config(1 元=N 积分 settings 面+收款码+推广阈值 980 默认)、GET/POST /api/recharge/orders(金额两位舍入/≥1 元/≤10 万;orderNo=‘RCH’+毫秒+3 位随机)、POST /api/recharge/orders/:id/proof(凭证上传 8MB,multer 两路由共用限额)、POST /api/admin/recharge-orders/:id/approve 🔒(到账+两级返佣+SSE recharge 事件+单笔达标自动开推广资格)、POST /api/admin/recharge-orders/:id/reject 🔒(note 落库截 200/通知截 100 缺省「凭证有误」两处不同源)、GET /api/admin/recharge-orders 🔒(status 过滤,‘全部’ 或空=不过滤,LIMIT 200)、POST /api/admin/pay-qrcode 🔒。

M9 剧本库与投稿(25)

Go 实现现状(v1.3 W10 盘点,P2 排期范围外):M9 全部 25 端点 Go 零实现——前端剧本库弹窗/市集对 Go 后端 404 系排期现状非回归(迁移前后行为一致)。归属亲数勘误:scriptlib.js 9(genres/list/:id/use 四件 + admin script-library GET/POST/PUT/DELETE 四件 + upload 一件)+ studio.js 16(market/scripts 二件、投稿 submissions 四件、编剧 writer-profile 二件、writers 二件、admin/submissions 审核二件、admin cover+rating 二件、tools/narrations 二件)= 25。

✅ W13 落地(2026-10-18,backend/internal/domain/scriptlib 25 端点全量):routes.go M9 组恰 25 条亲数;AdminMiddleware 接线 9 admin 端点(403 forbidden;十四续 B3 勘误「8」=scriptlib 5+studio 4 亲数);integration 第五链 ScriptlibChain(ensureSeed 首触/submissions 全链/admin review publish 多表写/narrations 扣费 30 对账恒等式);前端消费面 URL 不变零改动(Dashboard 弹窗/ScriptLibraryView/StudioView/WritersView/AdminView/IndependentToolsView 404 面转绿)。实现差异登记:①admin upload 修后语义——冻结 scriptlib.js:248 run 传 16 参数对 9 占位符,better-sqlite3 绑定超占位恒 throw RangeError(已实测坐实),冻结版 upload 端点从未可用,Go 按 9 列 INSERT 修后实现(F3 同制);②cover_path 落库走 F8 口径(MinIO 绝对 URL/local /files/ 相对),冻结恒 /files/ 相对;③upload GBK 回退用 GB18030 解码(WHATWG TextDecoder(‘gbk’) label 实走 gb18030 算法);④upload/cover 限额=路由级 BodyLimit(45mb/10mb)+handler 单文件校验(2MB/超 20 文件按 multer 语义 500),冻结 multer fileSize 单文件限制;⑤length()→CHAR_LENGTH(MySQL length 为字节数);⑥char_count/preview/catalog 截断按 rune(JS UTF-16 BMP 等价,gateway.Err 300 rune 先例同制);⑦go.mod 无新增依赖(golang.org/x/text 已在 indirect 转直接);⑧writers 列表 search Go 侧 TrimSpace 后 LIKE(冻结 studio.js:105 直用原值不 trim)——用户裁决保持+登记(检索体验更稳;market 端点 search 与冻结一致不 trim,两处刻意不同源,repo.go 注释在);⑨narrations 扣费台账 task_id 落 '' 而非冻结 null(credits.Record.TaskID 为 string 非 *string,沿既有 credits 模型形态——二十一期⑤已收口:0003 列 NULL 化+域内 ''→NULL 绑定;冻结 studio.js:158 tryDeduct 第 4 参 null)——credit-records 响应形态微差,待 credits 模型指针化时一并(十四续 B7 正文差异清单补登,v1.5 修订行已有同义注记)。

市集:GET /api/script-library/genres(含 markets/audiences/forms 配置)、GET /api/script-library(五维筛选/排序)、GET /api/script-library/:id(目录+试读)、POST /api/script-library/:id/use(7 日热度)、GET /api/market/scripts、GET /api/market/scripts/:id。种子幂等回填逻辑(ensureSeed)保留。 投稿:GET/POST /api/studio/submissions、PUT /api/studio/submissions/:id、POST /api/studio/submissions/:id/submit(draft→pending)、编剧档案 GET/POST /api/studio/writer-profile、GET /api/writers、GET /api/writers/:id。 管理:GET/POST /api/admin/script-library、POST /api/admin/script-library/upload(20 文件×2MB)、PUT/DELETE /api/admin/script-library/:id、POST /api/admin/script-library/:id/cover、PUT /api/admin/script-library/:id/rating、GET /api/admin/submissions、POST /api/admin/submissions/:id/review 🔒(needs_change/rejected/published;publish 自动建档+入库)。 解说:POST/GET /api/tools/narrations(30 积分,Mock WAV)。

M10 导演与融合(28)

导演:GET/POST /api/director3d、DELETE /api/director3d/:id、GET /api/director3d/:id、POST /api/director3d/:id/resplit、GET /api/director3d/episodes/:eid、POST /api/director3d/:id/episodes/:eid/extract-assets、POST /api/director3d/:id/episodes/:eid/shots(确定性 9 字段分镜)、PUT /api/director3d/shots/:id、POST /api/director3d/shots/:id/generate-image(-video)、GET /api/director3d/:id/export(ZIP)、POST /api/director3d/import。双表通路:director_shots 与 shots 并存,providers 按 shot._tbl 路由(Go 版以表名字段显式传递)。 融合:GET/POST /api/director3d/:id/assets、POST /api/director3d/assets/:id/generate(3 积分)、POST /api/director3d/:id/assets/batch-generate、POST/DELETE /api/director3d/assets/:id/queue*、GET /api/director3d/:id/queue(持久化队列 recoverQueue)、POST /api/director3d/:id/assets/import、POST/GET /api/director3d/:id/fusion*(融合生图)、POST /api/director3d/:id/remix(30 积分一键转剧)、GET/POST /api/director3d/:id/ref-videos*、DELETE /api/director3d/ref-videos/:id、POST /api/director3d/:id/convert/:eid(30 积分一键转剧——v1.11 勘正补列,原清单文字漏列而合计 28 自洽)。

✅ M10 落地(2026-10-19,backend/internal/domain/director 单包多文件 28 端点全量〔director.js 11+fusion.js 17——亲数 11+17=28 清点清白〕):integration 第十链 DirectorChain(建项目→分集→分镜→分镜图/视频扣费对账恒等式贯穿→资产提取/生成/队列→融合/改创→参考视频→export ZIP 魔数→import ZIP→一键转剧→resplit→属主 404/401)。实现差异登记:①splitEpisodes 双阈值(resplit 1200/fusion CreateProject 800)刻意不同源勿统一(合参参数化);②splitScenes 锚点前残余段亦成场景(「第一集 开端」头成 scene 目标——冻结 lookahead split 语义照抄,集成实测 5 目标坐实);③「道具:」的「道具」二字亦命中 character 正则(冻结 :140 quirk 照抄);④InsertShot 冻结字面 0 错位(:179 列 15 VALUES 16——字面 0 落 resolution、attempts 落 resolution 字符串,SQLite 动态类型容忍的存量 bug;F3 同族)——MySQL strict 恒 1265,Go 按修后语义 15 列 15 ?(resolution=草稿值/attempts=0)登记;⑤videoSmart Mock 分支 UPDATE shots 硬编码(providers.js:91 真实分支才按 tbl 路由)——导演分镜 Mock 生成后分镜行不回填(0 行静默),Go 按 tbl 意图语义打 director_shots(ShotView.Tbl 显式传递——PRD 双表通路约定落地);⑥episodes 面 eid↔project 无关联校验(ep 按 eid 查活、project 按属主查——跨项目 eid 可达 quirk 照抄);convert 例外(:256 WHERE id AND project_id 关联逐字);⑦fusion cost=3 / convert flat=30 硬编码(非 ImageCost 面)+convert taskId=裸 p.id(非 dir 前缀,:259 照抄);⑧convert 空场次:冻结 scene.split TypeError 恒 500(fallback 对象调 split)——Go 按意图语义以 ep.title 单场生成登记;⑨extract-assets 逐张生成失败 continue 不中断(冻结 providers.imageSmart 内部退款等价形态——域内 Refund 唯一口退单价 nil claim,调用方不重复退);⑩assets/images 行 task_id=‘dir’+project_id 约定(M6 projectRank 聚合面依赖);⑪promptcenter 模板查库面沿 M2 同源不查 prompt_templates(内置默认渲染——getShotImagePrompt 冻结有 getActive 查库,M2 起未接线,差异沿袭)——二十一期⑦已接线收口(shot_image/shot_video/asset_*×3 单级查库+内置默认回退,split 三级沿 SplitTemplate);⑫buildShotFields JSON 键序 Go map 字典序 vs JS 插入序(JSON 对象语义等价,前端按键取);⑬AssetJoined 等 JOIN 投影不选无字段列(gorp 反射报错——M6 GetWriterJoinedAt 同族教训,集成链抓获实修);⑭multipart 两面 import 20MB/ref-videos 60MB(up60 新档位;upload 处理器内单文件上限双保险);⑮空串形态与 Mock 台账 desc 两处漏登补记(二十续 B4):assets/ref_videos 的 description/note 空串冻结恒写 ‘’(fusion.js:41/:212)vs Go 落 NULL(wire null vs “"——前端 ||'' 消费无感);videoSmart Mock 失败退款台账 desc 参数化「导演分镜视频失败自动退回」vs 冻结硬编码「视频生成失败自动退回」(providers.js Mock catch——⑤只登记了 UPDATE 表名面);冒烟面 404 属主过滤(英文短文案)+403 episodes/extract 属主面逐字。 | Claude |

M11 评估与工具(14——v1.12 勘正:evaluation.js 6+workbench.js 6+index.js viral 2;原清单 :208 自列 6+6+2=14 而标题少算,P0 统计残留第七例与 M8 同型反向)

评估:GET /api/evaluations/config、POST /api/evaluations/upload(txt/md/docx,UTF-8/GBK 自动识别,10MB)、GET /api/evaluations、GET /api/evaluations/:id、POST /api/evaluations(quick 100/deep 300 可配,8 角色×3 阶段流水线,冻结 cost 语义)、GET /api/evaluations/:id/report(txt 下载);SSE eval 事件(stage/done/failed);失败全额退款。 工作台:POST /api/workbench/tasks(转绘 20/去字幕 10/转高清 15)、GET /api/workbench/tasks(recoverWorkbench)、POST/GET /api/tasks/:id/review*、POST/GET /api/director3d/:id/review*(审片 10 积分,双入口共用 review_reports,scope classic/director)。 爆款分析:GET/POST /api/viral-analysis(COSTS.viral=5)。

✅ M11 落地(2026-10-19 W20,internal/domain/evaluation 单包多文件 14 端点全量〔workbench 6+eval 6+viral 2——v1.12 第七例勘正〕):integration 第十一链 EvaluationChain(config 对拍→upload 真上传→扣 100 台账逐字+taskID=ev id→Mock 异步收口 waitFor done 不退款→report 下载头+体→列表定列/详情全列→404 双哨兵)+第十二链 WorkbenchNotifyChain(workbench 守卫三面→video_id 引用 done 成片 Mock done 扣 20 对账→审片双入口 404 两文案分叉+扣 10 台账+空分镜先退对冲→viral 扣 5→M5 四端点 unread-count 联动+read 单条/全标+announcements 公开/401)。实现差异登记:①costOf settings 值为 0 也回退默认 quirk 照抄(冻结 +r.value||def);②engine 两字面不同源勿统一(config『规则(Mock)』vs POST『规则』);③mode 非法静默归 quick 无 400;④runEval finished_at UTC 形态照抄(冻结 :181 toISOString 变形——与 created_at localtime 分裂同源)+Mock 节奏 sleep 1100/1500/900 照抄(mockSleep 可注入);⑤LLM 通道 evalLLM 接线(modelCfg 三元+llm.Client.Chat——M12 反引号修复后已生效),模板查库不接线沿差异⑪先例(EVAL_PROMPT 兜底)——二十一期⑦已接线(eval_deep/eval_quick active 查库,content 空回退 EVAL_PROMPT;写侧 CATEGORIES 八键无此二键入口=冻结同 quirk 照抄);⑥workbench watchVideo 状态丢失/tries>180 不 emit SSE 照抄(冻结 :84 无 bus.emit)+超时不退款照抄(providers 已退语义——与 generation PollTimeout 先例不同源勿统一);⑦审片零 SSE 零通知+reviewShots target/scope 死变量不建+classic ’task not found’ vs director ’not found’ 404 文案分叉照抄+空分镜先退台账「审片退回:无分镜(+10)」逐字;⑧viral Math.random→math/rand+五列 INSERT(Go DDL status/version 惯例列默认)+title slice255 防御截断(冻结 SQLite VARCHAR 无约束存全量——MySQL strict 1406 防护,方言适配,二十一期 B2 补登);⑨recoverWorkbench 整体迁移 evaluation.RecoverStuck(recovery/repo.go 预定注释兑现——四方法+BenchRef/BenchFailedErrorText 移除、WorkbenchRecoverer 窄接口注入;装配序教训:deps.eval 必须先于 recovery 建立的首跑 nil panic 被集成 RecoveryChain 抓获);⑩workbench POST 双载荷形态(multipart 80MB up80 新档/JSON——WorkbenchView :131/:133 两形态)+taskId 无=空串(冻结 undefined——narrations ⑥ 同族沿袭);⑪审片跨域共表读 COALESCE(image_prompt,’’)(冻结 ||'' 消费语义——集成链 NULL 直插行抓获存量炸点:gorp Scan NULL→string 恒错,shots 表真实 NULL 行同炸);⑫workbench_tasks 可空列裁决=不收紧(source_path/video_id 二选一语义可空;DDL NOT NULL DEFAULT ’’ 即冻结 NULL 形态——wire null vs "” 随 M10 ⑮ 口径),delta 无 0003 维持;⑬GET /workbench/tasks out_url 双条件冗余+...w 展开 JOIN 伴列(out_path/video_status)照抄;⑭LLM 边缘面两处微差(二十一期核查 B4 登记):parseEval 重复 dims key 累加 vs 冻结 find 首个(evaluation.js:125——仅 LLM 畸形输出可达);报告模板缺失键 %v→<nil> vs 冻结 ||''(:271——Mock 全键不达)。 | Claude |

M12 管理后台(39)

用户与积分:GET /api/admin/summary、GET /api/admin/users、PUT /api/admin/users/:id、POST /api/admin/users/:id/password、GET /api/admin/credit-grant-records、POST /api/admin/credit-grant-records、GET /api/admin/credit-records/export(CSV)、GET /api/admin/runtime/tasks(运行时任务观测)。 生成审计:GET /api/admin/generation-audit/failures、POST /api/admin/generation-audit/videos/:id/release(人工退款,校验 refunded 防重)、POST /api/admin/generation-audit/tasks/:id/retry-split。 公告:GET/POST /api/admin/announcements、PUT /api/admin/announcements/:id。 组织审批:GET /api/admin/organization-applications、POST /api/admin/organization-applications/:id/approve(-reject)。 计费配置:GET/PUT /api/admin/credit-settings(白名单键,见 F6)、GET/PUT /api/admin/model-settings。 模型接入:GET/POST /api/admin/model-endpoints、PUT/DELETE /api/admin/model-endpoints/:id、POST /api/admin/model-endpoints/:id/activate、POST /api/admin/model-endpoints/:id/test(text→chat 8 token/image→红圆真生成/video→可达性,45s 超时;api_key 列表掩码前 6 位)。 提示词中心:GET/POST /api/admin/prompts、POST /api/admin/prompts/upload、PUT/DELETE /api/admin/prompts/:id、POST /api/admin/prompts/:id/activate(互斥生效版);指令版本 GET/POST /api/admin/instruction-versions、PUT/DELETE /api/admin/instruction-versions/:id、GET /api/admin/instruction-versions/active、POST /api/admin/instruction-versions/:id/activate(v1.7 通配展开补登 PUT/DELETE :id 两条;DELETE 404 not found 与 prompts DELETE 的 版本不存在 刻意不同源照抄)。

Go 实现差异登记(v1.7 W14,internal/domain/admin 单包多文件沿 M9 先例):①withdrawals 2 端点(GET/PUT /api/admin/withdrawals)随 M7 期落地,本期 404 系排期现状非回归;②死端点照抄:GET/PUT /admin/model-settings、GET /admin/instruction-versions/active 前端零调用(契约对齐,防演进踩空);③ErrNoUser 吞形:grant/release 传不存在用户冻结 addCredits 静默 no-op 通知照发——Go credits.Add 显式 ErrNoUser 由管理台吞掉保冻结信封;④api_key 列表明文回显照抄(冻结 models.js:36 含原文+掩码双键)——管理台泄漏面,沿 C2 先例登记安全注记,未来收敛另立修正项(二十一期②已收敛:EndpointRow.APIKey 改 json:"-" 仅下发 api_key_masked/has_key——前端 AdminView.vue:206 只消费 masked 零消费实证,wire 与冻结分叉一处);⑤instruction-versions DELETE 按修后语义打 prompt_templates(404 not found/400 文案逐字保持)——冻结查删 instruction_versions 死表(迁移后恒空→恒 404),F3 同制;⑥跨域共表写归表主域:retry-split 经 task.AdminRetrySplit(不删根资产=冻结原样,重复重拆根资产重复系冻结行为)、release 认领经 generation.ClaimManualRelease(CAS refunded=0+CONCAT(COALESCE(error,’’)) 追加一步,修冻结先查后改的并发窗,F9 同向);⑦读侧衔接零失效逻辑与冻结同构,但 P0 起 modelCfg.setting() key 未反引号恒 1064——读侧配置链全哑的存量真 bug 由本期集成断言抓获并修复(见 v1.7 修订行④);⑧prompt_templates 面不做 in-band ensureSeed(冻结 promptCenter.ensureSeed legacy 迁移在 Go 无源库):cmd/seed 表级哨兵启动补种 5 行已覆盖,管理台 CRUD 纯存储面;⑨providers/publish 反向死调用不实现=echo 404 兜底即冻结形态(AdminView 对应调用在冻结版同样无后端端点,前端零改动面)。

M13 火花计划(2——v1.14 补登:index.js:739-766「火花计划」段;P0 统计残留第八例,与第七例同型「无模块行认领」——二十六期 e2e 全站巡检抓获 Go 零 spark 路由后回溯冻结源码定界)

报名激励:POST /api/spark/join(joined 守卫 400「您已加入火花计划」逐字 → users.spark_joined 置位 → 台账 kind=‘spark’ desc「加入火花计划奖励(+100)」→ 通知「火花计划报名成功」→ {joined:true,bonus:100});GET /api/spark/me(submissions 三计数:total 系 status!=‘draft’ / published / pending;三阶梯投影 min-max-per-name-perk〔星火 1-2 部 100/炬火 3-5 部 150/燎原 6+ 部 200〕+ reward_earned=published×per + next_tier 环形取下一档——燎原的下一档回星火)。

Go 实现(v1.14 W26,internal/domain/spark 单包三件):逐字对齐无差异;errRespond 哨兵 ErrAlreadyJoined→400;集成第十六链 SparkChain(初态星火回退→join 三动作对账→重复 400→阶梯联动 submissions 直插→401 面)。

5. 数据模型概览

52 表终态(qmtv_main 单库)——分类/逐表裁决/视图清单见 docs/数据库表设计-qmtv.md(W9);DDL 权威 = backend/migrations/full/qmtv_main_full.sql。状态表 22 张(version 乐观锁+entity_lifecycle_event 载体)、日志台账 4、字典配置 6、技术 1(refresh_tokens 重构)、资源明细 15、新增基建 4、裁剪 1(providers)。

P2 DDL 收紧(delta/0002,2026-10-18 落地):tasks 5 可空 TEXT 列+shots 2 prompt 列 UPDATE 回填后 MODIFY NOT NULL(MySQL TEXT 无字面 DEFAULT——漏写列 strict mode 显式红=守卫语义);seed.go tasks INSERT 全列写恒 '';C7 例外不动(videos.prompt/error 保持 *string NULL 透传冻结语义);director_shots(M10)/workbench_tasks(M11)待域落地随域裁决。seed Go 版一步到位差异:producer@xingmang.cn 独立演示账号(referral_code=QMXINGMANG01,与 demo 并存)+台账单笔 init(沿 SQL seed 惯例;冻结 demo 为 0 元 register 标记行形态)+prompt_templates 表级 COUNT 哨兵补种 5 行模板(Go prompts 内置不读表,纯存储面对齐产物无差)。恢复扫描窄投影:task 恢复 SELECT * 遇可空列 NULL 整段静默 no-op 已修(SplitRecoverRow 5 列窄投影,语义等价)——W8 集成抽样抓获。

6. 非功能约束

  • 性能:SSE 心跳 25s;视频轮询 8s 首查/10s 步进/15min 上限;workbench 轮询 3s/5s/180 次;LLM timeout 240s;图片供应商 180s;模型测试 45s。
  • 启动恢复四扫描:videos.processing→failed+退款、tasks.split_status=processing→Mock 回退、workbench_tasks.processing→按 video 状态收口、assets.queue_status=generating→回 queued。v1.3 P2 范围注记(W10 更新:四扫描已全部落地):Go P2 W6 已内联实现全部四处(退款走 F9 唯一口 ClaimVideoRefund 认领置位)+幂等可重复启动——原注记「workbench_tasks 随 M11」已过时。实现差异登记(v1.3 W10 入正文):①逐段容错——冻结 videos 段无 catch(异常即崩启动,SQLite 同步 API 副作用非设计)vs Go 统一逐段容错不挡启动;②workbench finished_at 冻结 datetime('now','localtime') vs Go NOW(3)(方言惯例);③恢复扫描用 SplitRecoverRow 窄投影(§5,W8 集成抽样抓获后修)。
  • 跨聚合扣款时序(v1.3 定稿,取代 TECH.md §5 actor+outbox 草案原则):对齐冻结同步流——handler 内 credits.TryDeduct(CAS)→ 业务落库(videos/images 行)→ providers 调用 → 失败 → credits.Refund(F9 唯一口);异步轮询 goroutine 持 ctx,重启丢轮询由启动恢复兜底(与冻结 setTimeout 语义等价)。不引 user actor 串行与 outbox 补偿:CAS 行锁已防超扣(冻结单进程无跨进程面);RunWithRetry/isConflict 无生产原型(qmtv/pms 双侧零调用)。internal/actor、internal/event(outbox relay)维持 P0 骨架预留不强接。
  • Mock 保真:SVG 渐变图/动画 SVG 视频/手写 WAV(16kHz/16bit/mono,voice 基频 female 523/male 330/child 659/narrator 392Hz)/19 种风格缩略图幂等文件名——Go 版产物对前端不可区分。
  • 种子:admin@qmtv.com/admin123456(10 万积分)、demo@qmtv.com/demo123456(1335 积分+示例任务)、distribution_settings(0.08/0.02/100)、2 公告;幂等(有 admin 即跳过)。

7. 前端项目与演进轨道(v1.1 立项)

裁决(2026-10-17):推翻「前端零改动、直接用 qmtv/ 冻结前端」口径——新建 frontend/ 独立前端项目。选型依据与优劣对比见 prd/前端技术对比-qmtv-v1.md(§2.3 可迁移经验与 §5 钉子表继续有效)。

7.1 项目形态(初始 = 复制,行为对等)

项内容
位置仓库根 frontend/(与 backend/ 对称,非冻结区)
原样复制src/(31 文件 9668 行:根 5 + components 2 + views 24)、index.html、vite.config.js(proxy /api /files → :3300 不变)——探查证实 src/ 零路径耦合(import 仅 vue/vue-router + 相对路径,api.js 纯同源 /api),复制即用
裁剪重写package.json:仅保留前端 4 依赖(vue、vue-router + dev 的 vite、@vitejs/plugin-vue;原 6 依赖中 better-sqlite3/express/multer/jszip 属后端,jszip 前端也未用);scripts 仅 dev/build/preview
排除server/、data/、dist/、node_modules/、docs/、shots/、一次性脚本、package-lock.json(重装生成)

7.2 演进三件(后续期渐进落地,吸收 pms 模式而非换框架)

#项治理什么起步方式
E1@tanstack/vue-query 服务端状态层各页面自管 loading/缓存/失效的复杂度爆炸(Dashboard 1328 行单文件的根因);等价获得 pms React Query 191 处 useQuery 的声明式红利从 Dashboard/Workbench 类多数据源页面开始接线
E2vitest + @vue/test-utils零测试欠账:242 端点契约无前端侧断言新代码带测试起步;参照 pms「页面测试近 1:1」与 docs/测试规划-qmtv.md 范式(全 mock,不连外部服务)
E3TypeScript 渐进类型化(✅ 二十五期 2026-10-19 落地:31 文件全量 TS 化,strict 闸门 ci 3.8)劣势 #1「无类型,接口契约只存在于约定」allowJs 混用,从 api.js/router.js 类型化起步,.js 按文件渐进改 .ts;纪律:api 返回类型显式收敛、禁 as any 兜底

7.3 什么是 TS(TypeScript)

TypeScript = JavaScript 超集 + 静态类型系统(微软 2012 年发布)。所有合法 JS 都是合法 TS;它在 JS 基础上加了「编译期类型检查」这一层:

  • 错误发现时机前移:纯 JS 的类型错误运行时才爆(用户点按钮才发现 undefined);TS 在编辑器/编译期立刻红线。
  • 运行时零开销:类型只是标注,编译(tsc / vite 内置 esbuild)时全部擦除,产出纯 JS——浏览器不认识也不需要认识 TS。
  • 契约代码化:接口形状写成类型,传错即编译失败,无需等运行时验证。
interface User { id: string; credits: number }        // API 契约的类型化

function deduct(u: User, n: number): boolean {
  return u.credits >= n;   // 若误写 u.cridets:TS 编译期报错;纯 JS 要等运行时 undefined 比较才出错
}

deduct("不是User对象", 5);  // ❌ TS 编译期拒绝;纯 JS 静默放行,线上才炸
  • 渐进迁移:allowJs 允许 .js/.ts 混用,可按文件逐个改后缀,不必 big-bang——对 qmtv 前端 9668 行 JS 的存量是唯一现实路径。
  • 对本项目的意义:PRD 里 242 端点的请求/响应契约目前只存在于本文档文字;E3 落地后变成代码里的编译期断言(api 函数返回类型显式收敛),契约漂移在 CI 就被拦下。

7.4 约束

  • §2 全局契约 C1~C12 对 frontend/ 全部继续有效——前端演进的是内部形态,不改后端兼容面。
  • 端口:dev :5173 与冻结版同端口(同一时刻只跑一个;需要并行时 vite 自动 +1);生产终态 Go :3300 托管 frontend/dist。
  • 演进不反向解冻 qmtv/:冻结区保持对照基准原样。

3 - 01 · 系统设计方案

本文说明 QMTV 的产品定位、功能全景与各模块的设计方案。历史设计决策的完整推导过程见 D:\WORK\GAE\QMTV网站设计文档.md(22 节版本史)。

1. 产品定位

QMTV 是面向短剧/漫剧制作方的一站式 AI 内容生产平台,覆盖「剧本 → 资产 → 分镜 → 视频 → 成片 → 交付」完整链路,并配套内容生态(剧本库/评估/编剧激励)、企业协同(团队/权限/素材库)与商业闭环(积分/充值/返佣)三大体系。

设计原则:

  • 生产工具 + 内容社区 + 商业化三合一:既做工具(对标巨日禄的项目内八类资源中心、工作台工具集),也做生态(对标新版 GAE 的剧本评估/剧本库/编剧广场),还做生意(积分计费/充值返佣/团队管理)。
  • 积分是唯一硬通货:所有 AI 消耗统一折算积分,任务级流水可查,失败自动退款。商业模块(充值/返佣/提现)全部围绕积分展开。
  • 功能零缺失复刻:以行业头部平台(manjuchuhai.cn 旧版/新版、video.jurilu.com)为参照逐项对齐,允许布局不同、不允许功能缺失。

2. 功能全景

QMTV
├── 创作生产
│   ├── 剧本拆解台        剧本→场次/分镜/资产,四种故事板生成方式,18 种视觉风格
│   ├── 导演工作台        项目→分集→分镜(9字段导演指令)→逐镜出图出片,八类资源 Tab
│   ├── 剧本视频生成      分镜→视频:一键下载/串行打标/全自动渲染/剪映包,智能审片
│   └── AI 工具集         独立生图/生视频/爆款分析;一键转绘/去字幕/转高清;本入剧出
├── 内容生态
│   ├── 剧本库市集        多维筛选+详情五区块(亮点/试读/人物/世界观/目录)+导入拆解台
│   ├── 剧本评估中心      8 AI 角色 × 3 阶段流水线,七维评分,逐集证据,深度/快速两档
│   ├── 编剧广场+投稿中心 编剧档案/主页,投稿状态流,过审上架剧本超市
│   ├── 火花计划          阶梯积分激励 + 现金奖池赛事页
│   ├── 作品展示          成片作品墙,发布/撤下/站内播放
│   └── 全站搜索          Ctrl K 同时搜剧本与编剧
├── 企业协同
│   ├── 企业管理台        数据看板(趋势+双排行榜)/成员角色/成员组/权限组/素材权限矩阵
│   ├── 企业素材库        目录树+10GB容量展示+共享素材跨成员可见
│   └── 项目共享          导演项目一键共享到企业
├── 商业闭环
│   ├── 积分体系          生成按量计费/任务级流水/失败退款/冻结-结算-退回
│   ├── 充值返佣          凭证审核入账、两级返佣(8%/2%)、满980自动开通推广资格
│   └── 管理后台          14 板块:用户/积分/公告/企业/提现状态机/模型接入/计费/剧本/提示词/指令/充值审核/投稿审核/任务审计
└── 平台基础
    ├── 模型接入注册表    文本/图片/视频三类,每条独立接口地址+密钥+模型名
    ├── 提示词中心        8 分类版本管理,占位符引擎
    └── 实时推送          SSE 事件流(视频进度/拆解完成/充值到账/审片报告)

3. 核心模块设计方案

3.1 剧本拆解(双引擎)

  • 提交:POST /api/tasks/v2 接收剧本+配置(剧本类型/脸型/风格/时长区间/提取范围/自定义指令)。
  • 引擎 A(规则拆解):preprocess.js 正则识别场次/分镜/角色,确定性输出,秒级完成,永远可用。
  • 引擎 B(LLM 拆解):tasks/v2 走异步任务——取提示词中心生效的拆解指令(带输出合同:[CHARACTERS]/[SCENES]/[PROPS]/[SCRIPT]/[SHOT]/[IMG]/[VID] 段落标记),llm.js 调用注册表当前文本模型,parser.js 状态机解析回填。失败自动回退引擎 A 并站内通知。
  • 设计要点:输出合同用段落标记而非纯 JSON——大模型对分段文本的遵循度比严格 JSON 高得多;解析器按行状态机容错,允许模型输出多余空行/前后缀。

3.2 资产一致性与融合生图

  • 角色/场景/物品在项目内统一建档(assets 表),生成图后 image_id 回填,形成"资产卡"。
  • 提示词组装:promptCenter.buildAssetPrompt(type, 描述, 脸型) 拼接资产类别模板 + 占位符替换,保证同角色跨镜头提示词同源——这是一致性的第一保障。
  • 融合生图(3 积分/张):组合角色/场景/物品卡描述 + 姿态/特效 + 画面描述 → 单张图,明确写入"保持所选资产外观一致性"指令。
  • 图片改创:以项目内任意图为底图,原文提示词 + [改创要求] 后缀重新生成。
  • 待生成队列:资产先入队(queue_status: idle/queued/generating/done)不扣费,生成时才计费;失败回 queued 不丢队列;重启时 recoverQueue() 把 generating 回退 queued(持久化挂起)。

3.3 分镜与视频渲染

  • 分镜支持 9 字段导演指令(环境状态/叙事任务/世界空间锁/位置锁/轴线锁/投影/群像锁/逐秒动作/转场点,JSON 存 director_shots.shot_fields)。
  • 视频/图片生成统一走 providers.imageSmart / videoSmart(见架构文档 §5);批量渲染逐笔容错——单笔失败退款继续,返回 failed 计数。
  • 智能审片(10 积分):五维评分(主体一致性/画面美感/动作连贯/字幕与口型/穿帮检测)+ 分级问题清单 + 修复建议;LLM 可用时走结构化 JSON 审片,否则规则引擎,engine 字段标注来源。经典工作台与导演工作台双入口,报告存 review_reports。

3.4 剧本评估(多智能体流水线)

  • 快速 100 / 深度 300 积分,提交冻结、完成结算、失败退回(tryDeduct type=‘reserve’)。
  • 8 角色 × 3 阶段:一级 交付规范主审+交叉核验 → 二级 全剧主审+前十精读+情绪人物+海外市场 → 三级 证据复核+评分审定。阶段落库 eval_projects.stage,前端轮询渲染流水线动画。
  • 七维评分(合计 100):交付规范10 / 内容基础20 / 前10集转化20 / 人物情绪15 / 结构兑现15 / 海外适配10 / AI漫剧可视化10。
  • 深度评估附逐集证据(按「第X集」切分,Mock 引擎与 LLM 提示词都要求按集给证据)。

3.5 剧本库市集与生态

  • script_library(官方库)与 submissions(用户投稿)两源:官方库管理端维护;投稿过审后上架。字段完全市集化:题材/市场/受众/形式/标签/亮点/试读/人物小传/世界观/梗概/设定/集数/策划字数/编剧署名/评分/封面。
  • 详情目录自动从正文解析「第X集」生成;导入使用记 script_uses(近 7 天热度驱动排序与 🔥 角标)。
  • 火花计划:spark_joined 报名送 100 积分;阶梯 = 星火(1-2部过审,100/部) → 炬火(3-5部,150/部) → 燎原(6+部,200/部);页面叠加现金赛事卡(奖池/奖项表/投稿入口)。

3.6 企业协同

  • 组织/成员/邀请码;owner→admin→member 三级角色。
  • 成员组(member_groups)与权限组(perm_groups:查看/编辑/删除/下载四权限 JSON)挂在 org_members 上;素材权限五项矩阵(查看/上传/下载/编辑/删除,org_members.material_perms)带联动规则:授上传/下载/编辑/删除自动含查看,授删除自动含编辑,取消查看清空全部——与行业对标产品一致。
  • 数据看板:组织成员聚合的积分概览(可用+冻结)、近 14 天消耗趋势、项目消耗榜(credit_records.task_id 反查任务/项目名)、人员消耗榜。
  • 素材库:asset_folders 目录树 + asset_library.folder_id 归属 + 容量估算(图片/音频真实大小、缺失按 80KB/2MB 估算,配额 10GB)。

3.7 商业闭环

  • 计费:util.COSTS 基础价 + 管理端计费配置(视频=拉取5+每秒5,图片10,2K预览15,拆解20,爆款5,评估100/300,审片10,转绘20/去字幕10/转高清15,融合3,一键转剧30/集,导出2/段)。计费参数存 system_settings,管理端可改。
  • 充值:创建订单→上传凭证→管理审核→approve 入账 + 两级返佣(一级 8%、二级 2%,从 distribution_settings 读)→ 单笔满 980 元自动 affiliate_enabled 开通推广资格。
  • 提现状态机:pending→reviewing→topay→paid→(用户确认)done;任意审核阶段可驳回;pending/reviewing 可用户撤回解锁收益。非法流转被 W_FLOW 矩阵拒绝。
  • 安全:JWT 密钥持久化 data/.jwt_secret(支持 QMTV_JWT_SECRET 覆盖);登录 20 次/分/IP、注册 5 次/时/IP 限流;密码 hash 存储;管理端接口全部 adminRequired。

4. 数据模型设计要点

49 张表见架构文档 §6。关键设计决策:

  • 多态引用:images.task_id 既存拆解任务 id(t_)也存导演项目前缀 id(dir_);videos.shot_id 配合 shots._tbl 约定(providers 内部判断 director_shots/shots)指向不同表——避免为两套工作台建两套生成表。
  • 积分流水即账本:credit_records(task_id) 使任意消耗可追溯到项目,管理端审计、项目积分记录、企业看板共用这一张表。
  • 轻量迁移:所有列变更走 migrations 数组幂等 ALTER,历史兼容靠 COALESCE/DEFAULT 占位值(注意:迁移 DEFAULT 值会挡住后续数据回填,需显式覆盖,见交接文档踩坑 §7.4)。
  • 种子数据幂等:剧本库种子按标题匹配回填,且只覆盖"默认占位值"(market=‘中国内地’ 等),不覆盖人工修改。

5. AI 链路设计

页面动作 → routes(校验+tryDeduct) → promptCenter 组提示词
  → providers.imageSmart / videoSmart
      ├─ 注册表有启用接入(base_url+api_key+model)→ 真实供应商
      │    图片:OpenAI 兼容 /images/generations(同步,比例→尺寸映射)
      │    视频:异步任务 提交→轮询(10s×90次)→下载回填→SSE通知;失败自动退款
      └─ 无接入 → 本地 Mock(SVG 占位图/动画视频/WAV 配音),同步返回
  → 结果落 images/videos 表 → bus.emit → SSE → 前端 toast + 刷新
  • 模型接入注册表(model_endpoints):purpose ∈ text/image/video,每条独立 base_url/api_key/model/enabled,active_model_<purpose> 指定当前使用;管理端可测试连通。
  • 提示词中心(prompt_templates):8 分类(split/shot_image/shot_video/asset_character/asset_scene/asset_prop/video_tag/viral+eval_quick/eval_deep)版本管理,单分类单生效;占位符 {描述}{脸型}{场次}{景别}{转场}{风格基调} 生成时替换。
  • 失败语义统一:providers 内部退款并抛 {status, message},全局错误中间件透传;调用方不得重复退款。

6. 视觉设计体系

  • 三主题 CSS 变量切换(html[data-theme] = dark/light/gae + localStorage),深色为主品牌(深空蓝 #04060e 底 + #2f6bff→#22d3ee 电光蓝渐变),玻璃拟态面板(backdrop-blur + 半透明边框光晕)。
  • 登录页左右分屏品牌大图;分镜卡 v-tilt 自定义指令 3D 悬浮倾斜(触屏禁用)。
  • 导航为分组下拉(工作台/创作工具/内容生态),菜单文字固定浅色(浅色主题下 var(–text) 会在深色菜单底上不可读——历史踩坑)。
  • 移动端断点:1100px 导航换行、900px 网格降列。

7. 兼容对标对照

参照平台已对齐模块
巨日禄 video.jurilu.com项目八类资源中心、融合生图、图片改创、待生成队列、公共池、参考视频/音频、本入剧出、剧本超市、团队管理(看板/组/权限/素材权限)、企业素材库(目录树/容量)、工作台工具集(转绘/去字幕/转高清——对方还标记"即将上线")、火花计划、作品展示
新版 GAE newgae.manjuchuhai.cn剧本评估中心(8角色3阶段七维)、剧本库市集(多维筛选/详情五区块/试读)、编剧广场、投稿中心、账号中心、全站搜索
旧版 GAE manjuchuhai.cn拆解台完整配置、视频页四一键、15 项功能更新全量、双工作台

4 - 前端技术对比:qmtv(Vue3)vs pms web(React18+AntD5)

文档定位:回答"前端不改写是确定的,但两套前端技术各有什么优劣"。结论前置:qmtv 前端零改动(已裁决);本文是选型对比存档 + 为 Go 移植钉住前端兼容面 + 沉淀"若未来前端演进,哪些 pms 经验值得吸收"。事实基线:2026-10-17 双仓库实测。

修订(2026-10-17,PRD v1.1):§3 结论「前端不动」已被新裁决取代——新建 frontend/ 独立前端项目(初始复制 qmtv 前端)+ 演进三件(@tanstack/vue-query / vitest+vue / TS 渐进),详见 prd-qmtv-v1.md §7。本文 §1/§2 事实对照、§2.3 可迁移经验(vue-query 等价获得、测试文化、类型收敛纪律)与 §5 钉子表全部继续有效;原文保留存档不改。

1. 两套技术栈事实对照

维度qmtv(Vue3 单体)pms web(React 中后台)
框架/语言Vue 3.5 + vue-router 4,纯 JS 无 TSReact 18.3 + TS 5.6(strict:true,关 noUnusedLocals)
构建Vite 8(vite.config 13 行,proxy /api /files)Vite 5(tsc -b 前置 + vite build)
UI 库无——全部手写组件 + 自定义指令(v-tilt 3D 倾斜)+ CSS 三主题(dark/light/gae)AntD 5.22 + ProComponents(实际只用 ProLayout 布局壳,ProTable/ProForm 未用)
请求层src/api.js 46 行:fetch 相对路径 /api、401 自动 refresh 重试一次、localStorage 存 tokenaxios + 拦截器;UnwrappedClient 双泛型修补运行时解包与 TS 签名的断裂
服务端状态无——各页面自管 loading/缓存(Dashboard 1328 行单文件是代价)TanStack Query 重度:191 useQuery / 86 useMutation / 363 queryKey + 自研 QueryTable 封装
客户端状态router.js 内轻量 reactive store(user/notifications)Zustand 4 个极小 store(<100 行)
i18n无(纯中文)react-i18next 四语 1750 key/语言 + coverage.test 双重防护(语言间 parity + t() 字面键扫描)
测试零(仅根目录 4 个 verify_*.js API 冒烟脚本)vitest 142 文件 639 例(页面测试与源文件近 1:1)+ Playwright 双册(断言册 API-first 25 例与截图册物理隔离)
路由集中 24 条 + meta.admin 守卫 + 全局 beforeEach集中 110 Route、零懒加载、组件包裹式守卫
规模24 页面 9082 行(最大 AdminView 1371 行/Dashboard 1328 行单文件)104 页面 + 20 封装组件 + 96 测试文件
实时原生 EventSource(/api/events?token=)+ 每分钟轮询补偿SSE/轮询按需(生命周期时间线组件)

2. 优劣分析

qmtv Vue3 的优势(在它的场景里)

  1. 极简依赖、零构建心智:6 个运行时依赖,13 行 vite 配置,单人可全栈维护;对 AI 辅助开发极友好(上下文小)。
  2. 前端对后端零耦合:相对路径 + 单一 fetch 封装,后端换语言零改动(本次移植的前提,已验证成立)。
  3. 产品形态匹配:C 端气质的创意工具(3D 分镜/主题切换/悬浮客服),手写组件的自由度比 AntD 中后台模板更贴合;AntD 反而会给它套上管理后台的壳。
  4. vue-router 的 meta 守卫与 SFC 单文件组织,样板代码比 React 集中路由少。

qmtv 的劣势(真实欠账)

  1. 无类型:9082 行 JS,接口契约只存在于约定;AdminView 14 个 Tab 1371 行单文件,回归靠人肉。
  2. 无服务端状态层:缓存/失效/重试每页手写——Dashboard/Workbench 类多数据源页面复杂度爆炸的根因。
  3. 零测试:239 个后端契约没有任何前端侧断言。
  4. 无 i18n:纯中文硬编码,产品出海需全量改造。

pms web 的优势(可迁移的经验)

  1. React Query 服务端状态模式是 pms 最值得移植的工程习惯——loading/缓存/失效全部声明式,191 处 useQuery 换来的是每个页面只剩"数据+渲染"。qmtv 若演进,@tanstack/vue-query 可等价获得,不必换 React。
  2. 测试文化:页面测试近 1:1、Playwright 断言册与截图册物理隔离、i18n coverage 双重防护——这些约定与框架无关,可原样移植到 vitest+vue。
  3. 类型收敛纪律:api 函数返回类型显式收敛、禁止 as any 兜底(注释溯源)——qmtv 若加 TS,这条是第一规则。
  4. AntD5 中后台生态确实是复制式开发效率的根源;但注意 pms 实际只用了 ProLayout,ProTable/ProForm 红利并未吃到——“上了 AntD 就高效"要打折扣。

pms web 的劣势(对比中看到的税)

  1. axios 运行时解包与 TS 方法签名的断裂需要 UnwrappedClient 类型修补层持续还债;Row 接口仍带 [k:string]:any 兜底。
  2. 110 条路由零懒加载,bundle 全量;qmtv 反而做了按页面 code-split。
  3. ProComponents 引入而未深度使用,依赖面大于收益面。

3. 结论

问题结论
现在要不要动 qmtv 前端不动。它与 Go 后端的耦合面只有 8 条契约(§5),Go 版逐条钉住即可;产品已建成,重写无动机
若未来前端演进,选什么沿 Vue3 生态增量演进:加 TS(渐进)+ @tanstack/vue-query(服务端状态)+ vitest(补测试)——吸收 pms 的模式而非换框架
对 Go 移植的输入§5 的 8 条契约钉子进 PRD(已完成)与 TECH.md;SSE/token query/时间格式三处最易破

4. 迁移成本对照(假设反向迁移,仅作存档论证)

qmtv→pms 栈重写 ≈ 24 页面×(组件重写+React Query 接线+测试补齐) ≈ 与后端 Go 移植同量级的工程;而它解决的三个痛点(类型/服务端状态/测试)都能在 Vue 生态内补齐。重写框架 = 高成本解决低价值问题,此结论与"后端为何值得重写”(生产化运营的并发/部署/一致性硬需求)不同质。

5. Go 侧 8 条逐字节兼容约束(钉子表,PRD §2 已契约化)

#契约前端依赖点Go 版钉子
1响应信封 {ok,data} / {error}api.js:37 解包 .data、抛 {status,message}gateway.OK/Err helper 全局唯一出口
2/api/health 裸 {ok:true,name:"QMTV"}DEPLOY.md 监控/冒烟不走信封
3token query 双通道EventSource/img 标签无法带 headerauth 中间件白名单
4SSE 帧格式+25s 心跳App.vue addEventListener 四类事件SSE hub 逐字节对齐
5uid 前缀+UUIDv4 格式slice 截取(routes2.js:368/enterprise.js:40 同语义前端存在)infra/ids 前缀常量表
6scrypt N=16384/r=8/p=1 salt:hash登录面(种子账号兼容)infra/crypto 参数显式
7时间 YYYY-MM-DD HH:MM:SS 字符串直接渲染不解析LocalTime 类型,禁 RFC3339
8中文错误文案+错误码面前端正则匹配(/所有者/、/密码/、429 文案)PRD C9 冻结文案表

5 - 04 · 待开发功能与规划

本文供排期参考。分四类:A 真实模型接入(最高价值)、B 产品功能补强、C 生产化改造、D 技术债与优化。每项标注预估规模(S≤1天 / M≤3天 / L>3天)与前置依赖。

A. 真实 AI 能力接入(拿到 Key 后第一优先)

#事项规模说明
A1文本模型接入验证S管理后台填 Key→测试连接→设为当前;验证 LLM 拆解/评估/审片三条链路自动升级(llm.isAvailable 分支已就绪)
A2图片模型接入验证S验证 /images/generations 兼容性(比例→尺寸映射在 providers.generateImageReal);重点测 9:16 竖屏
A3视频模型接入验证M异步任务型接口已在 providers 适配(提交+轮询+下载),需用真实供应商联调:超时(15min)、同步 url 直返、错误码三类路径
A4智能审片 Vision 升级M当前审片文本摘要式;接入 Vision 模型(图片入参)做真正的画面级审片——reviewShots 已预留 engine 标注与回退
A5成本核账S真实接入后校准计费配置(管理后台计费设置),对照供应商定价调整 积分/张、积分/秒

验收清单(A1-A3 通用):拆解→出图→渲染→导出全链路真实素材走通;失败退款正确(故意填错 Key 验证);SSE 通知到达;项目积分记录与账实一致。

B. 产品功能补强(对标差距已清零后的深化)

#事项规模说明
B1剧本超市独立市集页M当前投稿过审剧本混在 /library 市集与管理端;可拆独立「剧本超市」页(购买/订阅制、按播放分成是巨日禄未做完的方向)
B2作品展示公开化S/showcase 目前需登录;可开放匿名浏览 + 作者主页聚合其作品
B3素材权限矩阵落地执行M五项权限已存储+联动,但 asset_library 接口未按权限拦截(仅管理语义);需在共享素材读取/上传/删除处校验成员 material_perms
B4成员独立配额Morganizations.credit_allocation_mode 已有 pooled/independent 字段但未实现 independent 分支(成员配额 quota 列闲置)
B5手机号登录/找回M账号中心已留占位;需接短信服务商 + users.phone 列 + 登录分支
B6邮箱验证/找回密码M改邮箱已做(密码验证);找回密码需邮件服务
B7剧本库 tier 分级S新版 GAE 有 premium/free 分级;script_library 可加 tier 列 + 市集页筛选项
B8批量任务中心M全自动渲染/批量生成目前同步逐笔;量大后建议落任务队列(DB 表 + 轮询即可,不必上 MQ)+ 独立任务中心页
B9移动端适配M现有断点仅保证不烂;拆解台/视频页在小屏的体验需专项优化
B10运营位体系S首页 hero 可配置化(公告已有,扩为运营位:banner/活动入口),管理端配置

C. 生产化改造(上生产环境前必做)

#事项规模说明
C1数据库迁移 SQLite→MySQL/PGLbetter-sqlite3 同步 API 遍布全栈;建议先做 SQL 方言审计(当前用大量 SQLite 特有 datetime(’now’,’localtime’) 与字符串拼接 IN),或短期维持 SQLite+定时备份(小团队可接受)
C2对象存储Mdata/files 本地盘 → OSS/S3(assets.js saveUpload 与 providers.finishVideo 两处写入点收敛良好,改造成本可控)
C3进程守护与水平扩展Mpm2/容器 + 健康检查;SSE 与限流是进程内存态,多实例需改 Redis(bus 与 rateLimit 两处)
C4日志与监控Sstdout → 文件轮转(如 pino);关键指标(生成成功率/退款率/供应商耗时)打点
C5HTTPS 与域名S部署层(nginx/caddy)解决;注意 SSE 需要 proxy_buffering off
C6支付对接L充值目前人工转账+凭证审核;接微信/支付宝需订单回调 + 幂等入账(recharge.js approve 逻辑可复用)
C7安全加固M密码强度策略、接口幂等键、上传文件类型魔数校验、管理端操作审计日志(credit_records 已有雏形)
C8备份自动化Sdata/ 定时备份脚本 + 异地存储

D. 技术债与优化

#事项规模说明
D1index.js 拆分S824 行主入口可拆出 auth/tasks/videos/admin 四个模块,降低合并冲突
D2测试体系M现有 verify_*.js 是冒烟脚本;建议引入 vitest,把 verify 场景转成断言用例(后端纯函数/路由层)
D3前端组件抽取M弹层/表格/标签在多页重复,可抽 BaseModal/BaseTable;三主题变量已就绪
D4旧表清理Sproviders 表(旧供应商管理)已无路由引用,可归档;exchanges 兑换功能未接 UI
D5providers.js 真实供应商矩阵M当前视频适配只验证过一类异步接口;多供应商(字段名差异)可加 adapter 映射表
D6国际化L全部中文硬编码;海外市场卖点(评估七维含海外适配)落地前需 i18n

建议节奏

  1. 第一周:A1+A2+A3(真实接入验证)+ C8 备份 —— 把"演示态"变"真实态"
  2. 第二周:A4 审片 Vision + A5 成本核账 + D1 拆 index.js
  3. 之后按业务方向二选一:To B 深耕 → B3/B4/C6(权限落地+独立配额+在线支付);To C 生态 → B1/B2/B7(市集与社区)
  4. 上生产前:C1-C5 按 C3(单机 pm2 + SQLite 维持)或 C1(多实例)两条路线二选一

已知问题(截至交接)

  • 无 P0/P1 级 bug;以下为已记录的低优先观察项:
    • 提交拆解无 Key 时同步返回(量大会占连接),有 Key 后自然变为异步
    • 限流内存桶重启清零(C3 一并解决)
    • 作品墙/共享项目列表分页上限 60/默认(量大需翻页)
    • 移动端仅断点兜底(B9)