From c068cd48b081c8f1a3b0c03e9f78151537d6781f Mon Sep 17 00:00:00 2001 From: saller Date: Mon, 23 Oct 2023 10:04:36 +0800 Subject: [PATCH] fix(comp:upload): controlled update should trigger upload and abort (#1715) --- packages/components/upload/demo/Controlled.md | 14 ++++++ .../components/upload/demo/Controlled.vue | 45 +++++++++++++++++ .../upload/src/composables/useFilesData.ts | 5 +- .../upload/src/composables/useRequest.ts | 20 ++++---- .../src/composables/useUploadControl.ts | 50 +++++++++++++------ packages/components/upload/src/types.ts | 2 +- 6 files changed, 109 insertions(+), 27 deletions(-) create mode 100644 packages/components/upload/demo/Controlled.md create mode 100644 packages/components/upload/demo/Controlled.vue diff --git a/packages/components/upload/demo/Controlled.md b/packages/components/upload/demo/Controlled.md new file mode 100644 index 000000000..cb2b43cbd --- /dev/null +++ b/packages/components/upload/demo/Controlled.md @@ -0,0 +1,14 @@ +--- +title: + zh: 受控使用 + en: Controlled usage +order: 0 +--- + +## zh + +`files` 支持受控,添加文件到 `files` 中可自动上传文件,删除则可以自动终止上传。 + +## en + +`files` supports controlled usage, file is auto uploaded after added to `files`, and aborts after removed. diff --git a/packages/components/upload/demo/Controlled.vue b/packages/components/upload/demo/Controlled.vue new file mode 100644 index 000000000..a8a2c1051 --- /dev/null +++ b/packages/components/upload/demo/Controlled.vue @@ -0,0 +1,45 @@ + + + diff --git a/packages/components/upload/src/composables/useFilesData.ts b/packages/components/upload/src/composables/useFilesData.ts index 70bcecbac..e2c6a4e39 100644 --- a/packages/components/upload/src/composables/useFilesData.ts +++ b/packages/components/upload/src/composables/useFilesData.ts @@ -6,7 +6,8 @@ */ import type { UploadFile, UploadProps } from '../types' -import type { ComputedRef } from 'vue' + +import { type ComputedRef, toRaw } from 'vue' import { callEmit, useControlledProp } from '@idux/cdk/utils' @@ -47,7 +48,7 @@ export function useFilesData(props: UploadProps): FilesDataContext { } }) - setFileList(newFileList) + setFileList(toRaw(newFileList)) statusChangeFiles.forEach(file => { callEmit(props.onFileStatusChange, file) diff --git a/packages/components/upload/src/composables/useRequest.ts b/packages/components/upload/src/composables/useRequest.ts index b5c8a3244..80770969c 100644 --- a/packages/components/upload/src/composables/useRequest.ts +++ b/packages/components/upload/src/composables/useRequest.ts @@ -46,20 +46,20 @@ export function useRequest(props: UploadProps, filesDataContext: FilesDataContex } function abort(file: UploadFile): void { - const curFile = getTargetFile(file, fileList.value) - if (!curFile) { - return - } - const curAbort = aborts.get(curFile.key) - curAbort?.() - updateFileStatus(curFile, 'abort') - fileUploading.value.splice(getTargetFileIndex(curFile, fileUploading.value), 1) - aborts.delete(curFile.key) + aborts.get(file.key)?.() + props.onRequestChange && callEmit(props.onRequestChange, { status: 'abort', - file: { ...curFile }, + file: { ...file }, }) + fileUploading.value.splice(getTargetFileIndex(file, fileUploading.value), 1) + aborts.delete(file.key) + + const curFile = getTargetFile(file, fileList.value) + if (curFile) { + updateFileStatus(curFile, 'abort') + } } async function startUpload(file: UploadFile): Promise { diff --git a/packages/components/upload/src/composables/useUploadControl.ts b/packages/components/upload/src/composables/useUploadControl.ts index 1b1bccdd1..f33874dbc 100644 --- a/packages/components/upload/src/composables/useUploadControl.ts +++ b/packages/components/upload/src/composables/useUploadControl.ts @@ -10,26 +10,48 @@ import type { UploadFile } from '../types' import { type ComputedRef, watch } from 'vue' +import { useState } from '@idux/cdk/utils' + import { getTargetFile } from '../utils/files' export function useUploadControl(fileList: ComputedRef, uploadRequest: UploadRequest): void { const { startUpload, abort } = uploadRequest - watch(fileList, (currentFileList, preFileList) => { - currentFileList.forEach(file => { - const preFile = getTargetFile(file, preFileList) - - if (!preFile && file.status === 'selected') { - startUpload(file) + const [proxyedFileList, setProxyedFileList] = useState([...fileList.value]) + + watch( + fileList, + _fileList => { + setProxyedFileList([..._fileList]) + }, + { + deep: true, + }, + ) + + watch( + [proxyedFileList, () => proxyedFileList.value.length], + ([currentFileList, currentLength], [preFileList, preLength]) => { + if (currentLength === preLength) { + return } - }) - preFileList.forEach(file => { - const currentFile = getTargetFile(file, currentFileList) + currentFileList.forEach(file => { + const preFile = getTargetFile(file, preFileList) + console.log(preFile, file, currentFileList === preFileList) - if (!currentFile && file.status === 'uploading') { - abort(file) - } - }) - }) + if (!preFile && file.status === 'selected') { + startUpload(file) + } + }) + + preFileList.forEach(file => { + const currentFile = getTargetFile(file, currentFileList) + + if (!currentFile && file.status === 'uploading') { + abort(file) + } + }) + }, + ) } diff --git a/packages/components/upload/src/types.ts b/packages/components/upload/src/types.ts index f7124e4d5..029998dbd 100644 --- a/packages/components/upload/src/types.ts +++ b/packages/components/upload/src/types.ts @@ -71,7 +71,7 @@ export interface UploadRequestChangeOption { export const uploadProps = { files: { type: Array as PropType, - default: [], + default: () => [], }, accept: String, action: {