mirror of
https://github.com/nocobase/nocobase
synced 2024-11-15 09:38:51 +00:00
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 { 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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -40,7 +40,7 @@
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
.ant-upload-list-picture-card-container {
|
||||
// margin-bottom: 28px;
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user