diff --git a/src/views/ValueForum/components/CreatePostModal.js b/src/views/ValueForum/components/CreatePostModal.js index 81d1953e..34c78447 100644 --- a/src/views/ValueForum/components/CreatePostModal.js +++ b/src/views/ValueForum/components/CreatePostModal.js @@ -70,22 +70,117 @@ const CreatePostModal = ({ isOpen, onClose, onPostCreated }) => { return Object.keys(newErrors).length === 0; }; - // 处理图片上传 - const handleImageUpload = (e) => { - const files = Array.from(e.target.files); + // 压缩图片 + const compressImage = (file) => { + return new Promise((resolve, reject) => { + // 检查文件大小(5MB 限制) + if (file.size > 5 * 1024 * 1024) { + toast({ + title: '图片过大', + description: '单张图片不能超过 5MB', + status: 'warning', + duration: 3000, + }); + reject(new Error('图片过大')); + return; + } - files.forEach((file) => { const reader = new FileReader(); - reader.onloadend = () => { - setFormData((prev) => ({ - ...prev, - images: [...prev.images, reader.result], - })); + reader.onload = (e) => { + const img = new Image(); + img.onload = () => { + // 创建 canvas 进行压缩 + const canvas = document.createElement('canvas'); + let width = img.width; + let height = img.height; + + // 如果图片尺寸过大,等比缩放到最大 1920px + const maxDimension = 1920; + if (width > maxDimension || height > maxDimension) { + if (width > height) { + height = (height * maxDimension) / width; + width = maxDimension; + } else { + width = (width * maxDimension) / height; + height = maxDimension; + } + } + + canvas.width = width; + canvas.height = height; + + const ctx = canvas.getContext('2d'); + ctx.drawImage(img, 0, 0, width, height); + + // 转换为 JPEG 格式,质量 0.8(压缩) + canvas.toBlob( + (blob) => { + const compressedReader = new FileReader(); + compressedReader.onloadend = () => { + console.log( + `图片压缩: ${(file.size / 1024).toFixed(2)}KB -> ${(blob.size / 1024).toFixed(2)}KB` + ); + resolve(compressedReader.result); + }; + compressedReader.readAsDataURL(blob); + }, + 'image/jpeg', + 0.8 + ); + }; + img.onerror = () => { + reject(new Error('图片加载失败')); + }; + img.src = e.target.result; + }; + reader.onerror = () => { + reject(new Error('文件读取失败')); }; reader.readAsDataURL(file); }); }; + // 处理图片上传 + const handleImageUpload = async (e) => { + const files = Array.from(e.target.files); + + if (files.length === 0) return; + + // 检查总数量限制 + if (formData.images.length + files.length > 9) { + toast({ + title: '图片数量超限', + description: '最多只能上传 9 张图片', + status: 'warning', + duration: 3000, + }); + return; + } + + try { + // 压缩所有图片 + const compressedImages = await Promise.all( + files.map((file) => compressImage(file)) + ); + + // 添加到表单数据 + setFormData((prev) => ({ + ...prev, + images: [...prev.images, ...compressedImages], + })); + + toast({ + title: '上传成功', + description: `成功添加 ${files.length} 张图片`, + status: 'success', + duration: 2000, + }); + } catch (error) { + console.error('图片上传失败:', error); + // 已经在 compressImage 中显示了具体错误 + } + }; + // 移除图片 const removeImage = (index) => { setFormData((prev) => ({