import { Tick } from "./tick" ; export type CountdownValueIndex = "d" | "h" | "i" | "s" ; export type CountdownValue = { [ key in CountdownValueIndex ] ? : number ; } ; export type UpdateCallback = ( value : CountdownValue ) => void ; export interface CountdownOption { remain ? : number | string ; onUpdate ? : UpdateCallback ; onEnd ? : ( ) => void ; format ? : string ; } export class Countdown { /**
     * 倒计时的剩余时间，单位为秒
     */ total = 0 ; remain = 0 ; /**
     * 当前倒计时的格式
     * d：天
     * h：时
     * i：分
     * s：秒
     */ format = [ "d" , "h" , "i" , "s" ] ; _stopTick ? : ( ) => void ; _onUpdate ? : UpdateCallback ; _onEnd ? : ( ) => void ; constructor ( option ) { if ( typeof option . remain === "number" && option . remain >= 0 ) { this . total = this . remain = option . remain ; } if ( typeof option . format === "string" ) { const parts = option . format . split ( "" ) ; const output = [ ] ; this . format . forEach ( ( item ) => { if ( parts . includes ( item ) ) { output . push ( item ) ; } } ) ; this . format = output ; } else { this . format = [ "h" , "i" , "s" ] ; } this . _onUpdate = option . onUpdate ; this . _onEnd = option . onEnd ; } onUpdate ( callback ) { this . _onUpdate = callback ; } onEnd ( callback ) { this . _onEnd = callback ; } start ( ) { if ( this . remain <= 0 ) { this . _stopTick ?. ( ) ; this . _onUpdate ?. ( this . formatValue ( ) ) ; this . _onEnd ?. ( ) ; return ; } this . _onUpdate ?. ( this . formatValue ( ) ) ; const start = Date . now ( ) ; const tickInstance = new Tick ( ( ) => { const duration = Math . floor ( ( Date . now ( ) - start ) / 1000 ) ; const currentRemain = this . total - duration ; if ( currentRemain <= 0 ) { this . remain = 0 ; this . _stopTick ?. ( ) ; this . _onUpdate ?. ( this . formatValue ( ) ) ; this . _onEnd ?. ( ) ; return ; } if ( currentRemain !== this . remain ) { this . remain = currentRemain ; this . _onUpdate ?. ( this . formatValue ( ) ) ; } } ) ; tickInstance . start ( ) ; this . _stopTick = ( ) => tickInstance . destroy ( ) ; } stop ( ) { this . total = this . remain ; this . _stopTick ?. ( ) ; } param remainTime formatValue ( ) { let remainTime = this . remain ; const result = { } ; this . format . forEach ( ( key ) => { switch ( key ) { case "d" : result . d = Math . floor ( remainTime / 86400 ) ; remainTime = remainTime - result . d * 86400 ; break ; case "h" : result . h = Math . floor ( remainTime / 3600 ) ; remainTime = remainTime - result . h * 3600 ; break ; case "i" : result . i = Math . floor ( remainTime / 60 ) ; remainTime = remainTime - result . i * 60 ; break ; case "s" : result . s = remainTime ; break ; default : break ; } } ) ; return result ; } }