206 lines
4.9 KiB
Vue
206 lines
4.9 KiB
Vue
<script setup>
|
||
import { ref, onMounted, onBeforeUnmount } from "vue";
|
||
import Guide from "@/components/Guide.vue";
|
||
import BowPower from "@/components/BowPower.vue";
|
||
import Avatar from "@/components/Avatar.vue";
|
||
import audioManager from "@/audioManager";
|
||
import { simulShootAPI } from "@/apis";
|
||
import { checkConnection } from "@/util";
|
||
import { MESSAGETYPES } from "@/constants";
|
||
import useStore from "@/store";
|
||
import { storeToRefs } from "pinia";
|
||
const store = useStore();
|
||
const { user, device } = storeToRefs(store);
|
||
const props = defineProps({
|
||
guide: {
|
||
type: Boolean,
|
||
default: true,
|
||
},
|
||
isBattle: {
|
||
type: Boolean,
|
||
default: false,
|
||
},
|
||
});
|
||
const arrow = ref({});
|
||
const power = ref(0);
|
||
const distance = ref(0);
|
||
const debugInfo = ref("");
|
||
const showsimul = ref(false);
|
||
const count = ref(15);
|
||
const timer = ref(null);
|
||
|
||
const updateTimer = (value) => {
|
||
count.value = Math.round(value);
|
||
};
|
||
onMounted(() => {
|
||
audioManager.play("请射箭测试距离");
|
||
timer.value = setInterval(() => {
|
||
if (count.value > 0) count.value -= 1;
|
||
else clearInterval(timer.value);
|
||
}, 1000);
|
||
uni.$on("update-timer", updateTimer);
|
||
});
|
||
onBeforeUnmount(() => {
|
||
if (timer.value) clearInterval(timer.value);
|
||
uni.$off("update-timer", updateTimer);
|
||
});
|
||
|
||
async function onReceiveMessage(messages = []) {
|
||
messages.forEach((msg) => {
|
||
if (msg.constructor === MESSAGETYPES.ShootSyncMeArrowID) {
|
||
arrow.value = msg.target;
|
||
power.value = msg.target.battery;
|
||
distance.value = Number((msg.target.dst / 100).toFixed(2));
|
||
debugInfo.value = msg.target;
|
||
audioManager.play("距离合格");
|
||
} else if (msg.constructor === MESSAGETYPES.InvalidShot) {
|
||
distance.value = Number((msg.target.dst / 100).toFixed(2));
|
||
audioManager.play("距离不足");
|
||
}
|
||
});
|
||
}
|
||
|
||
const simulShoot = async () => {
|
||
if (device.value.deviceId) await simulShootAPI(device.value.deviceId);
|
||
};
|
||
|
||
onMounted(() => {
|
||
checkConnection();
|
||
uni.$on("socket-inbox", onReceiveMessage);
|
||
const accountInfo = uni.getAccountInfoSync();
|
||
const envVersion = accountInfo.miniProgram.envVersion;
|
||
if (envVersion !== "release") showsimul.value = true;
|
||
});
|
||
|
||
onBeforeUnmount(() => {
|
||
uni.$off("socket-inbox", onReceiveMessage);
|
||
});
|
||
</script>
|
||
|
||
<template>
|
||
<view class="container">
|
||
<Guide v-show="guide">
|
||
<view
|
||
:style="{
|
||
display: 'flex',
|
||
justifyContent: 'space-between',
|
||
alignItems: 'center',
|
||
paddingRight: '10px',
|
||
}"
|
||
>
|
||
<view :style="{ display: 'flex', flexDirection: 'column' }">
|
||
<text :style="{ color: '#fed847' }">请确保站距达到5米</text>
|
||
<text>低于5米的射箭无效</text>
|
||
</view>
|
||
</view>
|
||
</Guide>
|
||
<view class="test-area">
|
||
<image
|
||
class="text-bg"
|
||
src="https://static.shelingxingqiu.com/attachment/2025-07-05/db3skuq1n9rj4fmld4.png"
|
||
mode="widthFix"
|
||
/>
|
||
<button
|
||
class="simul"
|
||
@click="simulShoot"
|
||
hover-class="none"
|
||
v-if="showsimul"
|
||
>
|
||
模拟射箭
|
||
</button>
|
||
<view class="warnning-text">
|
||
<block v-if="distance > 0">
|
||
<text>当前距离{{ distance }}米</text>
|
||
<text v-if="distance >= 5">已达到距离要求</text>
|
||
<text v-else>请调整站位</text>
|
||
</block>
|
||
<block v-else>
|
||
<text>请射箭,测试站距</text>
|
||
</block>
|
||
</view>
|
||
<view class="user-row">
|
||
<Avatar :src="user.avatar" :size="35" />
|
||
<BowPower :power="power" />
|
||
</view>
|
||
</view>
|
||
<view v-if="isBattle" class="ready-timer">
|
||
<image src="../static/test-tip.png" mode="widthFix" />
|
||
<view>
|
||
<text>具体正式比赛还有</text>
|
||
<text>{{ count }}</text>
|
||
<text>秒</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<style scoped>
|
||
.container {
|
||
width: 100vw;
|
||
max-height: 70vh;
|
||
}
|
||
.ready-timer {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
transform: translateY(-10vw);
|
||
}
|
||
.ready-timer > image:first-child {
|
||
width: 40%;
|
||
}
|
||
.ready-timer > view {
|
||
width: 80%;
|
||
height: 45px;
|
||
background-color: #545454;
|
||
border-radius: 30px;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
transform: translateY(-8vw);
|
||
color: #bebebe;
|
||
font-size: 15px;
|
||
}
|
||
.ready-timer > view > text:nth-child(2) {
|
||
color: #fed847;
|
||
font-size: 20px;
|
||
width: 22px;
|
||
text-align: center;
|
||
}
|
||
.test-area {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
width: 100%;
|
||
height: 112vw;
|
||
position: relative;
|
||
}
|
||
.test-area > view:last-child {
|
||
padding: 15px;
|
||
width: calc(100% - 30px);
|
||
}
|
||
.text-bg {
|
||
width: 100%;
|
||
position: absolute;
|
||
top: -14.4%;
|
||
left: 0;
|
||
}
|
||
.warnning-text {
|
||
color: #fed847;
|
||
font-size: 27px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: center;
|
||
height: 40%;
|
||
}
|
||
.warnning-text > text {
|
||
width: 70vw;
|
||
text-align: center;
|
||
}
|
||
.simul {
|
||
position: absolute;
|
||
color: #fff;
|
||
right: 10px;
|
||
}
|
||
</style>
|