QMTV 移植契约规格(PRD)v1
文档定位:本文是 qmtv 后端 Go+MySQL 移植的需求契约唯一权威——以冻结版 Node 实现(
qmtv/server/,2026-10-17)的实际行为为基准逐条登记,外加已裁决的修正项。Go 版若与本文不符,以本文为准;本文与冻结代码不符处=修正项章节。上游设计参照:qmtv/docs/01-系统设计方案.md(冻结)。后续 FSD 以 Go 实现代码为事实基准反向对账本文;本文修订走版本记录(§0.1)。
0.1 修订记录
| 版本 | 日期 | 修订说明 | 作者 |
|---|---|---|---|
| v1 | 2026-10-17 | 初版:239 端点全清单 + 6 修正项 + 全局契约 | Claude |
| v1.1 | 2026-10-17 | 前端项目立项:新建 frontend/(初始复制 qmtv 前端,行为对等),演进轨道 vue-query/vitest/TS(§1 前端行更新 + 新增 §7);C3/C4/§2.1 token query 表述按冻结实际行为修正(全局兜底,非白名单) | Claude |
| v1.2 | 2026-10-18 | P1 期首核查勘误 + 裁决落册: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.3 | 2026-10-18 | P2 立项定稿:F2 尾注更新(RunWithRetry 实测不引入——CAS 谓词仅 credits>=? 下 affected=0 ⇔ 余额不足,qmtv/pms 双侧零生产调用);F8 补 file_path 布局差异(ObjectKey 日期子目录 vs 冻结扁平);新增 F9(退款防重唯一口,修冻结双退款漏洞);§6 启动恢复注记 P2 范围拆分(workbench 随 M11);跨聚合扣款时序定稿(§6,不引 actor/outbox 对齐冻结同步流) | Claude |
| v1.3-pending | 2026-10-18 | W10 对账预告(pending,正文暂不改):M2 端点数实测 38(routes.go M2 组实装口径),§3 表 :33/§4 :118/合计 :45 的「66」系 P0 统计残留——W10 收尾时三处一并校准;增量端点逐条清单移 docs/API-增量.md 累加 | Claude |
| v1.3-pending | 2026-10-18 | C1 裁决落地(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-pending | 2026-10-18 | W10 对账预告(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-pending | 2026-10-18 | M3 实现差异登记(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-pending | 2026-10-18 | M4 实现差异登记(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-pending | 2026-10-18 | W6/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-pending | 2026-10-18 | A1 落地(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.4 | 2026-10-18 | W10 对账落地(十一续期首核查后收尾,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+M1 | Claude |
| v1.5 | 2026-10-18 | M9 落地 + 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.6 | 2026-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.7 | 2026-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 无 0003 | Claude |
| v1.8 | 2026-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 无 0003 | Claude |
| v1.9 | 2026-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 无 0003 | Claude |
| v1.10 | 2026-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 无 0003 | Claude |
| v1.11 | 2026-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 无 0003 | Claude |
| v1.14 | 2026-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.13 | 2026-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.12 | 2026-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(认证段) | 9 | 9(P1) | 注册/登录/refresh/登出/me/积分流水分页/改密/改邮箱/工作台状态(v1.2 清点修正:原漏登 logout 与 credit-records) |
| M2 任务与拆解 | index.js + routes2 + routes3(task 段) | 38 | 38(P2 W3) | 任务 CRUD、双引擎拆解、资产/分镜/重拆/场次(v1.3 W10 校准:66 系 P0 统计残留,实存 38——含 POST /api/images/storyboard/generate,routes.go 沿冻结物理段归 M2 组) |
| M3 生成与素材 | index.js + routes2 + routes3(生成段) | 19 | 19(P2 W4) | 图片/视频生成、打标、独立工具、音频配音(v1.3 W10 校准:38 系 P0 统计残留,实存 19——含公开面 style-presets/faq 与 GET /api/models/active 补登;storyboard/generate 归 M2 组,剪映属 M4) |
| M4 导出交付 | index.js + routes2 + routes3(导出段) | 10 | 10(P2 W5) | ZIP 交付/剪映草稿/导出任务 |
| M5 通知公告 | index.js | 4 | 4(W20) | 通知/未读数/已读/公告(读侧并入 notification 包——hub 同包零新建) |
| M6 组织协同 | index.js(组织段 :513-:597)+ enterprise.js | 29 | 29(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 链) | 11 | 11(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/ 前缀拼出) | 8 | 8(P2 W16) | 订单/凭证/收款码/审核+两级返佣写入链(v1.9 十七续勘误 5→8:亲数恰 8 条、§4 清单自列即 8——原 5 系 P0 统计残留第五例,与 M2/M3/M12/M7 同型;§4 清单 8 条一直正确而标题少算,与 M7「标题多算」同型反向) |
| M9 剧本库与投稿 | scriptlib.js + studio.js | 25 | 25(P2 W13) | 剧本市集/投稿工作流/编剧档案/解说成片(亲数核验:scriptlib.js 9 + studio.js 16 = 25,v1.3 W10 归属勘误——二十五端点并非全在 scriptlib.js) |
| M10 导演与融合 | director.js + fusion.js | 28 | 28(W18) | 导演工作台/分集分镜/项目资源中心/融合生图 |
| M11 评估与工具 | evaluation.js + workbench.js + index.js:490-513(viral——v1.12 勘正归入) | 14 | 14(W20) | 剧本评估流水线/工作台工具/审片/爆款分析(v1.12:12→14 亲数勘误第七例) |
| M12 管理后台 | index.js(admin) + llmroutes.js + routes2(admin) | 39 | 39(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 补登) | 2 | 2(W26) | join 报名(置位+台账+100+通知)/me 激励投影(submissions 三计数+三阶梯+环形 next_tier)(v1.14:PRD 清单从未登记——P0 统计残留第八例,与第七例同型「无模块行认领」) |
| 基础 | index.js(SSE/health/release-mode) | 3 | 3(P0) | SSE 事件流/健康检查/发布模式 |
| 合计 | 239 | 239 | (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.1 | 401 面 |
| C4 | token 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 |
| C5 | SSE | GET /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 各模块) | 实时进度失效 |
| C6 | uid 格式 | <前缀>+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 | 中文文件名乱码 |
| C12 | JWT | 三段标准 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 行为 | 兼容影响 |
|---|---|---|---|---|
| F1 | refreshToken 真轮换 | 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 | 前端无感;并发下不再超扣 |
| F3 | export_tasks.shot_count | INSERT 引用该列但建表缺失(新库导出必报错的存量 bug) | 建表含 shot_count INT NOT NULL DEFAULT 0 | 修复 |
| F4 | providers 死表 | 建表但无任何代码读写 | 裁剪不建 | 无 |
| F5 | JWT 标准化 | 两段式 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/... 相对 URL | infra/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/events | token query | SSE 流(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/me | Bearer | publicUser 字段集:id/email/nickname/role/credits/org_id/workspace_version/referral_code/affiliate_enabled/created_at |
| POST /api/auth/logout | Bearer | 冻结无服务端状态清除;Go F1:撤销该用户全部 refreshToken(v1.2 补登) |
| GET /api/auth/credit-records | Bearer | 全局积分流水分页(size 20,{list,total,page},created_at DESC,id DESC)(v1.2 补登) |
| POST /api/auth/change-password | Bearer | 改密后撤销全部 refreshToken |
| PUT /api/auth/email | Bearer | 需密码确认;F7 严格版 |
| PUT /api/auth/workspace-state | Bearer | 工作台版本状态存 users.workspace_version |
M2 任务与拆解(38,v1.3 W10 校准:标题「66」系 P0 统计残留)
端点实装清单见
docs/API-增量.mdM2 节(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-增量.mdM3 节(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 转绿(前端零改动)。实现差异登记:①readMySQL 保留字全 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);②dashboardavailable恒=balance 无任何过滤+frozen 仅 eval_projects status=‘running’(M11 未落地恒 0)+projectRankdir_前缀死分支(实产 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 缺省时冻结回nullvs 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’ 字符串 → Gotime.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/scriptlib25 端点全量):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 GoNOW(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 类多数据源页面开始接线 |
| E2 | vitest + @vue/test-utils | 零测试欠账:242 端点契约无前端侧断言 | 新代码带测试起步;参照 pms「页面测试近 1:1」与 docs/测试规划-qmtv.md 范式(全 mock,不连外部服务) |
| E3 | TypeScript 渐进类型化(✅ 二十五期 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。
- 契约代码化:接口形状写成类型,传错即编译失败,无需等运行时验证。
- 渐进迁移:
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/:冻结区保持对照基准原样。