import React, { useCallback, useReducer, useImperativeHandle, useMemo } from 'react'; import Button from 'antd/es/button'; import 'antd/es/button/style/index'; import Upload, { UploadProps, RcFile, UploadChangeParam } from 'antd/es/upload'; import 'antd/es/upload/style/index'; import UploadOutlined from '@ant-design/icons/UploadOutlined'; import PlusOutlined from '@ant-design/icons/PlusOutlined'; import { UploadFile } from 'antd/es/upload/interface'; import { loadFile, openFile } from '@jy-fe/utils/es/joyowoUmi'; import { XuiUploadButtonProps, XuiUploadButtonHandles, InitialStateType, } from './xui-upload-button.d'; const initialState: InitialStateType = { fileList: [], }; const reducer = ( state: InitialStateType, action: { type: string; payload?: { [key: string]: any }; }, ) => { switch (action.type) { case 'update': return { ...state, ...action.payload }; default: throw new Error(); } }; const UploadButton: React.ForwardRefRenderFunction = ( { name, data, apiUrl, listType = 'text', accept, acceptErrorTip, maxSize, callbackDataKey, maxSizeErrorTip, nullErrorTip = '请上传文件', templateUrl, otherJudgment, onChange, }, ref, ) => { const className = 'xui-ant__upload-button'; const [state, hookDispatch] = useReducer(reducer, initialState); const { fileList } = state; const triggerDispatch = useCallback( (payload: Partial) => { hookDispatch({ type: 'update', payload, }); }, [state], ); const beforeUpload = useCallback( (file: RcFile) => { if (accept && !accept.includes(file.type)) { triggerDispatch({ fileList: [], }); if (onChange) { onChange(new Error(acceptErrorTip)); } return false; } if (maxSize && file.size > maxSize) { triggerDispatch({ fileList: [], }); if (onChange) { onChange(new Error(maxSizeErrorTip)); } return false; } return true; }, [accept, acceptErrorTip, maxSize, maxSizeErrorTip, onChange], ); const changeUpload = useCallback( (info: UploadChangeParam) => { if (info.file.status === 'uploading' || info.file.status === 'done') { triggerDispatch({ fileList: [info.file], }); if (info.file.response && onChange) { const { status, data: resData, msg } = info.file.response; if (!status && resData) { onChange(resData[callbackDataKey]); } else if (otherJudgment) { triggerDispatch({ fileList: [], }); onChange(otherJudgment(resData || {})); } else { triggerDispatch({ fileList: [], }); onChange(new Error(msg)); } } } }, [onChange, callbackDataKey], ); const onPreview = useCallback((file: UploadFile) => { openFile(file.response.data.url || ''); }, []); const onRemove = useCallback(() => { triggerDispatch({ fileList: [], }); if (onChange) { onChange(new Error(nullErrorTip)); } }, [nullErrorTip, onChange]); const props: UploadProps = { className: `${className}--upload`, name, listType, fileList, headers: { AuthToken: localStorage.getItem('token') || '', }, action: apiUrl, data: data || {}, beforeUpload, onChange: changeUpload, onPreview, onRemove, }; if (accept) { props.accept = accept.join(','); } useImperativeHandle(ref, () => ({ clear: () => { onRemove(); }, })); const UploadContent = useMemo(() => { if (listType === 'text') { return ( ); } if (listType === 'picture-card') { if (fileList.length > 0) { return null; } return ; } return null; }, [fileList, listType]); return (
{UploadContent} {templateUrl && ( loadFile(templateUrl)}> 模板下载 )}
); }; export default React.forwardRef(UploadButton);