From 3a713f988f2a1b9f322258e14c192470d879eee5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8C=97=E6=9E=B3?= <7854742+wang_rumeng@user.noreply.gitee.com> Date: Mon, 18 Aug 2025 14:17:07 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20=E5=88=86=E9=95=9C?= =?UTF-8?q?=E6=8F=8F=E8=BF=B0=EF=BC=8C=E9=87=8D=E6=96=B0=E7=94=9F=E6=88=90?= =?UTF-8?q?=E8=A7=86=E9=A2=91=EF=BC=8C=E7=BB=99=E6=8E=A5=E5=8F=A3=E4=BC=A0?= =?UTF-8?q?=E9=80=92=E6=8F=8F=E8=BF=B0=E6=96=87=E5=AD=97=20=E8=BF=98?= =?UTF-8?q?=E6=98=AF=20=E6=97=A7=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/service/adapter/textToShot.ts | 18 ++++++++++-------- components/ui/shot-editor/ShotsEditor.tsx | 9 +++++---- components/ui/shot-tab-content.tsx | 15 +++++++++++---- hooks/useDeepCompareEffect.ts | 20 ++++++++++++++++++++ 4 files changed, 46 insertions(+), 16 deletions(-) create mode 100644 hooks/useDeepCompareEffect.ts diff --git a/app/service/adapter/textToShot.ts b/app/service/adapter/textToShot.ts index 81a2c71..b9c8111 100644 --- a/app/service/adapter/textToShot.ts +++ b/app/service/adapter/textToShot.ts @@ -257,14 +257,16 @@ export class TextToShotAdapter { if (shotData.shotDescContent.length > 0) { // 合并所有描述段落的文本内容 shotData.shotDescContent.forEach(paragraph => { - paragraph.content.forEach(node => { - if (node.type === 'text') { - currentScript += node.text; - } - if (node.type === 'characterToken') { - currentScript += node.attrs.name; - } - }); + if (paragraph.content) { + paragraph.content.forEach(node => { + if (node.type === 'text') { + currentScript += node.text; + } + if (node.type === 'characterToken') { + currentScript += node.attrs.name; + } + }); + } }); } diff --git a/components/ui/shot-editor/ShotsEditor.tsx b/components/ui/shot-editor/ShotsEditor.tsx index 0dacc6a..9a562d9 100644 --- a/components/ui/shot-editor/ShotsEditor.tsx +++ b/components/ui/shot-editor/ShotsEditor.tsx @@ -1,4 +1,5 @@ -import React, { forwardRef, useEffect, useRef, useState } from "react"; +import React, { forwardRef, useRef, useState } from "react"; +import { useDeepCompareEffect } from "@/hooks/useDeepCompareEffect"; import { Plus, X, UserRoundPlus, MessageCirclePlus, MessageCircleMore, ClipboardType } from "lucide-react"; import ShotEditor from "./ShotEditor"; import { toast } from "sonner"; @@ -51,16 +52,16 @@ export const ShotsEditor = forwardRef(function ShotsEdito const descEditorRef = useRef(null); const dialogEditorRef = useRef(null); - useEffect(() => { - console.log('-==========shotInfo===========-', shotInfo); + useDeepCompareEffect(() => { if (shotInfo) { + console.log('-==========shotInfo===========-', shotInfo); const shots = shotInfo.map((shot) => { return TextToShotAdapter.fromLensType(shot, roles); }); console.log('-==========shots===========-', shots); setShots(shots as Shot[]); } - }, [shotInfo]); + }, [shotInfo, roles]); const handleDescContentChange = (content: any) => { const shot = shots[currentShotIndex]; diff --git a/components/ui/shot-tab-content.tsx b/components/ui/shot-tab-content.tsx index bf381ca..e22aec4 100644 --- a/components/ui/shot-tab-content.tsx +++ b/components/ui/shot-tab-content.tsx @@ -47,11 +47,19 @@ export const ShotTabContent = (props: ShotTabContentProps) => { const [isLoadingShots, setIsLoadingShots] = useState(false); const shotsEditorRef = useRef(null); const [isRegenerate, setIsRegenerate] = useState(false); + const [pendingRegeneration, setPendingRegeneration] = useState(false); useEffect(() => { console.log('shotTabContent-----roles', roles); }, [roles]); + useEffect(() => { + if (pendingRegeneration) { + regenerateVideoSegment(); + setPendingRegeneration(false); + } + }, [shotData[selectedIndex]?.lens]); + // 监听当前选中index变化 useEffect(() => { console.log('shotTabContent-----shotData', shotData); @@ -165,13 +173,12 @@ export const ShotTabContent = (props: ShotTabContentProps) => { console.log('regenerate'); setIsRegenerate(true); const shotInfo = shotsEditorRef.current.getShotInfo(); - console.log('shotTabContent-----shotInfo', shotInfo); + console.log('shotInfo', shotInfo); setSelectedSegment({ ...shotData[selectedIndex], lens: shotInfo }); - await regenerateVideoSegment(); - setIsRegenerate(false); + setPendingRegeneration(true); }; // 新增分镜 @@ -408,7 +415,7 @@ export const ShotTabContent = (props: ShotTabContentProps) => { handleRegenerate()} className="flex items-center justify-center gap-2 px-4 py-3 bg-blue-500/10 hover:bg-blue-500/20 - text-blue-500 rounded-lg transition-colors" + text-blue-500 rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed" whileHover={{ scale: 1.02 }} whileTap={{ scale: 0.98 }} disabled={isRegenerate} diff --git a/hooks/useDeepCompareEffect.ts b/hooks/useDeepCompareEffect.ts new file mode 100644 index 0000000..2851cda --- /dev/null +++ b/hooks/useDeepCompareEffect.ts @@ -0,0 +1,20 @@ +import { useEffect, useRef } from 'react'; +import isEqual from 'lodash/isEqual'; + +function useDeepCompareMemoize(value: T) { + const ref = useRef(); + + if (!isEqual(value, ref.current)) { + ref.current = value; + } + + return ref.current; +} + +export function useDeepCompareEffect( + callback: () => void | (() => void), + dependencies: any[] +) { + // eslint-disable-next-line react-hooks/exhaustive-deps + useEffect(callback, dependencies.map(useDeepCompareMemoize)); +} \ No newline at end of file