组件
<template>
<a-upload
v-model:file-list="fileList"
:maxCount="maxCount"
:listType="listType"
:multiple="multiple"
:before-upload="beforeUpload"
:customRequest="customRequest"
:progress="progress"
>
<div v-if="fileList.length < maxCount">
<a-button v-if="listType === 'text'">
<upload-outlined></upload-outlined>
Upload
</a-button>
<div v-else>
<plus-outlined />
<div style="margin-top: 8px">Upload</div>
</div>
</div>
</a-upload>
</template>
<script>
import { message, Upload } from 'ant-design-vue';
import { PlusOutlined, UploadOutlined } from '@ant-design/icons-vue';
import { computed, defineComponent, unref } from 'vue';
import { upload } from '@/api/supload';
export default defineComponent({
name: 'Supload',
components: {
PlusOutlined,
UploadOutlined,
},
// 与官网一致 =》 https://antdv.com/components/upload-cn#components-upload-demo-upload-custom-action-icon
props: {
listType: {
// 与官网一致
type: String,
default: 'picture-card',
},
maxCount: {
// 与官网一致
type: Number,
default: 2,
},
multiple: {
// 与官网一致
type: Boolean,
default: true,
},
modelValue: {
type: Array,
default: () => [],
},
validType: {
// 验证文件格式
type: Array,
default: () => ['EXCEL'],
},
isLtSize: {
// 验证文件大小
type: Number,
default: 2,
},
checkFile: {
// 是否开启后台异步校验
type: Object,
default: () => {
return { isCheck: false };
},
},
},
setup(props, { emit }) {
const { isLtSize, validType, checkFile } = props;
const progress = {
// 内置进度条样式
strokeColor: {
'0%': '#108ee9',
'100%': '#87d068',
},
strokeWidth: 3,
format: (percent) => `${parseFloat(percent.toFixed(2))}%`,
};
const fileList = computed({
// 页面 v-model 的数据
get: () => props.modelValue,
set: (val) => {
emit('update:modelValue', val);
},
});
// 上传前校验
const beforeUpload = async (file) => {
const isLt2M = file.size / 1024 / 1024 < isLtSize; // 验证文件大小,通过 isLtSize 设置大小 单位(兆)
const suffix = file.name
.substring(file.name.lastIndexOf('.') + 1)
.toUpperCase();
const isValidType = validType.includes(suffix); // 验证文件格式 数组 validType 全部大写
if (!isLt2M) {
message.error(`【${file.name}】文件大小超过限制!`);
return Upload.LIST_IGNORE;
}
if (!isValidType) {
message.error(`【${file.name}】文件格式不合法!`);
return Upload.LIST_IGNORE;
}
if (checkFile.isCheck) { // 判断是否需要通过接口校验文件
try {
const res = await checkFile.api(file.name);
if (res.code === 0 && res.msg === 'active success') {
return file;
} else {
message.error(res.msg);
return Upload.LIST_IGNORE;
}
} catch (error) {
message.error('Failed to validate file');
return Upload.LIST_IGNORE;
}
}
};
const customRequest = (options) => {
// 自定义上传方法
const formData = new FormData();
formData.append('file', options.file);
upload(formData)
.then((res) => {
if (res.code === 0) {
options.onSuccess(res, options.file);
emitIsFinsh(true);
} else {
message.error({
content: res.msg,
});
}
})
.catch((err) => {
message.error(err);
});
};
// 控制页面提交按钮 <a-button :disabled="isFinsh">提交</a-button>
// 上传完成后才能提交否则禁用
const emitIsFinsh = (val) => {
emit('update:isFinsh', val);
};
return {
fileList,
beforeUpload,
customRequest,
progress,
};
},
});
</script>
页面使用
<Supload
v-model="importFileList"
v-model:isFinsh="isFinsh"
:maxCount="2"
:validType="['PDF','EXCEL','XLSX']"
:checkFile="{
isCheck: true,
api: checkFileName,
}"
></Supload>