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:
parent
ece7cb76c2
commit
d71fed0471
@ -1,10 +1,9 @@
|
|||||||
import { DeleteOutlined, DownloadOutlined, PlusOutlined } from '@ant-design/icons';
|
import { DeleteOutlined, DownloadOutlined, PlusOutlined } from '@ant-design/icons';
|
||||||
import { connect, mapReadPretty } from '@formily/react';
|
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 cls from 'classnames';
|
||||||
import { css } from '@emotion/css';
|
|
||||||
import { saveAs } from 'file-saver';
|
import { saveAs } from 'file-saver';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import Lightbox from 'react-image-lightbox';
|
import Lightbox from 'react-image-lightbox';
|
||||||
import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app
|
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 [photoIndex, setPhotoIndex] = useState(0);
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const internalFileList = useRef([]);
|
||||||
|
|
||||||
// 兼容旧版本
|
// 兼容旧版本
|
||||||
const showSelectButton = selectFile === undefined && quickUpload === undefined;
|
const showSelectButton = selectFile === undefined && quickUpload === undefined;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setFileList(toFileList(value));
|
const fileList = toFileList(value);
|
||||||
|
setFileList(fileList);
|
||||||
|
internalFileList.current = fileList;
|
||||||
}, [value]);
|
}, [value]);
|
||||||
|
|
||||||
const handleRemove = (file) => {
|
const handleRemove = (file) => {
|
||||||
@ -70,7 +72,7 @@ export const FileSelector = (props: Props) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
return (
|
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 ant-upload-list-item-done ant-upload-list-item-list-type-picture-card">
|
||||||
<div className={'ant-upload-list-item-info'}>
|
<div className={'ant-upload-list-item-info'}>
|
||||||
<span className="ant-upload-span">
|
<span className="ant-upload-span">
|
||||||
@ -114,6 +116,7 @@ export const FileSelector = (props: Props) => {
|
|||||||
icon={<DeleteOutlined />}
|
icon={<DeleteOutlined />}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleRemove(file);
|
handleRemove(file);
|
||||||
|
internalFileList.current = internalFileList.current.filter((item) => item.uid !== file.uid);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@ -166,9 +169,14 @@ export const FileSelector = (props: Props) => {
|
|||||||
showUploadList={false}
|
showUploadList={false}
|
||||||
onRemove={handleRemove}
|
onRemove={handleRemove}
|
||||||
onChange={(info) => {
|
onChange={(info) => {
|
||||||
|
// info.fileList 有 BUG,会导致上传状态一直是 uploading
|
||||||
|
// 所以这里仿照 antd 源码,自己维护一个 fileList
|
||||||
|
const list = updateFileList(info.file, internalFileList.current);
|
||||||
|
internalFileList.current = list;
|
||||||
|
|
||||||
// 如果不在这里 setFileList 的话,会导致 onChange 只会执行一次
|
// 如果不在这里 setFileList 的话,会导致 onChange 只会执行一次
|
||||||
setFileList([...info.fileList]);
|
setFileList(toFileList(list));
|
||||||
uploadProps.onChange?.(info);
|
uploadProps.onChange?.({ fileList: list });
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@ -250,3 +258,14 @@ export const FileSelector = (props: Props) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default Preview;
|
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;
|
||||||
|
}
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
import { DeleteOutlined, DownloadOutlined, InboxOutlined, LoadingOutlined, PlusOutlined } from '@ant-design/icons';
|
import { DeleteOutlined, DownloadOutlined, InboxOutlined, LoadingOutlined, PlusOutlined } from '@ant-design/icons';
|
||||||
import { usePrefixCls } from '@formily/antd/esm/__builtins__';
|
import { usePrefixCls } from '@formily/antd/esm/__builtins__';
|
||||||
import { connect, mapProps, mapReadPretty } from '@formily/react';
|
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 cls from 'classnames';
|
||||||
import { css } from '@emotion/css';
|
|
||||||
import { saveAs } from 'file-saver';
|
import { saveAs } from 'file-saver';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import Lightbox from 'react-image-lightbox';
|
import Lightbox from 'react-image-lightbox';
|
||||||
import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app
|
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 [visible, setVisible] = useState(false);
|
||||||
const [fileType, setFileType] = useState<'image' | 'pdf'>();
|
const [fileType, setFileType] = useState<'image' | 'pdf'>();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const internalFileList = useRef([]);
|
||||||
|
|
||||||
function closeIFrameModal() {
|
function closeIFrameModal() {
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
}
|
}
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (sync) {
|
if (sync) {
|
||||||
setFileList(toFileList(value));
|
const fileList = toFileList(value);
|
||||||
|
setFileList(fileList);
|
||||||
|
internalFileList.current = fileList;
|
||||||
}
|
}
|
||||||
}, [value, sync]);
|
}, [value, sync]);
|
||||||
const uploadProps = useUploadProps({ ...props });
|
const uploadProps = useUploadProps({ ...props });
|
||||||
@ -64,7 +67,7 @@ Upload.Attachment = connect((props: UploadProps) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
return (
|
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 ant-upload-list-item-done ant-upload-list-item-list-type-picture-card">
|
||||||
<div className={'ant-upload-list-item-info'}>
|
<div className={'ant-upload-list-item-info'}>
|
||||||
<span className="ant-upload-span">
|
<span className="ant-upload-span">
|
||||||
@ -115,6 +118,9 @@ Upload.Attachment = connect((props: UploadProps) => {
|
|||||||
}
|
}
|
||||||
const index = prevFileList.indexOf(file);
|
const index = prevFileList.indexOf(file);
|
||||||
prevFileList.splice(index, 1);
|
prevFileList.splice(index, 1);
|
||||||
|
internalFileList.current = internalFileList.current.filter(
|
||||||
|
(item) => item.uid !== file.uid,
|
||||||
|
);
|
||||||
onChange(toValue([...prevFileList]));
|
onChange(toValue([...prevFileList]));
|
||||||
return [...prevFileList];
|
return [...prevFileList];
|
||||||
});
|
});
|
||||||
@ -141,12 +147,17 @@ Upload.Attachment = connect((props: UploadProps) => {
|
|||||||
listType={'picture-card'}
|
listType={'picture-card'}
|
||||||
fileList={fileList}
|
fileList={fileList}
|
||||||
onChange={(info) => {
|
onChange={(info) => {
|
||||||
|
// info.fileList 有 BUG,会导致上传状态一直是 uploading
|
||||||
|
// 所以这里仿照 antd 源码,自己维护一个 fileList
|
||||||
|
const list = updateFileList(info.file, internalFileList.current);
|
||||||
|
internalFileList.current = list;
|
||||||
|
|
||||||
setSync(false);
|
setSync(false);
|
||||||
if (multiple) {
|
if (multiple) {
|
||||||
if (info.file.status === 'done') {
|
if (info.file.status === 'done') {
|
||||||
onChange(toValue(info.fileList));
|
onChange(toValue(list));
|
||||||
}
|
}
|
||||||
setFileList(info.fileList.map(toItem));
|
setFileList(list.map(toItem));
|
||||||
} else {
|
} else {
|
||||||
if (info.file.status === 'done') {
|
if (info.file.status === 'done') {
|
||||||
// TODO(BUG): object 的联动有问题,不响应,折中的办法先置空再赋值
|
// TODO(BUG): object 的联动有问题,不响应,折中的办法先置空再赋值
|
||||||
@ -207,7 +218,7 @@ Upload.Attachment = connect((props: UploadProps) => {
|
|||||||
footer={[
|
footer={[
|
||||||
<Button
|
<Button
|
||||||
style={{
|
style={{
|
||||||
textTransform: 'capitalize'
|
textTransform: 'capitalize',
|
||||||
}}
|
}}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@ -220,12 +231,13 @@ Upload.Attachment = connect((props: UploadProps) => {
|
|||||||
</Button>,
|
</Button>,
|
||||||
<Button onClick={closeIFrameModal} style={{ textTransform: 'capitalize' }}>
|
<Button onClick={closeIFrameModal} style={{ textTransform: 'capitalize' }}>
|
||||||
{t('close')}
|
{t('close')}
|
||||||
</Button>
|
</Button>,
|
||||||
]}
|
]}
|
||||||
width={'85vw'}
|
width={'85vw'}
|
||||||
centered={true}
|
centered={true}
|
||||||
>
|
>
|
||||||
<div style={{
|
<div
|
||||||
|
style={{
|
||||||
padding: '8px',
|
padding: '8px',
|
||||||
maxWidth: '100%',
|
maxWidth: '100%',
|
||||||
maxHeight: 'calc(100vh - 256px)',
|
maxHeight: 'calc(100vh - 256px)',
|
||||||
@ -235,14 +247,17 @@ Upload.Attachment = connect((props: UploadProps) => {
|
|||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
overflowY: 'auto'
|
overflowY: 'auto',
|
||||||
}} >
|
}}
|
||||||
<iframe src={images[fileIndex].url} style={{
|
>
|
||||||
|
<iframe
|
||||||
|
src={images[fileIndex].url}
|
||||||
|
style={{
|
||||||
width: '100%',
|
width: '100%',
|
||||||
maxHeight: '90vh',
|
maxHeight: '90vh',
|
||||||
flex: '1 1 auto'
|
flex: '1 1 auto',
|
||||||
}}>
|
}}
|
||||||
</iframe>
|
></iframe>
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
)}
|
)}
|
||||||
@ -305,3 +320,14 @@ Upload.DraggerV2 = connect(
|
|||||||
);
|
);
|
||||||
|
|
||||||
export default Upload;
|
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;
|
||||||
|
}
|
||||||
|
@ -2,7 +2,6 @@ import { Field } from '@formily/core';
|
|||||||
import { useField } from '@formily/react';
|
import { useField } from '@formily/react';
|
||||||
import { reaction } from '@formily/reactive';
|
import { reaction } from '@formily/reactive';
|
||||||
import { isArr, isValid, toArr as toArray } from '@formily/shared';
|
import { isArr, isValid, toArr as toArray } from '@formily/shared';
|
||||||
import { UploadChangeParam } from 'antd/es/upload';
|
|
||||||
import { UploadFile } from 'antd/es/upload/interface';
|
import { UploadFile } from 'antd/es/upload/interface';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useAPIClient } from '../../../api-client';
|
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) {
|
export function useUploadProps<T extends IUploadProps = UploadProps>({ serviceErrorMessage, ...props }: T) {
|
||||||
useUploadValidator(serviceErrorMessage);
|
useUploadValidator(serviceErrorMessage);
|
||||||
const onChange = (param: UploadChangeParam<UploadFile>) => {
|
const onChange = (param: { fileList: any[] }) => {
|
||||||
props.onChange?.(normalizeFileList([...param.fileList]));
|
props.onChange?.(normalizeFileList([...param.fileList]));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -212,7 +211,10 @@ export function useUploadProps<T extends IUploadProps = UploadProps>({ serviceEr
|
|||||||
|
|
||||||
export const toItem = (file) => {
|
export const toItem = (file) => {
|
||||||
if (file?.response?.data) {
|
if (file?.response?.data) {
|
||||||
file = file.response.data;
|
file = {
|
||||||
|
uid: file.uid,
|
||||||
|
...file.response.data,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
...file,
|
...file,
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
background: rgba(0, 0, 0, 0.5);
|
background: rgba(0, 0, 0, 0.5);
|
||||||
}
|
}
|
||||||
.ant-upload-list-picture-card-container {
|
.ant-upload-list-picture-card-container {
|
||||||
// margin-bottom: 28px;
|
margin-bottom: 28px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user