121 lines
3.2 KiB
TypeScript
121 lines
3.2 KiB
TypeScript
|
||
import { useIframeMode } from '@/components/html-editor/hooks/useIframeMode'
|
||
import type { TaskArtifact } from '@/components/nova-sdk'
|
||
import { useDebounceFn } from 'ahooks'
|
||
import { useEffect } from 'react'
|
||
import { savePPT } from '../server'
|
||
import { useEditState } from '@/components/html-editor/hooks/useEditState'
|
||
import { usePPTEditContext } from '@/components/html-editor/context'
|
||
|
||
interface SliderListItem {
|
||
content: string
|
||
file_name: string
|
||
file_type: string
|
||
id: string
|
||
path: string
|
||
title: string
|
||
}
|
||
|
||
export interface SlideJson {
|
||
outline: Array<{
|
||
id: string;
|
||
summary: string;
|
||
title: string;
|
||
}>;
|
||
project_dir: string;
|
||
slide_ids: string[];
|
||
slide_list: SliderListItem[]
|
||
}
|
||
|
||
|
||
export const usePPTEditor = (
|
||
id: string,
|
||
slideRef: React.RefObject<HTMLIFrameElement | null>,
|
||
scale: number,
|
||
slideJson: SlideJson | undefined,
|
||
artifact: TaskArtifact,
|
||
taskId: string | null | undefined,
|
||
editable: boolean
|
||
) => {
|
||
const editorContext = usePPTEditContext()
|
||
const editState = useEditState()
|
||
|
||
const saveHandler = async (type: 'auto' | 'manual' = 'auto', callback?: () => void) => {
|
||
if (editState.isSaving) return
|
||
const slideList = editorContext?.originalSlide.current || []
|
||
if (!slideList || slideList.length === 0) return
|
||
editState.setSaveType(type)
|
||
editState.setIsSaving(true)
|
||
try {
|
||
console.log('保存变更, ppt页数', slideList.length, artifact)
|
||
await savePPT({
|
||
task_id: taskId!,
|
||
slide_content: JSON.stringify({
|
||
...slideJson,
|
||
slide_list: slideList,
|
||
}),
|
||
slide_path: artifact.path,
|
||
})
|
||
} catch (e) {
|
||
console.error(e)
|
||
} finally {
|
||
editState.setIsSaving(false)
|
||
editState.setSaveType(null)
|
||
setTimeout(() => {
|
||
callback?.()
|
||
}, 500);
|
||
}
|
||
}
|
||
const handleSave = useDebounceFn(saveHandler, { wait: 1000 })
|
||
|
||
const manualSave = () => {
|
||
handleSave.cancel()
|
||
saveHandler('manual')
|
||
}
|
||
|
||
const useIframeReturn = useIframeMode(
|
||
id,
|
||
slideRef,
|
||
{
|
||
onContentChange: content => {
|
||
const originalSlide = editorContext?.originalSlide.current || []
|
||
if (originalSlide && originalSlide.length) {
|
||
const slide = originalSlide.find(s => s.id === id)
|
||
if (slide) {
|
||
console.log('内容变更写入', id)
|
||
slide.content = content
|
||
}
|
||
handleSave.run('auto');
|
||
}
|
||
},
|
||
onHistoryChange: (_state, instance) => {
|
||
editState.handleHistoryChangeEvent(instance)
|
||
},
|
||
enabled: editable
|
||
},
|
||
scale,
|
||
)
|
||
const { selectedElement, editor, tipPosition } = useIframeReturn
|
||
|
||
|
||
|
||
useEffect(() => {
|
||
const hasActive = editor?.EditorRegistry.hasActiveEditor()
|
||
const reWriteState = { ...useIframeReturn }
|
||
if (hasActive && selectedElement) {
|
||
// 有激活的实例且为当前的实例
|
||
editorContext?.setState(reWriteState)
|
||
} else if (!selectedElement && !hasActive) {
|
||
// 失焦后清空所有状态,关闭tip
|
||
reWriteState.position = null
|
||
reWriteState.tipPosition = null
|
||
editorContext?.setState(reWriteState)
|
||
}
|
||
}, [selectedElement, editor, tipPosition])
|
||
|
||
return {
|
||
...editState,
|
||
handleSave,
|
||
manualSave,
|
||
}
|
||
} |