From 6cb5288631b5fe4d0652d9eb190eef362bc66eed Mon Sep 17 00:00:00 2001 From: chenlimao Date: Wed, 13 May 2026 11:17:30 +0800 Subject: [PATCH] =?UTF-8?q?fix=EF=BC=9A=E4=BC=98=E5=8C=96=E9=87=8D?= =?UTF-8?q?=E8=BF=9B=E6=AF=94=E8=B5=9Btips=E5=B1=95=E7=A4=BA=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/HeaderProgress.vue | 10 ++++++++++ src/pages/team-battle.vue | 12 ++++++++++-- src/store.js | 5 +++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/components/HeaderProgress.vue b/src/components/HeaderProgress.vue index f735806..0b9aaad 100644 --- a/src/components/HeaderProgress.vue +++ b/src/components/HeaderProgress.vue @@ -102,6 +102,14 @@ watch(() => store.game.totalShot, (newVal) => { } }, { immediate: true }); +// 监听 Pinia store 中 tips 变化,用于比赛恢复时同步提示文案(替代 uni.$emit 避免时序问题) +// 使用 immediate: true 确保组件创建时立即读取 store 当前值(解决 onShow 早于 onMounted 导致 uni.$emit 事件丢失的问题) +watch(() => store.game.tips, (newVal) => { + if (newVal) { + tips.value = newVal; + } +}, { immediate: true }); + onMounted(() => { uni.$on("update-tips", onUpdateTips); uni.$on("socket-inbox", onReceiveMessage); @@ -111,6 +119,8 @@ onMounted(() => { onBeforeUnmount(() => { uni.$off("socket-inbox", onReceiveMessage); uni.$off("play-sound", playSound); + // 补充取消 update-tips 监听,防止页面重建时监听器叠加 + uni.$off("update-tips", onUpdateTips); if (timer.value) clearInterval(timer.value); }); diff --git a/src/pages/team-battle.vue b/src/pages/team-battle.vue index 8986437..daab6aa 100644 --- a/src/pages/team-battle.vue +++ b/src/pages/team-battle.vue @@ -113,7 +113,14 @@ const recoverData = (battleInfo, {force = false, arrowOnly = false} = {}) => { audioManager.play(audioKey, false); } tips.value = nextTips; - uni.$emit("update-tips", nextTips); + // 同步写入 Pinia store,供 HeaderProgress 通过 immediate watch 在 onMounted 时立即读取 + // 规避 WeChat 小程序 onShow 在组件 onMounted 之前触发导致 uni.$emit 事件丢失的时序问题 + store.updateTips(nextTips); + // force 模式下改为在 nextTick 内发送 update-tips,规避 WeChat 小程序 + // onShow 与 onMounted 时序问题导致 HeaderProgress 监听器尚未注册的边界情况 + if (!force) { + uni.$emit("update-tips", nextTips); + } // redPlayer 已在上方 find() 确认:不为 null 则当前射手在红队 const targetTeam = redPlayer ? 'red' : 'blue'; if (force) { @@ -128,7 +135,8 @@ const recoverData = (battleInfo, {force = false, arrowOnly = false} = {}) => { } const actualRemain = updateRemainSecond.value; nextTick(() => { - // 等 ShootProgress2 挂载后再发重置事件,确保事件能被接收 + // 在 nextTick 内统一发送,确保 ShootProgress2 和 HeaderProgress 均已挂载 + uni.$emit("update-tips", nextTips); uni.$emit("update-remain", {reset: true, value: 15, team: targetTeam}); // 重置动画完成后,直接启动倒计时(无需依赖音频结束回调) setTimeout(() => { diff --git a/src/store.js b/src/store.js index 2ab1868..7549772 100644 --- a/src/store.js +++ b/src/store.js @@ -82,6 +82,7 @@ export default defineStore("store", { roomNumber: "", // 当前房间号,供 Header 展示房号胶囊 currentShot: 0, // 当前已射箭数(用于 HeaderProgress 恢复状态) totalShot: 0, // 轮次总箭数(用于 HeaderProgress 恢复状态) + tips: "", // 当前提示文案(用于 HeaderProgress 恢复状态,替代 uni.$emit 避免时序问题) }, }), @@ -143,6 +144,10 @@ export default defineStore("store", { this.game.currentShot = currentShot; this.game.totalShot = totalShot; }, + /** 更新当前提示文案(用于 HeaderProgress 恢复状态,替代 uni.$emit 避免时序问题) */ + updateTips(tips = "") { + this.game.tips = tips; + }, /** 更新当前房间号,供 Header 组件展示房号胶囊 */ updateRoomNumber(number) { this.game.roomNumber = number;