zy-react-library/components/Upload/index.js

177 lines
4.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import { PlusOutlined } from "@ant-design/icons";
import { Upload as AntUpload, Button, message, Modal } from "antd";
import { useState } from "react";
/**
* 文件上传组件
*/
const Upload = (props) => {
const {
value = [],
onChange,
onPreview,
maxCount = 1,
listType = "text",
accept = "",
ratio = "",
showTip = true,
multiple = true,
size = 0,
tipContent,
uploadButtonText = "点击选择文件上传",
formValues,
...restProps
} = props;
const [previewVisible, setPreviewVisible] = useState(false);
const [previewImage, setPreviewImage] = useState("");
// 生成提示信息
const getTipText = () => {
if (tipContent)
return tipContent;
const tips = [
`最多上传${maxCount}个文件`,
accept
? `并且只能上传${accept
.replace(/\./g, "")
.split(",")
.join("、")}格式的文件`
: "可以上传任意格式的文件",
size ? `文件大小不能超过${size}M` : "",
ratio ? `只能上传${ratio}分辨率的图片` : "",
].filter(Boolean);
return `${tips.join("")}`;
};
const handleBeforeUpload = () => {
return false;
};
// 文件状态改变
const handleChange = ({ file, fileList }) => {
const acceptList = accept ? accept.split(",") : [];
const ratioArr = ratio ? ratio.split("*") : [];
const suffix = file.name.substring(
file.name.lastIndexOf("."),
file.name.length,
);
const maxSize = size * 1024 * 1024;
// 验证文件格式
if (acceptList.length > 0 && !acceptList.includes(suffix)) {
message.warning(`只能上传${accept}格式的文件`);
return;
}
// 验证文件大小
if (maxSize && file.size > maxSize) {
message.warning(`文件大小不能超过${size}M`);
return;
}
// 验证图片分辨率
if (ratioArr.length === 2 && file.type?.startsWith("image/")) {
const validateImageResolution = (imageUrl) => {
const img = new Image();
img.onload = () => {
if (img.width !== +ratioArr[0] || img.height !== +ratioArr[1]) {
message.warning(`只能上传${ratio}分辨率的图片`);
const filtered = fileList.filter(item => item.uid !== file.uid);
onChange?.(filtered);
return;
}
onChange?.(fileList);
};
img.src = imageUrl;
};
// 如果有现成的URL则直接使用否则使用FileReader读取本地文件
if (file.url) {
validateImageResolution(file.url);
}
else {
const reader = new FileReader();
reader.onload = (e) => {
validateImageResolution(e.target.result);
};
reader.readAsDataURL(file);
}
}
else {
onChange?.(fileList);
}
};
// 预览文件
const handlePreview = (file) => {
if (["picture-card", "picture-circle", "picture"].includes(listType)) {
setPreviewImage(file.url || file.thumbUrl);
setPreviewVisible(true);
}
onPreview?.(file);
};
// 关闭预览
const handleCancel = () => {
setPreviewVisible(false);
};
// 上传按钮
const uploadButton
= ["picture-card", "picture-circle", "picture"].includes(listType)
? (
<div>
<PlusOutlined style={{ fontSize: 32 }} />
</div>
)
: (
<Button type="primary">{uploadButtonText}</Button>
);
return (
<>
<AntUpload
fileList={value}
multiple={multiple}
maxCount={maxCount}
listType={listType}
accept={accept}
onChange={handleChange}
onPreview={handlePreview}
beforeUpload={handleBeforeUpload}
{...restProps}
>
{value.length >= maxCount ? null : uploadButton}
</AntUpload>
{
showTip
? (tipContent || getTipText()) && (
<div style={{ marginTop: 10, color: "#ff4d4f" }}>
{tipContent || getTipText()}
</div>
)
: null
}
<Modal
open={previewVisible}
title="查看图片"
footer={null}
onCancel={handleCancel}
>
<img
alt="preview"
style={{ width: "100%", objectFit: "scale-down" }}
src={previewImage}
/>
</Modal>
</>
);
};
Upload.displayName = "Upload";
export default Upload;