countDown.ts 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. import { ref, Ref } from 'vue'
  2. interface CountdownTimerOptions {
  3. delay?: number
  4. cacheKey?: string
  5. }
  6. /**
  7. * 倒计时
  8. * - Ref countdown、isCounting
  9. * - Fn start、stop
  10. */
  11. class CountdownTimer {
  12. delay: number
  13. cacheKey: string
  14. isCounting: Ref<boolean>
  15. countdown: Ref<number>
  16. countdownTimer: any
  17. constructor({ delay, cacheKey }: CountdownTimerOptions = {}) {
  18. this.delay = delay || 59
  19. this.cacheKey = cacheKey || 'sms-count-timer'
  20. this.isCounting = ref(false)
  21. this.countdown = ref(0)
  22. this.countdownTimer = null
  23. this.recoverCacheCountdown()
  24. }
  25. /**
  26. * 对外提供调用
  27. */
  28. getInstance() {
  29. return {
  30. countdown: this.countdown,
  31. isCounting: this.isCounting,
  32. start: this.startCountdown.bind(this),
  33. stop: this.stopTimer.bind(this)
  34. }
  35. }
  36. /**
  37. * 开始倒计时
  38. */
  39. startCountdown() {
  40. if (!this.isCounting.value) {
  41. if (this.cacheKey) {
  42. localStorage.setItem(this.cacheKey, Date.now().toString())
  43. }
  44. this.countdown.value = this.delay
  45. this.startTimer()
  46. }
  47. }
  48. /**
  49. * 恢复缓存倒计时
  50. */
  51. recoverCacheCountdown() {
  52. if (this.cacheKey && localStorage.getItem(this.cacheKey)) {
  53. const cacheDelay = this.calcCountdown(
  54. parseInt(localStorage.getItem(this.cacheKey))
  55. )
  56. if (cacheDelay) {
  57. this.countdown.value = cacheDelay
  58. this.startTimer()
  59. }
  60. }
  61. }
  62. /**
  63. * 计算倒计时,如果超过60秒则不再计算
  64. * @param start - 需要与当前时间对比的开始时间,ms
  65. */
  66. calcCountdown(start) {
  67. const startTime = parseInt(start) || Date.now()
  68. const diffTime = Math.ceil((Date.now() - startTime) / 1000)
  69. if (diffTime > 0 && diffTime <= this.delay) {
  70. return this.delay - diffTime
  71. }
  72. return 0
  73. }
  74. /**
  75. * 开始倒计时
  76. */
  77. startTimer() {
  78. this.isCounting.value = true
  79. this.countdownTimer = setInterval(() => {
  80. this.countdown.value--
  81. if (this.countdown.value <= 0) {
  82. this.isCounting.value = false
  83. clearInterval(this.countdownTimer)
  84. if (this.cacheKey) {
  85. localStorage.removeItem(this.cacheKey)
  86. }
  87. }
  88. }, 1000)
  89. }
  90. /**
  91. * 停止倒计时
  92. */
  93. stopTimer() {
  94. clearInterval(this.countdownTimer)
  95. }
  96. }
  97. export default CountdownTimer