From 3104d82a7bb230dbcfeea179b827058b4a726a6d Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Tue, 18 Aug 2026 13:15:39 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=A0=87=E9=A2=98=E5=8F=A0=E5=8A=A0?= =?UTF-8?q?=E5=B1=82=E5=A7=8B=E7=BB=88=E6=B8=B2=E6=9F=93+=E7=A7=BB?= =?UTF-8?q?=E9=99=A4=E4=B8=8D=E5=AD=98=E5=9C=A8=E7=9A=84batch=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PreviewVideoPanel: 重构布局结构,标题叠加层不再受加载状态影响 - 单一 .xx-preview-video 容器,内部条件渲染 loading/player - TitleOverlay 始终渲染在容器顶层(z-index: 30) - 只要有标题文字就显示,不依赖素材加载完成 - usePreviewAssets: 移除 POST /assets/batch(后端返回405) - 直接使用 Promise.allSettled 并发 GET /assets/{id} - 消除每次加载时的无效 405 请求 --- .../generate/components/PreviewVideoPanel.tsx | 50 +++++++++++-------- .../pages/generate/hooks/usePreviewAssets.ts | 23 +++------ 2 files changed, 35 insertions(+), 38 deletions(-) diff --git a/apps/web/src/pages/generate/components/PreviewVideoPanel.tsx b/apps/web/src/pages/generate/components/PreviewVideoPanel.tsx index 7ab9e7d12..2976a8156 100644 --- a/apps/web/src/pages/generate/components/PreviewVideoPanel.tsx +++ b/apps/web/src/pages/generate/components/PreviewVideoPanel.tsx @@ -132,7 +132,7 @@ const TitleOverlay: React.FC<{ titleSettings: TitleSettings }> = ({ titleSetting style={{ position: "absolute", inset: 0, - zIndex: 20, + zIndex: 30, pointerEvents: "none", }} > @@ -160,6 +160,7 @@ export const PreviewVideoPanel: React.FC = ({ titleSettings, }) => { const videoAspectStyle = { aspectRatio: (videoRatio || "16:9").replace(":", "/") } + const hasTitle = !!titleSettings?.title?.trim() return (
@@ -168,33 +169,40 @@ export const PreviewVideoPanel: React.FC = ({ {assetsReady && assets.length > 0 && 实时预览}
- {/* 加载中 */} - {assetsLoading && ( -
-
-
- -

- 加载素材中... -

-
+ {/* 预览容器 — 标题叠加层始终渲染在容器顶层,不受加载状态影响 */} +
+ {/* 内容层:加载中 or 前端播放器 */} + {assetsLoading ? ( +
+ +

+ 加载素材中... +

-
- )} - - {/* 前端预览播放器 + CSS 标题叠加 */} - {!assetsLoading && ( -
+ ) : ( - {/* CSS 标题实时预览层 — 与 FFmpeg ASS 渲染坐标对齐 */} - {titleSettings && } -
- )} + )} + + {/* CSS 标题实时预览层 — 与 FFmpeg ASS 渲染坐标对齐 + 始终渲染在内容层之上(z-index: 30),只要 titleSettings 有标题文字就显示 */} + {hasTitle && } +
{/* 素材信息 */} {assetsReady && assets.length > 0 && ( diff --git a/apps/web/src/pages/generate/hooks/usePreviewAssets.ts b/apps/web/src/pages/generate/hooks/usePreviewAssets.ts index 48b93387d..69d221a26 100644 --- a/apps/web/src/pages/generate/hooks/usePreviewAssets.ts +++ b/apps/web/src/pages/generate/hooks/usePreviewAssets.ts @@ -1,33 +1,22 @@ /** * 预览素材加载 Hook - * 根据选中的素材 ID 列表,批量获取素材详情(含 file_url、duration 等) + * 根据选中的素材 ID 列表,逐个获取素材详情(含 file_url、duration 等) * 供前端预览播放器使用 + * + * 注意:后端没有批量接口(/assets/batch 返回 405), + * 因此直接使用 Promise.allSettled 并发请求单个 GET /assets/{id} */ import { useState, useEffect, useCallback, useRef } from "react" import type { AssetItem } from "@/api/assets" import type { AxiosResponse } from "axios" -/** 批量获取素材详情的 API 路径 */ -const ASSETS_BATCH_URL = "/assets/batch" - /** - * 通过 ID 列表批量获取素材 - * 优先使用批量接口,失败则回退为逐个获取 + * 通过 ID 列表逐个获取素材(并发) + * 使用 Promise.allSettled 确保单个失败不影响整体 */ async function fetchAssetsByIds(ids: string[]): Promise { if (!ids.length) return [] - try { - // 尝试批量接口 - const { default: apiClient } = await import("@/api/client") - const response = await apiClient.post(ASSETS_BATCH_URL, { ids }) - const items: AssetItem[] = response.data?.items || response.data || [] - if (items.length > 0) return items - } catch { - // 批量接口不存在,回退为逐个获取 - } - - // 回退:逐个获取 try { const { default: apiClient } = await import("@/api/client") const results = await Promise.allSettled( -- 2.54.0