import React, { useEffect, useRef } from 'react' import { useDebounceFn } from 'ahooks' import { cleanDom } from '../lib/core/utils' import { Html } from '../components/html-render/task-html' import { useIframeMode } from '../hooks/useIframeMode' import { useDiff } from '../hooks/useDiff' import { useEditState } from '../hooks/useEditState' import { FloatingToolbar } from '../../ppt-editor/FloatingToolbar' import type { ArtifactEditState } from '../types' import { saveMarkdown } from '../server' import { TaskArtifact } from '@/components/nova-sdk' export const HtmlWithEditMode: React.FC<{ taskId: string taskArtifact: TaskArtifact onStateChange?: (state: ArtifactEditState) => void content: string isDoc?: boolean }> = props => { const { taskId, isDoc ,taskArtifact, content, onStateChange } = props const htmlIframe = useRef(null) const editState = useEditState() const saveHandler = async (type: 'auto' | 'manual' = 'auto', callback?: () => void) => { if (editState.isSaving) return if (!htmlIframe.current) return const iframeDoc = htmlIframe.current.contentDocument?.documentElement if (!iframeDoc) return editState.setSaveType(type) editState.setIsSaving(true) try { const srcDoc = cleanDom(iframeDoc) await saveMarkdown({ task_id: taskId, content: srcDoc, path: taskArtifact.path, }) callback?.() } catch (e) { console.error(e) } finally { editState.setIsSaving(false) editState.setSaveType(null) } } const handleSave = useDebounceFn(saveHandler, { wait: 1000 }) const manualSave = () => { handleSave.cancel() saveHandler('manual') } const useIframeReturn = useIframeMode(taskId, htmlIframe, { enableGlobalContentEditable: isDoc, onContentChange: content => { handleSave.run('auto') }, onHistoryChange: (_state, instance) => { editState.handleHistoryChangeEvent(instance) // 同时向上传递状态,保持兼容性 if (onStateChange && instance) { const canRedo = instance.EditorRegistry.canRedo() const canUndo = instance.EditorRegistry.canUndo() onStateChange({ canRedo, canUndo, redo: () => instance.EditorRegistry.redo(), undo: () => instance.EditorRegistry.undo(), }) } }, }) useEffect(() => { const saveHandler = (callback?: () => void) => { if (!useIframeReturn.loadSuccess) { callback?.() return } if (!htmlIframe.current) return const iframeDoc = htmlIframe.current.contentDocument?.documentElement if (iframeDoc) { const srcDoc = cleanDom(iframeDoc) handleSave.run('auto', callback) } } // eventBus.on('html-edit-save', saveHandler) return () => { // eventBus.off('html-edit-save', saveHandler) } }, [useIframeReturn.loadSuccess]) // doc编辑与web编辑差异逻辑 useDiff(useIframeReturn, isDoc) return (
{/* 悬浮工具栏 */}
editState.undo.current()} onRedo={() => editState.redo.current()} onSave={manualSave} isSaving={editState.isSaving} saveType={editState.saveType} />
) }