FSD M11 · 评估与工具
← 总则 | 附录 → | 上游:PRD §4 M11 实现落点:
backend/internal/domain/evaluation/(model/service〔workbench+watchVideo〕/service_eval〔评估流水线〕/service_review〔审片双入口〕/service_viral/repo)+cmd/server/workbench_handlers.go+cmd/server/evaluation_handlers.go+cmd/server/routes.go:239-267(挂载,审片 4 条 :264-267 物理居中)。事实基准=Go 代码;冻结版qmtv/server/workbench.js/evaluation.js/index.js:490-513(viral)仅差异对拍参照。 域内要点:评估冻结-结算是全站唯一 TypeReserve 台账面(总则 §1 词条的展开落点);审片双入口 404 文案分叉(classic ’task not found’ vs director ’not found’);审片面零 SSE 零通知;watchVideo 状态丢失不 emit;wire 全蛇形;PRD §4 M11 已登记差异 ①~⑭(prd-qmtv-v1.md:216)引用不重立。上传档位 up80(工作台)/up10(评估)。
M11 评估与工具
14 端点全量(workbench 2+审片 4+eval 6+viral 2)。三扣费面三制式:工作台 TOOLS 固定价、审片 10(空分镜先退后拒)、评估 TypeReserve 冻结-结算、viral 5——四制式互不同源(quirk 富矿域)。
F11.01 工作台工具提交(workbench/tasks POST)
对应 PRD:§4 M11 · POST /api/workbench/tasks | 状态:实现 | 实现落点:workbench_handlers.go:18-54、service.go:141-221 | UI:WorkbenchView(E2E-GEN-02 已实现——toast「去字幕完成」;confirm 仅 repaint 空描述分支)
1 功能定义
视频工作台三工具(一键转绘 20/去字幕 10/转高清 15)提交:扣费→异步处理→SSE workbench done。
2 触发条件与前置状态
登录态;tool key 白名单(TOOLS map);余额不足 402;双载荷(multipart 视频/JSON 文本,PRD ⑩)。
3 输入与校验
{tool, video_id?/描述}——repaint 需描述(前端 confirm 分支对应);taskId 无=空串(台账「工作台·X(-N)」service.go:176-178 逐字,冻结 workbench.js:52)。
4 处理流程
TryDeduct(固定价,settings 无此键)→ INSERT workbench_tasks(status=‘processing’)→ 异步 goroutine(提交段同步返回)→ watchVideo 编排(F11.02)。
5 输出与结果状态
{id, status:'processing'}(wb_ 行投影);列表窄投影不含 params 全文(model.go json:"-" 面:OutPath/VideoStatus JOIN 伴列)。
6 状态流转
processing→done(SSE workbench done 帧)/failed(视频链失败联动);「任务状态丢失」为终态旁支(不 emit,F11.02 §7)。
7 边界与异常
| 条件 | 系统行为 | 提示/码 |
|---|---|---|
| tool 非三值 | 400 | TOOLS 键校验 |
| 余额不足 | 402 | 统一信封 |
| 提交后进程重启 | RecoverStuck 回队(PRD ⑨,F11.02 §4) | — |
8 权限与数据规则
authed + amw 属主面;up80 档(workbench.js:12 multer 80MB 对齐,handler 单文件双保险 500「File too large」:35-37)。
F11.02 工作台列表/轮询/启动恢复(workbench/tasks GET)
对应 PRD:§4 M11 · GET /api/workbench/tasks | 状态:实现 | 实现落点:workbench_handlers.go:57-66、service.go:225-304 | UI:WorkbenchView 列表+轮询 | 场景挂钩:E2E-GEN-02(间接)
1 功能定义
本人工作台任务列表 + watchVideo 轮询状态机 + 服务重启悬挂恢复。
2 触发条件与前置状态
列表登录态(按 user_id);watchVideo 由 F11.01 提交后 goroutine 内启动(非 HTTP 端点)。
3 输入与校验
无参数(全量本人任务,无分页——照冻结 :78-123)。
4 处理流程
watchVideo(service.go:228-260):首 tick 3s/步进 5s/上限 180 次(model.go:117-122 可注入常量)→ VideoStatusOf 查 M3 videos 行 → done:SetWorkbenchDone+hub.Emit workbench done;视频 failed:SetWorkbenchWatchFailed 联动;状态丢失(!found 或超次):置失败后直接 return 不 emit(:238-241——PRD ⑥:冻结 :84 同分支无 bus.emit)。 RecoverStuck:启动扫 processing 悬挂行→重挂 watchVideo(PRD ⑨,二十续迁移面)。
5 输出与结果状态
列表行+status(含 done/failed/「任务状态丢失」文案面)。
6 状态流转
与 F11.01 §6 同一张状态机(本节是驱动器)。
7 边界与异常
| 条件 | 系统行为 | 提示/码 |
|---|---|---|
| 轮询超 180 次 | 置「任务状态丢失」无 SSE 帧(quirk 照抄——前端轮询兜底可见) | — |
| 超时不退款 | 扣费不回(PRD ⑥ 已登记) | — |
| goroutine panic | recover 吞(service.go:227——防崩保护,watchVideo 假漏覆写测试教训面) | — |
8 权限与数据规则
authed + amw;轮询消费 M3 videos 表跨域读(VideoStatusOf 窄投影三列)。
F11.03 智能审片·写(review 双入口 POST)
对应 PRD:§4 M11 · POST /api/tasks/:id/review、POST /api/director3d/:id/review | 状态:实现 | 实现落点:workbench_handlers.go:69-92、service_review.go:21-73 | UI:DashboardView/VideoView 审片(classic)+ Director3DView 审片(director)| 场景挂钩:无
1 功能定义
智能审片提交:按 scope 拉分镜→LLM/Mock 逐镜评审→review_reports 落行。双入口同表同逻辑、404 文案分叉。
2 触发条件与前置状态
classic:task 存在+属主,404「task not found」(service_review.go:24);director:404「not found」(:34)——两哨兵不同字(model.go:224/:227,PRD ⑦);空分镜:先退台账再 400「审片退回:无分镜(+10)」(:52-58,Refund 唯一口 nil claim)。
3 输入与校验
无 body(scope 由服务端定);审片费 10 固定(402 走统一信封)。
4 处理流程
TryDeduct「智能审片(-10)」→ 拉分镜(classic 走 shots/director 走 director_shots——跨域共表 COALESCE 可空列读,PRD ⑪ 炸点修复面)→ LLM 截 40 条(firstN :95)→ mockReview:阈值 0.22/0.5/0.7 三档 issue(high/mid/low,:140-146)+维度分 78+rand20,主体一致性 −6,clamp [55,98](:157-161)→ review_reports 落行(scope/target_id 归属)。
5 输出与结果状态
{id}(report 行 id);详情走 F11.04。
6 状态流转
同步完成(review_reports 一次落定,无 processing 态)。
7 边界与异常
| 条件 | 系统行为 | 提示/码 |
|---|---|---|
| classic 任务不存在 | 404 | 「task not found」 |
| director 项目不存在 | 404 | 「not found」(文案分叉勿统一) |
| 无分镜 | 先退 10 再 400(台账+拒绝双写) | 「审片退回:无分镜(+10)」 |
8 权限与数据规则
authed + amw 属主面;零 SSE 零通知(全文件 grep Emit/InsertNotification 零命中——PRD ⑦,唯一不发通知的写路径);扣费 type=‘review’。
F11.04 智能审片·读(review 双入口 GET)
对应 PRD:§4 M11 · GET /api/tasks/:id/review、GET /api/director3d/:id/review | 状态:实现 | 实现落点:workbench_handlers.go:81-116、service_review.go:76-88 | UI:同 F11.03 读侧 | 场景挂钩:无
1 功能定义
审片报告读取:按 target 取最新报告(含逐镜 issues/维度分/总分)。
2 触发条件与前置状态
属主校验同写侧(双 404 文案分叉同 F11.03 §2);无报告返回 null 形态(非 404——照冻结 :198-203/:220-225)。
3 输入与校验
路径 :id(classic=task id / director=project id)。
4 处理流程
review_reports 按 target_id DESC 取首行 → report JSON 反序列化下发。
5 输出与结果状态
{report: {...}|null};issues 数组键形照 mockReview 产出(shot_no/level/message)。
6 状态流转
零写面。
7 边界与异常
| 条件 | 系统行为 | 提示/码 |
|---|---|---|
| 从未审过 | report=null(200) | — |
| 越权 | 404 双文案分叉 | 同 F11.03 |
8 权限与数据规则
authed + amw 属主面;报告 JSON 全文下发(无脱敏)。
F11.05 评估配置与上传(evaluations/config + upload)
对应 PRD:§4 M11 · GET /api/evaluations/config、POST /api/evaluations/upload(up10)| 状态:实现 | 实现落点:evaluation_handlers.go:17-53、service_eval.go:28-43/:47-90/:521-590 | UI:EvaluationView 配置区+上传 | 场景挂钩:无
1 功能定义
评估价目配置读面(quick/deep 双价)+ 剧本文件上传解析(txt/docx、GBK 回退)。
2 触发条件与前置状态
config 登录态;upload up10 档(原 studio cover 档复用)。
3 输入与校验
config 无参;upload multipart file——.txt/.docx 白名单;costOf settings 0 值回退默认(service_eval.go:38-42 err != nil || n == 0 → def,PRD ①;quick 默认 100/deep 300)。
4 处理流程
- config:两价+引擎名——engine『规则(Mock)』字面(:48-51,与 F11.06 POST 面『规则』两字面不同源,PRD ②)。
- upload:GBK 判定(ToValidUTF8→U+FFFD 计数>max(2, 0.2%)→GB18030 解码 :521-534,M9 同族)→ .docx 走 zip 解包+XML 五实体反转义(&/</>/"/&#N;,:537-590)→ 纯文本回传。
5 输出与结果状态
config {quick: n, deep: n, engine: str};upload {text, name, chars} 形态(rune 计数)。
6 状态流转
零写面(upload 不落库——解析产物仅回显,落库在 F11.06 create)。
7 边界与异常
| 条件 | 系统行为 | 提示/码 |
|---|---|---|
| settings 价=0 或解析失败 | 回默认 100/300(0 不生效 quirk,PRD ①) | — |
| docx 损坏 | 解包错误透传 500 族 | — |
8 权限与数据规则
authed + amw;价键 eval_cost_quick/eval_cost_deep(管理台计费配置可调——标「可调」族)。
F11.06 评估项目与流水线(evaluations 三件+runEval)
对应 PRD:§4 M11 · POST/GET /api/evaluations、GET /api/evaluations/:id | 状态:实现 | 实现落点:evaluation_handlers.go:54-101、service_eval.go:93-153/:226-321 | UI:EvaluationView 列表+进度轮询 | 场景挂钩:无(SSE eval 三态帧:stage/done/failed)
1 功能定义
评估项目创建(TypeReserve 冻结扣费)→ 异步流水线(五 stage 推进+SSE)→ 终态结算。
2 触发条件与前置状态
create:script_text 必填;mode ∑ {quick, deep}——非法值静默归 quick 无 400(service_eval.go:97-100,PRD ③);余额不足 402。
3 输入与校验
{name, script_text, mode}——name 缺省「未命名评估」族;script_text 落库截断(与 upload 解析面衔接)。
4 处理流程
TryDeduct type='reserve'「剧本快速/深度评估冻结(-N,完成后结算)」taskID=id(:104-106 冻结 :252-253 逐字)→ INSERT eval_projects(status=‘running’)→ 异步 goRun(:226 起,注入点便于测试):五 stage 推进(解析/拆解/维度打分/汇总/出报告,SSE eval stage 帧逐发)→ Mock 确定性打分 (v*7919)%40(:398,冻结 :56 镜像)→ done:SetEvalDone(无台账动作——冻结即终态;TypeReserve 台账仅失败面全额退款消化)+SSE done;失败:全额退款「评估失败自动退回(+N)」+SSE failed+通知「评估失败:《name》…N 积分已退回」(evalFail :311-321,错误截 100)。
5 输出与结果状态
create {id};list=EvalListRow 定列七投影(model.go:173-181,Report json:"-" 不入列表);:id=全行+report(终态才有)。
6 状态流转
running→done/failed(SSE eval 帧+前端 3s 轮询双通道——E1 轮询机保留手管先例);finished_at UTC 形态(PRD ④)。
7 边界与异常
| 条件 | 系统行为 | 提示/码 |
|---|---|---|
| mode 乱值 | 归 quick(静默) | — |
| 流水线任一 stage 失败 | 全额退款+SSE failed+通知 | 「评估失败自动退回(+300)」 |
| Mock sleep | 1100/1500/900ms 三段(:287-291——Mock 行为是契约) | — |
| 模板缺键 | <nil> 透传(PRD ⑭) | — |
8 权限与数据规则
authed + amw 属主面;TypeReserve 是全站唯一冻结-结算制(先冻结后按结果结算/失败全退——总则 §1 词条展开);evalLLM 通道已接线(PRD ⑤,二十一期⑦)。
F11.07 评估报告下载(evaluations/:id/report GET)
对应 PRD:§4 M11 · GET /api/evaluations/:id/report | 状态:实现 | 实现落点:evaluation_handlers.go:102-114、service_eval.go:156-222 | UI:EvaluationView「下载报告」| 场景挂钩:无
1 功能定义
评估报告 GAE 模板渲染下载(docx 兼容 HTML 容器)。
2 触发条件与前置状态
项目存在+属主;status 非 done 时 report 缺失→按冻结形态返回空/错误面。
3 输入与校验
路径 :id;无 body。
4 处理流程
report JSON → GAE 模板变量填充(七维表/总分/建议段)→ HTML 全文响应(前端 blob 下载——E1 保留 fetch+blob 先例)。
5 输出与结果状态
text/html 全文(非 JSON 信封——下载面直出);engine 字面「规则」(POST 面字面——PRD ② 双字面对照 F11.05)。
6 状态流转
零写面。
7 边界与异常
| 条件 | 系统行为 | 提示/码 |
|---|---|---|
| 未完成即取 | 空报告形态 | — |
| 越权 | 404 | — |
8 权限与数据规则
authed + amw 属主面;报告含全维度明文。
F11.08 爆款分析(viral-analysis 二件)
对应 PRD:§4 M11 · GET/POST /api/viral-analysis | 状态:实现 | 实现落点:evaluation_handlers.go:115-138、service_viral.go:16-67、repo.go:397 | UI:ViralAnalysisView | 场景挂钩:无
1 功能定义
爆款标题/文案四维建议生成(math/rand Mock):单次扣 5 积分,历史保留最近 20 条。
2 触发条件与前置状态
create:title 必填(空→400 族);余额不足 402。
3 输入与校验
{title};title 截 255(slice :56,PRD ⑧ 二十一期 B2 补登)。
4 处理流程
TryDeduct CostViral=5(billing.go:15)→ math/rand 四维 advice(score=60+Intn(35)、comment/emoji/duty 三键随机池,service_viral.go:44-50——math/rand 非确定性 Mock,PRD ⑧;与 eval 7919 确定性不同制)→ viral_analyses 落行(五列 INSERT)→ 响应。
5 输出与结果状态
create {id, advice:{score, comment, emoji, duty}};list=本人最近 LIMIT 20(repo.go:397),Result/Status json:"-"(model.go json:"-" 面)。
6 状态流转
零状态(同步完成落行)。
7 边界与异常
| 条件 | 系统行为 | 提示/码 |
|---|---|---|
| title 超 255 | 截断(不报错) | — |
| 历史超 20 | 旧条滚出(LIMIT 查询面) | — |
8 权限与数据规则
authed + amw 属主面;扣费 type=‘viral’(TypeViral 独立常量——credit-records 单列归组)。
册尾端点覆盖对账(14/14)
对账 backend/cmd/server/routes.go:239-267 亲数 14 条 ↔ 本册 F11.01~F11.08(审片 4 条 :264-267 物理居 M11 段,:259-262 为 M13 spark 段——紧邻勿混):
| # | 端点(routes.go:line) | 节 | # | 端点(routes.go:line) | 节 |
|---|---|---|---|---|---|
| 1 | POST /workbench/tasks(:247) | F11.01 | 8 | GET /evaluations/:id/report(:255) | F11.07 |
| 2 | GET /workbench/tasks(:248) | F11.02 | 9 | GET /viral-analysis(:257) | F11.08 |
| 3 | GET /evaluations/config(:250) | F11.05 | 10 | POST /viral-analysis(:258) | F11.08 |
| 4 | POST /evaluations/upload(:251) | F11.05 | 11 | POST /tasks/:id/review(:264) | F11.03 |
| 5 | GET /evaluations(:252) | F11.06 | 12 | GET /tasks/:id/review(:265) | F11.04 |
| 6 | GET /evaluations/:id(:253) | F11.06 | 13 | POST /director3d/:id/review(:266) | F11.03 |
| 7 | POST /evaluations(:254) | F11.06 | 14 | GET /director3d/:id/review(:267) | F11.04 |
(:249/:256/:259-263 为注释/空行/M13 spark 段邻接行,非端点。)
差异纪律:PRD §4 M11 ①~⑭ 全引用不重立;本册零新立 DIF(goroutine recover/三注入点系测试基建形态非行为差异,节内注记);集成锚第十一链 EvaluationChain/第十二链 WorkbenchNotifyChain 在位(backend/integration_test.go)。