返回 AiToEarn
useKeepTimeCountdown.ts
根目录 / project / aitoearn-web / src / hooks / useKeepTimeCountdown.ts
1 /**
2 * useKeepTimeCountdown - 任务保留时间倒计时 Hook
3 * 根据 keepTime(秒) 和 acceptedAt(起算时间) 计算剩余秒数并每秒递减
4 */
5
6 import { useEffect, useState } from 'react'
7
8 function calcRemaining(keepTime: number, acceptedAt?: string): number {
9 if (keepTime <= 0 || !acceptedAt)
10 return -1 // -1 表示不限时
11 const deadline = new Date(acceptedAt).getTime() + keepTime * 1000
12 const remaining = Math.floor((deadline - Date.now()) / 1000)
13 return Math.max(remaining, 0)
14 }
15
16 export function formatCountdown(totalSeconds: number): string {
17 if (totalSeconds < 0)
18 return ''
19 const hours = Math.floor(totalSeconds / 3600)
20 const minutes = Math.floor((totalSeconds % 3600) / 60)
21 const seconds = totalSeconds % 60
22
23 const pad = (n: number) => String(n).padStart(2, '0')
24 return `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`
25 }
26
27 export function useKeepTimeCountdown(keepTime: number, acceptedAt?: string) {
28 const [remaining, setRemaining] = useState(() => calcRemaining(keepTime, acceptedAt))
29
30 useEffect(() => {
31 const initial = calcRemaining(keepTime, acceptedAt)
32 setRemaining(initial)
33
34 if (initial <= 0)
35 return
36
37 const timer = setInterval(() => {
38 setRemaining((prev) => {
39 if (prev <= 1) {
40 clearInterval(timer)
41 return 0
42 }
43 return prev - 1
44 })
45 }, 1000)
46
47 return () => clearInterval(timer)
48 }, [keepTime, acceptedAt])
49
50 return {
51 remaining, // 剩余秒数,-1 表示不限时,0 表示已过期
52 isExpired: remaining === 0,
53 isUnlimited: remaining < 0,
54 formatted: formatCountdown(remaining),
55 }
56 }
57
57 lines TYPESCRIPT