From d7b36135d65c9af9d9db0eb103b997ea6e2e2ca4 Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Tue, 21 Jul 2026 09:16:54 +0800 Subject: [PATCH] =?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: [] }), }))