From b3dd066d30138f4a8aa3630ccd3834bacb5b0dae Mon Sep 17 00:00:00 2001 From: sheepluo Date: Mon, 6 Nov 2023 11:13:19 +0800 Subject: [PATCH] [Upload] some features (#3566) * feat(image-viewer): support closeOnEscKeydown * feat(Upload): support imageViewerProps * feat(upload): image Upload support size limit tips * docs(upload): add docs explanation * fix(upload): max=1 and multiple=false * feat(upload): add more params to fileListDisplay * test: update snapshots * feat(upload): support cancelUploadButton/uploadButton/showImageFileName * feat(upload): image viewer * feat(upload): update api docs * feat(_common): update commmon --- src/_common | 2 +- src/image-viewer/image-viewer.en-US.md | 10 +- src/image-viewer/image-viewer.md | 8 +- src/image-viewer/image-viewer.tsx | 4 +- src/image-viewer/props.ts | 6 + src/image-viewer/type.ts | 9 +- src/image-viewer/utils.ts | 2 +- .../__snapshots__/vitest-upload.test.jsx.snap | 105 +-- src/upload/_example/file-flow-list.vue | 8 + src/upload/_example/image.vue | 14 +- src/upload/_example/img-flow-list.vue | 57 +- src/upload/constants.ts | 1 + src/upload/hooks/useUpload.ts | 2 +- src/upload/interface.ts | 2 + src/upload/props.ts | 21 +- src/upload/themes/dragger-file.tsx | 3 +- src/upload/themes/image-card.tsx | 13 +- src/upload/themes/multiple-flow-list.tsx | 90 ++- src/upload/themes/normal-file.tsx | 12 +- src/upload/type.ts | 33 +- src/upload/upload.en-US.md | 6 +- src/upload/upload.md | 8 +- src/upload/upload.tsx | 6 + test/unit/snap/__snapshots__/csr.test.js.snap | 699 ++++++++++++++++-- test/unit/snap/__snapshots__/ssr.test.js.snap | 4 +- 25 files changed, 966 insertions(+), 159 deletions(-) diff --git a/src/_common b/src/_common index a93f68dbfb..56f3acdc7c 160000 --- a/src/_common +++ b/src/_common @@ -1 +1 @@ -Subproject commit a93f68dbfb458bfca83bee1cd2216405209936d8 +Subproject commit 56f3acdc7c44c2a1dde6c74deb68f6b952de1a7d diff --git a/src/image-viewer/image-viewer.en-US.md b/src/image-viewer/image-viewer.en-US.md index 83520e7f4d..a507da3a27 100644 --- a/src/image-viewer/image-viewer.en-US.md +++ b/src/image-viewer/image-viewer.en-US.md @@ -6,19 +6,21 @@ name | type | default | description | required -- | -- | -- | -- | -- closeBtn | Boolean / Slot / Function | true | Typescript:`boolean \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-vue-next/blob/develop/src/common.ts) | N +closeOnEscKeydown | Boolean | true | trigger image viewer close event on `ESC` keydown | N closeOnOverlay | Boolean | - | \- | N draggable | Boolean | undefined | \- | N imageScale | Object | - | Typescript:`ImageScale` `interface ImageScale { max: number; min: number; step: number }`。[see more ts definition](https://github.com/Tencent/tdesign-vue-next/tree/develop/src/image-viewer/type.ts) | N images | Array | [] | Typescript:`Array` `interface ImageInfo { mainImage: string \| File; thumbnail?: string \| File; download?: boolean }`。[see more ts definition](https://github.com/Tencent/tdesign-vue-next/tree/develop/src/image-viewer/type.ts) | N -index | Number | - | `v-model:index` is supported | N -defaultIndex | Number | - | uncontrolled property | N +index | Number | 0 | `v-model:index` is supported | N +defaultIndex | Number | 0 | uncontrolled property | N mode | String | modal | options: modal/modeless | N navigationArrow | Boolean / Slot / Function | true | Typescript:`boolean \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-vue-next/blob/develop/src/common.ts) | N showOverlay | Boolean | undefined | \- | N title | String / Slot / Function | - | preview title。Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-vue-next/blob/develop/src/common.ts) | N -trigger | String / Slot / Function | - | trigger element。Typescript:`string \| TNode<{ open: () => void }>`。[see more ts definition](https://github.com/Tencent/tdesign-vue-next/blob/develop/src/common.ts) | N +trigger | String / Slot / Function | - | trigger element。Typescript:`TNode \| TNode<{ open: () => void }>`。[see more ts definition](https://github.com/Tencent/tdesign-vue-next/blob/develop/src/common.ts) | N viewerScale | Object | - | Typescript:`ImageViewerScale` `interface ImageViewerScale { minWidth: number; minHeight: number }`。[see more ts definition](https://github.com/Tencent/tdesign-vue-next/tree/develop/src/image-viewer/type.ts) | N -visible | Boolean | false | `v-model` and `v-model:visible` is supported | N +visible | Boolean | false | hide or show image viewer。`v-model` and `v-model:visible` is supported | N +defaultVisible | Boolean | false | hide or show image viewer。uncontrolled property | N zIndex | Number | - | \- | N onClose | Function | | Typescript:`(context: { trigger: 'close-btn' \| 'overlay' \| 'esc'; e: MouseEvent \| KeyboardEvent }) => void`
| N onIndexChange | Function | | Typescript:`(index: number, context: { trigger: 'prev' \| 'next' \| 'current' }) => void`
| N diff --git a/src/image-viewer/image-viewer.md b/src/image-viewer/image-viewer.md index d5a79f7007..2b38657dde 100644 --- a/src/image-viewer/image-viewer.md +++ b/src/image-viewer/image-viewer.md @@ -34,19 +34,21 @@ 名称 | 类型 | 默认值 | 说明 | 必传 -- | -- | -- | -- | -- closeBtn | Boolean / Slot / Function | true | 是否展示关闭按钮,值为 `true` 显示默认关闭按钮;值为 `false` 则不显示关闭按钮;也可以完全自定义关闭按钮。TS 类型:`boolean \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-vue-next/blob/develop/src/common.ts) | N +closeOnEscKeydown | Boolean | true | 按下 ESC 时是否触发图片预览器关闭事件 | N closeOnOverlay | Boolean | - | 是否在点击遮罩层时,触发预览关闭 | N draggable | Boolean | undefined | 是否允许拖拽调整位置。`mode=modal` 时,默认不允许拖拽;`mode=modeless` 时,默认允许拖拽 | N imageScale | Object | - | 图片缩放相关配置。`imageScale.max` 缩放的最大比例;`imageScale.min` 缩放的最小比例;`imageScale.step` 缩放的步长速度。TS 类型:`ImageScale` `interface ImageScale { max: number; min: number; step: number }`。[详细类型定义](https://github.com/Tencent/tdesign-vue-next/tree/develop/src/image-viewer/type.ts) | N images | Array | [] | 图片数组。`mainImage` 表示主图,必传;`thumbnail` 表示缩略图,如果不存在,则使用主图显示;`download` 是否允许下载图片,默认允许下载。示例: `['img_url_1', 'img_url_2']`,`[{ thumbnail: 'small_image_url', mainImage: 'big_image_url', download: false }]`。TS 类型:`Array` `interface ImageInfo { mainImage: string \| File; thumbnail?: string \| File; download?: boolean }`。[详细类型定义](https://github.com/Tencent/tdesign-vue-next/tree/develop/src/image-viewer/type.ts) | N -index | Number | - | 当前预览图片所在的下标。支持语法糖 `v-model:index` | N -defaultIndex | Number | - | 当前预览图片所在的下标。非受控属性 | N +index | Number | 0 | 当前预览图片所在的下标。支持语法糖 `v-model:index` | N +defaultIndex | Number | 0 | 当前预览图片所在的下标。非受控属性 | N mode | String | modal | 模态预览(modal)和非模态预览(modeless)。可选项:modal/modeless | N navigationArrow | Boolean / Slot / Function | true | 切换预览图片的左图标,可自定义。TS 类型:`boolean \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-vue-next/blob/develop/src/common.ts) | N showOverlay | Boolean | undefined | 是否显示遮罩层。`mode=modal` 时,默认显示;`mode=modeless` 时,默认不显示 | N title | String / Slot / Function | - | 预览标题。TS 类型:`string \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-vue-next/blob/develop/src/common.ts) | N -trigger | String / Slot / Function | - | 触发图片预览的元素,可能是一个预览按钮,可能是一张缩略图,完全自定义。TS 类型:`string \| TNode<{ open: () => void }>`。[通用类型定义](https://github.com/Tencent/tdesign-vue-next/blob/develop/src/common.ts) | N +trigger | String / Slot / Function | - | 触发图片预览的元素,可能是一个预览按钮,可能是一张缩略图,完全自定义。TS 类型:`TNode \| TNode<{ open: () => void }>`。[通用类型定义](https://github.com/Tencent/tdesign-vue-next/blob/develop/src/common.ts) | N viewerScale | Object | - | 限制预览器缩放的最小宽度和最小高度,仅 `mode=modeless` 时有效。TS 类型:`ImageViewerScale` `interface ImageViewerScale { minWidth: number; minHeight: number }`。[详细类型定义](https://github.com/Tencent/tdesign-vue-next/tree/develop/src/image-viewer/type.ts) | N visible | Boolean | false | 隐藏/显示预览。支持语法糖 `v-model` 或 `v-model:visible` | N +defaultVisible | Boolean | false | 隐藏/显示预览。非受控属性 | N zIndex | Number | - | 层级,默认为 2000 | N onClose | Function | | TS 类型:`(context: { trigger: 'close-btn' \| 'overlay' \| 'esc'; e: MouseEvent \| KeyboardEvent }) => void`
关闭时触发,事件参数包含触发关闭的来源:关闭按钮、遮罩层、ESC 键 | N onIndexChange | Function | | TS 类型:`(index: number, context: { trigger: 'prev' \| 'next' \| 'current' }) => void`
预览图片切换时触发,`context.prev` 切换到上一张图片,`context.next` 切换到下一张图片 | N diff --git a/src/image-viewer/image-viewer.tsx b/src/image-viewer/image-viewer.tsx index 9282cdaa8c..b81077f1f7 100644 --- a/src/image-viewer/image-viewer.tsx +++ b/src/image-viewer/image-viewer.tsx @@ -110,7 +110,9 @@ export default defineComponent({ onZoomOut(); break; case EVENT_CODE.esc: - onClose({ e, trigger: 'esc' }); + if (props.closeOnEscKeydown) { + onClose({ e, trigger: 'esc' }); + } break; default: break; diff --git a/src/image-viewer/props.ts b/src/image-viewer/props.ts index 3106a53295..c736635386 100644 --- a/src/image-viewer/props.ts +++ b/src/image-viewer/props.ts @@ -13,6 +13,11 @@ export default { type: [Boolean, Function] as PropType, default: true as TdImageViewerProps['closeBtn'], }, + /** 按下 ESC 时是否触发图片预览器关闭事件 */ + closeOnEscKeydown: { + type: Boolean, + default: true, + }, /** 是否在点击遮罩层时,触发预览关闭 */ closeOnOverlay: Boolean, /** 是否允许拖拽调整位置。`mode=modal` 时,默认不允许拖拽;`mode=modeless` 时,默认允许拖拽 */ @@ -37,6 +42,7 @@ export default { /** 当前预览图片所在的下标,非受控属性 */ defaultIndex: { type: Number, + default: 0, }, /** 模态预览(modal)和非模态预览(modeless) */ mode: { diff --git a/src/image-viewer/type.ts b/src/image-viewer/type.ts index fc43edd45b..8b65c81d56 100644 --- a/src/image-viewer/type.ts +++ b/src/image-viewer/type.ts @@ -12,6 +12,11 @@ export interface TdImageViewerProps { * @default true */ closeBtn?: boolean | TNode; + /** + * 按下 ESC 时是否触发图片预览器关闭事件 + * @default true + */ + closeOnEscKeydown?: boolean; /** * 是否在点击遮罩层时,触发预览关闭 */ @@ -31,10 +36,12 @@ export interface TdImageViewerProps { images?: Array; /** * 当前预览图片所在的下标 + * @default 0 */ index?: number; /** * 当前预览图片所在的下标,非受控属性 + * @default 0 */ defaultIndex?: number; /** @@ -58,7 +65,7 @@ export interface TdImageViewerProps { /** * 触发图片预览的元素,可能是一个预览按钮,可能是一张缩略图,完全自定义 */ - trigger?: string | TNode<{ open: () => void }>; + trigger?: TNode | TNode<{ open: () => void }>; /** * 限制预览器缩放的最小宽度和最小高度,仅 `mode=modeless` 时有效 */ diff --git a/src/image-viewer/utils.ts b/src/image-viewer/utils.ts index a8ff253f67..bf2d013b6a 100644 --- a/src/image-viewer/utils.ts +++ b/src/image-viewer/utils.ts @@ -33,7 +33,7 @@ export const downloadFile = function (imgSrc: string) { }; const isImageInfo = (image: string | File | ImageInfo): image is ImageInfo => { - return !isString(image) && !(image instanceof File); + return !!image && !isString(image) && !(image instanceof File); }; export const formatImages = (images: TdImageViewerProps['images']): ImageInfo[] => { diff --git a/src/upload/__tests__/__snapshots__/vitest-upload.test.jsx.snap b/src/upload/__tests__/__snapshots__/vitest-upload.test.jsx.snap index 2dbf2f442a..c9764537de 100644 --- a/src/upload/__tests__/__snapshots__/vitest-upload.test.jsx.snap +++ b/src/upload/__tests__/__snapshots__/vitest-upload.test.jsx.snap @@ -159,6 +159,7 @@ exports[`Upload Component > props.draggable: theme=image & draggable=true, fail + `; @@ -326,6 +327,7 @@ exports[`Upload Component > props.draggable: theme=image & draggable=true, progr + `; @@ -488,6 +490,7 @@ exports[`Upload Component > props.draggable: theme=image & draggable=true, succe + `; @@ -650,6 +653,7 @@ exports[`Upload Component > props.draggable: theme=image & draggable=true, succe + `; @@ -783,6 +787,7 @@ exports[`Upload Component > props.draggable: theme=image & draggable=true, waiti + `; @@ -1084,6 +1089,7 @@ exports[`Upload Component > props.theme: theme=file-flow works fine 1`] = ` + `; @@ -1206,7 +1212,7 @@ exports[`Upload Component > props.theme: theme=image-flow works fine 1`] = `
- + @@ -1226,8 +1232,20 @@ exports[`Upload Component > props.theme: theme=image-flow works fine 1`] = `

+ + + img.txt

@@ -1331,8 +1349,20 @@ exports[`Upload Component > props.theme: theme=image-flow works fine 1`] = `

