123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- import { Button, Modal, Upload, message } from "antd";
- import { PlusOutlined } from "@ant-design/icons";
- import { FC, useMemo, useRef, useState } from "react";
- import { RcFile, UploadFile, UploadProps } from "antd/es/upload";
- import { getTokenInfo } from "@/utils";
- import { DageUploadProps, DageUploadType } from "./types";
- import { UploadOutlined } from "@ant-design/icons";
- import "./index.scss";
- const getBase64 = (file: RcFile): Promise<string> =>
- new Promise((resolve, reject) => {
- const reader = new FileReader();
- reader.readAsDataURL(file);
- reader.onload = () => resolve(reader.result as string);
- reader.onerror = (error) => reject(error);
- });
- export const DageUpload: FC<DageUploadProps> = ({
- action,
- value,
- type = DageUploadType.IMG,
- maxCount = 9,
- maxSize = 5,
- tips,
- disabled,
- onUploaded,
- onUploading,
- onChange,
- }) => {
- const [previewOpen, setPreviewOpen] = useState(false);
- const [previewImage, setPreviewImage] = useState("");
- const [previewTitle, setPreviewTitle] = useState("");
- const [uploading, setUploading] = useState(false);
- const uploadListType = useMemo(() => {
- switch (type) {
- case DageUploadType.IMG:
- return "picture-card";
- default:
- return "text";
- }
- }, [type]);
- const isPictureCard = uploadListType === "picture-card";
- const uploadingFileNum = useRef(0);
- const beforeUpload = (file: RcFile) => {
- let pass = false;
- let passFileType = false;
- // 校验文件类型
- switch (type) {
- case DageUploadType.IMG:
- passFileType = ["image/jpeg", "image/png", "image/gif"].includes(
- file.type
- );
- if (!passFileType) {
- message.error("只支持png、jpg、gif和jpeg格式!");
- }
- break;
- case DageUploadType.MODEL:
- passFileType = file.name.indexOf(".4dage") > -1;
- if (!passFileType) {
- message.error("只支持4dage格式的模型文件!");
- }
- break;
- case DageUploadType.VIDEO:
- passFileType = ["video/mp4"].includes(file.type);
- if (!passFileType) {
- message.error("只支持mp4格式!");
- }
- break;
- case DageUploadType.AUDIO:
- passFileType = ["audio/mpeg"].includes(file.type);
- if (!passFileType) {
- message.error("只支持mp3格式!");
- }
- break;
- }
- // 校验文件大小
- const isLtM = file.size / 1024 / 1024 < maxSize;
- if (!isLtM) {
- message.error(`最大支持 ${maxSize}M!`);
- }
- uploadingFileNum.current += 1;
- pass = passFileType && isLtM;
- return pass ? pass : Upload.LIST_IGNORE;
- };
- const handleChange: UploadProps["onChange"] = ({
- fileList: newFileList,
- file,
- }) => {
- if (file.status === "uploading") {
- setUploading(true);
- onUploading?.();
- }
- if (file.status === "done") {
- uploadingFileNum.current -= 1;
- if (uploading && !uploadingFileNum.current) {
- setUploading(false);
- onUploaded?.();
- }
- }
- onChange?.(
- newFileList.map((i) => ({
- ...i,
- dType: type,
- }))
- );
- };
- const handleCancel = () => setPreviewOpen(false);
- const handlePreview = async (file: UploadFile) => {
- if (!isPictureCard) return;
- if (!file.url && !file.preview) {
- file.preview = await getBase64(file.originFileObj as RcFile);
- }
- setPreviewImage(file.url || (file.preview as string));
- setPreviewOpen(true);
- setPreviewTitle(
- file.name || file.url!.substring(file.url!.lastIndexOf("/") + 1)
- );
- };
- return (
- <div className="dage-upload">
- <Upload
- disabled={disabled}
- headers={{
- token: getTokenInfo().token,
- }}
- fileList={value}
- withCredentials
- action={process.env.REACT_APP_BACKEND_URL + action}
- name="file"
- listType={uploadListType}
- data={{
- type,
- }}
- maxCount={maxCount}
- showUploadList={{
- showDownloadIcon: true,
- }}
- multiple={maxCount > 1}
- onPreview={handlePreview}
- beforeUpload={beforeUpload}
- onChange={handleChange}
- >
- {!disabled &&
- (isPictureCard ? (
- (!value || value.length < maxCount) && <PlusOutlined />
- ) : (
- <Button icon={<UploadOutlined />}>上传</Button>
- ))}
- </Upload>
- {!!tips && (
- <p
- style={{ marginTop: isPictureCard ? 0 : "8px" }}
- className="dage-upload__tips"
- >
- {tips}
- </p>
- )}
- <Modal
- open={previewOpen}
- title={previewTitle}
- footer={null}
- onCancel={handleCancel}
- >
- <img alt="example" style={{ width: "100%" }} src={previewImage} />
- </Modal>
- </div>
- );
- };
- export * from "./types";
|