diff --git a/app/service/adapter/textToShot.ts b/app/service/adapter/textToShot.ts index 828f012..3c6d5ca 100644 --- a/app/service/adapter/textToShot.ts +++ b/app/service/adapter/textToShot.ts @@ -190,18 +190,25 @@ export class TextToShotAdapter { shotData.shotDialogsContent.forEach(paragraph => { let dialogRoleName = ''; let dialogContent = ''; + let firstFindRole = false; // 遍历段落内容 - paragraph.content.forEach((node, index) => { - if (node.type === 'characterToken') { - // 记录说话角色的名称 - index === 0 && (dialogRoleName = node.attrs.name); - index !== 0 && (dialogContent += node.attrs.name); - } else if (node.type === 'text') { - // 累积对话内容 - dialogContent += node.text; - } - }); + if (paragraph.content) { + paragraph.content.forEach((node, index) => { + if (node.type === 'characterToken') { + // 记录说话角色的名称 + if (!firstFindRole) { + dialogRoleName = node.attrs.name; + firstFindRole = true; + } else { + dialogContent += node.attrs.name; + } + } else if (node.type === 'text') { + // 累积对话内容 + dialogContent += node.text; + } + }); + } // 如果有角色名和对话内容,添加到结果中 if (dialogRoleName && dialogContent) { diff --git a/components/ui/shot-editor/ShotEditor.tsx b/components/ui/shot-editor/ShotEditor.tsx index 0d7592e..883f6da 100644 --- a/components/ui/shot-editor/ShotEditor.tsx +++ b/components/ui/shot-editor/ShotEditor.tsx @@ -1,4 +1,5 @@ import React, { useState, useCallback, useEffect } from 'react'; +import { flushSync } from 'react-dom'; import { EditorContent, useEditor } from '@tiptap/react'; import StarterKit from '@tiptap/starter-kit'; import Placeholder from '@tiptap/extension-placeholder' @@ -12,6 +13,7 @@ interface ShotEditorProps { roles?: any[]; onCharacterClick?: (attrs: any) => void; placeholder?: string; + onChangeContent?: (content: any) => void; } declare module '@tiptap/core' { @@ -36,14 +38,17 @@ interface EditorRef { editor: any; insertCharacter: (character: CharacterToken) => void; insertContent: (content: any) => void; - getContent: () => any; } const ShotEditor = React.forwardRef( - function ShotEditor({ content, onCharacterClick, roles, placeholder }, ref) { + function ShotEditor({ content, onCharacterClick, roles, placeholder, onChangeContent }, ref) { const [segments, setSegments] = useState(content); const [isOptimizing, setIsOptimizing] = useState(false); + useEffect(() => { + onChangeContent?.(segments); + }, [segments]); + const handleSmartPolish = () => { setIsOptimizing(true); setTimeout(() => { @@ -60,9 +65,11 @@ const ShotEditor = React.forwardRef( ShotTitle, ReadonlyText, Placeholder.configure({ - placeholder: placeholder || 'Add shot description here...', - showOnlyWhenEditable: true, - showOnlyCurrent: false, + placeholder: ({ node }) => { + console.log('-==========placeholder node===========-', segments); + + return placeholder || 'Add shot description here...'; + }, }), ], content: { type: 'doc', content: segments }, @@ -76,9 +83,10 @@ const ShotEditor = React.forwardRef( editor.setOptions({ editable: true }) }, onUpdate: ({ editor }) => { - const json = editor.getJSON() - console.log('-==========json===========-', json); - setSegments(json.content); + const json = editor.getJSON(); + flushSync(() => { + setSegments(json.content); + }); }, }) @@ -94,9 +102,6 @@ const ShotEditor = React.forwardRef( }, insertContent: (content: any) => { editor?.commands.insertContent(content); - }, - getContent: () => { - return segments; } }), [editor]) // 依赖 editor,确保更新 diff --git a/components/ui/shot-editor/ShotsEditor.tsx b/components/ui/shot-editor/ShotsEditor.tsx index b3ecc93..dfdc50d 100644 --- a/components/ui/shot-editor/ShotsEditor.tsx +++ b/components/ui/shot-editor/ShotsEditor.tsx @@ -23,8 +23,20 @@ interface CharacterToken { const createEmptyShot = (): Shot => ({ name: `shot${Date.now()}`, - shotDescContent: [], - shotDialogsContent: [] + shotDescContent: [{ + type: 'paragraph', + content: [{ + type: 'text', + text: 'Add shot description here...' + }] + }], + shotDialogsContent: [{ + type: 'paragraph', + content: [{ + type: 'text', + text: 'Add shot dialogue here...' + }] + }] }); interface ShotsEditorProps { @@ -50,32 +62,31 @@ export const ShotsEditor = forwardRef(({ roles, shotInfo, } }, [shotInfo]); - // 更新当前分镜内容 - const updateShot = () => { + const handleDescContentChange = (content: any) => { const shot = shots[currentShotIndex]; - if (descEditorRef.current) { - const content = descEditorRef.current.getContent(); - console.log('-==========descEditorcontent===========-', content); - shot.shotDescContent = content; - } - if (dialogEditorRef.current) { - const content = dialogEditorRef.current.getContent(); - console.log('-==========dialogEditorcontent===========-', content); - shot.shotDialogsContent = content; - } - setShots([...shots]); + shot.shotDescContent = content; + setShots(prevShots => + prevShots.map((item, index) => + index === currentShotIndex ? shot : item + ) + ); + } + const handleDialogContentChange = (content: any) => { + const shot = shots[currentShotIndex]; + shot.shotDialogsContent = content; + setShots(prevShots => + prevShots.map((item, index) => + index === currentShotIndex ? shot : item + ) + ); } const handleShotTabClick = (index: number) => { - // 切换前更新当前分镜内容 - updateShot(); setCurrentShotIndex(index); } const getShotInfo = () => { - // 生成前 更新当前分镜内容 - updateShot(); - console.log('-==========shots===========-', shots); + console.log('-==========getShotInfo shots===========-', shots); const shotInfo = shots.map((shot) => { return TextToShotAdapter.toLensType(shot); }); @@ -93,7 +104,6 @@ export const ShotsEditor = forwardRef(({ roles, shotInfo, } const newShot = createEmptyShot(); setShots([...shots, newShot]); - // onShotsChange([...shots, newShot]); // 自动切换到新创建的分镜 setCurrentShotIndex(shots.length); }; @@ -250,6 +260,7 @@ export const ShotsEditor = forwardRef(({ roles, shotInfo, onCharacterClick={() => {}} roles={roles} placeholder="Add shot description here..." + onChangeContent={(content) => {handleDescContentChange(content)}} /> @@ -281,6 +292,7 @@ export const ShotsEditor = forwardRef(({ roles, shotInfo, onCharacterClick={() => {}} roles={roles} placeholder="Add shot dialogue here..." + onChangeContent={(content) => {handleDialogContentChange(content)}} /> diff --git a/components/ui/shot-tab-content.tsx b/components/ui/shot-tab-content.tsx index f62c29e..1bfc3b5 100644 --- a/components/ui/shot-tab-content.tsx +++ b/components/ui/shot-tab-content.tsx @@ -113,7 +113,7 @@ export function ShotTabContent({ ...shotData[selectedIndex], lens: shotInfo }); - // regenerateVideoSegment(); + regenerateVideoSegment(); }; // 新增分镜