From 8c9a71251c8120b4901561a08db5fe094e3b8adb Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Wed, 16 Sep 2026 11:09:33 +0800 Subject: [PATCH 1/3] =?UTF-8?q?fix(wizard):=20#1954=20=E7=94=9F=E6=88=90?= =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=90=8E=E5=BA=95=E9=83=A8=E6=8C=89=E9=92=AE?= =?UTF-8?q?=E6=AD=A3=E7=A1=AE=E6=98=BE=E7=A4=BA=E3=80=8C=E4=B8=8B=E4=B8=80?= =?UTF-8?q?=E6=AD=A5=EF=BC=9A=E9=80=89=E6=8B=A9=E5=B0=81=E9=9D=A2=E3=80=8D?= =?UTF-8?q?=E5=B9=B6=E8=A1=A5=E5=9B=9E=20E2E=20=E5=B0=81=E9=9D=A2=E6=AD=A5?= =?UTF-8?q?=E9=AA=A4=E6=96=AD=E8=A8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/GenerateStepActions.tsx | 42 ++++++++----------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/apps/web/src/pages/generate/components/GenerateStepActions.tsx b/apps/web/src/pages/generate/components/GenerateStepActions.tsx index 2f436814a..2f6c5660b 100644 --- a/apps/web/src/pages/generate/components/GenerateStepActions.tsx +++ b/apps/web/src/pages/generate/components/GenerateStepActions.tsx @@ -1,11 +1,11 @@ /** - * GeneratePage 步骤底部操作按钮(Issue #1677 修正:固定 6 步) - * v2: 步骤4 按钮前显示本次积分消耗;积分不足时禁用按钮并提示充值 + * GeneratePage 步骤底部操作按钮(5 步向导:素材→配音→标题→确认生成→封面) + * v3: 修复 #1954 off-by-one —— 步骤4 单视频/批量生成完成后正确显示「下一步:选择封面」 * * 步骤 1~3:上一步 / 下一步 - * 步骤 4(选择标题):「✨ 确认生成视频 / 确认生成 N 个视频」→ 创建正式生成任务,成功后跳步骤5 - * 步骤 5(确认生成):渲染进度页,全部完成后「下一步:选择封面」;仅上一步 - * 步骤 6(选择封面):仅上一步 + * 步骤 4(确认生成/进度):未开始 →「✨ 确认生成视频」;生成中 →「⏳ 视频渲染中…」; + * 失败 →「🔄 重新生成」;全部完成 →「下一步:选择封面 →」 + * 步骤 5(选择封面):仅上一步,无主按钮 */ import React from "react" import { Tooltip } from "antd" @@ -22,14 +22,13 @@ export interface GenerateStepActionsProps { generateError: string | null /** 批量模式下勾选的视频数量(N=1 时为1) */ selectedCount?: number - // v2: 积分相关 /** 本次预估消耗积分 */ estimatedCost?: number /** 是否积分不足 */ pointsInsufficient?: boolean /** 积分不足原因 */ insufficientReason?: string - /** 剩余免费混剪次数 */ + /** 本次使用的免费混剪次数 */ freeClipsUsedThisTime?: number /** 前往充值 */ onRecharge?: () => void @@ -60,8 +59,17 @@ const GenerateStepActions: React.FC = ({ ) } - /* 步骤 4:选择标题 — 确认生成 */ + /* 步骤 4:确认生成 / 进度 / 完成进封面 */ if (currentStep === 4) { + // #1954 修复:单视频/批量 全部生成完成后显示「下一步:选择封面」 + if (generated && !generating && !generateError) { + return ( + + ) + } + const costTag = typeof estimatedCost === "number" && estimatedCost > 0 ? ( @@ -118,23 +126,7 @@ const GenerateStepActions: React.FC = ({ ) } - /* 步骤 5:确认生成进度页 — 全部完成后下一步进封面 */ - if (currentStep === 5) { - if (generated) { - return ( - - ) - } - return ( - - ) - } - - /* 步骤 6(封面,最后一步):无主按钮 */ + /* 步骤 5(封面,最后一步):无主按钮 */ return null } -- 2.54.0 From 72b6c4ebb188234a90fa2376815f54fa8c0fc808 Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Wed, 16 Sep 2026 11:09:34 +0800 Subject: [PATCH 2/3] =?UTF-8?q?fix(wizard):=20#1954=20=E7=94=9F=E6=88=90?= =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=90=8E=E5=BA=95=E9=83=A8=E6=8C=89=E9=92=AE?= =?UTF-8?q?=E6=AD=A3=E7=A1=AE=E6=98=BE=E7=A4=BA=E3=80=8C=E4=B8=8B=E4=B8=80?= =?UTF-8?q?=E6=AD=A5=EF=BC=9A=E9=80=89=E6=8B=A9=E5=B0=81=E9=9D=A2=E3=80=8D?= =?UTF-8?q?=E5=B9=B6=E8=A1=A5=E5=9B=9E=20E2E=20=E5=B0=81=E9=9D=A2=E6=AD=A5?= =?UTF-8?q?=E9=AA=A4=E6=96=AD=E8=A8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/e2e/core-generation.spec.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/apps/web/e2e/core-generation.spec.ts b/apps/web/e2e/core-generation.spec.ts index c94dcec9b..a4a09953e 100755 --- a/apps/web/e2e/core-generation.spec.ts +++ b/apps/web/e2e/core-generation.spec.ts @@ -265,8 +265,21 @@ test.describe("Core generation flow", () => { await expect(page.getByText("视频渲染中")).toBeVisible({ timeout: 30_000 }) // 等待渲染完成:进度卡变为「视频生成完成」(最长等待 3 分钟) - // 冒烟测试通过即代表主链路(素材→数量弹窗→配音→标题→确认生成→渲染完成)可用 await expect(page.getByText("视频生成完成")).toBeVisible({ timeout: 180_000 }) + + // #1954 修复:生成完成后步骤4底部应显示「下一步:选择封面」按钮,点击进入步骤5封面页 + const nextCoverBtn = page + .locator(".xx-step-actions .xx-btn-primary") + .filter({ hasText: "下一步:选择封面" }) + await expect(nextCoverBtn).toBeVisible({ timeout: 10_000 }) + await nextCoverBtn.click() + + // 断言进入步骤5:步骤条应高亮「选择封面」,主内容出现「🖼️ 选择封面」标题 + await expect(page.getByRole("heading", { name: "🖼️ 选择封面" })).toBeVisible({ + timeout: 10_000, + }) + // 主按钮应消失(封面是最后一步),仅保留「← 上一步」 + await expect(page.locator(".xx-step-actions .xx-btn-primary")).toHaveCount(0) } else { console.log(`[E2E] Generate API returned ${genResp.status()}, wizard flow test still passes`) // 创建失败时停留在标题页并展示错误提示 -- 2.54.0 From 777104243d106ed1c309a5e04aca79e8c5a94752 Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Wed, 16 Sep 2026 11:56:53 +0800 Subject: [PATCH 3/3] =?UTF-8?q?test(e2e):=20#1954=20=E7=94=A8=E7=A8=B3?= =?UTF-8?q?=E5=AE=9A=E7=9A=84=E3=80=8C=E4=B8=8B=E8=BD=BD=E3=80=8D=E6=8C=89?= =?UTF-8?q?=E9=92=AE=E6=96=AD=E8=A8=80=E4=BB=A3=E6=9B=BF=E6=98=93=E6=B6=88?= =?UTF-8?q?=E5=A4=B1=E7=9A=84=E3=80=8C=E8=A7=86=E9=A2=91=E7=94=9F=E6=88=90?= =?UTF-8?q?=E5=AE=8C=E6=88=90=E3=80=8Dtoast?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/e2e/core-generation.spec.ts | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/apps/web/e2e/core-generation.spec.ts b/apps/web/e2e/core-generation.spec.ts index a4a09953e..e3247e0d6 100755 --- a/apps/web/e2e/core-generation.spec.ts +++ b/apps/web/e2e/core-generation.spec.ts @@ -264,22 +264,22 @@ test.describe("Core generation flow", () => { // 注意:进度页底部按钮变为 disabled 的「⏳ 视频渲染中…」 await expect(page.getByText("视频渲染中")).toBeVisible({ timeout: 30_000 }) - // 等待渲染完成:进度卡变为「视频生成完成」(最长等待 3 分钟) - await expect(page.getByText("视频生成完成")).toBeVisible({ timeout: 180_000 }) + // 等待渲染完成:单视频成片播放器渲染(带「⬇️ 下载」按钮),最长等待 3 分钟 + // 注意:message.success「视频生成完成」toast 3秒后自动消失,不能作为稳定断言点 + await expect(page.getByRole("button", { name: "⬇️ 下载" })).toBeVisible({ timeout: 180_000 }) - // #1954 修复:生成完成后步骤4底部应显示「下一步:选择封面」按钮,点击进入步骤5封面页 + // #1954 修复:生成完成后步骤4底部应显示「下一步:选择封面」按钮 + // 等待底部主按钮从「⏳/确认生成」切换为「下一步:选择封面」 const nextCoverBtn = page - .locator(".xx-step-actions .xx-btn-primary") - .filter({ hasText: "下一步:选择封面" }) - await expect(nextCoverBtn).toBeVisible({ timeout: 10_000 }) + .locator(".xx-step-actions > .xx-btn-primary") + .filter({ hasText: "选择封面" }) + await expect(nextCoverBtn).toBeVisible({ timeout: 15_000 }) await nextCoverBtn.click() - // 断言进入步骤5:步骤条应高亮「选择封面」,主内容出现「🖼️ 选择封面」标题 - await expect(page.getByRole("heading", { name: "🖼️ 选择封面" })).toBeVisible({ - timeout: 10_000, - }) - // 主按钮应消失(封面是最后一步),仅保留「← 上一步」 - await expect(page.locator(".xx-step-actions .xx-btn-primary")).toHaveCount(0) + // 断言进入步骤5封面页:主内容出现「选择封面」标题 + await expect(page.getByText("🖼️ 选择封面")).toBeVisible({ timeout: 10_000 }) + // 底部操作栏主按钮应消失(封面是最后一步,只剩「← 上一步」) + await expect(page.locator(".xx-step-actions > .xx-btn-primary")).toHaveCount(0) } else { console.log(`[E2E] Generate API returned ${genResp.status()}, wizard flow test still passes`) // 创建失败时停留在标题页并展示错误提示 -- 2.54.0