From d71fed0471666126bc9c521660941a362945b1ff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=A2=AB=E9=9B=A8=E6=B0=B4=E8=BF=87=E6=BB=A4=E7=9A=84?=
=?UTF-8?q?=E7=A9=BA=E6=B0=94-Rairn?= <958414905@qq.com>
Date: Wed, 28 Jun 2023 15:38:03 +0800
Subject: [PATCH] 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
---
.../schema-component/antd/preview/Preview.tsx | 33 ++++++--
.../schema-component/antd/upload/Upload.tsx | 84 ++++++++++++-------
.../schema-component/antd/upload/shared.ts | 8 +-
.../schema-component/antd/upload/style.less | 2 +-
4 files changed, 87 insertions(+), 40 deletions(-)
diff --git a/packages/core/client/src/schema-component/antd/preview/Preview.tsx b/packages/core/client/src/schema-component/antd/preview/Preview.tsx
index 948eadea31..df2c32beba 100644
--- a/packages/core/client/src/schema-component/antd/preview/Preview.tsx
+++ b/packages/core/client/src/schema-component/antd/preview/Preview.tsx
@@ -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 (
-
+
@@ -114,6 +116,7 @@ export const FileSelector = (props: Props) => {
icon={}
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 });
}}
>
{
};
export default Preview;
+
+function updateFileList(file: UploadFile, fileList: (UploadFile | Readonly
)[]) {
+ const nextFileList = [...fileList];
+ const fileIndex = nextFileList.findIndex(({ uid }) => uid === file.uid);
+ if (fileIndex === -1) {
+ nextFileList.push(file);
+ } else {
+ nextFileList[fileIndex] = file;
+ }
+ return nextFileList;
+}
diff --git a/packages/core/client/src/schema-component/antd/upload/Upload.tsx b/packages/core/client/src/schema-component/antd/upload/Upload.tsx
index 03b270f64e..a1fef5fce9 100644
--- a/packages/core/client/src/schema-component/antd/upload/Upload.tsx
+++ b/packages/core/client/src/schema-component/antd/upload/Upload.tsx
@@ -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 (
-
+
@@ -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' && (
{
footer={[
,
- ,
]}
width={'85vw'}
centered={true}
>
-
-
+ background: 'white',
+ display: 'flex',
+ flexDirection: 'column',
+ alignItems: 'center',
+ overflowY: 'auto',
+ }}
+ >
+
)}
@@ -305,3 +320,14 @@ Upload.DraggerV2 = connect(
);
export default Upload;
+
+function updateFileList(file: UploadFile, fileList: (UploadFile | Readonly)[]) {
+ const nextFileList = [...fileList];
+ const fileIndex = nextFileList.findIndex(({ uid }) => uid === file.uid);
+ if (fileIndex === -1) {
+ nextFileList.push(file);
+ } else {
+ nextFileList[fileIndex] = file;
+ }
+ return nextFileList;
+}
diff --git a/packages/core/client/src/schema-component/antd/upload/shared.ts b/packages/core/client/src/schema-component/antd/upload/shared.ts
index 7bfe51c8ab..a283a5e940 100644
--- a/packages/core/client/src/schema-component/antd/upload/shared.ts
+++ b/packages/core/client/src/schema-component/antd/upload/shared.ts
@@ -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({ serviceErrorMessage, ...props }: T) {
useUploadValidator(serviceErrorMessage);
- const onChange = (param: UploadChangeParam) => {
+ const onChange = (param: { fileList: any[] }) => {
props.onChange?.(normalizeFileList([...param.fileList]));
};
@@ -212,7 +211,10 @@ export function useUploadProps({ serviceEr
export const toItem = (file) => {
if (file?.response?.data) {
- file = file.response.data;
+ file = {
+ uid: file.uid,
+ ...file.response.data,
+ };
}
return {
...file,
diff --git a/packages/core/client/src/schema-component/antd/upload/style.less b/packages/core/client/src/schema-component/antd/upload/style.less
index 41468d990f..a4b225c471 100644
--- a/packages/core/client/src/schema-component/antd/upload/style.less
+++ b/packages/core/client/src/schema-component/antd/upload/style.less
@@ -40,7 +40,7 @@
background: rgba(0, 0, 0, 0.5);
}
.ant-upload-list-picture-card-container {
- // margin-bottom: 28px;
+ margin-bottom: 28px;
}
}