1.0.1 - Update

- 将时间判断方法改为时间戳判断,修复息屏后无法计时的问题。
This commit is contained in:
RiseForever
2026-08-29 18:13:48 +08:00
parent 982e1add78
commit 025050dde0
11 changed files with 348 additions and 91 deletions
+89 -30
View File
@@ -43,8 +43,13 @@ export default {
paused: false,
isResting: false,
focusDurationSeconds: 1200,
focusTotalSeconds: 0,
restTotalSeconds: 0,
restDurationSeconds: 300,
// 息屏后 setInterval 会被系统挂起,所有计时以时间戳为准
phaseEndAt: 0,
lastCountedAt: 0,
lastPersistAt: 0,
focusTotalMs: 0,
restTotalMs: 0,
focusTotalText: "00:00:00",
restTotalText: "00:00:00"
},
@@ -56,51 +61,88 @@ export default {
this.clockTimer = setInterval(() => this.updateTime(), 1000)
},
onShow() {
// 亮屏后立刻按时间戳补齐息屏期间的进度
this.updateTime()
this.sync()
},
onDestroy() {
clearInterval(this.clockTimer)
clearInterval(this.countdownTimer)
this.countdownTimer = null
if (!this.paused) {
this.accumulate(Date.now())
this.updateStats()
}
this.persistStats(true)
},
startCountdown(seconds) {
clearInterval(this.countdownTimer)
this.focusDurationSeconds = seconds > 0 ? seconds : 1200
this.remaining = this.focusDurationSeconds
this.isResting = false
this.paused = false
this.updateCountdown()
this.countdownTimer = setInterval(() => this.tick(), 1000)
this.beginPhase(false, this.focusDurationSeconds, Date.now())
this.ensureTicking()
},
startRest() {
this.remaining = 300
this.isResting = true
startRest(startAt) {
this.beginPhase(true, this.restDurationSeconds, startAt)
this.paused = true
},
beginPhase(isResting, durationSeconds, startAt) {
this.isResting = isResting
this.paused = false
this.phaseEndAt = startAt + durationSeconds * 1000
this.lastCountedAt = startAt
this.remaining = durationSeconds
this.updateCountdown()
},
ensureTicking() {
if (this.countdownTimer === null) {
this.countdownTimer = setInterval(() => this.sync(), 1000)
}
},
updateTime() {
const now = new Date()
const pad = (value) => (value < 10 ? `0${value}` : `${value}`)
this.time = `${pad(now.getHours())}:${pad(now.getMinutes())}`
},
tick() {
if (this.paused || this.remaining <= 0) return
this.remaining -= 1
if (this.isResting) this.restTotalSeconds += 1
else this.focusTotalSeconds += 1
this.updateStats()
this.persistStats()
this.updateCountdown()
if (this.remaining === 0) {
// 把 lastCountedAt 到 untilAt 之间的时间计入当前阶段的累计值
accumulate(untilAt) {
const delta = untilAt - this.lastCountedAt
if (delta <= 0) return
if (this.isResting) this.restTotalMs += delta
else this.focusTotalMs += delta
this.lastCountedAt = untilAt
},
sync() {
// phaseEndAt 为 0 表示还没开始计时
if (this.paused || this.phaseEndAt === 0) return
const now = Date.now()
// 息屏期间可能已跨过一个或多个阶段,逐段结算
while (now >= this.phaseEndAt) {
this.accumulate(this.phaseEndAt)
const endedAt = this.phaseEndAt
if (this.isResting) {
vibrator.vibrate({ mode: "short" })
this.startCountdown(this.focusDurationSeconds)
this.beginPhase(false, this.focusDurationSeconds, endedAt)
} else {
vibrator.vibrate({ mode: "long" })
this.startRest()
this.startRest(endedAt)
break
}
}
if (!this.paused) {
this.accumulate(now)
this.remaining = Math.max(0, Math.round((this.phaseEndAt - now) / 1000))
this.updateCountdown()
}
this.updateStats()
this.persistStats(false)
},
durationSeconds(config) {
@@ -117,8 +159,8 @@ export default {
},
updateStats() {
this.focusTotalText = this.formatDuration(this.focusTotalSeconds)
this.restTotalText = this.formatDuration(this.restTotalSeconds)
this.focusTotalText = this.formatDuration(Math.floor(this.focusTotalMs / 1000))
this.restTotalText = this.formatDuration(Math.floor(this.restTotalMs / 1000))
},
formatDuration(totalSeconds) {
@@ -136,8 +178,9 @@ export default {
try {
const stats = JSON.parse(data.text)
if (stats.date === this.today()) {
this.focusTotalSeconds = parseInt(stats.focus, 10) || 0
this.restTotalSeconds = parseInt(stats.rest, 10) || 0
// 读取是异步的,期间可能已经累计了一点时间,用加法避免被覆盖
this.focusTotalMs += (parseInt(stats.focus, 10) || 0) * 1000
this.restTotalMs += (parseInt(stats.rest, 10) || 0) * 1000
}
} catch (error) {}
this.updateStats()
@@ -146,13 +189,17 @@ export default {
})
},
persistStats() {
persistStats(force) {
const now = Date.now()
// 每秒写盘没有必要,节流到 5 秒;退出/暂停时强制落盘
if (!force && now - this.lastPersistAt < 5000) return
this.lastPersistAt = now
file.writeText({
uri: "internal://files/focus-stats.json",
text: JSON.stringify({
date: this.today(),
focus: this.focusTotalSeconds,
rest: this.restTotalSeconds
focus: Math.floor(this.focusTotalMs / 1000),
rest: Math.floor(this.restTotalMs / 1000)
})
})
},
@@ -164,7 +211,19 @@ export default {
},
togglePause() {
this.paused = !this.paused
if (this.paused) {
// 恢复:把剩余秒数换算成新的结束时间戳
const now = Date.now()
this.phaseEndAt = now + this.remaining * 1000
this.lastCountedAt = now
this.paused = false
this.ensureTicking()
} else {
this.accumulate(Date.now())
this.paused = true
this.updateStats()
this.persistStats(true)
}
},
stopTimer() {