<!--
  @description: 倒计时组件
  @Modifier: haoFx
  @routerPath:
  @date: 2020/3/18-22:44
-->
<template>
  <div class="countdown-content">
    <!-- 文案 -->
    <p v-if="timeType!=='time'" class="time-text">
      {{ timeText }}
    </p>
    <!-- 倒计时 -->
    <div v-if="isTimeStop==='01'&&timeType!=='text'" style="display: inline-block;">
      <p class="countdown">
        <span>{{ countdownText }}</span>
        <span>{{ timeDate.day }}</span>天
        <span>{{ timeDate.hour }}</span>时
        <span>{{ timeDate.minutes }}</span>分
        <span>{{ timeDate.seconds }}</span>秒
      </p>
    </div>
  </div>
</template>

<script>
/* api*/
import { getTime } from '@api/common/tools.js' // 获取服务器时间
export default {
  name: 'CountDown',
  props: {
    // 活动结束时间
    endTime: {
      type: String,
      default: ''
    },
    // 展示倒计时类型 time 只展示倒计时 text 只展示文字 time-text 展示文字和倒计时
    timeType: {
      type: String,
      default: 'time-text'
    },
    // 倒计时结束回调
    endCallback: {
      type: Function,
      default: function() {}
    },
    // 倒计时标示文案
    countdownText: {
      type: String,
      default: '时间剩余：'
    },
    // 倒计时进行中 显示文本
    ongoingText: {
      type: String,
      default: ''
    },
    // 倒计时结束显示文本
    endText: {
      type: String,
      default: '倒计时结束'
    }
  },
  data() {
    return {
      isTimeStop: '00', // 倒计时状态 00 获取时间中 01 定时器进行中 02 定时器结束
      timeText: '正在获取时间', // 文案展示
      timeOut: '', // 到时器-定时器
      currentTime: '', // 系统当前时间
      winStCurrentTime: '', // 本地终端时间-定时器起始时间
      count: 1, // 标记执行次数
      interval: 1000, // 倒计时执行间隔时间 1000 = 1秒
      // 毫秒计算
      timeDate: {
        // 倒计时数值
        day: '', // 天
        hour: '', // 小时
        minutes: '', // 分钟
        seconds: '' // 秒
      }
    }
  },
  watch: {
    isTimeStop() {
      this.readyData()// 初始化数据
    }
    // endTime(val) {
    //   if (val) {
    //     // 计算时间
    //     this.loadTime()
    //   }
    // }
  },
  beforeDestroy() {
    clearInterval(this.timeOut)
  },
  created() {
    this.readyData()// 初始化数据
    this.getCurrentTime() // 获取当前时间
  },
  methods: {
    // 初始化数据
    readyData() {
      this.timeText = this.isTimeStop === '01' ? this.ongoingText : this.isTimeStop === '02' ? this.endText : this.timeText
    },
    // 获取当前时间
    getCurrentTime() {
      getTime().then((res) => {
        this.currentTime = res.data.time// 系统当前时间
        this.winStCurrentTime = new Date().getTime()// 本地终端时间-定时器起始时间
        // 计算时间
        this.loadTime()
      })
    },
    // 计算时间
    loadTime() {
      if (!this.currentTime && !this.endTime) return
      let endTime = '' // 活动结束时间
      let currentTime = '' // 系统当前时间
      // 活动结束时间
      if (this.endTime) {
        // 活动结束时间-处理ie不兼容日期格式
        endTime = this.endTime.replace(/-/g, '/')
        // 活动结束时间-转换时间戳
        endTime = new Date(endTime).getTime()
      }
      // 系统当前时间
      if (this.currentTime) {
        // 系统当前时间-处理ie不兼容日期格式
        currentTime = this.currentTime.replace(/-/g, '/')
        // 系统当前时间-转换时间戳
        currentTime = new Date(currentTime).getTime()
      }
      // 启动倒计时
      const data = {
        endTime, // 活动结束时间
        currentTime, // 当前系统时间
        index: this.index, // 索引
        endCallBack: this.end_callBack // 倒计时结束回调
      }
      this.runTime(data)
    },
    // 启动倒计时
    runTime(data) {
      const _s = Date.now()
      const timeDate = this.timeDate
      const { endTime, currentTime } = data
      // 倒计时执行间隔时间
      let interval = this.interval
      // 标记执行次数
      this.count++
      /*
       * 休眠误差-计算误差
       * 时间差     =    本地终端当前时间     - (本地终端时间-定时器起始时间 + 定时器执行次数 * 倒计时执行间隔时间）
      */
      let difference = new Date().getTime() - (this.winStCurrentTime + this.count * interval)
      // 若误差超过执行间隔时间，则立即校正(会出现跳秒的情况)
      if (difference > interval) {
        // 标记执行次数 = 获取时差执行次数
        this.count += Math.floor(difference / interval)
        // 校正当前时间
        data.currentTime += Math.floor(difference / interval) * interval
        // 取余
        difference = difference % interval
        // 标准间隔时差减去此次的休眠误差，为下一次执行的时间
        interval = interval - difference
      } else if (difference < 0) {
        difference = 0
      }
      // 时间戳 = 活动结束时间 - 系统当前时间
      let timeDistance = endTime - currentTime
      if (timeDistance > 0) {
        // 定时器-进行中
        this.isTimeStop = '01'
        // 计算时间
        // 天
        timeDate.day = Math.floor(timeDistance / 86400000)
        timeDistance -= timeDate.day * 86400000
        // 时
        timeDate.hour = Math.floor(timeDistance / 3600000)
        timeDistance -= timeDate.hour * 3600000
        // 分
        timeDate.minutes = Math.floor(timeDistance / 60000)
        timeDistance -= timeDate.minutes * 60000
        // 秒
        timeDate.seconds = Math.floor(timeDistance / 1000)
        timeDistance -= timeDate.seconds * 1000
        // 判断是否小于 10 如果小于0 则加 '0'
        if (timeDate.hour < 10) timeDate.hour = '0' + timeDate.hour
        if (timeDate.minutes < 10) timeDate.minutes = '0' + timeDate.minutes
        if (timeDate.seconds < 10) timeDate.seconds = '0' + timeDate.seconds
        // 定时器
        const _e = Date.now()
        //   js执行误差
        const diffPerFunc = _e - _s
        // 启动倒计时
        this.timeOut = setTimeout(() => {
          data.currentTime += this.interval
          this.runTime(data)
        }, interval - diffPerFunc)
      } else {
        // 结束回调
        this.isTimeStop = '02'
        data.endCallBack(data)
      }
    },
    // 倒计时结束回调
    end_callBack(data) {
      data = {
        ...data,
        isTimeStop: this.isTimeStop === '02' // 02 倒计时回调结束
      }
      this.endCallback(data)
    }
  }
}
</script>

<style scoped lang="less">
@import "~@assets/style/common/public.less";
@countdown-color:@hyacinthine;//倒计时文本颜色
@time-text-bc:@hyacinthine;//文本背景色样式
@time-text-h:22px;//文本背景色样式
// 时间倒计时样式
.countdown-content {
  // 倒计时样式
  .countdown {
    display: inline-block;
    span{
      padding:0 10px;
      color:@countdown-color;
      font-weight: bold;
    }
  }
  // 倒计时文本
  .time-text {
    padding: 0px 10px;
    font-size: 12px;
    line-height: @time-text-h;
    display: inline-block;
    text-align: center;
    color: white;
    background-color: @time-text-bc;
    border-radius: calc(@time-text-h / 2);
  }
}
</style>