+ + + img1.txt

@@ -1436,8 +1466,20 @@ exports[`Upload Component > props.theme: theme=image-flow works fine 1`] = `

+ + + img2.txt

@@ -1471,29 +1513,7 @@ exports[`Upload Component > props.theme: theme=image-flow works fine 1`] = `
- - - - - - - - + @@ -1513,8 +1533,9 @@ exports[`Upload Component > props.theme: theme=image-flow works fine 1`] = `

+ img3.txt

@@ -1561,29 +1582,7 @@ exports[`Upload Component > props.theme: theme=image-flow works fine 1`] = `
- - - - - - - - + @@ -1603,8 +1602,9 @@ exports[`Upload Component > props.theme: theme=image-flow works fine 1`] = `

+ img4.txt

@@ -1621,5 +1621,6 @@ exports[`Upload Component > props.theme: theme=image-flow works fine 1`] = ` + `; diff --git a/src/upload/_example/file-flow-list.vue b/src/upload/_example/file-flow-list.vue index 5191f9a3fa..57ffd117ca 100644 --- a/src/upload/_example/file-flow-list.vue +++ b/src/upload/_example/file-flow-list.vue @@ -25,6 +25,7 @@ :allow-upload-duplicate-file="allowUploadDuplicateFile" :is-batch-upload="isBatchUpload" :upload-all-files-in-one-request="uploadAllFilesInOneRequest" + :format-response="formatResponse" > @@ -41,4 +42,11 @@ const showThumbnail = ref(false); const allowUploadDuplicateFile = ref(false); const isBatchUpload = ref(false); const uploadAllFilesInOneRequest = ref(false); + +const formatResponse = (res) => { + if (!res) { + return { status: 'fail', error: '上传失败,原因:文件过大或网络不通' }; + } + return res; +}; diff --git a/src/upload/_example/image.vue b/src/upload/_example/image.vue index a3502816fb..90e962e411 100644 --- a/src/upload/_example/image.vue +++ b/src/upload/_example/image.vue @@ -1,6 +1,7 @@