feat:【antd】图片上传组件增加 modelValue 参数适配,同时支持 modelValue 和 value 参数(适配 FormCreate)

pull/217/head
puhui999 2025-09-25 11:29:10 +08:00
parent fbeeb151ff
commit 510825bb49
1 changed files with 97 additions and 13 deletions

View File

@ -6,7 +6,7 @@ import type { FileUploadProps } from './typing';
import type { AxiosProgressEvent } from '#/api/infra/file';
import { ref, toRefs, watch } from 'vue';
import { computed, ref, toRefs, watch } from 'vue';
import { IconifyIcon } from '@vben/icons';
import { $t } from '@vben/locales';
@ -22,6 +22,7 @@ defineOptions({ name: 'ImageUpload', inheritAttrs: false });
const props = withDefaults(defineProps<FileUploadProps>(), {
value: () => [],
modelValue: undefined,
directory: undefined,
disabled: false,
listType: 'picture-card',
@ -34,7 +35,12 @@ const props = withDefaults(defineProps<FileUploadProps>(), {
resultField: '',
showDescription: true,
});
const emit = defineEmits(['change', 'update:value', 'delete']);
const emit = defineEmits([
'change',
'update:value',
'update:modelValue',
'delete',
]);
const { accept, helpText, maxNumber, maxSize } = toRefs(props);
const isInnerOperate = ref<boolean>(false);
const { getStringAccept } = useUploadType({
@ -43,6 +49,16 @@ const { getStringAccept } = useUploadType({
maxNumberRef: maxNumber,
maxSizeRef: maxSize,
});
// 使 modelValue
const currentValue = computed(() => {
return props.modelValue === undefined ? props.value : props.modelValue;
});
// 使 modelValue
const isUsingModelValue = computed(() => {
return props.modelValue !== undefined;
});
const previewOpen = ref<boolean>(false); //
const previewImage = ref<string>(''); //
const previewTitle = ref<string>(''); //
@ -51,9 +67,11 @@ 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[]>([]); //
watch(
() => props.value,
currentValue,
async (v) => {
if (isInnerOperate.value) {
isInnerOperate.value = false;
@ -122,6 +140,7 @@ async function handleRemove(file: UploadFile) {
const value = getValue();
isInnerOperate.value = true;
emit('update:value', value);
emit('update:modelValue', value);
emit('change', value);
emit('delete', file);
}
@ -133,6 +152,12 @@ function handleCancel() {
}
async function beforeUpload(file: File) {
//
if (fileList.value!.length >= props.maxNumber) {
message.error($t('ui.upload.maxNumber', [props.maxNumber]));
return Upload.LIST_IGNORE;
}
const { maxSize, accept } = props;
const isAct = checkImgType(file, accept);
if (!isAct) {
@ -140,6 +165,7 @@ async function beforeUpload(file: File) {
isActMsg.value = false;
//
setTimeout(() => (isActMsg.value = true), 1000);
return Upload.LIST_IGNORE;
}
const isLt = file.size / 1024 / 1024 > maxSize;
if (isLt) {
@ -147,8 +173,12 @@ async function beforeUpload(file: File) {
isLtMsg.value = false;
//
setTimeout(() => (isLtMsg.value = true), 1000);
return Upload.LIST_IGNORE;
}
return (isAct && !isLt) || Upload.LIST_IGNORE;
//
uploadNumber.value++;
return true;
}
async function customRequest(info: UploadRequestOption<any>) {
@ -163,20 +193,59 @@ async function customRequest(info: UploadRequestOption<any>) {
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'));
//
const value = getValue();
isInnerOperate.value = true;
emit('update:value', value);
emit('change', value);
} catch (error: any) {
console.error(error);
info.onError!(error);
handleUploadError(error);
}
}
//
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: file.name,
url: fileUrl,
status: UploadResultStatus.DONE,
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);
emit('update:modelValue', value);
emit('change', value);
}
}
//
function handleUploadError(error: any) {
console.error('上传错误:', error);
message.error($t('ui.upload.uploadError'));
//
uploadNumber.value = Math.max(0, uploadNumber.value - 1);
}
function getValue() {
const list = (fileList.value || [])
.filter((item) => item?.status === UploadResultStatus.DONE)
@ -186,11 +255,26 @@ function getValue() {
}
return item?.url || item?.response?.url || item?.response;
});
// add by String
//
if (props.maxNumber === 1) {
return list.length > 0 ? list[0] : '';
const singleValue = list.length > 0 ? list[0] : '';
// modelValue
if (
isString(props.value) ||
(isUsingModelValue.value && isString(props.modelValue))
) {
return singleValue;
}
return singleValue;
}
return list;
//
if (isUsingModelValue.value) {
return Array.isArray(props.modelValue) ? list : list.join(',');
}
return Array.isArray(props.value) ? list : list.join(',');
}
</script>