import React, { useState, useEffect, useCallback } from 'react' import { Folder, FileText, ChevronLeft, RefreshCw } from 'lucide-react' import { clsx } from 'clsx' import type { FileItem } from '@/lib/api' import { fetchSystemFiles } 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 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) } }, []) useEffect(() => { loadFiles(currentPath) }, [currentPath, loadFiles]) const handleGoBack = () => { if (pathHistory.length > 1) { const newHistory = [...pathHistory] newHistory.pop() const prevPath = newHistory[newHistory.length - 1] setPathHistory(newHistory) setCurrentPath(prevPath) onSelect(null) } } const handleGoInto = (file: FileItem) => { setPathHistory([...pathHistory, file.path]) setCurrentPath(file.path) onSelect(null) } const handleRefresh = () => { loadFiles(currentPath) } const getDisplayPath = () => { if (!currentPath) return '本地文件' if (currentPath === '' || currentPath === '/') 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.name}
))}
)}
) }