update:优化比赛结束

This commit is contained in:
2026-07-15 16:57:48 +08:00
parent af7f70ba80
commit fa7ad8f538
2 changed files with 83 additions and 34 deletions
+15 -2
View File
@@ -27,6 +27,8 @@ const data = ref({});
const showOverlay = ref(false); const showOverlay = ref(false);
/** 自动关闭覆盖层的计时器 */ /** 自动关闭覆盖层的计时器 */
const overlayTimer = ref(null); const overlayTimer = ref(null);
const overlayDelayTimer = ref(null);
let loadGeneration = 0;
/** 控制经验条是否执行进场动画(弹窗关闭后才置 true,避免动画被遮挡) */ /** 控制经验条是否执行进场动画(弹窗关闭后才置 true,避免动画被遮挡) */
const showExpAnim = ref(false); const showExpAnim = ref(false);
@@ -175,9 +177,11 @@ function getMeleeAvatarBorderColor(rank) {
// ---- 生命周期 ---- // ---- 生命周期 ----
onLoad(async (options) => { onLoad(async (options) => {
const currentLoadId = ++loadGeneration;
if (!options.battleId) return; if (!options.battleId) return;
const result = await getBattleAPI(options.battleId); const result = await getBattleAPI(options.battleId);
if (currentLoadId !== loadGeneration) return;
data.value = result; data.value = result;
// 从 teams 各队伍的 players 中找到当前用户,解析经验进度条所需字段 // 从 teams 各队伍的 players 中找到当前用户,解析经验进度条所需字段
@@ -219,7 +223,8 @@ onLoad(async (options) => {
} }
// 数据加载完成后延迟 1 秒再显示激励弹窗,避免进场时画面太杂 // 数据加载完成后延迟 1 秒再显示激励弹窗,避免进场时画面太杂
setTimeout(() => { overlayDelayTimer.value = setTimeout(() => {
overlayDelayTimer.value = null;
showOverlay.value = true; showOverlay.value = true;
// 弹窗显示后 2.5 秒自动关闭 // 弹窗显示后 2.5 秒自动关闭
overlayTimer.value = setTimeout(() => { overlayTimer.value = setTimeout(() => {
@@ -229,7 +234,15 @@ onLoad(async (options) => {
}); });
onBeforeUnmount(() => { onBeforeUnmount(() => {
if (overlayTimer.value) clearTimeout(overlayTimer.value); loadGeneration += 1;
if (overlayDelayTimer.value) {
clearTimeout(overlayDelayTimer.value);
overlayDelayTimer.value = null;
}
if (overlayTimer.value) {
clearTimeout(overlayTimer.value);
overlayTimer.value = null;
}
}); });
// ---- 方法 ---- // ---- 方法 ----
+43 -7
View File
@@ -105,6 +105,8 @@ let restoreLoadingTimer = null;
let pendingRoundAudio = false; let pendingRoundAudio = false;
// 一旦收到 BattleEnd,后续普通消息就不再进入队列。 // 一旦收到 BattleEnd,后续普通消息就不再进入队列。
let battleEnded = false; let battleEnded = false;
let battleEndTaskRunning = false;
let resultNavigationPending = false;
let skipNextRestoreOnShow = false; let skipNextRestoreOnShow = false;
let pendingReturnSnapshot = null; let pendingReturnSnapshot = null;
const handledMessageKeys = new Set(); const handledMessageKeys = new Set();
@@ -1094,8 +1096,38 @@ async function runNewRoundTask(task, runId) {
pendingRoundAudio = true; pendingRoundAudio = true;
} }
function navigateToBattleResultOnce(matchId) {
const targetMatchId = matchId || battleId.value;
if (!targetMatchId || resultNavigationPending) return false;
resultNavigationPending = true;
battleEnded = true;
restoreGeneration += 1;
if (pendingRestoreTimer) {
clearTimeout(pendingRestoreTimer);
pendingRestoreTimer = null;
}
hideRestoreLoading();
uni.redirectTo({
url: `/pages/friend-battle-result?battleId=${targetMatchId}`,
fail: (err) => {
resultNavigationPending = false;
console.log("navigate to battle result failed:", err);
},
});
return true;
}
// 终局任务:播放结束语音后,根据状态跳结果页或返回上一页。 // 终局任务:播放结束语音后,根据状态跳结果页或返回上一页。
async function runBattleEndTask(task, runId) { async function runBattleEndTask(task, runId) {
if (resultNavigationPending) {
notifyMatchAudioAck(task);
return;
}
battleEndTaskRunning = true;
try {
const battleInfo = task.message; const battleInfo = task.message;
applyBattleBase(battleInfo); applyBattleBase(battleInfo);
battleEnded = true; battleEnded = true;
@@ -1113,9 +1145,7 @@ async function runBattleEndTask(task, runId) {
if (!isQueueAlive(runId)) return; if (!isQueueAlive(runId)) return;
if (matchStatus.value === 2) { if (matchStatus.value === 2) {
uni.redirectTo({ navigateToBattleResultOnce(battleId.value);
url: `/pages/friend-battle-result?battleId=${battleId.value}`,
});
} else if (matchStatus.value === 4) { } else if (matchStatus.value === 4) {
const roomNumber = battleInfo.roomId || store.game.roomNumber || store.game.roomID; const roomNumber = battleInfo.roomId || store.game.roomNumber || store.game.roomID;
setTimeout(() => { setTimeout(() => {
@@ -1128,6 +1158,9 @@ async function runBattleEndTask(task, runId) {
} }
}, BATTLE_CANCEL_RETURN_DELAY); }, BATTLE_CANCEL_RETURN_DELAY);
} }
} finally {
battleEndTaskRunning = false;
}
} }
// 无效射击任务:弹 toast 并播报无效射击,不修改比赛主状态。 // 无效射击任务:弹 toast 并播报无效射击,不修改比赛主状态。
@@ -1143,7 +1176,7 @@ async function runInvalidShotTask(task, runId) {
// 回前台恢复入口:拉取服务端快照,处理结束态,然后继续消费增量队列。 // 回前台恢复入口:拉取服务端快照,处理结束态,然后继续消费增量队列。
async function restoreLatestBattle() { async function restoreLatestBattle() {
if (!battleId.value) return; if (!battleId.value || resultNavigationPending) return;
const currentRestoreId = ++restoreGeneration; const currentRestoreId = ++restoreGeneration;
showRestoreLoading(); showRestoreLoading();
@@ -1175,9 +1208,8 @@ async function restoreLatestBattle() {
if (result.status === 2) { if (result.status === 2) {
clearXRingStreaks(); clearXRingStreaks();
hideRestoreLoading(); hideRestoreLoading();
uni.redirectTo({ battleEnded = true;
url: `/pages/friend-battle-result?battleId=${result.matchId}`, if (!battleEndTaskRunning) navigateToBattleResultOnce(result.matchId);
});
return; return;
} }
if (result.status === 4) { if (result.status === 4) {
@@ -1284,6 +1316,8 @@ onLoad((options) => {
restoreGeneration += 1; restoreGeneration += 1;
pendingRoundAudio = false; pendingRoundAudio = false;
battleEnded = false; battleEnded = false;
battleEndTaskRunning = false;
resultNavigationPending = false;
handledMessageKeys.clear(); handledMessageKeys.clear();
handledMessageKeyOrder.length = 0; handledMessageKeyOrder.length = 0;
queuedMessageKeys.clear(); queuedMessageKeys.clear();
@@ -1328,6 +1362,8 @@ onMounted(async () => {
// 离开页面时清理监听、停止音频,并让当前队列整体失效。 // 离开页面时清理监听、停止音频,并让当前队列整体失效。
onBeforeUnmount(() => { onBeforeUnmount(() => {
restoreGeneration += 1;
battleEndTaskRunning = false;
uni.setKeepScreenOn({ uni.setKeepScreenOn({
keepScreenOn: false, keepScreenOn: false,
}); });