element-ui/el-upload上传oss,支持截屏后粘贴上传

upload上传是前端开发很常用的一个功能,在Vue开发中常用的Element组件库也提供了非常好用的upload组件。本文采用scoped-slot 去设置缩略图模版,并且实现了oss粘贴上传功能。

一、html代码

使用插槽scoped-slot获取当前上传的状态file。通过file.status的状态判断是否上传成功。file.status为uploading代表正在上传中,为success代表上传成功。上传中hover到文件显示上传的文件大小、进度、速度。

<template>
  <div class="base-upload">
    <el-upload
      :id="id"
      ref="baseUpload"
      :action="OSS_URL"
      list-type="picture-card"
      :class="{ 'picture-card--disabled': disabled }"
      :disabled="disabled"
      drag
      multiple
      :file-list="myValue"
      :accept="accept"
      :headers="headers"
      :limit="limit"
      :data="tokens"
      :before-upload="beforeUpload"
      :on-progress="handleProgress"
      :on-exceed="handleExceed"
      :on-success="handleUploadSuccess"
      :on-error="handleUploadError"
      :on-preview="handlePictureCardPreview"
      :on-remove="handleRemove"
    >
      <i slot="default" class="el-icon-plus"></i>
      <div slot="file" slot-scope="{ file }">
        <!-- 提示上传进度 -->
        <el-popover ref="popover" placement="right" :title="file.status === 'uploading' ? '上传中,请耐心等待' : '上传成功'" width="200" trigger="hover">
          <ul v-if="file.status === 'uploading'">
            <li class="target-size" :class="{ 'target-size--success': file.status === 'success' }">文件大小:{{ showSize(file.size) }}</li>
            <li class="target-size" :class="{ 'target-size--success': file.status === 'success' }">已上传:{{ showSize(file.size * (file.percentage / 100)) }}</li>
            <li class="target-size" :class="{ 'target-size--success': file.status === 'success' }">上传速度:{{ showSize((file.size * (file.percentage / 100)) / file.speed) }}/s</li>
          </ul>
        </el-popover>
        <!-- 上传主题 -->
        <el-image v-if="file.status === 'success' && file.url" class="el-upload-list__item-thumbnail" :src="getThumbnailUrl(file)" fit="fit" />
        <el-progress v-if="file.status === 'uploading'" type="circle" :percentage="parseInt(file.percentage)" />
        <span v-popover:popover class="el-upload-list__item-actions">
          <span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)">
            <i class="el-icon-zoom-in"></i>
          </span>
          <span v-if="download" class="el-upload-list__item-download" @click="handleDownload(file)">
            <i class="el-icon-download"></i>
          </span>
          <span v-if="!disabled" class="el-upload-list__item-delete" @click="handleRemove(file)">
            <i class="el-icon-delete"></i>
          </span>
        </span>
      </div>
    </el-upload>
    <el-dialog :visible.sync="dialogVisible" :lock-scroll="false" append-to-body>
      <img width="100%" :src="dialogImageUrl" alt="" />
    </el-dialog>
  </div>
</template>

二、js代码

1.首先声明data参数

data() {
    return {
      thumbnailMaxSize: 1048576 * 20, // 缩略图(最大20M)
      id: `baseUpload_${new Date().getTime()}`,
      uploadStartTimeList: [], // 存储开始上传的事件
      OSS_URL: defaultSettings.OSS_URL, // oss上传地址
      myValue: this.value,
      tokens: {},
      dialogImageUrl: '',
      dialogVisible: false,
      headers: {
        Authorization: getToken()
      }
    }
  },

2.计算属性设置,这里有一个需要注意的点,oss缩略图限制图片最大为20M。如果上传图片过大,可以直接显示图片,另外判断大于20M显示原图片。

  computed: {
    // 缩略图地址
    getThumbnailUrl(file) {
      return (file) => {
        return validURL(file.url) && file.size < this.thumbnailMaxSize ? file.url + `?x-oss-process=image/resize,w_${this.width}` : file.url
      }
    }
  },

