import React, { useState, useEffect, useCallback } from 'react' import { Folder, FileText, ChevronLeft, RefreshCw, HardDrive } from 'lucide-react' import { clsx } from 'clsx' import type { FileItem } from '@/lib/api' import { fetchSystemFiles, fetchSystemDrives } from '../../api' interface LocalFilePanelProps { selectedFile: FileItem | null onSelect: (file: FileItem | null) => void onUpload: () => void disabled?: boolean } export const LocalFilePanel: React.FC = ({ selectedFile, onSelect, onUpload, disabled, }) => { const [currentPath, setCurrentPath] = useState('') const [files, setFiles] = useState([]) const [loading, setLoading] = useState(false) const [pathHistory, setPathHistory] = useState(['']) const [isAtDrives, setIsAtDrives] = useState(true) const loadFiles = useCallback(async (systemPath: string) => { setLoading(true) try { const items = await fetchSystemFiles(systemPath) setFiles(items) } catch (err) { console.error('Failed to load local files:', err) } finally { setLoading(false) } }, []) const loadDrives = useCallback(async () => { setLoading(true) try { const items = await fetchSystemDrives() setFiles(items) } catch (err) { console.error('Failed to load drives:', err) } finally { setLoading(false) } }, []) useEffect(() => { if (isAtDrives) { loadDrives() } else { loadFiles(currentPath) } }, [currentPath, isAtDrives, loadFiles, loadDrives]) const handleGoBack = () => { if (pathHistory.length > 1) { const newHistory = [...pathHistory] newHistory.pop() const prevPath = newHistory[newHistory.length - 1] setPathHistory(newHistory) setCurrentPath(prevPath) if (prevPath === '') { setIsAtDrives(true) } onSelect(null) } } const handleGoInto = (file: FileItem) => { setIsAtDrives(false) setPathHistory([...pathHistory, file.path]) setCurrentPath(file.path) onSelect(null) } const handleRefresh = () => { if (isAtDrives) { loadDrives() } else { loadFiles(currentPath) } } const getDisplayPath = () => { if (isAtDrives) return '本地磁盘' const parts = currentPath.split(/[/\\]/) return parts[parts.length - 1] || currentPath } return (
{getDisplayPath()}
{ if ((e.target as HTMLElement).classList.contains('space-y-1') || (e.target as HTMLElement).classList.contains('p-2')) { onSelect(null) } }}> {loading ? (
加载中...
) : files.length === 0 ? (
空文件夹
) : (
{files.map((file) => (
onSelect(selectedFile?.path === file.path ? null : file)} onDoubleClick={() => file.type === 'dir' && handleGoInto(file)} className={clsx( 'flex items-center gap-2 px-2 py-1.5 rounded-md cursor-pointer transition-colors text-sm', selectedFile?.path === file.path ? 'bg-gray-100 text-gray-800 dark:bg-gray-700/60 dark:text-gray-200' : 'hover:bg-gray-100 dark:hover:bg-gray-700/50 text-gray-700 dark:text-gray-200' )} > {file.type === 'dir' || file.path.match(/^[A-Z]:\\?$/i) ? ( file.path.match(/^[A-Z]:\\?$/i) ? ( ) : ( ) ) : ( )} {file.name}
))}
)}
) }