8c7f633541
- var→const/let, function→arrow/class across all 13 JS files - Timer: prototype→class with ES6 getters - plan days: IIFE→Array.from declarative generation - storage/plan: unified formatDate via util.js - Bugfix: getPlanDay now filters by planId (plan switch accuracy) - Bugfix: getTodayRecord searches all months (cross-month boundary) - WXML/WXSS unchanged; public API unchanged
78 lines
1.9 KiB
JavaScript
78 lines
1.9 KiB
JavaScript
class Timer {
|
|
constructor(options = {}) {
|
|
this.onTick = options.onTick || (() => {})
|
|
this.onComplete = options.onComplete || (() => {})
|
|
|
|
this._duration = 0
|
|
this._remaining = 0
|
|
this._elapsed = 0
|
|
this._startTime = 0
|
|
this._pausedTime = 0
|
|
this._intervalId = null
|
|
this._running = false
|
|
this._paused = false
|
|
this._completed = false
|
|
}
|
|
|
|
start(duration) {
|
|
this._duration = duration
|
|
this._remaining = duration
|
|
this._elapsed = 0
|
|
this._completed = false
|
|
this._running = true
|
|
this._paused = false
|
|
this._startTime = Date.now()
|
|
this._tick()
|
|
this._intervalId = setInterval(() => { this._tick() }, 1000)
|
|
}
|
|
|
|
pause() {
|
|
if (!this._running || this._paused) return
|
|
this._paused = true
|
|
this._pausedTime = Date.now()
|
|
clearInterval(this._intervalId)
|
|
this._intervalId = null
|
|
}
|
|
|
|
resume() {
|
|
if (!this._running || !this._paused) return
|
|
this._startTime += Date.now() - this._pausedTime
|
|
this._paused = false
|
|
this._tick()
|
|
this._intervalId = setInterval(() => { this._tick() }, 1000)
|
|
}
|
|
|
|
stop() {
|
|
this._running = false
|
|
this._paused = false
|
|
clearInterval(this._intervalId)
|
|
this._intervalId = null
|
|
return this._elapsed
|
|
}
|
|
|
|
_tick() {
|
|
if (!this._running || this._paused) return
|
|
this._elapsed = Math.floor((Date.now() - this._startTime) / 1000)
|
|
this._remaining = Math.max(0, this._duration - this._elapsed)
|
|
|
|
this.onTick({
|
|
remaining: this._remaining,
|
|
elapsed: this._elapsed,
|
|
duration: this._duration
|
|
})
|
|
|
|
if (this._remaining <= 0 && !this._completed) {
|
|
this._completed = true
|
|
this.onComplete({ elapsed: this._elapsed, duration: this._duration })
|
|
}
|
|
}
|
|
|
|
get isRunning() { return this._running && !this._paused }
|
|
get isPaused() { return this._paused }
|
|
get isCompleted() { return this._completed }
|
|
get remaining() { return this._remaining }
|
|
get elapsed() { return this._elapsed }
|
|
}
|
|
|
|
module.exports = Timer
|