import { DeleteOutlined, DownloadOutlined, LoadingOutlined, PaperClipOutlined, UploadOutlined, } from '@ant-design/icons'; import { Button, Form, message, Tooltip, Upload } from 'antd'; import cls from 'classnames'; import { useCallback, useEffect, useState } from 'react'; import { v4 as uuidv4 } from 'uuid';
import { HTTP_CODE } from '@/constant/httpCode'; import { filePartUpload } from '@/pages/adminicularEvidence/service'; // 上传文件的接口
import styles from './index.less';
const FragmentUpload = (props) => { const { uploadExtra, acceptType, isDownload, labelName, handleloading, handleClickDownload, uploadItemLayout, } = props;
const [uploading, setUploading] = useState(false); const [fileData, setFileData] = useState(false);
useEffect(() => { handleloading(uploading); }, [uploading]);
const beforeUpload = useCallback((info) => { const fileName = info.name.substring(info.name.lastIndexOf('.'));
if (!acceptType.includes(fileName)) {
message.error('文件类型错误,请重新上传');
return false;
}
}, []);
const onRemove = useCallback(() => { setFileData(false); }, []);
const handleChange = useCallback((info) => { if (info.file.status === 'uploading') { setUploading(true); } else { setUploading(false); } if (info.file.status === 'done' || info.file.status === 'error') { setFileData(true); } }, []);
const sliceFileChunk = useCallback((file) => { const fileList = []; for (let i = 0; i < file.size; i += 5 * 1024 * 1024) { const endSize = i + 5 * 1024 * 1024 > file.size ? file.size : i + 5 * 1024 * 1024; const curFile = file.slice(i, endSize > file.size ? file.size : endSize); fileList.push(curFile); } return fileList; }, []);
const uploadChunkFile = async ( curChunkIndex, fileId, chunkFileList, totalSize, fileName, onSuccess, onError, ) => { const chunkFile = chunkFileList[curChunkIndex - 1]; const formData = new FormData(); formData.append('fileTmpId', fileId); formData.append('file', chunkFile); formData.append('fileName', fileName); formData.append('totalPart', String(chunkFileList.length)); formData.append('currentPart', String(curChunkIndex)); try { const res = await filePartUpload(formData);
if (curChunkIndex < chunkFileList.length) {
uploadChunkFile(
++curChunkIndex,
fileId,
chunkFileList,
totalSize,
fileName,
onSuccess,
onError,
);
}
if (
curChunkIndex === chunkFileList.length &&
res.code === HTTP_CODE.SUCCESS &&
res.data
) {
onSuccess(res);
}
} catch (error) {
onError(error);
}
};
const customRequest = async ({ data, file, filename, onSuccess, onError, }) => { const { size, name } = file; const formData = new FormData(); if (data) { Object.keys(data).forEach((keyData) => { formData.append(keyData, data[keyData]); }); } formData.append(filename, file); const fileId = uuidv4(); const chunkFileList = sliceFileChunk(file); uploadChunkFile(1, fileId, chunkFileList, size, name, onSuccess, onError); };
const itemRender = useCallback( (originNode, file, fileList, actions) => { return (
<DeleteOutlined
className={cls(styles.icon)}
onClick={() => {
actions.remove();
setFileData(false);
}}
/>
</div>
</>
) : null}
{file.status === 'error' ? (
<>
<PaperClipOutlined className={styles.err} />
<Tooltip placement="top" title={file?.error?.message}>
<span className={cls(styles.fileName, styles.err)}>
{file.name}
</span>
</Tooltip>
<DeleteOutlined
className={cls(styles.err, styles.icon)}
onClick={() => {
actions.remove();
setFileData(false);
}}
/>
</>
) : null}
</div>
);
},
[uploading],
);
return ( <Form.Item {...uploadItemLayout} name="fileIdEn" valuePropName="file" extra={uploadExtra} label={labelName} rules={[ { required: true, message: '请上传' }, () => ({ validator(rule, value) { if (value.status !== 'error') { return Promise.resolve(); } return Promise.reject(new Error('上传失败')); }, }), ]} getValueFromEvent={(e) => { if (Array.isArray(e)) { return e; } return e?.file; }} > <Button disabled={uploading || fileData} loading={uploading} icon={} > {uploading ? '上传中' : '选择文件'} </Form.Item> ); };
export default FragmentUpload;