This commit is contained in:
海龙 2025-08-10 19:20:18 +08:00
commit 3cac5196d4
4 changed files with 67 additions and 43 deletions

View File

@ -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) {

View File

@ -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<EditorRef, ShotEditorProps>(
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<EditorRef, ShotEditorProps>(
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<EditorRef, ShotEditorProps>(
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<EditorRef, ShotEditorProps>(
},
insertContent: (content: any) => {
editor?.commands.insertContent(content);
},
getContent: () => {
return segments;
}
}), [editor]) // 依赖 editor确保更新

View File

@ -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<any, ShotsEditorProps>(({ 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<any, ShotsEditorProps>(({ roles, shotInfo,
}
const newShot = createEmptyShot();
setShots([...shots, newShot]);
// onShotsChange([...shots, newShot]);
// 自动切换到新创建的分镜
setCurrentShotIndex(shots.length);
};
@ -250,6 +260,7 @@ export const ShotsEditor = forwardRef<any, ShotsEditorProps>(({ roles, shotInfo,
onCharacterClick={() => {}}
roles={roles}
placeholder="Add shot description here..."
onChangeContent={(content) => {handleDescContentChange(content)}}
/>
</div>
@ -281,6 +292,7 @@ export const ShotsEditor = forwardRef<any, ShotsEditorProps>(({ roles, shotInfo,
onCharacterClick={() => {}}
roles={roles}
placeholder="Add shot dialogue here..."
onChangeContent={(content) => {handleDialogContentChange(content)}}
/>
</div>
</div>

View File

@ -113,7 +113,7 @@ export function ShotTabContent({
...shotData[selectedIndex],
lens: shotInfo
});
// regenerateVideoSegment();
regenerateVideoSegment();
};
// 新增分镜