import { addListener, ListenerCallback, removeListener, Scheduler, setTimeOut } from '../../app/Scheduler'; import BSL from '../../typings'; import { newDate } from '../../utils/datetime'; export interface Props { /** 时间戳或倒计时毫秒或时间字符串,当number不足13位时value处理成倒计时毫秒 */ value: number | string; /** 倒计时还未开始前的文本 */ label?: any; /** 重置倒计时的标识 */ resetId?: any; onClick?: () => boolean; /** 倒计时结束时触发 */ onOver?: () => void; } export interface CalcCountdownParams extends Pick { getScheduler: () => Scheduler; disabled: boolean; /** 倒计时timer函数 */ countdown: BSL.MutableRefObject; /** 当前时间戳 */ currentTimeRef: BSL.MutableRefObject; setTime: (time: number) => void; setDisabled: (value: boolean) => void; } export function _isTimestamp(value: CalcCountdownParams['value']) { return value.toString().length === 13; } export function _defaultTime(value: CalcCountdownParams['value']) { return _isTimestamp(value) ? 0 : Number(value); } export function reset(params: CalcCountdownParams) { const { countdown, setDisabled, onClick, value, setTime, getScheduler } = params; setDisabled(false); if (onClick) { setTime(_defaultTime(value)); } if (countdown.current) { removeListener(getScheduler(), countdown.current); } } export function calcCountdown(params: CalcCountdownParams) { const { value, disabled, onClick, countdown, currentTimeRef, setTime, onOver, getScheduler } = params; const isTimestamp = _isTimestamp(value); const defaultTime = _defaultTime(value); let targetTimestamp: number; if (disabled || !onClick) { if (isTimestamp) { targetTimestamp = typeof value === 'number' ? value : newDate(value).getTime(); } else { targetTimestamp = Date.now() + defaultTime; } countdown.current = (currentTime: number, overTime: number) => { currentTimeRef.current = currentTime; if (overTime >= 1000) { const remainingTime = targetTimestamp - currentTime; if (remainingTime > 0) { setTime(remainingTime); } else { reset(params); if (onOver) { onOver(); } } return true; } return false; }; // 立即执行一次 setTimeOut(getScheduler, () => { countdown.current!(Date.now(), 1000); }, 0); addListener(getScheduler, countdown.current); } }