3.文件上传前钩子。前面说到的oss缩略图最大20M,在这里进行判断。之后通过后台接口设置签名,钩子返回Promise reject(false)则回调结束,

    generateTokens(key, file) {
      return new Promise((resolve, reject) => {
        getOssLiuParamsApi().then((res) => {
          file.startTime = new Date().getTime()
          this.uploadStartTimeList.push(file)

          this.tokens.key = res.dir + key
          this.tokens.policy = res.policy
          this.tokens.OSSAccessKeyId = res.accessid
          this.tokens.success_action_status = 200
          this.tokens.callback = res.callback
          this.tokens.signature = res.signature
          resolve(true)
        })
      }, () => {
        // eslint-disable-next-line no-undef
        reject(false)
      })
    },
    // 上传文件之前的钩子 {Object} file 文件信息
    beforeUpload(file) {
      const isBeyond = file.size < this.maxSize
      if (!isBeyond) {
        const beyondTip = '文件大小超过' + showSize(this.maxSize) + ',请重新上传。'
        this.$message.error(beyondTip)
        return isBeyond
      } else {
        const arr = file.name.split('.')
        const un_name = `${file.uid}.${arr[arr.length - 1]}`
        return this.generateTokens(un_name, file)
      }
    },

4.文件上传时钩子。

    handleProgress(event, file, fileList) {
      this.$store.dispatch('tool/toggleBeUploading', true)
      const currFile = this.uploadStartTimeList.filter(v => v.uid === file.uid)
      if (currFile && currFile[0]) {
        file.speed = (new Date().getTime() - currFile[0].startTime) / 1000
      }
      this.myValue = fileList
    },

5.文件上传成功钩子。设置图片路径,为避免前面设置上传进度的时候数据错乱,这里重新遍历设置,有其他更好的方法可以自行修改。

    handleUploadSuccess(res, file, fileList) {
      fileList.forEach(fileListItem => {
        const obj = this.setImg(file)
        const index = this.myValue.findIndex(item => item.uid === file.uid)
        this.myValue.splice(index, 1, obj)
      })
      console.log(this.myValue, 'myValue')
      this.$store.dispatch('tool/toggleBeUploading', false)
      this.$message({ type: 'success', message: '上传成功' })
    },

6.最后来说说截屏上传

原理:借助QQ、微信等截屏工具截屏,同时监听浏览器粘贴和鼠标移动事件, ctrl+v调用后台接口进行上传并且同步到upload组件

核心代码

mixins: [pasteUploadMixin],
    onMousemove(e) {
      const el = e.target
      const elWrappend = el.closest(`div#${this.id}`)
      const elCurrent = elWrappend.parentNode.parentNode.parentNode.firstElementChild
      if (elCurrent.getAttributeNode('for') && elCurrent.getAttributeNode('for').value) {
        this.pasteUploadKey = elCurrent.getAttributeNode('for').value
      } else {
        this.pasteUploadKey = ''
      }
    },
    // 初始化粘贴
    initPaste() {
      var handleAction = e => {
        var cbd = e.clipboardData
        var ua = window.navigator.userAgent
        // 如果是 Safari 直接 return
        if (!(e.clipboardData && e.clipboardData.items)) {
          return
        }

        // Mac平台下Chrome49版本以下 复制Finder中的文件的Bug Hack掉
        if (cbd.items && cbd.items.length === 2 && cbd.items[0].kind === 'string' && cbd.items[1].kind === 'file' && cbd.types && cbd.types.length === 2 && cbd.types[0] === 'text/plain' && cbd.types[1] === 'Files' && ua.match(/Macintosh/i) && Number(ua.match(/Chrome\/(\d{2})/i)[1]) < 49) {
          return
        }
        for (var i = 0; i < cbd.items.length; i++) {
          var item = cbd.items[i]
          if (item.kind === 'file') {
            var blob = item.getAsFile()
            if (blob.size === 0) {
              return
            }
            var reader = new FileReader()
            reader.readAsDataURL(blob)
            reader.onload = readerE => {
              this.submitUpload(readerE.target.result)
            }
          }
        }
      }

      this.newHandle = event => {
        handleAction(event)
      }

      document.getElementById(this.id).removeEventListener('paste', this.newHandle, false)
      document.getElementById(this.id).addEventListener('paste', this.newHandle, false)
    },

