fix(upload): fix the upload status not being updated if the upload was successful (#2133)

* fix(Upload): fix style

* fix(Upload): fix uploading

* Revert "fix(Upload): fix uploading"

This reverts commit 45984cd59fab38b8e6fb3f49930b29acc8699b4f.

* refactor: add key

* fix: fix the upload status not being updated if the upload was
successful

* fix(FileSelector): fix uploading

* fix: fix key
This commit is contained in:
被雨水过滤的空气-Rairn 2023-06-28 15:38:03 +08:00 committed by GitHub
parent ece7cb76c2
commit d71fed0471
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 87 additions and 40 deletions

View File

@ -1,10 +1,9 @@
import { DeleteOutlined, DownloadOutlined, PlusOutlined } from '@ant-design/icons';
import { connect, mapReadPretty } from '@formily/react';
import { Upload as AntdUpload, Button, Progress, Space } from 'antd';
import { Upload as AntdUpload, Button, Progress, Space, UploadFile } from 'antd';
import cls from 'classnames';
import { css } from '@emotion/css';
import { saveAs } from 'file-saver';
import React, { useEffect, useState } from 'react';
import React, { useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import Lightbox from 'react-image-lightbox';
import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app
@ -33,12 +32,15 @@ export const FileSelector = (props: Props) => {
const [photoIndex, setPhotoIndex] = useState(0);
const [visible, setVisible] = useState(false);
const { t } = useTranslation();
const internalFileList = useRef([]);
// 兼容旧版本
const showSelectButton = selectFile === undefined && quickUpload === undefined;
useEffect(() => {
setFileList(toFileList(value));
const fileList = toFileList(value);
setFileList(fileList);
internalFileList.current = fileList;
}, [value]);
const handleRemove = (file) => {
@ -70,7 +72,7 @@ export const FileSelector = (props: Props) => {
}
};
return (
<div key={file.id} className={'ant-upload-list-picture-card-container'}>
<div key={file.uid || file.id} className={'ant-upload-list-picture-card-container'}>
<div className="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture-card">
<div className={'ant-upload-list-item-info'}>
<span className="ant-upload-span">
@ -114,6 +116,7 @@ export const FileSelector = (props: Props) => {
icon={<DeleteOutlined />}
onClick={() => {
handleRemove(file);
internalFileList.current = internalFileList.current.filter((item) => item.uid !== file.uid);
}}
/>
)}
@ -166,9 +169,14 @@ export const FileSelector = (props: Props) => {
showUploadList={false}
onRemove={handleRemove}
onChange={(info) => {
// info.fileList 有 BUG会导致上传状态一直是 uploading
// 所以这里仿照 antd 源码,自己维护一个 fileList
const list = updateFileList(info.file, internalFileList.current);
internalFileList.current = list;
// 如果不在这里 setFileList 的话,会导致 onChange 只会执行一次
setFileList([...info.fileList]);
uploadProps.onChange?.(info);
setFileList(toFileList(list));
uploadProps.onChange?.({ fileList: list });
}}
>
<div
@ -250,3 +258,14 @@ export const FileSelector = (props: Props) => {
};
export default Preview;
function updateFileList(file: UploadFile, fileList: (UploadFile | Readonly<UploadFile>)[]) {
const nextFileList = [...fileList];
const fileIndex = nextFileList.findIndex(({ uid }) => uid === file.uid);
if (fileIndex === -1) {
nextFileList.push(file);
} else {
nextFileList[fileIndex] = file;
}
return nextFileList;
}

View File

@ -1,11 +1,10 @@
import { DeleteOutlined, DownloadOutlined, InboxOutlined, LoadingOutlined, PlusOutlined } from '@ant-design/icons';
import { usePrefixCls } from '@formily/antd/esm/__builtins__';
import { connect, mapProps, mapReadPretty } from '@formily/react';
import { Upload as AntdUpload, Button, Progress, Space, Modal } from 'antd';
import { Upload as AntdUpload, Button, Modal, Progress, Space, UploadFile } from 'antd';
import cls from 'classnames';
import { css } from '@emotion/css';
import { saveAs } from 'file-saver';
import React, { useEffect, useState } from 'react';
import React, { useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import Lightbox from 'react-image-lightbox';
import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app
@ -33,12 +32,16 @@ Upload.Attachment = connect((props: UploadProps) => {
const [visible, setVisible] = useState(false);
const [fileType, setFileType] = useState<'image' | 'pdf'>();
const { t } = useTranslation();
const internalFileList = useRef([]);
function closeIFrameModal() {
setVisible(false);
}
useEffect(() => {
if (sync) {
setFileList(toFileList(value));
const fileList = toFileList(value);
setFileList(fileList);
internalFileList.current = fileList;
}
}, [value, sync]);
const uploadProps = useUploadProps({ ...props });
@ -55,7 +58,7 @@ Upload.Attachment = connect((props: UploadProps) => {
setFileType('image');
setVisible(true);
setFileIndex(index);
} else if(isPdf(file.extname)) {
} else if (isPdf(file.extname)) {
setVisible(true);
setFileIndex(index);
setFileType('pdf');
@ -64,7 +67,7 @@ Upload.Attachment = connect((props: UploadProps) => {
}
};
return (
<div className={'ant-upload-list-picture-card-container'}>
<div key={file.uid || file.id} className={'ant-upload-list-picture-card-container'}>
<div className="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture-card">
<div className={'ant-upload-list-item-info'}>
<span className="ant-upload-span">
@ -115,6 +118,9 @@ Upload.Attachment = connect((props: UploadProps) => {
}
const index = prevFileList.indexOf(file);
prevFileList.splice(index, 1);
internalFileList.current = internalFileList.current.filter(
(item) => item.uid !== file.uid,
);
onChange(toValue([...prevFileList]));
return [...prevFileList];
});
@ -141,12 +147,17 @@ Upload.Attachment = connect((props: UploadProps) => {
listType={'picture-card'}
fileList={fileList}
onChange={(info) => {
// info.fileList 有 BUG会导致上传状态一直是 uploading
// 所以这里仿照 antd 源码,自己维护一个 fileList
const list = updateFileList(info.file, internalFileList.current);
internalFileList.current = list;
setSync(false);
if (multiple) {
if (info.file.status === 'done') {
onChange(toValue(info.fileList));
onChange(toValue(list));
}
setFileList(info.fileList.map(toItem));
setFileList(list.map(toItem));
} else {
if (info.file.status === 'done') {
// TODO(BUG): object 的联动有问题,不响应,折中的办法先置空再赋值
@ -198,7 +209,7 @@ Upload.Attachment = connect((props: UploadProps) => {
]}
/>
)}
{visible && fileType === 'pdf' && (
<Modal
open={visible}
@ -207,7 +218,7 @@ Upload.Attachment = connect((props: UploadProps) => {
footer={[
<Button
style={{
textTransform: 'capitalize'
textTransform: 'capitalize',
}}
onClick={(e) => {
e.preventDefault();
@ -218,31 +229,35 @@ Upload.Attachment = connect((props: UploadProps) => {
>
{t('download')}
</Button>,
<Button onClick={closeIFrameModal} style={{textTransform: 'capitalize'}}>
<Button onClick={closeIFrameModal} style={{ textTransform: 'capitalize' }}>
{t('close')}
</Button>
</Button>,
]}
width={'85vw'}
centered={true}
>
<div style={{
padding: '8px',
maxWidth: '100%',
maxHeight: 'calc(100vh - 256px)',
height: '90vh',
width: '100%',
background: 'white',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
overflowY: 'auto'
}} >
<iframe src={images[fileIndex].url} style={{
<div
style={{
padding: '8px',
maxWidth: '100%',
maxHeight: 'calc(100vh - 256px)',
height: '90vh',
width: '100%',
maxHeight: '90vh',
flex: '1 1 auto'
}}>
</iframe>
background: 'white',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
overflowY: 'auto',
}}
>
<iframe
src={images[fileIndex].url}
style={{
width: '100%',
maxHeight: '90vh',
flex: '1 1 auto',
}}
></iframe>
</div>
</Modal>
)}
@ -305,3 +320,14 @@ Upload.DraggerV2 = connect(
);
export default Upload;
function updateFileList(file: UploadFile, fileList: (UploadFile | Readonly<UploadFile>)[]) {
const nextFileList = [...fileList];
const fileIndex = nextFileList.findIndex(({ uid }) => uid === file.uid);
if (fileIndex === -1) {
nextFileList.push(file);
} else {
nextFileList[fileIndex] = file;
}
return nextFileList;
}

View File

@ -2,7 +2,6 @@ import { Field } from '@formily/core';
import { useField } from '@formily/react';
import { reaction } from '@formily/reactive';
import { isArr, isValid, toArr as toArray } from '@formily/shared';
import { UploadChangeParam } from 'antd/es/upload';
import { UploadFile } from 'antd/es/upload/interface';
import { useEffect } from 'react';
import { useAPIClient } from '../../../api-client';
@ -167,7 +166,7 @@ export const useUploadValidator = (serviceErrorMessage = 'Upload Service Error')
export function useUploadProps<T extends IUploadProps = UploadProps>({ serviceErrorMessage, ...props }: T) {
useUploadValidator(serviceErrorMessage);
const onChange = (param: UploadChangeParam<UploadFile>) => {
const onChange = (param: { fileList: any[] }) => {
props.onChange?.(normalizeFileList([...param.fileList]));
};
@ -212,7 +211,10 @@ export function useUploadProps<T extends IUploadProps = UploadProps>({ serviceEr
export const toItem = (file) => {
if (file?.response?.data) {
file = file.response.data;
file = {
uid: file.uid,
...file.response.data,
};
}
return {
...file,

View File

@ -40,7 +40,7 @@
background: rgba(0, 0, 0, 0.5);
}
.ant-upload-list-picture-card-container {
// margin-bottom: 28px;
margin-bottom: 28px;
}
}