From fe8b38bc6f4b49bda915b12bd160822f0b4fd6de Mon Sep 17 00:00:00 2001 From: zhangyibo95 <690096405@qq.com> Date: Fri, 22 May 2026 17:57:20 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E4=BF=AE=E5=A4=8D=E8=AF=AD=E9=9F=B3?= =?UTF-8?q?=EF=BC=8C=E5=B0=84=E7=AE=AD=E6=95=B0=E5=AD=97=EF=BC=8C=E7=AC=AC?= =?UTF-8?q?=E4=B8=80=E8=BD=AE=E6=8F=90=E5=89=8D=E6=8A=A5=E9=9D=B6=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/audioManager.js | 53 ++++++++++++++++++- .../team-battle/components/HeaderProgress.vue | 14 ++--- .../team-battle/components/ShootProgress2.vue | 6 +-- src/pages/team-battle/index.vue | 31 ++++++++++- 4 files changed, 91 insertions(+), 13 deletions(-) diff --git a/src/audioManager.js b/src/audioManager.js index 44fe3a5..a0f55bb 100644 --- a/src/audioManager.js +++ b/src/audioManager.js @@ -1,3 +1,6 @@ +export const AUDIO_INTERRUPTION_BEGIN_EVENT = "audio-interruption-begin"; +export const AUDIO_INTERRUPTION_END_EVENT = "audio-interruption-end"; + export const audioFils = { tententen: "https://static.shelingxingqiu.com/shootmini/static/audio/tententen.mp3", 点击按钮: "https://static.shelingxingqiu.com/shootmini/static/audio/%E7%82%B9%E5%87%BB%E6%8C%89%E9%92%AE.mp3", @@ -97,7 +100,7 @@ function debugLog(...args) { const envVersion = accountInfo.miniProgram.envVersion; // 只在体验版打印日志,正式版(release)和开发版(develop)不打印 - if (envVersion === "trial") { + if (envVersion === "trial" || envVersion === "develop") { console.log(...args); } } @@ -127,6 +130,7 @@ class AudioManager { // 防重复播放保护 this.lastPlayKey = null; this.lastPlayAt = 0; + this.isInterrupted = false; // 静音开关 this.isMuted = false; @@ -141,10 +145,41 @@ class AudioManager { this.localFileCache = uni.getStorageSync("audio_local_files") || {}; // 启动时自动清理过期的缓存文件(URL 已不在 audioFils 中的文件) this.cleanObsoleteCache(); + this.bindAudioInterruptionEvents(); this.initAudios(); } + bindAudioInterruptionEvents() { + if (this._audioInterruptionBound) return; + this._audioInterruptionBound = true; + + const begin = () => { + if (this.isInterrupted) return; + this.isInterrupted = true; + this.stopAll(); + this.isSequenceRunning = false; + this.sequenceQueue = []; + this.sequenceIndex = 0; + this.pendingPlayKey = null; + uni.$emit(AUDIO_INTERRUPTION_BEGIN_EVENT); + }; + + const end = () => { + if (!this.isInterrupted) return; + this.isInterrupted = false; + uni.$emit(AUDIO_INTERRUPTION_END_EVENT); + void this.reloadAll(); + }; + + if (typeof uni?.onAudioInterruptionBegin === "function") { + uni.onAudioInterruptionBegin(begin); + } + if (typeof uni?.onAudioInterruptionEnd === "function") { + uni.onAudioInterruptionEnd(end); + } + } + // 清理不再使用的缓存文件 cleanObsoleteCache() { const activeUrls = new Set(Object.values(audioFils)); @@ -461,6 +496,10 @@ class AudioManager { // 播放指定音频或音频数组(数组则按顺序连续播放) play(input, interrupt = true) { + if (this.isInterrupted) { + debugLog("音频处理中断状态,忽略播放请求"); + return; + } // 统一规范化为队列 let queue = []; if (Array.isArray(input)) { @@ -514,6 +553,10 @@ class AudioManager { // 内部方法:播放单个 key _playSingle(key, forceStopAll = false) { + if (this.isInterrupted) { + debugLog(`音频处理中断状态,跳过播放: ${key}`); + return; + } // 200ms 内的同 key 重复播放直接忽略,避免“比比赛开始”这类重复首音 const now = Date.now(); if (this.lastPlayKey === key && now - this.lastPlayAt < 250) { @@ -557,7 +600,13 @@ class AudioManager { // 显式授权播放并立即播放 this.allowPlayMap.set(key, true); - audio.play(); + try { + audio.play(); + } catch (err) { + this.allowPlayMap.set(key, false); + debugLog(`音频 ${key} 播放调用失败`, err?.errMsg || err); + return; + } this.currentPlayingKey = key; this.lastPlayKey = key; this.lastPlayAt = Date.now(); diff --git a/src/pages/team-battle/components/HeaderProgress.vue b/src/pages/team-battle/components/HeaderProgress.vue index 4073f30..ce1db3e 100644 --- a/src/pages/team-battle/components/HeaderProgress.vue +++ b/src/pages/team-battle/components/HeaderProgress.vue @@ -24,12 +24,14 @@ const onUpdateTips = (newVal) => { // 监听 Pinia store 中 totalShot 变化,用于比赛恢复时同步箭数(替代 uni.$emit 避免时序问题) // 使用 immediate: true 确保组件创建时立即读取 store 当前值(解决重入时 totalShot 值不变 watch 不触发的问题) -watch(() => store.game.totalShot, (newVal) => { - if (newVal > 0) { - totalShot.value = newVal; - currentShot.value = store.game.currentShot; - } -}, { immediate: true }); +watch( + () => [store.game.currentShot, store.game.totalShot], + ([newCurrentShot, newTotalShot]) => { + currentShot.value = newCurrentShot || 0; + totalShot.value = newTotalShot || 0; + }, + { immediate: true } +); // 监听 Pinia store 中 tips 变化,用于比赛恢复时同步提示文案(替代 uni.$emit 避免时序问题) // 使用 immediate: true 确保组件创建时立即读取 store 当前值(解决 onShow 早于 onMounted 导致 uni.$emit 事件丢失的问题) diff --git a/src/pages/team-battle/components/ShootProgress2.vue b/src/pages/team-battle/components/ShootProgress2.vue index c4d80e0..89af288 100644 --- a/src/pages/team-battle/components/ShootProgress2.vue +++ b/src/pages/team-battle/components/ShootProgress2.vue @@ -9,7 +9,7 @@ const props = defineProps({ }, total: { type: Number, - default: 15, + default: 12, }, currentRound: { type: String, @@ -18,9 +18,9 @@ const props = defineProps({ }); const barColor = ref(""); -const remain = ref(15); +const remain = ref(12); const timer = ref(null); -const loading = ref(false); +const loading = ref(true); const transitionStyle = ref("all 1s linear"); const currentTeam = ref(null); const MIN_TICK_MS = 1; diff --git a/src/pages/team-battle/index.vue b/src/pages/team-battle/index.vue index c665fad..166b773 100644 --- a/src/pages/team-battle/index.vue +++ b/src/pages/team-battle/index.vue @@ -1,6 +1,6 @@