update:优化比赛结束
This commit is contained in:
@@ -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;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// ---- 方法 ----
|
// ---- 方法 ----
|
||||||
|
|||||||
@@ -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,39 +1096,70 @@ 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) {
|
||||||
const battleInfo = task.message;
|
if (resultNavigationPending) {
|
||||||
applyBattleBase(battleInfo);
|
notifyMatchAudioAck(task);
|
||||||
battleEnded = true;
|
return;
|
||||||
clearXRingStreaks();
|
|
||||||
matchStatus.value = battleInfo.status;
|
|
||||||
if (battleInfo.status === 4) {
|
|
||||||
showRoundTip.value = true;
|
|
||||||
currentBluePoint.value = 0;
|
|
||||||
currentRedPoint.value = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 终局语音必须完整播完,再决定跳转或返回。
|
battleEndTaskRunning = true;
|
||||||
await playAudioKeys("比赛结束", { interrupt: false, timeout: AUDIO_TIMEOUT_MAX });
|
try {
|
||||||
notifyMatchAudioAck(task);
|
const battleInfo = task.message;
|
||||||
if (!isQueueAlive(runId)) return;
|
applyBattleBase(battleInfo);
|
||||||
|
battleEnded = true;
|
||||||
|
clearXRingStreaks();
|
||||||
|
matchStatus.value = battleInfo.status;
|
||||||
|
if (battleInfo.status === 4) {
|
||||||
|
showRoundTip.value = true;
|
||||||
|
currentBluePoint.value = 0;
|
||||||
|
currentRedPoint.value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (matchStatus.value === 2) {
|
// 终局语音必须完整播完,再决定跳转或返回。
|
||||||
uni.redirectTo({
|
await playAudioKeys("比赛结束", { interrupt: false, timeout: AUDIO_TIMEOUT_MAX });
|
||||||
url: `/pages/friend-battle-result?battleId=${battleId.value}`,
|
notifyMatchAudioAck(task);
|
||||||
});
|
if (!isQueueAlive(runId)) return;
|
||||||
} else if (matchStatus.value === 4) {
|
|
||||||
const roomNumber = battleInfo.roomId || store.game.roomNumber || store.game.roomID;
|
if (matchStatus.value === 2) {
|
||||||
setTimeout(() => {
|
navigateToBattleResultOnce(battleId.value);
|
||||||
if (roomNumber) {
|
} else if (matchStatus.value === 4) {
|
||||||
uni.redirectTo({
|
const roomNumber = battleInfo.roomId || store.game.roomNumber || store.game.roomID;
|
||||||
url: `/pages/battle-room?roomNumber=${encodeURIComponent(roomNumber)}&fromResult=1`,
|
setTimeout(() => {
|
||||||
});
|
if (roomNumber) {
|
||||||
} else {
|
uni.redirectTo({
|
||||||
uni.navigateBack();
|
url: `/pages/battle-room?roomNumber=${encodeURIComponent(roomNumber)}&fromResult=1`,
|
||||||
}
|
});
|
||||||
}, BATTLE_CANCEL_RETURN_DELAY);
|
} else {
|
||||||
|
uni.navigateBack();
|
||||||
|
}
|
||||||
|
}, BATTLE_CANCEL_RETURN_DELAY);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
battleEndTaskRunning = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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,
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user