完成打乱斗数据调试

This commit is contained in:
kron
2026-02-07 10:52:56 +08:00
parent 09d8e7b3da
commit 6101cd80ce
20 changed files with 444 additions and 473 deletions

205
src/pages/melee-battle.vue Normal file
View File

@@ -0,0 +1,205 @@
<script setup>
import { ref, onMounted, onBeforeUnmount } from "vue";
import { onLoad, onShow, onHide } from "@dcloudio/uni-app";
import Container from "@/components/Container.vue";
import BowTarget from "@/components/BowTarget.vue";
import ShootProgress from "@/components/ShootProgress.vue";
import BattleHeader from "@/components/BattleHeader.vue";
import PlayerScore from "@/components/PlayerScore.vue";
import SButton from "@/components/SButton.vue";
import Avatar from "@/components/Avatar.vue";
import ScreenHint from "@/components/ScreenHint.vue";
import TestDistance from "@/components/TestDistance.vue";
import audioManager from "@/audioManager";
import { getBattleAPI, laserCloseAPI } from "@/apis";
import { isGameEnded } from "@/util";
import { MESSAGETYPESV2 } from "@/constants";
import useStore from "@/store";
import { storeToRefs } from "pinia";
const store = useStore();
const { user } = storeToRefs(store);
const title = ref("");
const start = ref(null);
const battleId = ref("");
const currentRound = ref(1);
const tips = ref("即将开始...");
const players = ref([]);
const playersSorted = ref([]);
const playersScores = ref([]);
const halfTimeTip = ref(false);
const halfRest = ref(false);
function recoverData(battleInfo, { force = false } = {}) {
console.log("battleInfo", battleInfo);
if (battleInfo.way === 1) title.value = "好友约战 - 大乱斗";
if (battleInfo.way === 2) title.value = "排位赛 - 大乱斗";
players.value = battleInfo.teams[0].players;
start.value = battleInfo.status !== 0;
if (battleInfo.status === 0) {
const readyRemain = (Date.now() - battleInfo.createTime) / 1000;
console.log(`对局已进行${readyRemain}`);
if (readyRemain > 0 && readyRemain < 15) {
setTimeout(() => {
uni.$emit("update-timer", 15 - readyRemain - 0.2);
}, 200);
}
return;
}
tips.value =
(battleInfo.rounds.length !== 2 ? "上" : "下") + "半场请先射6箭";
playersScores.value = battleInfo.rounds.map((r) => ({ ...r.shoots }));
const totals = {};
players.value.forEach((p) => {
const total = playersScores.value.reduce((acc, round) => {
const arr = round[p.id] || [];
return acc + arr.length;
}, 0);
totals[p.id] = total;
});
playersSorted.value = players.value.slice().sort((a, b) => {
return totals[b.id] - totals[a.id];
});
if (battleInfo.status === 3) {
halfTimeTip.value = true;
halfRest.value = true;
tips.value = "准备下半场";
// 剩余休息时间
// const remain = (Date.now() - battleInfo.timeoutTime) / 1000;
setTimeout(() => {
uni.$emit("update-remain", 0);
}, 200);
return;
}
if (force) {
const remain = (Date.now() - battleInfo.current.startTime) / 1000;
console.log(
`当前轮已进行${remain}秒,${Date.now()},${
battleInfo.current.startTimeText
}`
);
if (remain > 0 && remain < 90) {
setTimeout(() => {
uni.$emit("update-remain", 90 - remain - 0.2);
}, 200);
}
} else {
uni.$emit("update-remain", battleInfo.readyTime);
}
}
onLoad(async (options) => {
if (options.battleId) battleId.value = options.battleId;
uni.enableAlertBeforeUnload({
message: "离开比赛可能导致比赛失败,是否继续?",
success: (res) => {
console.log("已启用离开提示");
},
});
});
async function onReceiveMessage(msg) {
if (Array.isArray(msg)) return;
if (msg.type === MESSAGETYPESV2.BattleStart) {
halfTimeTip.value = false;
halfRest.value = false;
recoverData(msg);
} else if (msg.type === MESSAGETYPESV2.ShootResult) {
recoverData(msg);
} else if (msg.type === MESSAGETYPESV2.HalfRest) {
halfTimeTip.value = true;
halfRest.value = true;
tips.value = "准备下半场";
} else if (msg.type === MESSAGETYPESV2.BattleEnd) {
uni.redirectTo({
url: "/pages/battle-result?battleId=" + msg.matchId,
});
}
}
onMounted(async () => {
uni.setKeepScreenOn({
keepScreenOn: true,
});
uni.$on("socket-inbox", onReceiveMessage);
await laserCloseAPI();
});
onBeforeUnmount(() => {
uni.setKeepScreenOn({
keepScreenOn: false,
});
uni.$off("socket-inbox", onReceiveMessage);
audioManager.stopAll();
});
onShow(async () => {
if (battleId.value) {
const result = await getBattleAPI(battleId.value);
if (result.status === 2) {
uni.showToast({
title: "比赛已结束",
icon: "none",
});
uni.navigateBack({
delta: 2,
});
} else {
recoverData(result, { force: true });
}
}
});
</script>
<template>
<Container :title="title" :bgType="1">
<view class="container">
<BattleHeader v-if="!start" :players="players" />
<TestDistance v-if="start === false" :guide="false" :isBattle="true" />
<ShootProgress
:show="start"
:start="start && !halfRest"
:tips="tips"
:total="90"
:melee="true"
:battleId="battleId"
/>
<view v-if="start" class="user-row">
<Avatar :src="user.avatar" :size="35" />
<BowPower />
</view>
<BowTarget
v-if="start"
:currentRound="
playersScores.map((s) => s[user.id].length).reduce((a, b) => a + b, 0)
"
:totalRound="12"
:scores="playersScores.map((r) => r[user.id]).flat()"
:stop="halfRest"
/>
<view :style="{ paddingBottom: '20px' }">
<PlayerScore
v-if="start"
v-for="(player, index) in playersSorted"
:key="index"
:player="player"
:scores="playersScores.map((s) => s[player.id])"
/>
</view>
<ScreenHint
:show="halfTimeTip"
mode="small"
:onClose="() => (halfTimeTip = false)"
>
<view class="half-time-tip">
<text>上半场结束休息一下吧:</text>
<text>20秒后开始下半场</text>
</view>
</ScreenHint>
</view>
</Container>
</template>
<style scoped>
.container {
width: 100%;
height: 100%;
}
</style>