From 75e42002b5ca876adfa6b48fc6a99bf10701f4ea Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Thu, 6 Aug 2026 10:16:31 +0800 Subject: [PATCH 01/13] =?UTF-8?q?feat:=20=E7=B4=A0=E6=9D=90=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E6=B7=BB=E5=8A=A048x48=E7=BC=A9=E7=95=A5=E5=9B=BE?= =?UTF-8?q?=E9=A2=84=E8=A7=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../material/ManualMaterialList.tsx | 37 ++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/apps/web/src/pages/generate/components/material/ManualMaterialList.tsx b/apps/web/src/pages/generate/components/material/ManualMaterialList.tsx index 0225a338f..15825b189 100644 --- a/apps/web/src/pages/generate/components/material/ManualMaterialList.tsx +++ b/apps/web/src/pages/generate/components/material/ManualMaterialList.tsx @@ -32,6 +32,8 @@ const ManualMaterialList: React.FC = ({
{materials.items.map((m) => { const checked = selectedMaterials.includes(m.id) + const isVideo = m.mime_type.startsWith("video/") + const thumbSrc = m.thumbnail_url || (isVideo ? m.file_url : undefined) return (
-
+
)} @@ -310,6 +348,7 @@ export const PreviewVideoPanel: React.FC = ({
-
+
)} -- 2.54.0 From 1caa1296d9583099ec37a078105e27f105f0d282 Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Thu, 6 Aug 2026 10:24:12 +0800 Subject: [PATCH 04/13] =?UTF-8?q?fix:=20mime=5Ftype=E5=8F=AF=E9=80=89?= =?UTF-8?q?=E9=93=BE=E9=98=B2=E5=BE=A1+=E7=BC=A9=E7=95=A5=E5=9B=BEsrc?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AI Code Review阻塞问题修复: - mime_type使用?.可选链避免null/undefined崩溃 - 类型标签split链加?.和默认值 - thumbSrc已有三元条件渲染 --- .../pages/generate/components/material/ManualMaterialList.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/web/src/pages/generate/components/material/ManualMaterialList.tsx b/apps/web/src/pages/generate/components/material/ManualMaterialList.tsx index 15825b189..61a8bd6ba 100644 --- a/apps/web/src/pages/generate/components/material/ManualMaterialList.tsx +++ b/apps/web/src/pages/generate/components/material/ManualMaterialList.tsx @@ -32,7 +32,7 @@ const ManualMaterialList: React.FC = ({
{materials.items.map((m) => { const checked = selectedMaterials.includes(m.id) - const isVideo = m.mime_type.startsWith("video/") + const isVideo = m.mime_type?.startsWith("video/") ?? false const thumbSrc = m.thumbnail_url || (isVideo ? m.file_url : undefined) return ( ) -- 2.54.0 From 3966f91398370d39f0641ead03ea8743e48cd83d Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Thu, 6 Aug 2026 10:29:10 +0800 Subject: [PATCH 05/13] =?UTF-8?q?fix:=20=E7=A7=BB=E9=99=A4file=5Furl?= =?UTF-8?q?=E4=BD=9C=E4=B8=BAimg=20src=E5=9B=9E=E9=80=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit file_url是视频/音频文件,无法渲染。 仅使用thumbnail_url(静态截图),无缩略图时显示emoji fallback --- .../pages/generate/components/material/ManualMaterialList.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/web/src/pages/generate/components/material/ManualMaterialList.tsx b/apps/web/src/pages/generate/components/material/ManualMaterialList.tsx index 61a8bd6ba..112bddaee 100644 --- a/apps/web/src/pages/generate/components/material/ManualMaterialList.tsx +++ b/apps/web/src/pages/generate/components/material/ManualMaterialList.tsx @@ -33,7 +33,9 @@ const ManualMaterialList: React.FC = ({ {materials.items.map((m) => { const checked = selectedMaterials.includes(m.id) const isVideo = m.mime_type?.startsWith("video/") ?? false - const thumbSrc = m.thumbnail_url || (isVideo ? m.file_url : undefined) + // thumbnail_url 是静态截图,可直接用于 + // file_url 是视频/音频文件本身, 无法渲染,不能作为 src 回退 + const thumbSrc = m.thumbnail_url || undefined return (
Date: Thu, 6 Aug 2026 11:21:16 +0800 Subject: [PATCH 13/13] =?UTF-8?q?fix:=20Canvas=E6=A0=87=E9=A2=98=E5=B1=85?= =?UTF-8?q?=E4=B8=AD=E5=A2=9E=E5=8A=A0offsetY=E8=A1=A5=E5=81=BFvideo?= =?UTF-8?q?=E5=9E=82=E7=9B=B4=E5=81=8F=E7=A7=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/pages/generate/components/PreviewVideoPanel.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/web/src/pages/generate/components/PreviewVideoPanel.tsx b/apps/web/src/pages/generate/components/PreviewVideoPanel.tsx index afe097426..d02fd88a3 100644 --- a/apps/web/src/pages/generate/components/PreviewVideoPanel.tsx +++ b/apps/web/src/pages/generate/components/PreviewVideoPanel.tsx @@ -55,6 +55,7 @@ function wrapText(ctx: CanvasRenderingContext2D, text: string, maxWidth: number) * @param topOffset 顶部/底部偏移量 * @param fontSizeScale 字号缩放(no-video 模式下缩小) * @param offsetX 绘制区域左边缘相对于 canvas 的偏移(用于 video 居中时补偿 offsetLeft) + * @param offsetY 绘制区域上边缘相对于 canvas 的偏移(用于 video 居中时补偿 offsetTop) */ function drawTitleOnCanvas( ctx: CanvasRenderingContext2D, @@ -67,6 +68,7 @@ function drawTitleOnCanvas( topOffset: number, fontSizeScale = 1, offsetX = 0, + offsetY = 0, ) { const dpr = window.devicePixelRatio || 1 const w = canvasWidth @@ -130,10 +132,10 @@ function drawTitleOnCanvas( break } - // 逐行绘制(offsetX 补偿 video 在容器内的居中偏移) + // 逐行绘制(offsetX/offsetY 补偿 video 在容器内的居中偏移) const x = offsetX + w / 2 lines.forEach((line, i) => { - const y = startY + i * lineHeight + const y = offsetY + startY + i * lineHeight if (settings.stroke) ctx.strokeText(line, x, y) ctx.fillText(line, x, y) }) @@ -208,6 +210,7 @@ export const PreviewVideoPanel: React.FC = ({ 60, 1, videoEl ? videoEl.offsetLeft : 0, + videoEl ? videoEl.offsetTop : 0, ) }, [titleText, titleSettings]) -- 2.54.0