index.vue 2.31 KB
<template>
  <div class="upload-wrapper">
    <label>{{ placeholderCopy }}</label>
    <div class="uw-right">
      <el-button class="uw-btn">
        <slot></slot>
      </el-button>
      <input
        class="uw-input"
        type="file"
        id="image_uploads"
        name="image_uploads"
        :accept="accept"
        :multiple="multiple"
        @change="handleChange"
      />
    </div>
  </div>
</template>

<script>
export default {
  props: {
    placeholder: {
      type: String,
      default: '上传图片,可多选'
    },
    accept: {
      type: String,
      default: '.jpg, .jpeg, .png, .JPG, .JPEG, .PNG, .bmp, .BMP'
    },
    multiple: {
      type: Boolean,
      default: false
    },
    onExceed: {
      type: Function,
      default: () => {}
    },
    limit: {
      type: Number
    },
    onChange: {
      type: Function,
      default: () => {}
    }
  },
  data() {
    return {
      placeholderCopy: this.placeholder
    }
  },
  methods: {
    handleChange(e) {
      const files = e.currentTarget.files
      const length = files.length
      if (!this.isValidator(files)) {
        this.$emit('onFail', files)
        return
      }
      if (this.limit && length > this.limit) {
        this.onExceed()
        return
      }
      if (files.length > 0) {
        this.placeholderCopy = files[0].name
        this.onChange(Array.from(files))
      }
    },
    getAcceptType() {
      const arr = this.accept
        .toLowerCase()
        .split(',')
        .map(item => `image/${item.slice(item.indexOf('.') + 1)}`)
      return Array.from(new Set(arr))
    },
    isValidator(files) {
      return Array.from(files).every(file =>
        this.getAcceptType().includes(file.type)
      )
    }
  },
  mounted() {
    this.getAcceptType()
  }
}
</script>

<style lang="scss" scoped>
.upload-wrapper {
  width: 300px;
  height: 42px;
  background: #f2f2f2;
  display: inline-block;
  position: relative;
  label {
    font-size: 12px;
    line-height: 42px;
    width: 100%;
    display: inline-block;
    height: 100%;
    overflow: hidden;
  }
  .uw-right {
    position: absolute;
    top: 0;
    bottom: 0;
    right: 0;
    width: 70px;
  }
  input {
    position: absolute;
    top: 0;
    bottom: 0;
    right: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
  }
}
</style>