import React, { useState, useEffect } from 'react'; import { Modal, Upload, Button, Progress, message, Form, Select, Radio, Slider } from 'antd'; import { InboxOutlined } from '@ant-design/icons'; import { v4 as uuidv4 } from 'uuid'; import type { UploadFile, UploadPictureParams, AlbumResponse } from '../../api'; import { uploadPicture, getAlbums } from '../../api'; const { Dragger } = Upload; const { Option } = Select; interface UploadDialogProps { visible: boolean; onClose: () => void; onUploadComplete: () => void; } const ImageUploadDialog: React.FC = ({ visible, onClose, onUploadComplete }) => { const [uploadQueue, setUploadQueue] = useState([]); const [uploading, setUploading] = useState(false); const [form] = Form.useForm(); const [albums, setAlbums] = useState([]); const [concurrentUploads, setConcurrentUploads] = useState(3); useEffect(() => { if (visible) { fetchAlbums(); } }, [visible]); const fetchAlbums = async () => { try { const result = await getAlbums(); if (result.success && result.data) { setAlbums(result.data); } } catch (error) { console.error('获取相册列表失败:', error); } }; const handleBeforeUpload = (file: File) => { // 检查是否为图片文件 const isImage = file.type.startsWith('image/'); if (!isImage) { message.error(`${file.name} 不是图片文件`); return false; } // 限制文件大小,例如 10MB const isLt10M = file.size / 1024 / 1024 < 10; if (!isLt10M) { message.error('图片大小不能超过 10MB!'); return false; } // 添加到上传队列 const newFile: UploadFile = { id: uuidv4(), file, status: 'pending', percent: 0 }; setUploadQueue((prev) => [...prev, newFile]); return false; // 阻止自动上传 }; const uploadFiles = async () => { if (uploadQueue.length === 0) { message.warning('请先选择需要上传的图片'); return; } try { setUploading(true); const values = await form.validateFields(); const params: UploadPictureParams = {}; if (values.permission !== undefined) { params.permission = values.permission; } if (values.albumId) { params.albumId = values.albumId; } let successCount = 0; let failCount = 0; // 创建上传队列的副本 const queue = [...uploadQueue].filter(item => item.status !== 'success'); // 上传单个文件的函数 const uploadSingleFile = async (item: UploadFile) => { // 更新状态为上传中 setUploadQueue((prev) => prev.map(file => file.id === item.id ? { ...file, status: 'uploading' } : file) ); try { // 上传文件 const result = await uploadPicture(item.file, { ...params, onProgress: (percent) => { setUploadQueue((prev) => prev.map(file => file.id === item.id ? { ...file, percent } : file) ); } }); if (result.success && result.data) { // 更新为上传成功 setUploadQueue((prev) => prev.map(file => file.id === item.id ? { ...file, status: 'success', response: result.data, percent: 100 } : file) ); successCount++; } else { // 更新为上传失败 setUploadQueue((prev) => prev.map(file => file.id === item.id ? { ...file, status: 'error', error: result.message || '上传失败' } : file) ); failCount++; } } catch (error: any) { // 更新为上传失败 setUploadQueue((prev) => prev.map(file => file.id === item.id ? { ...file, status: 'error', error: error.message || '上传失败' } : file) ); failCount++; } }; // 批量上传函数 - 支持并发控制 const batchUpload = async () => { // 每次处理的批次大小 const batchSize = concurrentUploads; while (queue.length > 0) { // 取出当前批次的文件 const batch = queue.splice(0, batchSize); // 并行上传当前批次的所有文件 await Promise.all(batch.map(item => uploadSingleFile(item))); } }; // 执行批量上传 await batchUpload(); // 显示上传结果 if (successCount > 0) { if (failCount > 0) { message.warning(`上传完成,成功 ${successCount} 张,失败 ${failCount} 张`); } else { message.success(`成功上传 ${successCount} 张图片`); // 如果全部成功,清空队列并关闭对话框 setTimeout(() => { setUploadQueue([]); onClose(); onUploadComplete(); }, 1000); } } else { message.error('上传失败,请重试'); } } catch (error) { console.error('表单验证或上传过程出错:', error); message.error('上传失败,请检查表单信息'); } finally { setUploading(false); } }; const handleRemove = (id: string) => { setUploadQueue((prev) => prev.filter(file => file.id !== id)); }; const handleClose = () => { // 如果正在上传,提示用户 if (uploading) { Modal.confirm({ title: '确认取消', content: '上传正在进行中,确定要取消吗?', onOk: () => { setUploading(false); setUploadQueue([]); onClose(); } }); } else { setUploadQueue([]); onClose(); } }; // 自定义上传列表项 const renderUploadItem = (item: UploadFile) => { let statusIcon; let statusColor; switch(item.status) { case 'success': statusIcon = '✓'; statusColor = '#52c41a'; break; case 'error': statusIcon = '✗'; statusColor = '#ff4d4f'; break; default: statusIcon = ''; statusColor = '#1890ff'; } return (
{item.file instanceof File && ( {item.file.name} )}
{item.file.name}
{item.status === 'uploading' && ( )} {item.status === 'error' && item.error && (
{item.error}
)}
{item.status !== 'uploading' && ( )} {statusIcon && ( {statusIcon} )}
); }; return ( 取消 , , ]} width={600} >
公开 好友可见 仅自己 setConcurrentUploads(value)} marks={{ 1: '1', 5: '5', 10: '10' }} />

点击或拖拽图片到此区域上传

支持单个或批量上传,图片大小不超过10MB

已选择 {uploadQueue.length} 张图片
0 ? '1px solid #f0f0f0' : 'none', borderRadius: '4px', padding: uploadQueue.length > 0 ? '8px' : '0' }}> {uploadQueue.map(renderUploadItem)}
); }; export default ImageUploadDialog;