完成加入,退出房间

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

@@ -6,7 +6,7 @@ try {
switch (envVersion) {
case "develop": // 开发版
BASE_URL = "https://apitest.shelingxingqiu.com/api/shoot";
BASE_URL = "http://192.168.1.242:8000/api/shoot";
break;
case "trial": // 体验版
BASE_URL = "https://apitest.shelingxingqiu.com/api/shoot";
@@ -444,3 +444,7 @@ export const getPractiseDataAPI = async () => {
export const getBattleDataAPI = async () => {
return request("GET", "/user/fight/statistics");
};
export const chooseTeamAPI = async (number, group) => {
return request("POST", "/user/room/group", { number, group });
};

View File

@@ -23,10 +23,11 @@ const createRoom = async () => {
}
if (loading.value === true) return;
loading.value = true;
const result = await createRoomAPI(
battleMode.value,
battleMode.value === 1 ? 2 : 10
);
let size = 2;
if (battleMode.value === 2) size = 10;
if (battleMode.value === 3) size = 4;
if (battleMode.value === 4) size = 6;
const result = await createRoomAPI(battleMode.value === 2 ? 2 : 1, size);
if (result.number) roomNumber.value = result.number;
step.value = 2;
loading.value = false;

View File

@@ -17,7 +17,7 @@ const props = defineProps({
});
const barColor = ref("linear-gradient( 180deg, #FFA0A0 0%, #FF6060 100%)");
const remain = ref(10);
const remain = ref(15);
const timer = ref(null);
watch(

View File

@@ -9,17 +9,24 @@ const props = defineProps({
type: Array,
default: () => [],
},
currentShooterId: {
type: Number,
default: "",
},
youTurn: {
type: Boolean,
default: false,
},
});
const players = ref(props.team);
const youTurn = ref(false);
watch(
() => props.youTurn,
() => props.currentShooterId,
(newVal) => {
players.value = props.team;
}
const exit = props.team.some((p) => p.id === newVal);
youTurn.value = !!exit;
},
{ immediate: true }
);
</script>

View File

@@ -22,6 +22,7 @@ export const MESSAGETYPES = {
PaySuccess: 3793388244,
RankUpdate: 1121669910,
LvlUpdate: 3958625354,
TeamUpdate: 4168086616,
};
export const topThreeColors = ["#FFD947", "#D2D2D2", "#FFA515"];

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"

View File

@@ -14,7 +14,7 @@ function createWebSocket(token, onMessage) {
switch (envVersion) {
case "develop": // 开发版
url = "wss://apitest.shelingxingqiu.com/socket";
url = "ws://192.168.1.242:8000/socket";
break;
case "trial": // 体验版
url = "wss://apitest.shelingxingqiu.com/socket";