From ba18eb37da09aa72050135b6a248f8139822cfa5 Mon Sep 17 00:00:00 2001 From: xingyu4j Date: Mon, 26 May 2025 18:46:06 +0800 Subject: [PATCH] feat: add input upload --- .../src/components/upload/file-upload.vue | 61 +++++---------- apps/web-antd/src/components/upload/helper.ts | 10 +-- .../src/components/upload/image-upload.vue | 74 ++++++------------- apps/web-antd/src/components/upload/index.ts | 1 + .../src/components/upload/input-upload.vue | 63 ++++++++++++++++ apps/web-antd/src/components/upload/typing.ts | 29 ++++++++ .../src/components/upload/use-upload.ts | 19 +++-- 7 files changed, 150 insertions(+), 107 deletions(-) create mode 100644 apps/web-antd/src/components/upload/input-upload.vue diff --git a/apps/web-antd/src/components/upload/file-upload.vue b/apps/web-antd/src/components/upload/file-upload.vue index 5423ab9a..7577eeea 100644 --- a/apps/web-antd/src/components/upload/file-upload.vue +++ b/apps/web-antd/src/components/upload/file-upload.vue @@ -2,7 +2,7 @@ import type { UploadFile, UploadProps } from 'ant-design-vue'; import type { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface'; -import type { AxiosResponse } from '@vben/request'; +import type { FileUploadProps } from './typing'; import type { AxiosProgressEvent } from '#/api/infra/file'; @@ -20,44 +20,19 @@ import { useUpload, useUploadType } from './use-upload'; defineOptions({ name: 'FileUpload', inheritAttrs: false }); -const props = withDefaults( - defineProps<{ - // 根据后缀,或者其他 - accept?: string[]; - api?: ( - file: File, - onUploadProgress?: AxiosProgressEvent, - ) => Promise>; - // 上传的目录 - directory?: string; - disabled?: boolean; - helpText?: string; - // 最大数量的文件,Infinity不限制 - maxNumber?: number; - // 文件最大多少MB - maxSize?: number; - // 是否支持多选 - multiple?: boolean; - // support xxx.xxx.xx - resultField?: string; - // 是否显示下面的描述 - showDescription?: boolean; - value?: string | string[]; - }>(), - { - value: () => [], - directory: undefined, - disabled: false, - helpText: '', - maxSize: 2, - maxNumber: 1, - accept: () => [], - multiple: false, - api: undefined, - resultField: '', - showDescription: false, - }, -); +const props = withDefaults(defineProps(), { + value: () => [], + directory: undefined, + disabled: false, + helpText: '', + maxSize: 2, + maxNumber: 1, + accept: () => [], + multiple: false, + api: undefined, + resultField: '', + showDescription: false, +}); const emit = defineEmits(['change', 'update:value', 'delete', 'returnText']); const { accept, helpText, maxNumber, maxSize } = toRefs(props); const isInnerOperate = ref(false); @@ -112,7 +87,7 @@ watch( }, ); -const handleRemove = async (file: UploadFile) => { +async function handleRemove(file: UploadFile) { if (fileList.value) { const index = fileList.value.findIndex((item) => item.uid === file.uid); index !== -1 && fileList.value.splice(index, 1); @@ -122,9 +97,9 @@ const handleRemove = async (file: UploadFile) => { emit('change', value); emit('delete', file); } -}; +} -const beforeUpload = async (file: File) => { +async function beforeUpload(file: File) { // 使用现代的Blob.text()方法替代FileReader const fileContent = await file.text(); emit('returnText', fileContent); @@ -145,7 +120,7 @@ const beforeUpload = async (file: File) => { setTimeout(() => (isLtMsg.value = true), 1000); } return (isAct && !isLt) || Upload.LIST_IGNORE; -}; +} async function customRequest(info: UploadRequestOption) { let { api } = props; diff --git a/apps/web-antd/src/components/upload/helper.ts b/apps/web-antd/src/components/upload/helper.ts index a7a67639..27313cea 100644 --- a/apps/web-antd/src/components/upload/helper.ts +++ b/apps/web-antd/src/components/upload/helper.ts @@ -1,3 +1,8 @@ +/** + * 默认图片类型 + */ +export const defaultImageAccepts = ['jpg', 'jpeg', 'png', 'gif', 'webp']; + export function checkFileType(file: File, accepts: string[]) { if (!accepts || accepts.length === 0) { return true; @@ -7,11 +12,6 @@ export function checkFileType(file: File, accepts: string[]) { return reg.test(file.name); } -/** - * 默认图片类型 - */ -export const defaultImageAccepts = ['jpg', 'jpeg', 'png', 'gif', 'webp']; - export function checkImgType( file: File, accepts: string[] = defaultImageAccepts, diff --git a/apps/web-antd/src/components/upload/image-upload.vue b/apps/web-antd/src/components/upload/image-upload.vue index 10da9086..392d47b9 100644 --- a/apps/web-antd/src/components/upload/image-upload.vue +++ b/apps/web-antd/src/components/upload/image-upload.vue @@ -2,9 +2,7 @@ import type { UploadFile, UploadProps } from 'ant-design-vue'; import type { UploadRequestOption } from 'ant-design-vue/lib/vc-upload/interface'; -import type { AxiosResponse } from '@vben/request'; - -import type { UploadListType } from './typing'; +import type { FileUploadProps } from './typing'; import type { AxiosProgressEvent } from '#/api/infra/file'; @@ -22,46 +20,20 @@ import { useUpload, useUploadType } from './use-upload'; defineOptions({ name: 'ImageUpload', inheritAttrs: false }); -const props = withDefaults( - defineProps<{ - // 根据后缀,或者其他 - accept?: string[]; - api?: ( - file: File, - onUploadProgress?: AxiosProgressEvent, - ) => Promise>; - // 上传的目录 - directory?: string; - disabled?: boolean; - helpText?: string; - listType?: UploadListType; - // 最大数量的文件,Infinity不限制 - maxNumber?: number; - // 文件最大多少MB - maxSize?: number; - // 是否支持多选 - multiple?: boolean; - // support xxx.xxx.xx - resultField?: string; - // 是否显示下面的描述 - showDescription?: boolean; - value?: string | string[]; - }>(), - { - value: () => [], - directory: undefined, - disabled: false, - listType: 'picture-card', - helpText: '', - maxSize: 2, - maxNumber: 1, - accept: () => defaultImageAccepts, - multiple: false, - api: undefined, - resultField: '', - showDescription: true, - }, -); +const props = withDefaults(defineProps(), { + value: () => [], + directory: undefined, + disabled: false, + listType: 'picture-card', + helpText: '', + maxSize: 2, + maxNumber: 1, + accept: () => defaultImageAccepts, + multiple: false, + api: undefined, + resultField: '', + showDescription: true, +}); const emit = defineEmits(['change', 'update:value', 'delete']); const { accept, helpText, maxNumber, maxSize } = toRefs(props); const isInnerOperate = ref(false); @@ -130,7 +102,7 @@ function getBase64(file: File) { }); } -const handlePreview = async (file: UploadFile) => { +async function handlePreview(file: UploadFile) { if (!file.url && !file.preview) { file.preview = await getBase64(file.originFileObj!); } @@ -141,9 +113,9 @@ const handlePreview = async (file: UploadFile) => { previewImage.value.slice( Math.max(0, previewImage.value.lastIndexOf('/') + 1), ); -}; +} -const handleRemove = async (file: UploadFile) => { +async function handleRemove(file: UploadFile) { if (fileList.value) { const index = fileList.value.findIndex((item) => item.uid === file.uid); index !== -1 && fileList.value.splice(index, 1); @@ -153,14 +125,14 @@ const handleRemove = async (file: UploadFile) => { emit('change', value); emit('delete', file); } -}; +} -const handleCancel = () => { +function handleCancel() { previewOpen.value = false; previewTitle.value = ''; -}; +} -const beforeUpload = async (file: File) => { +async function beforeUpload(file: File) { const { maxSize, accept } = props; const isAct = checkImgType(file, accept); if (!isAct) { @@ -177,7 +149,7 @@ const beforeUpload = async (file: File) => { setTimeout(() => (isLtMsg.value = true), 1000); } return (isAct && !isLt) || Upload.LIST_IGNORE; -}; +} async function customRequest(info: UploadRequestOption) { let { api } = props; diff --git a/apps/web-antd/src/components/upload/index.ts b/apps/web-antd/src/components/upload/index.ts index a66b2fca..14e57fed 100644 --- a/apps/web-antd/src/components/upload/index.ts +++ b/apps/web-antd/src/components/upload/index.ts @@ -1,2 +1,3 @@ export { default as FileUpload } from './file-upload.vue'; export { default as ImageUpload } from './image-upload.vue'; +export { default as InputUpload } from './input-upload.vue'; diff --git a/apps/web-antd/src/components/upload/input-upload.vue b/apps/web-antd/src/components/upload/input-upload.vue new file mode 100644 index 00000000..11ee4cf0 --- /dev/null +++ b/apps/web-antd/src/components/upload/input-upload.vue @@ -0,0 +1,63 @@ + +