优化Upload

master
LiuJiaNan 2026-02-24 11:42:08 +08:00
parent d6ada39fd0
commit ea129b523c
1 changed files with 84 additions and 48 deletions

View File

@ -1,6 +1,6 @@
import { PlusOutlined, UploadOutlined, VideoCameraAddOutlined } from "@ant-design/icons"; import { PlusOutlined, UploadOutlined, VideoCameraAddOutlined } from "@ant-design/icons";
import { Upload as AntUpload, Button, message, Modal } from "antd"; import { Upload as AntUpload, Button, message, Modal } from "antd";
import { useState } from "react"; import { useRef, useState } from "react";
/** /**
* 文件上传组件 * 文件上传组件
@ -29,6 +29,9 @@ const Upload = (props) => {
const [previewVisible, setPreviewVisible] = useState(false); const [previewVisible, setPreviewVisible] = useState(false);
const [previewImage, setPreviewImage] = useState(""); const [previewImage, setPreviewImage] = useState("");
// 记录已经提示过错误的文件uid避免重复提示
const warnedFileUids = useRef(new Set());
// 预设的文件格式 // 预设的文件格式
const imageAccept = ".jpg,.jpeg,.png"; const imageAccept = ".jpg,.jpeg,.png";
const documentAccept = ".pdf,.doc,.docx"; const documentAccept = ".pdf,.doc,.docx";
@ -137,66 +140,99 @@ const Upload = (props) => {
}; };
// 文件状态改变 // 文件状态改变
const handleChange = ({ file, fileList }) => { const handleChange = ({ fileList }) => {
console.log(fileList);
const acceptList = accept ? accept.split(",") : []; const acceptList = accept ? accept.split(",") : [];
const ratioArr = ratio ? ratio.split("*") : []; const ratioArr = ratio ? ratio.split("*") : [];
const suffix = file.name.substring(
file.name.lastIndexOf("."),
file.name.length,
);
const maxSize = size * 1024 * 1024; const maxSize = size * 1024 * 1024;
// 对整个fileList进行验证和过滤
const validateFiles = async (files) => {
const validFiles = [];
const invalidFiles = [];
for (const fileItem of files) {
const suffix = fileItem.name?.substring(
fileItem.name.lastIndexOf("."),
fileItem.name.length,
) || "";
// 验证文件格式 // 验证文件格式
if (acceptList.length > 0 && !acceptList.includes(suffix)) { if (acceptList.length > 0 && !acceptList.includes(suffix)) {
message.warning(`只能上传${acceptTip}格式的文件`); invalidFiles.push(fileItem);
const filtered = fileList.filter(item => item.uid !== file.uid); // 只提示未提示过的文件
onChange?.(filtered); if (!warnedFileUids.current.has(fileItem.uid)) {
return; warnedFileUids.current.add(fileItem.uid);
message.warning(`${fileItem.name}:只能上传${acceptTip}格式的文件`);
}
continue;
} }
// 验证文件大小 // 验证文件大小
if (maxSize && file.size > maxSize) { if (maxSize && fileItem.size > maxSize) {
message.warning(`文件大小不能超过${size}M`); invalidFiles.push(fileItem);
const filtered = fileList.filter(item => item.uid !== file.uid); // 只提示未提示过的文件
onChange?.(filtered); if (!warnedFileUids.current.has(fileItem.uid)) {
return; warnedFileUids.current.add(fileItem.uid);
message.warning(`${fileItem.name}:文件大小不能超过${size}M`);
}
continue;
} }
// 验证图片分辨率 // 验证图片分辨率(异步)
if (ratioArr.length === 2 && file.type?.startsWith("image/")) { if (ratioArr.length === 2 && fileItem.type?.startsWith("image/")) {
const validateImageResolution = (imageUrl) => { const validateImageResolution = (imageUrl) => {
return new Promise((resolve) => {
const img = new Image(); const img = new Image();
img.onload = () => { img.onload = () => {
if (img.width !== +ratioArr[0] || img.height !== +ratioArr[1]) { const isValid = img.width === +ratioArr[0] && img.height === +ratioArr[1];
message.warning(`只能上传${ratio}分辨率的图片`); if (!isValid) {
const filtered = fileList.filter(item => item.uid !== file.uid); // 只提示未提示过的文件
onChange?.(filtered); if (!warnedFileUids.current.has(fileItem.uid)) {
return; warnedFileUids.current.add(fileItem.uid);
message.warning(`${fileItem.name}:只能上传${ratio}分辨率的图片`);
} }
onChange?.(fileList); }
resolve(isValid);
}; };
img.onerror = () => resolve(false);
img.src = imageUrl; img.src = imageUrl;
});
}; };
// 如果有现成的URL则直接使用否则使用FileReader读取本地文件 const validResolution = fileItem.url
if (file.url) { ? await validateImageResolution(fileItem.url)
validateImageResolution(file.url); : await new Promise((resolve) => {
}
else {
const reader = new FileReader(); const reader = new FileReader();
reader.onload = (e) => { reader.onload = (e) => {
validateImageResolution(e.target.result); validateImageResolution(e.target.result).then(resolve);
}; };
reader.readAsDataURL(file); reader.onerror = () => resolve(false);
reader.readAsDataURL(fileItem.originFileObj);
});
if (!validResolution) {
invalidFiles.push(fileItem);
continue;
} }
} }
else {
onChange?.(fileList); validFiles.push(fileItem);
} }
return { validFiles, invalidFiles };
};
// 执行验证并更新
validateFiles(fileList).then(({ validFiles }) => {
onChange?.(validFiles);
});
}; };
// 删除文件 // 删除文件
const handleRemove = (file) => { const handleRemove = (file) => {
// 清理该文件的提示记录
warnedFileUids.current.delete(file.uid);
if (!file.originFileObj) if (!file.originFileObj)
onGetRemoveFile?.(file); onGetRemoveFile?.(file);
return onRemove?.(file); return onRemove?.(file);