<!-- 电子签名 -->
<template>
  <cs-field
    ref="csField"
    class="cs-signature"
    v-model="currentValue"
    :label="label"
    :rules="rules"
    :rules-key="rulesKey"
    :disabled="disabled"
    :colon="colon"
    :required="required"
    :error-message-align="errorMessageAlign"
    :label-class="labelClass"
    :label-width="labelWidth"
    :label-align="labelAlign"
    :input-align="inputAlign"
    :popupCloseable="true"
    right-icon="edit"
    @click="showPicker"
  >
    <div :class="disabled ? 'disabled' : ''">
      <div class="upload-image" v-if="currentValue">
        <img class="image-item" :src="currentUrl" />
        <van-icon class="delete" name="clear" @click.stop="deleteImage(index)" v-if="!readonly" />
      </div>
      <span class="placeholder" v-else>{{ currentPlaceholder }}</span>
    </div>

    <template #popup>
      <!-- 标题 -->
      <div class="title">{{ title }}</div>

      <div id="vueApp" class="page">
        <div class="wrapper">
          <div class="handBtn">
            <div
              class="black-select"
              @click="selectColorEvent('black', '#1A1A1A')"
              :class="[selectColor === 'black' ? 'color_select' : '']"
            ></div>
            <div
              class="red-select"
              @click="selectColorEvent('red', '#ca262a')"
              :class="[selectColor === 'red' ? 'color_select' : '']"
            ></div>
            <van-tag type="default" size="large" plain @click="cancel" class="return">返 回</van-tag>
            <van-tag type="default" size="large" plain @click="clearArea" class="delBtn">重 写</van-tag>
            <van-tag type="default" size="large" plain @click="previewCanvasImg" class="previewBtn">预 览</van-tag>
            <van-tag type="success" size="large" @click="saveSign" class="subBtn">确 认</van-tag>
          </div>
          <div class="handCenter sign-wrap" id="signWrap">
            <canvas id="myCanvas"></canvas>
          </div>
          <div class="handRight">
            <div class="handTitle">请签名</div>
          </div>
          <van-overlay :show="show" @click="show = false">
            <div class="wrapper1">
              <img :src="image" class="block" />
            </div>
          </van-overlay>
        </div>
      </div>
    </template>
  </cs-field>
</template>
<script>
import CsField from '../Base'
import mixin from '../mixin'
import { i18n } from '../../../..//lib/locale/lang/index'

