Files
shoot-miniprograms/src/components/BowTarget.vue

321 lines
7.0 KiB
Vue
Raw Normal View History

2025-05-10 16:57:36 +08:00
<script setup>
2025-08-09 12:02:36 +08:00
import { ref, watch, onMounted } from "vue";
2025-05-16 15:56:54 +08:00
import BowPower from "@/components/BowPower.vue";
2025-06-25 00:09:53 +08:00
import StartCountdown from "@/components/StartCountdown.vue";
2025-06-24 13:18:03 +08:00
import { simulShootAPI } from "@/apis";
import useStore from "@/store";
import { storeToRefs } from "pinia";
const store = useStore();
2025-07-16 09:33:33 +08:00
const { user, device } = storeToRefs(store);
2025-06-24 13:18:03 +08:00
2025-05-29 23:45:44 +08:00
const props = defineProps({
2025-07-16 09:33:33 +08:00
currentRound: {
2025-05-10 16:57:36 +08:00
type: Number,
default: 0,
},
2025-07-16 09:33:33 +08:00
totalRound: {
2025-05-10 16:57:36 +08:00
type: Number,
default: 0,
},
avatar: {
type: String,
default: "",
},
power: {
type: Number,
default: 0,
},
2025-05-29 23:45:44 +08:00
scores: {
type: Array,
default: () => [],
},
2025-06-14 22:45:07 +08:00
blueScores: {
type: Array,
default: () => [],
},
2025-06-26 01:27:23 +08:00
mode: {
type: String,
default: "solo", // solo 单排team 双排
},
2025-07-16 09:33:33 +08:00
// start: {
// type: Boolean,
// default: false,
// },
2025-07-15 17:10:56 +08:00
stop: {
type: Boolean,
default: false,
},
2025-05-10 16:57:36 +08:00
});
2025-05-29 23:45:44 +08:00
2025-08-09 12:02:36 +08:00
const showsimul = ref(false);
2025-07-16 09:33:33 +08:00
const latestOne = ref(null);
2025-07-16 12:09:27 +08:00
const prevScores = ref([]);
const prevBlueScores = ref([]);
2025-07-11 00:47:34 +08:00
// const startCount = ref(false);
2025-06-15 20:55:34 +08:00
const timer = ref(null);
2025-06-08 12:52:49 +08:00
2025-07-11 00:47:34 +08:00
// watch(
// () => props.start,
// (newVal) => {
// startCount.value = newVal;
// },
// {
// immediate: true,
// }
// );
2025-06-25 00:09:53 +08:00
2025-06-08 12:52:49 +08:00
watch(
() => props.scores,
2025-07-16 12:09:27 +08:00
(newVal) => {
if (newVal.length - prevScores.value.length === 1) {
latestOne.value = newVal[newVal.length - 1];
if (timer.value) clearTimeout(timer.value);
timer.value = setTimeout(() => {
latestOne.value = null;
}, 1000);
}
prevScores.value = [...newVal];
2025-06-08 12:52:49 +08:00
},
{
deep: true,
}
);
2025-06-26 01:27:23 +08:00
watch(
() => props.blueScores,
(newVal) => {
2025-07-16 12:09:27 +08:00
if (newVal.length - prevBlueScores.value.length === 1) {
latestOne.value = newVal[newVal.length - 1];
if (timer.value) clearTimeout(timer.value);
timer.value = setTimeout(() => {
latestOne.value = null;
}, 1000);
}
prevBlueScores.value = [...newVal];
2025-06-26 01:27:23 +08:00
},
{
deep: true,
}
);
2025-08-21 16:08:42 +08:00
function calcRealX(num) {
2025-07-03 11:05:31 +08:00
const len = 20.4 + num;
2025-08-21 16:08:42 +08:00
return `calc(${(len / 40.8) * 100 - 1.5}%)`;
2025-05-29 23:45:44 +08:00
}
2025-08-21 16:08:42 +08:00
function calcRealY(num) {
2025-07-03 11:05:31 +08:00
const len = num < 0 ? Math.abs(num) + 20.4 : 20.4 - num;
2025-08-21 16:08:42 +08:00
return `calc(${(len / 40.8) * 100 - 1.5}%)`;
2025-05-29 23:45:44 +08:00
}
2025-06-24 13:18:03 +08:00
const simulShoot = async () => {
if (device.value.deviceId) await simulShootAPI(device.value.deviceId);
};
2025-07-05 18:51:27 +08:00
const simulShoot2 = async () => {
if (device.value.deviceId) await simulShootAPI(device.value.deviceId, 1, 1);
};
2025-08-09 12:02:36 +08:00
onMounted(() => {
const accountInfo = uni.getAccountInfoSync();
const envVersion = accountInfo.miniProgram.envVersion;
if (envVersion !== "release") showsimul.value = true;
});
2025-05-10 16:57:36 +08:00
</script>
2025-05-08 22:05:53 +08:00
<template>
<view class="container">
2025-06-25 00:09:53 +08:00
<view class="header" v-if="totalRound > 0 || power">
2025-05-16 15:56:54 +08:00
<text v-if="totalRound > 0" class="round-count">{{
2025-05-31 14:57:25 +08:00
(currentRound > totalRound ? totalRound : currentRound) +
"/" +
totalRound
2025-05-10 16:57:36 +08:00
}}</text>
2025-06-15 20:55:34 +08:00
<BowPower :power="power" />
2025-05-08 22:05:53 +08:00
</view>
2025-05-29 23:45:44 +08:00
<view class="target">
2025-07-15 17:10:56 +08:00
<view v-if="stop" class="stop-sign">中场休息</view>
2025-06-08 20:59:41 +08:00
<view
2025-07-16 09:33:33 +08:00
v-if="latestOne && user.id === latestOne.playerId"
2025-07-10 19:55:30 +08:00
class="e-value fade-in-out"
:style="{
2025-07-16 09:33:33 +08:00
left: calcRealX(latestOne.ring ? latestOne.x : 0, 66),
top: calcRealY(latestOne.ring ? latestOne.y : 0, 150),
2025-07-10 19:55:30 +08:00
}"
2025-06-08 12:52:49 +08:00
>
2025-06-24 13:18:03 +08:00
经验 +1
</view>
2025-06-17 16:02:29 +08:00
<view
2025-07-16 09:33:33 +08:00
v-if="latestOne"
2025-07-10 19:55:30 +08:00
class="round-tip fade-in-out"
:style="{
2025-07-16 09:33:33 +08:00
left: calcRealX(latestOne.ring ? latestOne.x : 0, 100),
top: calcRealY(latestOne.ring ? latestOne.y : 0, 100),
2025-07-10 19:55:30 +08:00
}"
2025-07-16 09:33:33 +08:00
>{{ latestOne.ring || "未上靶"
}}<text v-if="latestOne.ring"></text></view
2025-06-26 01:27:23 +08:00
>
2025-06-17 19:35:21 +08:00
<block v-for="(bow, index) in scores" :key="index">
2025-07-07 14:39:17 +08:00
<view
v-if="bow.ring > 0"
:class="`hit ${
2025-07-16 12:09:27 +08:00
index === scores.length - 1 && latestOne ? 'pump-in' : ''
2025-07-07 14:39:17 +08:00
}`"
:style="{
left: calcRealX(bow.x),
top: calcRealY(bow.y),
backgroundColor:
index === scores.length - 1 &&
!blueScores.length &&
2025-07-16 12:09:27 +08:00
latestOne &&
2025-07-07 14:39:17 +08:00
mode !== 'team'
? 'green'
2025-08-05 15:17:19 +08:00
: '#ff4444',
2025-07-07 14:39:17 +08:00
}"
2025-07-14 13:39:10 +08:00
><text>{{ index + 1 }}</text></view
2025-07-07 14:39:17 +08:00
>
2025-06-17 19:35:21 +08:00
</block>
<block v-for="(bow, index) in blueScores" :key="index">
2025-07-07 14:39:17 +08:00
<view
v-if="bow.ring > 0"
:class="`hit ${
2025-07-16 12:09:27 +08:00
index === blueScores.length - 1 && latestOne ? 'pump-in' : ''
2025-07-07 14:39:17 +08:00
}`"
:style="{
left: calcRealX(bow.x),
top: calcRealY(bow.y),
backgroundColor: 'blue',
}"
>
2025-07-15 17:10:56 +08:00
<text>{{ index + 1 }}</text>
</view>
2025-06-17 19:35:21 +08:00
</block>
2025-05-29 23:45:44 +08:00
<image src="../static/bow-target.png" mode="widthFix" />
</view>
2025-05-16 15:56:54 +08:00
<view v-if="avatar" class="footer">
2025-05-10 16:57:36 +08:00
<image :src="avatar" mode="widthFix" />
</view>
2025-08-09 12:02:36 +08:00
<view class="simul" v-if="showsimul">
2025-07-05 18:51:27 +08:00
<button @click="simulShoot">模拟</button>
<button @click="simulShoot2">射箭</button>
2025-06-24 13:18:03 +08:00
</view>
2025-07-11 22:21:34 +08:00
<!-- <text :style="{ color: '#fff', wordBreak: 'break-all' }">{{
2025-07-08 20:08:25 +08:00
scores.length ? scores[scores.length - 1] : ""
2025-07-11 22:21:34 +08:00
}}</text> -->
2025-07-11 00:47:34 +08:00
<!-- <StartCountdown :start="startCount" /> -->
2025-05-08 22:05:53 +08:00
</view>
</template>
<style scoped>
.container {
width: calc(100% - 30px);
2025-07-23 18:24:26 +08:00
padding: 0px 15px;
2025-06-24 13:18:03 +08:00
position: relative;
2025-05-08 22:05:53 +08:00
}
2025-05-29 23:45:44 +08:00
.target {
position: relative;
2025-07-07 14:39:17 +08:00
margin: 10px;
2025-05-29 23:45:44 +08:00
}
2025-06-08 12:52:49 +08:00
.e-value {
position: absolute;
2025-07-10 19:55:30 +08:00
/* top: 30%;
left: 60%; */
2025-06-08 12:52:49 +08:00
background-color: #0006;
color: #fff;
font-size: 12px;
padding: 4px 7px;
border-radius: 5px;
2025-06-13 16:36:18 +08:00
z-index: 2;
2025-07-10 19:55:30 +08:00
width: 50px;
text-align: center;
2025-06-08 12:52:49 +08:00
}
.round-tip {
position: absolute;
2025-07-10 19:55:30 +08:00
/* top: 38%; */
/* left: 60%; */
2025-06-08 12:52:49 +08:00
color: #fff;
font-size: 30px;
font-weight: bold;
2025-06-13 16:36:18 +08:00
z-index: 2;
2025-07-11 22:21:34 +08:00
width: 100px;
2025-07-10 19:55:30 +08:00
text-align: center;
2025-06-08 12:52:49 +08:00
}
.round-tip > text {
2025-06-24 13:18:03 +08:00
font-size: 24px;
2025-06-08 12:52:49 +08:00
margin-left: 5px;
}
2025-05-29 23:45:44 +08:00
.target > image:last-child {
2025-05-08 22:05:53 +08:00
width: 100%;
}
2025-05-29 23:45:44 +08:00
.hit {
position: absolute;
2025-08-21 16:08:42 +08:00
width: 3%;
height: 3%;
min-width: 3%;
min-height: 3%;
2025-07-07 14:39:17 +08:00
border-radius: 50%;
border: 1px solid #fff;
2025-06-13 16:36:18 +08:00
z-index: 1;
2025-07-07 14:39:17 +08:00
color: #fff;
2025-08-21 16:08:42 +08:00
font-size: 2.2vw;
2025-07-07 14:39:17 +08:00
box-sizing: border-box;
2025-07-31 14:32:14 +08:00
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
2025-08-21 16:08:42 +08:00
display: flex;
justify-content: center;
align-items: center;
2025-05-29 23:45:44 +08:00
}
2025-07-14 13:39:10 +08:00
.hit > text {
transform: scaleX(0.7);
display: block;
2025-07-14 17:57:52 +08:00
font-weight: bold;
2025-07-14 13:39:10 +08:00
}
2025-05-08 22:05:53 +08:00
.header {
2025-05-10 22:16:59 +08:00
width: 100%;
2025-05-08 22:05:53 +08:00
display: flex;
align-items: center;
justify-content: space-between;
2025-07-23 14:31:21 +08:00
margin-bottom: -40px;
2025-05-08 22:05:53 +08:00
}
2025-05-10 16:57:36 +08:00
.header > image:first-child {
2025-05-08 22:05:53 +08:00
width: 40px;
height: 40px;
}
2025-05-16 15:56:54 +08:00
.round-count {
2025-05-10 16:57:36 +08:00
font-size: 20px;
color: #fed847;
top: 75px;
2025-07-10 15:34:00 +08:00
font-weight: bold;
2025-05-10 16:57:36 +08:00
}
.footer {
width: calc(100% - 20px);
padding: 0 10px;
display: flex;
margin-top: -40px;
}
.footer > image {
width: 40px;
2025-06-20 01:47:57 +08:00
min-height: 40px;
2025-06-21 21:40:31 +08:00
max-height: 40px;
2025-05-30 13:58:43 +08:00
border-radius: 50%;
2025-06-28 12:03:33 +08:00
border: 1px solid #fff;
2025-05-10 16:57:36 +08:00
}
2025-06-24 13:18:03 +08:00
.simul {
position: absolute;
2025-08-15 11:23:23 +08:00
bottom: 40px;
2025-06-24 13:18:03 +08:00
right: 20px;
margin-left: 20px;
}
2025-07-05 18:51:27 +08:00
.simul > button {
color: #fff;
}
2025-07-15 17:10:56 +08:00
.stop-sign {
position: absolute;
2025-07-18 15:04:29 +08:00
font-size: 44px;
color: #fff9;
2025-07-15 17:10:56 +08:00
text-align: center;
width: 200px;
height: 60px;
left: calc(50% - 100px);
top: calc(50% - 30px);
2025-07-21 10:40:43 +08:00
z-index: 99;
font-weight: bold;
2025-07-15 17:10:56 +08:00
}
2025-05-08 22:05:53 +08:00
</style>