diff --git a/apps/web/src/pages/assets/AssetLibrary.tsx b/apps/web/src/pages/assets/AssetLibrary.tsx index 80aef0597..fa618d8ba 100644 --- a/apps/web/src/pages/assets/AssetLibrary.tsx +++ b/apps/web/src/pages/assets/AssetLibrary.tsx @@ -10,7 +10,6 @@ import { SearchOutlined, InboxOutlined, VideoCameraOutlined, - SoundOutlined, PictureOutlined, PlayCircleOutlined, CheckOutlined, @@ -37,7 +36,7 @@ import "./assets.css"; /* ============================================================ * 类型 * ============================================================ */ -type AssetKind = "video" | "voice" | "image"; +type AssetKind = "video" | "image"; type StatusType = "ok" | "warn" | "bad" | "info"; interface LibraryItem { @@ -67,7 +66,6 @@ interface AssetItem { /** 根据 mime_type 推断前端 AssetKind */ const inferKind = (mimeType: string): AssetKind => { if (mimeType.startsWith("video/")) return "video"; - if (mimeType.startsWith("audio/")) return "voice"; return "image"; }; @@ -99,7 +97,7 @@ const formatDuration = (seconds: number): string => { const mapLibrary = (item: AssetLibraryItem): LibraryItem => ({ id: item.id, name: item.name, - kind: item.kind || inferKind("video"), + kind: (item.kind === "voice" ? "video" : item.kind) || inferKind("video"), count: item.asset_count ?? 0, }); @@ -149,8 +147,6 @@ const kindIcon = (kind: AssetKind) => { switch (kind) { case "video": return ; - case "voice": - return ; case "image": return ; } @@ -160,8 +156,6 @@ const kindLabel = (kind: AssetKind) => { switch (kind) { case "video": return "视频"; - case "voice": - return "配音"; case "image": return "图片"; } @@ -172,8 +166,6 @@ const thumbGradient = (kind: AssetKind): string => { switch (kind) { case "video": return "linear-gradient(135deg, #312e81 0%, #4f46e5 50%, #6366f1 100%)"; - case "voice": - return "linear-gradient(135deg, #064e3b 0%, #059669 50%, #10b981 100%)"; case "image": return "linear-gradient(135deg, #78350f 0%, #d97706 50%, #f59e0b 100%)"; } @@ -246,7 +238,7 @@ const AssetCard: React.FC<{ )} {/* 视频/配音类显示播放按钮 */} - {(asset.kind === "video" || asset.kind === "voice") && ( + {asset.kind === "video" && ( { @@ -450,8 +442,9 @@ const AssetLibrary: React.FC = () => { message.success(`"${file.name}" 上传成功`); queryClient.invalidateQueries({ queryKey: ["assets"] }); queryClient.invalidateQueries({ queryKey: ["asset-libraries"] }); - } catch { - message.error(`"${file.name}" 上传失败`); + } catch (err: unknown) { + const detail = err instanceof Error ? err.message : ""; + message.error(`"${file.name}" 上传失败${detail ? `:${detail}` : ""}`); } finally { setUploading(false); setUploadProgress(0); @@ -645,7 +638,7 @@ const AssetLibrary: React.FC = () => { beforeUpload={handleUpload} showUploadList={false} multiple - accept="video/*,audio/*,image/*" + accept="video/*,image/*" >

@@ -655,7 +648,7 @@ const AssetLibrary: React.FC = () => { {uploading ? "上传中..." : "点击或拖拽文件到此区域上传"}

- 支持视频、音频、图片,单文件不超过 2GB + 支持视频、图片,单文件不超过 2GB

@@ -678,7 +671,6 @@ const AssetLibrary: React.FC = () => { options={[ { value: "all", label: "全部类型" }, { value: "video", label: "视频" }, - { value: "voice", label: "配音" }, { value: "image", label: "图片" }, ]} /> @@ -809,7 +801,6 @@ const AssetLibrary: React.FC = () => { style={{ width: "100%" }} options={[ { value: "video", label: "视频" }, - { value: "voice", label: "配音" }, { value: "image", label: "图片" }, ]} /> diff --git a/apps/web/src/pages/generate/GeneratePage.tsx b/apps/web/src/pages/generate/GeneratePage.tsx index 1c6ad79ea..2e0621c4e 100644 --- a/apps/web/src/pages/generate/GeneratePage.tsx +++ b/apps/web/src/pages/generate/GeneratePage.tsx @@ -6,11 +6,14 @@ */ import React, { useState, useRef, useCallback, useEffect } from "react"; import { useQuery, useMutation } from "@tanstack/react-query"; -import { Typography, message } from "antd"; +import { Typography, message, Select } from "antd"; import { AudioOutlined, ThunderboltOutlined, CheckCircleFilled, + CheckCircleOutlined, + CloseCircleOutlined, + LoadingOutlined, PlayCircleOutlined, PauseCircleOutlined, DownloadOutlined, @@ -160,6 +163,7 @@ const GeneratePage: React.FC = () => { const [generating, setGenerating] = useState(false); const [progress, setProgress] = useState(0); const [generated, setGenerated] = useState(false); + const [generateError, setGenerateError] = useState(null); const progressTimer = useRef>(undefined); const audioRef = useRef(null); @@ -477,6 +481,7 @@ const GeneratePage: React.FC = () => { setGenerating(true); setProgress(0); setGenerated(false); + setGenerateError(null); try { const voiceConfig: Record = {}; @@ -537,6 +542,7 @@ const GeneratePage: React.FC = () => { )?.error_message || "视频生成失败,请联系管理员或重试"; console.error("[生成失败] planId:", plan.id, "响应:", data); + setGenerateError(errorMsg); message.error(errorMsg); return; } @@ -593,7 +599,9 @@ const GeneratePage: React.FC = () => { "完整错误:", axiosErr, ); - message.error(backendMsg || "生成失败,请检查网络后重试或联系管理员"); + const errorMsg = backendMsg || "生成失败,请检查网络后重试或联系管理员"; + setGenerateError(errorMsg); + message.error(errorMsg); } }, [ title, @@ -917,14 +925,30 @@ const GeneratePage: React.FC = () => {

📝 选择标题

- +