update:优化比赛队列

This commit is contained in:
2026-07-08 18:18:27 +08:00
parent e0d976fcce
commit af07d09ab6
5 changed files with 589 additions and 38 deletions
+90 -5
View File
@@ -13,6 +13,7 @@ import TestDistance from "@/components/TestDistance.vue";
import SModal from "@/components/SModal.vue";
import audioManager from "@/audioManager";
import { getBattleAPI, laserCloseAPI } from "@/apis";
import { connectMatchWebSocket } from "@/matchWebsocket";
import { MESSAGETYPESV2 } from "@/constants";
import useStore from "@/store";
import { storeToRefs } from "pinia";
@@ -31,6 +32,14 @@ const playersScores = ref([]);
const halfTimeTip = ref(false);
const halfRest = ref(false);
const HALF_REST_SECONDS = 20;
const MATCH_READY_SNAPSHOT_PREFIX = "match-ready-snapshot:";
const MATCH_STATUS_BY_TEXT = {
MATCH_STATUS_READY: 0,
MATCH_STATUS_STARTED: 1,
MATCH_STATUS_END: 2,
MATCH_STATUS_TIMEOUT: 3,
MATCH_STATUS_UNEXPECTEDLY: 4,
};
const halfRestRemain = ref(HALF_REST_SECONDS);
let halfRestTimer = null;
/** 控制设备离线提示弹窗的显示状态 */
@@ -93,6 +102,68 @@ const currentPlayer = computed(() =>
);
const isCurrentUserSvip = computed(() => currentPlayer.value?.sVip === true);
function getReadySnapshotKey(matchId) {
return `${MATCH_READY_SNAPSHOT_PREFIX}${String(matchId || "")}`;
}
function normalizeBattleInfo(battleInfo) {
if (!battleInfo || typeof battleInfo !== "object") return battleInfo;
const statusText = battleInfo.statusText || battleInfo.status_text;
if (
(battleInfo.status === undefined ||
battleInfo.status === null ||
battleInfo.status === "") &&
MATCH_STATUS_BY_TEXT[statusText] !== undefined
) {
return {
...battleInfo,
status: MATCH_STATUS_BY_TEXT[statusText],
};
}
return battleInfo;
}
function hasKnownStatus(battleInfo) {
return !(
battleInfo?.status === undefined ||
battleInfo?.status === null ||
battleInfo?.status === ""
);
}
function hasStartedSnapshot(battleInfo) {
if (hasKnownStatus(battleInfo)) return Number(battleInfo.status) !== 0;
const current = battleInfo?.current || {};
return !!(
current.playerId ||
current.startTime ||
current.round ||
(Array.isArray(battleInfo?.rounds) && battleInfo.rounds.length)
);
}
function takeReadySnapshot(matchId) {
const key = getReadySnapshotKey(matchId);
const snapshot = uni.getStorageSync(key);
if (snapshot) uni.removeStorageSync(key);
return normalizeBattleInfo(snapshot);
}
function reconnectMatchServer(battleInfo) {
const status = Number(battleInfo?.status);
if ([2, 3, 4].includes(status)) return;
if (!battleInfo?.serverAddr) return;
connectMatchWebSocket({
serverAddr: battleInfo.serverAddr,
matchId: battleInfo.matchId || battleId.value,
userId: user.value.id,
});
}
/**
* 监听设备在线状态,大乱斗比赛进行中设备离线时弹窗提示用户
*/
@@ -103,6 +174,7 @@ watch(online, (newVal, oldVal) => {
});
function recoverData(battleInfo, { force = false } = {}) {
battleInfo = normalizeBattleInfo(battleInfo);
if (!battleInfo) return;
try {
if (battleInfo.way === 1) title.value = "好友约战 - 大乱斗";
@@ -121,7 +193,14 @@ function recoverData(battleInfo, { force = false } = {}) {
players.value = [];
}
start.value = battleInfo.status !== 0;
if (hasKnownStatus(battleInfo)) {
start.value = battleInfo.status !== 0;
} else if (!hasStartedSnapshot(battleInfo)) {
if (start.value !== true) start.value = false;
return;
} else {
start.value = true;
}
if (battleInfo.status === 0) {
const readyRemain = (Date.now() - (battleInfo.createTime || Date.now())) / 1000;
@@ -131,9 +210,10 @@ function recoverData(battleInfo, { force = false } = {}) {
return;
}
const rounds = Array.isArray(battleInfo.rounds) ? battleInfo.rounds : [];
tips.value =
(battleInfo.rounds.length !== 2 ? "上" : "下") + "半场:请先射6箭";
playersScores.value = battleInfo.rounds.map((r) => ({ ...r.shoots }));
(rounds.length !== 2 ? "上" : "下") + "半场:请先射6箭";
playersScores.value = rounds.map((r) => ({ ...r.shoots }));
const totals = {};
players.value.forEach((p) => {
const total = playersScores.value.reduce((acc, round) => {
@@ -171,6 +251,8 @@ function recoverData(battleInfo, { force = false } = {}) {
onLoad(async (options) => {
if (options.battleId) battleId.value = options.battleId;
const readySnapshot = takeReadySnapshot(battleId.value);
if (readySnapshot?.status === 0) recoverData(readySnapshot);
// uni.enableAlertBeforeUnload({
// message: "离开比赛可能导致比赛失败,是否继续?",
// success: (res) => {
@@ -207,7 +289,9 @@ function checkAndPlayTententen(playerId, isTenPlusRingShot) {
async function onReceiveMessage(msg) {
if (Array.isArray(msg)) return;
if (msg.type === MESSAGETYPESV2.BattleStart) {
if (msg.type === MESSAGETYPESV2.AboutToStart) {
recoverData(msg);
} else if (msg.type === MESSAGETYPESV2.BattleStart) {
clearHalfRestCountdown();
halfTimeTip.value = false;
halfRest.value = false;
@@ -267,7 +351,7 @@ onBeforeUnmount(() => {
onShow(async () => {
if (battleId.value) {
const result = await getBattleAPI(battleId.value);
const result = normalizeBattleInfo(await getBattleAPI(battleId.value));
if (!result) return;
if (result.status === 2) {
uni.showToast({
@@ -278,6 +362,7 @@ onShow(async () => {
delta: 2,
});
} else {
reconnectMatchServer(result);
recoverData(result, { force: true });
}
}