169 lines
4.1 KiB
JavaScript
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
|