From b94c8c33330afa46e0d303bc20bb5496484264ed Mon Sep 17 00:00:00 2001 From: Zhousg Date: Sat, 20 May 2023 19:15:29 +0800 Subject: [PATCH] feat(Uploader): add reupload (#11854) * feat(Uploader): add reupload * feat(Uploader): add reupload * Update packages/vant/src/uploader/README.md Co-authored-by: neverland * Update packages/vant/src/uploader/README.zh-CN.md Co-authored-by: neverland --------- Co-authored-by: neverland --- packages/vant/src/uploader/README.md | 22 ++++++++ packages/vant/src/uploader/README.zh-CN.md | 36 ++++++++++--- packages/vant/src/uploader/Uploader.tsx | 43 +++++++++++++--- .../vant/src/uploader/UploaderPreviewItem.tsx | 9 ++-- packages/vant/src/uploader/demo/index.vue | 8 +++ .../test/__snapshots__/demo-ssr.spec.ts.snap | 50 +++++++++++++++++++ .../test/__snapshots__/demo.spec.ts.snap | 34 +++++++++++++ packages/vant/src/uploader/test/index.spec.ts | 28 ++++++++++- packages/vant/src/uploader/types.ts | 1 + 9 files changed, 214 insertions(+), 17 deletions(-) diff --git a/packages/vant/src/uploader/README.md b/packages/vant/src/uploader/README.md index fafcbf978..676fc2518 100644 --- a/packages/vant/src/uploader/README.md +++ b/packages/vant/src/uploader/README.md @@ -298,6 +298,26 @@ export default { }; ``` +### Open Reupload + +```html + +``` + +```ts +import { ref } from 'vue'; + +export default { + setup() { + const fileList = ref([ + { url: 'https://fastly.jsdelivr.net/npm/@vant/assets/leaf.jpeg' }, + ]); + + return { fileList }; + }, +}; +``` + ## API ### Props @@ -315,6 +335,7 @@ export default { | disabled | Whether to disabled the upload | _boolean_ | `false` | | readonly | Whether to make upload area readonly | _boolean_ | `false` | | deletable | Whether to show delete icon | _boolean_ | `true` | +| reupload | Whether to enable reupload, if enabled, the image preview will be disabled | _boolean_ | `false` | | show-upload | Whether to show upload area | _boolean_ | `true` | | lazy-load | Whether to enable lazy load, should register [Lazyload](#/en-US/lazyload) component | _boolean_ | `false` | | capture | Capture, can be set to `camera` | _string_ | - | @@ -337,6 +358,7 @@ export default { | oversize | Emitted when file size over limit | Same as after-read | | click-upload | Emitted when click upload area | _event: MouseEvent_ | | click-preview | Emitted when preview image is clicked | Same as after-read | +| click-reupload | Emitted when reupload image is clicked | Same as after-read | | close-preview | Emitted when the full screen image preview is closed | - | | delete | Emitted when preview file is deleted | Same as after-read | diff --git a/packages/vant/src/uploader/README.zh-CN.md b/packages/vant/src/uploader/README.zh-CN.md index e22e81a3a..51bcb8f47 100644 --- a/packages/vant/src/uploader/README.zh-CN.md +++ b/packages/vant/src/uploader/README.zh-CN.md @@ -317,6 +317,26 @@ export default { }; ``` +### 开启覆盖上传 + +```html + +``` + +```ts +import { ref } from 'vue'; + +export default { + setup() { + const fileList = ref([ + { url: 'https://fastly.jsdelivr.net/npm/@vant/assets/leaf.jpeg' }, + ]); + + return { fileList }; + }, +}; +``` + ## API ### Props @@ -334,6 +354,7 @@ export default { | disabled | 是否禁用文件上传 | _boolean_ | `false` | | readonly | 是否将上传区域设置为只读状态 | _boolean_ | `false` | | deletable | 是否展示删除按钮 | _boolean_ | `true` | +| reupload | 是否开启覆盖上传,开启后会关闭图片预览 | _boolean_ | `false` | | show-upload | 是否展示上传区域 | _boolean_ | `true` | | lazy-load | 是否开启图片懒加载,须配合 [Lazyload](#/zh-CN/lazyload) 组件使用 | _boolean_ | `false` | | capture | 图片选取模式,可选值为 `camera` (直接调起摄像头) | _string_ | - | @@ -351,13 +372,14 @@ export default { ### Events -| 事件名 | 说明 | 回调参数 | -| ------------- | ---------------------- | ------------------- | -| oversize | 文件大小超过限制时触发 | 同 `after-read` | -| click-upload | 点击上传区域时触发 | _event: MouseEvent_ | -| click-preview | 点击预览图时触发 | 同 `after-read` | -| close-preview | 关闭全屏图片预览时触发 | - | -| delete | 删除文件预览时触发 | 同 `after-read` | +| 事件名 | 说明 | 回调参数 | +| -------------- | ---------------------- | ------------------- | +| oversize | 文件大小超过限制时触发 | 同 `after-read` | +| click-upload | 点击上传区域时触发 | _event: MouseEvent_ | +| click-preview | 点击预览图时触发 | 同 `after-read` | +| click-reupload | 点击覆盖上传时触发 | 同 `after-read` | +| close-preview | 关闭全屏图片预览时触发 | - | +| delete | 删除文件预览时触发 | 同 `after-read` | ### Slots diff --git a/packages/vant/src/uploader/Uploader.tsx b/packages/vant/src/uploader/Uploader.tsx index 0d7bd2637..df78937f6 100644 --- a/packages/vant/src/uploader/Uploader.tsx +++ b/packages/vant/src/uploader/Uploader.tsx @@ -65,6 +65,7 @@ export const uploaderProps = { uploadIcon: makeStringProp('photograph'), uploadText: String, deletable: truthProp, + reupload: Boolean, afterRead: Function as PropType, showUpload: truthProp, modelValue: makeArrayProp(), @@ -95,12 +96,14 @@ export default defineComponent({ 'clickUpload', 'closePreview', 'clickPreview', + 'clickReupload', 'update:modelValue', ], setup(props, { emit, slots }) { const inputRef = ref(); const urls: string[] = []; + const reuploadIndex = ref(-1); const getDetail = (index = props.modelValue.length) => ({ name: props.name, @@ -133,7 +136,14 @@ export default defineComponent({ } } items = reactive(items); - emit('update:modelValue', [...props.modelValue, ...toArray(items)]); + if (reuploadIndex.value > -1) { + const arr = [...props.modelValue]; + arr.splice(reuploadIndex.value, 1, items as UploaderFileListItem); + emit('update:modelValue', arr); + reuploadIndex.value = -1; + } else { + emit('update:modelValue', [...props.modelValue, ...toArray(items)]); + } if (props.afterRead) { props.afterRead(items, getDetail()); @@ -265,10 +275,17 @@ export default defineComponent({ emit('delete', item, getDetail(index)); }; + const reuploadImage = (index: number) => { + // eslint-disable-next-line no-use-before-define + chooseFile(); + reuploadIndex.value = index; + }; + const renderPreviewItem = (item: UploaderFileListItem, index: number) => { const needPickData = [ 'imageFit', 'deletable', + 'reupload', 'previewSize', 'beforeDelete', ] as const; @@ -283,9 +300,16 @@ export default defineComponent({ v-slots={pick(slots, ['preview-cover', 'preview-delete'])} item={item} index={index} - onClick={() => emit('clickPreview', item, getDetail(index))} + onClick={() => + emit( + props.reupload ? 'clickReupload' : 'clickPreview', + item, + getDetail(index) + ) + } onDelete={() => deleteFile(item, index)} onPreview={() => previewImage(item)} + onReupload={() => reuploadImage(index)} {...pick(props, ['name', 'lazyLoad'])} {...previewData} /> @@ -301,10 +325,13 @@ export default defineComponent({ const onClickUpload = (event: MouseEvent) => emit('clickUpload', event); const renderUpload = () => { - if (props.modelValue.length >= +props.maxCount) { + if (props.modelValue.length >= +props.maxCount && !props.reupload) { return; } + const hideUploader = + props.modelValue.length >= +props.maxCount && props.reupload; + const Input = props.readonly ? null : ( @@ -320,7 +347,11 @@ export default defineComponent({ if (slots.default) { return ( -
+
{slots.default()} {Input}
@@ -329,7 +360,7 @@ export default defineComponent({ return (
, lazyLoad: Boolean, deletable: Boolean, + reupload: Boolean, previewSize: [Number, String, Array] as PropType< Numeric | [Numeric, Numeric] >, beforeDelete: Function as PropType, }, - emits: ['delete', 'preview'], + emits: ['delete', 'preview', 'reupload'], setup(props, { emit, slots }) { const renderMask = () => { @@ -71,6 +72,8 @@ export default defineComponent({ const onPreview = () => emit('preview'); + const onReupload = () => emit('reupload'); + const renderDeleteIcon = () => { if (props.deletable && props.item.status !== 'uploading') { const slot = slots['preview-delete']; @@ -104,7 +107,7 @@ export default defineComponent({ }; const renderPreview = () => { - const { item, lazyLoad, imageFit, previewSize } = props; + const { item, lazyLoad, imageFit, previewSize, reupload } = props; if (isImageFile(item)) { return ( @@ -116,7 +119,7 @@ export default defineComponent({ width={Array.isArray(previewSize) ? previewSize[0] : previewSize} height={Array.isArray(previewSize) ? previewSize[1] : previewSize} lazyLoad={lazyLoad} - onClick={onPreview} + onClick={reupload ? onReupload : onPreview} /> ); } diff --git a/packages/vant/src/uploader/demo/index.vue b/packages/vant/src/uploader/demo/index.vue index f69fe2e9f..cf2c784a8 100644 --- a/packages/vant/src/uploader/demo/index.vue +++ b/packages/vant/src/uploader/demo/index.vue @@ -25,6 +25,7 @@ const t = useTranslate({ previewCover: '自定义预览样式', deleteMessage: '删除前置处理', customPreviewImage: '自定义单个图片预览', + reupload: '开启覆盖上传', }, 'en-US': { status: 'Upload Status', @@ -44,6 +45,7 @@ const t = useTranslate({ previewCover: 'Preview Cover', deleteMessage: 'Before Delete', customPreviewImage: 'Custom single preview image', + reupload: 'Open Reupload', }, }); @@ -142,6 +144,8 @@ const onOversize = (file: UploaderFileListItem, detail: unknown) => { console.log(file, detail); showToast(t('overSizeTip')); }; + +const fileList6 = ref([{ url: cdnURL('leaf.jpeg') }]);