三、调用

<template>
  <base-upload v-model="value" accept="image/*" />
</template>
<script>
import BaseUpload from '@/components/BaseUpload'

export default {
  components: { BaseUpload },
  data() {
    return {
        value: ''
    }
  },
  methods: {
  }
}
</script>

完整代码

代码存放目录

BaseUpload
    mixin
        paste-upload.js
    index.vue

 对应的JS方法

import { uploadingPicture } from '@/utils/dict'
// 上传默认图片
export const uploadingPicture = {
  zip: 'http://xxxx.aliyuncs.com/1546836641143_4273.png',
  xls: 'http://xxxx.aliyuncs.com/1550486132435_7782.png',
  doc: 'http://xxxx.aliyuncs.com/1550486135954_2036.png',
  txt: 'http://xxxx.aliyuncs.com/1550486134063_8220.png',
  mp4: 'http://xxxx.aliyuncs.com/1550653591085_6150.png',
  other: 'http://xxxx.aliyuncs.com/1550653593890_4662.png'
}

import { showSize } from '@/utils'
/**
 * @description 将字节转化为MB GB T
 * @param {Number} size 字节
 * @return {string} data 转化后的大小
 */
export const showSize = size => {
  let data = ''
  if (size < 1048576) {
    data = Number((size / 1024).toFixed(2)) + 'KB'
  } else if (size === 1048576) {
    data = '1MB'
  } else if (size > 1048576 && size < 1073741824) {
    data = Number((size / (1024 * 1024)).toFixed(2)) + 'MB'
  } else if (size > 1048576 && size === 1073741824) {
    data = '1GB'
  } else if (size > 1073741824 && size < 1099511627776) {
    data = Number((size / (1024 * 1024 * 1024)).toFixed(2)) + 'GB'
  } else {
    data = '文件超过1TB'
  }
  return data
}

import { validURL } from '@/utils/validate'
/**
 * @param {string} url
 * @returns {Boolean}
 */
export function validURL(url) {
  const reg = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
  return reg.test(url)
}

import { getToken } from '@/utils/auth'
export function getToken() {
  return Cookies.get(TokenKey)
}

import { pasteUploadMixin } from './mixin/paste-upload'

import { getOssLiuParamsApi } from '@/api/utils'
// 前端直传参数接口
export function getOssLiuParamsApi(data) {
  return request({
    url: 'order/ossLiu',
    method: 'post',
    data
  })
}

import defaultSettings from '@/settings'
module.exports = {
  OSS_URL: 'https://xxxx/', // oss下载地址(测试)
  BASE_API: 'https://xxxx/' // 测试环境
}


/**
 * @param {Array} str
 * @returns {Boolean}
 */
export function isEmpty(str) {
  if (str === '' || str === null || str === undefined || str.length === 0) {
    return true
  }
  return false
}

