69 lines
1.7 KiB
JavaScript
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
|
|
}
|
|
}
|