完成加入,退出房间

This commit is contained in:
kron
2025-08-14 15:24:12 +08:00
parent 6803d0f408
commit 2a9a373743
8 changed files with 138 additions and 57 deletions

View File

@@ -7,7 +7,13 @@ import Guide from "@/components/Guide.vue";
import SButton from "@/components/SButton.vue";
import SModal from "@/components/SModal.vue";
import Avatar from "@/components/Avatar.vue";
import { getRoomAPI, destroyRoomAPI, exitRoomAPI, startRoomAPI } from "@/apis";
import {
getRoomAPI,
destroyRoomAPI,
exitRoomAPI,
startRoomAPI,
chooseTeamAPI,
} from "@/apis";
import { MESSAGETYPES } from "@/constants";
import useStore from "@/store";
import { storeToRefs } from "pinia";
@@ -17,12 +23,9 @@ const room = ref({});
const roomNumber = ref("");
const owner = ref({});
const opponent = ref({});
const players = ref([
{ name: "player1", team: 1 },
{ name: "player2", team: 0 },
{ name: "player3", team: 2 },
{ name: "player4", team: 1 },
]);
const players = ref([]);
const blueTeam = ref([]);
const redTeam = ref([]);
const showModal = ref(false);
const battleType = ref(0);
@@ -44,7 +47,7 @@ async function refreshRoomData() {
}
return false;
});
if (result.battleType === 1) {
if (result.battleType === 1 && result.count === 1) {
if (user.value.id !== owner.value.id) {
opponent.value = {
id: user.value.id,
@@ -77,6 +80,9 @@ async function refreshRoomData() {
result.members.forEach((m, index) => {
if (ownerIndex !== index) players.value.push(m.userInfo);
});
} else {
players.value = new Array(result.count).fill({});
refreshMembers(result.members);
}
}
@@ -84,6 +90,23 @@ const startGame = async () => {
const result = await startRoomAPI(room.value.number);
};
const refreshMembers = (members) => {
blueTeam.value = [];
redTeam.value = [];
members.forEach((m, index) => {
players.value[index] = { ...m.userInfo, groupType: m.groupType };
if (m.groupType === 1) {
blueTeam.value.push({ ...m.userInfo, groupType: 1 });
} else if (m.groupType === 0) {
redTeam.value.push({ ...m.userInfo, groupType: 0 });
}
});
for (let i = 0; i < room.value.count / 2; i++) {
if (!blueTeam.value[i]) blueTeam.value[i] = {};
if (!redTeam.value[i]) redTeam.value[i] = {};
}
};
async function onReceiveMessage(messages = []) {
messages.forEach((msg) => {
if (msg.roomNumber === roomNumber.value) {
@@ -134,6 +157,14 @@ async function onReceiveMessage(messages = []) {
if (battleType.value === 2) {
players.value = players.value.filter((p) => p.id !== msg.userId);
}
if (msg.room && msg.room.members) {
refreshMembers(msg.room.members);
}
}
if (msg.constructor === MESSAGETYPES.TeamUpdate) {
if (msg.room && msg.room.members) {
refreshMembers(msg.room.members);
}
}
if (msg.constructor === MESSAGETYPES.RoomDestroy) {
uni.showToast({
@@ -169,6 +200,17 @@ async function onReceiveMessage(messages = []) {
});
}
const chooseTeam = async (team) => {
if (team !== 2) {
const notInTeam = room.value.members.some(
(m) => m.userInfo.id === user.value.id && m.groupType === 2
);
if (!notInTeam) return;
}
const result = await chooseTeamAPI(roomNumber.value, team);
refreshMembers(result.members);
};
const destroyRoom = async () => {
if (roomNumber.value) await destroyRoomAPI(roomNumber.value);
};
@@ -237,7 +279,7 @@ onHide(() => {});
<view @click="setClipboardData">复制房间号</view>
</view>
</Guide>
<view v-if="battleType === 1" class="team-mode">
<view v-if="battleType === 1 && room.count === 2" class="team-mode">
<image
src="https://static.shelingxingqiu.com/attachment/2025-08-05/dbua9nuf5fyeph7cxi.png"
mode="widthFix"
@@ -270,44 +312,66 @@ onHide(() => {});
:total="room.count || 10"
:players="players"
/>
<view class="all-players">
<image
src="https://static.shelingxingqiu.com/attachment/2025-08-13/dc0x1p59iab6cvbhqc.png"
mode="widthFix"
/>
<image src="../static/title-2v2.png" mode="widthFix" />
<view>
<view v-for="(item, index) in players" :key="index">
<Avatar :src="item.avatar" :size="36" />
<text v-if="index === 0">创建者</text>
<block v-if="battleType === 1 && room.count >= 4">
<view class="all-players">
<image
src="https://static.shelingxingqiu.com/attachment/2025-08-13/dc0x1p59iab6cvbhqc.png"
mode="widthFix"
/>
<image src="../static/title-2v2.png" mode="widthFix" />
<view>
<view v-for="(item, index) in players" :key="index">
<Avatar v-if="item.id" :src="item.avatar" :size="36" />
<text v-if="owner.id === item.id">创建者</text>
</view>
</view>
</view>
</view>
<view class="choose-side">
<view>
<view v-for="i in 3" :key="i" class="choose-side-left-item">
<button hover-class="none">
<image src="../static/close-grey.png" mode="widthFix" />
</button>
<text class="truncate">23232323232</text>
<Avatar :size="36" />
<view class="choose-side">
<view>
<view
v-for="(item, index) in blueTeam"
:key="index"
class="choose-side-left-item"
>
<button
hover-class="none"
v-if="item.id === user.id"
@click="chooseTeam(2)"
>
<image src="../static/close-grey.png" mode="widthFix" />
</button>
<text class="truncate">{{ item.name || "我要加入" }}</text>
<Avatar v-if="item.id" :src="item.avatar" :size="36" />
<button v-else hover-class="none" @click="chooseTeam(1)">
<image src="../static/add-grey.png" mode="widthFix" />
</button>
</view>
</view>
<view>
<view
v-for="(item, index) in redTeam"
:key="index"
class="choose-side-right-item"
>
<Avatar v-if="item.id" :src="item.avatar" :size="36" />
<button v-else hover-class="none" @click="chooseTeam(0)">
<image src="../static/add-grey.png" mode="widthFix" />
</button>
<text class="truncate">{{ item.name || "我要加入" }}</text>
<button
hover-class="none"
v-if="item.id === user.id"
@click="chooseTeam(2)"
>
<image src="../static/close-grey.png" mode="widthFix" />
</button>
</view>
</view>
</view>
<view>
<view v-for="i in 3" :key="i" class="choose-side-right-item">
<button hover-class="none">
<image src="../static/add-grey.png" mode="widthFix" />
</button>
<text class="truncate">22222</text>
<button hover-class="none">
<image src="../static/close-grey.png" mode="widthFix" />
</button>
</view>
</view>
</view>
</block>
<view>
<SButton
v-if="user.id === owner.id && battleType === 1"
v-if="user.id === owner.id && battleType === 1 && room.count === 2"
:disabled="!opponent.id"
:onClick="startGame"
>进入对战</SButton
@@ -318,6 +382,14 @@ onHide(() => {});
:onClick="startGame"
>进入大乱斗</SButton
>
<SButton
v-if="user.id === owner.id && battleType === 1 && room.count >= 4"
:disabled="
players.some((p) => p.groupType === undefined || p.groupType === 2)
"
:onClick="startGame"
>开启对局</SButton
>
<SButton v-if="user.id !== owner.id" disabled>等待房主开启对战</SButton>
<text class="tips">创建者点击下一步所有人即可进入游戏</text>
</view>
@@ -559,6 +631,7 @@ onHide(() => {});
.choose-side-right-item > text {
margin: 10px;
max-width: 100px;
font-size: 14px;
}
.choose-side-left-item > button:first-child,
.choose-side-right-item > button:last-child {

View File

@@ -315,14 +315,9 @@ onHide(() => {
:team="blueTeam"
:isRed="false"
:currentShooterId="currentShooterId"
:youTurn="true"
/>
<ShootProgress2 :tips="tips" :currentRound="'round' + currentRound" />
<TeamAvatars
:team="redTeam"
:currentShooterId="currentShooterId"
:youTurn="true"
/>
<TeamAvatars :team="redTeam" :currentShooterId="currentShooterId" />
</view>
<BowTarget
v-if="start"