From e60ec8b61af4ae84ad1b9077bfaf8431706f55c7 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: Thu, 14 Aug 2025 20:47:12 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=AF=8C=E6=96=87?= =?UTF-8?q?=E6=9C=AC=E7=BC=96=E8=BE=91=20=E5=88=A0=E9=99=A4=E6=8A=A5?= =?UTF-8?q?=E9=94=99=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/service/adapter/textToShot.ts | 20 +++---- components/ui/main-editor/MainEditor.tsx | 69 ++++++++++++++++++++---- 2 files changed, 70 insertions(+), 19 deletions(-) diff --git a/app/service/adapter/textToShot.ts b/app/service/adapter/textToShot.ts index de4da67..3465975 100644 --- a/app/service/adapter/textToShot.ts +++ b/app/service/adapter/textToShot.ts @@ -312,15 +312,17 @@ export class TextToShotAdapter { public static fromRoleToText(paragraphs: Paragraph[]): string { let text = ''; paragraphs.forEach(paragraph => { - paragraph.content.forEach(node => { - if (node.type === 'highlightText') { - text += node.attrs.text; - } else if (node.type === 'text') { - text += node.text; - } else if (node.type === 'characterToken') { - text += node.attrs.name; - } - }); + if (paragraph?.content) { + paragraph.content.forEach(node => { + if (node.type === 'highlightText') { + text += node.attrs.text; + } else if (node.type === 'text') { + text += node.text; + } else if (node.type === 'characterToken') { + text += node.attrs.name; + } + }); + } }); return text; } diff --git a/components/ui/main-editor/MainEditor.tsx b/components/ui/main-editor/MainEditor.tsx index 605d1ac..a518903 100644 --- a/components/ui/main-editor/MainEditor.tsx +++ b/components/ui/main-editor/MainEditor.tsx @@ -13,35 +13,84 @@ export default function MainEditor({ content, onChangeContent }: MainEditorProps const [renderContent, setRenderContent] = useState(content); useEffect(() => { - onChangeContent?.(renderContent);; + onChangeContent?.(renderContent); }, [renderContent]); const editor = useEditor({ extensions: [ - StarterKit, + StarterKit.configure({ + paragraph: { + HTMLAttributes: { + class: 'paragraph' + } + }, + }), HighlightTextExtension, ], - content: { type: 'doc', content: renderContent }, + content: { + type: 'doc', + content: renderContent.length === 0 ? [{ type: 'paragraph', content: [] }] : renderContent + }, editorProps: { attributes: { class: 'prose prose-invert max-w-none focus:outline-none' + }, + handleDOMEvents: { + keydown: (view, event) => { + // 如果内容为空且按下删除键或退格键,阻止默认行为 + if ( + (event.key === 'Backspace' || event.key === 'Delete') && + editor?.isEmpty + ) { + event.preventDefault(); + return true; + } + return false; + } } }, - immediatelyRender: false, onCreate: ({ editor }) => { - editor.setOptions({ editable: true }) + editor.setOptions({ editable: true }); }, onUpdate: ({ editor }) => { - const json = editor.getJSON(); - flushSync(() => { - setRenderContent(json.content); - }); + try { + const json = editor.getJSON(); + // 确保至少有一个空段落 + const safeContent = json.content.length === 0 + ? [{ type: 'paragraph', content: [] }] + : json.content; + + flushSync(() => { + setRenderContent(safeContent); + }); + } catch (error) { + console.error('Editor update error:', error); + } }, + immediatelyRender: false, // 解决 SSR 水合问题 }); + // 监听编辑器内容变化,确保始终有一个段落 + useEffect(() => { + const handleEmpty = () => { + if (editor?.isEmpty) { + editor.commands.setContent([{ + type: 'paragraph', + content: [] + }]); + } + }; + + editor?.on('update', handleEmpty); + return () => { + editor?.off('update', handleEmpty); + }; + }, [editor]); + if (!editor) { - return null + return null; } + return ( ); From 2bd27ef7f650b8a692a35079966bc5239a78b864 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: Thu, 14 Aug 2025 20:57:37 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=85=B6=E4=BB=96tab?= =?UTF-8?q?=E4=B8=8B=E4=BF=AE=E6=94=B9=E5=BA=94=E7=94=A8=E6=B2=A1=E8=A7=A6?= =?UTF-8?q?=E5=8F=91=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/ui/edit-modal.tsx | 9 +++++---- components/ui/script-tab-content.tsx | 8 +++++++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/components/ui/edit-modal.tsx b/components/ui/edit-modal.tsx index 47c573b..613689a 100644 --- a/components/ui/edit-modal.tsx +++ b/components/ui/edit-modal.tsx @@ -117,9 +117,6 @@ const [pendingSwitchTabId, setPendingSwitchTabId] = useState(null // 切换前 检查是否更新 const isUpdate = checkUpdate(tabId); if (isUpdate) { - // setPendingSwitchTabId(tabId); // 记录要切换到的目标tab - // setRemindFallbackText('You must click Apply button to save the current changes.'); - // setIsRemindFallbackOpen(true); return; } setActiveTab(tabId); @@ -129,8 +126,12 @@ const [pendingSwitchTabId, setPendingSwitchTabId] = useState(null const handleSave = () => { console.log('handleSave'); // setIsRemindFallbackOpen(true); - if (activeTab === '1') { + if (activeTab === '0') { + scriptTabContentRef.current.saveBefore(); + } else if (activeTab === '1') { characterTabContentRef.current.saveBefore(); + } else if (activeTab === '3') { + handleConfirmGotoFallback(); } } diff --git a/components/ui/script-tab-content.tsx b/components/ui/script-tab-content.tsx index 6b8b86f..c347006 100644 --- a/components/ui/script-tab-content.tsx +++ b/components/ui/script-tab-content.tsx @@ -15,7 +15,7 @@ interface ScriptTabContentProps { } export const ScriptTabContent = forwardRef< - { switchBefore: (tabId: string) => boolean }, + { switchBefore: (tabId: string) => boolean, saveBefore: () => void }, ScriptTabContentProps >((props, ref) => { const { setIsPauseWorkFlow, isPauseWorkFlow, originalText, onApply, setActiveTab } = props; @@ -39,6 +39,12 @@ export const ScriptTabContent = forwardRef< } return isUpdate; }, + saveBefore: () => { + console.log('saveBefore'); + if (isUpdate) { + onApply(); + } + } })); const handleApply = () => {