export default {
  name: 'CsFieldSignature',
  components: { CsField },
  mixins: [mixin],
  props: {
    // 租户编号
    tenantId: {
      default: null
    },
    // 只读
    readonly: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      i18nLang: new Vue({ i18n }),
      currentValue: this.value,
      imageUrl: '',

      show: false,
      image: '',
      mousePressed: false,
      c: null,
      ctx: null,
      lastX: 0,
      lastY: 0,
      selectColor: 'black',
      lineColor: '#1A1A1A',
      lineWidth: 5, //下笔的宽度 [Number] 可选
      lineCap: 'round', //线条的边缘类型 [butt]平直的边缘 [round]圆形线帽 [square]	正方形线帽
      lineJoin: 'round', //线条交汇时边角的类型  [bevel]创建斜角 [round]创建圆角 [miter]创建尖角。
      lineSize: 1.5, // 笔记倍数
      lineMin: 0.5, // 最小笔画半径
      lineMax: 4, // 最大笔画半径
      pressure: 1, // 默认压力
      smoothness: 60 //顺滑度，用60的距离来计算速度
    }
  },
  //监听属性 类似于data概念
  computed: {
    currentPlaceholder() {
      if (this.placeholder) {
        return this.placeholder
      } else {
        return this.i18nLang.$t('common.placeholderSignature')
      }
    },
    currentUrl() {
      if (!this.currentValue) {
        return ''
      }
      return this.$util.getThumbnail(this.tenantId, this.currentValue)
    }
  },
  //监控data中的数据变化
  watch: {
    value: {
      handler(val, oldVal) {
        if (this.currentValue != val && val !== oldVal) {
          this.currentValue = this.value
        }
      },
      immediate: true, // 首次绑定是否执行
      deep: true // 对象内部的属性监听，也叫深度监听
    },
    currentValue: {
      handler(val, oldVal) {
        this.$emit('input', val)
      },
      immediate: true, // 首次绑定是否执行
      deep: true // 对象内部的属性监听，也叫深度监听
    }
  },
  //方法集合
  methods: {
    change() {
      this.$forceUpdate()
    },

    /** 删除图片 */
    deleteImage(index) {
      vant.Dialog.confirm({
        message: `请确认是否要删除签名？`
      })
        .then(() => {
          this.currentValue = ''
          this.$util.info('删除成功')
        })
        .catch(() => {})
    },

    /** 弹出选择框 */
    showPicker() {
      if (this.disabled) {
        return
      }
      this.$refs.csField.showPopup = true
      this.$nextTick(() => {
        this.image = ''
        this.mousePressed = false
        this.ctx = document.getElementById('myCanvas').getContext('2d')
        this.c = document.getElementById('myCanvas')
        var signWrap = document.getElementById('signWrap')
        this.c.width = signWrap.clientWidth // 设置宽度
        this.c.height = signWrap.clientHeight // 设置高度
        // 监听touchstart事件，touchmove事件，touchend事件等事件
        this.initEventListener()
      })
    },

    /** 切换颜色 */
    selectColorEvent(str, color) {
      this.selectColor = str
      this.lineColor = color
    },

    /** 返回 */
    cancel() {
      this.$refs.csField.showPopup = false
    },

    /** 清空画板 */
    clearArea() {
      this.ctx.setTransform(1, 0, 0, 1, 0, 0)
      this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height)
    },

    /** 预览 */
    previewCanvasImg() {
      this.show = true
      this.image = this.c.toDataURL('image/png') // 得到生成后的签名base64数据
    },

    /** 初始化监听事件 */
    initEventListener() {
      var that = this
      // 手指触摸屏幕时触发
      this.c.addEventListener(
        'touchstart',
        function (event) {
          if (event.targetTouches.length == 1) {
            event.preventDefault() // 阻止浏览器默认事件，重要
            var touch = event.targetTouches[0]
            // 当前滚动条高度
            let scrollTop = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop
            this.mousePressed = true
            that.setDraw(touch.pageX - this.offsetLeft, touch.pageY - this.offsetTop - scrollTop, false)
          }
        },
        false
      )
      // 手指在屏幕滑动时触发
      this.c.addEventListener(
        'touchmove',
        function (event) {
          if (event.targetTouches.length == 1) {
            event.preventDefault() // 阻止浏览器默认事件，重要
            var touch = event.targetTouches[0]
            // 当前滚动条高度
            let scrollTop = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop
            if (this.mousePressed) {
              that.setDraw(touch.pageX - this.offsetLeft, touch.pageY - this.offsetTop - scrollTop, true)
            }
          }
        },
        false
      )
      // 手指从屏幕时移开时触发
      this.c.addEventListener(
        'touchend',
        function (event) {
          if (event.targetTouches.length == 1) {
            event.preventDefault() // 阻止浏览器默认事件，防止手写的时候拖动屏幕，重要
            this.mousePressed = false
          }
        },
        false
      )

      // 鼠标按下事件
      this.c.onmousedown = function (event) {
        this.mousePressed = true
        let scrollTop = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop
        that.setDraw(event.pageX - this.offsetLeft, event.pageY - this.offsetTop - scrollTop, false)
      }
      // 鼠标指针移动事件
      this.c.onmousemove = function (event) {
        if (this.mousePressed) {
          let scrollTop = window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop
          that.setDraw(event.pageX - this.offsetLeft, event.pageY - this.offsetTop - scrollTop, true)
        }
      }
      // 鼠标释放事件
      this.c.onmouseup = function (event) {
        this.mousePressed = false
      }
    },
    /** 设置画布 */
    setDraw(x, y, isDown) {
      if (isDown) {
        this.ctx.beginPath()
        this.ctx.strokeStyle = this.lineColor // 颜色
        this.ctx.lineWidth = this.lineWidth // 线宽
        this.ctx.lineCap = this.lineCap
        this.ctx.lineJoin = this.lineJoin
        this.ctx.lineMax = this.lineMax // 设置画笔最大线宽
        this.ctx.lineMin = this.lineMin // 设置画笔最小线宽
        this.ctx.linePressure = this.pressure // 设置画笔笔触压力
        this.ctx.smoothness = this.smoothness // 设置画笔笔触大小变化的平滑度
        this.ctx.moveTo(this.lastX, this.lastY)
        this.ctx.lineTo(x, y)
        this.ctx.closePath()
        this.ctx.stroke()
      }
      this.lastX = x
      this.lastY = y
    },

    /** 提交签名 */
    saveSign() {
      if (this.isCanvasBlank(this.c)) {
        alert('请在签名区域签名后再次确认')
        return
      }
      var img = new Image()
      img.src = this.c.toDataURL('image/png') // 得到生成后的签名base64位  url 地址
      img.onload = () => {
        let clipCanvas = document.createElement('canvas')
        clipCanvas.width = this.c.height
        clipCanvas.height = this.c.width
        let ctx = clipCanvas.getContext('2d')
        ctx.translate(0, clipCanvas.height)
        ctx.rotate((-90 * Math.PI) / 180)
        ctx.drawImage(img, 0, 0, clipCanvas.height, clipCanvas.width)
        var image2 = clipCanvas.toDataURL('image/png', 1)
        this.uploadBase64Image(image2)
      }
    },

    /** 验证canvas画布是否为空函数 */
    isCanvasBlank(canvas) {
      var blank = document.createElement('canvas') // 系统获取一个空canvas对象
      blank.width = canvas.width
      blank.height = canvas.height
      return canvas.toDataURL() == blank.toDataURL() // 比较值相等则为空
    },

    /** 上传base64图片 */
    uploadBase64Image(base64Image) {
      vant.Toast.loading({
        duration: 0,
        message: `正在上传中...`,
        forbidClick: true
      })
      var base64Body = base64Image.split(';base64,')[1]
      this.postAxios(
        `//api/v2/Foundation/DbFile`,
        { action: 'NewBase64', tenantId: this.tenantId, fileName: `电子签名-${new Date().getTime()}` },
        base64Body,
        null,
        { disableLoading: true }
      )
        .then(res => {
          vant.Toast.clear()
          this.currentValue = res.Id
          this.cancel()
          this.$util.info('上传成功')
        })
        .catch(error => {
          this.$util.warning('上传失败')
          vant.Toast.clear()
        })
    }
  },
  //生命周期 - 创建完成（可以访问当前this实例）
  created() {},
  //生命周期 - 挂载完成（可以访问DOM元素）
  mounted() {},
  beforeCreate() {}, //生命周期 - 创建之前
  beforeMount() {}, //生命周期 - 挂载之前
  beforeUpdate() {}, //生命周期 - 更新之前
  updated() {}, //生命周期 - 更新之后
  beforeDestroy() {}, //生命周期 - 销毁之前
  destroyed() {}, //生命周期 - 销毁完成
  activated() {} //如果页面有keep-alive缓存功能，这个函数会触发
}
</script>
<style lang="scss" scoped>
.cs-signature {
  .upload-image {
    position: relative;
    text-align: center;

    .image-item {
      max-width: 80%;
      border: 1px dashed #d9d9d9;
    }

    .delete {
      position: absolute;
      top: 7px;
      right: 10%;
      opacity: 0.8;
      color: #969799;
      width: 25px;
      height: 25px;
      border-radius: 0 0 0 15px;
      z-index: 100;
      font-size: 16px;
    }
  }

  .page {
    /* background: #fbfbfb; */
    background: #f9f9f9;
    height: 100%;
    overflow: hidden;

    .wrapper {
      width: 100%;
      height: calc(100% - 30px);
      /* height: 95vh; */
      margin: 15px 0;
      overflow: hidden;
      display: flex;
      align-content: center;
      flex-direction: row;
      justify-content: center;
      font-size: 14px;

      .handCenter {
        border: 2px dashed #e9e9e9;
        flex: 5;
        overflow: hidden;
        box-sizing: border-box;
        background: #fff;
      }

      .handBtn {
        display: inline-flex;
        flex-direction: column;
        justify-content: space-between;
        align-content: space-between;
        flex: 1;

        .return {
          position: absolute;
          top: 125px;
          left: 3px;
          transform: rotate(90deg);
          color: #666;
        }

        .delBtn {
          position: absolute;
          top: 190px;
          left: 3px;
          transform: rotate(90deg);
          color: #666;
        }

        .previewBtn {
          position: absolute;
          top: 255px;
          left: 3px;
          transform: rotate(90deg);
          color: #666;
        }

        .subBtn {
          position: absolute;
          bottom: 45px;
          left: -22px;
          transform: rotate(90deg);
          text-align: center;
          display: block;
          padding: 7px 30px;
          font-size: 16px;
        }

        .black-select {
          width: 26px;
          height: 26px;
          position: absolute;
          top: 15px;
          left: 12px;
          border-radius: 50%;
          background: #1a1a1a;
          border: 5px solid #f9f9f9;
          box-sizing: initial;
        }

        .red-select {
          width: 26px;
          height: 26px;
          position: absolute;
          top: 60px;
          left: 12px;
          border-radius: 50%;
          background: #ca262a;
          border: 5px solid #f9f9f9;
          box-sizing: initial;
        }

        .color_select {
          border: 5px solid #fff;
          box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
        }
      }

      .handRight {
        display: inline-flex;
        align-items: center;

        .handTitle {
          transform: rotate(90deg);
          flex: 1;
          color: #666;
        }
      }

      .wrapper1 {
        display: flex;
        align-items: center;
        justify-content: center;
        height: 100%;

        .block {
          width: 90%;
          height: 90%;
          background-color: #fff;
          border-radius: 3px;
        }
      }
    }
  }
}
</style>
<style lang="scss">
.cs-signature {
  .van-popup {
    height: 100vh;

    .van-tag {
      padding: 7px;
      margin: 5px;
    }
  }

  .van-popup__close-icon {
    display: none;
  }
}
</style>
