1. 组件功能介绍
    • 上传格式限制
    • 上传大小限制
    • 上传文件数量限制
    • 自定义上传区
    • 上传成功回调
    • 禁用上传开关与点击上传自定义事件
    • 暴露所以上传文件列表(uploadList)与当前文件数据(uploadLatestFile
  2. 组件代码Upload.vue
<template>
  <div>
    <div>
      <el-upload
        class="flx-align-center"
        :file-list="fileList"
        :multiple="multiple"
        :limit="limit"
        :disabled="disabled"
        :accept="fileType"
        :show-file-list="false"
        :http-request="handleHttpUpload"
        :before-upload="beforeUpload"
        :on-exceed="handleExceed"
      >
        <slot name="upload-btn">
          <div class="upload-content">
            <el-button type="primary" :icon="UploadFilled" plain @click="handleClick">点击上传</el-button>
          </div>
        </slot>
      </el-upload>
      <!-- 提示 -->
      <div class="upload-tip" v-if="tipShow">
        <slot name="tip">{{ tipComputed }}</slot>
      </div>
    </div>
    <div class="upload-box">
      <slot></slot>
    </div>
  </div>
</template>

<script setup lang="ts" name="UploadBasics">
import { ref, computed } from "vue";
import { UploadFilled } from "@element-plus/icons-vue";
import type { UploadUserFile } from "element-plus";
import { ElNotification } from "element-plus";
import { uploadImg } from "@/api/modules/upload";
import { getFileType } from "@/utils/assetsFile";

interface UploadFileProps {
  fileType: string;
  fileSize: number; // 允许上传文件的最大尺寸
  limit: number; // 允许上传文件的最大数量
  tipShow: boolean; // 是否显示提示
  multiple: boolean; // 是否可以多选
  fileList: UploadUserFile[];
  disabled: boolean;
  handleClick: () => void; // 点击上传按钮自定义事件, 可在禁用时触发
}

const props = withDefaults(defineProps<Partial<UploadFileProps>>(), {
  fileType: ".pdf, .jpg, .png, .jpeg",
  fileSize: 10,
  tipShow: true,
  multiple: true,
  fileList: () => [],
  disabled: false
});

// 提示
const tipComputed = computed(() => {
  const tip = props.fileType.replace(/\./g, "").replace(/,/g, "、").toUpperCase();
  return `支持${tip}格式,大小不得超过${props.fileSize}M`;
});

// 文件上传前的钩子
const beforeUpload = rawFile => {
  // 判断文件类型, 不显示小数点
  const extension = getFileType(rawFile.name, 1);
  const fileType = props.fileType.replace(/\./g, ""); // 若传入类型有小数点,替换
  const imgType = fileType.includes(extension);
  if (!imgType) {
    ElNotification({
      title: "温馨提示",
      message: "上传图片不符合所需的格式!",
      type: "warning"
    });
    return false;
  }
  // 判断大小
  if (rawFile.size / 1024 / 1024 > props.fileSize) {
    ElNotification({
      title: "温馨提示",
      message: `上传图片大小不能超过 ${props.fileSize}M!`,
      type: "warning"
    });
    return false;
  }
};

const handleExceed = () => {
  ElNotification({
    title: "温馨提示",
    message: `超出文件上传最大数量:${props.limit}`,
    type: "warning"
  });
  return false;
};

// 上传文件请求
const uploadLatestFile = ref<UploadUserFile>(); // 最近上传的文件
const uploadList = ref<UploadUserFile[]>([]); // 所有上传的文件列表

const handleHttpUpload = async options => {
  let formData = new FormData();
  formData.append("file", options.file);

  try {
// 上传请求
    const { data } = await uploadImg(formData);
    uploadLatestFile.value = {
      name: data.data.name as string,
      url: data.data.url
    };

    uploadList.value = [
      ...uploadList.value,
      {
        name: data.data.name as string,
        url: data.data.url
      }
    ];

    emits("upload-success", { uploadLatestFile: uploadLatestFile.value, uploadList: uploadList.value });
  } catch (error) {
    options.onError(error as any);
  }
};

const emits = defineEmits(["upload-success"]);

defineExpose({
  uploadList,
  uploadLatestFile
});
</script>

<style lang="scss" scoped>
// 上传按钮区
.upload-content {
  display: flex;
  flex-direction: column;
}

// 上传文件显示容器
.upload-box {
  max-height: 400px;

  // margin-top: 10px;
  overflow: auto;
}

// 提示
.upload-tip {
  display: flex;
  align-items: center;
  font-size: 12px;
  line-height: 32px;
  color: var(--el-label-color-regular);
}
</style>

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.
  • 143.
  • 144.
  • 145.
  • 146.
  • 147.
  • 148.
  • 149.
  • 150.
  • 151.
  • 152.
  • 153.
  • 154.
  • 155.
  • 156.
  • 157.
  • 158.
  • 159.
  • 160.
  • 161.
  • 162.
  • 163.
  1. 使用示例一:
  • 使用默认的上传按钮
<Upload
  ref="uploadRef"
  :file-size="20"
  :limit="10"
  :file-list="uploadItemRef?.newFileList"
  file-type="zip,png,jpg,jpeg,doc,docx,xls,xlsx,pdf,ppt,pptx"
  direction="horizontal"
>
<UploadItem ref="uploadItemRef" :file-list="fileList" :upload-list="uploadRef?.uploadList" />
</Upload>


// UploadItem 是展示内容
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 效果图展示:
    vue3+ el-upload封装上传组件_upload
  1. 使用示例二:使用自定义的上传按钮
  • Upload上传组件内部使用UploadItem展示文件,展示文件内部又有上传功能:
<Upload ref="uploadRef">
  <UploadItem :file-list="dataList" :upload-list="uploadRef?.uploadList" />
</Upload>
  • 1.
  • 2.
  • 3.
  • UploadItem.vue 内:
<div class="file-div flx-justify-between" v-for="(item, index) in list" :key="index">
    <div class="flx-align-center">
      <img :src="getFileTypeImg(item.url)" :alt="item.name" />
      <span v-if="isExt">{{ item.name }}</span>
      <!-- <span v-else>{{ item.name }}{{ getFileType(item.url) }}</span> -->
      <span v-else>{{ item.name }}</span>
    </div>

    <div class="upload-btns">
      <el-button v-if="isDown" type="primary" text @click="handleDown(item)"> 下载 </el-button>
      <Upload :tip-show="false" :multiple="false" @upload-success="uploadSuccess($event, item)">
        <template #upload-btn>
          <img src="@/assets/images/disposal/reactupload.png" alt="reactupload" class="reactupload" />
        </template>
      </Upload>
    </div>
  </div>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 效果图
    vue3+ el-upload封装上传组件_上传文件_02