// 上传粘贴的图片到oss
export function uploadingUpFile(data) {
  return request({
    url: 'order/screenshotImg',
    method: 'post',
    data
  })
}
<!-- index.vue -->
<template>
  <div class="base-upload" @mousemove="onMousemove">
    <el-upload
      :id="id"
      ref="baseUpload"
      :action="OSS_URL"
      list-type="picture-card"
      :class="{ 'picture-card--disabled': disabled }"
      :disabled="disabled"
      drag
      multiple
      :file-list="myValue"
      :accept="accept"
      :headers="headers"
      :limit="limit"
      :data="tokens"
      :before-upload="beforeUpload"
      :on-progress="handleProgress"
      :on-exceed="handleExceed"
      :on-success="handleUploadSuccess"
      :on-error="handleUploadError"
      :on-preview="handlePictureCardPreview"
      :on-remove="handleRemove"
    >
      <i slot="default" class="el-icon-plus"></i>
      <div slot="file" slot-scope="{ file }">
        <!-- 提示上传进度 -->
        <el-popover ref="popover" placement="right" :title="file.status === 'uploading' ? '上传中,请耐心等待' : '上传成功'" width="200" trigger="hover">
          <ul v-if="file.status === 'uploading'">
            <li class="target-size" :class="{ 'target-size--success': file.status === 'success' }">文件大小:{{ showSize(file.size) }}</li>
            <li class="target-size" :class="{ 'target-size--success': file.status === 'success' }">已上传:{{ showSize(file.size * (file.percentage / 100)) }}</li>
            <li class="target-size" :class="{ 'target-size--success': file.status === 'success' }">上传速度:{{ showSize((file.size * (file.percentage / 100)) / file.speed) }}/s</li>
          </ul>
        </el-popover>
        <!-- 上传主题 -->
        <el-image v-if="file.status === 'success' && file.url" class="el-upload-list__item-thumbnail" :src="getThumbnailUrl(file)" fit="fit" />
        <el-progress v-if="file.status === 'uploading'" type="circle" :percentage="parseInt(file.percentage)" />
        <!-- <el-progress :text-inside="true" :stroke-width="18" :percentage="Math.floor(item.percentage * 100) / 100"></el-progress> -->
        <span v-popover:popover class="el-upload-list__item-actions">
          <span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)">
            <i class="el-icon-zoom-in"></i>
          </span>
          <span v-if="download" class="el-upload-list__item-download" @click="handleDownload(file)">
            <i class="el-icon-download"></i>
          </span>
          <span v-if="!disabled" class="el-upload-list__item-delete" @click="handleRemove(file)">
            <i class="el-icon-delete"></i>
          </span>
        </span>
      </div>
    </el-upload>
    <el-dialog :visible.sync="dialogVisible" :lock-scroll="false" append-to-body>
      <img width="100%" :src="dialogImageUrl" alt="" />
    </el-dialog>
  </div>
</template>
<script>
import { uploadingPicture } from '@/utils/dict'
import { showSize } from '@/utils'
import { validURL } from '@/utils/validate'
import { getToken } from '@/utils/auth'
import { pasteUploadMixin } from './mixin/paste-upload'
import { getOssLiuParamsApi } from '@/api/utils'
import defaultSettings from '@/settings'

