初始化模版工程
This commit is contained in:
121
components/ppt-editor/hooks/usePPTEditor.ts
Normal file
121
components/ppt-editor/hooks/usePPTEditor.ts
Normal file
@@ -0,0 +1,121 @@
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
32
components/ppt-editor/hooks/useSize.ts
Normal file
32
components/ppt-editor/hooks/useSize.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { useState, useLayoutEffect } from 'react'
|
||||
|
||||
/**
|
||||
* 监听元素尺寸变化的 Hook
|
||||
*/
|
||||
export function useSize(target: React.RefObject<HTMLElement | null>) {
|
||||
const [size, setSize] = useState<{ width: number; height: number } | null>(null)
|
||||
|
||||
useLayoutEffect(() => {
|
||||
const element = target.current
|
||||
if (!element) {
|
||||
console.log('useSize: element is null')
|
||||
return
|
||||
}
|
||||
|
||||
const resizeObserver = new ResizeObserver((entries) => {
|
||||
for (const entry of entries) {
|
||||
const { width, height } = entry.contentRect
|
||||
console.log('useSize: resize', width, height)
|
||||
setSize({ width, height })
|
||||
}
|
||||
})
|
||||
|
||||
resizeObserver.observe(element)
|
||||
|
||||
return () => {
|
||||
resizeObserver.disconnect()
|
||||
}
|
||||
}, [target])
|
||||
|
||||
return size
|
||||
}
|
||||
Reference in New Issue
Block a user