diff --git a/README.md b/README.md index 86dbfca..495548d 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,11 @@ 短剧 Agent 的前端工作台。支持剧本创作、拆解、视觉风格、角色选角、主体形态、分镜设计、镜头首帧与视频生产,使用真实后端 API,不包含演示数据或浏览器端模型调用。 -## 最新同步(2026-09-04) +## 最新同步(2026-09-07) -- 对齐后端 `dev@05bb9e8b7e0a0e85303b16eb3a2ac634e01dd7eb`:图片/视频模型由后端统一配置,前端不再发送固定 Provider。 -- 新增首帧视觉校验、有限自动修复、当前集小批量质量生成、视频抽样帧质量检查、视频修复候选与复检晋升、只读模型能力查询。默认不调用模型,付费操作需确认,结果可定位和导出。 +- 对齐后端 `dev@697cf864e1e8d6f66e3ad7beeebdfd0ae0d6c16c`:图片/视频模型由后端统一配置,前端不再发送固定 Provider。 +- 视频主入口使用严格质量流水线:候选生成完成后自动校验、有限修复,通过后才晋升主视频;首帧质量生成和手工抽样检查仍保留。 +- 分镜只使用正式项目级生成接口,不把 `generate-test`、`start-test` 或 `stream-test` 暴露为生产入口。 - 保留主要布局和业务能力,导出/执行记录/提示词等次要入口收进菜单,长介绍和高级规则按需展开;关键错误、过期、未保存与费用提示继续直显。 - 全部业务抽屉统一挂载到 `body`,侧栏及遮罩覆盖完整视口,不受 `main/content` 裁切;保持原有宽度、正文内部滚动和关闭后配置草稿。 @@ -153,10 +154,8 @@ Oxfmt 不负责代码质量,Oxlint 不负责 Vue 的完整类型推导;Vue S | POST | `/projects/:id/breakdown/resume-shots` | 复用已成功剧集镜头,生成缺失剧集 | | POST | `/projects/:id/breakdown/resume-storyboard` | 修复已有镜头的 SubjectRef / Form,再持久化 | | GET | `/projects/:id/storyboard-directions?episodeNo=N` | 正式 Shot ID、导演设计、单集覆盖率 | -| POST | `/projects/:id/storyboard-directions/generate-test` | 单集导演设计;明确发送 `persist: true` | | POST | `/projects/:id/storyboard-directions/generate` | 项目批量;`concurrency`、`force` | | GET | `/projects/:id/storyboard-visual-states?episodeNo=N` | 已持久化的环境、主体状态、单集覆盖率 | -| POST | `/projects/:id/storyboard-visual-states/generate-test` | 单集即时状态;`persist: true`、`maxRepairAttempts` | | POST | `/projects/:id/storyboard-visual-states/generate` | 项目批量;增加 `maxRepairAttempts` | | GET | `/storyboard-shots/:shotId/references` | 主体形态参考图、缺失原因 | | GET | `/storyboard-shots/:shotId/generation-spec` | 后端确定性编译结果,不调用模型 | @@ -188,10 +187,11 @@ Oxfmt 不负责代码质量,Oxlint 不负责 Vue 的完整类型推导;Vue S | GET / POST | `/projects/:id/keyframes/readiness`、`/keyframes/generate` | 首帧就绪检查与批量 后端图片模型 生图 | | GET / POST | `/storyboard-shots/:shotId/keyframes`、`/keyframe` | 单镜头首帧历史与生图 | | PUT | `/storyboard-shots/:shotId/keyframes/:keyframeId/primary` | 切换主首帧 | -| GET / POST | `/projects/:id/videos/readiness`、`/videos/generate` | 视频前置检查与批量 后端视频模型 任务 | +| GET / POST | `/projects/:id/videos/readiness`、`/videos/generate-quality` | 视频前置检查与批量严格质量任务 | | GET | `/projects/:id/videos/status` | 项目最近视频任务状态 | | POST | `/projects/:id/videos/retry-failed` | 重试最近失败的视频任务 | -| GET / POST | `/storyboard-shots/:shotId/videos` | 单镜头视频历史与任务创建 | +| GET | `/storyboard-shots/:shotId/videos` | 单镜头视频历史 | +| POST | `/storyboard-shots/:shotId/videos/generate-quality` | 单镜头严格质量候选;后台自动校验与有限修复 | | PUT | `/storyboard-shots/:shotId/videos/:videoId/primary` | 切换主视频 | | POST | `/projects/:id/production/start` | 高级串联入口;重复预检、费用确认,仅传两种 Provider,不生成首帧、不等待成片 | @@ -213,9 +213,8 @@ API 层也提供 `state` 与 `breakdown/latest` 方法。页面通过共享 chec 1. 入口为 `/projects/:projectId/storyboard`。先完成 Breakdown 的主体、形态、镜头与持久化,再生成 Direction,最后生成 VisualState。 2. 当前 Direction 服务读取**最新** Breakdown 的 `state.breakdownResult.storyboardEpisodeShots`;VisualState 读取顶层 `state.storyboardEpisodeShots`、`subjectCandidates`、`subjectForms`。页面不使用历史可恢复快照代替这些生成前置条件。历史快照只补充镜头标题和剧情描述。 3. 镜头 ID 来自正式数据库 GET,按 `shotId` 关联 Direction 和 VisualState。`shotNo` 仅在 Beat 内唯一,不能用它拼装接口 ID。VisualState 查询响应的环境字段是扁平结构,与单集生成返回的领域结构不同。 -4. 单集入口虽然名为 `generate-test`,也是后端目前唯一的单集生成接口。页面发送 `persist: true`,通过校验才保存;**单集始终重生成**,不受批量的覆盖开关影响。 -5. 批量默认 `force: false`,跳过完整剧集。重新点击“补齐”用于重试未完成项,没有虚构独立 retry 接口。`force: true` 才覆盖全部。VisualState 可设置非负整数修复次数,`0` 表示不修复。 -6. VisualState 单集生成需要该集所有正式镜头都有 Direction;批量接口由后端逐集检查,缺少前置条件的集数会单独失败。HTTP 200 也可能包含校验失败或部分失败,页面展示逐集诊断和修复次数,不视为全成功。 +4. 页面只使用正式项目批量接口;`generate-test` 暂不作为前端入口。批量默认 `force: false`,跳过完整剧集;`force: true` 才覆盖全部。VisualState 可设置非负整数修复次数,`0` 表示不修复。 +5. VisualState 批量接口由后端逐集检查;缺少完整 Direction 等前置条件的集数会单独失败。HTTP 200 也可能包含校验失败或部分失败,页面展示逐集诊断和修复次数,不视为全成功。 7. 上游重生成**不会自动使下游旧数据失效**。覆盖 Direction 后请重生成 VisualState,修改设计/状态/参考图后按需覆盖 Prompt。覆盖率只说明字段已保存,不能证明下游与新版本一致。 8. 分镜页用刷新按钮查询当前剧集的两类正式结果;这不是全项目实时进度。后端没有独立 Storyboard running / executionId 查询。回执只保留当前浏览器会话,切换页面不丢失,刷新浏览器会丢失。 9. 参考图和 GenerationSpec 按需 GET,切换镜头或设计变化时取消旧查询。GenerationSpec 需要有效的 Direction、VisualState 和形态关联,不生成图片或视频。 @@ -270,7 +269,7 @@ API 层也提供 `state` 与 `breakdown/latest` 方法。页面通过共享 chec - 精简的进度接口及按 graph 分页的 checkpoint; - 将 Breakdown 改为 202 异步任务提交,再以轮询或 SSE 读取进度。 -前端未模拟这些能力,不调用 `stream-test` 来伪造进度。Storyboard 的单集 `generate-test` 仅在用户明确确认生成后调用。 +前端未模拟这些能力,也不调用 `stream-test`、`start-test` 或 Storyboard `generate-test` 来伪造生产功能。 ## 部署 diff --git a/design-qa.md b/design-qa.md new file mode 100644 index 0000000..dcf5df8 --- /dev/null +++ b/design-qa.md @@ -0,0 +1,64 @@ +# Design QA + +- Source visual truth: + - `/workspace/scratch/6e52996114b8/upload/83e0987d-5b6e-46b1-b39b-0674bf374f43.png` + - `/workspace/scratch/6e52996114b8/upload/60e23391-685b-4538-95a2-46f6334f5f6d.png` + - `/workspace/scratch/6e52996114b8/upload/430bec04-93fd-429f-a820-1edefdafc792.png` +- Source pixel dimensions: `2048 × 819`, `447 × 203`, `238 × 198`. +- Intended implementation viewport: desktop dark theme; the primary reference is `2048 × 819`. +- Implementation screenshot: unavailable. +- CSS size and density normalization: unavailable because the implementation could not be opened in the cloud browser. +- State: 主体身份详情页已有身份母版;形态图库默认筛选和布局切换状态。 + +## Full-view comparison evidence + +The source images were opened and inspected. The first source shows the generic `.asset-image` width expanding the identity-anchor summary image across the detail panel and squeezing its explanatory copy into a narrow column on the far right. The second source shows the gallery summary/actions and filter panel consuming too much vertical space. The third source establishes the compact dark workspace density used by the surrounding pages. + +The implementation passed lint, formatting, TypeScript, component/unit tests, and the production build. A local Sites preview started successfully at the required port, but the cloud browser rejected `terminal.local` with `net::ERR_BLOCKED_BY_CLIENT` on both the existing tab and one fresh tab. Therefore no browser-rendered implementation evidence is available. + +## Focused region comparison evidence + +- Identity anchor: `.identity-anchor > .asset-image` now has a component-local `80 × 80` square constraint with higher selector specificity than the generic AssetImage width rule. The adjacent copy has `min-width: 0`. +- Identity detail container: the detail scrollbar, its container/content, and the panel now explicitly use `width: 100%`, `min-width: 0`, and `max-width: 100%` to contain long content. +- Gallery density: the summary/actions moved into the `WorkspacePage` header and the filter region's vertical padding changed from `14px` to `5px`. +- Page headers: every `WorkspacePage` caller now uses compact mode. + +These are code-level checks only and do not replace a rendered focused-region comparison. + +## Required fidelity surfaces + +- Fonts and typography: existing project font stack, sizes, weights, and wrapping were preserved; browser comparison is blocked. +- Spacing and layout rhythm: the requested header compaction and `5px` gallery filter padding are implemented; browser measurement is blocked. +- Colors and visual tokens: existing dark/light CSS variables were preserved; browser comparison is blocked. +- Image quality and asset fidelity: no source assets were replaced or generated; existing backend images remain in use. Browser crop verification is blocked. +- Copy and content: existing product copy is retained except where video generation now describes the formal strict-quality workflow. + +## Findings + +- [P1] Browser-rendered comparison unavailable + - Location: all three target states. + - Evidence: the preview process is healthy, but the required cloud browser returns `net::ERR_BLOCKED_BY_CLIENT` for `http://terminal.local:4173/`. + - Impact: exact visual fidelity, responsive behavior, interactions, and console state cannot be certified from the browser. + - Fix: open the same preview in an available Work Mode cloud browser, reproduce the target data/theme, capture the three states, and rerun this QA. + +## Primary interactions tested + +Automated component tests cover filters, layout switching, workspace drawers, project-level formal storyboard actions, video quality API parameters, disabled states, receipts, and navigation. Browser interactions were not available. + +## Console errors checked + +Not checked because the page could not be opened in the cloud browser. + +## Comparison history + +- Iteration 1: identified the P1 implementation-capture blocker after the local preview started. No visual iteration could be completed. + +## Implementation checklist + +- [x] Constrain the identity anchor thumbnail and detail width. +- [x] Move gallery summary/actions into the compact header. +- [x] Change gallery filter vertical padding from 14px to 5px. +- [x] Apply compact mode to all workspace pages. +- [ ] Capture and compare the rendered identity and gallery states in the cloud browser. + +final result: blocked diff --git a/docs/backend-coverage.md b/docs/backend-coverage.md index 15939c4..7578498 100644 --- a/docs/backend-coverage.md +++ b/docs/backend-coverage.md @@ -1,6 +1,6 @@ # 后端功能覆盖说明 -核对日期:2026-09-03。后端:`qianlanse/short-drama-agent`,`dev@05bb9e8b7e0a0e85303b16eb3a2ac634e01dd7eb`。以 API 路由和实际 service/workflow 实现为依据,不只根据接口名称推断功能。本轮不修改后端。 +核对日期:2026-09-07。后端:`qianlanse/short-drama-agent`,`dev@697cf864e1e8d6f66e3ad7beeebdfd0ae0d6c16c`。以 API 路由和实际 service/workflow 实现为依据,不只根据接口名称推断功能。本轮不修改后端。 ## 页面与接口能力 @@ -18,16 +18,16 @@ | 身份参考图 | 主体身份图库 | `identity/images`、图片 `anchor` | 保留完整预览、历史、辅助视角与母版切换;修正道具继承说明 | | 正式形态提示词 | 形态卡片 → 提示词与生成;批量工具 | POST `subject-forms/:id/generation-prompt`、项目 `subject-forms/generation-prompts` | 新增单个生成/重生成、原始素材与正式文本对照、导出、批量补齐/覆盖及失败回执 | | 形态图片 | 形态图片及图库 | 项目 `subject-forms`、形态 `images`、主图 PUT、项目 `subject-images/generate` | 增加本批数量上限;支持后端自动补正式 Prompt;人物/场景/道具已锁定母版继承;过期刷新只生成候选 | -| 导演设计与即时状态 | 分镜设计 | directions/visual-states 查询、单集 generate-test、项目 generate | 保留单集持久化(`persist: true`)、项目批量、覆盖、校验修复次数、逐集回执 | +| 导演设计与即时状态 | 分镜设计 | directions/visual-states 查询、项目 `generate` | 只保留正式项目批量、覆盖、校验修复次数和逐集回执;不暴露 `generate-test` | | 参考图与规格 | 分镜参考图/生产单镜头 | `references`、`generation-spec`、`keyframe-spec`、`video-generation-spec` | 保留按需只读检查与缺失原因,查询不调用生成模型 | | 视频提示词 | 分镜设计/镜头生产 | 单镜头 `video-prompt`、项目 `video-prompts/readiness` 与 `generate` | 保留单镜头/项目生成,重写需确认 | | 镜头首帧 | 镜头生产 | 项目 `keyframes/readiness` 与 `generate`、单镜头 keyframe/keyframes、主图 PUT | 新增批量 `limit` 与成对尺寸;保留当前集/过期项/覆盖范围;显示因上限未执行数 | -| 视频任务与主视频 | 镜头生产 | 项目 videos readiness/generate/status/retry-failed,逐镜 videos,单任务 status,主视频 PUT | 保留任务提交、轮询、播放、失败重试与主视频切换;不把 HTTP 完成当成片完成 | +| 视频任务与主视频 | 镜头生产 | 项目 videos readiness/generate-quality/status/retry-failed,逐镜 generate-quality/videos,单任务 status,主视频 PUT | 主入口改为严格质量候选:后台自动校验、有限修复,通过后晋升;保留状态刷新、播放和失败重试 | | 高级串联生产 | 镜头生产批量面板底部(默认折叠) | POST `/projects/:id/production/start` | 新增预检、再次校验、费用确认、分阶段回执与诊断导出;明确不是全链自动制片 | ## 新增质量检查与修复 -已接入:首帧 `validate`、`repair`,项目 `keyframes/generate-quality`,视频 `validate`/`repair`,公开图片模型能力及逐镜能力 GET。生成请求不再传固定 Provider。质量接口的详细参数、默认一镜范围、费用确认、主图晋升、三点视频抽样和会话回执限制见 [前端简化与质量功能同步](frontend-simplification.md)。首帧校验历史尚无 GET,不虚构读取接口;视频已有结果从 `rawJson.videoValidation` 读取。 +已接入:首帧 `validate`、`repair`,项目 `keyframes/generate-quality`,视频 `validate`/`repair`,以及单镜头和项目级 `videos/generate-quality`。严格视频候选由后端 Poller 自动执行 Validator,失败时按上限创建 Repair Candidate,只有 PASS 才晋升 Primary;前端识别 `rawJson.qualityCandidate`,禁止未通过候选绕过校验手动设为主视频。生成请求不再传固定 Provider。质量接口的详细参数、默认一镜范围、费用确认、主图晋升、三点视频抽样和会话回执限制见 [前端简化与质量功能同步](frontend-simplification.md)。首帧校验历史尚无 GET,不虚构读取接口;视频已有结果从 `rawJson.videoValidation` 读取。 ## 高级串联生产边界 @@ -63,7 +63,7 @@ | `timeline` | 新诊断从 `timeline/grouped` 展平并按 index 排序,保持同一份数据 | | 图片/首帧/视频的 GET primary | 从后端完整列表的 primary 标志选取,无需再次发相同内容请求 | | POST `/projects/:id/resume` | 实际只返回恢复信息,并不启动恢复工作流;不显示虚假的“继续执行”按钮 | -| `projects/stream-test`、`breakdown/start-test` | 测试专用,不暴露生产入口;Storyboard 的 generate-test 是现有正式单集生成入口,仍传 `persist: true` | +| `projects/stream-test`、`breakdown/start-test`、Storyboard `generate-test` | 测试或试运行路由,不暴露生产入口;分镜只使用正式项目级 `generate` | | 手工保存形态 generationPrompt、取消运行任务、删除项目、合并最终视频 | 后端没有对应正式路由,本轮不虚构按钮、成功提示或客户端模拟实现 | ## 回归验证 diff --git a/docs/frontend-simplification.md b/docs/frontend-simplification.md index 5d5209e..127c87d 100644 --- a/docs/frontend-simplification.md +++ b/docs/frontend-simplification.md @@ -35,13 +35,17 @@ | 已完成首帧 → 质量检查 → 仅校验 | POST `/storyboard-shots/:shotId/keyframes/:keyframeId/validate` | 调用视觉模型,不重生成、不切换主首帧 | | 首帧 → 质量检查 → 校验并修复 | POST 同路径 `/repair` | 有限重生成;新候选通过才晋升主首帧;原图直接通过不会自动晋升 | | 生产工具栏 → 首帧质量生成 | POST `/projects/:projectId/keyframes/generate-quality` | 当前集、默认最多一镜、并发 1、最多修复 1 次;每镜候选通过后才设主图 | +| 单镜头 → 提交视频质量任务 | POST `/storyboard-shots/:shotId/videos/generate-quality` | 创建严格质量候选;生成完成后由后端自动校验,失败时最多自动修复 2 次,通过后才晋升主视频 | +| 批量生产 → 视频成片 | POST `/projects/:projectId/videos/generate-quality` | 显式限制本批镜头数和每镜修复次数;只提交 ready 镜头,后续 Validator/Repair 由 Poller 推进 | | 已完成视频 → 质量检查 | POST `/storyboard-shots/:shotId/videos/:videoId/validate` | 三点抽帧视觉检查,不检测音频/口型/完整连续运动;普通候选不切换主视频,修复候选通过后自动晋升 | 批量质量配置与普通批量面板独立。后端非 force 先根据全项目是否有过期项决定筛选,再筛当前集;因此其他集存在过期项而当前集无过期项时,本集不会先补缺失首帧。前端明确提示切换剧集,不悄悄扩大范围。 允许文字按行输入并清理空白/重复;未填写不自行授权文字。宽高同时留空或填写正整数,修复次数可为 0。确认区显示本次最多生图/视觉校验调用次数,修改参数或目标后撤销费用确认。 -### 视频修复与复检晋升(本轮后端追加更新) +### 视频自动质量链与手工复检 + +生产页的单镜和批量视频主入口使用 `generate-quality`。HTTP 回执只表示初始 Candidate 已创建;后台 Poller 会在 Provider 完成后自动执行 Validator,失败时按 `maxRepairAttempts` 创建下一代 Repair Candidate,只有通过校验的版本才会晋升 Primary。前端读取 `rawJson.qualityCandidate` 和 `qualityPipeline` 标记质量候选,并禁止未通过候选使用普通“设为主视频”绕过校验。 视频质量面板新增“生成修复候选”,使用 POST `/storyboard-shots/:shotId/videos/:videoId/repair`,只接受 `maxRepairAttempts`(默认 2,正整数)。该参数是修复链的上限,不是本次自动生成次数。本次只提交一个视频候选,不自动等待、复检或循环重试;修复约束和允许文字沿用已保存的失败校验。 diff --git a/src/features/create-drama/CreateDramaPage.vue b/src/features/create-drama/CreateDramaPage.vue index d86418f..03a5b26 100644 --- a/src/features/create-drama/CreateDramaPage.vue +++ b/src/features/create-drama/CreateDramaPage.vue @@ -69,7 +69,7 @@ function exportScript() {