export default {
  name: 'BaseUpload',
  mixins: [pasteUploadMixin],
  props: {
    // 接受上传的文件类型
    accept: {
      type: String,
      default: null
    },
    // 是否禁用
    disabled: {
      type: Boolean,
      default: false
    },
    // 是否允许下载
    download: {
      type: Boolean,
      default: true
    },
    // 上传个数
    limit: {
      type: Number,
      default: 10
    },
    // 文件大小限制,单位为byte,默认1 * 10G(1M=1024k=1048576字节)
    maxSize: {
      type: Number,
      default: (1048576 * 10240)
    },
    value: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      thumbnailMaxSize: 1048576 * 20, // 缩略图(最大20M)
      id: `baseUpload_${new Date().getTime()}`,
      uploadStartTimeList: [],
      OSS_URL: defaultSettings.OSS_URL,
      myValue: this.value,
      tokens: {},
      dialogImageUrl: '',
      dialogVisible: false,
      headers: {
        Authorization: getToken()
      }
    }
  },
  computed: {
    // 缩略图地址
    getThumbnailUrl(file) {
      return (file) => {
        return validURL(file.url) && file.size < this.thumbnailMaxSize ? file.url + `?x-oss-process=image/resize,w_${this.width}` : file.url
      }
    }
  },
  watch: {
    value(newVal) {
      this.myValue = newVal
    },
    myValue(newVal) {
      this.$emit('input', newVal)
    }
  },
  created() {
  },
  methods: {
    showSize,
    /**
     * @description 正在上传
     * @param {Object} event
     * @param {Object} file 文件信息
     * @param {Array} fileList 当前数组
     * @result void
     */
    handleProgress(event, file, fileList) {
      this.$store.dispatch('tool/toggleBeUploading', true)
      const currFile = this.uploadStartTimeList.filter(v => v.uid === file.uid)
      if (currFile && currFile[0]) {
        file.speed = (new Date().getTime() - currFile[0].startTime) / 1000
      }
      this.myValue = fileList
    },
    /**
     * @description 图片数量限制
     * @param {Object} file 文件信息
     * @param {Array} fileList 当前数组
     * @result void
     */
    handleExceed(files, fileList) {
      this.$message.warning(`当前限制选择 ${this.limit} 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`)
    },
    generateTokens(key, file) {
      return new Promise((resolve, reject) => {
        getOssLiuParamsApi().then((res) => {
          file.startTime = new Date().getTime()
          this.uploadStartTimeList.push(file)

          this.tokens.key = res.dir + key
          this.tokens.policy = res.policy
          this.tokens.OSSAccessKeyId = res.accessid
          this.tokens.success_action_status = 200
          this.tokens.callback = res.callback
          this.tokens.signature = res.signature
          resolve(true)
        })
      }, () => {
        // eslint-disable-next-line no-undef
        reject(false)
      })
    },
    // 上传文件之前的钩子 {Object} file 文件信息
    beforeUpload(file) {
      const isBeyond = file.size < this.maxSize
      if (!isBeyond) {
        const beyondTip = '文件大小超过' + showSize(this.maxSize) + ',请重新上传。'
        this.$message.error(beyondTip)
        return isBeyond
      } else {
        const arr = file.name.split('.')
        const un_name = `${file.uid}.${arr[arr.length - 1]}`
        return this.generateTokens(un_name, file)
      }
    },
    /**
     * @description 文件上传成功时的钩子
     * @param {Object} res 成功返回值
     * @param {Object} file 文件信息
     * @param {Array} fileList 当前数组
     * @result void
     */
    handleUploadSuccess(res, file, fileList) {
      fileList.forEach(fileListItem => {
        const obj = this.setImg(file)
        const index = this.myValue.findIndex(item => item.uid === file.uid)
        this.myValue.splice(index, 1, obj)
      })
      this.$store.dispatch('tool/toggleBeUploading', false)
      this.$message({ type: 'success', message: '上传成功' })
    },
    /**
     * @desc 重新设置图片地址
     * @param {Object} file 文件信息
     * @return {Object} img
     */
    setImg(file) {
      const arr = file.name.split('.')
      const un_name = `${file.uid}.${arr[arr.length - 1]}`
      var fileAddress = 'design' + un_name
      const img = {
        uid: file.uid,
        real_url: this.OSS_URL + fileAddress,
        name: file.name,
        size: file.size
      }
      if (fileAddress.indexOf('.zip') > -1 || fileAddress.indexOf('.rar') > -1) {
        file.url = uploadingPicture.zip
        img.url = uploadingPicture.zip
      } else if (fileAddress.indexOf('.xls') > -1) {
        file.url = uploadingPicture.xls
        img.url = uploadingPicture.xls
      } else if (fileAddress.indexOf('.doc') > -1) {
        file.url = uploadingPicture.doc
        img.url = uploadingPicture.doc
      } else if (fileAddress.indexOf('.txt') > -1) {
        file.url = uploadingPicture.txt
        img.url = uploadingPicture.txt
      } else if (fileAddress.indexOf('.mp4') > -1) {
        file.url = uploadingPicture.mp4
        img.url = uploadingPicture.mp4
      } else if (fileAddress.indexOf('.jpg') > -1 || fileAddress.indexOf('.png') > -1 || fileAddress.indexOf('.jpeg') > -1 || fileAddress.indexOf('.gif') > -1 || fileAddress.indexOf('.JPG') > -1 || fileAddress.indexOf('.PNG') > -1 || fileAddress.indexOf('.JPEG') > -1 || fileAddress.indexOf('.GIF') > -1) {
        file.url = this.OSS_URL + fileAddress
        img.url = this.OSS_URL + fileAddress
      } else {
        file.url = uploadingPicture.other
        img.url = uploadingPicture.other
      }
      return img
    },
    // 文件上传失败时的钩子
    handleUploadError() {
      this.$message({ type: 'error', message: '上传失败' })
    },
    // 下载 {Object} file 文件信息
    handleDownload(file) {
      if (this.download) {
        if (file.real_url) {
          window.open(file.real_url)
        } else {
          window.open(file.url)
        }
      }
    },
    // 图片查看 {Object} file 文件信息
    handlePictureCardPreview(file) {
      this.dialogImageUrl = file.url
      this.dialogVisible = true
    },
    // 删除 {Object} file 文件信息
    handleRemove(file) {
      this.$refs.baseUpload.abort(file)
      this.myValue = this.myValue.filter(v => v.uid !== file.uid)
    }
  }
}
</script>
<style lang="scss">
.base-upload {
  // 图片大小
  @include upload-width(78px, 78px);
  .picture-card--disabled {
    .el-upload--picture-card {
      display: none;
    }
  }
}
</style>
<style lang="scss" scoped>
.target-size {
  @include fc(12px, red);
  line-height: 25px;
}
.target-size--success {
  color: #91b493;
}
</style>
// paste-upload.js
import { uploadingUpFile } from '@/api/utils'
import { mapGetters } from 'vuex'
import { isEmpty } from '@/utils/validate'
export const pasteUploadMixin = {
  data() {
    return {
      newHandle: null,
      pasteUploadKey: ''
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.initPaste()
    })
  },
  computed: {
    ...mapGetters(['pastPanel']),
    // 获取激活项的地址(默认粘贴板的地址)
    getBase64() {
      return function(base64) {
        let result = base64
        if (!isEmpty(this.pastPanel.active)) {
          const newResult = this.pastPanel.list.filter(v => v.id === this.pastPanel.active)
          result = newResult[0].src
        }
        return result
      }
    },
    // 返回粘贴限制key对应的type
    getPasteUploadType() {
      return function(key) {
        const keyMap = {
          model_img: 1,
          reference_img: 2,
          material_img: 3
        }
        return keyMap[key]
      }
    }
  },
  methods: {
    onMousemove(e) {
      const el = e.target
      const elWrappend = el.closest(`div#${this.id}`)
      const elCurrent = elWrappend.parentNode.parentNode.parentNode.firstElementChild
      if (elCurrent.getAttributeNode('for') && elCurrent.getAttributeNode('for').value) {
        this.pasteUploadKey = elCurrent.getAttributeNode('for').value
      } else {
        this.pasteUploadKey = ''
      }
    },
    // 初始化粘贴
    initPaste() {
      var handleAction = e => {
        var cbd = e.clipboardData
        var ua = window.navigator.userAgent
        // 如果是 Safari 直接 return
        if (!(e.clipboardData && e.clipboardData.items)) {
          return
        }

        // Mac平台下Chrome49版本以下 复制Finder中的文件的Bug Hack掉
        if (cbd.items && cbd.items.length === 2 && cbd.items[0].kind === 'string' && cbd.items[1].kind === 'file' && cbd.types && cbd.types.length === 2 && cbd.types[0] === 'text/plain' && cbd.types[1] === 'Files' && ua.match(/Macintosh/i) && Number(ua.match(/Chrome\/(\d{2})/i)[1]) < 49) {
          return
        }
        for (var i = 0; i < cbd.items.length; i++) {
          var item = cbd.items[i]
          if (item.kind === 'file') {
            var blob = item.getAsFile()
            if (blob.size === 0) {
              return
            }
            var reader = new FileReader()
            reader.readAsDataURL(blob)
            reader.onload = readerE => {
              this.submitUpload(readerE.target.result)
            }
          }
        }
      }

      this.newHandle = event => {
        handleAction(event)
      }

      document.getElementById(this.id).removeEventListener('paste', this.newHandle, false)
      document.getElementById(this.id).addEventListener('paste', this.newHandle, false)
    },
    submitUpload(base64) {
      const params = {
        type: this.getPasteUploadType(this.pasteUploadKey),
        data: this.getBase64(base64)
      }
      this.$message.info('正在上传中,勿刷新页面')
      this.$store.dispatch('tool/toggleBeUploading', true)
      uploadingUpFile(params)
        .then(res => {
          this.myValue.push({ url: res.data, name: new Date().getTime() + '.jpg' })
          this.$message({ type: 'success', message: '上传成功' })
          this.$store.dispatch('tool/toggleBeUploading', false)
        })
        .catch(() => {
          this.$message({ type: 'error', message: '上传失败' })
          this.$store.dispatch('tool/toggleBeUploading', false)
        })
    }
  },
  destroyed() {
    document.getElementById(this.id) && document.getElementById(this.id).removeEventListener('paste', this.newHandle, false)
  }
}

喜欢的给个👍哦,欢迎留言

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值