<template>
<div>
  <el-upload
    ref="upload_com"
    :headers="headers"
    :action="action"
    :show-file-list="showFileList"
    :file-list="fileList"
    :on-success="_onSuccess"
    :on-preview="_onPreview"
    :http-request="oss_upload"
    :on-remove="_onRemove"
    :before-remove="_onBeforeRemove"
    :before-upload="_beforeUpload"
    :on-exceed="_onExceed"
    :limit="limit"
    :list-type="list_type"
    :accept="accept"
    :on-change="handleChange"
    :multiple="multiple">
    <slot></slot>
    <slot name="tip"></slot>
  </el-upload>
  <el-progress v-show="showProcess" :percentage="processLength" :stroke-width="2"></el-progress>
</div>
</template>

<script>
  function noop() {
  }

  import moment from 'moment'
  import axios from 'axios'
  import { Loading } from 'element-ui';
  import axiosUpload from '@/utils/axiosUpload'
  export default {
    props: {
      action: {
        type: String,
        required: true
      },
      headers: {
        type: Object,
        default() {
          return {};
        }
      },
      data: Object,
      coursePath:{
        type:String,
        default:null
      },
      multiple: Boolean,
      list_type:{
        type: String,
        default: 'text'
      },
      name: {
        type: String,
        default: 'file'
      },
      drag: Boolean,
      dragger: Boolean,
      withCredentials: Boolean,
      showFileList: {
        type: Boolean,
        default: false
      },
      accept:{
        type:String,
        // default:'image/*'
      },
      type: {
        type: String,
        default: 'select'
      },
      beforeUpload: Function,
      beforeRemove: Function,
      onRemove: {
        type: Function,
        default: noop
      },
      onBeforeRemove:{
        type: Function,
        default: noop
      },
      onChange: {
        type: Function,
        default: noop
      },
      onPreview: {
        type: Function
      },
      onSuccess: {
        type: Function,
        default: noop
      },
      onProgress: {
        type: Function,
        default: noop
      },
      onError: {
        type: Function,
        default: noop
      },
      fileList: {
        type: Array,
        default() {
          return [];
        }
      },
      autoUpload: {
        type: Boolean,
        default: true
      },
      listType: {
        type: String,
        default: 'text' // text,picture,picture-card
      },
      httpRequest: Function,
      disabled: Boolean,
      limit: {
        type: Number,
        default: ()=>{
          return 1
        }
      },
      onExceed: {
        type: Function,
        default: noop
      }
    },
    name: "upload",
    data() {
      return {
        processLength:0,
        showProcess:false,
        files:{},
        config: null
      }
    },
    methods: {
      handleChange(file,fileList){
        this.files = file
      },
      handleChanges(file){
        if(file.status === 'ready'){
          this.processLength = 0
          this.showProcess = true
          const interval = setInterval(() => {
            if(this.processLength >= 99){
            clearInterval(interval)
            return
            }
            this.processLength += 1
          },20)
        }
        if(file.status === 'success'){
          this.processLength =100
          this.showProcess = false
        }
      },
      //清空图片
      // clearPictures(){
      //   this.$refs.upload_com.clearFiles();
      // },
      get_sign(callback) {
        // 测试添加 'https://intesys.cms.g107.com'
        axiosUpload('get','https://intesys.cms.g107.com/integral.php/Api/get_signature').then(res => {
          this.config = res.data.data
          callback()
        })
      },
      _beforeUpload(file) {
        if(!this.beforeUpload(file)){
          return false
        }else{
          this.handleChanges(this.files)
        }

      },
      oss_upload(upload_obj){
        this.get_sign(()=>{
          // this.beforeUpload_all(upload_obj.file).then(res=>{
          //   this.upload(res)
          // });
          this.upload(upload_obj.file)
        })
      },
      fileByBase64(file, callback){
        let reader = new FileReader();
        // 传入一个参数对象即可得到基于该参数对象的文本内容
        reader.readAsDataURL(file);
        reader.onload = function (e) {
          // target.result 该属性表示目标对象的DataURL
          callback(e.target.result)
        };
      },
      // 添加水印
      async beforeUpload_all(file) {
          return new Promise((resolve, reject) => {
            //把文件转换为base64
            this.fileByBase64(file, async (base64) => {   // 1.调用方法1： 把文件转换为base64字符串
              // 把文件转换为Canvas
              let tempCanvas = await this.imgToCanvas(base64) // 2. 调用方法2：把base64转换为Canvas
              // 把水印写入
              const canvas = this.addWatermark(tempCanvas,this.$moment().format('YYYY-MM-DD HH:mm')) //3.调用方法3： 写入水印到Canvas
              // canvas转成img
              const img = this.convasToImg(canvas, file.type) //4. 调用方法4：把Canvas转换为image文件
              //被canvas转换为文件
              let newFile = this.base64ToFile(img.src, file.name) //5.调用方法5：被image转换为File文件
              resolve(newFile)
            })
          })
      },
      /**
       * Base64转成canvas
       * @param  base64
       */
      async imgToCanvas(base64) {
        // 创建img元素
        const img = document.createElement('img')
        img.setAttribute('src', base64)
        await new Promise((resolve) => (img.onload = resolve))
        // 创建canvas DOM元素，并设置其宽高和图片一样
        const canvas = document.createElement('canvas')
        canvas.width = img.width
        canvas.height = img.height
        // 坐标(0,0) 表示从此处开始绘制，相当于偏移。
        canvas.getContext('2d').drawImage(img, 0, 0)
        return canvas
      },
      /**
       * canvas添加水印
       * @param  canvas 对象
       * @param text 水印文字
       */
      addWatermark(canvas, text) {
        const ctx = canvas.getContext('2d')

        let fontSize=ctx.canvas.width / 36
         //设置文本画笔的样式
        ctx.textAlign = 'left';//设置文本对齐方式
        ctx.textBaseline = 'middle';//设置文本基线
        ctx.font =fontSize +"px Microsoft Yahei";//设置文本字体属性
        ctx.fillStyle = "rgba(255, 255, 255,0.3)"//设置文本字体颜色

        //在canvas画布上绘制文字 ctx.fillText(文字内容, x位置, y位置, 文本最大宽度)
        ctx.fillText(text,20, ctx.canvas.width / 36 + 20)//14为文字大小
        return canvas
      },
      /**
       * canvas转成img
       * @param {canvas对象} canvas
       */
      convasToImg(canvas) {
        // 新建Image对象，可以理解为DOM
        let image = new Image()
        // canvas.toDataURL 返回的是一串Base64编码的URL
        // 指定格式 PNG
        image.src = canvas.toDataURL('image/png')
        return image
      },
      /**
       * @param urlData  base64
       * @param fileName 文件名称
       * @returns {File}
       */
      base64ToFile(urlData, fileName) {
        let arr = urlData.split(',');
        let mime = arr[0].match(/:(.*?);/)[1];
        let bytes = atob(arr[1]); // 解码base64
        let n = bytes.length
        let ia = new Uint8Array(n);
        while (n--) {
          ia[n] = bytes.charCodeAt(n);
        }
        return new File([ia], fileName, { type: mime });
      },


      _onExceed(files, fileList){
        this.$message.warning(`文件数量不能超过 ${this.limit} 个`)
      },
      _onSuccess(response, file, fileList) {
        this.onSuccess(response, file, fileList)
      },
      _onPreview(file) {
        this.onPreview(file)
      },
      _onRemove(file, fileList) {
        this.onRemove(file, fileList)
      },
      _onBeforeRemove(file, fileList){
        if(file.status == "success"){
          return this.$confirm(`确定移除此项？`)
        }
      },
      random_string(len) {
        len = len || 32
        var chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'
        var maxPos = chars.length
        var pwd = ''
        for (let i = 0; i < len; i++) {
          pwd += chars.charAt(Math.floor(Math.random() * maxPos))
        }
        return pwd
      },
      upload(item) {
        let self = this
        const photo = item // 获取图片对象
        const photoName = item.name // 原图片的名称
        const url = 'https://integralsys.oss-cn-shenzhen.aliyuncs.com'
        let date = moment().format('YYYY/MM/DD')
        let param = new FormData()
        let site_id
        if(this.coursePath){
          site_id = this.coursePath
        }else{
          site_id = this.$getCache('site_info').id
        }
        let randomStr = this.random_string(32)
        let key = 'intesys/' + site_id + '/' + date + '/' + randomStr +'/'+ photoName
        // let loadingInstance = Loading.service({});
        param.append('Filename', photoName)
        param.append('key', key)
        param.append('policy', this.config.policy)
        param.append('OSSAccessKeyId', this.config.accessid)
        param.append('success_action_status', '200') // 不要问为什么，照做
        param.append('callback', this.config.callback)
        param.append('signature', this.config.signature)
        param.append('file', photo) // 这个**切记**一定要放到最后去 append ，不然阿里云会一直报 key 的错误
        axios.post(url, param, {
            headers: {
              'Content-Type': 'multipart/form-data'
            }
          }).then(response => {
            if(response.data.Status == 'Ok'){
                this.processLength = 100
                this.showProcess = false
              setTimeout(()=>{
                this.processLength = 0
                // this.$nextTick(() => { // 以服务的方式调用的 Loading 需要异步关闭
                //   loadingInstance.close();
                // });
              },200)
              self.fileList.push({name: randomStr + photoName, url: 'https://integralsys.oss-cn-shenzhen.aliyuncs.com/' + key, name: item.name, response:{
                  url: 'https://integralsys.oss-cn-shenzhen.aliyuncs.com/' + key
                }})
              self._onSuccess({status: 1, url: 'https://integralsys.oss-cn-shenzhen.aliyuncs.com/' + key, file_name: randomStr + photoName}, item, self.fileList)
            }
          }).catch(err => {
            this.showProcess = false
            // this.$nextTick(() => { // 以服务的方式调用的 Loading 需要异步关闭
            //   loadingInstance.close();
            // });
          })
      },
    }
  }
</script>

<style scoped>

</style>
