From ed16ac5efd183beb5aece75b25135f212ea22e1b Mon Sep 17 00:00:00 2001 From: cnliucheng Date: Thu, 9 Jul 2026 10:36:14 +0800 Subject: [PATCH] =?UTF-8?q?fix(vibrate):=20=E4=BF=AE=E5=A4=8D=E6=97=A7?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E9=9C=87=E5=8A=A8=E5=A4=B1=E6=95=88=20+=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E9=9C=87=E5=8A=A8=E5=BC=BA=E5=BA=A6=E9=80=89?= =?UTF-8?q?=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因:user_settings 早期无 vibrate 字段,getSettings 未兜底, _remind 的 !s.vibrate 误判 undefined 为关闭,导致震动静默失效, 需手动操作开关才恢复。 - storage: getSettings 兜底 vibrate/voiceGuide/vibrateIntensity 默认值 - timer: !s.vibrate 改 === false,字段缺失视为开(与 voiceGuide 一致) - timer: vibrate 按 vibrateIntensity 选 API(light/medium=vibrateShort, heavy=vibrateLong),fail 回调辅助排查 - settings: 新增"震动强度"三档(短促/标准/强烈),默认强烈 Co-Authored-By: Claude Fable 5 --- config.js | 4 ++-- pages/settings/settings.js | 16 ++++++++++++++++ pages/settings/settings.wxml | 15 +++++++++++++++ pages/timer/timer.js | 18 ++++++++++++++++-- utils/storage.js | 10 +++++++++- 5 files changed, 58 insertions(+), 5 deletions(-) diff --git a/config.js b/config.js index 3d6542e..1bf5ad2 100644 --- a/config.js +++ b/config.js @@ -24,7 +24,7 @@ module.exports = { * speed: 语速 -2~2(正数加快,0 为默认)。 */ tts: { - female: { voiceType: 502005, volume: 9, speed: 1 }, - male: { voiceType: 602005, volume: 9, speed: 1 } + female: { voiceType: 501004, volume: 9, speed: 1 }, + male: { voiceType: 502005, volume: 9, speed: 1 } } } diff --git a/pages/settings/settings.js b/pages/settings/settings.js index 586fa6d..af58fcc 100644 --- a/pages/settings/settings.js +++ b/pages/settings/settings.js @@ -58,6 +58,12 @@ Page({ { key: 'female', name: '女声' }, { key: 'male', name: '男声' } ], + vibrateIntensity: 'heavy', + vibrateIntensityOptions: [ + { key: 'light', name: '短促' }, + { key: 'medium', name: '标准' }, + { key: 'heavy', name: '强烈' } + ], icons: iconsMod.build(), nickName: '', avatarUrl: '', @@ -92,6 +98,7 @@ Page({ voiceGuide: s.voiceGuide, vibrate: s.vibrate, voiceGender: s.voiceGender || 'female', + vibrateIntensity: s.vibrateIntensity || 'heavy', currentThemeId: theme.id, theme, icons: iconsMod.build(theme), @@ -253,6 +260,15 @@ Page({ this.setData({ voiceGender: key }) }, + onSelectVibrateIntensity(e) { + const key = e.currentTarget.dataset.key + if (key === this.data.vibrateIntensity) return + const s = storage.getSettings() + s.vibrateIntensity = key + storage.saveSettings(s) + this.setData({ vibrateIntensity: key }) + }, + onCopyWechat() { wx.setClipboardData({ data: config.developer, diff --git a/pages/settings/settings.wxml b/pages/settings/settings.wxml index 98a872d..df12838 100644 --- a/pages/settings/settings.wxml +++ b/pages/settings/settings.wxml @@ -140,6 +140,21 @@ + + + + 震动强度 + + + {{item.name}} + + diff --git a/pages/timer/timer.js b/pages/timer/timer.js index a5b3f3d..433587f 100644 --- a/pages/timer/timer.js +++ b/pages/timer/timer.js @@ -132,13 +132,27 @@ Page({ const s = storage.getSettings() const { remaining, elapsed, duration } = tick const vibrate = (n, ms) => { - if (!s.vibrate) return + // `=== false` (not `!s.vibrate`) so an undefined field (legacy users + // whose settings predate the toggle) is treated as ON, matching the + // voiceGuide check below. `!s.vibrate` used to see undefined as falsy + // and silently skip vibration until the user toggled the switch. + if (s.vibrate === false) return + const intensity = s.vibrateIntensity || 'heavy' + // light/medium = vibrateShort(type); heavy = vibrateLong(400ms). + // vibrateLong is the most reliable on iOS real devices; the short + // types are nicer but may be silent on some devices - user picks. + const doVibrate = () => { + const fail = (err) => console.warn('[vibrate] failed:', err.errMsg || err) + if (intensity === 'light') wx.vibrateShort({ type: 'light', fail }) + else if (intensity === 'medium') wx.vibrateShort({ type: 'medium', fail }) + else wx.vibrateLong({ fail }) + } try { for (let i = 0; i < n; i++) { // Track timers so pause/stop/unload can cancel pending bursts // instead of firing vibrations on a page that's already torn down. const id = setTimeout(() => { - wx.vibrateShort() + doVibrate() const idx = this._vibrateTimers.indexOf(id) if (idx > -1) this._vibrateTimers.splice(idx, 1) }, i * (ms + 30)) diff --git a/utils/storage.js b/utils/storage.js index 9ce82cb..a59a2e2 100644 --- a/utils/storage.js +++ b/utils/storage.js @@ -170,13 +170,21 @@ const getSettings = () => { // Backfill voiceGender for existing users (added with the male/female // voice option). Defaults to female, the prior behavior. if (!s.voiceGender) s.voiceGender = 'female' + // Backfill vibrate/voiceGuide for users whose settings predate these + // toggles. Without this, s.vibrate is undefined and `!s.vibrate` in + // the timer reads it as "off" - vibration silently no-ops until the + // user manually toggles the switch (which writes a real boolean). + if (s.vibrate == null) s.vibrate = true + if (s.voiceGuide == null) s.voiceGuide = true + if (!s.vibrateIntensity) s.vibrateIntensity = 'heavy' return s } return { planId: 'beginner', voiceGuide: true, vibrate: true, - voiceGender: 'female' + voiceGender: 'female', + vibrateIntensity: 'heavy' } }