添加分享房间链接和对战结束返回房间

This commit is contained in:
kron
2026-01-09 11:50:21 +08:00
parent 4aa14c6a4c
commit 71b25144a4
14 changed files with 204 additions and 209 deletions

View File

@@ -1,6 +1,6 @@
<script setup>
import { ref, watch, onMounted, onBeforeUnmount } from "vue";
import { onLoad, onShow, onHide } from "@dcloudio/uni-app";
import { onLoad, onShareAppMessage } from "@dcloudio/uni-app";
import Container from "@/components/Container.vue";
import PlayerSeats from "@/components/PlayerSeats.vue";
import Guide from "@/components/Guide.vue";
@@ -13,12 +13,15 @@ import {
exitRoomAPI,
startRoomAPI,
chooseTeamAPI,
getReadyAPI,
} from "@/apis";
import { MESSAGETYPES } from "@/constants";
import useStore from "@/store";
import { storeToRefs } from "pinia";
const store = useStore();
const { user } = storeToRefs(store);
const room = ref({});
const roomNumber = ref("");
const owner = ref({});
@@ -30,14 +33,27 @@ const redTeam = ref([]);
const showModal = ref(false);
const battleType = ref(0);
const refreshRoomTimer = ref(null);
const ready = ref(false);
const allReady = ref(false);
const timer = ref(null);
async function refreshRoomData() {
if (!roomNumber.value) return;
const result = await getRoomAPI(roomNumber.value);
if (result.started) return;
room.value = result;
battleType.value = result.battleType;
(result.members || []).some((m) => {
const members = result.members || [];
if (members.length === result.count) {
allReady.value = members.every((m) => !!m.userInfo.state);
}
members.some((m) => {
if (m.userInfo.id === user.value.id) {
ready.value = !!m.userInfo.state;
return true;
}
return false;
});
members.some((m) => {
if (m.userInfo.id === result.creator) {
owner.value = {
id: m.userInfo.id,
@@ -77,13 +93,19 @@ async function refreshRoomData() {
players.value = new Array(result.count).fill({});
refreshMembers(result.members);
}
if (timer.value) clearInterval(timer.value);
timer.value = setTimeout(refreshRoomData, 1000);
}
const startGame = async () => {
const result = await startRoomAPI(room.value.number);
};
const refreshMembers = (members) => {
const getReady = async () => {
await getReadyAPI(roomNumber.value);
};
const refreshMembers = (members = []) => {
blueTeam.value = [];
redTeam.value = [];
members.forEach((m, index) => {
@@ -138,8 +160,7 @@ async function onReceiveMessage(messages = []) {
});
}
}
}
if (msg.constructor === MESSAGETYPES.UserExitRoom) {
} else if (msg.constructor === MESSAGETYPES.UserExitRoom) {
if (battleType.value === 1) {
if (msg.userId === room.value.creator) {
owner.value = {
@@ -157,25 +178,22 @@ async function onReceiveMessage(messages = []) {
if (msg.room && msg.room.members) {
refreshMembers(msg.room.members);
}
}
if (msg.constructor === MESSAGETYPES.TeamUpdate) {
} else if (msg.constructor === MESSAGETYPES.TeamUpdate) {
if (msg.room && msg.room.members) {
refreshMembers(msg.room.members);
}
}
if (msg.constructor === MESSAGETYPES.RoomDestroy) {
} else if (msg.constructor === MESSAGETYPES.RoomDestroy) {
uni.showToast({
title: "房间已解散",
icon: "none",
});
roomNumber.value = "";
setTimeout(() => {
uni.navigateBack();
}, 1000);
} else if (msg.constructor === MESSAGETYPES.SomeoneIsReady) {
refreshRoomData();
}
}
if (msg.constructor === MESSAGETYPES.WaitForAllReady) {
roomNumber.value = "";
} else if (msg.constructor === MESSAGETYPES.WaitForAllReady) {
if (msg.groupUserStatus) {
uni.setStorageSync("red-team", msg.groupUserStatus.redTeam);
uni.setStorageSync("blue-team", msg.groupUserStatus.blueTeam);
@@ -184,6 +202,8 @@ async function onReceiveMessage(messages = []) {
...msg.groupUserStatus.blueTeam,
]);
uni.removeStorageSync("current-battle");
// 避免离开页面,触发退出房间
roomNumber.value = "";
if (msg.groupUserStatus.config.mode == 1) {
uni.redirectTo({
url: `/pages/team-battle?battleId=${msg.id}&gameMode=1`,
@@ -226,15 +246,18 @@ const setClipboardData = () => {
});
};
const onBack = () => {
showModal.value = true;
};
onShareAppMessage(() => {
return {
title: "邀请您进入房间对战",
path: "/pages/friend-battle?roomID=" + roomNumber.value,
imageUrl: "",
};
});
onLoad(async (options) => {
if (options.roomNumber) {
roomNumber.value = options.roomNumber;
refreshRoomData();
refreshRoomTimer.value = setInterval(refreshRoomData, 2000);
}
});
@@ -251,19 +274,14 @@ onBeforeUnmount(() => {
keepScreenOn: false,
});
uni.$off("socket-inbox", onReceiveMessage);
if (roomNumber.value && owner.value.id !== user.value.id) {
exitRoomAPI(roomNumber.value);
}
if (roomNumber.value) exitRoomAPI(roomNumber.value);
if (timer.value) clearInterval(timer.value);
timer.value = null;
});
onShow(async () => {
refreshRoomData();
});
onHide(() => {});
</script>
<template>
<Container :title="`好友约战 - ${roomNumber}`" :onBack="onBack">
<Container :title="`好友约战 - ${roomNumber}`">
<view class="standby-phase">
<Guide>
<view class="battle-guide">
@@ -274,7 +292,7 @@ onHide(() => {});
}}</text>
<text v-if="battleType === 2">大乱斗即将开始! </text>
</view>
<view @click="setClipboardData">复制房间号</view>
<button hover-class="none" open-type="share">邀请</button>
</view>
</Guide>
<view v-if="battleType === 1 && room.count === 2" class="team-mode">
@@ -389,7 +407,7 @@ onHide(() => {});
</view>
</block>
<view>
<SButton
<!-- <SButton
v-if="user.id === owner.id && battleType === 1 && room.count === 2"
:disabled="!opponent.id"
:onClick="startGame"
@@ -409,11 +427,14 @@ onHide(() => {});
:onClick="startGame"
>开启对局</SButton
>
<SButton v-if="user.id !== owner.id" disabled>等待房主开启对战</SButton>
<text class="tips">创建者点击下一步所有人即可进入游戏</text>
<SButton v-if="user.id !== owner.id" disabled>等待房主开启对战</SButton> -->
<SButton :disabled="ready" :onClick="getReady">{{
allReady.value ? "即将进入对局..." : "我准备好了"
}}</SButton>
<!-- <text class="tips">创建者点击下一步所有人即可进入游戏</text> -->
</view>
</view>
<SModal
<!-- <SModal
:show="showModal"
:onClose="() => (showModal = false)"
height="520rpx"
@@ -429,7 +450,7 @@ onHide(() => {});
</SButton>
</block>
</view>
</SModal>
</SModal> -->
</Container>
</template>
@@ -537,7 +558,7 @@ onHide(() => {});
align-items: center;
justify-content: space-between;
}
.battle-guide > view:last-child {
.battle-guide > button:last-child {
color: #fed847;
border: 1px solid #fed847;
margin-right: 10px;