6 Commits

8 changed files with 316 additions and 100 deletions

View File

@@ -362,6 +362,7 @@ class AudioManager {
} }
this.allowPlayMap.set(key, false); this.allowPlayMap.set(key, false);
this.onAudioEnded(key); this.onAudioEnded(key);
uni.$emit('audioEnded', key);
}); });
audio.onStop(() => { audio.onStop(() => {

View File

@@ -27,7 +27,7 @@ defineProps({
display: flex; display: flex;
align-items: center; align-items: center;
padding: 0 15px; padding: 0 15px;
margin-bottom: 14px; margin-bottom: 14rpx;
width: clac(100% - 30px); width: clac(100% - 30px);
} }
.container .shooter2 { .container .shooter2 {

View File

@@ -59,6 +59,9 @@ const loading = ref(false);
const pointBook = ref(null); const pointBook = ref(null);
const showProgress = ref(false); const showProgress = ref(false);
const heat = ref(0); const heat = ref(0);
/** 当前对战房间的房号,由 battle-room 页面通过 uni.$emit 传入 */
const battleRoomNumber = ref("");
const updateLoading = (value) => { const updateLoading = (value) => {
loading.value = value; loading.value = value;
}; };
@@ -67,6 +70,14 @@ const updateHot = (value) => {
heat.value = value; heat.value = value;
}; };
/**
* 接收 battle-room 页面发出的房间信息,更新房号展示
* @param {{ roomNumber: string }} info
*/
const updateBattleRoomInfo = (info) => {
battleRoomNumber.value = info.roomNumber || "";
};
onMounted(() => { onMounted(() => {
const pages = getCurrentPages(); const pages = getCurrentPages();
const currentPage = pages[pages.length - 1]; const currentPage = pages[pages.length - 1];
@@ -83,9 +94,11 @@ onMounted(() => {
showProgress.value = true; showProgress.value = true;
} }
uni.$on("update-hot", updateHot); uni.$on("update-hot", updateHot);
uni.$on("battle-room-info", updateBattleRoomInfo);
}); });
onBeforeUnmount(() => { onBeforeUnmount(() => {
uni.$off("update-hot", updateHot); uni.$off("update-hot", updateHot);
uni.$off("battle-room-info", updateBattleRoomInfo);
}); });
</script> </script>
@@ -172,6 +185,16 @@ onBeforeUnmount(() => {
<view v-if="showProgress" class="battle-progress"> <view v-if="showProgress" class="battle-progress">
<HeaderProgress /> <HeaderProgress />
</view> </view>
<!-- 对战房间:整个胶囊为分享按钮,点击任意区域均可触发分享 -->
<button
v-if="currentPage === 'pages/battle-room' && battleRoomNumber"
open-type="share"
hover-class="none"
class="battle-room-number"
>
<text class="battle-room-number__text">房号: {{ battleRoomNumber }}</text>
<image src="../static/share2.png" mode="widthFix" class="battle-room-number__icon" />
</button>
</view> </view>
</template> </template>
@@ -259,4 +282,37 @@ onBeforeUnmount(() => {
margin: 0 20rpx; margin: 0 20rpx;
max-width: 300rpx; max-width: 300rpx;
} }
/* 对战房间:整个胶囊作为分享按钮,靠右对齐 */
.battle-room-number {
margin-left: auto;
margin-right: 10rpx;
display: flex;
align-items: center;
justify-content: center;
width: 240rpx;
height: 64rpx;
background: rgba(0, 0, 0, 0.15);
border-radius: 96rpx;
border: 1rpx solid #5b5758;
flex-shrink: 0;
padding: 0;
line-height: normal;
}
/* 重置 button 默认边框 */
.battle-room-number::after {
border: none;
}
.battle-room-number__text {
width: 156rpx;
height: 28rpx;
font-weight: 400;
font-size: 20rpx;
color: #ffffff;
text-align: center;
line-height: 28rpx;
}
.battle-room-number__icon {
width: 25rpx;
height: 26rpx;
}
</style> </style>

View File

@@ -1,6 +1,7 @@
<script setup> <script setup>
import { ref, watch, onMounted, onBeforeUnmount } from "vue"; import {ref, watch, onMounted, onBeforeUnmount} from "vue";
import { RoundGoldImages } from "@/constants"; import {RoundGoldImages} from "@/constants";
const props = defineProps({ const props = defineProps({
tips: { tips: {
type: String, type: String,
@@ -19,13 +20,26 @@ const props = defineProps({
const barColor = ref(""); const barColor = ref("");
const remain = ref(15); const remain = ref(15);
const timer = ref(null); const timer = ref(null);
const laoding = ref(false); const loading = ref(false);
const transitionStyle = ref("all 1s linear"); const transitionStyle = ref("all 1s linear");
const currentTeam = ref(null);
const updateRemain = (value) => { const updateRemain = (value) => {
if (timer.value) clearInterval(timer.value); if (value.stop) {
const newVal = Math.round(value); if (timer.value) clearInterval(timer.value);
return
}
loading.value = false;
currentTeam.value = value.team
if (value.team === 'red')
barColor.value = "linear-gradient( 180deg, #FFA0A0 0%, #FF6060 100%)";
if (value.team === 'blue')
barColor.value = "linear-gradient( 180deg, #9AB3FF 0%, #4288FF 100%)";
if (value.reset) {
remain.value = value.value;
return;
}
const newVal = Math.round(value.value);
// 如果剩余时间增加(如轮次切换重置),瞬间变化无动画;否则保持动画 // 如果剩余时间增加(如轮次切换重置),瞬间变化无动画;否则保持动画
if (newVal >= remain.value) { if (newVal >= remain.value) {
transitionStyle.value = "none"; transitionStyle.value = "none";
@@ -38,26 +52,19 @@ const updateRemain = (value) => {
} }
timer.value = setInterval(() => { timer.value = setInterval(() => {
laoding.value = remain.value === 0; loading.value = remain.value === 0;
if (remain.value > 0) remain.value--; if (remain.value > 0) remain.value--;
}, 1000); }, 1000);
}; };
watch( watch(
() => props.tips, () => props.tips,
(newVal) => { (newVal) => {
if (newVal.includes("红队"))
barColor.value = "linear-gradient( 180deg, #FFA0A0 0%, #FF6060 100%)"; },
if (newVal.includes("蓝队")) {
barColor.value = "linear-gradient( 180deg, #9AB3FF 0%, #4288FF 100%)"; immediate: true,
if (newVal.includes("重回")) return;
if (newVal.includes("红队") || newVal.includes("蓝队")) {
updateRemain(props.total);
} }
},
{
immediate: true,
}
); );
onMounted(() => { onMounted(() => {
@@ -72,21 +79,21 @@ onBeforeUnmount(() => {
<template> <template>
<view class="container"> <view class="container">
<image :src="RoundGoldImages[props.currentRound]" mode="widthFix" /> <image :src="RoundGoldImages[props.currentRound]" mode="widthFix"/>
<view <view
:style="{ :style="{
justifyContent: tips.includes('红队') ? 'flex-end' : 'flex-start', justifyContent: currentTeam==='red' ? 'flex-end' : 'flex-start',
}" }"
> >
<view <view
:style="{ :style="{
width: `${(remain / total) * 100}%`, width: `${(remain / total) * 100}%`,
background: barColor, background: barColor,
right: tips.includes('红队') ? 0 : 'unset', right: currentTeam==='red' ? 0 : 'unset',
transition: transitionStyle, transition: transitionStyle,
}" }"
/> />
<text v-if="!laoding">剩余{{ remain }}</text> <text v-if="!loading">剩余{{ remain }}</text>
<text v-else>···</text> <text v-else>···</text>
</view> </view>
</view> </view>
@@ -99,11 +106,13 @@ onBeforeUnmount(() => {
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
} }
.container > image { .container > image {
width: 380rpx; width: 380rpx;
height: 80rpx; height: 80rpx;
transform: translateY(18rpx); transform: translateY(18rpx);
} }
.container > view:last-child { .container > view:last-child {
width: 100%; width: 100%;
text-align: center; text-align: center;
@@ -115,10 +124,12 @@ onBeforeUnmount(() => {
display: flex; display: flex;
align-items: center; align-items: center;
} }
.container > view:last-child > view { .container > view:last-child > view {
height: 24rpx; height: 24rpx;
border-radius: 15px; border-radius: 15px;
} }
.container > view:last-child > text { .container > view:last-child > text {
font-size: 18rpx; font-size: 18rpx;
color: #fff; color: #fff;

View File

@@ -6,6 +6,7 @@ import PlayerSeats from "@/components/PlayerSeats.vue";
import GuideTwo from "@/components/GuideTwo.vue"; import GuideTwo from "@/components/GuideTwo.vue";
import SButton from "@/components/SButton.vue"; import SButton from "@/components/SButton.vue";
import Avatar from "@/components/Avatar.vue"; import Avatar from "@/components/Avatar.vue";
import ScreenHint from "@/components/ScreenHint.vue";
import { import {
getRoomAPI, getRoomAPI,
destroyRoomAPI, destroyRoomAPI,
@@ -29,6 +30,18 @@ const players = ref([]);
const blueTeam = ref([]); const blueTeam = ref([]);
const redTeam = ref([]); const redTeam = ref([]);
/**
* 根据对战类型和房间人数动态生成页面标题
* battleType=1: 组队对战count 2/4/6 分别对应 1v1/2v2/3v3
* battleType=2: 多人乱斗
*/
const battleTitle = computed(() => {
if (!room.value.battleType) return "好友约战";
if (room.value.battleType === 2) return "多人乱斗";
const half = room.value.count / 2;
return `${half}v${half}对抗赛`;
});
const ready = ref(false); const ready = ref(false);
const allReady = ref(false); const allReady = ref(false);
const timer = ref(null); const timer = ref(null);
@@ -96,6 +109,9 @@ async function refreshRoomData() {
} }
if (timer.value) clearInterval(timer.value); if (timer.value) clearInterval(timer.value);
// timer.value = setTimeout(refreshRoomData, 2000); // timer.value = setTimeout(refreshRoomData, 2000);
// 通知 Header 组件更新房号展示
uni.$emit("battle-room-info", { roomNumber: roomNumber.value });
} }
const startGame = async () => { const startGame = async () => {
@@ -184,8 +200,32 @@ const exitRoom = async () => {
uni.navigateBack(); uni.navigateBack();
}; };
const removePlayer = async (player) => { /** 待确认踢出的玩家信息 */
await kickPlayerAPI(roomNumber.value, player.id); const playerToKick = ref(null);
/** 控制踢出确认弹窗的显示状态 */
const showKickConfirm = ref(false);
/**
* 点击踢出按钮,弹出二次确认弹窗
* @param {object} player - 被踢的玩家信息
*/
const removePlayer = (player) => {
playerToKick.value = player;
showKickConfirm.value = true;
};
/** 确认踢出:调用 API 并关闭弹窗 */
const confirmKick = async () => {
if (!playerToKick.value) return;
await kickPlayerAPI(roomNumber.value, playerToKick.value.id);
showKickConfirm.value = false;
playerToKick.value = null;
};
/** 取消踢出:关闭弹窗 */
const cancelKick = () => {
showKickConfirm.value = false;
playerToKick.value = null;
}; };
const canClick = computed(() => { const canClick = computed(() => {
@@ -214,7 +254,11 @@ onShow(() => {
}); });
onLoad(async (options) => { onLoad(async (options) => {
if (options.roomNumber) roomNumber.value = options.roomNumber; if (options.roomNumber) {
roomNumber.value = options.roomNumber;
// 立即通知 Header 显示房号,无需等待异步 API 返回
uni.$emit("battle-room-info", { roomNumber: options.roomNumber });
}
}); });
onMounted(() => { onMounted(() => {
@@ -236,7 +280,7 @@ onBeforeUnmount(() => {
</script> </script>
<template> <template>
<Container :title="`好友约战 - ${roomNumber}`"> <Container :title="battleTitle">
<view class="standby-phase"> <view class="standby-phase">
<GuideTwo> <GuideTwo>
<view class="battle-guide"> <view class="battle-guide">
@@ -247,7 +291,6 @@ onBeforeUnmount(() => {
}}</text> }}</text>
<text v-if="room.battleType === 2">大乱斗即将开始! </text> <text v-if="room.battleType === 2">大乱斗即将开始! </text>
</view> </view>
<!-- <button hover-class="none" open-type="share">邀请</button> -->
</view> </view>
</GuideTwo> </GuideTwo>
<view v-if="room.battleType === 1 && room.count === 2" class="team-mode"> <view v-if="room.battleType === 1 && room.count === 2" class="team-mode">
@@ -343,6 +386,20 @@ onBeforeUnmount(() => {
</view> </view>
</view> </view>
</Container> </Container>
<!-- 踢出玩家二次确认弹窗不传 onClose屏蔽 X 关闭按钮 -->
<ScreenHint :show="showKickConfirm">
<view class="kick-confirm">
<!-- 弹窗标题玩家名字高亮显示 -->
<text class="kick-confirm__title">
是否把<text style="color: #F7D550">{{ playerToKick && playerToKick.name }}</text>移出房间
</text>
<!-- 按钮区确认在左取消在右 -->
<view class="kick-confirm__btns">
<button hover-class="none" class="kick-confirm__btn kick-confirm__btn--confirm" @click="confirmKick">确定</button>
<button hover-class="none" class="kick-confirm__btn kick-confirm__btn--cancel" @click="cancelKick">取消</button>
</view>
</view>
</ScreenHint>
</template> </template>
<style scoped> <style scoped>
@@ -380,7 +437,7 @@ onBeforeUnmount(() => {
.team-mode { .team-mode {
width: calc(100vw - 30px); width: calc(100vw - 30px);
height: 125vw; height: 125vw;
margin: 15px; margin: 0 15px 15px 15px;
} }
.team-mode>image:first-child { .team-mode>image:first-child {
@@ -445,6 +502,66 @@ onBeforeUnmount(() => {
color: #fed847 !important; color: #fed847 !important;
} }
/* 踢出确认弹窗内容 */
.kick-confirm {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 20rpx 30rpx;
color: #fff;
}
.kick-confirm__title {
font-size: 30rpx;
font-weight: 500;
text-align: center;
line-height: 1.5;
/* 标题与按钮区间距 */
margin-bottom: 58rpx;
}
.kick-confirm__btns {
display: flex;
/* 两个按钮间距 */
gap: 16rpx;
}
/* 按钮公共基础样式:固定宽高与圆角 */
.kick-confirm__btn {
font-size: 28rpx;
width: 232rpx;
height: 70rpx;
border-radius: 44rpx;
line-height: 70rpx;
display: flex;
align-items: center;
justify-content: center;
}
/* 取消按钮:白色半透明背景(用 rgba 避免 opacity 平铺到文字) */
.kick-confirm__btn--cancel {
background: rgba(255, 255, 255, 0.2);
border: none;
color: #FFFFFF;
font-weight: 500;
font-size: 28rpx;
text-align: center;
border-radius: 44rpx;
}
.kick-confirm__btn--cancel::after {
border: none;
}
/* 确认按钮:黄色实心背景 */
.kick-confirm__btn--confirm {
background: #FED847;
border: none;
color: #000000;
font-weight: 500;
font-size: 28rpx;
text-align: center;
border-radius: 44rpx;
}
.kick-confirm__btn--confirm::after {
border: none;
}
.remove-player { .remove-player {
width: 40rpx; width: 40rpx;
height: 40rpx; height: 40rpx;

View File

@@ -73,10 +73,10 @@ const onSignin = () => {
showSignin.value = false; showSignin.value = false;
}; };
/** 跳转到我的战绩页面 */ /** 跳转到我的战绩页面默认展示「好友约战」tab */
const goMyRecord = () => { const goMyRecord = () => {
uni.navigateTo({ uni.navigateTo({
url: '/pages/my-growth', url: '/pages/my-growth?tab=1',
}); });
}; };
onShow(async () => { onShow(async () => {

View File

@@ -1,5 +1,6 @@
<script setup> <script setup>
import { onMounted } from "vue"; import { onMounted } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import Container from "@/components/Container.vue"; import Container from "@/components/Container.vue";
import Avatar from "@/components/Avatar.vue"; import Avatar from "@/components/Avatar.vue";
import BowData from "@/components/BowData.vue"; import BowData from "@/components/BowData.vue";
@@ -56,6 +57,17 @@ const getName = (battle) => {
if (battle.mode <= 3) return `${battle.mode}V${battle.mode}`; if (battle.mode <= 3) return `${battle.mode}V${battle.mode}`;
return battle.mode + "人大乱斗"; return battle.mode + "人大乱斗";
}; };
/**
* 支持通过 URL 参数指定初始 tab
* @example /pages/my-growth?tab=1 跳转到「好友约战」tab
*/
onLoad((options) => {
if (options && options.tab !== undefined) {
const tabIndex = parseInt(options.tab, 10);
if (!isNaN(tabIndex)) selectedIndex.value = tabIndex;
}
});
</script> </script>
<template> <template>

View File

@@ -1,6 +1,6 @@
<script setup> <script setup>
import { ref, onMounted, onBeforeUnmount, nextTick } from "vue"; import {ref, onMounted, onBeforeUnmount, nextTick} from "vue";
import { onLoad, onShow, onHide } from "@dcloudio/uni-app"; import {onLoad, onShow, onHide} from "@dcloudio/uni-app";
import Container from "@/components/Container.vue"; import Container from "@/components/Container.vue";
import BattleHeader from "@/components/BattleHeader.vue"; import BattleHeader from "@/components/BattleHeader.vue";
import BowTarget from "@/components/BowTarget.vue"; import BowTarget from "@/components/BowTarget.vue";
@@ -11,13 +11,14 @@ import RoundEndTip from "@/components/RoundEndTip.vue";
import TestDistance from "@/components/TestDistance.vue"; import TestDistance from "@/components/TestDistance.vue";
import TeamAvatars from "@/components/TeamAvatars.vue"; import TeamAvatars from "@/components/TeamAvatars.vue";
import ShootProgress2 from "@/components/ShootProgress2.vue"; import ShootProgress2 from "@/components/ShootProgress2.vue";
import { laserCloseAPI, getBattleAPI } from "@/apis"; import {laserCloseAPI, getBattleAPI} from "@/apis";
import { MESSAGETYPESV2 } from "@/constants"; import {MESSAGETYPESV2} from "@/constants";
import audioManager from "@/audioManager"; import audioManager from "@/audioManager";
import useStore from "@/store"; import useStore from "@/store";
import { storeToRefs } from "pinia"; import {storeToRefs} from "pinia";
const store = useStore(); const store = useStore();
const { user } = storeToRefs(store); const {user} = storeToRefs(store);
const start = ref(null); const start = ref(null);
const tips = ref(""); const tips = ref("");
const battleId = ref(""); const battleId = ref("");
@@ -36,8 +37,9 @@ const bluePoints = ref(0);
const showRoundTip = ref(false); const showRoundTip = ref(false);
const isFinalShoot = ref(false); const isFinalShoot = ref(false);
const matchStatus = ref(undefined); const matchStatus = ref(undefined);
const updateRemainSecond = ref(0);
const recoverData = (battleInfo, { force = false, arrowOnly = false } = {}) => { const recoverData = (battleInfo, {force = false, arrowOnly = false} = {}) => {
try { try {
battleId.value = battleInfo.matchId; battleId.value = battleInfo.matchId;
@@ -71,28 +73,27 @@ const recoverData = (battleInfo, { force = false, arrowOnly = false } = {}) => {
if (!arrowOnly) { if (!arrowOnly) {
currentShooterId.value = battleInfo.current.playerId; currentShooterId.value = battleInfo.current.playerId;
const redPlayer = battleInfo.teams[2].players.find( const redPlayer = battleInfo.teams[2].players.find(
(item) => item.id === battleInfo.current.playerId (item) => item.id === battleInfo.current.playerId
); );
let nextTips = redPlayer ? "请红队射箭" : "请蓝队射箭"; let nextTips = redPlayer ? "请红队射箭" : "请蓝队射箭";
if (force) nextTips += "重回"; if (force) nextTips += "重回";
if ( if (
battleInfo.current.playerId === user.value.id && battleInfo.current.playerId === user.value.id &&
redTeam.value.length > 1 redTeam.value.length > 1
) { ) {
nextTips += "你"; nextTips += "你";
} }
tips.value = nextTips; tips.value = nextTips;
uni.$emit("update-tips", nextTips); uni.$emit("update-tips", nextTips);
uni.$emit("update-remain", {reset: true, value: 15, team: redTeam?'red':'blue'});
if (force) { if (force) {
const remain = (Date.now() - battleInfo.current.startTime) / 1000; const remain = (Date.now() - battleInfo.current.startTime) / 1000;
console.log(`当前轮已进行${remain}`); console.log(`当前轮已进行${remain}`);
if (remain > 0 && remain < 15) { if (remain > 0 && remain < 15) {
setTimeout(() => { updateRemainSecond.value = 15 - remain - 0.2
uni.$emit("update-remain", 15 - remain - 0.2);
}, 200);
} }
} else { } else {
uni.$emit("update-remain", battleInfo.readyTime); updateRemainSecond.value = battleInfo.readyTime
} }
} else { } else {
currentRound.value = battleInfo.current.round || 1; currentRound.value = battleInfo.current.round || 1;
@@ -111,15 +112,39 @@ const recoverData = (battleInfo, { force = false, arrowOnly = false } = {}) => {
} }
}; };
function onBattleEnd(){ function onAudioEnded(s) {
showRoundTip.value = false if (s.indexOf('请红方射箭') >= 0 || s.indexOf('请蓝方射箭') >= 0) {
console.log("onBattleEnd ended...") let team = s.indexOf('请红方射箭') >= 0 ? 'red' : 'blue';
uni.$emit("update-remain", {stop: false, value: updateRemainSecond.value, team: team});
}
if (s.indexOf("比赛结束") >= 0) {
onBattleEnd()
}
}
function onBattleEnd() {
if (matchStatus.value === 2) { if (matchStatus.value === 2) {
uni.redirectTo({ uni.redirectTo({
url: `/pages/battle-result?battleId=${battleId.value}`, url: `/pages/battle-result?battleId=${battleId.value}`,
}); });
} }
} }
function onNewRound(msg) {
showRoundTip.value = true;
isFinalShoot.value = msg.current.goldRound;
const latestRound = msg.rounds[currentRound.value - 1];
if (latestRound) {
if (isFinalShoot.value) {
currentBluePoint.value = msg.teams[1].score;
currentRedPoint.value = msg.teams[2].score;
} else {
currentBluePoint.value = latestRound.scores[1].score;
currentRedPoint.value = latestRound.scores[2].score;
}
}
}
async function onReceiveMessage(msg) { async function onReceiveMessage(msg) {
if (Array.isArray(msg)) return; if (Array.isArray(msg)) return;
if (msg.type === MESSAGETYPESV2.BattleStart) { if (msg.type === MESSAGETYPESV2.BattleStart) {
@@ -127,21 +152,13 @@ async function onReceiveMessage(msg) {
} else if (msg.type === MESSAGETYPESV2.ToSomeoneShoot) { } else if (msg.type === MESSAGETYPESV2.ToSomeoneShoot) {
recoverData(msg); recoverData(msg);
} else if (msg.type === MESSAGETYPESV2.ShootResult) { } else if (msg.type === MESSAGETYPESV2.ShootResult) {
uni.$emit("update-remain", {stop: true})
showRoundTip.value = false; showRoundTip.value = false;
recoverData(msg, { arrowOnly: true }); recoverData(msg, {arrowOnly: true});
} else if (msg.type === MESSAGETYPESV2.NewRound) { } else if (msg.type === MESSAGETYPESV2.NewRound) {
showRoundTip.value = true; setTimeout(() => {
isFinalShoot.value = msg.current.goldRound; onNewRound(msg)
const latestRound = msg.rounds[currentRound.value - 1]; }, 800)
if (latestRound) {
if (isFinalShoot.value) {
currentBluePoint.value = msg.teams[1].score;
currentRedPoint.value = msg.teams[2].score;
} else {
currentBluePoint.value = latestRound.scores[1].score;
currentRedPoint.value = latestRound.scores[2].score;
}
}
} else if (msg.type === MESSAGETYPESV2.BattleEnd) { } else if (msg.type === MESSAGETYPESV2.BattleEnd) {
matchStatus.value = msg.status; matchStatus.value = msg.status;
if (msg.status === 4) { if (msg.status === 4) {
@@ -169,13 +186,14 @@ onMounted(async () => {
keepScreenOn: true, keepScreenOn: true,
}); });
uni.$on("socket-inbox", onReceiveMessage); uni.$on("socket-inbox", onReceiveMessage);
uni.$on("audioEnded", onAudioEnded);
await laserCloseAPI(); await laserCloseAPI();
}); });
onBeforeUnmount(() => { onBeforeUnmount(() => {
uni.setKeepScreenOn({ uni.setKeepScreenOn({
keepScreenOn: false, keepScreenOn: false,
}); });
uni.$off("socket-inbox", onReceiveMessage); uni.$off("audioEnded", onAudioEnded);
audioManager.stopAll(); audioManager.stopAll();
}); });
const refreshTimer = ref(null); const refreshTimer = ref(null);
@@ -192,7 +210,7 @@ onShow(async () => {
delta: 2, delta: 2,
}); });
} else { } else {
recoverData(result, { force: true }); recoverData(result, {force: true});
} }
} }
}); });
@@ -202,53 +220,53 @@ onShow(async () => {
<Container :bgType="start ? 3 : 1"> <Container :bgType="start ? 3 : 1">
<view class="container"> <view class="container">
<BattleHeader <BattleHeader
v-if="start === false" v-if="start === false"
:redTeam="redTeam" :redTeam="redTeam"
:blueTeam="blueTeam" :blueTeam="blueTeam"
/> />
<TestDistance v-if="start === false" :guide="false" :isBattle="true" /> <TestDistance v-if="start === false" :guide="false" :isBattle="true"/>
<view v-if="start" class="players-row"> <view v-if="start" class="players-row">
<TeamAvatars <TeamAvatars
:team="blueTeam" :team="blueTeam"
:isRed="false" :isRed="false"
:currentShooterId="currentShooterId" :currentShooterId="currentShooterId"
/> />
<ShootProgress2 <ShootProgress2
:tips="tips" :tips="tips"
:currentRound=" :currentRound="
goldenRound > 0 ? 'gold' + goldenRound : 'round' + currentRound goldenRound > 0 ? 'gold' + goldenRound : 'round' + currentRound
" "
/> />
<TeamAvatars :team="redTeam" :currentShooterId="currentShooterId" /> <TeamAvatars :team="redTeam" :currentShooterId="currentShooterId"/>
</view> </view>
<BowTarget <BowTarget
v-if="start" v-if="start"
mode="team" mode="team"
:scores="scores" :scores="scores"
:blueScores="blueScores" :blueScores="blueScores"
/> />
<BattleFooter <BattleFooter
v-if="start" v-if="start"
:roundResults="roundResults" :roundResults="roundResults"
:redPoints="redPoints" :redPoints="redPoints"
:bluePoints="bluePoints" :bluePoints="bluePoints"
:goldenRound="goldenRound" :goldenRound="goldenRound"
/> />
<ScreenHint <ScreenHint
:show="showRoundTip" :show="showRoundTip"
:onClose="() => (showRoundTip = false)" :onClose="() => (showRoundTip = false)"
:mode="isFinalShoot ? 'tall' : 'normal'" :mode="isFinalShoot ? 'tall' : 'normal'"
> >
<RoundEndTip <RoundEndTip
v-if="showRoundTip" v-if="showRoundTip"
:isFinal="isFinalShoot" :isFinal="isFinalShoot"
:round="currentRound" :round="currentRound"
:bluePoint="currentBluePoint" :bluePoint="currentBluePoint"
:redPoint="currentRedPoint" :redPoint="currentRedPoint"
:roundData=" :roundData="
roundResults[currentRound - 1] ? roundResults[currentRound - 1] : [] roundResults[currentRound - 1] ? roundResults[currentRound - 1] : []
" "
:onAutoClose="onBattleEnd" :onAutoClose="()=>{ showRoundTip = false}"
/> />
</ScreenHint> </ScreenHint>
</view> </view>
@@ -260,6 +278,7 @@ onShow(async () => {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
.players-row { .players-row {
display: flex; display: flex;
align-items: center; align-items: center;