Compare commits
14 Commits
a3fea0bb1f
...
select-tar
| Author | SHA1 | Date | |
|---|---|---|---|
| 8c48216a75 | |||
| c1ff0cedad | |||
| 56650793e8 | |||
| e8568ee6a8 | |||
|
|
1181a2133a | ||
|
|
b9bb1e6653 | ||
|
|
608de34dd3 | ||
|
|
88f1ef5d95 | ||
|
|
b0bf1880e4 | ||
|
|
812879d252 | ||
|
|
303e1830d3 | ||
|
|
61ff1af4c3 | ||
|
|
a3a9f7b351 | ||
|
|
4801833fa9 |
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"i18n-ally.localesPaths": []
|
||||||
|
}
|
||||||
492
src/App.vue
492
src/App.vue
@@ -1,256 +1,292 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { watch } from "vue";
|
import {
|
||||||
import { onShow, onHide } from "@dcloudio/uni-app";
|
watch
|
||||||
import websocket from "@/websocket";
|
} from "vue";
|
||||||
import { getDeviceBatteryAPI } from "@/apis";
|
import {
|
||||||
import useStore from "@/store";
|
onShow,
|
||||||
import { storeToRefs } from "pinia";
|
onHide
|
||||||
const store = useStore();
|
} from "@dcloudio/uni-app";
|
||||||
const { user } = storeToRefs(store);
|
import websocket from "@/websocket";
|
||||||
const { updateUser, updateOnline } = store;
|
import {
|
||||||
|
getDeviceBatteryAPI
|
||||||
|
} from "@/apis";
|
||||||
|
import useStore from "@/store";
|
||||||
|
import {
|
||||||
|
storeToRefs
|
||||||
|
} from "pinia";
|
||||||
|
import audioManager from "./audioManager";
|
||||||
|
const store = useStore();
|
||||||
|
const {
|
||||||
|
user
|
||||||
|
} = storeToRefs(store);
|
||||||
|
const {
|
||||||
|
updateUser,
|
||||||
|
updateOnline
|
||||||
|
} = store;
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => user.value.id,
|
() => user.value.id,
|
||||||
(newVal) => {
|
(newVal) => {
|
||||||
const token = uni.getStorageSync(
|
const token = uni.getStorageSync(
|
||||||
`${uni.getAccountInfoSync().miniProgram.envVersion}_token`
|
`${uni.getAccountInfoSync().miniProgram.envVersion}_token`
|
||||||
);
|
);
|
||||||
if (newVal && token) {
|
if (newVal && token) {
|
||||||
websocket.createWebSocket(token, (content) => {
|
websocket.createWebSocket(token, onShootWsMsg);
|
||||||
uni.$emit("socket-inbox", content);
|
}
|
||||||
});
|
if (!newVal) {
|
||||||
}
|
websocket.closeWebSocket();
|
||||||
if (!newVal) {
|
}
|
||||||
websocket.closeWebSocket();
|
}, {
|
||||||
}
|
deep: false, // 如果 user 是一个对象或数组,建议开启
|
||||||
},
|
immediate: false, // 若想在初始化时立即执行一次回调,可开启。
|
||||||
{
|
}
|
||||||
deep: false, // 如果 user 是一个对象或数组,建议开启
|
);
|
||||||
immediate: false, // 若想在初始化时立即执行一次回调,可开启。
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
function emitUpdateUser(value) {
|
function emitUpdateUser(value) {
|
||||||
updateUser(value);
|
updateUser(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function emitUpdateOnline() {
|
async function emitUpdateOnline() {
|
||||||
const data = await getDeviceBatteryAPI();
|
const data = await getDeviceBatteryAPI();
|
||||||
updateOnline(data.online);
|
updateOnline(data.online);
|
||||||
}
|
}
|
||||||
|
|
||||||
onShow(() => {
|
function onDeviceShoot() {
|
||||||
uni.$on("update-user", emitUpdateUser);
|
audioManager.play("射箭声音")
|
||||||
uni.$on("update-online", emitUpdateOnline);
|
}
|
||||||
const token = uni.getStorageSync(
|
|
||||||
`${uni.getAccountInfoSync().miniProgram.envVersion}_token`
|
|
||||||
);
|
|
||||||
if (user.value.id && token) {
|
|
||||||
console.log("回到前台,重新连接 websocket");
|
|
||||||
websocket.createWebSocket(token, (content) => {
|
|
||||||
uni.$emit("socket-inbox", content);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
onHide(() => {
|
function onShootWsMsg(content) {
|
||||||
uni.$off("update-user", emitUpdateUser);
|
if(content.type === 'shoot-trigger'){
|
||||||
uni.$off("update-online", emitUpdateOnline);
|
onDeviceShoot()
|
||||||
websocket.closeWebSocket();
|
}
|
||||||
});
|
uni.$emit("socket-inbox", content);
|
||||||
|
}
|
||||||
|
|
||||||
|
onShow(() => {
|
||||||
|
uni.$on("update-user", emitUpdateUser);
|
||||||
|
uni.$on("update-online", emitUpdateOnline);
|
||||||
|
const token = uni.getStorageSync(
|
||||||
|
`${uni.getAccountInfoSync().miniProgram.envVersion}_token`
|
||||||
|
);
|
||||||
|
if (user.value.id && token) {
|
||||||
|
console.log("回到前台,重新连接 websocket");
|
||||||
|
websocket.createWebSocket(token, onShootWsMsg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
onHide(() => {
|
||||||
|
uni.$off("update-user", emitUpdateUser);
|
||||||
|
uni.$off("update-online", emitUpdateOnline);
|
||||||
|
websocket.closeWebSocket();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
page {
|
page {
|
||||||
-webkit-touch-callout: none;
|
-webkit-touch-callout: none;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
background-color: #000;
|
background-color: #000;
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
button {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border: none;
|
border: none;
|
||||||
background: none;
|
background: none;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
outline: none;
|
outline: none;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
view::-webkit-scrollbar {
|
view::-webkit-scrollbar {
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 0;
|
height: 0;
|
||||||
color: transparent;
|
color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
button::after {
|
button::after {
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.guide-tips {
|
.guide-tips {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
}
|
}
|
||||||
.guide-tips > text:first-child {
|
|
||||||
color: #fed847;
|
|
||||||
}
|
|
||||||
.guide-tips > text:nth-child(2) {
|
|
||||||
font-size: 24rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadeInOut {
|
.guide-tips>text:first-child {
|
||||||
0% {
|
color: #fed847;
|
||||||
transform: translateY(20px);
|
}
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
30% {
|
|
||||||
transform: translateY(0);
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
80% {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.fade-in-out {
|
.guide-tips>text:nth-child(2) {
|
||||||
animation: fadeInOut 1.2s ease forwards;
|
font-size: 24rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes fadeOut {
|
@keyframes fadeInOut {
|
||||||
from {
|
0% {
|
||||||
transform: translateY(0);
|
transform: translateY(20px);
|
||||||
opacity: 1;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
to {
|
|
||||||
transform: translateY(20px);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.fade-out {
|
30% {
|
||||||
animation: fadeOut 0.3s ease forwards;
|
transform: translateY(0);
|
||||||
}
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes scaleIn {
|
80% {
|
||||||
from {
|
opacity: 1;
|
||||||
transform: scale(0);
|
}
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
transform: scale(1);
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.scale-in {
|
100% {
|
||||||
animation: scaleIn 0.3s ease-out forwards;
|
opacity: 0;
|
||||||
transform-origin: center center;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes scaleOut {
|
.fade-in-out {
|
||||||
from {
|
animation: fadeInOut 1.2s ease forwards;
|
||||||
transform: scale(1);
|
}
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
transform: scale(0);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.scale-out {
|
@keyframes fadeOut {
|
||||||
animation: scaleOut 0.3s ease-out forwards;
|
from {
|
||||||
transform-origin: center center;
|
transform: translateY(0);
|
||||||
}
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes rotate {
|
to {
|
||||||
from {
|
transform: translateY(20px);
|
||||||
transform: rotate(0deg);
|
opacity: 0;
|
||||||
}
|
}
|
||||||
to {
|
}
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes pumpIn {
|
.fade-out {
|
||||||
from {
|
animation: fadeOut 0.3s ease forwards;
|
||||||
transform: scale(2);
|
}
|
||||||
}
|
|
||||||
to {
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.pump-in {
|
@keyframes scaleIn {
|
||||||
animation: pumpIn 0.3s ease-out forwards;
|
from {
|
||||||
transform-origin: center center;
|
transform: scale(0);
|
||||||
}
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.share-canvas {
|
to {
|
||||||
width: 300px;
|
transform: scale(1);
|
||||||
height: 530px;
|
opacity: 1;
|
||||||
position: absolute;
|
}
|
||||||
top: -1000px;
|
}
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.truncate {
|
.scale-in {
|
||||||
white-space: nowrap;
|
animation: scaleIn 0.3s ease-out forwards;
|
||||||
overflow: hidden;
|
transform-origin: center center;
|
||||||
text-overflow: ellipsis;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.modal {
|
@keyframes scaleOut {
|
||||||
height: 100%;
|
from {
|
||||||
display: flex;
|
transform: scale(1);
|
||||||
flex-direction: column;
|
opacity: 1;
|
||||||
align-items: center;
|
}
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
.user-row {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
padding: 0 15px;
|
|
||||||
padding-top: 7px;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.half-time-tip {
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.half-time-tip > text:last-child {
|
|
||||||
margin-top: 20px;
|
|
||||||
color: #fff9;
|
|
||||||
}
|
|
||||||
.see-more {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
margin-top: 20rpx;
|
|
||||||
}
|
|
||||||
.see-more > text {
|
|
||||||
color: #39a8ff;
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
.see-more > image {
|
|
||||||
width: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@font-face {
|
to {
|
||||||
font-family: "DINCondensed";
|
transform: scale(0);
|
||||||
src: url("https://static.shelingxingqiu.com/font/DIN-Condensed-Bold-2.ttf")
|
opacity: 0;
|
||||||
format("truetype");
|
}
|
||||||
font-weight: 700;
|
}
|
||||||
font-style: normal;
|
|
||||||
font-display: swap;
|
.scale-out {
|
||||||
}
|
animation: scaleOut 0.3s ease-out forwards;
|
||||||
</style>
|
transform-origin: center center;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes rotate {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pumpIn {
|
||||||
|
from {
|
||||||
|
transform: scale(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.pump-in {
|
||||||
|
animation: pumpIn 0.3s ease-out forwards;
|
||||||
|
transform-origin: center center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.share-canvas {
|
||||||
|
width: 300px;
|
||||||
|
height: 530px;
|
||||||
|
position: absolute;
|
||||||
|
top: -1000px;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.truncate {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0 15px;
|
||||||
|
padding-top: 7px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.half-time-tip {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.half-time-tip>text:last-child {
|
||||||
|
margin-top: 20px;
|
||||||
|
color: #fff9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.see-more {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.see-more>text {
|
||||||
|
color: #39a8ff;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.see-more>image {
|
||||||
|
width: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "DINCondensed";
|
||||||
|
src: url("https://static.shelingxingqiu.com/font/DIN-Condensed-Bold-2.ttf") format("truetype");
|
||||||
|
font-weight: 700;
|
||||||
|
font-style: normal;
|
||||||
|
font-display: swap;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
113
src/apis.js
113
src/apis.js
@@ -6,8 +6,8 @@ try {
|
|||||||
|
|
||||||
switch (envVersion) {
|
switch (envVersion) {
|
||||||
case "develop": // 开发版
|
case "develop": // 开发版
|
||||||
// BASE_URL = "http://192.168.1.30:8000/api/shoot";
|
BASE_URL = "http://localhost:8000/api/shoot";
|
||||||
BASE_URL = "https://apitest.shelingxingqiu.com/api/shoot";
|
// BASE_URL = "https://apitest.shelingxingqiu.com/api/shoot";
|
||||||
break;
|
break;
|
||||||
case "trial": // 体验版
|
case "trial": // 体验版
|
||||||
BASE_URL = "https://apitest.shelingxingqiu.com/api/shoot";
|
BASE_URL = "https://apitest.shelingxingqiu.com/api/shoot";
|
||||||
@@ -196,10 +196,11 @@ export const getMyDevicesAPI = () => {
|
|||||||
return request("GET", "/user/device/getBindings");
|
return request("GET", "/user/device/getBindings");
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createPractiseAPI = (arrows, time) => {
|
export const createPractiseAPI = (arrows, time, target) => {
|
||||||
return request("POST", "/user/practice/create", {
|
return request("POST", "/user/practice/create", {
|
||||||
shootNumber: arrows,
|
shootNumber: arrows,
|
||||||
shootTime: time,
|
shootTime: time,
|
||||||
|
targetType: target*20,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -215,10 +216,11 @@ export const getPractiseAPI = async (id) => {
|
|||||||
return request("GET", `/user/practice/get?id=${id}`);
|
return request("GET", `/user/practice/get?id=${id}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createRoomAPI = (gameType, teamSize) => {
|
export const createRoomAPI = (gameType, teamSize, targetType) => {
|
||||||
return request("POST", "/user/createroom", {
|
return request("POST", "/user/createroom", {
|
||||||
gameType,
|
gameType,
|
||||||
teamSize,
|
teamSize,
|
||||||
|
targetType,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -270,78 +272,6 @@ export const readyGameAPI = (battleId) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getGameAPI = async (battleId) => {
|
|
||||||
const result = await request("POST", "/user/battle/detail", {
|
|
||||||
id: battleId,
|
|
||||||
});
|
|
||||||
if (!result.battleStats) return {};
|
|
||||||
const {
|
|
||||||
battleStats = {},
|
|
||||||
playerStats = {},
|
|
||||||
goldenRoundRecords = [],
|
|
||||||
} = result;
|
|
||||||
const data = {
|
|
||||||
id: battleId,
|
|
||||||
mode: battleStats.mode, // 1.几V几 2.大乱斗
|
|
||||||
gameMode: battleStats.gameMode, // 1.约战 2.排位
|
|
||||||
teamSize: battleStats.teamSize,
|
|
||||||
};
|
|
||||||
if (battleStats && battleStats.mode === 1) {
|
|
||||||
data.winner = battleStats.winner;
|
|
||||||
data.roundsData = {};
|
|
||||||
data.redPlayers = {};
|
|
||||||
data.bluePlayers = {};
|
|
||||||
data.mvps = [];
|
|
||||||
data.goldenRounds =
|
|
||||||
goldenRoundRecords && goldenRoundRecords.length ? goldenRoundRecords : [];
|
|
||||||
playerStats.forEach((item) => {
|
|
||||||
const { playerBattleStats = {}, roundRecords = [] } = item;
|
|
||||||
if (playerBattleStats.team === 0) {
|
|
||||||
data.redPlayers[playerBattleStats.playerId] = playerBattleStats;
|
|
||||||
}
|
|
||||||
if (playerBattleStats.team === 1) {
|
|
||||||
data.bluePlayers[playerBattleStats.playerId] = playerBattleStats;
|
|
||||||
}
|
|
||||||
if (playerBattleStats.mvp) {
|
|
||||||
data.mvps.push(playerBattleStats);
|
|
||||||
}
|
|
||||||
roundRecords.forEach((round) => {
|
|
||||||
data.roundsData[round.roundNumber] = {
|
|
||||||
...data.roundsData[round.roundNumber],
|
|
||||||
[round.playerId]: round.arrowHistory,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
|
||||||
const totalRounds = Object.keys(data.roundsData).length;
|
|
||||||
(goldenRoundRecords || []).forEach((item, index) => {
|
|
||||||
item.arrowHistory.forEach((arrow) => {
|
|
||||||
if (!data.roundsData[totalRounds + index + 1]) {
|
|
||||||
data.roundsData[totalRounds + index + 1] = {};
|
|
||||||
}
|
|
||||||
if (!data.roundsData[totalRounds + index + 1][arrow.playerId]) {
|
|
||||||
data.roundsData[totalRounds + index + 1][arrow.playerId] = [];
|
|
||||||
}
|
|
||||||
data.roundsData[totalRounds + index + 1][arrow.playerId].push(arrow);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
data.mvps.sort((a, b) => b.totalRings - a.totalRings);
|
|
||||||
}
|
|
||||||
if (battleStats && battleStats.mode === 2) {
|
|
||||||
data.players = [];
|
|
||||||
playerStats.forEach((item) => {
|
|
||||||
data.players.push({
|
|
||||||
...item.playerBattleStats,
|
|
||||||
arrowHistory: item.roundRecords[0].arrowHistory,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
data.players = data.players.sort((a, b) => b.totalScore - a.totalScore);
|
|
||||||
}
|
|
||||||
// console.log("game result:", result);
|
|
||||||
// console.log("format data:", data);
|
|
||||||
return data;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const simulShootAPI = (device_id, x, y) => {
|
export const simulShootAPI = (device_id, x, y) => {
|
||||||
const data = {
|
const data = {
|
||||||
device_id,
|
device_id,
|
||||||
@@ -354,39 +284,12 @@ export const simulShootAPI = (device_id, x, y) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const getBattleListAPI = async (page, battleType) => {
|
export const getBattleListAPI = async (page, battleType) => {
|
||||||
const data = [];
|
|
||||||
const result = await request("POST", "/user/battle/details/list", {
|
const result = await request("POST", "/user/battle/details/list", {
|
||||||
page,
|
page,
|
||||||
|
pageSize: 10,
|
||||||
battleType,
|
battleType,
|
||||||
modeType: 0,
|
|
||||||
});
|
});
|
||||||
(result.Battles || []).forEach((item) => {
|
return result.list;
|
||||||
let name = "";
|
|
||||||
if (item.battleStats.mode === 1) {
|
|
||||||
name = `${item.playerStats.length / 2}V${item.playerStats.length / 2}`;
|
|
||||||
}
|
|
||||||
if (item.battleStats.mode === 2) {
|
|
||||||
name = `${item.playerStats.length}人大乱斗`;
|
|
||||||
}
|
|
||||||
data.push({
|
|
||||||
name,
|
|
||||||
battleId: item.battleStats.battleId,
|
|
||||||
mode: item.battleStats.mode,
|
|
||||||
createdAt: item.battleStats.createdAt,
|
|
||||||
gameEndAt: item.battleStats.gameEndAt,
|
|
||||||
winner: item.battleStats.winner,
|
|
||||||
players: item.playerStats
|
|
||||||
.map((p) => p.playerBattleStats)
|
|
||||||
.sort((a, b) => b.totalScore - a.totalScore),
|
|
||||||
redPlayers: item.playerStats
|
|
||||||
.filter((p) => p.playerBattleStats.team === 0)
|
|
||||||
.map((p) => p.playerBattleStats),
|
|
||||||
bluePlayers: item.playerStats
|
|
||||||
.filter((p) => p.playerBattleStats.team === 1)
|
|
||||||
.map((p) => p.playerBattleStats),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return data;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getRankListAPI = () => {
|
export const getRankListAPI = () => {
|
||||||
|
|||||||
@@ -40,26 +40,26 @@ export const audioFils = {
|
|||||||
未上靶:
|
未上靶:
|
||||||
"https://static.shelingxingqiu.com/attachment/2025-11-12/de6n45o3tsm1v4unam.mp3",
|
"https://static.shelingxingqiu.com/attachment/2025-11-12/de6n45o3tsm1v4unam.mp3",
|
||||||
"1环":
|
"1环":
|
||||||
"https://static.shelingxingqiu.com/attachment/2025-09-17/dcutxin1aq7gxjih5l.mp3",
|
"https://static.shelingxingqiu.com/shootaudio/v3/1.mp3",
|
||||||
"2环":
|
"2环":
|
||||||
"https://static.shelingxingqiu.com/attachment/2025-09-17/dcutxin64tdgx2s4at.mp3",
|
"https://static.shelingxingqiu.com/shootaudio/v3/2.mp3",
|
||||||
"3环":
|
"3环":
|
||||||
"https://static.shelingxingqiu.com/attachment/2025-09-17/dcutxinlmf87vt8z65.mp3",
|
"https://static.shelingxingqiu.com/shootaudio/v3/3.mp3",
|
||||||
"4环":
|
"4环":
|
||||||
"https://static.shelingxingqiu.com/attachment/2025-09-17/dcutxinniv97sx0q9u.mp3",
|
"https://static.shelingxingqiu.com/shootaudio/v3/4.mp3",
|
||||||
"5环":
|
"5环":
|
||||||
"https://static.shelingxingqiu.com/attachment/2025-09-17/dcutxin7j01kknpb7k.mp3",
|
"https://static.shelingxingqiu.com/shootaudio/v3/5.mp3",
|
||||||
"6环":
|
"6环":
|
||||||
"https://static.shelingxingqiu.com/attachment/2025-09-17/dcutxin4syy1015rtq.mp3",
|
"https://static.shelingxingqiu.com/shootaudio/v3/6.mp3",
|
||||||
"7环":
|
"7环":
|
||||||
"https://static.shelingxingqiu.com/attachment/2025-09-17/dcutxin3iz3dvmjdai.mp3",
|
"https://static.shelingxingqiu.com/shootaudio/v3/7.mp3",
|
||||||
"8环":
|
"8环":
|
||||||
"https://static.shelingxingqiu.com/attachment/2025-09-17/dcutxinnjd42lhpfiw.mp3",
|
"https://static.shelingxingqiu.com/shootaudio/v3/8.mp3",
|
||||||
"9环":
|
"9环":
|
||||||
"https://static.shelingxingqiu.com/attachment/2025-09-17/dcutxin69nj1xh7yfz.mp3",
|
"https://static.shelingxingqiu.com/shootaudio/v3/9.mp3",
|
||||||
"10环":
|
"10环":
|
||||||
"https://static.shelingxingqiu.com/attachment/2025-09-17/dcutxinnvsx0tt7ksa.mp3",
|
"https://static.shelingxingqiu.com/shootaudio/v3/10.mp3",
|
||||||
X环: "https://static.shelingxingqiu.com/attachment/2026-02-09/dga8puwekpe2gmtbu4.mp3",
|
X环: "https://static.shelingxingqiu.com/shootaudio/v4/v4/X%E7%8E%AF.mp3",
|
||||||
向上调整:
|
向上调整:
|
||||||
"https://static.shelingxingqiu.com/attachment/2025-11-12/de6ellf5pfvu3l8dhr.mp3",
|
"https://static.shelingxingqiu.com/attachment/2025-11-12/de6ellf5pfvu3l8dhr.mp3",
|
||||||
向右上调整:
|
向右上调整:
|
||||||
@@ -80,6 +80,10 @@ export const audioFils = {
|
|||||||
"https://static.shelingxingqiu.com/attachment/2025-11-13/de7kzzllq0futwynso.mp3",
|
"https://static.shelingxingqiu.com/attachment/2025-11-13/de7kzzllq0futwynso.mp3",
|
||||||
练习开始:
|
练习开始:
|
||||||
"https://static.shelingxingqiu.com/attachment/2025-11-14/de88w0lmmt43nnfmoi.mp3",
|
"https://static.shelingxingqiu.com/attachment/2025-11-14/de88w0lmmt43nnfmoi.mp3",
|
||||||
|
射箭声音:
|
||||||
|
"https://static.shelingxingqiu.com/shootaudio/v4/v4/%E7%AE%AD%E9%A3%9E%E8%A1%8C.mp3",
|
||||||
|
命中:
|
||||||
|
"https://static.shelingxingqiu.com/shootaudio/%E5%91%BD%E4%B8%AD.mp3"
|
||||||
};
|
};
|
||||||
|
|
||||||
// 版本控制日志函数
|
// 版本控制日志函数
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { formatTimestamp } from "@/util";
|
||||||
|
|
||||||
const loadImage = (src) =>
|
const loadImage = (src) =>
|
||||||
new Promise((resolve, reject) => {
|
new Promise((resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
@@ -635,7 +637,7 @@ export function renderScores(ctx, arrows = [], bgImg) {
|
|||||||
}
|
}
|
||||||
renderText(
|
renderText(
|
||||||
ctx,
|
ctx,
|
||||||
item.ring,
|
item.ringX ? "X" : item.ring,
|
||||||
18,
|
18,
|
||||||
"#fed847",
|
"#fed847",
|
||||||
29.5 + (i % 9) * 30,
|
29.5 + (i % 9) * 30,
|
||||||
@@ -657,7 +659,7 @@ export function renderScores(ctx, arrows = [], bgImg) {
|
|||||||
}
|
}
|
||||||
renderText(
|
renderText(
|
||||||
ctx,
|
ctx,
|
||||||
item.ring,
|
item.ringX ? "X" : item.ring,
|
||||||
23,
|
23,
|
||||||
"#fed847",
|
"#fed847",
|
||||||
43 + rowIndex * 42,
|
43 + rowIndex * 42,
|
||||||
@@ -737,9 +739,7 @@ export async function sharePractiseData(canvasId, type, user, data) {
|
|||||||
|
|
||||||
let subTitle = "正式开启弓箭手之路";
|
let subTitle = "正式开启弓箭手之路";
|
||||||
if (type > 1) {
|
if (type > 1) {
|
||||||
subTitle = `今日弓箭练习打卡 ${data.createdAt
|
subTitle = `今日弓箭练习打卡 ${formatTimestamp(data.startTime)}`;
|
||||||
.split(" ")[0]
|
|
||||||
.replaceAll("-", ".")}`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.drawImage(titleImg, (width - 160) / 2, 160, 160, 40);
|
ctx.drawImage(titleImg, (width - 160) / 2, 160, 160, 40);
|
||||||
@@ -748,14 +748,14 @@ export async function sharePractiseData(canvasId, type, user, data) {
|
|||||||
renderText(ctx, subTitle, 18, "#fff", width / 2, 224, "center");
|
renderText(ctx, subTitle, 18, "#fff", width / 2, 224, "center");
|
||||||
|
|
||||||
renderText(ctx, "共", 14, "#fff", 122, 300);
|
renderText(ctx, "共", 14, "#fff", 122, 300);
|
||||||
const totalRing = data.arrows.reduce((last, next) => last + next.ring, 0);
|
const totalRing = data.details.reduce((last, next) => last + next.ring, 0);
|
||||||
renderText(ctx, totalRing, 14, "#fed847", 148, 300, "center");
|
renderText(ctx, totalRing, 14, "#fed847", 148, 300, "center");
|
||||||
renderText(ctx, "环", 14, "#fff", 161, 300);
|
renderText(ctx, "环", 14, "#fff", 161, 300);
|
||||||
|
|
||||||
renderLine(ctx, 77);
|
renderLine(ctx, 77);
|
||||||
renderLine(ctx, 185);
|
renderLine(ctx, 185);
|
||||||
|
|
||||||
renderScores(ctx, data.arrows, scoreBgImg);
|
renderScores(ctx, data.details, scoreBgImg);
|
||||||
|
|
||||||
ctx.drawImage(qrCodeImg, width * 0.06, height * 0.87, 52, 52);
|
ctx.drawImage(qrCodeImg, width * 0.06, height * 0.87, 52, 52);
|
||||||
renderText(ctx, "射灵平台", 12, "#fff", width * 0.26, height * 0.9);
|
renderText(ctx, "射灵平台", 12, "#fff", width * 0.26, height * 0.9);
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ defineProps({
|
|||||||
<text class="player-name">{{ player.name }}</text>
|
<text class="player-name">{{ player.name }}</text>
|
||||||
</view>
|
</view>
|
||||||
<image
|
<image
|
||||||
v-if="winner === 0"
|
v-if="winner === 2"
|
||||||
src="../static/winner-badge.png"
|
src="../static/winner-badge.png"
|
||||||
mode="widthFix"
|
mode="widthFix"
|
||||||
class="right-winner-badge"
|
class="right-winner-badge"
|
||||||
|
|||||||
@@ -49,16 +49,16 @@ const props = defineProps({
|
|||||||
<view class="desc">
|
<view class="desc">
|
||||||
<text>{{ arrows.length }}</text>
|
<text>{{ arrows.length }}</text>
|
||||||
<text>支箭,共</text>
|
<text>支箭,共</text>
|
||||||
<text>{{ arrows.reduce((a, b) => a + b.ring, 0) }}</text>
|
<text>{{ arrows.reduce((a, b) => a + (b.ring || 0), 0) }}</text>
|
||||||
<text>环</text>
|
<text>环</text>
|
||||||
</view>
|
</view>
|
||||||
<ScorePanel
|
<ScorePanel
|
||||||
:completeEffect="false"
|
:completeEffect="false"
|
||||||
:rowCount="arrows.length === 12 ? 6 : 9"
|
:rowCount="total === 12 ? 6 : 9"
|
||||||
:total="total"
|
:total="total"
|
||||||
:arrows="arrows"
|
:arrows="arrows"
|
||||||
:margin="arrows.length === 12 ? 4 : 1"
|
:margin="total === 12 ? 4 : 1"
|
||||||
:fontSize="arrows.length === 12 ? 25 : 22"
|
:fontSize="total === 12 ? 25 : 22"
|
||||||
/>
|
/>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ const props = defineProps({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const battleMode = ref(1);
|
const battleMode = ref(1);
|
||||||
|
const targetMode = ref(1);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const roomNumber = ref("");
|
const roomNumber = ref("");
|
||||||
|
|
||||||
@@ -35,13 +36,14 @@ const createRoom = debounce(async () => {
|
|||||||
try {
|
try {
|
||||||
const result = await createRoomAPI(
|
const result = await createRoomAPI(
|
||||||
battleMode.value === 2 ? 2 : 1,
|
battleMode.value === 2 ? 2 : 1,
|
||||||
battleMode.value === 2 ? 10 : size
|
battleMode.value === 2 ? 10 : size,
|
||||||
|
targetMode.value*20,
|
||||||
);
|
);
|
||||||
if (result.number) {
|
if (result.number) {
|
||||||
props.onConfirm();
|
props.onConfirm();
|
||||||
await joinRoomAPI(result.number);
|
await joinRoomAPI(result.number);
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: "/pages/battle-room?roomNumber=" + result.number,
|
url: "/pages/battle-room?roomNumber=" + result.number + "&target=" + targetMode.value,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -53,7 +55,11 @@ const createRoom = debounce(async () => {
|
|||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<view class="container">
|
<view class="container">
|
||||||
<image src="../static/choose-battle-mode.png" mode="widthFix" />
|
<view class="target-options-header">
|
||||||
|
<view class="target-options-header-line-left"></view>
|
||||||
|
<image class="target-options-header-title-img" src="../static/choose-battle-mode.png" mode="widthFix" />
|
||||||
|
<view class="target-options-header-line-right"></view>
|
||||||
|
</view>
|
||||||
<view class="create-options">
|
<view class="create-options">
|
||||||
<view
|
<view
|
||||||
:class="{ 'battle-btn': true, 'battle-choosen': battleMode === 1 }"
|
:class="{ 'battle-btn': true, 'battle-choosen': battleMode === 1 }"
|
||||||
@@ -80,6 +86,25 @@ const createRoom = debounce(async () => {
|
|||||||
<text>乱斗模式(3-10人)</text>
|
<text>乱斗模式(3-10人)</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<view class="target-options-header">
|
||||||
|
<view class="target-options-header-line-left"></view>
|
||||||
|
<view class="target-options-header-title">选择靶纸</view>
|
||||||
|
<view class="target-options-header-line-right"></view>
|
||||||
|
</view>
|
||||||
|
<view class="target-options">
|
||||||
|
<view
|
||||||
|
:class="{ 'battle-btn': true, 'battle-choosen': targetMode === 1 }"
|
||||||
|
@click="() => (targetMode = 1)"
|
||||||
|
>
|
||||||
|
<text>20厘米全环靶</text>
|
||||||
|
</view>
|
||||||
|
<view
|
||||||
|
:class="{ 'battle-btn': true, 'battle-choosen': targetMode === 2 }"
|
||||||
|
@click="() => (targetMode = 2)"
|
||||||
|
>
|
||||||
|
<text>40厘米全环靶</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
<SButton :onClick="createRoom">创建房间</SButton>
|
<SButton :onClick="createRoom">创建房间</SButton>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
@@ -91,6 +116,7 @@ const createRoom = debounce(async () => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
padding-top: 44rpx;
|
||||||
}
|
}
|
||||||
.container > image:first-child {
|
.container > image:first-child {
|
||||||
width: 45%;
|
width: 45%;
|
||||||
@@ -105,6 +131,50 @@ const createRoom = debounce(async () => {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
.target-options-header{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
}
|
||||||
|
.target-options-header-title-img{
|
||||||
|
width: 196rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
}
|
||||||
|
.target-options-header-title{
|
||||||
|
width: 112rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
font-family: PingFang SC, PingFang SC;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 28rpx;
|
||||||
|
text-align: center;
|
||||||
|
font-style: normal;
|
||||||
|
text-transform: none;
|
||||||
|
color: #FFEFBA;
|
||||||
|
margin: 0 18rpx;
|
||||||
|
}
|
||||||
|
.target-options-header-line-left{
|
||||||
|
width: 214rpx;
|
||||||
|
height: 0rpx;
|
||||||
|
border-radius: 0rpx 0rpx 0rpx 0rpx;
|
||||||
|
border: 1rpx solid;
|
||||||
|
border-image: linear-gradient(90deg, rgba(133, 119, 96, 0), rgba(133, 119, 96, 1)) 1 1;
|
||||||
|
}
|
||||||
|
.target-options-header-line-right{
|
||||||
|
width: 214rpx;
|
||||||
|
height: 0rpx;
|
||||||
|
border-radius: 0rpx 0rpx 0rpx 0rpx;
|
||||||
|
border: 1rpx solid;
|
||||||
|
border-image: linear-gradient(90deg, rgba(133, 119, 96, 1), rgba(133, 119, 96, 0)) 1 1;
|
||||||
|
}
|
||||||
|
.target-options {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0 10px;
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
justify-content: center;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
.battle-btn {
|
.battle-btn {
|
||||||
width: 45%;
|
width: 45%;
|
||||||
height: 55px;
|
height: 55px;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, watch, onMounted, onBeforeUnmount } from "vue";
|
import { ref, watch, onMounted, onBeforeUnmount } from "vue";
|
||||||
import audioManager from "@/audioManager";
|
import audioManager from "@/audioManager";
|
||||||
import { MESSAGETYPES, MESSAGETYPESV2 } from "@/constants";
|
import { MESSAGETYPESV2 } from "@/constants";
|
||||||
import { getDirectionText } from "@/util";
|
import { getDirectionText } from "@/util";
|
||||||
|
|
||||||
import useStore from "@/store";
|
import useStore from "@/store";
|
||||||
@@ -55,11 +55,9 @@ async function onReceiveMessage(message) {
|
|||||||
totalShot.value = mode === 1 ? 3 : 2;
|
totalShot.value = mode === 1 ? 3 : 2;
|
||||||
currentRoundEnded.value = true;
|
currentRoundEnded.value = true;
|
||||||
audioManager.play("比赛开始");
|
audioManager.play("比赛开始");
|
||||||
}
|
} else if (type === MESSAGETYPESV2.BattleEnd) {
|
||||||
if (type === MESSAGETYPESV2.BattleEnd) {
|
|
||||||
audioManager.play("比赛结束");
|
audioManager.play("比赛结束");
|
||||||
}
|
} else if (type === MESSAGETYPESV2.ShootResult) {
|
||||||
if (type === MESSAGETYPESV2.ShootResult) {
|
|
||||||
if (melee.value && current.playerId !== user.value.id) return;
|
if (melee.value && current.playerId !== user.value.id) return;
|
||||||
if (current.playerId === user.value.id) currentShot.value++;
|
if (current.playerId === user.value.id) currentShot.value++;
|
||||||
if (message.shootData) {
|
if (message.shootData) {
|
||||||
@@ -73,11 +71,16 @@ async function onReceiveMessage(message) {
|
|||||||
key.push(`向${getDirectionText(shootData.angle)}调整`);
|
key.push(`向${getDirectionText(shootData.angle)}调整`);
|
||||||
audioManager.play(key, false);
|
audioManager.play(key, false);
|
||||||
}
|
}
|
||||||
}
|
} else if (type === MESSAGETYPESV2.NewRound) {
|
||||||
if (type === MESSAGETYPESV2.NewRound) {
|
|
||||||
currentShot.value = 0;
|
currentShot.value = 0;
|
||||||
currentRound.value = current.round;
|
currentRound.value = current.round;
|
||||||
currentRoundEnded.value = true;
|
currentRoundEnded.value = true;
|
||||||
|
} else if (type === MESSAGETYPESV2.InvalidShot) {
|
||||||
|
uni.showToast({
|
||||||
|
title: "距离不足,无效",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
audioManager.play("射击无效");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,137 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
defineProps({
|
|
||||||
avatar: {
|
|
||||||
type: String,
|
|
||||||
default: "",
|
|
||||||
},
|
|
||||||
blueTeam: {
|
|
||||||
type: Array,
|
|
||||||
default: () => [],
|
|
||||||
},
|
|
||||||
redTeam: {
|
|
||||||
type: Array,
|
|
||||||
default: () => [],
|
|
||||||
},
|
|
||||||
currentShooterId: {
|
|
||||||
type: Number,
|
|
||||||
default: 0,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<view class="container">
|
|
||||||
<image v-if="avatar" class="avatar" :src="avatar" mode="widthFix" />
|
|
||||||
<view
|
|
||||||
v-if="blueTeam.length && redTeam.length"
|
|
||||||
:style="{ height: 20 + blueTeam.length * 20 + 'px' }"
|
|
||||||
>
|
|
||||||
<view
|
|
||||||
v-for="(player, index) in blueTeam"
|
|
||||||
:key="index"
|
|
||||||
:style="{
|
|
||||||
top: index * 20 + 'px',
|
|
||||||
zIndex: blueTeam.length - index,
|
|
||||||
left: 0,
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<image
|
|
||||||
class="avatar"
|
|
||||||
:src="player.avatar || '../static/user-icon.png'"
|
|
||||||
mode="widthFix"
|
|
||||||
:style="{
|
|
||||||
borderColor: currentShooterId === player.id ? '#5fadff' : '#fff',
|
|
||||||
}"
|
|
||||||
/>
|
|
||||||
<text
|
|
||||||
:style="{
|
|
||||||
color: currentShooterId === player.id ? '#5fadff' : '#fff',
|
|
||||||
fontSize: currentShooterId === player.id ? 16 : 12 + 'px',
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
{{ player.name }}
|
|
||||||
</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view
|
|
||||||
v-if="!avatar"
|
|
||||||
:style="{
|
|
||||||
height: 20 + redTeam.length * 20 + 'px',
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<view
|
|
||||||
v-for="(player, index) in redTeam"
|
|
||||||
:key="index"
|
|
||||||
:style="{
|
|
||||||
top: index * 20 + 'px',
|
|
||||||
zIndex: redTeam.length - index,
|
|
||||||
right: 0,
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<text
|
|
||||||
:style="{
|
|
||||||
color: currentShooterId === player.id ? '#ff6060' : '#fff',
|
|
||||||
fontSize: currentShooterId === player.id ? 16 : 12 + 'px',
|
|
||||||
textAlign: 'right',
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
{{ player.name }}
|
|
||||||
</text>
|
|
||||||
<image
|
|
||||||
class="avatar"
|
|
||||||
:src="player.avatar || '../static/user-icon.png'"
|
|
||||||
mode="widthFix"
|
|
||||||
:style="{
|
|
||||||
borderColor: currentShooterId === player.id ? '#ff6060' : '#fff',
|
|
||||||
}"
|
|
||||||
/>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.container {
|
|
||||||
width: calc(100% - 30px);
|
|
||||||
margin: 0 15px;
|
|
||||||
margin-top: 5px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: flex-start;
|
|
||||||
}
|
|
||||||
.container > view {
|
|
||||||
width: 50%;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.container > view > view {
|
|
||||||
position: absolute;
|
|
||||||
top: -20px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
transition: all 0.3s linear;
|
|
||||||
}
|
|
||||||
.container > view > view > text {
|
|
||||||
margin: 0 10px;
|
|
||||||
overflow: hidden;
|
|
||||||
width: 120px;
|
|
||||||
transition: all 0.3s linear;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
.avatar {
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
min-width: 40px;
|
|
||||||
min-height: 40px;
|
|
||||||
border: 1px solid #fff;
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
.red-avatar {
|
|
||||||
border: 1px solid #ff6060;
|
|
||||||
}
|
|
||||||
.blue-avatar {
|
|
||||||
border: 1px solid #5fadff;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -88,6 +88,7 @@ watch(
|
|||||||
transform: translateY(100%);
|
transform: translateY(100%);
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
background-color: #372E1D;
|
||||||
}
|
}
|
||||||
.modal-content > image:first-child {
|
.modal-content > image:first-child {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@@ -56,16 +56,20 @@ onMounted(() => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const validArrows = computed(() => {
|
|
||||||
return (props.result.details || []).filter(
|
|
||||||
(arrow) => arrow.x !== -30 && arrow.y !== -30
|
|
||||||
).length;
|
|
||||||
});
|
|
||||||
|
|
||||||
const getRing = (arrow) => {
|
const getRing = (arrow) => {
|
||||||
if (arrow.ringX) return "X";
|
if (arrow.ringX) return "X";
|
||||||
return arrow.ring ? arrow.ring + "环" : "-";
|
return arrow.ring ? arrow.ring : "-";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const arrows = computed(() => {
|
||||||
|
const data = new Array(props.total).fill({ ring: 0 });
|
||||||
|
(props.result.details || []).forEach((arrow, index) => {
|
||||||
|
data[index] = arrow;
|
||||||
|
});
|
||||||
|
return data;
|
||||||
|
});
|
||||||
|
|
||||||
|
const validArrows = computed(() => arrows.value.filter((a) => !!a.ring).length);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -96,8 +100,8 @@ const getRing = (arrow) => {
|
|||||||
</view>
|
</view>
|
||||||
<view :style="{ gridTemplateColumns: `repeat(${rowCount}, 1fr)` }">
|
<view :style="{ gridTemplateColumns: `repeat(${rowCount}, 1fr)` }">
|
||||||
<view v-for="(_, index) in new Array(total).fill(0)" :key="index">
|
<view v-for="(_, index) in new Array(total).fill(0)" :key="index">
|
||||||
{{ getRing(result.details[index])
|
{{ getRing(arrows[index])
|
||||||
}}<text v-if="getRing(result.details[index]) !== '-'">环</text>
|
}}<text v-if="getRing(arrows[index]) !== '-'">环</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view>
|
<view>
|
||||||
@@ -160,7 +164,7 @@ const getRing = (arrow) => {
|
|||||||
</view>
|
</view>
|
||||||
</ScreenHint>
|
</ScreenHint>
|
||||||
<BowData
|
<BowData
|
||||||
:total="result.details.length"
|
:total="arrows.length"
|
||||||
:arrows="result.details"
|
:arrows="result.details"
|
||||||
:show="showBowData"
|
:show="showBowData"
|
||||||
:onClose="() => (showBowData = false)"
|
:onClose="() => (showBowData = false)"
|
||||||
|
|||||||
@@ -143,6 +143,12 @@ async function onReceiveMessage(msg) {
|
|||||||
} else if (msg.type === MESSAGETYPESV2.HalfRest) {
|
} else if (msg.type === MESSAGETYPESV2.HalfRest) {
|
||||||
halfTime.value = true;
|
halfTime.value = true;
|
||||||
audioManager.play("中场休息");
|
audioManager.play("中场休息");
|
||||||
|
} else if (msg.type === MESSAGETYPESV2.InvalidShot) {
|
||||||
|
uni.showToast({
|
||||||
|
title: "距离不足,无效",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
audioManager.play("射击无效");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -87,28 +87,34 @@ const handleLogin = async () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
const wxResult = await wxLogin();
|
try {
|
||||||
const fileManager = uni.getFileSystemManager();
|
const wxResult = await wxLogin();
|
||||||
const avatarBase64 = fileManager.readFileSync(avatarUrl.value, "base64");
|
const fileManager = uni.getFileSystemManager();
|
||||||
const base64Url = `data:image/png;base64,${avatarBase64}`;
|
const avatarBase64 = fileManager.readFileSync(avatarUrl.value, "base64");
|
||||||
const result = await loginAPI(
|
const base64Url = `data:image/png;base64,${avatarBase64}`;
|
||||||
phone.value,
|
const result = await loginAPI(
|
||||||
nickName.value,
|
phone.value,
|
||||||
base64Url,
|
nickName.value,
|
||||||
wxResult.code
|
base64Url,
|
||||||
);
|
wxResult.code
|
||||||
const data = await getHomeData();
|
);
|
||||||
if (data.user) updateUser(data.user);
|
const data = await getHomeData();
|
||||||
const devices = await getMyDevicesAPI();
|
if (data.user) updateUser(data.user);
|
||||||
if (devices.bindings && devices.bindings.length) {
|
const devices = await getMyDevicesAPI();
|
||||||
updateDevice(devices.bindings[0].deviceId, devices.bindings[0].deviceName);
|
if (devices.bindings && devices.bindings.length) {
|
||||||
try {
|
updateDevice(
|
||||||
|
devices.bindings[0].deviceId,
|
||||||
|
devices.bindings[0].deviceName
|
||||||
|
);
|
||||||
const data = await getDeviceBatteryAPI();
|
const data = await getDeviceBatteryAPI();
|
||||||
updateOnline(data.online);
|
updateOnline(data.online);
|
||||||
} catch (error) {}
|
}
|
||||||
|
props.onClose();
|
||||||
|
} catch (error) {
|
||||||
|
console.log("login error", error);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
}
|
}
|
||||||
loading.value = false;
|
|
||||||
props.onClose();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const openServiceLink = () => {
|
const openServiceLink = () => {
|
||||||
|
|||||||
197
src/components/TargetPicker.vue
Normal file
197
src/components/TargetPicker.vue
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref, watch } from "vue";
|
||||||
|
import SButton from "@/components/SButton.vue";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
show: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
onClose: {
|
||||||
|
type: Function,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
onConfirm: {
|
||||||
|
type: Function,
|
||||||
|
default: () => {},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const selectedTarget = ref(2);
|
||||||
|
const showContainer = ref(false);
|
||||||
|
const showContent = ref(false);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.show,
|
||||||
|
(newValue) => {
|
||||||
|
if (newValue) {
|
||||||
|
showContainer.value = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
showContent.value = true;
|
||||||
|
}, 100);
|
||||||
|
} else {
|
||||||
|
showContent.value = false;
|
||||||
|
setTimeout(() => {
|
||||||
|
showContainer.value = false;
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleConfirm = () => {
|
||||||
|
props.onConfirm(selectedTarget.value);
|
||||||
|
props.onClose();
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<view
|
||||||
|
class="container"
|
||||||
|
v-if="showContainer"
|
||||||
|
:class="{ 'container-show': showContent }"
|
||||||
|
@click="onClose"
|
||||||
|
>
|
||||||
|
<view
|
||||||
|
class="modal-content"
|
||||||
|
:class="{ 'modal-show': showContent }"
|
||||||
|
@click.stop=""
|
||||||
|
>
|
||||||
|
<view class="header">
|
||||||
|
<view class="header-title">
|
||||||
|
<view class="header-title-line-left"></view>
|
||||||
|
<text>选择靶型</text>
|
||||||
|
<view class="header-title-line-right"></view>
|
||||||
|
</view>
|
||||||
|
<view class="close-btn" @click="onClose">
|
||||||
|
<image src="../static/close-yellow.png" mode="widthFix" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="target-options">
|
||||||
|
<view
|
||||||
|
:class="{ 'target-btn': true, 'target-choosen': selectedTarget === 1 }"
|
||||||
|
@click="() => (selectedTarget = 1)"
|
||||||
|
>
|
||||||
|
<text>20厘米全环靶</text>
|
||||||
|
</view>
|
||||||
|
<view style="width: 30rpx"></view>
|
||||||
|
<view
|
||||||
|
:class="{ 'target-btn': true, 'target-choosen': selectedTarget === 2 }"
|
||||||
|
@click="() => (selectedTarget = 2)"
|
||||||
|
>
|
||||||
|
<text>40厘米全环靶</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<SButton width="694rpx" :onClick="handleConfirm">确定</SButton>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.container {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
background-color: #00000099;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
opacity: 0;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
z-index: 999;
|
||||||
|
}
|
||||||
|
.container-show {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
.modal-content {
|
||||||
|
width: 100%;
|
||||||
|
transform: translateY(100%);
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
background: url("https://static.shelingxingqiu.com/attachment/2025-12-04/dep11770wzxg6o2alo.png")
|
||||||
|
no-repeat center top;
|
||||||
|
background-size: 100% auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding-bottom: 68rpx;
|
||||||
|
padding-top: 44rpx;
|
||||||
|
}
|
||||||
|
.modal-show {
|
||||||
|
transform: translateY(0%);
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 44rpx;
|
||||||
|
}
|
||||||
|
.header-title{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.header-title text{
|
||||||
|
width: 196rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
font-family: PingFang SC, PingFang SC;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 28rpx;
|
||||||
|
text-align: center;
|
||||||
|
font-style: normal;
|
||||||
|
text-transform: none;
|
||||||
|
color: #FFEFBA;
|
||||||
|
}
|
||||||
|
.header-title-line-left{
|
||||||
|
width: 214rpx;
|
||||||
|
height: 0rpx;
|
||||||
|
border-radius: 0rpx 0rpx 0rpx 0rpx;
|
||||||
|
border: 1rpx solid;
|
||||||
|
border-image: linear-gradient(90deg, rgba(133, 119, 96, 1), rgba(133, 119, 96, 0)) 1 1;
|
||||||
|
}
|
||||||
|
.header-title-line-right{
|
||||||
|
width: 214rpx;
|
||||||
|
height: 0rpx;
|
||||||
|
border-radius: 0rpx 0rpx 0rpx 0rpx;
|
||||||
|
border: 1rpx solid;
|
||||||
|
border-image: linear-gradient(90deg, rgba(133, 119, 96, 1), rgba(133, 119, 96, 0)) 1 1;
|
||||||
|
}
|
||||||
|
.close-btn {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: -10px;
|
||||||
|
}
|
||||||
|
.close-btn > image {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
.target-options {
|
||||||
|
width: 750rpx;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
margin-bottom: 38rpx;
|
||||||
|
}
|
||||||
|
.target-btn {
|
||||||
|
width: 332rpx;
|
||||||
|
height: 92rpx;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 2rpx solid #fff3;
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: #fff;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.target-choosen {
|
||||||
|
color: #fed847;
|
||||||
|
border: 4rpx solid #fed847;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -40,6 +40,7 @@ export const MESSAGETYPESV2 = {
|
|||||||
HalfRest: 7,
|
HalfRest: 7,
|
||||||
TestDistance: 8,
|
TestDistance: 8,
|
||||||
MatchSuccess: 9,
|
MatchSuccess: 9,
|
||||||
|
InvalidShot: 10,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const topThreeColors = ["#FFD947", "#D2D2D2", "#FFA515"];
|
export const topThreeColors = ["#FFD947", "#D2D2D2", "#FFA515"];
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, onBeforeUnmount } from "vue";
|
import { ref, onMounted, computed, 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";
|
||||||
@@ -188,6 +188,18 @@ const removePlayer = async (player) => {
|
|||||||
await kickPlayerAPI(roomNumber.value, player.id);
|
await kickPlayerAPI(roomNumber.value, player.id);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const canClick = computed(() => {
|
||||||
|
if (ready.value) return false;
|
||||||
|
const { members = [] } = room.value;
|
||||||
|
if (members.length < 2) return false;
|
||||||
|
if (
|
||||||
|
owner.value.id === user.value.id &&
|
||||||
|
members.some((m) => !m.userInfo.state && m.userInfo.id !== owner.value.id)
|
||||||
|
)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
onShareAppMessage(() => {
|
onShareAppMessage(() => {
|
||||||
return {
|
return {
|
||||||
title: "邀请您进入房间对战",
|
title: "邀请您进入房间对战",
|
||||||
@@ -373,14 +385,16 @@ onBeforeUnmount(() => {
|
|||||||
:removePlayer="removePlayer"
|
:removePlayer="removePlayer"
|
||||||
/>
|
/>
|
||||||
<view>
|
<view>
|
||||||
<SButton :disabled="ready" :onClick="getReady">{{
|
<SButton :disabled="!canClick" :onClick="getReady">
|
||||||
allReady.value
|
{{
|
||||||
? "即将进入对局..."
|
allReady.value
|
||||||
: owner.id === user.id && (room.members || []).length > 2
|
? "即将进入对局..."
|
||||||
? "开始对局"
|
: owner.id === user.id
|
||||||
: "我准备好了"
|
? "开始对局"
|
||||||
}}</SButton>
|
: "我准备好了"
|
||||||
<text class="tips">所有人准备后自动开始游戏。</text>
|
}}
|
||||||
|
</SButton>
|
||||||
|
<text class="tips">所有人准备好后由房主点击开始</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@@ -5,15 +5,15 @@ import SButton from "@/components/SButton.vue";
|
|||||||
import { capsuleHeight } from "@/util";
|
import { capsuleHeight } from "@/util";
|
||||||
|
|
||||||
const images = [
|
const images = [
|
||||||
"https://static.shelingxingqiu.com/attachment/2025-09-04/dcjmxsmf6yitekatwe.jpg",
|
"https://static.shelingxingqiu.com/mall/images/mall_01.jpg",
|
||||||
"https://static.shelingxingqiu.com/attachment/2025-09-04/dcjmxsmi475gqdtrvx.jpg",
|
"https://static.shelingxingqiu.com/mall/images/mall_02.jpg",
|
||||||
"https://static.shelingxingqiu.com/attachment/2025-09-04/dcjmxsmgy8ej5wuap5.jpg",
|
"https://static.shelingxingqiu.com/mall/images/mall_03.jpg",
|
||||||
"https://static.shelingxingqiu.com/attachment/2025-09-04/dcjmxsmg6y7nveaadv.jpg",
|
"https://static.shelingxingqiu.com/mall/images/mall_04.jpg",
|
||||||
"https://static.shelingxingqiu.com/attachment/2025-12-04/depguhlqg9zxastyn3.jpg",
|
"https://static.shelingxingqiu.com/mall/images/mall_05.jpg",
|
||||||
"https://static.shelingxingqiu.com/attachment/2025-12-04/depguhlfr041aedqmb.jpg",
|
"https://static.shelingxingqiu.com/mall/images/mall_06.jpg",
|
||||||
"https://static.shelingxingqiu.com/attachment/2025-12-04/depguhlpnlyxndnor5.jpg",
|
"https://static.shelingxingqiu.com/mall/images/mall_07.jpg",
|
||||||
"https://static.shelingxingqiu.com/attachment/2025-09-04/dcjmxsmg68a8mezgzx.jpg",
|
"https://static.shelingxingqiu.com/mall/images/mall_08.jpg",
|
||||||
"https://static.shelingxingqiu.com/attachment/2025-10-14/ddht51a3hiyw7ueli4.jpg",
|
"https://static.shelingxingqiu.com/mall/images/mall_09.jpg",
|
||||||
];
|
];
|
||||||
|
|
||||||
const addBg = ref(false);
|
const addBg = ref(false);
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ const nextStep = async () => {
|
|||||||
btnDisabled.value = true;
|
btnDisabled.value = true;
|
||||||
step.value = 2;
|
step.value = 2;
|
||||||
title.value = "-感知距离";
|
title.value = "-感知距离";
|
||||||
const result = await createPractiseAPI(total, 360);
|
const result = await createPractiseAPI(total, 120);
|
||||||
if (result) practiseId.value = result.id;
|
if (result) practiseId.value = result.id;
|
||||||
} else if (step.value === 2) {
|
} else if (step.value === 2) {
|
||||||
showGuide.value = false;
|
showGuide.value = false;
|
||||||
@@ -166,7 +166,7 @@ const onClose = async () => {
|
|||||||
start.value = false;
|
start.value = false;
|
||||||
scores.value = [];
|
scores.value = [];
|
||||||
step.value = 3;
|
step.value = 3;
|
||||||
const result = await createPractiseAPI(total, 360);
|
const result = await createPractiseAPI(total, 120);
|
||||||
if (result) practiseId.value = result.id;
|
if (result) practiseId.value = result.id;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ onLoad(async (options) => {
|
|||||||
<SModal
|
<SModal
|
||||||
:show="showModal"
|
:show="showModal"
|
||||||
:onClose="() => (showModal = false)"
|
:onClose="() => (showModal = false)"
|
||||||
height="520rpx"
|
height="716rpx"
|
||||||
>
|
>
|
||||||
<view v-if="warnning" class="warnning">
|
<view v-if="warnning" class="warnning">
|
||||||
{{ warnning }}
|
{{ warnning }}
|
||||||
|
|||||||
@@ -39,11 +39,11 @@ const toPage = async (path) => {
|
|||||||
showModal.value = true;
|
showModal.value = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (path === "/pages/first-try") {
|
// if (path === "/pages/first-try") {
|
||||||
// if (canEenter(user.value, device.value, online.value, path)) {
|
// if (canEenter(user.value, device.value, online.value, path)) {
|
||||||
// await uni.$checkAudio();
|
// await uni.$checkAudio();
|
||||||
// }
|
// }
|
||||||
}
|
// }
|
||||||
uni.navigateTo({ url: path });
|
uni.navigateTo({ url: path });
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -75,7 +75,6 @@ onShow(async () => {
|
|||||||
if ("823,209,293,257".indexOf(homeData.user.id) !== -1) {
|
if ("823,209,293,257".indexOf(homeData.user.id) !== -1) {
|
||||||
const show = uni.getStorageSync("show-the-user");
|
const show = uni.getStorageSync("show-the-user");
|
||||||
if (!show) {
|
if (!show) {
|
||||||
showTheUser.value = true;
|
|
||||||
uni.setStorageSync("show-the-user", true);
|
uni.setStorageSync("show-the-user", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 || "60143330377469952";
|
battleId.value = options.battleId || "60510101693403136";
|
||||||
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) {
|
||||||
@@ -128,7 +128,7 @@ const checkBowData = (selected) => {
|
|||||||
<text :style="{ color: team == 1 ? '#64BAFF' : '#FF6767' }">
|
<text :style="{ color: team == 1 ? '#64BAFF' : '#FF6767' }">
|
||||||
{{ round.shoots[team].reduce((acc, cur) => acc + cur.ring, 0) }}环
|
{{ round.shoots[team].reduce((acc, cur) => acc + cur.ring, 0) }}环
|
||||||
</text>
|
</text>
|
||||||
<text>得分 {{ round.scores[team].totalRing }}</text>
|
<text>得分 {{ round.scores[team].score }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import ScreenHint from "@/components/ScreenHint.vue";
|
|||||||
import TestDistance from "@/components/TestDistance.vue";
|
import TestDistance from "@/components/TestDistance.vue";
|
||||||
import audioManager from "@/audioManager";
|
import audioManager from "@/audioManager";
|
||||||
import { getBattleAPI, laserCloseAPI } from "@/apis";
|
import { getBattleAPI, laserCloseAPI } from "@/apis";
|
||||||
import { isGameEnded } from "@/util";
|
|
||||||
import { MESSAGETYPESV2 } from "@/constants";
|
import { MESSAGETYPESV2 } from "@/constants";
|
||||||
import useStore from "@/store";
|
import useStore from "@/store";
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
@@ -103,9 +102,11 @@ async function onReceiveMessage(msg) {
|
|||||||
halfRest.value = true;
|
halfRest.value = true;
|
||||||
tips.value = "准备下半场";
|
tips.value = "准备下半场";
|
||||||
} else if (msg.type === MESSAGETYPESV2.BattleEnd) {
|
} else if (msg.type === MESSAGETYPESV2.BattleEnd) {
|
||||||
uni.redirectTo({
|
setTimeout(() => {
|
||||||
url: "/pages/battle-result?battleId=" + msg.matchId,
|
uni.redirectTo({
|
||||||
});
|
url: "/pages/battle-result?battleId=" + msg.matchId,
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
|
|||||||
@@ -14,11 +14,10 @@ const arrows = ref([]);
|
|||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
|
|
||||||
onLoad(async (options) => {
|
onLoad(async (options) => {
|
||||||
if (options.id) {
|
if (!options.id) return;
|
||||||
const result = await getPractiseAPI(options.id);
|
const result = await getPractiseAPI(options.id || 176);
|
||||||
arrows.value = result.arrows;
|
arrows.value = result.details;
|
||||||
total.value = result.completed_arrows;
|
total.value = result.details.length;
|
||||||
}
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const practiseList = ref([]);
|
|||||||
|
|
||||||
const toMatchDetail = (id) => {
|
const toMatchDetail = (id) => {
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: `/pages/match-detail?id=${id}`,
|
url: `/pages/match-detail?battleId=${id}`,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const getPractiseDetail = async (id) => {
|
const getPractiseDetail = async (id) => {
|
||||||
@@ -52,6 +52,10 @@ const onPractiseLoading = async (page) => {
|
|||||||
}
|
}
|
||||||
return result.length;
|
return result.length;
|
||||||
};
|
};
|
||||||
|
const getName = (battle) => {
|
||||||
|
if (battle.mode <= 3) return `${battle.mode}V${battle.mode}`;
|
||||||
|
return battle.mode + "人大乱斗";
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -80,19 +84,19 @@ const onPractiseLoading = async (page) => {
|
|||||||
<view
|
<view
|
||||||
v-for="(item, index) in matchList"
|
v-for="(item, index) in matchList"
|
||||||
:key="index"
|
:key="index"
|
||||||
@click="() => toMatchDetail(item.battleId)"
|
@click="() => toMatchDetail(item.id)"
|
||||||
>
|
>
|
||||||
<view class="contest-header">
|
<view class="contest-header">
|
||||||
<text>{{ item.name }}</text>
|
<text>{{ getName(item) }}</text>
|
||||||
<text>{{ item.createdAt }}</text>
|
<text>{{ item.createTime }}</text>
|
||||||
<image src="../static/back.png" mode="widthFix" />
|
<image src="../static/back.png" mode="widthFix" />
|
||||||
</view>
|
</view>
|
||||||
<BattleHeader
|
<BattleHeader
|
||||||
:players="item.mode === 1 ? [] : item.players"
|
:players="item.teams[0] ? item.teams[0].players : []"
|
||||||
:blueTeam="item.bluePlayers"
|
:blueTeam="item.teams[1] ? item.teams[1].players : []"
|
||||||
:redTeam="item.redPlayers"
|
:redTeam="item.teams[2] ? item.teams[2].players : []"
|
||||||
:winner="item.winner"
|
:winner="item.winTeam"
|
||||||
:showRank="item.mode === 2"
|
:showRank="item.teams[0]"
|
||||||
:showHeader="false"
|
:showHeader="false"
|
||||||
/>
|
/>
|
||||||
</view>
|
</view>
|
||||||
@@ -103,19 +107,19 @@ const onPractiseLoading = async (page) => {
|
|||||||
<view
|
<view
|
||||||
v-for="(item, index) in battleList"
|
v-for="(item, index) in battleList"
|
||||||
:key="index"
|
:key="index"
|
||||||
@click="() => toMatchDetail(item.battleId)"
|
@click="() => toMatchDetail(item.id)"
|
||||||
>
|
>
|
||||||
<view class="contest-header">
|
<view class="contest-header">
|
||||||
<text>{{ item.name }}</text>
|
<text>{{ getName(item) }}</text>
|
||||||
<text>{{ item.createdAt }}</text>
|
<text>{{ item.createTime }}</text>
|
||||||
<image src="../static/back.png" mode="widthFix" />
|
<image src="../static/back.png" mode="widthFix" />
|
||||||
</view>
|
</view>
|
||||||
<BattleHeader
|
<BattleHeader
|
||||||
:players="item.mode === 1 ? [] : item.players"
|
:players="item.teams[0] ? item.teams[0].players : []"
|
||||||
:blueTeam="item.bluePlayers"
|
:blueTeam="item.teams[1] ? item.teams[1].players : []"
|
||||||
:redTeam="item.redPlayers"
|
:redTeam="item.teams[2] ? item.teams[2].players : []"
|
||||||
:winner="item.winner"
|
:winner="item.winTeam"
|
||||||
:showRank="item.mode === 2"
|
:showRank="item.teams[0]"
|
||||||
:showHeader="false"
|
:showHeader="false"
|
||||||
/>
|
/>
|
||||||
</view>
|
</view>
|
||||||
@@ -131,7 +135,7 @@ const onPractiseLoading = async (page) => {
|
|||||||
>
|
>
|
||||||
<text
|
<text
|
||||||
>{{ item.completed_arrows === 36 ? "耐力挑战" : "单组练习" }}
|
>{{ item.completed_arrows === 36 ? "耐力挑战" : "单组练习" }}
|
||||||
{{ item.createdAt }}</text
|
{{ item.createTime }}</text
|
||||||
>
|
>
|
||||||
<image src="../static/back.png" mode="widthFix" />
|
<image src="../static/back.png" mode="widthFix" />
|
||||||
</view>
|
</view>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, onBeforeUnmount } from "vue";
|
import { ref, onMounted, onBeforeUnmount } from "vue";
|
||||||
import { onShow } from "@dcloudio/uni-app";
|
import { onLoad } from "@dcloudio/uni-app";
|
||||||
import Container from "@/components/Container.vue";
|
import Container from "@/components/Container.vue";
|
||||||
import ShootProgress from "@/components/ShootProgress.vue";
|
import ShootProgress from "@/components/ShootProgress.vue";
|
||||||
import BowTarget from "@/components/BowTarget.vue";
|
import BowTarget from "@/components/BowTarget.vue";
|
||||||
@@ -21,7 +21,7 @@ import {
|
|||||||
} from "@/apis";
|
} from "@/apis";
|
||||||
import { sharePractiseData } from "@/canvas";
|
import { sharePractiseData } from "@/canvas";
|
||||||
import { wxShare, debounce } from "@/util";
|
import { wxShare, debounce } from "@/util";
|
||||||
import { MESSAGETYPESV2, MESSAGETYPES, roundsName } from "@/constants";
|
import { MESSAGETYPESV2, roundsName } from "@/constants";
|
||||||
|
|
||||||
import useStore from "@/store";
|
import useStore from "@/store";
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
@@ -31,15 +31,20 @@ const { user } = storeToRefs(store);
|
|||||||
const start = ref(false);
|
const start = ref(false);
|
||||||
const scores = ref([]);
|
const scores = ref([]);
|
||||||
const total = 12;
|
const total = 12;
|
||||||
const currentRound = ref(0);
|
|
||||||
const practiseResult = ref({});
|
const practiseResult = ref({});
|
||||||
const practiseId = ref("");
|
const practiseId = ref("");
|
||||||
const showGuide = ref(false);
|
const showGuide = ref(false);
|
||||||
const tips = ref("");
|
const tips = ref("");
|
||||||
|
const targetType = ref(1);
|
||||||
|
|
||||||
|
onLoad((options) => {
|
||||||
|
if (options.target) {
|
||||||
|
targetType.value = Number(options.target);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const onReady = async () => {
|
const onReady = async () => {
|
||||||
await startPractiseAPI();
|
await startPractiseAPI();
|
||||||
currentRound.value = 0;
|
|
||||||
scores.value = [];
|
scores.value = [];
|
||||||
start.value = true;
|
start.value = true;
|
||||||
audioManager.play("练习开始");
|
audioManager.play("练习开始");
|
||||||
@@ -56,26 +61,6 @@ async function onReceiveMessage(msg) {
|
|||||||
} else if (msg.type === MESSAGETYPESV2.BattleEnd) {
|
} else if (msg.type === MESSAGETYPESV2.BattleEnd) {
|
||||||
setTimeout(onOver, 1500);
|
setTimeout(onOver, 1500);
|
||||||
}
|
}
|
||||||
// messages.forEach((msg) => {
|
|
||||||
// if (msg.constructor === MESSAGETYPES.ShootSyncMeArrowID) {
|
|
||||||
// if (scores.value.length < total) {
|
|
||||||
// scores.value.push(msg.target);
|
|
||||||
// currentRound.value += 1;
|
|
||||||
// if (currentRound.value === 4) {
|
|
||||||
// currentRound.value = 1;
|
|
||||||
// }
|
|
||||||
// if (practiseId && scores.value.length === total / 2) {
|
|
||||||
// showGuide.value = true;
|
|
||||||
// setTimeout(() => {
|
|
||||||
// showGuide.value = false;
|
|
||||||
// }, 3000);
|
|
||||||
// }
|
|
||||||
// if (scores.value.length === total) {
|
|
||||||
// setTimeout(onOver, 1500);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onComplete() {
|
async function onComplete() {
|
||||||
@@ -89,8 +74,7 @@ async function onComplete() {
|
|||||||
practiseResult.value = {};
|
practiseResult.value = {};
|
||||||
start.value = false;
|
start.value = false;
|
||||||
scores.value = [];
|
scores.value = [];
|
||||||
currentRound.value = 0;
|
const result = await createPractiseAPI(total, 120);
|
||||||
const result = await createPractiseAPI(total, 360);
|
|
||||||
if (result) practiseId.value = result.id;
|
if (result) practiseId.value = result.id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,7 +91,7 @@ onMounted(async () => {
|
|||||||
});
|
});
|
||||||
uni.$on("socket-inbox", onReceiveMessage);
|
uni.$on("socket-inbox", onReceiveMessage);
|
||||||
uni.$on("share-image", onClickShare);
|
uni.$on("share-image", onClickShare);
|
||||||
const result = await createPractiseAPI(total, 120);
|
const result = await createPractiseAPI(total, 120, targetType.value);
|
||||||
if (result) practiseId.value = result.id;
|
if (result) practiseId.value = result.id;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -152,7 +136,7 @@ onBeforeUnmount(() => {
|
|||||||
</view>
|
</view>
|
||||||
<BowTarget
|
<BowTarget
|
||||||
:totalRound="start ? total / 4 : 0"
|
:totalRound="start ? total / 4 : 0"
|
||||||
:currentRound="currentRound"
|
:currentRound="scores.length % 3"
|
||||||
:scores="scores"
|
:scores="scores"
|
||||||
/>
|
/>
|
||||||
<ScorePanel2 :arrows="scores" />
|
<ScorePanel2 :arrows="scores" />
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import { MESSAGETYPESV2 } from "@/constants";
|
|||||||
|
|
||||||
import useStore from "@/store";
|
import useStore from "@/store";
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
|
import {onLoad} from "@dcloudio/uni-app";
|
||||||
const store = useStore();
|
const store = useStore();
|
||||||
const { user } = storeToRefs(store);
|
const { user } = storeToRefs(store);
|
||||||
|
|
||||||
@@ -33,6 +34,13 @@ const total = 36;
|
|||||||
const practiseResult = ref({});
|
const practiseResult = ref({});
|
||||||
const practiseId = ref("");
|
const practiseId = ref("");
|
||||||
const showGuide = ref(false);
|
const showGuide = ref(false);
|
||||||
|
const targetType = ref(1);
|
||||||
|
|
||||||
|
onLoad((options) => {
|
||||||
|
if (options.target) {
|
||||||
|
targetType.value = Number(options.target);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const onReady = async () => {
|
const onReady = async () => {
|
||||||
await startPractiseAPI();
|
await startPractiseAPI();
|
||||||
@@ -97,7 +105,7 @@ onMounted(async () => {
|
|||||||
});
|
});
|
||||||
uni.$on("socket-inbox", onReceiveMessage);
|
uni.$on("socket-inbox", onReceiveMessage);
|
||||||
uni.$on("share-image", onClickShare);
|
uni.$on("share-image", onClickShare);
|
||||||
const result = await createPractiseAPI(total, 360);
|
const result = await createPractiseAPI(total, 360, targetType.value);
|
||||||
if (result) practiseId.value = result.id;
|
if (result) practiseId.value = result.id;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { onShow } from "@dcloudio/uni-app";
|
|||||||
import Container from "@/components/Container.vue";
|
import Container from "@/components/Container.vue";
|
||||||
import Guide from "@/components/Guide.vue";
|
import Guide from "@/components/Guide.vue";
|
||||||
import Avatar from "@/components/Avatar.vue";
|
import Avatar from "@/components/Avatar.vue";
|
||||||
|
import TargetPicker from "@/components/TargetPicker.vue";
|
||||||
import { getPractiseDataAPI } from "@/apis";
|
import { getPractiseDataAPI } from "@/apis";
|
||||||
import { canEenter } from "@/util";
|
import { canEenter } from "@/util";
|
||||||
|
|
||||||
@@ -12,12 +13,20 @@ import { storeToRefs } from "pinia";
|
|||||||
const store = useStore();
|
const store = useStore();
|
||||||
const { user, device, online } = storeToRefs(store);
|
const { user, device, online } = storeToRefs(store);
|
||||||
const data = ref({});
|
const data = ref({});
|
||||||
|
const showTargetPicker = ref(false);
|
||||||
|
const pendingPractiseType = ref("");
|
||||||
|
|
||||||
const goPractise = async (type) => {
|
const goPractise = async (type) => {
|
||||||
if (!canEenter(user.value, device.value, online.value)) return;
|
if (!canEenter(user.value, device.value, online.value)) return;
|
||||||
// await uni.$checkAudio();
|
pendingPractiseType.value = type;
|
||||||
|
showTargetPicker.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTargetConfirm = (target) => {
|
||||||
|
showTargetPicker.value = false;
|
||||||
|
const type = pendingPractiseType.value;
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: `/pages/practise-${type}`,
|
url: `/pages/practise-${type}?target=${target}`,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -88,6 +97,11 @@ onShow(async () => {
|
|||||||
/>
|
/>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
<TargetPicker
|
||||||
|
:show="showTargetPicker"
|
||||||
|
:onClose="() => (showTargetPicker = false)"
|
||||||
|
:onConfirm="handleTargetConfirm"
|
||||||
|
/>
|
||||||
</Container>
|
</Container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { onLoad, onShow, onHide } from "@dcloudio/uni-app";
|
|||||||
import Container from "@/components/Container.vue";
|
import Container from "@/components/Container.vue";
|
||||||
import BattleHeader from "@/components/BattleHeader.vue";
|
import BattleHeader from "@/components/BattleHeader.vue";
|
||||||
import BowTarget from "@/components/BowTarget.vue";
|
import BowTarget from "@/components/BowTarget.vue";
|
||||||
import PlayersRow from "@/components/PlayersRow.vue";
|
|
||||||
import BattleFooter from "@/components/BattleFooter.vue";
|
import BattleFooter from "@/components/BattleFooter.vue";
|
||||||
import ScreenHint from "@/components/ScreenHint.vue";
|
import ScreenHint from "@/components/ScreenHint.vue";
|
||||||
import SButton from "@/components/SButton.vue";
|
import SButton from "@/components/SButton.vue";
|
||||||
@@ -13,8 +12,7 @@ import TestDistance from "@/components/TestDistance.vue";
|
|||||||
import TeamAvatars from "@/components/TeamAvatars.vue";
|
import TeamAvatars from "@/components/TeamAvatars.vue";
|
||||||
import ShootProgress2 from "@/components/ShootProgress2.vue";
|
import ShootProgress2 from "@/components/ShootProgress2.vue";
|
||||||
import { laserCloseAPI, getBattleAPI } from "@/apis";
|
import { laserCloseAPI, getBattleAPI } from "@/apis";
|
||||||
import { isGameEnded, formatTimestamp } from "@/util";
|
import { MESSAGETYPESV2 } from "@/constants";
|
||||||
import { MESSAGETYPES, MESSAGETYPESV2, roundsName } from "@/constants";
|
|
||||||
import audioManager from "@/audioManager";
|
import audioManager from "@/audioManager";
|
||||||
import useStore from "@/store";
|
import useStore from "@/store";
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
@@ -129,9 +127,11 @@ async function onReceiveMessage(msg) {
|
|||||||
}, 2000);
|
}, 2000);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uni.redirectTo({
|
setTimeout(() => {
|
||||||
url: "/pages/battle-result?battleId=" + msg.matchId,
|
uni.redirectTo({
|
||||||
});
|
url: "/pages/battle-result?battleId=" + msg.matchId,
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
23
src/util.js
23
src/util.js
@@ -1,5 +1,3 @@
|
|||||||
import { getUserGameState, getGameAPI } from "@/apis";
|
|
||||||
|
|
||||||
export const formatTimestamp = (timestamp) => {
|
export const formatTimestamp = (timestamp) => {
|
||||||
const date = new Date(timestamp * 1000);
|
const date = new Date(timestamp * 1000);
|
||||||
const year = date.getFullYear();
|
const year = date.getFullYear();
|
||||||
@@ -89,27 +87,6 @@ export const wxShare = async (canvasId = "shareCanvas") => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const isGameEnded = async (battleId) => {
|
|
||||||
const state = await getUserGameState();
|
|
||||||
if (!state.gaming) {
|
|
||||||
const result = await getGameAPI(battleId);
|
|
||||||
if (result.mode) {
|
|
||||||
uni.redirectTo({
|
|
||||||
url: `/pages/battle-result?battleId=${battleId}`,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
uni.showToast({
|
|
||||||
title: "比赛已结束",
|
|
||||||
icon: "none",
|
|
||||||
});
|
|
||||||
setTimeout(() => {
|
|
||||||
uni.navigateBack();
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return !state.gaming;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取元素尺寸和位置信息
|
// 获取元素尺寸和位置信息
|
||||||
export const getElementRect = (classname) => {
|
export const getElementRect = (classname) => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ function createWebSocket(token, onMessage) {
|
|||||||
|
|
||||||
switch (envVersion) {
|
switch (envVersion) {
|
||||||
case "develop": // 开发版
|
case "develop": // 开发版
|
||||||
// url = "ws://192.168.1.30:8000/socket";
|
url = "ws://localhost:8000/socket";
|
||||||
url = "wss://apitest.shelingxingqiu.com/socket";
|
// url = "wss://apitest.shelingxingqiu.com/socket";
|
||||||
break;
|
break;
|
||||||
case "trial": // 体验版
|
case "trial": // 体验版
|
||||||
url = "wss://apitest.shelingxingqiu.com/socket";
|
url = "wss://apitest.shelingxingqiu.com/socket";
|
||||||
@@ -47,9 +47,9 @@ function createWebSocket(token, onMessage) {
|
|||||||
uni.onSocketMessage((res) => {
|
uni.onSocketMessage((res) => {
|
||||||
const { data, event } = JSON.parse(res.data);
|
const { data, event } = JSON.parse(res.data);
|
||||||
if (event === "pong") return;
|
if (event === "pong") return;
|
||||||
if (data.type && data.data) {
|
if (data.type) {
|
||||||
console.log("收到消息:", getMessageTypeName(data.type), data.data);
|
console.log("收到消息:", getMessageTypeName(data.type), data.data);
|
||||||
if (onMessage) onMessage({ ...data.data, type: data.type });
|
if (onMessage) onMessage({ ...(data.data || {}), type: data.type });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (onMessage && data.updates) onMessage(data.updates);
|
if (onMessage && data.updates) onMessage(data.updates);
|
||||||
|
|||||||
Reference in New Issue
Block a user