文件上传组件封装

什么是组件化?

       所谓组件化,就是把页面拆分成多个组件,每个组件依赖的 CSS、JS、模板、图片等资源放在一起开发和维护。 因为组件是资源独立的,所以组件在系统内部可复用,组件和组件之间可以嵌套,如果项目比较复杂,可以极大简化代码量,并且对后期的需求变更和维护也更加友好。

好处:增加代码的复用性、灵活性,从而提高开发效率。

技术点:

  1. 父往子传值
  2. 子往父传值
  3. 插槽技术

组件源码:

<template>
  <el-dialog :title="upload.title" :visible.sync="visible" width="520px" append-to-body class="uploadFileBox" @close="closed">
    <div class="temDownload">
      <div class="content">
        <div class="frontBox">
          <div class="title">下载导入模板</div>
          <div class="text">根据模板提示完善内容</div>
        </div>
        <div class="btnBox">
          <el-button @click="handleDownLoadTemp"><i class="el-icon-download"></i>下载模板</el-button>
        </div>
      </div>
    </div>
    <el-upload drag ref="upload" class="text-center" :limit="upload.maxCount" :accept="accept" :auto-upload="false" :headers="upload.headers" :action="uploadUrl" :show-file-list="upload.showFileList" :before-upload="beforeUpload" :disabled="upload.isUploading" :on-progress="handleFileUploadProgress" :on-success="handleFileSuccess" :on-error="handleError" :on-exceed="handleExceed" :on-change="handleChange" :on-remove="removeFile" :file-list="fileList">
      <template v-if="fileList.length == 0">
        <i class="el-icon-folder-opened" style="width:50px;height:50px">
        <div class="el-upload__text fileName">将文件拖到此处,或<em>点击上传</em></div>
        <div class="tips">{{`只能上传${accept}格式文件,且不超过10M`}}</div>
      </template>
      <template v-if="fileList.length > 0">
        <i v-if="!zipType" class="el-icon-document"  class="icon" width="50" height="50"></i>
        <i v-else class="el-icon-film"  class="icon" width="50" height="50"></i>
        <div class="fileName">{{files.name}}</div>
        <div><a>重新上传</a></div>
      </template>
    </el-upload>
    <div slot="footer" class="dialog-footer">
      <el-button @click="visible = false" size="small">取 消</el-button>
      <el-button type="primary" @click="submitFileForm" size="small">确 定</el-button>
    </div>
  </el-dialog>
</template>
<script>

