更换测距页面

This commit is contained in:
kron
2025-07-05 14:52:41 +08:00
parent 054bf2ef21
commit 1c70471959
10 changed files with 224 additions and 179 deletions

View File

@@ -25,10 +25,6 @@ const props = defineProps({
type: Number, type: Number,
default: 0, default: 0,
}, },
tips: {
type: String,
default: "",
},
scores: { scores: {
type: Array, type: Array,
default: () => [], default: () => [],
@@ -183,7 +179,6 @@ const simulShoot = async () => {
<view v-if="avatar" class="footer"> <view v-if="avatar" class="footer">
<image :src="avatar" mode="widthFix" /> <image :src="avatar" mode="widthFix" />
</view> </view>
<text v-if="tips">{{ tips }}</text>
<view class="simul" @click="simulShoot" :style="{ color: '#fff' }"> <view class="simul" @click="simulShoot" :style="{ color: '#fff' }">
模拟射箭 模拟射箭
</view> </view>
@@ -263,13 +258,6 @@ const simulShoot = async () => {
border-radius: 50%; border-radius: 50%;
border: 1px solid #fff; border: 1px solid #fff;
} }
.container > text {
width: 100%;
color: #fed847;
text-align: center;
line-height: 40px;
display: block;
}
.simul { .simul {
position: absolute; position: absolute;
bottom: 20px; bottom: 20px;

View File

@@ -56,11 +56,10 @@ watch(
(newVal, oldVal) => { (newVal, oldVal) => {
if (newVal === false) { if (newVal === false) {
if (timer.value) clearInterval(timer.value); if (timer.value) clearInterval(timer.value);
remain.value = props.total;
} }
if (!oldVal && newVal === true) { if (!oldVal && newVal === true) {
setTimeout(() => {
remain.value = props.total; remain.value = props.total;
setTimeout(() => {
timer.value = setInterval(() => { timer.value = setInterval(() => {
if (remain.value > 0) { if (remain.value > 0) {
remain.value--; remain.value--;

View File

@@ -38,7 +38,7 @@ onUnmounted(() => {
</script> </script>
<template> <template>
<view class="container" :style="{ top: `calc(50% - ${isIos ? 59 : 64}px)` }"> <view class="container" :style="{ top: `calc(50% - ${isIos ? 56 : 64}px)` }">
<view class="number pump-in" v-if="count === 3">3</view> <view class="number pump-in" v-if="count === 3">3</view>
<view class="number pump-in" v-if="count === 2">2</view> <view class="number pump-in" v-if="count === 2">2</view>
<view class="number pump-in" v-if="count === 1">1</view> <view class="number pump-in" v-if="count === 1">1</view>

View File

@@ -0,0 +1,124 @@
<script setup>
import { ref, onMounted, onUnmounted } from "vue";
import Guide from "@/components/Guide.vue";
import BowPower from "@/components/BowPower.vue";
import Avatar from "@/components/Avatar.vue";
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,
},
});
const arrow = ref({});
const power = ref(0);
const distance = ref(0);
const debugInfo = ref("");
async function onReceiveMessage(messages = []) {
messages.forEach((msg) => {
if (msg.constructor === MESSAGETYPES.ShootSyncMeArrowID) {
arrow.value = msg.target;
power.value = msg.target.battery;
distance.value = msg.target.dst / 100;
debugInfo.value = msg.target;
}
});
}
const simulShoot = async () => {
if (device.value.deviceId) await simulShootAPI(device.value.deviceId);
};
onMounted(() => {
checkConnection();
uni.$on("socket-inbox", onReceiveMessage);
});
onUnmounted(() => {
uni.$off("socket-inbox", onReceiveMessage);
});
</script>
<template>
<view class="container">
<Guide v-if="guide">
<view
:style="{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
paddingRight: '10px',
}"
>
<view :style="{ display: 'flex', flexDirection: 'column' }">
<text :style="{ color: '#fed847' }">请预先射几箭测试</text>
<text>请确保射击距离只有5米</text>
</view>
<BowPower :power="power" />
</view>
</Guide>
<image
class="text-bg"
src="https://api.shelingxingqiu.com/attachment/2025-07-05/db3skuq1n9rj4fmld4.png"
mode="widthFix"
/>
<view class="warnning-text" v-if="distance > 0">
<text>当前距离{{ distance }}</text>
<text v-if="distance >= 5">已达到距离要求</text>
<text v-else>请调整站位</text>
</view>
<view class="debug-text">{{ debugInfo }}</view>
<view>
<Avatar :src="user.avatar" :size="35" />
<view class="simul" @click="simulShoot" :style="{ color: '#fff' }">
模拟射箭
</view>
</view>
</view>
</template>
<style scoped>
.container {
width: 100vw;
display: flex;
flex-direction: column;
}
.text-bg {
width: 100%;
}
.warnning-text {
position: fixed;
color: #fed847;
font-size: 30px;
display: flex;
flex-direction: column;
align-items: center;
left: calc(50% - 27vw);
top: 30%;
}
.warnning-text > text {
width: 54vw;
text-align: center;
}
.container > view:last-child {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px;
margin-top: -27vw;
}
.debug-text {
position: fixed;
left: calc(50% - 45vw);
top: 66%;
color: #fff;
font-size: 14px;
}
</style>

View File

@@ -15,8 +15,8 @@ import PlayersRow from "@/components/PlayersRow.vue";
import SModal from "@/components/SModal.vue"; import SModal from "@/components/SModal.vue";
import ScreenHint from "@/components/ScreenHint.vue"; import ScreenHint from "@/components/ScreenHint.vue";
import RoundEndTip from "@/components/RoundEndTip.vue"; import RoundEndTip from "@/components/RoundEndTip.vue";
import TestDistance from "@/components/TestDistance.vue";
import { getRoomAPI, destroyRoomAPI, exitRoomAPI, startRoomAPI } from "@/apis"; import { getRoomAPI, destroyRoomAPI, exitRoomAPI, startRoomAPI } from "@/apis";
import { checkConnection } from "@/util";
import { MESSAGETYPES, roundsName, getMessageTypeName } from "@/constants"; import { MESSAGETYPES, roundsName, getMessageTypeName } from "@/constants";
import useStore from "@/store"; import useStore from "@/store";
import { storeToRefs } from "pinia"; import { storeToRefs } from "pinia";
@@ -127,10 +127,6 @@ async function onReceiveMessage(messages = []) {
) { ) {
console.log("收到消息:", getMessageTypeName(msg.constructor), msg); console.log("收到消息:", getMessageTypeName(msg.constructor), msg);
} }
if (!start.value && msg.constructor === MESSAGETYPES.ShootSyncMeArrowID) {
scores.value.push(msg.target);
power.value = msg.target.battery;
}
if (msg.constructor === MESSAGETYPES.WaitForAllReady) { if (msg.constructor === MESSAGETYPES.WaitForAllReady) {
// 这里会掉多次; // 这里会掉多次;
timerSeq.value += 1; timerSeq.value += 1;
@@ -288,7 +284,6 @@ const exitRoom = async () => {
}; };
onMounted(() => { onMounted(() => {
checkConnection();
uni.$on("socket-inbox", onReceiveMessage); uni.$on("socket-inbox", onReceiveMessage);
}); });
@@ -358,25 +353,7 @@ onUnmounted(() => {
:redTeam="redTeam" :redTeam="redTeam"
:players="players" :players="players"
/> />
<Guide noBg> <TestDistance :guide="false" />
<view :style="{ display: 'flex', justifyContent: 'space-between' }">
<view :style="{ display: 'flex', flexDirection: 'column' }">
<text :style="{ color: '#fed847' }">请预先射几箭测试</text>
<text>请确保射击距离只有5米</text>
</view>
<BowPower :power="power" />
</view>
</Guide>
<BowTarget
:scores="scores"
:tips="
!start && scores.length > 0
? `本次射程${scores[scores.length - 1].dst / 100}米,${
scores[scores.length - 1].dst / 100 >= 5 ? '已' : '未'
}达到距离要求`
: ''
"
/>
</view> </view>
<view v-if="step === 3"> <view v-if="step === 3">
<ShootProgress <ShootProgress

View File

@@ -10,8 +10,9 @@ import ScorePanel from "@/components/ScorePanel.vue";
import Container from "@/components/Container.vue"; import Container from "@/components/Container.vue";
import Avatar from "@/components/Avatar.vue"; import Avatar from "@/components/Avatar.vue";
import BowPower from "@/components/BowPower.vue"; import BowPower from "@/components/BowPower.vue";
import TestDistance from "@/components/TestDistance.vue";
import { createPractiseAPI } from "@/apis"; import { createPractiseAPI } from "@/apis";
import { generateCanvasImage, checkConnection } from "@/util"; import { generateCanvasImage } from "@/util";
import { MESSAGETYPES } from "@/constants"; import { MESSAGETYPES } from "@/constants";
import useStore from "@/store"; import useStore from "@/store";
import { storeToRefs } from "pinia"; import { storeToRefs } from "pinia";
@@ -33,7 +34,7 @@ const title = ref("新手试炼场");
const start = ref(false); const start = ref(false);
const practiseResult = ref({}); const practiseResult = ref({});
const power = ref(0); const power = ref(0);
const btnDisabled = ref(false); // const btnDisabled = ref(false);
const practiseId = ref(""); const practiseId = ref("");
const createPractise = async (arrows) => { const createPractise = async (arrows) => {
@@ -47,9 +48,9 @@ async function onReceiveMessage(messages = []) {
scores.value.push(msg.target); scores.value.push(msg.target);
power.value = msg.target.battery; power.value = msg.target.battery;
// if (step.value === 2 && msg.target.dst / 100 > 5) { // if (step.value === 2 && msg.target.dst / 100 > 5) {
if (step.value === 2 && msg.target.dst > 5) { // if (step.value === 2 && msg.target.dst > 5) {
btnDisabled.value = false; // btnDisabled.value = false;
} // }
} }
if (msg.constructor === MESSAGETYPES.ShootSyncMePracticeID) { if (msg.constructor === MESSAGETYPES.ShootSyncMePracticeID) {
if (practiseId.value && practiseId.value === msg.practice.id) { if (practiseId.value && practiseId.value === msg.practice.id) {
@@ -72,7 +73,6 @@ async function onReceiveMessage(messages = []) {
} }
onMounted(() => { onMounted(() => {
checkConnection();
uni.$on("socket-inbox", onReceiveMessage); uni.$on("socket-inbox", onReceiveMessage);
}); });
@@ -85,7 +85,7 @@ const nextStep = async () => {
step.value = 1; step.value = 1;
title.value = "凹造型"; title.value = "凹造型";
} else if (step.value === 1) { } else if (step.value === 1) {
btnDisabled.value = true; // btnDisabled.value = true;
step.value = 2; step.value = 2;
title.value = "感知距离"; title.value = "感知距离";
} else if (step.value === 2) { } else if (step.value === 2) {
@@ -201,29 +201,20 @@ const onClose = () => {
:total="100" :total="100"
:start="start" :start="start"
/> />
<TestDistance v-if="step === 2" :guide="false" />
<view <view
class="infos" class="infos"
v-if="step === 2 || step === 4" v-if="step === 4"
:style="{ marginBottom: step === 2 ? '40px' : '0' }" :style="{ marginBottom: step === 2 ? '40px' : '0' }"
> >
<text v-if="step === 2">大人请射箭</text> <Avatar :src="user.avatar" :size="35" />
<Avatar v-if="step === 4" :src="user.avatar" :size="35" />
<BowPower :power="power" /> <BowPower :power="power" />
</view> </view>
<BowTarget <BowTarget
v-if="step === 4"
:start="start" :start="start"
:avatar="step === 2 ? user.avatar : ''"
:debug="step === 2"
v-if="step === 2 || step === 4"
:currentRound="step === 4 ? scores.length : 0" :currentRound="step === 4 ? scores.length : 0"
:totalRound="step === 4 ? total : 0" :totalRound="step === 4 ? total : 0"
:tips="
step === 2 && scores.length > 0
? `本次射程${scores[scores.length - 1].dst / 100}米,${
scores[scores.length - 1].dst / 100 >= 5 ? '已' : '未'
}达到距离要求`
: ''
"
:scores="scores" :scores="scores"
/> />
<ScorePanel <ScorePanel
@@ -245,7 +236,7 @@ const onClose = () => {
<canvas class="share-canvas" canvas-id="shareCanvas"></canvas> <canvas class="share-canvas" canvas-id="shareCanvas"></canvas>
</view> </view>
<view :style="{ marginBottom: '20px' }"> <view :style="{ marginBottom: '20px' }">
<SButton v-if="step !== 4" :onClick="nextStep" :disabled="btnDisabled">{{ <SButton v-if="step !== 4" :onClick="nextStep">{{
stepButtonTexts[step] stepButtonTexts[step]
}}</SButton> }}</SButton>
</view> </view>

View File

@@ -13,6 +13,7 @@ import Avatar from "@/components/Avatar.vue";
import ScreenHint from "@/components/ScreenHint.vue"; import ScreenHint from "@/components/ScreenHint.vue";
import Matching from "@/components/Matching.vue"; import Matching from "@/components/Matching.vue";
import SModal from "@/components/SModal.vue"; import SModal from "@/components/SModal.vue";
import TestDistance from "@/components/TestDistance.vue";
import { matchGameAPI, readyGameAPI } from "@/apis"; import { matchGameAPI, readyGameAPI } from "@/apis";
import { MESSAGETYPES, getMessageTypeName } from "@/constants"; import { MESSAGETYPES, getMessageTypeName } from "@/constants";
import useStore from "@/store"; import useStore from "@/store";
@@ -79,10 +80,6 @@ async function onReceiveMessage(messages = []) {
}); });
}; };
} }
if (!start.value && msg.constructor === MESSAGETYPES.ShootSyncMeArrowID) {
scores.value.push(msg.target);
power.value = msg.target.battery;
}
if (msg.id !== battleId.value) return; if (msg.id !== battleId.value) return;
if (msg.constructor === MESSAGETYPES.MeleeAllReady) { if (msg.constructor === MESSAGETYPES.MeleeAllReady) {
start.value = true; start.value = true;
@@ -140,16 +137,8 @@ onUnmounted(() => {
> >
<view class="container"> <view class="container">
<block v-if="battleId"> <block v-if="battleId">
<BattleHeader v-if="players.length" :players="players" /> <BattleHeader :players="players" />
<Guide noBg v-if="!start && battleId"> <TestDistance v-if="!start" :guide="false" />
<view :style="{ display: 'flex', justifyContent: 'space-between' }">
<view :style="{ display: 'flex', flexDirection: 'column' }">
<text :style="{ color: '#fed847' }">请预先射几箭测试</text>
<text>请确保射击距离只有5米</text>
</view>
<BowPower :power="45" />
</view>
</Guide>
<ShootProgress <ShootProgress
v-if="start" v-if="start"
:seq="seq" :seq="seq"
@@ -161,7 +150,7 @@ onUnmounted(() => {
<BowPower :power="power" /> <BowPower :power="power" />
</view> </view>
<BowTarget <BowTarget
v-if="battleId" v-if="start"
:showE="start" :showE="start"
:currentRound="scores.length" :currentRound="scores.length"
:totalRound="start ? 12 : 0" :totalRound="start ? 12 : 0"

View File

@@ -8,8 +8,9 @@ import ScoreResult from "@/components/ScoreResult.vue";
import SButton from "@/components/SButton.vue"; import SButton from "@/components/SButton.vue";
import Avatar from "@/components/Avatar.vue"; import Avatar from "@/components/Avatar.vue";
import BowPower from "@/components/BowPower.vue"; import BowPower from "@/components/BowPower.vue";
import TestDistance from "@/components/TestDistance.vue";
import { createPractiseAPI, getHomeData } from "@/apis"; import { createPractiseAPI, getHomeData } from "@/apis";
import { generateCanvasImage, checkConnection } from "@/util"; import { generateCanvasImage } from "@/util";
import { MESSAGETYPES, roundsName } from "@/constants"; import { MESSAGETYPES, roundsName } from "@/constants";
import useStore from "@/store"; import useStore from "@/store";
import { storeToRefs } from "pinia"; import { storeToRefs } from "pinia";
@@ -70,7 +71,6 @@ async function onComplete() {
} }
onMounted(() => { onMounted(() => {
checkConnection();
uni.$on("socket-inbox", onReceiveMessage); uni.$on("socket-inbox", onReceiveMessage);
}); });
@@ -82,11 +82,15 @@ onUnmounted(() => {
<template> <template>
<Container :bgType="1" title="个人单组练习"> <Container :bgType="1" title="个人单组练习">
<view> <view>
<TestDistance v-if="!start && !practiseResult.arrows" />
<block v-if="start || practiseResult.arrows">
<ShootProgress <ShootProgress
:tips="`${ :tips="`${
!start || scores.length === 12 !start || scores.length === 12
? '' ? ''
: `请开始射箭第${roundsName[Math.ceil((scores.length + 1) / 3)]}轮` : `请开始射箭第${
roundsName[Math.ceil((scores.length + 1) / 3)]
}轮`
}`" }`"
:start="start" :start="start"
:total="120" :total="120"
@@ -100,15 +104,8 @@ onUnmounted(() => {
:totalRound="start ? total / 4 : 0" :totalRound="start ? total / 4 : 0"
:currentRound="currentRound" :currentRound="currentRound"
:scores="scores" :scores="scores"
:tips="
!start && scores.length > 0
? `本次射程${scores[scores.length - 1].dst / 100}米,${
scores[scores.length - 1].dst / 100 >= 5 ? '已' : '未'
}达到距离要求`
: ''
"
/> />
<ScorePanel2 v-if="start" :scores="scores.map((s) => s.ring)" /> <ScorePanel2 :scores="scores.map((s) => s.ring)" />
<ScoreResult <ScoreResult
v-if="practiseResult.arrows" v-if="practiseResult.arrows"
:rowCount="6" :rowCount="6"
@@ -120,6 +117,7 @@ onUnmounted(() => {
}finish-tip.png`" }finish-tip.png`"
/> />
<canvas class="share-canvas" canvas-id="shareCanvas"></canvas> <canvas class="share-canvas" canvas-id="shareCanvas"></canvas>
</block>
</view> </view>
<view :style="{ marginBottom: '20px' }"> <view :style="{ marginBottom: '20px' }">
<SButton v-if="!start" :onClick="onReady">准备好了直接开始</SButton> <SButton v-if="!start" :onClick="onReady">准备好了直接开始</SButton>

View File

@@ -8,8 +8,9 @@ import ScoreResult from "@/components/ScoreResult.vue";
import SButton from "@/components/SButton.vue"; import SButton from "@/components/SButton.vue";
import Avatar from "@/components/Avatar.vue"; import Avatar from "@/components/Avatar.vue";
import BowPower from "@/components/BowPower.vue"; import BowPower from "@/components/BowPower.vue";
import TestDistance from "@/components/TestDistance.vue";
import { createPractiseAPI, getHomeData } from "@/apis"; import { createPractiseAPI, getHomeData } from "@/apis";
import { generateCanvasImage, checkConnection } from "@/util"; import { generateCanvasImage } from "@/util";
import { MESSAGETYPES } from "@/constants"; import { MESSAGETYPES } from "@/constants";
import useStore from "@/store"; import useStore from "@/store";
import { storeToRefs } from "pinia"; import { storeToRefs } from "pinia";
@@ -74,7 +75,6 @@ async function onComplete() {
} }
onMounted(() => { onMounted(() => {
checkConnection();
uni.$on("socket-inbox", onReceiveMessage); uni.$on("socket-inbox", onReceiveMessage);
}); });
@@ -86,6 +86,8 @@ onUnmounted(() => {
<template> <template>
<Container :bgType="1" title="个人单组练习"> <Container :bgType="1" title="个人单组练习">
<view> <view>
<TestDistance v-if="!start && !practiseResult.arrows" />
<block v-if="start || practiseResult.arrows">
<ShootProgress <ShootProgress
:start="start" :start="start"
:tips="`请连续射箭${total}支`" :tips="`请连续射箭${total}支`"
@@ -100,13 +102,6 @@ onUnmounted(() => {
:totalRound="start ? total : 0" :totalRound="start ? total : 0"
:currentRound="currentRound" :currentRound="currentRound"
:scores="scores" :scores="scores"
:tips="
!start && scores.length > 0
? `本次射程${scores[scores.length - 1].dst / 100}米,${
scores[scores.length - 1].dst / 100 >= 5 ? '已' : '未'
}达到距离要求`
: ''
"
/> />
<ScorePanel <ScorePanel
v-if="start" v-if="start"
@@ -127,6 +122,7 @@ onUnmounted(() => {
}finish-tip.png`" }finish-tip.png`"
/> />
<canvas class="share-canvas" canvas-id="shareCanvas"></canvas> <canvas class="share-canvas" canvas-id="shareCanvas"></canvas>
</block>
</view> </view>
<view :style="{ marginBottom: '20px' }"> <view :style="{ marginBottom: '20px' }">
<SButton v-if="!start" :onClick="onReady">准备好了直接开始</SButton> <SButton v-if="!start" :onClick="onReady">准备好了直接开始</SButton>

View File

@@ -14,6 +14,7 @@ import SButton from "@/components/SButton.vue";
import Matching from "@/components/Matching.vue"; import Matching from "@/components/Matching.vue";
import SModal from "@/components/SModal.vue"; import SModal from "@/components/SModal.vue";
import RoundEndTip from "@/components/RoundEndTip.vue"; import RoundEndTip from "@/components/RoundEndTip.vue";
import TestDistance from "@/components/TestDistance.vue";
import { matchGameAPI, readyGameAPI } from "@/apis"; import { matchGameAPI, readyGameAPI } from "@/apis";
import { MESSAGETYPES, roundsName, getMessageTypeName } from "@/constants"; import { MESSAGETYPES, roundsName, getMessageTypeName } from "@/constants";
import useStore from "@/store"; import useStore from "@/store";
@@ -71,10 +72,6 @@ async function onReceiveMessage(messages = []) {
) { ) {
console.log("收到消息:", getMessageTypeName(msg.constructor), msg); console.log("收到消息:", getMessageTypeName(msg.constructor), msg);
} }
if (!start.value && msg.constructor === MESSAGETYPES.ShootSyncMeArrowID) {
scores.value.push(msg.target);
power.value = msg.target.battery;
}
if (msg.constructor === MESSAGETYPES.WaitForAllReady) { if (msg.constructor === MESSAGETYPES.WaitForAllReady) {
// 这里会掉多次; // 这里会掉多次;
onComplete.value = () => { onComplete.value = () => {
@@ -167,15 +164,7 @@ onUnmounted(() => {
:redTeam="redTeam" :redTeam="redTeam"
:blueTeam="blueTeam" :blueTeam="blueTeam"
/> />
<Guide noBg v-if="!start"> <TestDistance v-if="!start" :guide="false" />
<view :style="{ display: 'flex', justifyContent: 'space-between' }">
<view :style="{ display: 'flex', flexDirection: 'column' }">
<text :style="{ color: '#fed847' }">请预先射几箭测试</text>
<text>请确保射击距离只有5米</text>
</view>
<BowPower :power="45" />
</view>
</Guide>
<ShootProgress v-if="start" :tips="tips" :seq="seq" :total="15" /> <ShootProgress v-if="start" :tips="tips" :seq="seq" :total="15" />
<PlayersRow <PlayersRow
v-if="start" v-if="start"
@@ -184,6 +173,7 @@ onUnmounted(() => {
:redTeam="redTeam" :redTeam="redTeam"
/> />
<BowTarget <BowTarget
v-if="start"
mode="team" mode="team"
:showE="start && user.id === currentShooterId" :showE="start && user.id === currentShooterId"
:power="start ? power : 0" :power="start ? power : 0"
@@ -191,13 +181,6 @@ onUnmounted(() => {
:totalRound="totalRounds" :totalRound="totalRounds"
:scores="scores" :scores="scores"
:blueScores="blueScores" :blueScores="blueScores"
:tips="
!start && scores.length > 0
? `本次射程${scores[scores.length - 1].dst / 100}米,${
scores[scores.length - 1].dst / 100 >= 5 ? '已' : '未'
}达到距离要求`
: ''
"
/> />
<BattleFooter <BattleFooter
v-if="start" v-if="start"