let hoverAudio = null let clickAudio = null let unlocked = false let unlockListenerAdded = false function getHoverAudio() { if (!hoverAudio) { hoverAudio = uni.createInnerAudioContext() hoverAudio.src = '/static/sounds/hover.mp3' } return hoverAudio } function getClickAudio() { if (!clickAudio) { clickAudio = uni.createInnerAudioContext() clickAudio.src = '/static/sounds/click.mp3' } return clickAudio } /** 安全播放,吞掉 autoplay 策略导致的 Promise rejection */ function safePlay(audio) { try { audio.stop() const ret = audio.play() if (ret && typeof ret.then === 'function') { ret.catch(() => {}) } } catch (e) {} } /** 首次用户点击/触摸后解锁音频(hover 不算用户手势) */ function primeAudio() { ;[getHoverAudio(), getClickAudio()].forEach(audio => { try { audio.volume = 0 const ret = audio.play() const finish = () => { audio.stop() audio.volume = 1 } if (ret && typeof ret.then === 'function') { ret.then(finish).catch(() => { audio.volume = 1 }) } else { setTimeout(finish, 30) } } catch (e) { audio.volume = 1 } }) } export function setupSoundUnlock() { if (unlockListenerAdded || typeof document === 'undefined') return unlockListenerAdded = true const onUnlock = () => { if (unlocked) return unlocked = true primeAudio() document.removeEventListener('click', onUnlock, true) document.removeEventListener('touchstart', onUnlock, true) document.removeEventListener('keydown', onUnlock, true) } document.addEventListener('click', onUnlock, true) document.addEventListener('touchstart', onUnlock, true) document.addEventListener('keydown', onUnlock, true) } function ensureUnlocked() { if (!unlocked) { unlocked = true primeAudio() } } export function playHoverSound() { if (!unlocked) return safePlay(getHoverAudio()) } export function playClickSound() { ensureUnlocked() safePlay(getClickAudio()) } setupSoundUnlock()