最近在使用vue3写后台的时候,基本上每一两个页面就需要上传文件,重复使用elementPlus的上传组件太过于冗余,写个上传文件的组件方便使用。
<template>
<div>
<el-upload ref="uploadRef" :limit="limit" :before-upload="handleBeforeUpload" :accept="fileType" :headers="headers"
:action="url" :on-error="handleUploadError" :on-success="handleFileSuccess" :auto-upload="true" :drag="dragFlag"
:on-exceed="handleExceed">
<div v-if="dragFlag">
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
</div>
<el-button :icon="Upload" v-else>上传文件</el-button>
<template #tip>
<div class="el-upload__tip text-center" v-if="showTip">
<span> 请上传, 大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB。</b></span>
<span>格式为 <b style="color: #f56c6c">{{ fileType }} </b>的文件。</span>
<el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline"
@click="importTemplate">下载模板</el-link>
</div>
</template>
</el-upload>
</div>
</template>
<script setup>
import { ElMessage } from 'element-plus'
import { Upload } from '@element-plus/icons-vue'
const props = defineProps({
// 数量限制
limit: {
type: Number,
default: 1,
},
// 大小限制(MB)
fileSize: {
type: Number,
default: 1,
},
// 文件类型, 例如['png', 'jpg', 'jpeg']
fileType: {
type: String,
default: ".xlsx,.xls",
},
// 是否显示提示
isShowTip: {
type: Boolean,
default: true,
},
// 上传的请求头部
headers: {
required: false,
// default: { Authorization: `Bearer ${getToken()}` },
},
// 请求的url
url: {
type: String,
required: true,
// default:`${import.meta.env.VITE_APP_BASE_API}/wh/purchase/order/importData`
},
// 是否显示提示
isShowTip: {
type: Boolean,
default: true,
},
// 是否可以拖动
dragFlag: {
type: Boolean,
default: true,
}
});
const emit = defineEmits(['uploadSuccessEmits', 'importTemplateEmits']);
const uploadRef = ref(null)
const showTip = computed(() => props.isShowTip && (props.fileType || props.fileSize));
// 上传前检验文件类型和文件大小
const handleBeforeUpload = (file) => {
// 检验文件类型
let arr = props.fileType.split(',')
if (arr.length) {
let str = '.' + file.name.match(/\.([^.]+)$/)[1].toLowerCase() //匹配格式
const isTypeOk = arr.some((type) => {
if (str.indexOf(type) > -1) return true
return false
})
if (!isTypeOk) {
ElMessage.error(`文件格式不正确, 请上传${props.fileType}格式文件!`)
return false
}
}
// 检验文件大小
if (props.fileSize) {
const isLt = file.size / 1024 / 1024 < props.fileSize;
if (!isLt) {
ElMessage.error(`上传文件大小不能超过 ${props.fileSize} MB!`)
return false;
}
}
return true
}
// 上传失败时提示
const handleUploadError = () => {
ElMessage.error(`文件上传失败!`)
}
// 文件上传成功
const handleFileSuccess = (response, file, fileList) => {
// 自定义事件给父组件,由父组件处理
emit('uploadSuccessEmits', response, file, fileList);
}
// 上传超过限制
const handleExceed = () => {
ElMessage.error(`上传文件数量不能超过 ${props.limit} 个!`)
}
// 下载模板
const importTemplate = () => {
// 自定义事件给父组件,由父组件处理
emit('importTemplateEmits');
}
</script>
<style lang="scss" scoped></style>
对应的父组件直接传props里面的参数即可,上传成功与下载模板的函数由父组件进行处理。