From d7b36135d65c9af9d9db0eb103b997ea6e2e2ca4 Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Tue, 21 Jul 2026 09:16:54 +0800 Subject: [PATCH 1/5] =?UTF-8?q?fix(web):=20=E4=BF=AE=E5=A4=8D=E7=94=9F?= =?UTF-8?q?=E6=88=90=E9=A1=B5=20API=20=E8=B0=83=E7=94=A8=E9=80=82=E9=85=8D?= =?UTF-8?q?=E6=96=B0=E6=A8=A1=E6=9D=BF=E7=BC=96=E8=BE=91=E5=99=A8=E6=9E=B6?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #666 将 API 路径迁移到 /templates/{templateId}/editor 架构,但只改了 import 路径, 没有适配函数签名变化(参数从 planId 改为 templateId),也没有替换已废弃的 createEditPlan(后端无 /templates/drafts 接口)。 修复内容: - GeneratePage: createEditPlan → getEditPlan 自动创建草稿 + updateEditPlan 更新内容 - GeneratePage: 所有 plan.id 调用改为 selectedTemplate(templateId) - E2E: 等待 POST /editor/generate 替代已废弃的创建接口 - 单元测试: 更新 mock 返回值适配新 API 签名 根因:POST /template-editors → 404 → POST /templates/drafts → 405 --- apps/web/e2e/core-generation.spec.ts | 26 ++++++++++--------- apps/web/src/pages/generate/GeneratePage.tsx | 23 ++++++++-------- apps/web/src/test/pages/GeneratePage.test.tsx | 8 +++--- 3 files changed, 29 insertions(+), 28 deletions(-) mode change 100644 => 100755 apps/web/src/test/pages/GeneratePage.test.tsx diff --git a/apps/web/e2e/core-generation.spec.ts b/apps/web/e2e/core-generation.spec.ts index bd33efec8..1dfdf80e8 100755 --- a/apps/web/e2e/core-generation.spec.ts +++ b/apps/web/e2e/core-generation.spec.ts @@ -219,15 +219,16 @@ test.describe("Core generation flow", () => { // Step 7: confirm and generate await expect(page.getByRole("heading", { name: /确认生成/ })).toBeVisible() - // Wait for plan creation API to be called - // 精确匹配 POST /template-editors(创建接口),排除所有子路径(/generate, /clips, /ai-recommend 等) - const createPlanPromise = page.waitForResponse( + // Wait for generation API to be called + // 新架构:GET 草稿自动创建 → PUT 更新内容 → POST /generate 触发生成 + // 等 generate 接口返回,确认生成流程启动 + const generatePromise = page.waitForResponse( (response) => { const url = response.url() const path = new URL(url).pathname return ( response.request().method() === "POST" && - (path.endsWith("/templates/drafts") || path.endsWith("/templates/drafts/")) + path.endsWith("/editor/generate") ) }, { timeout: 30_000 }, @@ -236,17 +237,18 @@ test.describe("Core generation flow", () => { // Click generate button await page.locator(".xx-btn-primary").filter({ hasText: "确认生成" }).first().click() - // Verify plan was created successfully - const planResp = await createPlanPromise - if (!planResp.ok()) { - const body = await planResp.text() + // Verify generation was triggered successfully + const genResp = await generatePromise + if (!genResp.ok()) { + const body = await genResp.text() console.error( - `[E2E DEBUG] 创建计划接口失败: status=${planResp.status()} url=${planResp.url()} body=${body.slice(0, 500)}`, + `[E2E DEBUG] 触发生成接口失败: status=${genResp.status()} url=${genResp.url()} body=${body.slice(0, 500)}`, ) } - expect(planResp.ok()).toBeTruthy() - const planData = (await planResp.json()) as { id: string } - expect(planData.id).toBeTruthy() + expect(genResp.ok()).toBeTruthy() + const genData = (await genResp.json()) as { plan_id: string; generation_task_id: string } + expect(genData.plan_id).toBeTruthy() + expect(genData.generation_task_id).toBeTruthy() // Generation may fail in test env (no worker), that's OK // Just verify the flow started - check page shows generation-related UI diff --git a/apps/web/src/pages/generate/GeneratePage.tsx b/apps/web/src/pages/generate/GeneratePage.tsx index 27df1161a..e5901cd7c 100755 --- a/apps/web/src/pages/generate/GeneratePage.tsx +++ b/apps/web/src/pages/generate/GeneratePage.tsx @@ -25,11 +25,11 @@ import { import type { AssetItem } from "@/api/assets" import { getAssets, getAssetLibraries } from "@/api/assets" import { - createEditPlan, generateEditPlan, updateEditPlan, getGenerationTaskResults, getGenerationStatus, + getEditPlan, } from "@/api/templateEditor" import type { GeneratedVideo, EditPlanConfig, TitleConfig } from "@/api/templateEditor" import type { CoverConfig } from "../editing-planner/types" @@ -44,7 +44,6 @@ import { synthesizeSpeech, getTTSJobStatus, saveTtsToLibrary } from "@/api/tts" import { getTags, createTag } from "@/api/tags" import { useCloneProgress } from "@/hooks/useCloneProgress" import { useSearchParams, useNavigate } from "react-router-dom" -import { getEditPlan } from "@/api/templateEditor" import "./generate.css" const { Text } = Typography @@ -994,8 +993,11 @@ const GeneratePage: React.FC = () => { if (customVoiceText.trim()) voiceConfig.custom_text = customVoiceText.trim() } - const plan = await createEditPlan({ - template_id: selectedTemplate, + // 获取或创建草稿(新架构:GET /templates/{templateId}/editor 自动创建) + const plan = await getEditPlan(selectedTemplate) + + // 更新草稿内容 + 切换到 editing 状态 + await updateEditPlan(selectedTemplate, { name: titleSettings.title.trim(), config: { asset_ids: materialMode === "auto" ? smartSelectedIds : selectedMaterials, @@ -1018,17 +1020,14 @@ const GeneratePage: React.FC = () => { material_mode: materialMode, }, total_duration: duration, - source_edit_plan_id: editPlanId || undefined, + status: "editing", }) - // 后端要求计划处于 editing 状态才能触发渲染,自动转换状态 - await updateEditPlan(plan.id, { status: "editing" }) - - await generateEditPlan(plan.id) + await generateEditPlan(selectedTemplate) const poll = async () => { try { - const data = await getGenerationStatus(plan.id) + const data = await getGenerationStatus(selectedTemplate) if (data.plan_status === "completed") { setProgress(100) @@ -1075,7 +1074,7 @@ const GeneratePage: React.FC = () => { return String(val ?? "") } const errorMsg = safeExtract(rawMsg) - console.error("[生成失败] planId:", plan.id, "响应:", data) + console.error("[生成失败] templateId:", selectedTemplate, "响应:", data) setGenerateError(errorMsg) message.error(errorMsg) return @@ -1091,7 +1090,7 @@ const GeneratePage: React.FC = () => { > } catch (pollErr) { // 轮询接口本身出错(网络/鉴权等),记录并继续轮询一次 - console.error("[轮询出错] planId:", plan.id, pollErr) + console.error("[轮询出错] templateId:", selectedTemplate, pollErr) progressTimer.current = setTimeout(poll, 3000) as unknown as ReturnType< typeof setInterval > diff --git a/apps/web/src/test/pages/GeneratePage.test.tsx b/apps/web/src/test/pages/GeneratePage.test.tsx old mode 100644 new mode 100755 index f85c14af8..d02d98eb5 --- a/apps/web/src/test/pages/GeneratePage.test.tsx +++ b/apps/web/src/test/pages/GeneratePage.test.tsx @@ -214,10 +214,10 @@ vi.mock("@/api/titles", () => ({ })) vi.mock("@/api/templateEditor", () => ({ - createEditPlan: vi.fn().mockResolvedValue({ id: "test-plan" }), - generateEditPlan: vi.fn().mockResolvedValue({ task_id: "test-task" }), - updateEditPlan: vi.fn().mockResolvedValue({}), - getEditPlan: vi.fn().mockResolvedValue({}), + generateEditPlan: vi.fn().mockResolvedValue({ plan_id: "test-plan", generation_task_id: "test-task", plan_status: "processing", clip_count: 5 }), + updateEditPlan: vi.fn().mockResolvedValue({ plan_id: "test-plan", template_id: "test-template" }), + getEditPlan: vi.fn().mockResolvedValue({ plan_id: "test-plan", template_id: "test-template", name: "", config: {}, status: "draft" }), + getGenerationStatus: vi.fn().mockResolvedValue({ plan_status: "completed", generation_task_id: "test-task", clips: [] }), getGenerationTaskResults: vi.fn().mockResolvedValue({ items: [] }), })) -- 2.54.0 From 211b1ee33f407b229348250190bafbb645178537 Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Tue, 21 Jul 2026 10:04:08 +0800 Subject: [PATCH 2/5] =?UTF-8?q?fix(web):=20=E4=BF=AE=E5=A4=8Dlint=E9=94=99?= =?UTF-8?q?=E8=AF=AF=20-=20=E7=A7=BB=E9=99=A4=E6=9C=AA=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E5=8F=98=E9=87=8F=E5=92=8C=E5=A4=9A=E4=BD=99=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/src/pages/generate/GeneratePage.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) mode change 100755 => 100644 apps/web/src/pages/generate/GeneratePage.tsx diff --git a/apps/web/src/pages/generate/GeneratePage.tsx b/apps/web/src/pages/generate/GeneratePage.tsx old mode 100755 new mode 100644 index e5901cd7c..d95ce718d --- a/apps/web/src/pages/generate/GeneratePage.tsx +++ b/apps/web/src/pages/generate/GeneratePage.tsx @@ -994,7 +994,7 @@ const GeneratePage: React.FC = () => { } // 获取或创建草稿(新架构:GET /templates/{templateId}/editor 自动创建) - const plan = await getEditPlan(selectedTemplate) + await getEditPlan(selectedTemplate) // 更新草稿内容 + 切换到 editing 状态 await updateEditPlan(selectedTemplate, { @@ -1197,7 +1197,6 @@ const GeneratePage: React.FC = () => { duration, autoSubtitles, bgm, - editPlanId, selectedTemplate, generateCount, materialMode, -- 2.54.0 From 654c04f5cac0800a2460e1a5d9ba1bbb49296c35 Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Tue, 21 Jul 2026 10:08:22 +0800 Subject: [PATCH 3/5] fix: prettier formatting --- apps/web/e2e/core-generation.spec.ts | 5 +--- apps/web/src/test/pages/GeneratePage.test.tsx | 23 ++++++++++++++++--- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/apps/web/e2e/core-generation.spec.ts b/apps/web/e2e/core-generation.spec.ts index 1dfdf80e8..d4e4fb6d8 100755 --- a/apps/web/e2e/core-generation.spec.ts +++ b/apps/web/e2e/core-generation.spec.ts @@ -226,10 +226,7 @@ test.describe("Core generation flow", () => { (response) => { const url = response.url() const path = new URL(url).pathname - return ( - response.request().method() === "POST" && - path.endsWith("/editor/generate") - ) + return response.request().method() === "POST" && path.endsWith("/editor/generate") }, { timeout: 30_000 }, ) diff --git a/apps/web/src/test/pages/GeneratePage.test.tsx b/apps/web/src/test/pages/GeneratePage.test.tsx index d02d98eb5..84735cf39 100755 --- a/apps/web/src/test/pages/GeneratePage.test.tsx +++ b/apps/web/src/test/pages/GeneratePage.test.tsx @@ -214,10 +214,27 @@ vi.mock("@/api/titles", () => ({ })) vi.mock("@/api/templateEditor", () => ({ - generateEditPlan: vi.fn().mockResolvedValue({ plan_id: "test-plan", generation_task_id: "test-task", plan_status: "processing", clip_count: 5 }), + generateEditPlan: vi + .fn() + .mockResolvedValue({ + plan_id: "test-plan", + generation_task_id: "test-task", + plan_status: "processing", + clip_count: 5, + }), updateEditPlan: vi.fn().mockResolvedValue({ plan_id: "test-plan", template_id: "test-template" }), - getEditPlan: vi.fn().mockResolvedValue({ plan_id: "test-plan", template_id: "test-template", name: "", config: {}, status: "draft" }), - getGenerationStatus: vi.fn().mockResolvedValue({ plan_status: "completed", generation_task_id: "test-task", clips: [] }), + getEditPlan: vi + .fn() + .mockResolvedValue({ + plan_id: "test-plan", + template_id: "test-template", + name: "", + config: {}, + status: "draft", + }), + getGenerationStatus: vi + .fn() + .mockResolvedValue({ plan_status: "completed", generation_task_id: "test-task", clips: [] }), getGenerationTaskResults: vi.fn().mockResolvedValue({ items: [] }), })) -- 2.54.0 From 4dbda36c52375ba1639ce7fd63d36b4b5a578bae Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Tue, 21 Jul 2026 10:08:56 +0800 Subject: [PATCH 4/5] fix: restore file permissions --- apps/web/src/pages/voice-materials/VoiceMaterialLibrary.tsx | 0 apps/web/src/test/pages/GeneratePage.test.tsx | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 apps/web/src/pages/voice-materials/VoiceMaterialLibrary.tsx mode change 100755 => 100644 apps/web/src/test/pages/GeneratePage.test.tsx diff --git a/apps/web/src/pages/voice-materials/VoiceMaterialLibrary.tsx b/apps/web/src/pages/voice-materials/VoiceMaterialLibrary.tsx old mode 100755 new mode 100644 diff --git a/apps/web/src/test/pages/GeneratePage.test.tsx b/apps/web/src/test/pages/GeneratePage.test.tsx old mode 100755 new mode 100644 -- 2.54.0 From 86493c1753a4d10b8c34edba4b4ccfce372f368d Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Tue, 21 Jul 2026 10:30:43 +0800 Subject: [PATCH 5/5] fix: prettier formatting take 2 --- apps/web/src/test/pages/GeneratePage.test.tsx | 30 ++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/apps/web/src/test/pages/GeneratePage.test.tsx b/apps/web/src/test/pages/GeneratePage.test.tsx index 84735cf39..25b4975fc 100644 --- a/apps/web/src/test/pages/GeneratePage.test.tsx +++ b/apps/web/src/test/pages/GeneratePage.test.tsx @@ -214,24 +214,20 @@ vi.mock("@/api/titles", () => ({ })) vi.mock("@/api/templateEditor", () => ({ - generateEditPlan: vi - .fn() - .mockResolvedValue({ - plan_id: "test-plan", - generation_task_id: "test-task", - plan_status: "processing", - clip_count: 5, - }), + generateEditPlan: vi.fn().mockResolvedValue({ + plan_id: "test-plan", + generation_task_id: "test-task", + plan_status: "processing", + clip_count: 5, + }), updateEditPlan: vi.fn().mockResolvedValue({ plan_id: "test-plan", template_id: "test-template" }), - getEditPlan: vi - .fn() - .mockResolvedValue({ - plan_id: "test-plan", - template_id: "test-template", - name: "", - config: {}, - status: "draft", - }), + getEditPlan: vi.fn().mockResolvedValue({ + plan_id: "test-plan", + template_id: "test-template", + name: "", + config: {}, + status: "draft", + }), getGenerationStatus: vi .fn() .mockResolvedValue({ plan_status: "completed", generation_task_id: "test-task", clips: [] }), -- 2.54.0