import React, { useEffect, useState, useRef } from 'react' import { Trash2, FileText, Folder, Loader2 } from 'lucide-react' import { useWallpaper } from '@/stores' import { fetchRecycleBin, restoreItem, permanentlyDeleteItem, emptyRecycleBin } from './api' import type { RecycleBinGroupDTO, RecycleBinItemDTO } from '@shared/types' import { ContextMenu } from '@/components/common/ContextMenu' import { DeleteConfirmDialog } from '@/components/dialogs/DeleteConfirmDialog' type NotebookEvent = { event: string path?: string } const formatDate = (dateStr: string): string => { if (dateStr.length !== 8) return dateStr const year = dateStr.substring(0, 4) const month = dateStr.substring(4, 6) const day = dateStr.substring(6, 8) return `${year}年${month}月${day}日` } export const RecycleBinPage: React.FC = () => { const { opacity } = useWallpaper() const [groups, setGroups] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const [contextMenu, setContextMenu] = useState<{ isOpen: boolean position: { x: number; y: number } item: RecycleBinItemDTO | null }>({ isOpen: false, position: { x: 0, y: 0 }, item: null }) const [deleteDialog, setDeleteDialog] = useState<{ isOpen: boolean item: RecycleBinItemDTO | null }>({ isOpen: false, item: null }) const [emptyDialog, setEmptyDialog] = useState(false) const loadRecycleBinRef = useRef<(showLoading?: boolean) => Promise>() const loadRecycleBin = async (showLoading = true) => { if (showLoading) { setLoading(true) } setError(null) try { const data = await fetchRecycleBin() setGroups(data.groups) } catch (err) { console.error('Failed to load recycle bin:', err) setError('加载回收站失败') } finally { if (showLoading) { setLoading(false) } } } loadRecycleBinRef.current = loadRecycleBin useEffect(() => { loadRecycleBin() }, []) useEffect(() => { const eventSource = new EventSource('/api/events') eventSource.onmessage = (event) => { const data = JSON.parse(event.data) as NotebookEvent if ( data.event === 'change' || data.event === 'add' || data.event === 'unlink' || data.event === 'addDir' || data.event === 'unlinkDir' ) { if (data.path && data.path.startsWith('RB/')) { loadRecycleBinRef.current?.(false) } } } eventSource.onerror = () => { eventSource.close() } return () => { eventSource.close() } }, []) const handleContextMenu = (e: React.MouseEvent, item: RecycleBinItemDTO) => { e.preventDefault() e.stopPropagation() setContextMenu({ isOpen: true, position: { x: e.clientX, y: e.clientY }, item }) } const handleCloseContextMenu = () => { setContextMenu(prev => ({ ...prev, isOpen: false })) } const handleRestore = async () => { if (!contextMenu.item) return try { await restoreItem(contextMenu.item.path, contextMenu.item.type) handleCloseContextMenu() loadRecycleBin(false) } catch (err) { console.error('Failed to restore:', err) alert('恢复失败') } } const handlePermanentDeleteClick = () => { if (!contextMenu.item) return handleCloseContextMenu() setDeleteDialog({ isOpen: true, item: contextMenu.item }) } const handlePermanentDeleteConfirm = async () => { if (!deleteDialog.item) return try { await permanentlyDeleteItem(deleteDialog.item.path, deleteDialog.item.type) setDeleteDialog({ isOpen: false, item: null }) loadRecycleBin(false) } catch (err) { console.error('Failed to delete:', err) alert('删除失败') } } const handleDeleteDialogCancel = () => { setDeleteDialog({ isOpen: false, item: null }) } const handleEmptyClick = () => { setEmptyDialog(true) } const handleEmptyConfirm = async () => { try { await emptyRecycleBin() setEmptyDialog(false) loadRecycleBin(false) } catch (err) { console.error('Failed to empty recycle bin:', err) alert('清空回收站失败') } } const handleEmptyDialogCancel = () => { setEmptyDialog(false) } const contextMenuItems = [ { label: '恢复', onClick: handleRestore }, { label: '彻底删除', onClick: handlePermanentDeleteClick } ] const deleteItem = deleteDialog.item const deleteExpectedText = deleteItem?.type === 'dir' ? 'DESTROY FOLDER' : 'DESTROY FILE' const deleteTitle = deleteItem?.type === 'dir' ? '彻底删除文件夹' : '彻底删除文件' const deleteMessage = deleteItem?.type === 'dir' ? `确定要彻底删除文件夹 "${deleteItem?.originalName}" 吗?此操作不可撤销,文件夹中的所有内容都将被永久删除。` : `确定要彻底删除文件 "${deleteItem?.originalName}" 吗?此操作不可撤销,文件将被永久删除。` return (

回收站

{groups.length > 0 && ( )}
{loading && (
)} {error && (
{error}
)} {!loading && !error && groups.length === 0 && (

回收站是空的

)} {!loading && !error && groups.length > 0 && (
{groups.map((group) => (
{formatDate(group.date)}
{group.items.map((item) => (
handleContextMenu(e, item)} > {item.type === 'dir' ? ( ) : ( )} {item.originalName}
))}
))}
)}
) }