update:语音加载优化,修复大乱斗未重连比赛服问题
This commit is contained in:
@@ -192,6 +192,7 @@ const onClickShare = debounce(async () => {
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
void audioManager.warmAll();
|
||||
uni.setKeepScreenOn({
|
||||
keepScreenOn: true,
|
||||
});
|
||||
|
||||
@@ -256,11 +256,6 @@ const toPage = async (path) => {
|
||||
showModal.value = true;
|
||||
return;
|
||||
}
|
||||
// if (path === "/pages/first-try") {
|
||||
// if (canEenter(user.value, device.value, online.value, path)) {
|
||||
// await uni.$checkAudio();
|
||||
// }
|
||||
// }
|
||||
uni.navigateTo({url: path});
|
||||
};
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import { onLoad, onShow, onHide } from "@dcloudio/uni-app";
|
||||
import Container from "@/components/Container.vue";
|
||||
import Matching from "@/components/Matching.vue";
|
||||
import ModalDialog from "@/components/ModalDialog.vue";
|
||||
import audioManager from "@/audioManager";
|
||||
import { matchGameAPI, getBattleAPI } from "@/apis";
|
||||
import { MESSAGETYPESV2 } from "@/constants";
|
||||
import { isLimitError } from "@/util";
|
||||
@@ -146,6 +147,7 @@ onLoad(async (options) => {
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
void audioManager.warmAll();
|
||||
uni.setKeepScreenOn({
|
||||
keepScreenOn: true,
|
||||
});
|
||||
|
||||
@@ -65,6 +65,12 @@ function clearHalfRestCountdown() {
|
||||
}
|
||||
}
|
||||
|
||||
function leaveHalfRest() {
|
||||
clearHalfRestCountdown();
|
||||
halfTimeTip.value = false;
|
||||
halfRest.value = false;
|
||||
}
|
||||
|
||||
function getHalfRestSeconds(battleInfo) {
|
||||
const remainCandidates = [
|
||||
battleInfo?.halfRestRemain,
|
||||
@@ -204,7 +210,7 @@ function takeReadySnapshot(matchId) {
|
||||
|
||||
function reconnectMatchServer(battleInfo) {
|
||||
const status = Number(battleInfo?.status);
|
||||
if ([2, 3, 4].includes(status)) return;
|
||||
if ([2, 4].includes(status)) return;
|
||||
if (!battleInfo?.serverAddr) return;
|
||||
|
||||
connectMatchWebSocket({
|
||||
@@ -311,6 +317,7 @@ function recoverData(battleInfo, { force = false } = {}) {
|
||||
}, 200);
|
||||
return;
|
||||
}
|
||||
leaveHalfRest();
|
||||
if (force) {
|
||||
const remain = (Date.now() - (battleInfo.current?.startTime || Date.now())) / 1000;
|
||||
console.log(`当前轮已进行${remain}秒`);
|
||||
@@ -422,9 +429,7 @@ async function onReceiveMessage(msg) {
|
||||
if (msg.type === MESSAGETYPESV2.AboutToStart) {
|
||||
recoverData(msg);
|
||||
} else if (msg.type === MESSAGETYPESV2.BattleStart) {
|
||||
clearHalfRestCountdown();
|
||||
halfTimeTip.value = false;
|
||||
halfRest.value = false;
|
||||
leaveHalfRest();
|
||||
recoverData(msg);
|
||||
} else if (msg.type === MESSAGETYPESV2.ShootResult) {
|
||||
// 更新前快照各玩家本轮已射箭数,用于事后识别本次射手
|
||||
|
||||
@@ -196,6 +196,7 @@ const onClickShare = debounce(async () => {
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
void audioManager.warmAll();
|
||||
// audioManager.play("第一轮");
|
||||
uni.setKeepScreenOn({
|
||||
keepScreenOn: true,
|
||||
|
||||
@@ -211,6 +211,7 @@ const onClickShare = debounce(async () => {
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
void audioManager.warmAll();
|
||||
uni.setKeepScreenOn({
|
||||
keepScreenOn: true,
|
||||
});
|
||||
|
||||
@@ -126,7 +126,6 @@ const toMatchPage = async (gameType, teamSize) => {
|
||||
showLimitModal.value = true;
|
||||
return;
|
||||
}
|
||||
await uni.$checkAudio();
|
||||
uni.navigateTo({
|
||||
url: `/pages/match-page?gameType=${gameType}&teamSize=${teamSize}`,
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -19,7 +19,6 @@ const toOrderPage = () => {
|
||||
|
||||
const toFristTryPage = async () => {
|
||||
if (canEenter(user.value, device.value, online.value, "/pages/first-try")) {
|
||||
await uni.$checkAudio();
|
||||
uni.navigateTo({
|
||||
url: "/pages/first-try",
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user