<template>
  <el-dialog title="图片上传" :visible.sync="visible" :width="popupWidth+'px'" v-on:close="onClose" append-to-body>
    <div>
      <el-button @click="chooseFile" type="primary">选择图片</el-button>
      <el-button @click="uploadCroppedImage" type="primary" v-show="hasImg&&percentage===0">上传</el-button>
      <el-button @click="visible=false">取消</el-button>
    </div>
    <div class="workArea">
      <croppa v-model="myCroppa"
              :width="width"
              :height="height"
              :quality="2"
              placeholder="请选择图片"
              :placeholder-font-size="0"
              :disabled="false"
              :prevent-white-space="true"
              :show-remove-button="true"
              ref="croppa"
              v-on:new-image="hasImg=true"
              :initial-image="oldImgUrl"
              @file-choose="onFileChoose"
              canvas-color="transparent"
              :accept="transparent?'image/png':'image/*'"
              @file-type-mismatch="onFileTypeError"
      >
      </croppa>
      <el-progress :percentage="percentage" v-show="percentage>0&&percentage<100"></el-progress>
    </div>
  </el-dialog>
</template>

<script>
  import ossUpload from '../math/oss_upload';
  import Croppa from 'vue-croppa';
  import Vue from 'vue';
  import Global from '../math/global';
  import {layer} from '../math/layer';
  import 'vue-croppa/dist/vue-croppa.css';

  Vue.use(Croppa);

  export default {
    name: "img-upload",
    props: {
      /**
       * 上传模式 默认启用OSS
       */
      mode: {
        type: String,
        default: 'oss'
      },
      ossData: {
        type: Object,
        default: {}
      },
      /**
       * OSS模式下必传（获取OSS令牌的接口地址）
       */
      ossTokenUrl: {
        type: String
      },
      /**
       * OSS模式下必传 图片上传成功后的域名
       */
      ossWebPath: {
        type: String,
      },
      /**
       * OSS模式下 图片放到哪个目录下面（可选）
       */
      ossDir: {
        type: String,
        default: ''
      },
      /**
       * Api直传模式下 图片上传接口
       */
      uploadApi: {
        type: String
      },
      //输出图片宽度
      imgWidth: {
        type: Number,
        default: 300
      },
      //输出图片高度
      imgHeight: {
        type: Number,
        default: 300
      },
      quality: {
        type: Number,
        default: 2
      },
      /**
       * 图片压缩比
       */
      ratio: {
        type: Number,
        default: .8
      },
      autoSize: {
        type: Boolean,
        default: false
      },
      maxWidth: {
        type: Number,
        default: 500
      },
      transparent: {
        type: Boolean,
        default: false
      },
      maxSize: {
        type: Number,
        default: 1000
      }
    },
    data() {
      return {
        visible: false,
        myCroppa: {},
        hasImg: false,
        percentage: 0,
        oldImgUrl: '',
        width: this.imgWidth || 300,
        height: this.imgHeight || 300,
      }
    },
    mounted() {
    },
    methods: {
      onFileTypeError() {
        if (this.transparent) {
          layer.error('只允许选择png图片');
        } else {
          layer.error('只允许选择图片');
        }
      },
      /**
       * 显示图片管理器
       * @param paras - 必传
       */
      show(oldImgUrl) {
        this.visible = true;
        this.clear();
        if (oldImgUrl) {
          if (this.autoSize) {
            const img = new Image();
            img.src = oldImgUrl;

            img.onload = () => {
              this.resize(img.width, img.height);
            };
          }
          this.oldImgUrl = oldImgUrl;
          this.hasImg = true;
          if (this.$refs.croppa) {
            this.$refs.croppa.refresh();
          }
        } else {
          this.oldImgUrl = '';
          setTimeout(() => {
            this.chooseFile();
          }, 300);
        }
      },

      /**
       * 清空工作区
       */
      clear() {
        if (this.hasImg) {
          this.$refs.croppa.remove();
          this.hasImg = false;
        }
      },
      /**
       * 选择图片
       */
      chooseFile() {
        this.$refs.croppa.chooseFile();
      },
      /**
       *阿里OSS上传
       */
      uploadByOss(blob) {
        console.log(blob.size);
        if (blob.size > this.maxSize * 1024) {
          layer.alert('图片大小超出限制');
          return;
        }
        const xhr = new XMLHttpRequest();
        let fileName;
        xhr.onreadystatechange = () => {
          if (xhr.readyState === 4 && xhr.status === 200) {
            this.onUploadSuccess({
              imgUrl: (this.ossWebPath || Global.get('ossWebPath')) + fileName,
              imgId: 0
            });
          }
        };
        xhr.upload.addEventListener('progress', (e) => {
          this.percentage = ~~(100 * e.loaded / e.total) / 2;
        }, false);

        ossUpload(this.ossTokenUrl || Global.get('ossTokenUrl'), blob, this.ossDir, false, '', this.ossData,
          this.transparent).then((res) => {
          fileName = res.fileName;
          xhr.open('post', res.host);
          xhr.send(res.formData);
        });
      },
      /**
       * Api直接上传
       */
      uploadByApi(blob) {
        const xhr = new XMLHttpRequest();
        const formData = new FormData();

        formData.append('file', blob, this.transparent ? '图片.png' : '图片.jpg');
        if (this.oldImgUrl) {
          formData.append('oldFileName', this.oldImgUrl);
        }
        xhr.open('post', this.uploadApi);
        xhr.onreadystatechange = () => {
          if (xhr.readyState === 4 && xhr.status === 200) {
            this.onUploadSuccess(JSON.parse(xhr.responseText));
          }
        };
        xhr.upload.addEventListener('progress', (e) => {
          this.percentage = ~~(100 * e.loaded / e.total) / 2;
        }, false);
        xhr.send(formData);
      },
      /**
       * 上传图片
       */
      uploadCroppedImage() {
        if (!this.hasImg) {
          this.$message({
            message: '请选择图片',
            type: 'error'
          });
          return;
        }
        this.myCroppa.generateBlob((blob) => {
          switch (this.mode) {
            case 'oss':
              this.uploadByOss(blob);
              break;
            case 'api':
              this.uploadByApi(blob);
              break;
          }

        }, this.transparent ? 'image/png' : 'image/jpeg', this.ratio)
      },

      /**
       * 图片上传后触发
       * @param res
       */
      onUploadSuccess(res) {
        this.percentage = 0;

        this.$emit('on-upload-pro', res);
        this.$emit('on-upload', res.imgUrl, res.imgId);
        this.$message({
          message: '上传成功',
          type: 'success'
        });
        this.clear();
        this.visible = false;
      },
      /**
       * 关闭时抛出事件
       */
      onClose() {
        this.$emit('on-close');
      },
      onFileChoose(file) {
        if (this.autoSize) {
          const reader = new FileReader();
          reader.onload = (e) => {
            const data = e.target.result;
            //加载图片获取图片真实宽度和高度
            const image = new Image();
            image.onload = () => {
              this.resize(image.width, image.height);
            };
            image.src = data;
          };
          reader.readAsDataURL(file);
        }
      },
      resize(width, height) {
        if (width < this.maxWidth && height < this.maxWidth) {
          this.width = width;
          this.height = height;
          return;
        }
        const max = width > height ? width : height;
        const bili = width / this.maxWidth;
        this.width = width / bili;
        this.height = height / bili;

        this.$emit('resize', this.width, this.height);
      }
      //}
    },
    computed: {
      popupWidth() {
        if (this.width < this.maxWidth) {
          return this.maxWidth + 50;
        } else {
          return this.width + 50;
        }
      }
    }
  }
</script>

<style scoped>
  .workArea {
    text-align: center;
    padding-top: 20px;
  }

  .workArea div {
    line-height: 0px;
  }

  .isDefault {
    border: red 1px solid;
  }
</style>
