vue3基于elementPlus对于上传文件的二次封装

最近在使用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里面的参数即可,上传成功与下载模板的函数由父组件进行处理。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值