diff --git a/src/components/ShootProgress2.vue b/src/components/ShootProgress2.vue index 260837f..a8ee1dc 100644 --- a/src/components/ShootProgress2.vue +++ b/src/components/ShootProgress2.vue @@ -36,7 +36,14 @@ const updateRemain = (value) => { if (value.team === 'blue') barColor.value = "linear-gradient( 180deg, #9AB3FF 0%, #4288FF 100%)"; if (value.reset) { + // 重置前先清除旧计时器,防止超时未射箭时旧 interval 残留,导致进度条震荡 + if (timer.value) clearInterval(timer.value); + // 重置时瞬间跳满格,禁用 CSS 过渡避免从旧值「涨到满」的动画 + transitionStyle.value = "none"; remain.value = value.value; + setTimeout(() => { + transitionStyle.value = "all 1s linear"; + }, 50); return; } const newVal = Math.round(value.value); @@ -51,6 +58,8 @@ const updateRemain = (value) => { remain.value = newVal; } + // 启动前先清除旧计时器,防止多次 {stop:false} 事件叠加多个 interval + if (timer.value) clearInterval(timer.value); timer.value = setInterval(() => { loading.value = remain.value === 0; if (remain.value > 0) remain.value--; diff --git a/src/pages/match-page.vue b/src/pages/match-page.vue index ea73d8d..c1c1102 100644 --- a/src/pages/match-page.vue +++ b/src/pages/match-page.vue @@ -26,13 +26,15 @@ async function onReceiveMessage(msg) { onComplete.value = () => {} } if (msg.type === MESSAGETYPESV2.AboutToStart) { - if (gameType.value == 1) { + // 使用后端下发的 mode 字段判断跳转目标,与好友约战(battle-room.vue)保持一致 + // mode <= 3 为团队对抗,mode > 3 为大乱斗,覆盖全部 gameType(1~5),不再遗漏 + if (msg.mode <= 3) { uni.redirectTo({ - url: `/pages/team-battle?battleId=${msg.id}&gameMode=2`, + url: `/pages/team-battle?battleId=${msg.id}`, }); - } else if (gameType.value == 2) { + } else { uni.redirectTo({ - url: `/pages/melee-battle?battleId=${msg.id}&gameMode=2`, + url: `/pages/melee-battle?battleId=${msg.id}`, }); } } diff --git a/src/pages/team-battle.vue b/src/pages/team-battle.vue index 074bc3b..3f5e7ea 100644 --- a/src/pages/team-battle.vue +++ b/src/pages/team-battle.vue @@ -23,6 +23,8 @@ const start = ref(null); const tips = ref(""); const battleId = ref(""); const currentRound = ref(0); +/** 专用于 RoundEndTip 展示的轮次,与进度条的 currentRound 解耦,避免 ToSomeoneShoot 提前更新 currentRound 导致 Tip 显示错误轮次 */ +const roundTipRound = ref(0); const goldenRound = ref(0); const currentRedPoint = ref(0); const currentBluePoint = ref(0); @@ -75,6 +77,8 @@ const recoverData = (battleInfo, {force = false, arrowOnly = false} = {}) => { return; } if (!arrowOnly) { + // 在 ToSomeoneShoot 时同步更新当前轮次,使进度条轮次图片及时切换 + currentRound.value = battleInfo.current.round || 1; currentShooterId.value = battleInfo.current.playerId; const redPlayer = battleInfo.teams[2].players.find( (item) => item.id === battleInfo.current.playerId @@ -87,9 +91,17 @@ const recoverData = (battleInfo, {force = false, arrowOnly = false} = {}) => { ) { nextTips += "你"; } + // 同队连续出手时 tips 值不变,HeaderProgress watch 不触发音频 + // 需在赋值前比较旧值,手动播放音频确保始终触发 onAudioEnded 启动计时器 + // 注意:使用 interrupt=false 避免打断上一支箭的环数播报音频 + if (tips.value === nextTips && !nextTips.includes("重回")) { + const audioKey = redPlayer ? "请红方射箭" : "请蓝方射箭"; + audioManager.play(audioKey, false); + } tips.value = nextTips; uni.$emit("update-tips", nextTips); - uni.$emit("update-remain", {reset: true, value: 15, team: redTeam?'red':'blue'}); + // redPlayer 已在上方 find() 确认:不为 null 则当前射手在红队 + uni.$emit("update-remain", {reset: true, value: 15, team: redPlayer?'red':'blue'}); if (force) { const remain = (Date.now() - battleInfo.current.startTime) / 1000; console.log(`当前轮已进行${remain}秒`); @@ -117,8 +129,13 @@ const recoverData = (battleInfo, {force = false, arrowOnly = false} = {}) => { }; function onAudioEnded(s) { - if (s.indexOf('请红方射箭') >= 0 || s.indexOf('请蓝方射箭') >= 0) { - let team = s.indexOf('请红方射箭') >= 0 ? 'red' : 'blue'; + // "请红方射箭"/"请蓝方射箭":队友或对手轮次;"轮到你了":用户本人轮次(HeaderProgress特殊分支) + // 三者音频结束后均需启动倒计时进度条 + if (s.indexOf('请红方射箭') >= 0 || s.indexOf('请蓝方射箭') >= 0 || s.indexOf('轮到你了') >= 0) { + let team; + if (s.indexOf('请红方射箭') >= 0) team = 'red'; + else if (s.indexOf('请蓝方射箭') >= 0) team = 'blue'; + else team = tips.value.includes('红队') ? 'red' : 'blue'; // 轮到你了:从当前tips判断用户所在队伍 uni.$emit("update-remain", {stop: false, value: updateRemainSecond.value, team: team}); } if (s.indexOf("比赛结束") >= 0) { @@ -136,10 +153,20 @@ function onBattleEnd() { } } -function onNewRound(msg) { +/** + * @param {object} msg - NewRound 消息 + * @param {number} prevRound - 在 NewRound 消息到达时即时捕获的旧轮次,用于 Tip 展示,避免异步延迟内 currentRound 已被更新 + */ +function onNewRound(msg, prevRound) { showRoundTip.value = true; isFinalShoot.value = msg.current.goldRound; - const latestRound = msg.rounds[currentRound.value - 1]; + // 决金箭轮每人只射一箭,重置箭数显示为 (0/1) + if (msg.current.goldRound) { + uni.$emit("update-shot", { currentShot: 0, totalShot: 1 }); + } + // 用传入的 prevRound(捕获时刻的旧轮次)展示结算 Tip,与进度条 currentRound 解耦 + roundTipRound.value = prevRound; + const latestRound = msg.rounds[prevRound - 1]; if (latestRound) { if (isFinalShoot.value) { currentBluePoint.value = msg.teams[1].score; @@ -162,8 +189,10 @@ async function onReceiveMessage(msg) { showRoundTip.value = false; recoverData(msg, {arrowOnly: true}); } else if (msg.type === MESSAGETYPESV2.NewRound) { + // 在进入延迟前先捕获当前轮次,供 onNewRound 使用,防止 800ms 内 ToSomeoneShoot 提前更新 currentRound 造成 Tip 展示错轮 + const prevRound = currentRound.value; setTimeout(() => { - onNewRound(msg) + onNewRound(msg, prevRound) }, 800) } else if (msg.type === MESSAGETYPESV2.BattleEnd) { matchStatus.value = msg.status; @@ -263,11 +292,11 @@ onShow(async () => {