diff --git a/src/components/HeaderProgress.vue b/src/components/HeaderProgress.vue index bad1920..887afc9 100644 --- a/src/components/HeaderProgress.vue +++ b/src/components/HeaderProgress.vue @@ -52,7 +52,8 @@ async function onReceiveMessage(message) { const { type, mode, current, shootData } = message; if (type === MESSAGETYPESV2.BattleStart) { melee.value = Boolean(mode > 3); - totalShot.value = mode === 1 ? 3 : 2; + // 优先使用后端返回的 shootNumber,降级则根据 mode 推算 + totalShot.value = message.shootNumber ?? (mode === 1 ? 3 : 2); currentRoundEnded.value = true; audioManager.play("比赛开始"); } else if (type === MESSAGETYPESV2.BattleEnd) { diff --git a/src/pages/team-battle.vue b/src/pages/team-battle.vue index 3f5e7ea..6c3a3ff 100644 --- a/src/pages/team-battle.vue +++ b/src/pages/team-battle.vue @@ -42,6 +42,8 @@ const matchStatus = ref(undefined); const updateRemainSecond = ref(0); /** 对战来源类型(1=好友约战,2=匹配对战),用于结算页分流 */ const battleWay = ref(0); +/** 上一次处理的 ToSomeoneShoot 关键字段,用于去重过滤重复消息 */ +const lastToSomeoneShootKey = ref(""); const recoverData = (battleInfo, {force = false, arrowOnly = false} = {}) => { try { @@ -183,6 +185,11 @@ async function onReceiveMessage(msg) { if (msg.type === MESSAGETYPESV2.BattleStart) { start.value = true; } else if (msg.type === MESSAGETYPESV2.ToSomeoneShoot) { + // 去重防护:如果 playerId + round 与上一次处理完全相同,则忽略重复推送的消息 + // (防止 onBeforeUnmount 未及时 off 和页面重创建导致同一事件被处理多次) + const key = `${msg?.current?.playerId}-${msg?.current?.round}`; + if (key === lastToSomeoneShootKey.value) return; + lastToSomeoneShootKey.value = key; recoverData(msg); } else if (msg.type === MESSAGETYPESV2.ShootResult) { uni.$emit("update-remain", {stop: true}) @@ -228,6 +235,8 @@ onBeforeUnmount(() => { uni.setKeepScreenOn({ keepScreenOn: false, }); + // 注销所有第三方事件盓听,防止页面重创建时监听叠加导致消息重复处理 + uni.$off("socket-inbox", onReceiveMessage); uni.$off("audioEnded", onAudioEnded); audioManager.stopAll(); }); @@ -242,6 +251,10 @@ onShow(async () => { url: `/pages/friend-battle-result?battleId=${result.matchId}`, }); } else { + // shootNumber 来自后端,恢复状态时同步 totalShot,防止 BattleStart 不重新推送导致显示错误 + if (result.shootNumber) { + uni.$emit("update-shot", { currentShot: 0, totalShot: result.shootNumber }); + } recoverData(result, {force: true}); } }