Files
shoot-miniprograms/src/pages/friend-battle.vue

317 lines
7.8 KiB
Vue
Raw Normal View History

2025-05-01 16:36:24 +08:00
<script setup>
2025-05-16 15:56:54 +08:00
import { ref } from "vue";
2025-08-13 17:11:30 +08:00
import { onShow } from "@dcloudio/uni-app";
2025-07-02 17:21:44 +08:00
import Container from "@/components/Container.vue";
2025-05-01 22:50:17 +08:00
import Guide from "@/components/Guide.vue";
2025-05-10 16:57:36 +08:00
import SButton from "@/components/SButton.vue";
2025-05-16 15:56:54 +08:00
import SModal from "@/components/SModal.vue";
import CreateRoom from "@/components/CreateRoom.vue";
2025-08-12 18:33:39 +08:00
import Avatar from "@/components/Avatar.vue";
2025-08-13 17:11:30 +08:00
import { getRoomAPI, joinRoomAPI, isGamingAPI, getBattleDataAPI } from "@/apis";
2025-06-19 21:49:16 +08:00
import useStore from "@/store";
import { storeToRefs } from "pinia";
const store = useStore();
const { user } = storeToRefs(store);
2025-06-22 15:04:10 +08:00
import { debounce } from "@/util";
2025-05-16 15:56:54 +08:00
const showModal = ref(false);
const warnning = ref("");
const roomNumber = ref("");
2025-08-13 17:11:30 +08:00
const data = ref({});
2025-05-16 15:56:54 +08:00
2025-06-22 15:04:10 +08:00
const enterRoom = debounce(async () => {
2025-07-02 17:16:56 +08:00
const isGaming = await isGamingAPI();
if (isGaming) {
2025-07-03 21:13:55 +08:00
uni.$showHint(1);
2025-07-02 17:16:56 +08:00
return;
}
2025-05-16 15:56:54 +08:00
if (!roomNumber.value) {
warnning.value = "请输入房间号";
2025-05-30 16:14:17 +08:00
showModal.value = true;
2025-05-16 15:56:54 +08:00
} else {
2025-06-19 21:49:16 +08:00
const room = await getRoomAPI(roomNumber.value);
2025-05-30 16:14:17 +08:00
if (room.number) {
2025-06-19 21:49:16 +08:00
const alreadyIn = room.members.find(
(item) => item.userInfo.id === user.value.id
);
2025-07-25 10:00:18 +08:00
if (!alreadyIn) {
const result = await joinRoomAPI(roomNumber.value);
2025-07-25 15:18:46 +08:00
if (result.full) {
warnning.value = "房间已满员";
showModal.value = true;
return;
}
2025-07-25 10:00:18 +08:00
}
2025-05-30 16:14:17 +08:00
roomNumber.value = "";
2025-06-22 15:04:10 +08:00
showModal.value = false;
2025-05-30 16:14:17 +08:00
uni.navigateTo({
2025-06-13 14:05:30 +08:00
url: `/pages/battle-room?roomNumber=${room.number}`,
2025-05-30 16:14:17 +08:00
});
} else {
2025-07-25 10:00:18 +08:00
warnning.value = room.started ? "该房间对战已开始,无法加入" : "查无此房";
2025-05-30 16:14:17 +08:00
showModal.value = true;
}
2025-05-16 15:56:54 +08:00
}
2025-06-22 15:04:10 +08:00
});
const onCreateRoom = async () => {
const isGaming = await isGamingAPI();
if (isGaming) {
uni.$showHint(1);
return;
}
2025-05-16 15:56:54 +08:00
warnning.value = "";
showModal.value = true;
};
2025-08-13 17:11:30 +08:00
onShow(async () => {
const result = await getBattleDataAPI();
data.value = result;
});
2025-05-01 16:36:24 +08:00
</script>
<template>
2025-07-21 16:15:14 +08:00
<Container title="好友约战" :showBackToGame="true">
2025-07-02 17:21:44 +08:00
<view :style="{ width: '100%' }">
<Guide>
<view class="guide-tips">
<text>约上朋友开几局欢乐多不寂寞</text>
<text>一起练升级更快早日加入全国排位赛</text>
</view>
</Guide>
2025-08-12 18:33:39 +08:00
<view class="my-data">
<view>
<Avatar :rankLvl="user.rankLvl" :src="user.avatar" :size="30" />
2025-08-17 10:33:41 +08:00
<text class="truncate">{{ user.nickName }}</text>
2025-08-12 18:33:39 +08:00
</view>
<view>
<view>
<view>
2025-08-13 17:11:30 +08:00
<text>{{ data.TotalBattle }}</text>
2025-08-12 18:33:39 +08:00
<text></text>
</view>
<text>约战数量</text>
</view>
<view>
<view>
2025-08-13 17:11:30 +08:00
<text>{{ data.totalArrow }}</text>
2025-08-12 18:33:39 +08:00
<text></text>
</view>
<text>射箭量</text>
</view>
<view>
<view class="stars">
2025-08-13 17:11:30 +08:00
<block v-for="i in 5" :key="i">
<image
v-if="data.totalWinningRate >= i * 0.2"
src="../static/star-full.png"
mode="widthFix"
/>
<image
v-else-if="data.totalWinningRate >= (i - 1) * 0.2 + 0.1"
src="../static/star-half.png"
mode="widthFix"
/>
<image v-else src="../static/star-empty.png" mode="widthFix" />
</block>
2025-08-12 18:33:39 +08:00
</view>
<text>挑战难度</text>
</view>
</view>
</view>
2025-07-02 17:21:44 +08:00
<view class="founded-room">
<image src="../static/founded-room.png" mode="widthFix" />
2025-05-01 22:50:17 +08:00
<view>
2025-07-02 17:21:44 +08:00
<input
placeholder="输入房间号"
v-model="roomNumber"
placeholder-style="color: #ccc"
/>
<view @click="enterRoom">进入房间</view>
2025-05-01 22:50:17 +08:00
</view>
</view>
2025-07-02 17:21:44 +08:00
<view class="create-room">
2025-07-15 14:16:02 +08:00
<image
2025-08-04 18:36:44 +08:00
src="https://static.shelingxingqiu.com/attachment/2025-07-15/dbcejys872iyun92h6.png"
2025-07-15 14:16:02 +08:00
mode="widthFix"
/>
2025-08-13 16:44:25 +08:00
<image src="../static/room-notfound-title.png" mode="widthFix" />
2025-07-02 17:21:44 +08:00
<view>
2025-07-14 13:39:10 +08:00
<image :src="user.avatar" mode="widthFix" />
2025-07-02 17:21:44 +08:00
<image src="../static/versus.png" mode="widthFix" />
<view>
<image src="../static/question-mark.png" mode="widthFix" />
</view>
</view>
<view>
2025-07-15 14:16:02 +08:00
<SButton width="80%" :rounded="30" :onClick="onCreateRoom">
2025-07-02 17:21:44 +08:00
创建约战房
</SButton>
</view>
2025-05-10 16:57:36 +08:00
</view>
2025-07-02 17:21:44 +08:00
<SModal :show="showModal" :onClose="() => (showModal = false)">
<view v-if="warnning" class="warnning">
{{ warnning }}
</view>
<CreateRoom v-if="!warnning" :onConfirm="() => (showModal = false)" />
</SModal>
2025-05-01 22:50:17 +08:00
</view>
2025-07-02 17:21:44 +08:00
</Container>
2025-05-01 16:36:24 +08:00
</template>
<style scoped>
2025-05-01 22:50:17 +08:00
.founded-room {
display: flex;
flex-direction: column;
align-items: flex-start;
background-color: #54431d33;
border: 1px solid #54431d;
2025-08-12 18:33:39 +08:00
margin: 15px;
2025-05-01 22:50:17 +08:00
border-radius: 10px;
padding: 15px;
}
.founded-room > image {
width: 16vw;
}
.founded-room > view {
display: flex;
justify-content: space-between;
align-items: center;
2025-08-12 18:33:39 +08:00
margin-top: 15px;
2025-05-01 22:50:17 +08:00
background-color: #fff;
border-radius: 30px;
width: 100%;
overflow: hidden;
}
.founded-room > view > input {
width: 70%;
text-align: center;
2025-05-01 16:36:24 +08:00
font-size: 14px;
2025-05-07 23:34:15 +08:00
height: 40px;
2025-05-01 16:36:24 +08:00
}
2025-05-16 15:56:54 +08:00
.founded-room > view > view {
2025-05-01 22:50:17 +08:00
background-color: #fed847;
width: 30%;
2025-05-07 23:34:15 +08:00
line-height: 40px;
2025-05-01 22:50:17 +08:00
border-radius: 30px;
font-size: 14px;
padding: 3px 0;
font-weight: bold;
2025-05-10 16:57:36 +08:00
color: #000;
2025-05-16 15:56:54 +08:00
text-align: center;
2025-05-01 22:50:17 +08:00
}
.create-room {
position: relative;
2025-08-12 18:33:39 +08:00
margin: 15px;
height: 50vw;
2025-05-01 22:50:17 +08:00
}
.create-room > image:first-of-type {
position: absolute;
width: 100%;
}
2025-08-13 16:44:25 +08:00
.create-room > image:nth-of-type(2) {
padding: 15px;
width: 25vw;
position: relative;
}
.create-room > view:nth-child(3) {
margin: 12vw auto;
2025-05-01 22:50:17 +08:00
position: relative;
display: flex;
2025-08-13 16:44:25 +08:00
align-items: center;
justify-content: center;
2025-05-01 22:50:17 +08:00
}
.create-room > view > image:first-child {
2025-08-13 16:44:25 +08:00
width: 19vw;
transform: translateY(-60%);
2025-07-14 14:25:37 +08:00
border-radius: 50%;
2025-08-13 16:44:25 +08:00
position: relative;
2025-05-01 22:50:17 +08:00
}
.create-room > view > image:nth-child(2) {
2025-08-13 16:44:25 +08:00
width: 37vw;
position: relative;
2025-05-01 22:50:17 +08:00
}
.create-room > view > view:nth-child(3) {
2025-08-13 16:44:25 +08:00
position: relative;
width: 19vw;
height: 19vw;
2025-05-01 22:50:17 +08:00
border-radius: 50%;
background-color: #ccc;
display: flex;
justify-content: center;
align-items: center;
2025-08-13 16:44:25 +08:00
transform: translateY(60%);
2025-05-01 22:50:17 +08:00
}
.create-room > view > view:nth-child(3) > image {
2025-06-13 14:05:30 +08:00
width: 20px;
margin-right: 2px;
2025-05-01 22:50:17 +08:00
}
2025-05-16 15:56:54 +08:00
.warnning {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
color: #fff9;
}
2025-08-12 18:33:39 +08:00
.my-data {
width: calc(100% - 30px);
margin: 15px;
margin-top: 0;
border-radius: 10px;
border: 1px solid #54431d;
overflow: hidden;
background-color: #54431d33;
}
.my-data > view {
width: 100%;
display: flex;
color: #fff9;
}
.my-data > view:first-child {
width: calc(100% - 30px);
align-items: flex-end;
padding-bottom: 15px;
border-bottom: 1px solid #48494e;
margin: 15px;
margin-bottom: 0;
}
.my-data > view:first-child > text {
color: #fff;
font-size: 17px;
margin-left: 10px;
2025-08-17 10:33:41 +08:00
width: 120px;
2025-08-12 18:33:39 +08:00
}
.my-data > view:last-child {
margin-bottom: 15px;
}
.my-data > view:last-child > view {
width: 33%;
margin-top: 15px;
display: flex;
flex-direction: column;
align-items: center;
2025-08-14 10:50:17 +08:00
font-size: 12px;
2025-08-12 18:33:39 +08:00
}
.my-data > view:last-child > view > view {
margin-bottom: 5px;
}
.my-data > view:last-child > view > view > text:first-child {
color: #fff;
2025-08-13 17:11:30 +08:00
font-size: 20px;
2025-08-12 18:33:39 +08:00
margin-right: 5px;
2025-08-13 17:11:30 +08:00
transform: translateY(4px);
2025-08-12 18:33:39 +08:00
}
.my-data > view:last-child > view:nth-child(2) {
border-left: 1px solid #48494e;
border-right: 1px solid #48494e;
}
.my-data > view:last-child > view > view {
display: flex;
align-items: flex-end;
height: 20px;
}
.stars > image {
2025-08-13 17:11:30 +08:00
width: 4vw;
2025-08-12 18:33:39 +08:00
margin: 0 1px;
}
2025-05-01 16:36:24 +08:00
</style>