import { ElMessage } from 'element-plus'; import { useImageCompression, type CompressionLevel } from './useImageCompression'; import type { FileItem } from '@/stores/modules/files'; export interface UseFilePasteOptions { /** 最大文件大小 (字节) */ maxFileSize?: number; /** 最大总内容长度 */ maxTotalContentLength?: number; /** 压缩级别配置 */ compressionLevels?: CompressionLevel[]; /** 获取当前文件列表总长度 */ getCurrentTotalLength: () => number; /** 添加文件到列表 */ addFiles: (files: FileItem[]) => void; /** 是否只接受图片 (默认true) */ imagesOnly?: boolean; } /** * 从剪贴板数据项中提取文件 */ function extractFilesFromItems(items: DataTransferItemList): File[] { const files: File[] = []; for (let i = 0; i < items.length; i++) { const item = items[i]; if (item.kind === 'file') { const file = item.getAsFile(); if (file) { files.push(file); } } } return files; } /** * Composable: 处理粘贴事件中的文件 */ export function useFilePaste(options: UseFilePasteOptions) { const { maxFileSize = 3 * 1024 * 1024, maxTotalContentLength = 150000, compressionLevels, getCurrentTotalLength, addFiles, imagesOnly = true, } = options; const { tryCompressToLimit } = useImageCompression(); /** * 处理单个粘贴的文件 */ async function processPastedFile( file: File, currentTotalLength: number, ): Promise { // 验证文件大小 if (file.size > maxFileSize) { ElMessage.error(`文件 ${file.name} 超过 3MB 限制,已跳过`); return null; } const isImage = file.type.startsWith('image/'); if (isImage) { try { const result = await tryCompressToLimit( file, currentTotalLength, maxTotalContentLength, compressionLevels, ); if (!result) { ElMessage.error(`${file.name} 图片内容过大,请压缩后上传`); return null; } return { uid: crypto.randomUUID(), name: file.name, fileSize: file.size, file, maxWidth: '200px', showDelIcon: true, imgPreview: true, imgVariant: 'square', url: result.base64, isUploaded: true, base64: result.base64, fileType: 'image', }; } catch (error) { console.error('处理图片失败:', error); ElMessage.error(`${file.name} 处理失败`); return null; } } else if (!imagesOnly) { // 如果不是仅图片模式,可以在这里处理其他类型文件 ElMessage.warning(`${file.name} 不支持粘贴,请使用上传按钮`); return null; } return null; } /** * 处理粘贴事件 */ async function handlePaste(event: ClipboardEvent) { const items = event.clipboardData?.items; if (!items) return; const files = extractFilesFromItems(items); if (files.length === 0) return; event.preventDefault(); let totalContentLength = getCurrentTotalLength(); const newFiles: FileItem[] = []; for (const file of files) { const processedFile = await processPastedFile(file, totalContentLength); if (processedFile) { newFiles.push(processedFile); totalContentLength += Math.floor((processedFile.base64?.length || 0) * 0.5); } } if (newFiles.length > 0) { addFiles(newFiles); ElMessage.success(`已添加 ${newFiles.length} 个文件`); } } return { handlePaste, processPastedFile, }; }