Vue custom implementation file upload (encapsulation component)

Not much to say, directly upload the code, here it is directly encapsulated into a component, which can be reused

insert image description here

  • Attachments will only be uploaded when upload is clicked, and fileVoList can be passed as a parameter to the backend, which is an array of attachment lists
<template>
  <el-upload
    class="upload-demo"
    ref="upload"
    multiple
    action="/"
    :on-preview="handlePreview"
    :on-remove="handleRemove"
    :on-change="fileLimit"
    :file-list="accessoryList"
    :http-request="submitAccessoryList"
    :on-success="upSuccessAccessory"
    :auto-upload="false"
  >
    <el-button slot="trigger" size="small" type="primary">请选择文件</el-button>
    <el-button
      style="margin-left: 10px"
      size="small"
      type="linear"
      @click="submitUpload"
      >上传</el-button
    >
    <el-button
      style="margin-left: 10px"
      size="small"
      type="default"
      @click="(e) => (accessoryList = [])"
      >取消上传</el-button
    >
    <span style="color: red">(温馨提示:单个文件不超过5M)</span>
  </el-upload>
</template>

<script>
import {
    
     uploadAttachment } from "@/api";

export default {
    
    
  props: {
    
    
    //上传附件action的url,如果是自定义调接口上传文件此参数可以不传
    action: {
    
    
      type: String,
      default: () => "/",
    },
  },
  data() {
    
    
    return {
    
    
      accessoryList: [], //附件列表
      fileVoList: [], //上传接口需要的附件列表
      callback: null
    };
  },
  methods: {
    
    
    //点击附件内容
    handlePreview(file) {
    
    
      console.log("file是:", file.name);
    },
    //附件移除
    handleRemove(file) {
    
    
      this.$message.warning(`已移除${
      
      file.name}`);
      const index = this.fileVoList.findIndex(
        (item) => item.fileName == file.name
      );
      this.fileVoList.splice(index, 1);
      this.$emit("makeSure", this.fileVoList);
    },
    //自定义上传,如果是传action这里可以删掉这个方法,同时也删掉 :http-request这个属性
    async submitAccessoryList(param) {
    
    
      try {
    
    
        let formData = new FormData();
        formData.append("file", param.file);
        const res = await uploadAttachment(formData);
        this.fileVoList.push(res.data);

        if (this.fileVoList.length === this.accessoryList.length && typeof this.callback === 'function') {
    
    
            this.callback();
        }
      } catch (e) {
    
    
        console.log("上传失败", e);
      }
    },
    //确定上传附件
    submitUpload() {
    
    
      this.test().then((res) => {
    
    
        if (res.code == 200) {
    
    
            this.callback = () => {
    
    
            	//这里是自定义附件列表的格式参数,因为我是需要这个样子的参数,所以重新格式化一下
                this.fileVoList = this.fileVoList.map((item) => {
    
    
                return {
    
    
                    fileName: item.name,
                    fileSize: item.size,
                    fileUrl: item.url,
                    id: item.id,
                };
                });
                this.$emit("makeSure", this.fileVoList); //这里调用父组件方法,是想把this.fileVoList传给父组件,然后在form表单当作参数传给后端
            }
        }
      });
    },
    //异步拿取附件数据
    test() {
    
    
      return new Promise((res, rej) => {
    
    
        if (this.accessoryList.length > 0) {
    
    
          this.$refs.upload.submit();
          res({
    
     code: 200 });
        } else {
    
    
          this.$message.error('请选择上传文件')
          rej({
    
     code: 500 });
        }
      });
    },
    //限制上传附件
    fileLimit(file, fileList) {
    
    
    const extension = file.name.substring(file.name.lastIndexOf('.') + 1);
  	const size = file.size / 1024 / 1024;
  	if(extension !== 'zip') {
    
    
  		this.$message.warning('只能传后缀名为.zip的压缩文件')
  		return
  	}
      if (size > 5) {
    
    
        this.$message.warning("文件大小不得超过5M");
        return;
      }
      this.accessoryList = fileList;
    },

    //附件上传成功
    upSuccessAccessory() {
    
    
      this.$message.success("附件上传成功");
    },
  },
};
</script>

<style>
.el-upload-list {
    
    
  width: 500px;
}
</style>

Guess you like

Origin blog.csdn.net/luofei_create/article/details/125502799