150 lines
4.5 KiB
Vue
150 lines
4.5 KiB
Vue
<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>
|