yunshangxie/tuniao-ui/components/tn-verification-code/tn-verification-code.vue

150 lines
4.5 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="tn-code-class tn-code">
</view>
</template>
<script>
export default {
name: 'tn-verification-code',
props: {
// 倒计时总秒数
seconds: {
type: Number,
default: 60
},
// 开始时提示文字
startText: {
type: String,
default: '获取验证码'
},
// 倒计时提示文字
countDownText: {
type: String,
default: 's秒后重新获取'
},
// 结束时提示文字
endText: {
type: String,
default: '重新获取'
},
// 是否在H5刷新或各端返回再进入时继续倒计时
keepRunning: {
type: Boolean,
default: false
},
// 为了区分多个页面,或者一个页面多个倒计时组件本地存储的继续倒计时变了
uniqueKey: {
type: String,
default: ''
}
},
data() {
return {
timer: null,
secNum: this.seconds,
// 是否可以执行验证码操作
canGetCode: true
}
},
watch: {
seconds: {
handler(n) {
this.secNum = n
},
immediate: true
}
},
mounted() {
this.checkKeepRunning()
},
beforeDestroy() {
this.setTimeToStorage()
if (this.timer) {
clearInterval(this.timer)
this.timer = null
}
},
methods: {
// 检查是否继续运行
checkKeepRunning() {
// 获取上一次退出页面时的时间戳,如果没有上次保存,该值为空
let lastTimestamp = Number(uni.getStorageSync(this.uniqueKey + '_$tCountDownTimestamp'))
if (!lastTimestamp) return this.changeEvent(this.startText)
// 当前秒的时间戳
// + new Date() 相当于 new Date().getTime()
let nowTimestamp = Math.floor((+ new Date()) / 1000)
// 判断当前的时间戳,是否小于上一次的设定结束的时间,提前于结束的时间戳
if (this.keepRunning && lastTimestamp && lastTimestamp > nowTimestamp) {
// 剩余尚未执行完倒计时秒数
this.secNum = lastTimestamp - nowTimestamp
// 清除本地保存的变量
uni.removeStorageSync(this.uniqueKey + '_$tCountDownTimestamp')
// 开始倒计时
this.start()
} else {
// 如果不存在需要继续上一次的倒计时,执行正常的逻辑
this.changeEvent(this.startText);
}
},
// 开始倒计时
start() {
// 防止快速点击获取验证码按钮导致产生多个定时器导致混乱
if (this.timer) {
clearInterval(this.timer)
this.timer = null
}
this.$emit('start')
this.canGetCode = false
this.changeEvent(this.countDownText.replace(/s|S/, this.secNum))
this.setTimeToStorage()
this.timer = setInterval(() => {
if (--this.secNum) {
this.changeEvent(this.countDownText.replace(/s|S/, this.secNum))
} else {
// 倒计时结束,清空定时器、重置提示信息
this.reset()
this.$emit('end')
}
}, 1000)
},
// 重置倒计时
reset() {
this.canGetCode = true
if (this.timer) {
clearInterval(this.timer)
this.timer = null
}
this.secNum = this.seconds
this.changeEvent(this.endText)
},
// 倒计时改变事件
changeEvent(text) {
this.$emit('change', text)
},
// 保存当前时间戳
// 防止倒计时尚未结束H5刷新或者各端的右上角返回上一页再进来
setTimeToStorage() {
if (!this.keepRunning ||!this.timer) return
// 记录当前的时间戳,为了下次进入页面,如果还在倒计时内的话,继续倒计时
// 倒计时尚未结束结果大于0倒计时已经开始就会小于初始值如果等于初始值说明没有开始倒计时无需处理
if (this.secNum > 0 && this.secNum <= this.seconds) {
let nowTimestamp = Math.floor((+ new Date()) / 1000)
// 保存本次倒计时结束时候的时间戳
uni.setStorageSync(this.uniqueKey + '_$tCountDownTimestamp', nowTimestamp + this.secNum)
}
}
}
}
</script>
<style lang="scss" scoped>
.tn-code {
width: 0;
height: 0;
position: fixed;
z-index: -1;
}
</style>