import React from 'react' import { EditOutlined, DeleteOutlined, CopyOutlined, ScissorOutlined, DownloadOutlined, FileOutlined, FolderOpenOutlined, EyeOutlined, SnippetsOutlined, FileZipOutlined, FolderOutlined, ConsoleSqlOutlined, SoundOutlined } from '@ant-design/icons' import { FileItem } from '@/types/file' interface FileContextMenuProps { children: React.ReactNode file: FileItem selectedFiles: Set clipboard: { items: string[] operation: 'copy' | 'cut' | null } // 菜单全局状态props globalContextMenuInfo: { file: FileItem | null position: { x: number; y: number } } | null onOpen: (file: FileItem) => void onRename: (file: FileItem) => void onDelete: (files: FileItem[]) => void onDownload: (file: FileItem) => void onCopy: (files: FileItem[]) => void onCut: (files: FileItem[]) => void onPaste: () => void onView: (file: FileItem) => void onCompress: (files: FileItem[]) => void onExtract: (file: FileItem) => void onOpenTerminal: (file: FileItem) => void onAddToPlaylist?: (files: FileItem[]) => void // 菜单全局状态props setGlobalContextMenuInfo: React.Dispatch> } export const FileContextMenu: React.FC = ({ children, file, selectedFiles, clipboard, globalContextMenuInfo, onOpen, onRename, onDelete, onDownload, onCopy, onCut, onPaste, onView, onCompress, onExtract, onOpenTerminal, onAddToPlaylist, setGlobalContextMenuInfo }) => { const isSelected = selectedFiles.has(file.path) const selectedCount = selectedFiles.size const isMultipleSelected = selectedCount > 1 const contextMenuVisible = globalContextMenuInfo?.file?.path === file.path; const contextMenuPosition = globalContextMenuInfo?.position || { x: 0, y: 0 }; const getSelectedFiles = (): FileItem[] => { if (isSelected && isMultipleSelected) { // 如果当前文件被选中且有多个选中项,操作所有选中的文件 return Array.from(selectedFiles).map(path => ({ ...file, path })) } else { // 否则只操作当前文件 return [file] } } // 检查是否为音频文件 const isAudioFile = (fileName: string): boolean => { const supportedFormats = ['.mp3', '.wav', '.ogg', '.m4a', '.aac', '.flac'] return supportedFormats.some(format => fileName.toLowerCase().endsWith(format) ) } // 检查选中的文件中是否有音频文件 const hasAudioFiles = (): boolean => { const files = getSelectedFiles() return files.some(f => f.type === 'file' && isAudioFile(f.name)) } const handleContextMenu = (event: React.MouseEvent) => { event.preventDefault(); setGlobalContextMenuInfo({file, position: { x: event.clientX, y: event.clientY }}); //日志 console.log('显示右键菜单:', file.name); }; const handleMenuClick = () => { setGlobalContextMenuInfo(null); }; React.useEffect(() => { if (contextMenuVisible) { const handleClickOutside = () => setGlobalContextMenuInfo(null); document.addEventListener('click', handleClickOutside); return () => document.removeEventListener('click', handleClickOutside); } }, [contextMenuVisible, setGlobalContextMenuInfo]); return ( <>
{children}
{contextMenuVisible && (
{/* 打开/查看 */}
{ console.log('右键菜单 - 打开:', file.name) onOpen(file) }} > {file.type === 'directory' ? : } {file.type === 'directory' ? '打开文件夹' : '打开文件'}
{/* 查看(仅文件) */} {file.type === 'file' && (
onView(file)} > 预览
)} {/* 从此文件夹处打开终端(仅文件夹) */} {file.type === 'directory' && (
onOpenTerminal(file)} > 从此文件夹处打开终端
)} {/* 添加到播放列表(仅音频文件) */} {onAddToPlaylist && hasAudioFiles() && (
onAddToPlaylist(getSelectedFiles())} > {isMultipleSelected ? `添加 ${selectedCount} 项到播放列表` : '添加到播放列表'}
)}
{/* 重命名(仅单个文件) */} {!isMultipleSelected && (
onRename(file)} > 重命名
)} {/* 复制 */}
onCopy(getSelectedFiles())} > {isMultipleSelected ? `复制 ${selectedCount} 项` : '复制'}
{/* 剪切 */}
onCut(getSelectedFiles())} > {isMultipleSelected ? `剪切 ${selectedCount} 项` : '剪切'}
{/* 粘贴 */} {clipboard.operation && clipboard.items.length > 0 && (
粘贴 {clipboard.items.length} 项
)}
{/* 压缩 */}
onCompress(getSelectedFiles())} > {isMultipleSelected ? `压缩 ${selectedCount} 项` : '压缩'}
{/* 解压(仅zip文件) */} {file.type === 'file' && !isMultipleSelected && file.name.toLowerCase().endsWith('.zip') && (
onExtract(file)} > 解压
)}
{/* 下载(仅文件) */} {file.type === 'file' && !isMultipleSelected && (
onDownload(file)} > 下载
)} {/* 删除 */}
onDelete(getSelectedFiles())} > {isMultipleSelected ? `删除 ${selectedCount} 项` : '删除'}
)} ) }