SFH5/hooks/useCountDown.js
2026-03-16 11:10:28 +08:00

69 lines
1.7 KiB
JavaScript

import { ref, onUnmounted } from 'vue'
import dayjs from 'dayjs'
export function useCountDown(startTime, endTime, onFinished) {
if (!startTime || !endTime) {
throw new Error('startTime and endTime are required')
}
const remaining = ref(0)
const formatted = ref('00:00:00')
let timer = null
const toTimestamp = (t) => dayjs(t).valueOf()
let startTs = toTimestamp(startTime)
let endTs = toTimestamp(endTime)
const calc = () => {
const now = dayjs().valueOf()
if (now < startTs) {
remaining.value = startTs - now
} else if (now >= startTs && now < endTs) {
remaining.value = endTs - now
} else {
remaining.value = 0
clearInterval(timer)
timer = null
onFinished && onFinished()
}
format()
}
const format = () => {
let left = remaining.value
let totalSeconds = Math.floor(left / 1000)
const days = Math.floor(totalSeconds / 86400)
totalSeconds %= 86400
const h = String(Math.floor(totalSeconds / 3600)).padStart(2, '0')
const m = String(Math.floor((totalSeconds % 3600) / 60)).padStart(2, '0')
const s = String(totalSeconds % 60).padStart(2, '0')
formatted.value = days > 0 ? `${days}${h}:${m}:${s}` : `${h}:${m}:${s}`
}
const start = () => {
// 如果已有计时器,先清掉
if (timer) clearInterval(timer)
startTs = toTimestamp(startTime)
endTs = toTimestamp(endTime)
calc()
timer = setInterval(calc, 1000)
}
const reset = (newStart, newEnd) => {
startTime = newStart
endTime = newEnd
start()
}
onUnmounted(() => {
if (timer) clearInterval(timer)
})
return {
formatted,
remaining,
start,
reset
}
}