update:分包、对接个人练习
This commit is contained in:
@@ -82,7 +82,7 @@ const checkBowData = () => {
|
||||
<view class="container">
|
||||
<block v-if="data.mode <= 3">
|
||||
<view class="header-team" :style="{ marginTop: '25%' }">
|
||||
<image src="../static/battle-result.png" mode="widthFix" />
|
||||
<image src="https://static.shelingxingqiu.com/shootmini/static/battle-result.png" mode="widthFix" />
|
||||
<view class="header-solo" v-if="data.mode === 1">
|
||||
<text
|
||||
:style="{
|
||||
@@ -107,7 +107,7 @@ const checkBowData = () => {
|
||||
</view>
|
||||
<view class="header-mvp" v-if="data.mode === 2 || data.mode === 3">
|
||||
<image
|
||||
:src="`../static/${data.winTeam === 1 ? 'blue' : 'red'}-team-win.png`"
|
||||
:src="`https://static.shelingxingqiu.com/shootmini/static/${data.winTeam === 1 ? 'blue' : 'red'}-team-win.png`"
|
||||
mode="widthFix"
|
||||
/>
|
||||
<view
|
||||
@@ -118,7 +118,7 @@ const checkBowData = () => {
|
||||
}"
|
||||
>
|
||||
<view v-if="data.mvp && data.mvp.totalRings">
|
||||
<image src="../static/title-mvp.png" mode="widthFix" />
|
||||
<image src="https://static.shelingxingqiu.com/shootmini/static/title-mvp.png" mode="widthFix" />
|
||||
<text
|
||||
>斩获<text
|
||||
:style="{
|
||||
@@ -153,7 +153,7 @@ const checkBowData = () => {
|
||||
</view>
|
||||
</view>
|
||||
<view class="battle-winner">
|
||||
<image src="../static/shining-bg.png" mode="widthFix" />
|
||||
<image src="https://static.shelingxingqiu.com/shootmini/static/shining-bg.png" mode="widthFix" />
|
||||
<image
|
||||
:src="ifWin ? '../static/you-win.png' : '../static/you-lost.png'"
|
||||
mode="widthFix"
|
||||
@@ -173,7 +173,7 @@ const checkBowData = () => {
|
||||
<block v-else>
|
||||
<view class="header-melee">
|
||||
<view />
|
||||
<image src="../static/battle-result.png" mode="widthFix" />
|
||||
<image src="https://static.shelingxingqiu.com/shootmini/static/battle-result.png" mode="widthFix" />
|
||||
<view />
|
||||
</view>
|
||||
<view
|
||||
@@ -248,7 +248,7 @@ const checkBowData = () => {
|
||||
class="battle-e"
|
||||
:style="{ marginTop: data.mode > 3 ? '20px' : '20vw' }"
|
||||
>
|
||||
<image src="../static/row-yellow-bg.png" mode="widthFix" />
|
||||
<image src="https://static.shelingxingqiu.com/shootmini/static/row-yellow-bg.png" mode="widthFix" />
|
||||
<view class="team-avatar">
|
||||
<Avatar
|
||||
:src="user.avatar"
|
||||
|
||||
@@ -400,7 +400,7 @@ onBeforeUnmount(() => {
|
||||
<view v-else class="no-player" :style="{ transform: 'translateY(-60px)' }">
|
||||
<image src="../static/question-mark.png" mode="widthFix" />
|
||||
</view>
|
||||
<image src="../static/versus.png" mode="widthFix" />
|
||||
<image src="https://static.shelingxingqiu.com/shootmini/static/versus.png" mode="widthFix" />
|
||||
<view v-if="opponent.id" class="player" :style="{ transform: 'translateY(60px)' }">
|
||||
<Avatar :src="opponent.avatar" :size="60" />
|
||||
<text class="ready" :style="{ opacity: opponent.ready ? 1 : 0 }">
|
||||
@@ -420,8 +420,8 @@ onBeforeUnmount(() => {
|
||||
<block v-if="room.battleType === 1 && room.count >= 4">
|
||||
<view class="all-players">
|
||||
<image src="https://static.shelingxingqiu.com/attachment/2025-08-13/dc0x1p59iab6cvbhqc.png" mode="widthFix" />
|
||||
<image v-if="room.count === 4" src="../static/title-2v2.png" mode="widthFix" />
|
||||
<image v-if="room.count === 6" src="../static/title-3v3.png" mode="widthFix" />
|
||||
<image v-if="room.count === 4" src="https://static.shelingxingqiu.com/shootmini/static/title-2v2.png" mode="widthFix" />
|
||||
<image v-if="room.count === 6" src="https://static.shelingxingqiu.com/shootmini/static/title-3v3.png" mode="widthFix" />
|
||||
<view>
|
||||
<view v-for="(item, index) in players" :key="index">
|
||||
<Avatar v-if="item.id" :src="item.avatar" :size="36" />
|
||||
|
||||
+45
-21
@@ -15,19 +15,18 @@ import BubbleTip from "@/components/BubbleTip.vue";
|
||||
import audioManager from "@/audioManager";
|
||||
import {
|
||||
createPractiseAPI,
|
||||
startPractiseAPI,
|
||||
endPractiseAPI,
|
||||
getPractiseAPI,
|
||||
laserAimAPI,
|
||||
laserCloseAPI,
|
||||
} from "@/apis";
|
||||
import { connectMatchWebSocket, closeMatchWebSocket } from "@/matchWebsocket";
|
||||
import { sharePractiseData } from "@/canvas";
|
||||
import { wxShare, debounce } from "@/util";
|
||||
import { MESSAGETYPESV2 } from "@/constants";
|
||||
import useStore from "@/store";
|
||||
import { storeToRefs } from "pinia";
|
||||
const store = useStore();
|
||||
const { user } = storeToRefs(store);
|
||||
const { user, device } = storeToRefs(store);
|
||||
const scores = ref([]);
|
||||
const isSvip = ref(false);
|
||||
const step = ref(0);
|
||||
@@ -50,6 +49,7 @@ const showGuide = ref(false);
|
||||
const laserActive = ref(false);
|
||||
const guideSwiperIndex = ref(0);
|
||||
const sharing = ref(false);
|
||||
const RESULT_TIP_CDN = "https://static.shelingxingqiu.com/shootmini/static";
|
||||
|
||||
const guideImages = [
|
||||
"https://static.shelingxingqiu.com/shootmini/static/target.png",
|
||||
@@ -104,21 +104,42 @@ const closeCalibrationLaser = async () => {
|
||||
};
|
||||
|
||||
const createPractise = async (arrows) => {
|
||||
const result = await createPractiseAPI(arrows, 1);
|
||||
closeMatchWebSocket({ reason: "practice-recreate" });
|
||||
const result = await createPractiseAPI(
|
||||
arrows,
|
||||
120,
|
||||
1,
|
||||
device.value.deviceId
|
||||
);
|
||||
if (result) practiseId.value = result.id;
|
||||
if (!result?.serverAddr) {
|
||||
uni.showToast({
|
||||
title: "练习连接信息异常,请重试",
|
||||
icon: "none",
|
||||
});
|
||||
return null;
|
||||
}
|
||||
connectMatchWebSocket({
|
||||
serverAddr: result.serverAddr,
|
||||
matchId: result.id,
|
||||
userId: user.value.id,
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
const onOver = async () => {
|
||||
practiseResult.value = await getPractiseAPI(practiseId.value);
|
||||
const onOver = async (message) => {
|
||||
practiseResult.value = Array.isArray(message?.details)
|
||||
? message
|
||||
: await getPractiseAPI(practiseId.value);
|
||||
start.value = false;
|
||||
};
|
||||
|
||||
async function onReceiveMessage(msg) {
|
||||
if (msg.type === MESSAGETYPESV2.ShootResult) {
|
||||
isSvip.value = msg.sVip === true;
|
||||
scores.value = msg.details;
|
||||
scores.value = Array.isArray(msg.details) ? msg.details : scores.value;
|
||||
} else if (msg.type === MESSAGETYPESV2.BattleEnd) {
|
||||
setTimeout(onOver, 1500);
|
||||
setTimeout(() => onOver(msg), 1500);
|
||||
} else if (msg.type === MESSAGETYPESV2.TestDistance && step.value === 3) {
|
||||
if (msg.shootData.distance / 100 >= 5) {
|
||||
audioManager.play("距离合格");
|
||||
@@ -173,7 +194,7 @@ onBeforeUnmount(async () => {
|
||||
uni.$off("share-image", onClickShare);
|
||||
await closeCalibrationLaser();
|
||||
audioManager.stopAll();
|
||||
endPractiseAPI();
|
||||
closeMatchWebSocket({ reason: "practice-leave" });
|
||||
});
|
||||
|
||||
const nextStep = async () => {
|
||||
@@ -196,15 +217,18 @@ const nextStep = async () => {
|
||||
btnDisabled.value = true;
|
||||
step.value = 3;
|
||||
title.value = "-感知距离";
|
||||
const result = await createPractiseAPI(total, 120);
|
||||
if (result) practiseId.value = result.id;
|
||||
const result = await createPractise(total);
|
||||
if (!result) {
|
||||
btnDisabled.value = false;
|
||||
step.value = 2;
|
||||
return;
|
||||
}
|
||||
} else if (step.value === 3) {
|
||||
showGuide.value = false;
|
||||
step.value = 4;
|
||||
title.value = "-小试牛刀";
|
||||
} else if (step.value === 4) {
|
||||
title.value = "小试牛刀";
|
||||
await startPractiseAPI();
|
||||
scores.value = [];
|
||||
isSvip.value = false;
|
||||
step.value = 5;
|
||||
@@ -235,10 +259,16 @@ const onClose = async () => {
|
||||
scores.value = [];
|
||||
isSvip.value = false;
|
||||
step.value = 4;
|
||||
const result = await createPractiseAPI(total, 120);
|
||||
if (result) practiseId.value = result.id;
|
||||
await createPractise(total);
|
||||
}
|
||||
};
|
||||
|
||||
const getResultTipSrc = (result = {}) => {
|
||||
const validCount = (result.details || []).filter(
|
||||
(arrow) => arrow.x !== -30 && arrow.y !== -30
|
||||
).length;
|
||||
return `${RESULT_TIP_CDN}/${validCount < total ? "un" : ""}finish-tip.png`;
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -361,13 +391,7 @@ const onClose = async () => {
|
||||
:total="total"
|
||||
:onClose="onClose"
|
||||
:result="practiseResult"
|
||||
:tipSrc="`../static/${
|
||||
practiseResult.details.filter(
|
||||
(arrow) => arrow.x !== -30 && arrow.y !== -30
|
||||
).length < total
|
||||
? 'un'
|
||||
: ''
|
||||
}finish-tip.png`"
|
||||
:tipSrc="getResultTipSrc(practiseResult)"
|
||||
/>
|
||||
<canvas class="share-canvas" id="shareCanvas" type="2d"></canvas>
|
||||
</view>
|
||||
|
||||
@@ -404,12 +404,12 @@ function goBack() {
|
||||
<!-- 背景图:蓝队用 mvp-blue.png,红队用 mvp-red.png(平行四边形渐变切图) -->
|
||||
<image
|
||||
class="mvp-bg"
|
||||
:src="mvpTeam === 1 ? '../static/mvp-blue.png' : '../static/mvp-red.png'"
|
||||
:src="mvpTeam === 1 ? 'https://static.shelingxingqiu.com/shootmini/static/mvp-blue.png' : 'https://static.shelingxingqiu.com/shootmini/static/mvp-red.png'"
|
||||
mode="scaleToFill"
|
||||
/>
|
||||
<!-- 左:MVP 标题图 + 斩获环数 -->
|
||||
<view class="mvp-info">
|
||||
<image class="mvp-badge" src="../static/mvp-tip.png" mode="widthFix" />
|
||||
<image class="mvp-badge" src="https://static.shelingxingqiu.com/shootmini/static/mvp-tip.png" mode="widthFix" />
|
||||
<view class="mvp-rings">
|
||||
斩获<text class="mvp-rings-num">{{ mvpPlayer.totalRing }}</text>环
|
||||
</view>
|
||||
@@ -439,7 +439,7 @@ function goBack() {
|
||||
<!-- 本场战绩标题:装饰横线 + 标题图 + 装饰横线 -->
|
||||
<view class="melee-title">
|
||||
<view class="melee-title-line" />
|
||||
<image class="melee-title-img" src="../static/battle-result.png" mode="scaleToFill" />
|
||||
<image class="melee-title-img" src="https://static.shelingxingqiu.com/shootmini/static/battle-result.png" mode="scaleToFill" />
|
||||
<view class="melee-title-line" />
|
||||
</view>
|
||||
|
||||
|
||||
@@ -209,10 +209,10 @@ onLoad(async (options) => {
|
||||
</view>
|
||||
<view class="create-room">
|
||||
<image src="https://static.shelingxingqiu.com/attachment/2025-07-15/dbcejys872iyun92h6.png" mode="widthFix" />
|
||||
<image src="../static/room-notfound-title.png" mode="widthFix" />
|
||||
<image src="https://static.shelingxingqiu.com/shootmini/static/room-notfound-title.png" mode="widthFix" />
|
||||
<view>
|
||||
<image :src="user.avatar" mode="widthFix" />
|
||||
<image src="../static/versus.png" mode="widthFix" />
|
||||
<image src="https://static.shelingxingqiu.com/shootmini/static/versus.png" mode="widthFix" />
|
||||
<view>
|
||||
<image src="../static/question-mark.png" mode="widthFix" />
|
||||
</view>
|
||||
|
||||
+5
-5
@@ -423,7 +423,7 @@ onShareTimeline(() => {
|
||||
<text v-else-if="online">设备在线</text>
|
||||
</block>
|
||||
<image
|
||||
src="../static/first-try.png"
|
||||
src="https://static.shelingxingqiu.com/shootmini/static/first-try.png"
|
||||
mode="widthFix"
|
||||
@click="() => toPage('/pages/first-try')"
|
||||
/>
|
||||
@@ -434,10 +434,10 @@ onShareTimeline(() => {
|
||||
</view>
|
||||
<view class="play-card">
|
||||
<view @click="$clickSound(() => toPage('/pages/practise'))">
|
||||
<image src="../static/my-practise.png" mode="widthFix"/>
|
||||
<image src="https://static.shelingxingqiu.com/shootmini/static/my-practise.png" mode="widthFix"/>
|
||||
</view>
|
||||
<view @click="$clickSound(() => toPage('/pages/friend-battle'))">
|
||||
<image src="../static/friend-battle.png" mode="widthFix"/>
|
||||
<image src="https://static.shelingxingqiu.com/shootmini/static/friend-battle.png" mode="widthFix"/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -452,7 +452,7 @@ onShareTimeline(() => {
|
||||
hover-class="none"
|
||||
></button>
|
||||
<view class="ranking-players" @click="toRankListPage">
|
||||
<img src="../static/juezhanbang.png" mode="widthFix"/>
|
||||
<img src="https://static.shelingxingqiu.com/shootmini/static/juezhanbang.png" mode="widthFix"/>
|
||||
<view class="divide-line"></view>
|
||||
<view class="player-avatars">
|
||||
<view
|
||||
@@ -486,7 +486,7 @@ onShareTimeline(() => {
|
||||
</view>
|
||||
<view class="my-data">
|
||||
<view @click="() => toPage('/pages/my-growth')">
|
||||
<image src="../static/my-growth.png" mode="widthFix"/>
|
||||
<image src="https://static.shelingxingqiu.com/shootmini/static/my-growth.png" mode="widthFix"/>
|
||||
</view>
|
||||
<view @click="() => toPage('/pages/ranking')">
|
||||
<view>
|
||||
|
||||
@@ -65,7 +65,7 @@ onLoad(async (options) => {
|
||||
<Container title="靶纸">
|
||||
<view class="container">
|
||||
<image
|
||||
src="../static/battle-header-melee.png"
|
||||
src="https://static.shelingxingqiu.com/shootmini/static/battle-header-melee.png"
|
||||
mode="widthFix"
|
||||
:style="{ top: '-50rpx' }"
|
||||
/>
|
||||
|
||||
@@ -161,7 +161,7 @@ onShow(async () => {
|
||||
<Container title="弓箭绑定">
|
||||
<view v-if="!device.deviceId" class="scan-code">
|
||||
<button hover-class="none" @click="$clickSound(handleScan)">
|
||||
<image src="../static/scan.png" mode="widthFix" />
|
||||
<image src="https://static.shelingxingqiu.com/shootmini/static/scan.png" mode="widthFix" />
|
||||
</button>
|
||||
<button hover-class="none" @click="showTip = true">
|
||||
<text>扫</text>
|
||||
@@ -172,7 +172,7 @@ onShow(async () => {
|
||||
<text>射灵智能弓箭,三模传感系统与独创靶环算法,</text>
|
||||
<text>毫秒级在线实时对战,让你拥有全球约战的乐趣!</text>
|
||||
<button hover-class="none" @click="toDeviceIntroPage">
|
||||
<image src="../static/have-no-device.png" mode="widthFix" />
|
||||
<image src="https://static.shelingxingqiu.com/shootmini/static/have-no-device.png" mode="widthFix" />
|
||||
</button>
|
||||
<ScreenHint
|
||||
mode="square"
|
||||
@@ -219,7 +219,7 @@ onShow(async () => {
|
||||
:style="{ marginBottom: calibration ? '250rpx' : '100rpx' }"
|
||||
>
|
||||
<view>
|
||||
<image src="../static/device-icon.png" mode="widthFix" />
|
||||
<image src="https://static.shelingxingqiu.com/shootmini/static/device-icon.png" mode="widthFix" />
|
||||
<text>{{ device.deviceName }}</text>
|
||||
<view class="calibration" v-if="calibration">
|
||||
<button hover-class="none" @click="goCalibration">
|
||||
@@ -286,7 +286,7 @@ onShow(async () => {
|
||||
<view v-if="device.deviceId && !justBind" class="has-device">
|
||||
<view class="device-binded">
|
||||
<view>
|
||||
<image src="../static/device-icon.png" mode="widthFix" />
|
||||
<image src="https://static.shelingxingqiu.com/shootmini/static/device-icon.png" mode="widthFix" />
|
||||
<text>{{ device.deviceName }}</text>
|
||||
<view class="calibration">
|
||||
<button hover-class="none" @click="goCalibration">
|
||||
|
||||
@@ -44,7 +44,7 @@ onMounted(async () => {
|
||||
<Container :bgType="5" bgColor="#F5F5F5" :whiteBackArrow="false">
|
||||
<view class="top-part">
|
||||
<view>
|
||||
<image src="../static/point-champion.png" mode="widthFix" />
|
||||
<image src="https://static.shelingxingqiu.com/shootmini/static/point-champion.png" mode="widthFix" />
|
||||
<image
|
||||
:src="list[0] && list[0].avatar ? list[0].avatar : ''"
|
||||
mode="widthFix"
|
||||
|
||||
@@ -348,7 +348,7 @@ onShareTimeline(() => {
|
||||
/>
|
||||
<view class="heat-map">
|
||||
<image
|
||||
:src="bowTargetSrc || '../static/bow-target.png'"
|
||||
:src="bowTargetSrc || 'https://static.shelingxingqiu.com/shootmini/static/bow-target.png'"
|
||||
mode="widthFix"
|
||||
/>
|
||||
<image
|
||||
@@ -374,7 +374,7 @@ onShareTimeline(() => {
|
||||
</view>
|
||||
<view class="reward" v-if="data.totalArrow">
|
||||
<button hover-class="none" @click="showTip = true">
|
||||
<image src="../static/reward-us.png" mode="widthFix" />
|
||||
<image src="https://static.shelingxingqiu.com/shootmini/static/reward-us.png" mode="widthFix" />
|
||||
</button>
|
||||
</view>
|
||||
<RingBarChart :data="data.ringRate" v-if="user.id" />
|
||||
|
||||
+44
-28
@@ -15,10 +15,9 @@ import audioManager from "@/audioManager";
|
||||
|
||||
import {
|
||||
createPractiseAPI,
|
||||
startPractiseAPI,
|
||||
endPractiseAPI,
|
||||
getPractiseAPI,
|
||||
} from "@/apis";
|
||||
import { connectMatchWebSocket, closeMatchWebSocket } from "@/matchWebsocket";
|
||||
import { sharePractiseData } from "@/canvas";
|
||||
import { wxShare, debounce } from "@/util";
|
||||
import { MESSAGETYPESV2, roundsName } from "@/constants";
|
||||
@@ -26,7 +25,7 @@ import { MESSAGETYPESV2, roundsName } from "@/constants";
|
||||
import useStore from "@/store";
|
||||
import { storeToRefs } from "pinia";
|
||||
const store = useStore();
|
||||
const { user } = storeToRefs(store);
|
||||
const { user, device } = storeToRefs(store);
|
||||
|
||||
const start = ref(false);
|
||||
const scores = ref([]);
|
||||
@@ -40,6 +39,7 @@ const showGuide = ref(false);
|
||||
const tips = ref("");
|
||||
const targetType = ref(1);
|
||||
const sharing = ref(false);
|
||||
const RESULT_TIP_CDN = "https://static.shelingxingqiu.com/shootmini/static";
|
||||
|
||||
onLoad((options) => {
|
||||
if (options.target) {
|
||||
@@ -47,8 +47,31 @@ onLoad((options) => {
|
||||
}
|
||||
});
|
||||
|
||||
const createPractise = async () => {
|
||||
closeMatchWebSocket({ reason: "practice-recreate" });
|
||||
const result = await createPractiseAPI(
|
||||
total,
|
||||
120,
|
||||
targetType.value,
|
||||
device.value.deviceId
|
||||
);
|
||||
if (result?.id) practiseId.value = result.id;
|
||||
if (!result?.serverAddr) {
|
||||
uni.showToast({
|
||||
title: "练习连接信息异常,请重试",
|
||||
icon: "none",
|
||||
});
|
||||
return null;
|
||||
}
|
||||
connectMatchWebSocket({
|
||||
serverAddr: result.serverAddr,
|
||||
matchId: result.id,
|
||||
userId: user.value.id,
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
const onReady = async () => {
|
||||
await startPractiseAPI();
|
||||
scores.value = [];
|
||||
isSvip.value = false;
|
||||
xRingStreak.value = 0; // 新一局开始,重置 X 环连续计数
|
||||
@@ -56,8 +79,10 @@ const onReady = async () => {
|
||||
audioManager.play("练习开始");
|
||||
};
|
||||
|
||||
const onOver = async () => {
|
||||
practiseResult.value = await getPractiseAPI(practiseId.value);
|
||||
const onOver = async (message) => {
|
||||
practiseResult.value = Array.isArray(message?.details)
|
||||
? message
|
||||
: await getPractiseAPI(practiseId.value);
|
||||
start.value = false;
|
||||
};
|
||||
|
||||
@@ -87,14 +112,14 @@ async function onReceiveMessage(msg) {
|
||||
if (msg.type === MESSAGETYPESV2.ShootResult) {
|
||||
const prevLen = scores.value.length;
|
||||
isSvip.value = msg.sVip === true;
|
||||
scores.value = msg.details;
|
||||
scores.value = Array.isArray(msg.details) ? msg.details : scores.value;
|
||||
// 有新箭时取最后一箭判断是否 10 环及以上并检测连续计数
|
||||
if (scores.value.length > prevLen) {
|
||||
const latestArrow = scores.value[scores.value.length - 1];
|
||||
checkAndPlayTententen(isTenPlusRing(latestArrow));
|
||||
}
|
||||
} else if (msg.type === MESSAGETYPESV2.BattleEnd) {
|
||||
// setTimeout(onOver, 1500);
|
||||
setTimeout(() => onOver(msg), 1500);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,11 +136,17 @@ async function onComplete() {
|
||||
scores.value = [];
|
||||
isSvip.value = false;
|
||||
xRingStreak.value = 0; // 重新开始练习,重置 X 环连续计数
|
||||
const result = await createPractiseAPI(total, 120);
|
||||
if (result) practiseId.value = result.id;
|
||||
await createPractise();
|
||||
}
|
||||
}
|
||||
|
||||
const getResultTipSrc = (result = {}) => {
|
||||
const validCount = (result.details || []).filter(
|
||||
(arrow) => arrow.x !== -30 && arrow.y !== -30
|
||||
).length;
|
||||
return `${RESULT_TIP_CDN}/${validCount < total ? "un" : ""}finish-tip.png`;
|
||||
};
|
||||
|
||||
const onClickShare = debounce(async () => {
|
||||
if (sharing.value) return;
|
||||
sharing.value = true;
|
||||
@@ -132,12 +163,6 @@ const onClickShare = debounce(async () => {
|
||||
}
|
||||
});
|
||||
|
||||
function onAudioEnded(s) {
|
||||
if (s.indexOf("比赛结束") >= 0) {
|
||||
onOver()
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
// audioManager.play("第一轮");
|
||||
uni.setKeepScreenOn({
|
||||
@@ -145,9 +170,7 @@ onMounted(async () => {
|
||||
});
|
||||
uni.$on("socket-inbox", onReceiveMessage);
|
||||
uni.$on("share-image", onClickShare);
|
||||
uni.$on("audioEnded", onAudioEnded);
|
||||
const result = await createPractiseAPI(total, 120, targetType.value);
|
||||
if (result) practiseId.value = result.id;
|
||||
await createPractise();
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
@@ -156,9 +179,8 @@ onBeforeUnmount(() => {
|
||||
});
|
||||
uni.$off("socket-inbox", onReceiveMessage);
|
||||
uni.$off("share-image", onClickShare);
|
||||
uni.$off("audioEnded", onAudioEnded);
|
||||
audioManager.stopAll();
|
||||
endPractiseAPI();
|
||||
closeMatchWebSocket({ reason: "practice-leave" });
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -203,13 +225,7 @@ onBeforeUnmount(() => {
|
||||
:total="total"
|
||||
:onClose="onComplete"
|
||||
:result="practiseResult"
|
||||
:tipSrc="`../static/${
|
||||
practiseResult.details.filter(
|
||||
(arrow) => arrow.x !== -30 && arrow.y !== -30
|
||||
).length < total
|
||||
? 'un'
|
||||
: ''
|
||||
}finish-tip.png`"
|
||||
:tipSrc="getResultTipSrc(practiseResult)"
|
||||
/>
|
||||
<canvas class="share-canvas" id="shareCanvas" type="2d"></canvas>
|
||||
</block>
|
||||
|
||||
+44
-20
@@ -14,10 +14,9 @@ import audioManager from "@/audioManager";
|
||||
|
||||
import {
|
||||
createPractiseAPI,
|
||||
startPractiseAPI,
|
||||
endPractiseAPI,
|
||||
getPractiseAPI,
|
||||
} from "@/apis";
|
||||
import { connectMatchWebSocket, closeMatchWebSocket } from "@/matchWebsocket";
|
||||
import { sharePractiseData } from "@/canvas";
|
||||
import { wxShare, debounce } from "@/util";
|
||||
import { MESSAGETYPESV2 } from "@/constants";
|
||||
@@ -26,7 +25,7 @@ import useStore from "@/store";
|
||||
import { storeToRefs } from "pinia";
|
||||
import {onLoad} from "@dcloudio/uni-app";
|
||||
const store = useStore();
|
||||
const { user } = storeToRefs(store);
|
||||
const { user, device } = storeToRefs(store);
|
||||
|
||||
const start = ref(false);
|
||||
const scores = ref([]);
|
||||
@@ -39,6 +38,7 @@ const practiseId = ref("");
|
||||
const showGuide = ref(false);
|
||||
const targetType = ref(1);
|
||||
const sharing = ref(false);
|
||||
const RESULT_TIP_CDN = "https://static.shelingxingqiu.com/shootmini/static";
|
||||
|
||||
onLoad((options) => {
|
||||
if (options.target) {
|
||||
@@ -46,8 +46,31 @@ onLoad((options) => {
|
||||
}
|
||||
});
|
||||
|
||||
const createPractise = async () => {
|
||||
closeMatchWebSocket({ reason: "practice-recreate" });
|
||||
const result = await createPractiseAPI(
|
||||
total,
|
||||
3600,
|
||||
targetType.value,
|
||||
device.value.deviceId
|
||||
);
|
||||
if (result?.id) practiseId.value = result.id;
|
||||
if (!result?.serverAddr) {
|
||||
uni.showToast({
|
||||
title: "练习连接信息异常,请重试",
|
||||
icon: "none",
|
||||
});
|
||||
return null;
|
||||
}
|
||||
connectMatchWebSocket({
|
||||
serverAddr: result.serverAddr,
|
||||
matchId: result.id,
|
||||
userId: user.value.id,
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
const onReady = async () => {
|
||||
await startPractiseAPI();
|
||||
scores.value = [];
|
||||
isSvip.value = false;
|
||||
xRingStreak.value = 0; // 新一局开始,重置 X 环连续计数
|
||||
@@ -55,8 +78,10 @@ const onReady = async () => {
|
||||
audioManager.play("练习开始");
|
||||
};
|
||||
|
||||
const onOver = async () => {
|
||||
practiseResult.value = await getPractiseAPI(practiseId.value);
|
||||
const onOver = async (message) => {
|
||||
practiseResult.value = Array.isArray(message?.details)
|
||||
? message
|
||||
: await getPractiseAPI(practiseId.value);
|
||||
start.value = false;
|
||||
};
|
||||
|
||||
@@ -86,14 +111,14 @@ async function onReceiveMessage(msg) {
|
||||
if (msg.type === MESSAGETYPESV2.ShootResult) {
|
||||
const prevLen = scores.value.length;
|
||||
isSvip.value = msg.sVip === true;
|
||||
scores.value = msg.details;
|
||||
scores.value = Array.isArray(msg.details) ? msg.details : scores.value;
|
||||
// 有新箭时取最后一箭判断是否 10 环及以上并检测连续计数
|
||||
if (scores.value.length > prevLen) {
|
||||
const latestArrow = scores.value[scores.value.length - 1];
|
||||
checkAndPlayTententen(isTenPlusRing(latestArrow));
|
||||
}
|
||||
} else if (msg.type === MESSAGETYPESV2.BattleEnd) {
|
||||
setTimeout(onOver, 1500);
|
||||
setTimeout(() => onOver(msg), 1500);
|
||||
}
|
||||
// messages.forEach((msg) => {
|
||||
// if (msg.constructor === MESSAGETYPES.ShootSyncMeArrowID) {
|
||||
@@ -126,11 +151,17 @@ async function onComplete() {
|
||||
scores.value = [];
|
||||
isSvip.value = false;
|
||||
xRingStreak.value = 0; // 重新开始练习,重置 X 环连续计数
|
||||
const result = await createPractiseAPI(total, 3600);
|
||||
if (result) practiseId.value = result.id;
|
||||
await createPractise();
|
||||
}
|
||||
}
|
||||
|
||||
const getResultTipSrc = (result = {}) => {
|
||||
const validCount = (result.details || []).filter(
|
||||
(arrow) => arrow.x !== -30 && arrow.y !== -30
|
||||
).length;
|
||||
return `${RESULT_TIP_CDN}/${validCount < total ? "2un" : ""}finish-tip.png`;
|
||||
};
|
||||
|
||||
const onClickShare = debounce(async () => {
|
||||
if (sharing.value) return;
|
||||
sharing.value = true;
|
||||
@@ -153,8 +184,7 @@ onMounted(async () => {
|
||||
});
|
||||
uni.$on("socket-inbox", onReceiveMessage);
|
||||
uni.$on("share-image", onClickShare);
|
||||
const result = await createPractiseAPI(total, 3600, targetType.value);
|
||||
if (result) practiseId.value = result.id;
|
||||
await createPractise();
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
@@ -164,7 +194,7 @@ onBeforeUnmount(() => {
|
||||
uni.$off("socket-inbox", onReceiveMessage);
|
||||
uni.$off("share-image", onClickShare);
|
||||
audioManager.stopAll();
|
||||
endPractiseAPI();
|
||||
closeMatchWebSocket({ reason: "practice-leave" });
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -211,13 +241,7 @@ onBeforeUnmount(() => {
|
||||
:rowCount="9"
|
||||
:onClose="onComplete"
|
||||
:result="practiseResult"
|
||||
:tipSrc="`../static/${
|
||||
practiseResult.details.filter(
|
||||
(arrow) => arrow.x !== -30 && arrow.y !== -30
|
||||
).length < total
|
||||
? '2un'
|
||||
: ''
|
||||
}finish-tip.png`"
|
||||
:tipSrc="getResultTipSrc(practiseResult)"
|
||||
/>
|
||||
<canvas class="share-canvas" id="shareCanvas" type="2d"></canvas>
|
||||
</block>
|
||||
|
||||
@@ -328,8 +328,8 @@ onShow(async () => {
|
||||
<view class="battle-types-box">
|
||||
<view class="battle-types">
|
||||
<view class="first">
|
||||
<image src="../static/rank/battle-choose.png" mode="widthFix" />
|
||||
<image class="star" src="../static/rank/star.png" mode="widthFix" />
|
||||
<image src="https://static.shelingxingqiu.com/shootmini/static/rank/battle-choose.png" mode="widthFix" />
|
||||
<image class="star" src="https://static.shelingxingqiu.com/shootmini/static/rank/star.png" mode="widthFix" />
|
||||
</view>
|
||||
<image
|
||||
src="../static/rank/battle1v1.svg"
|
||||
|
||||
@@ -97,9 +97,9 @@ onBeforeUnmount(() => {
|
||||
class="back-to-game"
|
||||
@click="onClick"
|
||||
>
|
||||
<image src="../../../static/back-to-game-bg.png" mode="widthFix" />
|
||||
<image src="https://static.shelingxingqiu.com/shootmini/static/back-to-game-bg.png" mode="widthFix" />
|
||||
<block v-if="game.inBattle">
|
||||
<image src="../../../static/pk-icon.png" mode="widthFix" />
|
||||
<image src="https://static.shelingxingqiu.com/shootmini/static/pk-icon.png" mode="widthFix" />
|
||||
<text>返回进行中的对局</text>
|
||||
</block>
|
||||
<block v-else-if="game.roomID">
|
||||
|
||||
@@ -31,7 +31,7 @@ const normalRounds = computed(() => {
|
||||
<template>
|
||||
<view class="container">
|
||||
<view class="guide-row">
|
||||
<image src="../../../static/shooter.png" mode="widthFix" />
|
||||
<image src="https://static.shelingxingqiu.com/shootmini/static/shooter.png" mode="widthFix" />
|
||||
<view
|
||||
:style="{
|
||||
marginBottom: '10px',
|
||||
@@ -42,7 +42,7 @@ const normalRounds = computed(() => {
|
||||
</view>
|
||||
</view>
|
||||
<view>
|
||||
<image src="../../../static/battle-header-melee.png" mode="widthFix" />
|
||||
<image src="https://static.shelingxingqiu.com/shootmini/static/battle-header-melee.png" mode="widthFix" />
|
||||
<text>蓝队({{ bluePoints }})</text>
|
||||
<text>红队({{ redPoints }})</text>
|
||||
</view>
|
||||
|
||||
@@ -41,7 +41,7 @@ const isMember = (player = {}) => player.vip === true || player.sVip === true;
|
||||
<view class="container" :style="{ paddingTop: showHeader ? '5px' : '0' }">
|
||||
<image
|
||||
v-if="showHeader"
|
||||
:src="`../../../static/battle-header${players.length ? '-melee' : ''}.png`"
|
||||
:src="`https://static.shelingxingqiu.com/shootmini/static/battle-header${players.length ? '-melee' : ''}.png`"
|
||||
mode="widthFix"
|
||||
/>
|
||||
<view
|
||||
|
||||
@@ -531,7 +531,7 @@ onBeforeUnmount(() => {
|
||||
@impact="shakeTarget"
|
||||
@complete="completeShotEffect"
|
||||
/>
|
||||
<image src="../../../static/bow-target.png" mode="widthFix" />
|
||||
<image src="https://static.shelingxingqiu.com/shootmini/static/bow-target.png" mode="widthFix" />
|
||||
</view>
|
||||
<view class="footer">
|
||||
<PointSwitcher
|
||||
|
||||
@@ -12,13 +12,13 @@ defineProps({
|
||||
const bubbleTypes = [
|
||||
"../../../static/long-bubble.png",
|
||||
"../../../static/long-bubble-middle.png",
|
||||
"../../../static/long-bubble-tall.png",
|
||||
"https://static.shelingxingqiu.com/shootmini/static/long-bubble-tall.png",
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="container">
|
||||
<image src="../../../static/shooter.png" mode="widthFix" />
|
||||
<image src="https://static.shelingxingqiu.com/shootmini/static/shooter.png" mode="widthFix" />
|
||||
<view>
|
||||
<image
|
||||
v-if="!noBg"
|
||||
|
||||
@@ -27,22 +27,22 @@ const getContentHeight = () => {
|
||||
<view class="scale-in" :style="{ height: getContentHeight() }">
|
||||
<image
|
||||
v-if="mode === 'normal'"
|
||||
src="../../../static/screen-hint-bg.png"
|
||||
src="https://static.shelingxingqiu.com/shootmini/static/screen-hint-bg.png"
|
||||
mode="widthFix"
|
||||
/>
|
||||
<image
|
||||
v-if="mode === 'tall'"
|
||||
src="../../../static/coach-comment.png"
|
||||
src="https://static.shelingxingqiu.com/shootmini/static/coach-comment.png"
|
||||
mode="widthFix"
|
||||
/>
|
||||
<image
|
||||
v-if="mode === 'square'"
|
||||
src="../../../static/prompt-bg-square.png"
|
||||
src="https://static.shelingxingqiu.com/shootmini/static/prompt-bg-square.png"
|
||||
mode="widthFix"
|
||||
/>
|
||||
<image
|
||||
v-if="mode === 'small'"
|
||||
src="../../../static/finish-frame.png"
|
||||
src="https://static.shelingxingqiu.com/shootmini/static/finish-frame.png"
|
||||
mode="widthFix"
|
||||
/>
|
||||
<slot />
|
||||
|
||||
@@ -111,7 +111,7 @@ onBeforeUnmount(() => {
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="isBattle" class="ready-timer">
|
||||
<image src="../../../static/test-tip.png" mode="widthFix" />
|
||||
<image src="https://static.shelingxingqiu.com/shootmini/static/test-tip.png" mode="widthFix" />
|
||||
<view v-if="count >= 0">
|
||||
<text>具体正式比赛还有</text>
|
||||
<text>{{ count }}</text>
|
||||
|
||||
+1
-1
@@ -136,7 +136,7 @@ const buildVersion = typeof __BUILD_TIME__ !== 'undefined' ? __BUILD_TIME__ : ''
|
||||
<text>点</text>
|
||||
</UserItem>
|
||||
<view class="my-grow" @click="toMyGrowthPage">
|
||||
<image src="../static/my-grow.png" mode="widthFix" />
|
||||
<image src="https://static.shelingxingqiu.com/shootmini/static/my-grow.png" mode="widthFix" />
|
||||
</view>
|
||||
<UserItem title="关于我们" :onClick="toAboutUsPage" />
|
||||
<UserItem
|
||||
|
||||
Reference in New Issue
Block a user