完成加入,退出房间
This commit is contained in:
@@ -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 });
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ export const MESSAGETYPES = {
|
||||
PaySuccess: 3793388244,
|
||||
RankUpdate: 1121669910,
|
||||
LvlUpdate: 3958625354,
|
||||
TeamUpdate: 4168086616,
|
||||
};
|
||||
|
||||
export const topThreeColors = ["#FFD947", "#D2D2D2", "#FFA515"];
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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";
|
||||
|
||||
Reference in New Issue
Block a user