添加X环显示,比赛过程完善

This commit is contained in:
kron
2026-02-09 17:27:44 +08:00
parent b355f4e009
commit a3fea0bb1f
18 changed files with 82 additions and 104 deletions

View File

@@ -56,7 +56,7 @@ const props = defineProps({
:completeEffect="false" :completeEffect="false"
:rowCount="arrows.length === 12 ? 6 : 9" :rowCount="arrows.length === 12 ? 6 : 9"
:total="total" :total="total"
:scores="arrows.map((a) => a.ring)" :arrows="arrows"
:margin="arrows.length === 12 ? 4 : 1" :margin="arrows.length === 12 ? 4 : 1"
:fontSize="arrows.length === 12 ? 25 : 22" :fontSize="arrows.length === 12 ? 25 : 22"
/> />

View File

@@ -92,8 +92,10 @@ const simulShoot = async () => {
if (device.value.deviceId) await simulShootAPI(device.value.deviceId); if (device.value.deviceId) await simulShootAPI(device.value.deviceId);
}; };
const simulShoot2 = async () => { const simulShoot2 = async () => {
if (device.value.deviceId) if (device.value.deviceId) {
await simulShootAPI(device.value.deviceId, 0.01, 0.01); const r1 = Math.random() > 0.5 ? 0.01 : 0.02;
await simulShootAPI(device.value.deviceId, r1, r1);
}
}; };
const env = computed(() => { const env = computed(() => {

View File

@@ -69,7 +69,7 @@ async function onReceiveMessage(message) {
? `${shootData.ringX ? "X" : shootData.ring}` ? `${shootData.ringX ? "X" : shootData.ring}`
: "未上靶" : "未上靶"
); );
if (!shootData.ring) if (shootData.angle !== null)
key.push(`${getDirectionText(shootData.angle)}调整`); key.push(`${getDirectionText(shootData.angle)}调整`);
audioManager.play(key, false); audioManager.play(key, false);
} }

View File

@@ -9,7 +9,7 @@ const props = defineProps({
type: Number, type: Number,
default: 0, default: 0,
}, },
scores: { arrows: {
type: Array, type: Array,
default: () => [], default: () => [],
}, },
@@ -51,7 +51,7 @@ onBeforeUnmount(() => {
<template> <template>
<view class="container"> <view class="container">
<image <image
v-if="total > 0 && scores.length === total && completeEffect" v-if="total > 0 && arrows.length === total && completeEffect"
:src="bgImages[bgIndex]" :src="bgImages[bgIndex]"
class="complete-light" class="complete-light"
:style="{ :style="{
@@ -79,8 +79,10 @@ onBeforeUnmount(() => {
> >
<image src="../static/score-bg.png" mode="widthFix" /> <image src="../static/score-bg.png" mode="widthFix" />
<text <text
:style="{ fontWeight: scores[index] !== undefined ? 'bold' : 'normal' }" :style="{ fontWeight: arrows[index] !== undefined ? 'bold' : 'normal' }"
>{{ scores[index] !== undefined ? scores[index] : "-" }}</text >{{
!arrows[index] ? "-" : arrows[index].ringX ? "X" : arrows[index].ring
}}</text
> >
</view> </view>
</view> </view>

View File

@@ -1,6 +1,6 @@
<script setup> <script setup>
const props = defineProps({ const props = defineProps({
scores: { arrows: {
type: Array, type: Array,
default: () => [], default: () => [],
}, },
@@ -10,37 +10,34 @@ const getSum = (a, b, c) => {
return sum > 0 ? sum + "环" : "-"; return sum > 0 ? sum + "环" : "-";
}; };
const roundsName = ["第一轮", "第二轮", "第三轮", "第四轮"]; const roundsName = ["第一轮", "第二轮", "第三轮", "第四轮"];
const getShowText = (arrow = {}) => {
return arrow.ring ? (arrow.ringX ? "X" : arrow.ring + "环") : "-";
};
</script> </script>
<template> <template>
<view class="container"> <view class="container">
<view> <view>
<text :style="{ transform: 'translateX(-10%)' }">总成绩</text> <text :style="{ transform: 'translateX(-10%)' }">总成绩</text>
<text>{{ scores.reduce((last, next) => last + next, 0) }}</text> <text>{{ arrows.reduce((last, next) => last + next.ring, 0) }}</text>
</view> </view>
<view <view
v-for="(_, index) in new Array( v-for="(_, index) in new Array(
Math.min( Math.min(
Math.ceil(scores.length / 3) + (scores.length % 3 === 0 ? 1 : 0), Math.ceil(arrows.length / 3) + (arrows.length % 3 === 0 ? 1 : 0),
4 4
) )
).fill(1)" ).fill(1)"
:key="index" :key="index"
> >
<text>{{ roundsName[index] }}</text> <text>{{ roundsName[index] }}</text>
<text>{{ <text>{{ getShowText(arrows[index * 3 + 0]) }}</text>
scores[index * 3 + 0] ? scores[index * 3 + 0] + "环" : "-" <text>{{ getShowText(arrows[index * 3 + 1]) }}</text>
}}</text> <text>{{ getShowText(arrows[index * 3 + 2]) }}</text>
<text>{{
scores[index * 3 + 1] ? scores[index * 3 + 1] + "环" : "-"
}}</text>
<text>{{
scores[index * 3 + 2] ? scores[index * 3 + 2] + "环" : "-"
}}</text>
<text :style="{ width: '40%', transform: 'translateX(20%)' }">{{ <text :style="{ width: '40%', transform: 'translateX(20%)' }">{{
getSum( getSum(
scores[index * 3 + 0], arrows[index * 3 + 0],
scores[index * 3 + 1], arrows[index * 3 + 1],
scores[index * 3 + 2] arrows[index * 3 + 2]
) )
}}</text> }}</text>
</view> </view>

View File

@@ -63,8 +63,8 @@ const validArrows = computed(() => {
}); });
const getRing = (arrow) => { const getRing = (arrow) => {
if (arrow && arrow.x !== -30 && arrow.y !== -30) return arrow.ring; if (arrow.ringX) return "X";
return "-"; return arrow.ring ? arrow.ring + "环" : "-";
}; };
</script> </script>
@@ -160,7 +160,7 @@ const getRing = (arrow) => {
</view> </view>
</ScreenHint> </ScreenHint>
<BowData <BowData
:total="result.completed_arrows" :total="result.details.length"
:arrows="result.details" :arrows="result.details"
:show="showBowData" :show="showBowData"
:onClose="() => (showBowData = false)" :onClose="() => (showBowData = false)"

View File

@@ -137,7 +137,8 @@ async function onReceiveMessage(msg) {
} }
let key = []; let key = [];
key.push(arrow.ring ? `${arrow.ringX ? "X" : arrow.ring}` : "未上靶"); key.push(arrow.ring ? `${arrow.ringX ? "X" : arrow.ring}` : "未上靶");
if (!arrow.ring) key.push(`${getDirectionText(arrow.angle)}调整`); if (arrow.angle !== null)
key.push(`${getDirectionText(arrow.angle)}调整`);
audioManager.play(key, false); audioManager.play(key, false);
} else if (msg.type === MESSAGETYPESV2.HalfRest) { } else if (msg.type === MESSAGETYPESV2.HalfRest) {
halfTime.value = true; halfTime.value = true;

View File

@@ -51,7 +51,7 @@ export const getMessageTypeName = (id) => {
for (let key in MESSAGETYPESV2) { for (let key in MESSAGETYPESV2) {
if (MESSAGETYPESV2[key] === id) return key; if (MESSAGETYPESV2[key] === id) return key;
} }
return null; return id;
}; };
export const roundsName = { export const roundsName = {

View File

@@ -1,11 +1,10 @@
<script setup> <script setup>
import { ref, watch, onMounted, onBeforeUnmount } from "vue"; import { ref, onMounted, onBeforeUnmount } from "vue";
import { onShow, onLoad, onShareAppMessage } from "@dcloudio/uni-app"; import { onShow, onLoad, onShareAppMessage } from "@dcloudio/uni-app";
import Container from "@/components/Container.vue"; import Container from "@/components/Container.vue";
import PlayerSeats from "@/components/PlayerSeats.vue"; import PlayerSeats from "@/components/PlayerSeats.vue";
import Guide from "@/components/Guide.vue"; import Guide from "@/components/Guide.vue";
import SButton from "@/components/SButton.vue"; import SButton from "@/components/SButton.vue";
import SModal from "@/components/SModal.vue";
import Avatar from "@/components/Avatar.vue"; import Avatar from "@/components/Avatar.vue";
import { import {
getRoomAPI, getRoomAPI,
@@ -16,7 +15,6 @@ import {
getReadyAPI, getReadyAPI,
kickPlayerAPI, kickPlayerAPI,
} from "@/apis"; } from "@/apis";
import { MESSAGETYPES, MESSAGETYPESV2 } from "@/constants"; import { MESSAGETYPES, MESSAGETYPESV2 } from "@/constants";
import useStore from "@/store"; import useStore from "@/store";
import { storeToRefs } from "pinia"; import { storeToRefs } from "pinia";
@@ -31,8 +29,6 @@ const players = ref([]);
const blueTeam = ref([]); const blueTeam = ref([]);
const redTeam = ref([]); const redTeam = ref([]);
const showModal = ref(false);
const battleType = ref(0);
const ready = ref(false); const ready = ref(false);
const allReady = ref(false); const allReady = ref(false);
const timer = ref(null); const timer = ref(null);
@@ -43,7 +39,6 @@ async function refreshRoomData() {
const result = await getRoomAPI(roomNumber.value); const result = await getRoomAPI(roomNumber.value);
if (result.started) return; if (result.started) return;
room.value = result; room.value = result;
battleType.value = result.battleType;
owner.value = {}; owner.value = {};
opponent.value = {}; opponent.value = {};
const members = result.members || []; const members = result.members || [];
@@ -235,15 +230,15 @@ onBeforeUnmount(() => {
<view class="battle-guide"> <view class="battle-guide">
<view class="guide-tips"> <view class="guide-tips">
<text>弓箭手们人都到齐了吗?</text> <text>弓箭手们人都到齐了吗?</text>
<text v-if="battleType === 1">{{ <text v-if="room.battleType === 1">{{
`${room.count / 2}v${room.count / 2}比赛即将开始!` `${room.count / 2}v${room.count / 2}比赛即将开始!`
}}</text> }}</text>
<text v-if="battleType === 2">大乱斗即将开始! </text> <text v-if="room.battleType === 2">大乱斗即将开始! </text>
</view> </view>
<button hover-class="none" open-type="share">邀请</button> <button hover-class="none" open-type="share">邀请</button>
</view> </view>
</Guide> </Guide>
<view v-if="battleType === 1 && room.count === 2" class="team-mode"> <view v-if="room.battleType === 1 && room.count === 2" class="team-mode">
<image <image
src="https://static.shelingxingqiu.com/attachment/2025-08-05/dbua9nuf5fyeph7cxi.png" src="https://static.shelingxingqiu.com/attachment/2025-08-05/dbua9nuf5fyeph7cxi.png"
mode="widthFix" mode="widthFix"
@@ -272,9 +267,9 @@ onBeforeUnmount(() => {
:style="{ transform: 'translateY(60px)' }" :style="{ transform: 'translateY(60px)' }"
> >
<Avatar :src="opponent.avatar" :size="60" /> <Avatar :src="opponent.avatar" :size="60" />
<text :class="{ ready: opponent.ready }">{{ <text class="ready" :style="{ opacity: opponent.ready ? 1 : 0 }">
opponent.ready ? "已准备" : "" 已准备
}}</text> </text>
<text>{{ opponent.name }}</text> <text>{{ opponent.name }}</text>
<button <button
v-if="owner.id === user.id" v-if="owner.id === user.id"
@@ -290,7 +285,7 @@ onBeforeUnmount(() => {
</view> </view>
</view> </view>
</view> </view>
<block v-if="battleType === 1 && room.count >= 4"> <block v-if="room.battleType === 1 && room.count >= 4">
<view class="all-players"> <view class="all-players">
<image <image
src="https://static.shelingxingqiu.com/attachment/2025-08-13/dc0x1p59iab6cvbhqc.png" src="https://static.shelingxingqiu.com/attachment/2025-08-13/dc0x1p59iab6cvbhqc.png"
@@ -372,60 +367,22 @@ onBeforeUnmount(() => {
</view> </view>
</block> </block>
<PlayerSeats <PlayerSeats
v-if="battleType === 2" v-if="room.battleType === 2"
:total="room.count || 10" :total="room.count || 10"
:players="players" :players="players"
:removePlayer="removePlayer" :removePlayer="removePlayer"
/> />
<view> <view>
<!-- <SButton
v-if="user.id === owner.id && battleType === 1 && room.count === 2"
:disabled="!opponent.id"
:onClick="startGame"
>进入对战</SButton
>
<SButton
v-if="user.id === owner.id && battleType === 2"
:disabled="players.length < 3"
:onClick="startGame"
>进入大乱斗</SButton
>
<SButton
v-if="user.id === owner.id && battleType === 1 && room.count >= 4"
:disabled="
players.some((p) => p.groupType === undefined || p.groupType === 2)
"
:onClick="startGame"
>开启对局</SButton
>
<SButton v-if="user.id !== owner.id" disabled>等待房主开启对战</SButton> -->
<SButton :disabled="ready" :onClick="getReady">{{ <SButton :disabled="ready" :onClick="getReady">{{
allReady.value allReady.value
? "即将进入对局..." ? "即将进入对局..."
: owner.id === user.id : owner.id === user.id && (room.members || []).length > 2
? "开始对局" ? "开始对局"
: "我准备好了" : "我准备好了"
}}</SButton> }}</SButton>
<text class="tips">所有人准备后自动开始游戏</text> <text class="tips">所有人准备后自动开始游戏</text>
</view> </view>
</view> </view>
<!-- <SModal
:show="showModal"
:onClose="() => (showModal = false)"
height="520rpx"
>
<view class="btns">
<SButton :onClick="exitRoom" width="200px" :rounded="20">
暂时离开
</SButton>
<block v-if="owner.id === user.id">
<view :style="{ height: '20px' }"></view>
<SButton :onClick="destroyRoom" width="200px" :rounded="20">
解散房间
</SButton>
</block>
</view>
</SModal> -->
</Container> </Container>
</template> </template>

View File

@@ -262,7 +262,7 @@ const onClose = async () => {
v-if="step === 4" v-if="step === 4"
:total="total" :total="total"
:rowCount="6" :rowCount="6"
:scores="scores.map((s) => s.ring)" :arrows="scores"
/> />
<ScoreResult <ScoreResult
v-if="practiseResult.details" v-if="practiseResult.details"

View File

@@ -16,7 +16,7 @@ const players = ref([]);
onLoad(async (options) => { onLoad(async (options) => {
if (!options.battleId) return; if (!options.battleId) return;
battleId.value = options.battleId || "59090720979554304"; battleId.value = options.battleId || "60143330377469952";
const result = await getBattleAPI(battleId.value); const result = await getBattleAPI(battleId.value);
data.value = result; data.value = result;
if (result.mode > 3) { if (result.mode > 3) {
@@ -116,8 +116,12 @@ const checkBowData = (selected) => {
mode="widthFix" mode="widthFix"
/> />
</view> </view>
<text v-for="(arrow, index2) in round.shoots[team]" :key="index2"> <text
{{ arrow.ring }} v-for="(arrow, index2) in round.shoots[team]"
:key="index2"
:style="{ color: arrow.ringX ? '#fed847' : '#ccc' }"
>
{{ arrow.ringX ? "X" : `${arrow.ring}` }}
</text> </text>
</view> </view>
<view> <view>

View File

@@ -82,12 +82,12 @@ function recoverData(battleInfo, { force = false } = {}) {
onLoad(async (options) => { onLoad(async (options) => {
if (options.battleId) battleId.value = options.battleId; if (options.battleId) battleId.value = options.battleId;
uni.enableAlertBeforeUnload({ // uni.enableAlertBeforeUnload({
message: "离开比赛可能导致比赛失败,是否继续?", // message: "离开比赛可能导致比赛失败,是否继续?",
success: (res) => { // success: (res) => {
console.log("已启用离开提示"); // console.log("已启用离开提示");
}, // },
}); // });
}); });
async function onReceiveMessage(msg) { async function onReceiveMessage(msg) {

View File

@@ -90,7 +90,7 @@ onLoad(async (options) => {
class="score-item" class="score-item"
:style="{ width: '13vw', height: '13vw' }" :style="{ width: '13vw', height: '13vw' }"
> >
{{ score.ring }} {{ score.ringX ? "X" : score.ring }}
</view> </view>
</view> </view>
</view> </view>

View File

@@ -47,7 +47,7 @@ onLoad(async (options) => {
:completeEffect="false" :completeEffect="false"
:rowCount="total === 12 ? 6 : 9" :rowCount="total === 12 ? 6 : 9"
:total="total" :total="total"
:scores="arrows.map((a) => a.ring)" :arrows="arrows"
:margin="arrows.length === 12 ? 4 : 1" :margin="arrows.length === 12 ? 4 : 1"
:fontSize="arrows.length === 12 ? 25 : 22" :fontSize="arrows.length === 12 ? 25 : 22"
/> />

View File

@@ -155,7 +155,7 @@ onBeforeUnmount(() => {
:currentRound="currentRound" :currentRound="currentRound"
:scores="scores" :scores="scores"
/> />
<ScorePanel2 :scores="scores.map((s) => s.ring)" /> <ScorePanel2 :arrows="scores" />
<ScoreResult <ScoreResult
v-if="practiseResult.details" v-if="practiseResult.details"
:rowCount="6" :rowCount="6"

View File

@@ -142,7 +142,7 @@ onBeforeUnmount(() => {
/> />
<ScorePanel <ScorePanel
v-if="start" v-if="start"
:scores="scores.map((s) => s.ring)" :arrows="scores"
:total="total" :total="total"
:rowCount="total / 4" :rowCount="total / 4"
:margin="1.5" :margin="1.5"

View File

@@ -108,12 +108,27 @@ async function onReceiveMessage(msg) {
recoverData(msg, { arrowOnly: true }); recoverData(msg, { arrowOnly: true });
} else if (msg.type === MESSAGETYPESV2.NewRound) { } else if (msg.type === MESSAGETYPESV2.NewRound) {
showRoundTip.value = true; showRoundTip.value = true;
isFinalShoot.value = msg.current.goldRound;
const latestRound = msg.rounds[currentRound.value - 1]; const latestRound = msg.rounds[currentRound.value - 1];
if (latestRound) { if (latestRound) {
if (isFinalShoot.value) {
currentBluePoint.value = msg.teams[1].score;
currentRedPoint.value = msg.teams[2].score;
} else {
currentBluePoint.value = latestRound.scores[1].score; currentBluePoint.value = latestRound.scores[1].score;
currentRedPoint.value = latestRound.scores[2].score; currentRedPoint.value = latestRound.scores[2].score;
} }
}
} else if (msg.type === MESSAGETYPESV2.BattleEnd) { } else if (msg.type === MESSAGETYPESV2.BattleEnd) {
if (msg.status === 4) {
showRoundTip.value = true;
currentBluePoint.value = 0;
currentRedPoint.value = 0;
setTimeout(() => {
uni.navigateBack();
}, 2000);
return;
}
uni.redirectTo({ uni.redirectTo({
url: "/pages/battle-result?battleId=" + msg.matchId, url: "/pages/battle-result?battleId=" + msg.matchId,
}); });
@@ -122,12 +137,12 @@ async function onReceiveMessage(msg) {
onLoad(async (options) => { onLoad(async (options) => {
if (options.battleId) battleId.value = options.battleId; if (options.battleId) battleId.value = options.battleId;
uni.enableAlertBeforeUnload({ // uni.enableAlertBeforeUnload({
message: "离开比赛可能导致比赛失败,是否继续?", // message: "离开比赛可能导致比赛失败,是否继续?",
success: (res) => { // success: (res) => {
console.log("已启用离开提示"); // console.log("已启用离开提示");
}, // },
}); // });
}); });
onMounted(async () => { onMounted(async () => {
uni.setKeepScreenOn({ uni.setKeepScreenOn({

View File

@@ -82,7 +82,7 @@ const onClickTab = (index) => {
:key="index" :key="index"
class="score-item" class="score-item"
> >
{{ score.ring }} {{ score.ringX ? "X" : score.ring }}
</view> </view>
</view> </view>
</view> </view>