UNPKG

xph-form

Version:

This is a configurable form component that supports React

179 lines (178 loc) 6.85 kB
import { jsx as _jsx } from "react/jsx-runtime"; import React, { useState, useEffect, useRef } from "react"; import { Upload, message } from "antd"; import { getFileEncodingType } from "../../helper"; import { isEqual } from "lodash-es"; import { buildUUID } from "../../helper"; const returnTypeMap = { ["String"]: "String", ["String[]"]: "String[]", ["File[]"]: "File[]", ["FileList"]: "FileList", }; const AutoUpload = (autoUploadProps) => { console.log("render AutoUpload"); console.log(buildUUID()); const baseDefaultFileList = ""; // 用于覆盖defaultFileList的类型 const { api, maxCount = 1, // 默认只能上传一个文件 maxSize = 2, // 默认最大2M listType = "picture-card", // 默认展示文件列表 openCrop = false, // 默认不开启裁剪 data, // 默认带上的参数 returnType = returnTypeMap["String"], // 默认返回String(如果多文件默认","拼接) value: defaultFileList = baseDefaultFileList, // 默认文件列表 onChange /** onChange事件调用后会改变Form的值 */, } = autoUploadProps; const firstChange = useRef(true); // 是否是第一次fileList改变,用于第一次不触发onChange const uploadQty = useRef(0); // useRef缓存记录每次本地上传的数量(这个一定要是useRef,不能使用useState,因为setState是异步的) const realFileList = useRef([]); // 实时的fileList const [fileList, setFileList] = useState([]); // 用于渲染的fileList /** 需要存储一份实时的fileList在realFileList */ const updateFileList = (list) => { realFileList.current = list; setFileList([...list]); }; /** 把扩展的属性排除掉 */ const getAutoUploadProps = () => { /** beforeUpload、fileList也需要排除,防止传入了影响原业务 */ const { api, maxCount, maxSize, openCrop, beforeUpload, fileList, returnType, ...rest } = autoUploadProps; return rest; }; /** 上传前校验 */ const beforeUpload = (file) => { const limit = file.size / 1024 / 1024 < maxSize; if (!limit) { message.error(`文件大小超过:${maxSize}M, 请重试`); } const count = realFileList.current.length + uploadQty.current < maxCount; if (!count) { message.error(`文件数量不能超过${maxCount}个`); } limit && count ? uploadQty.current++ : null; const result = limit && count; // 此处如果需要开启裁剪需要判断 result result && handleCrop(file); return Upload.LIST_IGNORE; }; // 处理裁剪 const handleCrop = (file) => { // 不开启裁剪直接上传 if (!openCrop) { customRequest({ file }); } else { message.error("暂时不支持裁剪功能,后续兼容。。。。"); customRequest({ file }); } }; /** 自定义上传 */ const customRequest = (config) => { if (api) { api({ file: config.file, ...data }) .then((res) => { updateFileList([...realFileList.current, ...res]); }) .finally(() => { uploadQty.current--; }); } else { // 创建本地url用于下载/预览 Object.assign(config.file, { status: "done", url: URL.createObjectURL(new Blob([config.file], { type: getFileEncodingType(config.file.type), })), }); updateFileList([...realFileList.current, config.file]); uploadQty.current--; } }; const handleChange = (info) => { const { file, fileList: newFileList } = info; const { status } = file; switch (status) { case "removed": { updateFileList([...newFileList]); break; } } }; // 将url处理成file const handleUrlToFile = (url) => { const getName = (url) => { const list = url.split("/"); const last = list[list.length - 1]; const [name] = last.split("?"); return name; }; // url存在fileList中的uid无需重新生成 const getUid = (url) => { const lastItem = realFileList.current.find((item) => item.url === url); if (lastItem) return lastItem.uid; return buildUUID(); }; return { uid: getUid(url), name: getName(url), url: url, status: "done" }; }; const getOnChangeFileList = () => { switch (returnType) { case returnTypeMap["String"]: { return fileList.map((item) => item.url).join(","); } case returnTypeMap["String[]"]: { return fileList.map((item) => item.url); } case returnTypeMap["File[]"]: { return [...fileList]; } case returnTypeMap["FileList"]: { return [...fileList]; } } }; /** * 监听初始值变化,赋值fileList */ useEffect(() => { /** 排除AutoUpload的onChange赋值之后又触发defaultFileList改变导致fileList又被赋值 */ const curDefaultFileList = getOnChangeFileList(); if (isEqual(curDefaultFileList, defaultFileList)) return; let list = []; switch (returnType) { case returnTypeMap["String"]: { list = (defaultFileList || "") .split(",") .filter((url) => url) .map((url) => handleUrlToFile(url)); break; } case returnTypeMap["String[]"]: { list = (defaultFileList || []).map((url) => handleUrlToFile(url)); break; } case returnTypeMap["File[]"]: { list = (defaultFileList || []).map((item) => item); break; } case returnTypeMap["FileList"]: { list = (defaultFileList || []).map((item) => item); break; } } updateFileList(list); }, [defaultFileList]); /** * 监听fileList变化,change表单值 */ useEffect(() => { if (firstChange.current) { firstChange.current = false; return; } const onChangeFileList = getOnChangeFileList(); onChange?.(onChangeFileList); }, [fileList]); return (_jsx(Upload, { listType: listType, ...getAutoUploadProps(), fileList: fileList, beforeUpload: beforeUpload, onChange: handleChange, children: "\u4E0A\u4F20" })); }; export default AutoUpload;