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

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

@@ -2,12 +2,14 @@
import { ref, watch, onMounted, onBeforeUnmount } from "vue";
import { onShow } from "@dcloudio/uni-app";
import { isGamingAPI, getCurrentGameAPI } from "@/apis";
import { getCurrentGameAPI, getUserGameState } from "@/apis";
import { debounce } from "@/util";
import useStore from "@/store";
import { storeToRefs } from "pinia";
const { user } = storeToRefs(useStore());
const store = useStore();
const { user, game } = storeToRefs(store);
const { updateGame } = store;
const props = defineProps({
signin: {
@@ -15,13 +17,14 @@ const props = defineProps({
default: () => {},
},
});
const show = ref(false);
const loading = ref(false);
onShow(async () => {
if (user.value.id) {
const isGaming = await isGamingAPI();
show.value = isGaming;
setTimeout(async () => {
const state = await getUserGameState();
updateGame(state.gaming, state.roomId);
}, 1000);
}
});
@@ -29,10 +32,10 @@ watch(
() => user.value,
async (value) => {
if (!value.id) {
show.value = false;
updateGame(false, "");
} else {
const isGaming = await isGamingAPI();
show.value = isGaming;
const state = await getUserGameState();
updateGame(state.gaming, state.roomId);
}
}
);
@@ -40,26 +43,23 @@ watch(
const onClick = debounce(async () => {
if (loading.value) return;
try {
const isGaming = await isGamingAPI();
show.value = isGaming;
if (isGaming) {
loading.value = true;
loading.value = true;
if (game.value.inBattle) {
await uni.$checkAudio();
const result = await getCurrentGameAPI();
loading.value = false;
} else {
uni.showToast({
title: "比赛已结束",
icon: "none",
} else if (game.value.roomID) {
uni.navigateTo({
url: "/pages/battle-room?roomNumber=" + game.value.roomID,
});
} else {
updateGame(false, "");
}
} finally {
loading.value = false;
}
});
const gameOver = () => {
show.value = false;
updateGame(false, "");
};
onMounted(() => {
uni.$on("game-over", gameOver);
@@ -70,10 +70,19 @@ onBeforeUnmount(() => {
</script>
<template>
<view v-if="show" class="back-to-game" @click="onClick">
<view
v-if="game.inBattle || game.roomID"
class="back-to-game"
@click="onClick"
>
<image src="../static/back-to-game-bg.png" mode="widthFix" />
<image src="../static/pk-icon.png" mode="widthFix" />
<text>返回进行中的对局</text>
<block v-if="game.inBattle">
<image src="../static/pk-icon.png" mode="widthFix" />
<text>返回进行中的对局</text>
</block>
<block v-else-if="game.roomID">
<text>返回房间</text>
</block>
<image src="../static/back.png" mode="widthFix" />
</view>
</template>
@@ -93,17 +102,18 @@ onBeforeUnmount(() => {
.back-to-game > image:first-child {
position: absolute;
width: 100%;
height: 100rpx;
}
.back-to-game > image:nth-child(2) {
position: relative;
width: 60px;
height: 60px;
}
.back-to-game > text:nth-child(3) {
.back-to-game > text {
position: relative;
font-size: 14px;
}
.back-to-game > image:nth-child(4) {
.back-to-game > image:last-child {
position: relative;
width: 15px;
margin-left: 5px;

View File

@@ -112,21 +112,8 @@ const backToGame = debounce(async () => {
try {
isLoading.value = true;
// 设置请求超时
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error("请求超时")), 10000); // 10秒超时
});
const result = await Promise.race([getCurrentGameAPI(), timeoutPromise]);
// 处理返回结果
if (result && result.gameId) {
// 跳转到游戏页面
uni.navigateTo({
url: `/pages/battle-room?gameId=${result.gameId}`,
});
} else {
const game = await getCurrentGameAPI();
if (!game || !game.gameId) {
uni.showToast({
title: "没有进行中的对局",
icon: "none",
@@ -136,10 +123,6 @@ const backToGame = debounce(async () => {
showHint.value = false;
} catch (error) {
console.error("获取当前游戏失败:", error);
uni.showToast({
title: error.message || "网络请求失败,请重试",
icon: "none",
});
} finally {
isLoading.value = false;
}

View File

@@ -1,7 +1,14 @@
<script setup>
import { ref } from "vue";
import SButton from "@/components/SButton.vue";
import { joinRoomAPI, createRoomAPI, isGamingAPI } from "@/apis";
import { joinRoomAPI, createRoomAPI } from "@/apis";
import { debounce } from "@/util";
import useStore from "@/store";
import { storeToRefs } from "pinia";
const store = useStore();
const { user, game } = storeToRefs(store);
const props = defineProps({
onConfirm: {
@@ -11,13 +18,11 @@ const props = defineProps({
});
const battleMode = ref(1);
const step = ref(1);
const loading = ref(false);
const roomNumber = ref("");
const createRoom = async () => {
const isGaming = await isGamingAPI();
if (isGaming) {
const createRoom = debounce(async () => {
if (game.value.inBattle) {
uni.$showHint(1);
return;
}
@@ -31,36 +36,20 @@ const createRoom = async () => {
battleMode.value === 2 ? 2 : 1,
battleMode.value === 2 ? 10 : size
);
if (result.number) roomNumber.value = result.number;
step.value = 2;
if (result.number) {
props.onConfirm();
await joinRoomAPI(result.number);
uni.navigateTo({
url: "/pages/battle-room?roomNumber=" + result.number,
});
}
loading.value = false;
};
const enterRoom = async () => {
step.value = 1;
props.onConfirm();
await joinRoomAPI(roomNumber.value);
uni.navigateTo({
url: `/pages/battle-room?roomNumber=${roomNumber.value}`,
});
};
const setClipboardData = () => {
uni.setClipboardData({
data: roomNumber.value,
success() {
uni.showToast({ title: "复制成功" });
},
});
};
});
</script>
<template>
<view class="container">
<image
v-if="step === 1"
src="../static/choose-battle-mode.png"
mode="widthFix"
/>
<view v-if="step === 1" class="create-options">
<image src="../static/choose-battle-mode.png" mode="widthFix" />
<view class="create-options">
<view
:class="{ 'battle-btn': true, 'battle-choosen': battleMode === 1 }"
@click="() => (battleMode = 1)"
@@ -72,14 +61,12 @@ const setClipboardData = () => {
@click="() => (battleMode = 3)"
>
<text>对抗模式2V2</text>
<!-- <text>敬请期待</text> -->
</view>
<view
:class="{ 'battle-btn': true, 'battle-choosen': battleMode === 4 }"
@click="() => (battleMode = 4)"
>
<text>对抗模式3V3</text>
<!-- <text>敬请期待</text> -->
</view>
<view
:class="{ 'battle-btn': true, 'battle-choosen': battleMode === 2 }"
@@ -88,18 +75,7 @@ const setClipboardData = () => {
<text>乱斗模式3-10</text>
</view>
</view>
<SButton v-if="step === 1" :onClick="createRoom">下一步</SButton>
<view v-if="step === 2" class="room-info">
<view>
<text>房间号</text>
<text>{{ roomNumber }}</text>
</view>
<view class="copy-room-number" @click="setClipboardData"
>复制房间信息邀请朋友进入</view
>
<SButton width="70vw" :onClick="enterRoom">进入房间</SButton>
<text>30分钟无人进入则房间无效</text>
</view>
<SButton :onClick="createRoom">创建房间</SButton>
</view>
</template>
@@ -142,42 +118,4 @@ const setClipboardData = () => {
border: 4rpx solid #fff3;
border-color: #fed847;
}
/* .battle-close {
background-color: #8889;
color: #b3b3b3;
}
.battle-close > text:last-child {
font-size: 12px;
} */
.room-info {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
padding-top: 40px;
}
.room-info > view:first-child {
font-size: 22px;
color: #fff;
margin-bottom: 20px;
}
.room-info > text {
color: #888686;
font-size: 14px;
margin: 10px 0;
}
.room-info > view:last-child {
color: #287fff;
margin: 20px 0;
font-size: 14px;
}
.copy-room-number {
width: calc(70vw - 20px);
color: #fed847;
border: 1px solid #fed847;
padding: 10px;
text-align: center;
border-radius: 10px;
margin-bottom: 20px;
}
</style>

View File

@@ -97,8 +97,10 @@ const handleLogin = async () => {
const devices = await getMyDevicesAPI();
if (devices.bindings && devices.bindings.length) {
updateDevice(devices.bindings[0].deviceId, devices.bindings[0].deviceName);
const data = await getDeviceBatteryAPI();
updateOnline(data.online);
try {
const data = await getDeviceBatteryAPI();
updateOnline(data.online);
} catch (error) {}
}
loading.value = false;
props.onClose();