对antdesign上传图片组件进行二次封装

346 阅读1分钟

上传图片组件封装

<template>
  <div>
    <a-upload
      ref="uploader"
      list-type="picture-card"
      :fileList="fileList"
      :before-upload="beforeUpload"
      :custom-request="() => {}"
      :remove="handleRemove"
      @preview="handlePreview"
      :multiple="multiple"
      :customRequest="handleChange"
    >
      <!-- 单图片上传开启这个 -->
      <div v-if="FileList.length < limit">
        <a-icon type="plus" />
        <div class="ant-upload-text">上传</div>
      </div>
    </a-upload>
    <a-modal :visible="previewVisible" :footer="null" @cancel="handleCancel">
      <img alt="example" style="width: 100%" :src="previewImage" />
    </a-modal>
  </div>
</template>

<script>
//这里需要引入 图片 处理方法
function getBase64(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.readAsDataURL(file)
    reader.onload = () => resolve(reader.result)
    reader.onerror = (error) => reject(error)
  })
}
import axios from 'axios'

export default {
  name: 'UploadPicture',
  data() {
    return {
      previewVisible: false,
      previewImage: '',
      fileList: [], // 已上传文件列表
      imageUrl: '',
      isShowSpinning: false
    }
  },
  props: {
    //控制多少张图片
    limit: {
      type: Number,
      default: 1
    },
    // 增加控制是否是多选文件的字段
    multiple: {
      type: Boolean,
      default: false
    },
    // 接受父组件传递的对象
    FileList: {
      type: Array,
      default: () => []
    },
    type: {
      type: Number,
      default: 1
    },
    type_name: {
      type: String,
      default: 'bizLicense'
    }
  },
  computed: {
    imgurl() {
      return process.env.VUE_APP_IMAGE_URL
    }
  },
  watch: {
    FileList: {
      handler() {
        console.log(this.fileList, this.FileList)
        if (this.FileList.length > 0) {
          let arr = []
          let str = location.href
          let index = str.indexOf('#')
          let url = str.substring(0, index)
          this.FileList.map((item, index) => {
            console.log(item, '11')
            let a = {
              uid: item,
              name: 'xxx.png',
              status: 'done',
              url: this.imgurl + item
            }
            arr.push(a)
            this.fileList = arr
          })
        } else {
          this.fileList = []
        }
      },
      deep: true,
      immediate: true
    }
  },
  methods: {
    // 上传文件之前的钩子,参数上传的文件
    beforeUpload(file, fileList) {
      const testmsg = /^image\/(jpeg|png|jpg)$/.test(file.type)
      const isLt10M = file.size / 1024 / 1024 <= 10 // 图片大小不超过10MB
      return new Promise(async (resolve, reject) => {
        if (!file.type.includes('image')) {
          this.$message.warning('请上传图片')
          reject(new Error('请上传图片'))
          return
        }
        if (!testmsg) {
          this.$message.error('上传图片格式不对!')
          return reject(new Error(false))
        }
        if (!isLt10M) {
          this.$message.error('上传图片大小不能超过 10M!')
          return reject(new Error(false))
        }
        const newFile = await this.compressImg(file) // 上传之前,对图片进行压缩
        resolve(newFile)
      })
    },
    compressImg(file) {
      const that = this
      let files
      let fileSize = parseFloat(parseInt(file['size']) / 1024 / 1024).toFixed(2)
      let read = new FileReader()
      read.readAsDataURL(file)
      return new Promise(function (resolve, reject) {
        read.onload = function (e) {
          let img = new Image()
          img.src = e.target.result
          img.onload = function () {
            // 默认按比例压缩
            let w = this.width
            let h = this.height
            // 生成canvas
            let canvas = document.createElement('canvas')
            let ctx = canvas.getContext('2d')
            let base64
            // 创建属性节点
            canvas.setAttribute('width', w)
            canvas.setAttribute('height', h)
            ctx.drawImage(this, 0, 0, w, h)
            if (fileSize < 1) {
              // 如果图片小于一兆 那么压缩0.5
              base64 = canvas.toDataURL(file['type'], 0.5)
            } else if (fileSize > 1 && fileSize < 2) {
              // 如果图片大于1M并且小于2M 那么压缩0.5
              base64 = canvas.toDataURL(file['type'], 0.5)
            } else {
              // 如果图片超过2m 那么压缩0.2
              base64 = canvas.toDataURL(file['type'], 0.2)
            }
            // 回调函数返回file的值(将base64编码转成file)
            files = that.dataURLtoFile(base64, file.name) // 如果后台接收类型为base64的话这一步可以省略
            resolve(files)
          }
        }
      })
    },
    dataURLtoFile(dataurl, filename) {
      let arr = dataurl.split(',')
      let mime = arr[0].match(/:(.*?);/)[1]
      let bstr = atob(arr[1])
      let n = bstr.length
      let u8arr = new Uint8Array(n)
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
      }
      return new File([u8arr], filename, { type: mime })
    },
    // 删除图片
    handleRemove(file) {
      this.$emit('remove', file) // 触发父组件remove函数,并传当前删除文件
    },
    // 预览图片(点开小眼睛)
    async handlePreview(file) {
      if (!file.url && !file.preview) {
        file.preview = await getBase64(file.originFileObj)
      }
      this.previewImage = file.url || file.preview
      this.previewVisible = true
    },
    // 上传附件
    handleChange({ file, fileList }) {
      if (file.status !== 'removed') {
        const formData = new FormData()
        formData.append('files[]', file) // 注意接口需要的是files[],还是files
        formData.append('module', 'park') // 另一个传参
        if (this.type === 2) {
          const formData1 = new FormData()
          formData1.append('files[]', file)
          formData1.append(
            'module',
            this.type_name === 'bizLicense' ? 'bizLicense' : 'cardNumber'
          ) // 根据需求改变传参值
          formData1.append(
            'side',
            this.type_name === 'IDcardback' ? 'back' : 'face'
          )
          axios.post('/api/system/upload/ocr', formData1).then((res) => {
            this.$emit('upload', res.data) // 触发父组件upload函数,并把上传图片后结果传过去
          })
        } else {
          axios.post('/api/system/upload', formData).then((res) => {
            this.$emit('upload', res.data)
          })
        }
      }
    },

    // 取消预览图片
    handleCancel() {
      this.previewVisible = false
    }
  }
}
</script>

<style scoped lang="less"></style>

使用组件

import uploadMoreImgVue from '@/components/common/uploadimg.vue'
<templete>
    <uploadMoreImgVue
        :FileList="fileList"  // 上传图片数组需要传给子组件:limit="5"
        @upload="updateImg"
        @remove="removeImg"
    ></uploadMoreImgVue>
</templete>

// 上传图片触发函数
updateImg(data) {
    this.fileList.push(data[0].path)
    this.imglist.push({
        file_name: data[0].filename,
        file_path: data[0].path
    })
    if (this.fileList.length > 0) {
        this.$refs.ruleForm.clearValidate('fileList')
    } else {
        this.$refs.ruleForm.validate('fileList')
    }
},
// 删除图片触发函数
removeImg(file) {
    this.fileList = this.fileList.filter((item) => item !== file.uid)
    this.imglist = this.imglist.filter((item) => item.file_path !== file.uid)
},