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'
}
}