Commit 30e370ca45e765d01b347f25f0ac71fc1e823c46
1 parent
4e7bb68e
Plan second-phase tasks: dance.html + free wardrobe mode (T11-T17)
Breaks down dev-plan.md's phase-2 scope (dressup-dance-room.md 9节 第2条: dance.html + 免费衣柜模式 + 去重缓存, no paid modes/accounts/ credits yet) into T11-T17 with acceptance criteria, work estimates, and a dependency graph, same format as dev-plan.md's T1-T10. Notes that dev-plan.md's own phase-1 exit criterion (batch-generate >=30 seed videos with real assets) is still outstanding and is an operational step, not blocking this plan but blocking the wardrobe actually having content once T11-T17 land. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Showing
1 changed file
with
115 additions
and
0 deletions
docs/todo/dev-plan-2.md
0 → 100644
| 1 | +# 换装跳舞直播间 — 第二期开发任务规划 | |
| 2 | + | |
| 3 | +需求见 `docs/todo/dressup-dance-room.md`(下称"需求文档")第 3 节模式一、 | |
| 4 | +第 5.1 节年龄确认;设计见 `docs/todo/dressup-dance-room-mvcp.md`(下称 | |
| 5 | +"MVCP")V.1.1/M.8/P.1;架构见 `docs/structure/architecture.md`(下称 | |
| 6 | +"架构文档")2.1/2.5/2.6 节。第一期(后台三库 + 冷启动批量生成)任务表 | |
| 7 | +见 `docs/todo/dev-plan.md`,T1-T10 已全部完成并提交 | |
| 8 | +(`59c7398`/`4d437a4`/`7361786` 等),但**第一期出口清单里"批量跑出 ≥30 | |
| 9 | +条冷启动视频、人眼抽查"这一步还没做**——那是运营往三个库里灌真实素材 | |
| 10 | ++ 实跑 H3 GPU 集群的操作性步骤,不是代码任务,不阻塞本文档规划,但阻塞 | |
| 11 | +本文档任务落地后的"有内容可看"这个体验(衣柜是空的话,模式一自然选不 | |
| 12 | +出东西)。 | |
| 13 | + | |
| 14 | +工时是**粗估**,单位人天,用来排先后不用来考核。任务编号接着第一期的 | |
| 15 | +T1-T10 往下编,避免和 `dev-plan.md` 混淆。 | |
| 16 | + | |
| 17 | +--- | |
| 18 | + | |
| 19 | +## 0. 第二期范围(需求文档 9 节第 2 条) | |
| 20 | + | |
| 21 | +**做**:`dance.html` 上线(含首次进入的年龄确认+免责声明,5.1 节), | |
| 22 | +接入"衣柜选衣服"免费模式(3.1 节)+ 相同人物+衣服组合去重缓存(4.6 | |
| 23 | +节,M.7 唯一索引已在 T8 落地),复用现状排播队列基础设施思路但**要为 | |
| 24 | +`dance` 频道重新实现一份独立的 schedule/promptQueue**(架构文档 2.1/2.5 | |
| 25 | +节:两条频道各自维护自己的时刻表,不是共享一份)。此阶段全部免费内容 | |
| 26 | +仍按 v1 现有投票机制排序,**不涉及"付费插队"这条新规则**(那是 | |
| 27 | +`priority: paid_boost`,架构文档 2.6 节,第五期才有)。 | |
| 28 | + | |
| 29 | +**明确不做**(留到后续分期,见需求文档 9 节 3-5): | |
| 30 | + | |
| 31 | +- 模式二(付费传衣服)、模式三(付费传人物)——两者都要求账号+积分体系 | |
| 32 | + 先落地(第三/四期),本期不做上传+审核+扣积分链路。 | |
| 33 | +- 用户注册/登录(`sessions` 完整实现,M.10)——本期沿用现有匿名 | |
| 34 | + `viewer_uid` cookie,跟 `live.html` 一致(架构文档 2.7 节:"免费模式一 | |
| 35 | + 不强制登录")。 | |
| 36 | +- 积分、`pricing_config`、充值、退款(第四期)。 | |
| 37 | +- `blacklist`(M.11)人工拉黑表、人脸黑名单审核(第四/五期;模式一本身 | |
| 38 | + 不接受用户上传内容,风险面本来就比模式二/三小得多,可以先不接这道 | |
| 39 | + 口子)。 | |
| 40 | +- `admin-playback.html`(插播/置顶/暂停填充,6.5 节)——锦上添花,不是 | |
| 41 | + 第二期出口条件,见第 4 节"明确不在第二期范围"。 | |
| 42 | +- fal.ai 接入(第五期)。 | |
| 43 | + | |
| 44 | +--- | |
| 45 | + | |
| 46 | +## 1. 依赖关系 | |
| 47 | + | |
| 48 | +```mermaid | |
| 49 | +flowchart TD | |
| 50 | + T11[T11 dance 频道独立播出状态机] --> T15[T15 POST /api/dance/pick] | |
| 51 | + T12[T12 GET /api/dance/wardrobe] --> T16[T16 衣柜 tab 前端接线] | |
| 52 | + T15 --> T16 | |
| 53 | + T13[T13 dance.html 页面骨架] --> T16 | |
| 54 | + T13 --> T14[T14 年龄确认弹窗] | |
| 55 | + T11 --> T17[T17 点赞/在线人数] | |
| 56 | + T13 --> T17 | |
| 57 | + | |
| 58 | + classDef ready fill:#d4edda,stroke:#28a745 | |
| 59 | + class T11,T12,T13,T14 ready | |
| 60 | +``` | |
| 61 | + | |
| 62 | +T11/T12/T13/T14 互不依赖,可以并行开工;T15 需要 T11 的时刻表先能收 | |
| 63 | +`videoId` 入队;T16 是前端接线,需要 T12/T13/T15 都有了才能真正跑通端 | |
| 64 | +到端(但页面骨架本身可以先搭起来,用假数据联调);T17 依赖 T11(复用它 | |
| 65 | +的 tick)和 T13(页面上要有展示位)。 | |
| 66 | + | |
| 67 | +--- | |
| 68 | + | |
| 69 | +## 2. 任务表 | |
| 70 | + | |
| 71 | +| # | 任务 | 依赖 | 验收标准 | 工时 | | |
| 72 | +|---|---|---|---|---| | |
| 73 | +| T11 | **dance 频道独立播出状态机**:新增 `dance-state.json`(`{ schedule, promptQueue }`,结构参照 `live-state.json` 但按 MVCP M.8 的**要求**——`schedule` 条目存 `videoId` 引用,不内联整份 clip 快照,读取时 join `library.json`);`ensureSchedule`/tick 逻辑参照 v1(`server.js` 现有 `schedule`/`promptQueue`/`ensureSchedule`),改成只从 `library.json` 里 `channel === "dance"` 的 clip 里选片 | T1(已完成,读写模式复用)、T8(已完成,产出的 clip 已带 `channel:"dance"`) | 独立于 `live.html` 的 schedule 运行,互不干扰;进程重启后时刻表从 `dance-state.json` 恢复,不会因为读到旧的内联 clip 快照而跟 `library.json` 当前数据不一致(这是 M.8 强调的坑);新增 `GET /api/dance/live/state`,返回结构镜像 `/api/live/state`(`current`/`upNext`/`queue`) | 1.5 | | |
| 74 | +| T12 | **`GET /api/dance/wardrobe`**:公开只读接口,列出 `garments` 里 `isActive === true` 的条目(复用 `dressup-store.js` 的 `garments` store,不需要 admin 鉴权——这是观众端接口) | T4(已完成) | 下架的衣服不出现在返回列表里;无需登录/cookie 也能拿到 200 | 0.3 | | |
| 75 | +| T13 | **`dance.html` 页面骨架**(MVCP V.1.1):顶部条(Logo/在线人数占位)+ 左侧衣柜 tab(先只做这一个 tab,传衣服/传人 tab 留空占位,第三/四期再接)+ 播放器容器按 **9:16** 设计(不是 `live.html` 现有横向容器拉伸)+ 右侧点赞/排队展示(无文字输入框)+ 移动端底部 tab 切换 | 无 | 页面能独立打开(不依赖登录);播放器容器在桌面和一个典型移动端视口下都不出现大黑边;跟 `live.html` 视觉语言一致(同一套 `style.css`/组件风格) | 1.5 | | |
| 76 | +| T14 | **首次进入年龄确认弹窗**(5.1 节):非模态强制(不能通过点击背景关闭,必须点"已满18岁"才能继续),确认后写 cookie(**不需要**登录态,架构文档 2.7 节:免费模式一不强制登录,这条确认走 v1 昵称弹窗同款的纯前端 cookie 记忆套路),刷新页面不再弹 | T13 | 首次进入必弹;确认一次后关闭浏览器再打开(cookie 还在)不再弹;显式展示一句免责声明文案 | 0.3 | | |
| 77 | +| T15 | **`POST /api/dance/pick` {garmentId}**(P.1 流程):取当前 `characters` 里 `isDefault === true` 的那条(T3 已支持"只有一条默认"),调用 T8 已实现的 `submitGeneration({characterId, garmentId})`(`server.js`,已支持 M.7 去重缓存);命中缓存或生成完成后,把 `videoId` 推进 T11 的 dance `promptQueue`(而不是止步于"落进 library.json"——T8 原本只做到落库,这里要接上"排入队列"这一步,是 T8 的直接延伸) | T11 | 提交一件下架的衣服(`isActive:false`)返回 400;同一衣服两个不同 cookie 各提交一次,第二次是缓存命中、秒级返回并排入队列(不重新起 H3 任务);进程重启后,仍在 `generating` 状态的 pick 请求能续上(复用 T8 `resumeDressupGenerations` 的机制,不用重写) | 1 | | |
| 78 | +| T16 | **衣柜 tab 前端接线**:调 T12 拿列表渲染缩略图网格,点击调 T15 提交,提交后在"生成中"区域展示一条状态(复用 `live.html` 现有"生成中"列表的交互思路——`promptQueue` 里 `status` 驱动 UI,不是重新设计一套状态展示);播放器轮询 T11 的 `/api/dance/live/state` 按 `endAt` 精确切片(同 `live.html` 现有逻辑) | T12, T13, T15 | 选一件衣服 → 出现"生成中"提示 → 完成后自动进入播放队列,不需要手动刷新页面;两个浏览器 tab 看到的"当前播放"一致(服务端权威时钟,架构文档 1.2 节这条铁律在 dance 频道也要成立) | 1 | | |
| 79 | +| T17 | **点赞 + 在线人数**(dance 频道独立计数):复用 v1 `POST /api/queue/vote/:id`/在线人数统计的逻辑,但作用域限定在 dance 频道自己的 `promptQueue`/viewer 心跳(不能跟 `live.html` 共用同一份计数,否则"在线人数"会把两个频道的观众混在一起) | T11, T13 | 点赞数变化影响 dance 免费队列的排序(v1 现有投票机制,本期不做付费插队);`live.html` 和 `dance.html` 分别打开,两边"在线人数"独立变化,互不叠加 | 0.5 | | |
| 80 | + | |
| 81 | +**总工时约 6.1 人天**,T11/T12/T13/T14 四条(约 3.6 人天)可以完全并 | |
| 82 | +行;T15-T17(约 2.5 人天)依赖前面几条但彼此间也有一定并行空间(T15 | |
| 83 | +后端 和 T16 前端骨架可以同时开工,最后再联调)。 | |
| 84 | + | |
| 85 | +--- | |
| 86 | + | |
| 87 | +## 3. 第二期出口 | |
| 88 | + | |
| 89 | +- `dance.html` 能独立打开,首次进入弹年龄确认,确认后不再弹; | |
| 90 | +- 衣柜 tab 能看到后台已上架的衣服(**依赖第一期出口"批量生成 ≥30 条" | |
| 91 | + 先落地,不然衣柜是空的,见本文档开头的提示**); | |
| 92 | +- 免费选一件衣服 → 提交 → 排入独立于 `live.html` 的播出队列 → 播放; | |
| 93 | +- 同一件衣服被多个观众选中时,第二次起命中缓存,秒级排队,不重新起 | |
| 94 | + GPU 任务; | |
| 95 | +- 点赞/在线人数在 dance 频道内正常工作,且跟 `live.html` 的计数互不 | |
| 96 | + 干扰; | |
| 97 | +- 全程不涉及登录、积分、上传、审核。 | |
| 98 | + | |
| 99 | +达成后才进第三期(用户注册体系,见需求文档 9 节第 3 条)。 | |
| 100 | + | |
| 101 | +--- | |
| 102 | + | |
| 103 | +## 4. 明确不在第二期范围 | |
| 104 | + | |
| 105 | +避免执行时范围蔓延: | |
| 106 | + | |
| 107 | +- 模式二/三(付费传衣服/传人)的任何后端或前端部分(第三/四期,需要先 | |
| 108 | + 有账号+积分) | |
| 109 | +- 用户注册/登录 `sessions` 完整实现(第三期) | |
| 110 | +- 积分、`pricing_config`、充值、退款(第四期) | |
| 111 | +- `blacklist`(M.11)CRUD 后台页面、人脸黑名单审核(第四/五期) | |
| 112 | +- `admin-playback.html` 插播/置顶/暂停填充(6.5 节,非本期出口条件, | |
| 113 | + 有余力可顺手做但不阻塞验收) | |
| 114 | +- "我的作品"页面(7.4 节,依赖账号体系,第五期) | |
| 115 | +- fal.ai 接入、付费插队排播优先级(`priority: paid_boost`,第五期) | ... | ... |