vue 3.0 ant-design-vue 3.2.16 upload组件 二次封装

<template>
  <div class="a-upload-container">
    <a-upload
      v-model:file-list="fileListModel"
      :maxCount="maxCount"
      :listType="listType"
      :multiple="multiple"
      :before-upload="beforeUpload"
      :customRequest="customRequest"
      :showUploadList="showUploadList"
      :progress="progress"
    >
      <div v-if="fileListModel.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>
      <template
        #iconRender="{ file: UploadFile }"
        v-if="customIconRender.isCustom"
      >
        <img
          v-if="handelFileSuffix(UploadFile.name) === 'PDF'"
          src="@/assets/bulkUpload/pdf.png"
        />
        <img
          v-if="['EXCEL', 'XLSX'].includes(handelFileSuffix(UploadFile.name))"
          src="@/assets/bulkUpload/excel.png"
        />
        <span v-else>
          {{ handelFileSuffix(UploadFile.name) }}
        </span>
      </template>
    </a-upload>
    <s-modal
      :width="800"
      v-model:visible="visible"
      title="preview"
      :footer="null"
    >
      <div style="height: 500px">
        <iframe
          class="child"
          :src="fileUrl"
          style="width: 100%; height: 100%"
          frameborder="0"
        ></iframe>
      </div>
    </s-modal>
  </div>
</template>
<script>
import { message, Upload } from 'ant-design-vue';
import {
  PlusOutlined,
  UploadOutlined,
  LoadingOutlined,
} from '@ant-design/icons-vue';
import { computed, defineComponent } from 'vue';
import { upload } from '@/api/supload';
export default defineComponent({
  name: 'Supload',
  components: {
    PlusOutlined,
    UploadOutlined,
    LoadingOutlined,
  },
  //  与官网一致 =》 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,
    },
    showUploadList: {
      // 与官网一致
      //详情页面时配置  :showUploadList="{  showRemoveIcon: false }" 防止删除文件
      type: Object,
      default: {
        showPreviewIcon: true,
        showRemoveIcon: true,
      },
    },
    modelValue: {
      type: Array,
      default: () => [],
    },
    validType: {
      // 验证文件格式
      type: Array,
      default: () => ['PDF', 'EXCEL', 'XLSX'],
    },
    isLtSize: {
      // 验证文件大小
      type: Number,
      default: 2,
    },
    checkFile: {
      // 是否开启后台异步校验
      type: Object,
      default: () => {
        return { isCheck: false };
      },
    },
    customIconRender: {
      // 是否展示对应图片
      type: Object,
      default: () => {
        return {
          isCustom: false,
        };
      },
    },
    maxChooseCount: {
      type: Number,
      default: 3,
    },
  },
  setup(props, { emit }) {
    const { isLtSize, validType, checkFile, maxCount, maxChooseCount } = props;
    const visible = ref(false);
    const fileUrl = ref('');
    const openFile = ref('');
    const progress = {
      // 内置进度条样式
      strokeColor: {
        '0%': '#108ee9',
        '100%': '#87d068',
      },
      strokeWidth: 3,
      format: (percent) => `${parseFloat(percent.toFixed(2))}%`,
    };
    const fileListModel = computed({
      // 页面 v-model 的数据
      get: () => props.modelValue,
      set: (val) => {
        emit('update:modelValue', val);
      },
    });
    // 上传前校验
    const beforeUpload = async (file, fileList) => {
      const dataList = JSON.parse(JSON.stringify(fileListModel.value));
      let index = dataList.findIndex((item) => item.name === file.name); // 验证文件名是否重复
      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 (fileList.length > maxChooseCount && file.name === fileList[0].name) {
        message.error(`文件超出最大选择限制!`);
        return Upload.LIST_IGNORE;
      }
      if (dataList > maxCount && file.name === fileList[0].name) {
        message.error(`文件数量超出限制!`);
        return Upload.LIST_IGNORE;
      }
      if (index > -1) {
        message.error(`${file.name}】文件名重复!`);
        return Upload.LIST_IGNORE;
      }
      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) => {
      // 自定义上传方法
      emitIsFinsh(false);
      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);
    };
    // 预览
    const handlePreview = (file) => {
      const { data } = file.response;
      openFile.value = file;
      if (['XLSX', 'EXCEL'].includes(handelFileSuffix(file.name))) {
        window.open(data.url);
        return;
      }
      if (data.url) {
        visible.value = true;
        fileUrl.value = data.url;
      }
    };
    // 取文件后缀名方法
    const handelFileSuffix = (name) => {
      return name.substring(name.lastIndexOf('.') + 1).toUpperCase();
    };
    return {
      fileListModel,
      visible,
      fileUrl,
      beforeUpload,
      customRequest,
      progress,
      // handlePreview, @preview="handlePreview"
      handelFileSuffix,
      openFile,
    };
  },
});
</script>

<style lang="scss" scoped>
.a-upload-container {
  .icon {
    width: 50px;
    margin: 0 auto;
  }
}
</style>
 <Supload
   v-model="importFileList"
      v-model:isFinsh="isFinsh"
      :checkFile="{
        isCheck: true,
        api: checkFileName,
      }"
    ></Supload>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

web_Hsir

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值