From 277e46de4bc612a60cace13466d7f48a93d6eec6 Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Tue, 28 Jul 2026 15:26:56 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=85=8B=E9=9A=86=E9=9F=B3=E8=89=B2?= =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E8=A1=A5=E5=85=85=20project=5Fid/library=5Fi?= =?UTF-8?q?d=20=E4=BF=AE=E5=A4=8D=20422=20=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 后端 POST /upload 接口要求 FormData 必须包含 project_id 和 library_id, 克隆音色弹窗只传了 file 导致 422 Unprocessable Entity。 修复:上传前调用 getOrCreateDefaultProject() 和 ensureDefaultLibrary() 获取默认项目和 voice 素材库,追加到 FormData。 --- apps/web/src/components/voice/CloneModal.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/web/src/components/voice/CloneModal.tsx b/apps/web/src/components/voice/CloneModal.tsx index b962f2938..1162fda71 100644 --- a/apps/web/src/components/voice/CloneModal.tsx +++ b/apps/web/src/components/voice/CloneModal.tsx @@ -14,7 +14,8 @@ import React, { useState, useCallback, useRef, useEffect } from "react"; import { Modal, Button } from "@/components/ui"; import { createVoiceClone, toVoiceClone } from "@/api/voiceClone"; import type { VoiceClone } from "@/api/voiceClone"; -import { uploadAsset } from "@/api/assets"; +import { uploadAsset, ensureDefaultLibrary } from "@/api/assets"; +import { getOrCreateDefaultProject } from "@/api/projects"; import "./clone-modal.css"; /* ── 类型定义 ───────────────────────────────────────────── */ @@ -334,8 +335,14 @@ const CloneModal: React.FC = ({ ); } + // 获取默认项目和素材库(后端 /upload 接口必填) + const project = await getOrCreateDefaultProject(); + const library = await ensureDefaultLibrary({ project_id: project.id, kind: "voice" }); + const formData = new FormData(); formData.append("file", fileToUpload); + formData.append("project_id", project.id); + formData.append("library_id", library.id); const uploadResult = await uploadAsset(formData); // 阶段 2:克隆