update:语音加载优化,修复大乱斗未重连比赛服问题

This commit is contained in:
2026-07-13 14:50:21 +08:00
parent 1796d4aa40
commit 080af14be8
16 changed files with 340 additions and 447 deletions
@@ -67,7 +67,6 @@ const onClick = debounce(async () => {
loading.value = true;
const result = await getBattleAPI();
if (result && result.matchId) {
await uni.$checkAudio();
await returnToBattle(result, navigateOnce);
return;
}
+4 -53
View File
@@ -1,5 +1,5 @@
<script setup>
import { ref, computed, onMounted, onBeforeUnmount } from "vue";
import { ref } from "vue";
import { onShow } from "@dcloudio/uni-app";
import AppBackground from "./AppBackground.vue";
import Header from "./Header.vue";
@@ -8,7 +8,6 @@ import BackToGame from "./BackToGame.vue";
import {laserAimAPI, getBattleAPI, matchGameAPI} from "@/apis";
import { capsuleHeight, debounce } from "@/util";
import { returnToBattle } from "@/utils/matchReturn";
import AudioManager from "@/audioManager";
const props = defineProps({
title: {
type: String,
@@ -59,9 +58,6 @@ const isIOS = uni.getDeviceInfo().osName === "ios";
const showHint = ref(false);
const hintType = ref(0);
const isLoading = ref(false);
const audioInitProgress = ref(1);
const audioProgress = ref(0);
const audioTimer = ref(null);
const showGlobalHint = (type) => {
hintType.value = type;
@@ -72,52 +68,9 @@ const hideGlobalHint = () => {
showHint.value = false;
};
const restart = () => {
uni.restartMiniProgram({
path: "/pages/index",
});
};
const checkAudioProgress = async () => {
return new Promise((resolve, reject) => {
try {
audioInitProgress.value = AudioManager.getLoadProgress();
if (audioInitProgress.value === 1) return resolve();
audioTimer.value = setInterval(() => {
audioProgress.value = AudioManager.getLoadProgress();
if (audioProgress.value === 1) {
setTimeout(() => {
audioInitProgress.value = 1;
}, 200);
clearInterval(audioTimer.value);
resolve();
}
}, 200);
} catch (err) {
reject(err);
}
});
};
const audioFinalProgress = computed(() => {
const left = 1 - audioInitProgress.value;
if (left <= 0) return 0;
return Math.max(0, (audioProgress.value - audioInitProgress.value) / left);
});
const loadingProgress = computed(() => {
if (props.loading && audioInitProgress.value >= 1) return 1;
return audioFinalProgress.value;
});
onBeforeUnmount(() => {
if (audioTimer.value) clearInterval(audioTimer.value);
});
onShow(() => {
uni.$showHint = showGlobalHint;
uni.$hideHint = hideGlobalHint;
uni.$checkAudio = checkAudioProgress;
showHint.value = false;
});
@@ -137,7 +90,6 @@ const backToGame = debounce(async () => {
isLoading.value = true;
const result = await getBattleAPI();
if (result && result.matchId) {
await checkAudioProgress();
await returnToBattle(result, navigateTo);
}
} catch (error) {
@@ -235,13 +187,13 @@ const goCalibration = async () => {
</view>
</view>
</ScreenHint>
<view v-if="loading || audioInitProgress < 1" class="audio-progress">
<view v-if="loading" class="audio-progress">
<image
src="https://static.shelingxingqiu.com/attachment/2025-11-26/deihtj15xjwcz3c1tx.png"
mode="widthFix"
/>
<view>
<view :style="{ width: `${loadingProgress * 100}%` }">
<view :style="{ width: '100%' }">
<!-- <image
src="https://static.shelingxingqiu.com/attachment/2025-11-24/degu91a7si77sg9jqv.png"
mode="widthFix"
@@ -249,8 +201,7 @@ const goCalibration = async () => {
</view>
</view>
<view>
<text>{{ loading ? loadingText || "加载中..." : "若加载时间过长,请" }}</text>
<button v-if="!loading" hover-class="none" @click="restart">点击这里重启</button>
<text>{{ loadingText || "加载中..." }}</text>
</view>
</view>
</view>
+13 -5
View File
@@ -106,6 +106,7 @@ let pendingRoundAudio = false;
// 一旦收到 BattleEnd,后续普通消息就不再进入队列。
let battleEnded = false;
let skipNextRestoreOnShow = false;
let pendingReturnSnapshot = null;
const handledMessageKeys = new Set();
const handledMessageKeyOrder = [];
const queuedMessageKeys = new Set();
@@ -978,9 +979,9 @@ async function runToSomeoneShootTask(task, runId) {
notifyMatchAudioAck(task);
if (!isQueueAlive(runId)) return;
const remainingSeconds = getRemainingSeconds(battleInfo, task, {
fullDurationIfNoBackendRemain: isRoundFirstShoot,
});
// 实时换人消息的倒计时由本条语音 ACK 驱动:后端收到 ACK 后才开始计时,
// 因此前端也应从完整 shootTime 启动,不能扣除消息排队及 tententen/提示语音耗时。
const remainingSeconds = getShootTimeSeconds(battleInfo);
const countdown = getCountdownPayload(remainingSeconds, shootTimeTotal.value);
markProgressDeadline(countdown);
uni.$emit("update-remain", {
@@ -1249,6 +1250,7 @@ function onReceiveMessage(message) {
onLoad((options) => {
console.log('重新进入了')
const returnSnapshot = options.fromReturn ? takeMatchReturnSnapshot() : null;
pendingReturnSnapshot = returnSnapshot;
skipNextRestoreOnShow = false;
// 新对局入口:把所有会串场的状态、队列、时间戳和缓存一次性清空。
start.value = null;
@@ -1293,8 +1295,7 @@ onLoad((options) => {
latestShotFlash.value = null;
if (returnSnapshot) {
skipNextRestoreOnShow = true;
applyBattleSnapshot(returnSnapshot, { restore: true });
reconnectMatchServer(returnSnapshot);
showRestoreLoading();
return;
}
const readySnapshot = takeReadySnapshot(battleId.value);
@@ -1316,6 +1317,12 @@ onMounted(async () => {
uni.$on(PROGRESS_ZERO_EVENT, onProgressZero);
uni.$on(COUNTDOWN_READY_EVENT, hideRestoreLoading);
uni.$on(MATCH_WS_STATE_EVENT, onMatchSocketState);
if (pendingReturnSnapshot) {
const returnSnapshot = pendingReturnSnapshot;
pendingReturnSnapshot = null;
reconnectMatchServer(returnSnapshot);
scheduleRestoreLatestBattle();
}
await laserCloseAPI();
});
@@ -1333,6 +1340,7 @@ onBeforeUnmount(() => {
clearTimeout(pendingRestoreTimer);
pendingRestoreTimer = null;
}
pendingReturnSnapshot = null;
hideRestoreLoading();
invalidateBattleQueue({ stopAudio: true, stopProgress: true });
closeBattleServer("team-battle-unmount");