nex_docus/frontend/src/pages/Document/useDocumentEditorWorkspace.js

169 lines
4.1 KiB
JavaScript

import { useEffect, useState } from 'react'
import { getFileContent, getProjectTree } from '@/api/file'
import Toast from '@/components/Toast/Toast'
import { collectParentKeys, findNodeByKey } from './documentBrowserUtils'
function useDocumentEditorWorkspace({ projectId, searchParams, setSearchParams }) {
const [treeData, setTreeData] = useState([])
const [selectedFile, setSelectedFile] = useState(null)
const [selectedNode, setSelectedNode] = useState(null)
const [fileContent, setFileContent] = useState('')
const [loading, setLoading] = useState(false)
const [openKeys, setOpenKeys] = useState([])
const [selectedMenuKey, setSelectedMenuKey] = useState(null)
const [isPdfSelected, setIsPdfSelected] = useState(false)
const [refreshing, setRefreshing] = useState(false)
const [projectName, setProjectName] = useState('')
const [userRole, setUserRole] = useState('viewer')
const updateFileParam = (filePath) => {
const nextParams = new URLSearchParams(searchParams)
if (filePath) {
nextParams.set('file', filePath)
} else {
nextParams.delete('file')
}
setSearchParams(nextParams, { replace: true })
}
const fetchTree = async () => {
try {
const res = await getProjectTree(projectId)
const data = res.data || {}
setTreeData(data.tree || data || [])
setProjectName(data.project_name || '')
setUserRole(data.user_role || 'viewer')
} catch (error) {
Toast.error('加载失败', '加载文件树失败')
}
}
const clearSelection = () => {
setSelectedFile(null)
setSelectedNode(null)
setSelectedMenuKey(null)
setFileContent('')
setIsPdfSelected(false)
updateFileParam(null)
}
const loadEditableFile = async (filePath) => {
setLoading(true)
try {
const res = await getFileContent(projectId, filePath)
setSelectedFile(filePath)
setFileContent(res.data.content)
} catch (error) {
Toast.error('加载失败', '加载文件失败')
} finally {
setLoading(false)
}
}
const openNodeByKey = async (key, node = null, syncUrl = false) => {
const targetNode = node || findNodeByKey(treeData, key)
if (!targetNode) {
return
}
setSelectedNode(targetNode)
setSelectedMenuKey(key)
if (!targetNode.isLeaf) {
if (syncUrl) {
updateFileParam(null)
}
return
}
if (syncUrl) {
updateFileParam(key)
}
setOpenKeys((prev) => Array.from(new Set([...prev, ...collectParentKeys(key)])))
if (key.toLowerCase().endsWith('.pdf')) {
setSelectedFile(key)
setIsPdfSelected(true)
setFileContent('')
return
}
setIsPdfSelected(false)
await loadEditableFile(key)
}
const handleMenuClick = async ({ key }) => {
const node = findNodeByKey(treeData, key)
if (!node) {
return
}
await openNodeByKey(key, node, true)
}
const refreshCurrentDocument = async () => {
setRefreshing(true)
try {
await fetchTree()
if (selectedFile && !isPdfSelected) {
await loadEditableFile(selectedFile)
}
} catch (error) {
console.error('Refresh document editor error:', error)
Toast.error('刷新失败', '请稍后重试')
} finally {
setRefreshing(false)
}
}
useEffect(() => {
fetchTree()
}, [projectId])
useEffect(() => {
if (treeData.length === 0) {
return
}
const fileParam = searchParams.get('file')
if (!fileParam || fileParam === selectedFile) {
return
}
const targetNode = findNodeByKey(treeData, fileParam)
if (!targetNode) {
return
}
openNodeByKey(fileParam, targetNode, false)
}, [treeData, searchParams])
return {
treeData,
selectedFile,
selectedNode,
fileContent,
loading,
openKeys,
selectedMenuKey,
isPdfSelected,
refreshing,
projectName,
userRole,
setOpenKeys,
setSelectedNode,
setSelectedFile,
setSelectedMenuKey,
setFileContent,
fetchTree,
clearSelection,
loadEditableFile,
openNodeByKey,
handleMenuClick,
refreshCurrentDocument,
}
}
export default useDocumentEditorWorkspace