export default {
  data() {
    return {
      visible: false,
      zipType: false,//是否是zip包
      fileList: [],
      files: {},
      upload: {
        title: '导入',
        headers: { Authorization: this.$cookie.get('token') }, //头部
        url: process.env.NODE_ENV === "production" ? process.env.VUE_APP_BASE_API : "",//url前缀
        showFileList: false,//是否显示文件列表
        isUploading: false,
        maxCount: 1, //限制个数
      },
    };
  },
  props: {
    accept: {
      type: String,
      default: '.xlsx,.xls,.zip'
    },
    // type: Array,
    uploadUrl: {
      type: String,
      default: ``
    },
    downloadType: {
      type: String,
      default: 'materialDefine'
    },
    value: String
  },
  methods: {
    show() {
      this.visible = true;
    },
    closed() {
      this.visible = false
      this.onClear()
    },
    /**
     * 下载模板
     */
    handleDownLoadTemp() {
      this.$confirm('确定下载?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.$http({
          url: this.$http.SystemAdornUrl(`/file/url?type=${this.downloadType}`),
          method: 'get',
          params: ''
        }).then(({
          data
        }) => {
          if (data && data.code === 200) {
            window.open(data.msg);
            this.$message({ message: '操作成功', type: 'success', duration: 1000 });
          }
        });
      });
    },
    /**
     * 提交文件
     */
    submitFileForm() {
      if (this.files) {
        this.$refs.upload.submit();
      } else {
        this.$message.warning('请选择文件')
      }
    },
    /**
     * 图片格式校验
     */
    beforeUpload(file) {
      let _self = this;
      /* 新增部分文件格式,用户切换所有文件时做格式限制 */
      if (this.accept) {
        let acc = this.accept.split(',')
        let testmsg = file.name.substring(file.name.lastIndexOf('.'))
        const extension = acc.filter(e => e === testmsg)
        if (extension.length < 1) {
          this.$message({ message: `您上传的文件格式不符合要求!只支持${acc.join(',')}格式的文件`, type: 'error', duration: 1500 })
          this.onClear()
          return false
        }
      }
      /* 增加限制上传图片大小, 2021.4.14 */
      if (file.size > 10 * 1024 * 1024) {
        this.$message({
          message: '文件大小不能超过10MB',
          type: 'error',
          duration: 1500
        })
        this.onClear()
        return false;
      }
      this.loading = this.$loading({
        lock: true,
        text: 'Loading',
        customClass: 'addloading',
        background: 'rgba(0, 0, 0, 0.5)'
      });
    },
    // 清除文件
    onClear() {
      this.files = {}
      this.fileList = []
      this.$refs.upload.clearFiles();
    },
    // 文件上传中处理
    handleFileUploadProgress(event, file, fileList) {
      this.upload.isUploading = true;
    },
    // 文件上传成功处理
    handleFileSuccess(response, file, fileList) {
      this.loading.close();
      if (response.code == 200) {
        this.visible = false;
        this.$emit('ok', response.data)
        this.upload.isUploading = false;
        this.$refs.upload.clearFiles();
        this.$message.success('导入成功')
      } else {
        this.visible = false;
        this.upload.isUploading = false;
        this.$refs.upload.clearFiles();
        this.$message.error(response.msg)
      }
    },
    /**
     * 上传失败
     */
    handleError(err, file, fileList) {
      this.loading.close();
      if (err) {
        this.$message({
          message: JSON.parse(err.message).message,
          type: 'error',
          duration: 1500
        })
      }
    },
    /**
     * 文件超出个数限制时调用
     */
    handleExceed(files, fileList) {
      this.$set(fileList[0], 'raw', files[0]);
      this.$set(fileList[0], 'name', files[0].name);
      this.$refs['upload'].clearFiles();//清除文件
      this.$refs['upload'].handleStart(files[0]);//选择文件后的赋值方法
    },
    // 上传 change事件
    handleChange(files, fileList) {
      let type = files.name.substring(files.name.lastIndexOf('.') + 1)
      if (type == 'zip') {
        this.zipType = true
      } else {
        this.zipType = false
      }
      if (this.accept.indexOf(type) != -1) {
        this.files = { ...files }
        this.fileList = fileList
      } else {
        this.$message.warning(`只能上传${this.accept}格式文件`)
        this.onClear()
      }

    },
    removeFile(files, fileList) {
      this.files = ''
    },
  },
};
</script>
<style lang="scss" scoped>
.uploadFileBox {
  button {
    padding: 8px 12px !important;
  }
  .temDownload {
    width: 100%;
    height: 88px;
    background: #f8f9fd;
    border-radius: 4px;
    border: 1px solid #d4d9e1;
    margin-bottom: 12px;
    padding: 20px 24px;
    box-sizing: border-box;
    .content {
      display: flex;
      .frontBox {
        width: 340px;
      }
      .title {
        font-size: 14px;
        font-family: PingFangSC-Medium, PingFang SC;
        font-weight: 500;
        color: #1d2129;
        margin-bottom: 8px;
      }
      .text {
        font-size: 12px;
        font-family: PingFangSC-Regular, PingFang SC;
        font-weight: 400;
      }
      .icon-mobantubiao {
        color: #3e4756 !important;
        display: inline-block;
      }
    }
    .btnBox {
      ::v-deep svg:not(:root) {
        padding-top: 2px !important;
      }
    }
  }
  .text-center {
    width: 100%;
    height: 210px;
    svg:not(:root) {
      margin-top: 52px;
    }
    .fileName {
      height: 22px;
      font-size: 12px;
      font-family: PingFangSC-Regular, PingFang SC;
      font-weight: 400;
      color: #1d2129;
      line-height: 22px;
      margin-top: 14px;
    }
    em {
      text-decoration: underline;
      color: #165dff;
    }
    a {
      text-decoration: underline;
      height: 22px;
      font-size: 12px;
      font-family: PingFangSC-Regular, PingFang SC;
      font-weight: 400;
      color: #165dff;
      line-height: 22px;
    }
    .tips {
      font-size: 12px;
      font-family: PingFangSC-Regular, PingFang SC;
      font-weight: 400;
      color: #86909c;
      margin-top: 6px;
    }
  }
}
::v-deep .el-upload {
  width: 100%;
  .el-upload-dragger {
    width: 100%;
    height: 210px;
    background: #f8f9fd;
    border-radius: 4px;
    border: 1px solid #d4d9e1;
  }
}

::v-deep .el-dialog {
  height: 438px;
  display: flex;
  flex-direction: column;
  margin: 0 !important;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);

  .el-dialog__header {
    padding: 24px 28px 12px 28px;
  }
  .el-dialog__body {
    padding: 0 28px !important;
  }
  .el-dialog__footer {
    padding: 0 28px 16px 28px;
    width: 100%;
    position: absolute;
    bottom: 0;
    right: 0;
  }
}
</style>

 全局注册:

import Upload from "@/components/upload/upload";
// 全局组件挂载
Vue.component('Upload', Upload)

组件使用:

<el-button @click="onUpload">上传</el-button> 
<Upload ref="upLoadRef" :uploadUrl="`${$http.SystemAdornUrl('/file/upload')}`" @ok="handleOk"></Upload>

<script>
     methods: {
        onUpload(){
            this.$refs.upLoadRef.show()
        },
        handleOk(data){
          console.log(data,'dsssssssssss')
        },
    }
</script>

视图: 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值