Files
shoot-miniprograms/src/components/BackToGame.vue
T
2026-06-18 16:18:55 +08:00

148 lines
3.4 KiB
Vue

<script setup>
import { ref, watch, onMounted, onBeforeUnmount } from "vue";
import { onShow } from "@dcloudio/uni-app";
import { getBattleAPI, getUserGameState } from "@/apis";
import { debounce } from "@/util";
import useStore from "@/store";
import { storeToRefs } from "pinia";
const store = useStore();
const { user, game } = storeToRefs(store);
const { updateGame } = store;
const props = defineProps({
signin: {
type: Function,
default: () => {},
},
});
const loading = ref(false);
const navigating = ref(false);
/** 统一获取当前环境 token,用于守卫:无有效 token 时不发起接口请求 */
const getToken = () =>
uni.getStorageSync(`${uni.getAccountInfoSync().miniProgram.envVersion}_token`);
onShow(async () => {
navigating.value = false;
if (user.value.id && getToken()) {
setTimeout(async () => {
const state = await getUserGameState();
updateGame(state.gaming, state.roomId);
}, 1000);
}
});
watch(
() => user.value,
async (value) => {
if (!value.id) {
updateGame(false, "");
} else if (getToken()) {
// 有有效 token 时才查询在局状态,避免 token 失效时反复发起无效请求
const state = await getUserGameState();
updateGame(state.gaming, state.roomId);
}
}
);
const navigateOnce = (url) =>
new Promise((resolve, reject) => {
navigating.value = true;
uni.navigateTo({
url,
success: resolve,
fail: (error) => {
navigating.value = false;
reject(error);
},
});
});
const onClick = debounce(async () => {
if (loading.value || navigating.value) return;
try {
loading.value = true;
const result = await getBattleAPI();
if (result && result.matchId) {
await uni.$checkAudio();
if (result.mode <= 3) {
await navigateOnce(`/pages/team-battle/index?battleId=${result.matchId}`);
} else {
await navigateOnce(`/pages/melee-battle?battleId=${result.matchId}`);
}
return;
}
if (game.value.roomID) {
await navigateOnce("/pages/battle-room?roomNumber=" + game.value.roomID);
} else {
updateGame(false, "");
}
} finally {
loading.value = false;
}
});
const gameOver = () => {
updateGame(false, "");
};
onMounted(() => {
uni.$on("game-over", gameOver);
});
onBeforeUnmount(() => {
uni.$off("game-over", gameOver);
});
</script>
<template>
<view
v-if="game.inBattle || game.roomID"
class="back-to-game"
@click="onClick"
>
<image src="../static/back-to-game-bg.png" mode="widthFix" />
<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>
<style scoped>
.back-to-game {
position: fixed;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
width: 56vw;
left: calc(50% - 28vw);
top: 12%;
z-index: 999;
}
.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 {
position: relative;
font-size: 14px;
}
.back-to-game > image:last-child {
position: relative;
width: 15px;
margin-left: 5px;
transform: rotate(180deg);
}
</style>