update:对接个人训练改版

This commit is contained in:
2026-07-23 09:44:58 +08:00
parent a78ab1daeb
commit 3c5754b3fd
64 changed files with 1769 additions and 488 deletions
+64 -20
View File
@@ -27,6 +27,14 @@ const props = defineProps({
type: Number,
default: 120,
},
countdownEnabled: {
type: Boolean,
default: true,
},
trainingType: {
type: String,
default: "precision",
},
currentRound: {
type: Number,
default: 0,
@@ -45,8 +53,19 @@ const props = defineProps({
},
});
const trainingTitleIconMap = Object.freeze({
base: "../static/training-difficulty-design/text-icon-jcxl.png",
precision: "../static/training-difficulty-design/text-icon-jingzxl.png",
rhythm: "../static/training-difficulty-design/text-icon-jzxl.png",
endurance: "../static/training-difficulty-design/text-icon-nlxl.png",
});
const trainingTitleIcon = computed(
() =>
trainingTitleIconMap[props.trainingType] || trainingTitleIconMap.precision
);
const barColor = ref("#fed847");
const remain = ref(props.total);
const remain = ref(props.countdownEnabled ? props.total : 0);
const timer = ref(null);
const sound = ref(true);
const currentRound = ref(props.currentRound);
@@ -56,7 +75,7 @@ const wait = ref(0);
const transitionStyle = ref("all 1s linear");
const progressPercent = computed(() => {
if (!props.total) return 0;
if (!props.countdownEnabled || !props.total) return 0;
return Math.max(0, Math.min(100, (remain.value / props.total) * 100));
});
@@ -98,9 +117,23 @@ watch(
}
);
const clearTimer = () => {
if (!timer.value) return;
clearInterval(timer.value);
timer.value = null;
};
const resetTimer = (count) => {
if (timer.value) clearInterval(timer.value);
const newVal = Math.round(count);
clearTimer();
if (!props.countdownEnabled) {
remain.value = 0;
return;
}
const countValue = Number(count);
const newVal = Number.isFinite(countValue)
? Math.max(0, Math.round(countValue))
: 0;
if (newVal >= remain.value) {
transitionStyle.value = "none";
@@ -115,7 +148,7 @@ const resetTimer = (count) => {
if (remain.value > 0) {
timer.value = setInterval(() => {
if (remain.value === 0) {
clearInterval(timer.value);
clearTimer();
props.onStop();
}
if (remain.value > 0) remain.value--;
@@ -124,13 +157,13 @@ const resetTimer = (count) => {
};
watch(
() => props.start,
(newVal) => {
if (newVal) {
() => [props.start, props.countdownEnabled],
([started, countdownEnabled]) => {
if (started && countdownEnabled) {
resetTimer(props.total);
} else {
clearTimer();
remain.value = 0;
clearInterval(timer.value);
}
},
{
@@ -158,18 +191,29 @@ async function onReceiveMessage(msg) {
} else if (msg.type === MESSAGETYPESV2.BattleEnd) {
audioManager.play("比赛结束", false);
} else if (msg.type === MESSAGETYPESV2.ShootResult) {
let arrow = {};
if (msg.details && Array.isArray(msg.details)) {
arrow = msg.details[msg.details.length - 1];
} else {
if (msg.shootData.playerId !== user.value.id) return;
if (msg.shootData) arrow = msg.shootData;
const latestDetail =
Array.isArray(msg.details) && msg.details.length > 0
? msg.details[msg.details.length - 1]
: null;
// 语音和 ACK 优先使用同一份当前箭数据,details 仅作为兼容兜底。
const arrow = msg.shootData || latestDetail;
if (!arrow) return;
if (
arrow.playerId !== undefined &&
arrow.playerId !== null &&
String(arrow.playerId) !== String(user.value?.id)
) {
return;
}
let key = [];
const key = [];
key.push(arrow.ring ? `${arrow.ringX ? "X" : arrow.ring}` : "未上靶");
if (arrow.angle !== null) {
if (arrow.angle !== null && arrow.angle !== undefined) {
key.push(`${getDirectionText(arrow.angle)}调整`);
}
if (arrow.threeConsecutive10Rings === true) {
key.push("tententen");
}
audioManager.play(key, false);
} else if (msg.type === MESSAGETYPESV2.HalfRest) {
halfTime.value = true;
@@ -197,7 +241,7 @@ onBeforeUnmount(() => {
uni.$off("update-remain", resetTimer);
uni.$off("socket-inbox", onReceiveMessage);
uni.$off("play-sound", playSound);
if (timer.value) clearInterval(timer.value);
clearTimer();
});
</script>
@@ -228,10 +272,10 @@ onBeforeUnmount(() => {
<view class="progress-card__track-wrap">
<image
class="progress-card__titile"
src="../../../static/training-difficulty-design/text-icon-cgxl.png"
:src="trainingTitleIcon"
mode="aspectFit"
/>
<view class="progress-card__track">
<view v-if="countdownEnabled" class="progress-card__track">
<view
class="progress-card__fill"
:style="{