feat(timer): 训练时长低于阈值不记录并明确提示
- config.js 新增 minRecordSeconds: 20 阈值配置,改配置即可调整门槛 - timer.js: finishTraining/_onCircuitComplete 低时长不播完成语音; _saveAndShowCompletion 兜底判断,任何入口都不会把短时训练落库; 新增 _showNotRecorded: 不保存记录、不更新连胜,复用完成弹窗展示实际秒数 - timer.wxml/wxss: 完成弹窗新增"未计入记录"提示行(门槛说明), 未记录时隐藏"查看记录/分享"按钮,只留"再来一次+回到首页" - 修复状态残留: 未记录后点"再来一次",下次正常完成不会误显示"未计入记录"
This commit is contained in:
+64
-2
@@ -40,6 +40,10 @@ Page({
|
||||
// 组进度改由 progress-ring 外圈分段弧呈现,仅需传 sets/currentSet/resting,
|
||||
// 页面不再维护点阵渲染数据(circuitDots/dotsDone 等已随旧面板一并删除)。
|
||||
celebrationLevel: 'normal', // normal / first / milestone / record
|
||||
// 训练时长低于 config.minRecordSeconds 时置 true:完成弹窗提示"未计入记录",
|
||||
// 隐藏查看记录/分享入口;弹窗内展示门槛值给用户明确反馈
|
||||
completionNotRecorded: false,
|
||||
minRecordSeconds: 20,
|
||||
celebrationMessage: '',
|
||||
confettiPieces: [],
|
||||
// Completion modal (full-screen summary after training ends)
|
||||
@@ -435,7 +439,9 @@ Page({
|
||||
_onCircuitComplete() {
|
||||
this._clearVibrateTimers()
|
||||
const s = storage.getSettings()
|
||||
if (s.voiceGuide !== false) voice.play('complete')
|
||||
// 有效撑持秒数未达最低记录时长时不播完成语音(弹窗走"未计入记录"分支)
|
||||
const minSec = config.minRecordSeconds || 20
|
||||
if (this.data.workTotal >= minSec && s.voiceGuide !== false) voice.play('complete')
|
||||
this._saveAndShowCompletion(this.data.workTotal)
|
||||
},
|
||||
|
||||
@@ -725,8 +731,10 @@ Page({
|
||||
return
|
||||
}
|
||||
// Completion voice (replaces the old auto-onComplete cue). No vibration.
|
||||
// 未达最低记录时长时不播完成语音——弹窗会走"未计入记录"分支,不庆祝。
|
||||
const s = storage.getSettings()
|
||||
if (s.voiceGuide !== false) {
|
||||
const minSec = config.minRecordSeconds || 20
|
||||
if (elapsed >= minSec && s.voiceGuide !== false) {
|
||||
voice.play('complete')
|
||||
}
|
||||
this._saveAndShowCompletion(elapsed)
|
||||
@@ -759,6 +767,15 @@ Page({
|
||||
// Re-entry guard: protects the finishTraining path so the save never
|
||||
// runs twice even if the user double-taps end.
|
||||
if (this._saving) return
|
||||
|
||||
// 未达 config.minRecordSeconds:不写入记录/连胜,弹"未计入记录"提示。
|
||||
// 兜底判断——手动结束(finishTraining)与循环自然完成(_onCircuitComplete)
|
||||
// 两条路径最终都汇聚到这里,保证任何入口都不会把短时训练落库。
|
||||
const minSec = config.minRecordSeconds || 20
|
||||
if (elapsed < minSec) {
|
||||
this._showNotRecorded(elapsed, minSec)
|
||||
return
|
||||
}
|
||||
this._saving = true
|
||||
|
||||
const { level, message } = this._detectCelebrationLevel(elapsed)
|
||||
@@ -797,6 +814,9 @@ Page({
|
||||
// Background effects keep playing behind the modal
|
||||
status: 'completed',
|
||||
isCompleted: true,
|
||||
// 重置未记录标记(上一轮若走了 _showNotRecorded,这里必须回 false,
|
||||
// 否则下次正常完成的弹窗会误显示"未计入记录"且隐藏分享/记录按钮)
|
||||
completionNotRecorded: false,
|
||||
celebrationLevel: level,
|
||||
celebrationMessage: message,
|
||||
confettiPieces,
|
||||
@@ -827,6 +847,46 @@ Page({
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* 训练时长低于 config.minRecordSeconds:不保存记录、不更新连胜,
|
||||
* 复用完成弹窗(避免系统原生 modal 在 WebView stacking context 下
|
||||
* hit-test 不稳),弹窗内明确提示"本次未计入记录"。
|
||||
* 仍显示本次实际撑持秒数(大数字 countUp),但不放 confetti/连胜/科学提示,
|
||||
* 并隐藏"查看记录/分享"入口(没有记录可看)。
|
||||
*/
|
||||
_showNotRecorded(elapsed, minSec) {
|
||||
if (this._saving) return
|
||||
this._saving = true
|
||||
|
||||
this.setData({
|
||||
status: 'completed',
|
||||
isCompleted: true,
|
||||
completionNotRecorded: true,
|
||||
minRecordSeconds: minSec,
|
||||
showCompletion: true,
|
||||
completionElapsed: 0,
|
||||
completionActualElapsed: elapsed,
|
||||
completionTarget: this.data.duration,
|
||||
completionOvertime: 0,
|
||||
completionStreak: 0,
|
||||
completionLevel: 'normal',
|
||||
completionMessage: '未达最低记录时长',
|
||||
completionTipValue: '',
|
||||
completionTipRisk: '',
|
||||
confettiPieces: []
|
||||
})
|
||||
|
||||
// Animate the big number from 0 to elapsed (same as the normal modal)
|
||||
if (this._completionCountUp) this._completionCountUp.cancel()
|
||||
this._completionCountUp = countUp({
|
||||
from: 0,
|
||||
to: elapsed,
|
||||
duration: 1200,
|
||||
onUpdate: (v) => this.setData({ completionElapsed: v }),
|
||||
onComplete: () => { this._completionCountUp = null }
|
||||
})
|
||||
},
|
||||
|
||||
onCloseCompletion() {
|
||||
if (this._completionCountUp) {
|
||||
this._completionCountUp.cancel()
|
||||
@@ -882,6 +942,8 @@ Page({
|
||||
status: 'idle',
|
||||
isRunning: false,
|
||||
isPaused: false,
|
||||
// 复位未记录标记:若上一轮走了 _showNotRecorded,重练前必须回 false
|
||||
completionNotRecorded: false,
|
||||
remaining: this.data.duration,
|
||||
elapsed: 0,
|
||||
goalReached: false,
|
||||
|
||||
Reference in New Issue
Block a user