| | |
| | | maxSizeRef: maxSize, |
| | | }); |
| | | |
| | | /** 计算当前绑定的值,优先使用 modelValue */ |
| | | const currentValue = computed(() => { |
| | | return props.modelValue === undefined ? props.value : props.modelValue; |
| | | }); |
| | | |
| | | /** 判断是否使用 modelValue */ |
| | | const isUsingModelValue = computed(() => { |
| | | return props.modelValue !== undefined; |
| | | }); |
| | | |
| | | const fileList = ref<UploadProps['fileList']>([]); |
| | | const isLtMsg = ref<boolean>(true); // 文件大小错误提示 |
| | | const isActMsg = ref<boolean>(true); // 文件类型错误提示 |
| | | const isFirstRender = ref<boolean>(true); // 是否第一次渲染 |
| | | const uploadNumber = ref<number>(0); // 上传文件计数器 |
| | | const uploadList = ref<any[]>([]); // 临时上传列表 |
| | | const isLtMsg = ref<boolean>(true); |
| | | const isActMsg = ref<boolean>(true); |
| | | const isFirstRender = ref<boolean>(true); |
| | | const uploadNumber = ref<number>(0); |
| | | const uploadList = ref<any[]>([]); |
| | | |
| | | watch( |
| | | currentValue, |
| | |
| | | function handleUploadError(error: any) { |
| | | console.error('上传错误:', error); |
| | | message.error($t('ui.upload.uploadError')); |
| | | // 上传失败时减少计数器 |
| | | uploadNumber.value = Math.max(0, uploadNumber.value - 1); |
| | | } |
| | | |
| | | /** |
| | | * 上传前校验 |
| | | * @param file 待上传的文件 |
| | | * @returns 是否允许上传 |
| | | */ |
| | | async function beforeUpload(file: File) { |
| | | // 检查文件数量限制 |
| | | if (fileList.value!.length >= props.maxNumber) { |
| | | message.error($t('ui.upload.maxNumber', [props.maxNumber])); |
| | | return Upload.LIST_IGNORE; |
| | |
| | | if (!isAct) { |
| | | message.error($t('ui.upload.acceptUpload', [accept])); |
| | | isActMsg.value = false; |
| | | // 防止弹出多个错误提示 |
| | | setTimeout(() => (isActMsg.value = true), 1000); |
| | | return Upload.LIST_IGNORE; |
| | | } |
| | |
| | | if (isLt) { |
| | | message.error($t('ui.upload.maxSizeMultiple', [maxSize])); |
| | | isLtMsg.value = false; |
| | | // 防止弹出多个错误提示 |
| | | setTimeout(() => (isLtMsg.value = true), 1000); |
| | | return Upload.LIST_IGNORE; |
| | | } |
| | | |
| | | // 只有在验证通过后才增加计数器 |
| | | uploadNumber.value++; |
| | | if (props.returnText) { |
| | | const fileContent = await file.text(); |
| | |
| | | return true; |
| | | } |
| | | |
| | | /** 自定义上传请求 */ |
| | | async function customRequest(info: UploadRequestOption) { |
| | | let { api } = props; |
| | | if (!api || !isFunction(api)) { |
| | | api = useUpload(props.directory).httpRequest; |
| | | } |
| | | try { |
| | | // 上传文件 |
| | | const progressEvent: AxiosProgressEvent = (e) => { |
| | | const percent = Math.trunc((e.loaded / e.total!) * 100); |
| | | info.onProgress!({ percent }); |
| | | }; |
| | | const res = await api?.(info.file as File, progressEvent); |
| | | |
| | | // 处理上传成功后的逻辑 |
| | | handleUploadSuccess(res, info.file as File); |
| | | |
| | | info.onSuccess!(res); |
| | | message.success($t('ui.upload.uploadSuccess')); |
| | | } catch (error: any) { |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 处理上传成功 |
| | | * @param res 上传响应结果 |
| | | * @param file 上传的文件 |
| | | */ |
| | | function handleUploadSuccess(res: any, file: File) { |
| | | // 删除临时文件 |
| | | const index = fileList.value?.findIndex((item) => item.name === file.name); |
| | | if (index !== -1) { |
| | | fileList.value?.splice(index!, 1); |
| | | } |
| | | |
| | | // 添加到临时上传列表 |
| | | const fileUrl = res?.url || res?.data || res; |
| | | uploadList.value.push({ |
| | | name: res?.name || file.name, |
| | |
| | | uid: file.name + Date.now(), |
| | | }); |
| | | |
| | | // 检查是否所有文件都上传完成 |
| | | if (uploadList.value.length >= uploadNumber.value) { |
| | | fileList.value?.push(...uploadList.value); |
| | | uploadList.value = []; |
| | | uploadNumber.value = 0; |
| | | |
| | | // 更新值 |
| | | const value = getValue(); |
| | | isInnerOperate.value = true; |
| | | emit('update:value', value); |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 获取当前文件列表的值 |
| | | * @returns 文件 URL 列表或字符串 |
| | | */ |
| | | function getValue() { |
| | | const list = (fileList.value || []) |
| | | .filter((item) => item?.status === UploadResultStatus.DONE) |
| | |
| | | return props.valuePrefix ? `${props.valuePrefix}${val}` : val; |
| | | }); |
| | | |
| | | // 单个文件的情况,根据输入参数类型决定返回格式 |
| | | if (props.maxNumber === 1) { |
| | | const singleValue = list.length > 0 ? list[0] : ''; |
| | | // 如果原始值是字符串或 modelValue 是字符串,返回字符串 |
| | | if ( |
| | | isString(props.value) || |
| | | (isUsingModelValue.value && isString(props.modelValue)) |
| | |
| | | return singleValue; |
| | | } |
| | | |
| | | // 多文件情况,根据输入参数类型决定返回格式 |
| | | if (isUsingModelValue.value) { |
| | | return Array.isArray(props.modelValue) ? list : list.join(','); |
| | | } |
| | |
| | | </style> |
| | | |
| | | <style> |
| | | /* 文件上传列表显示手型光标样式失效。不知道为啥. 先这里加上 */ |
| | | .ant-upload-list-text .ant-upload-list-item { |
| | | cursor: pointer; |
| | | } |