添加设备在线离线处理

This commit is contained in:
kron
2025-12-31 13:39:16 +08:00
parent 25f51ad53a
commit af852d9b59
8 changed files with 104 additions and 57 deletions

View File

@@ -2,11 +2,12 @@
import { watch } from "vue"; import { watch } from "vue";
import { onShow, onHide } from "@dcloudio/uni-app"; import { onShow, onHide } from "@dcloudio/uni-app";
import websocket from "@/websocket"; import websocket from "@/websocket";
import { getDeviceBatteryAPI } from "@/apis";
import useStore from "@/store"; import useStore from "@/store";
import { storeToRefs } from "pinia"; import { storeToRefs } from "pinia";
const store = useStore(); const store = useStore();
const { user } = storeToRefs(store); const { user } = storeToRefs(store);
const { updateUser } = store; const { updateUser, updateOnline } = store;
watch( watch(
() => user.value.id, () => user.value.id,
@@ -33,8 +34,14 @@ function emitUpdateUser(value) {
updateUser(value); updateUser(value);
} }
async function emitUpdateOnline() {
const data = await getDeviceBatteryAPI();
updateOnline(data.online);
}
onShow(() => { onShow(() => {
uni.$on("update-user", emitUpdateUser); uni.$on("update-user", emitUpdateUser);
uni.$on("update-online", emitUpdateOnline);
const token = uni.getStorageSync( const token = uni.getStorageSync(
`${uni.getAccountInfoSync().miniProgram.envVersion}_token` `${uni.getAccountInfoSync().miniProgram.envVersion}_token`
); );
@@ -48,6 +55,7 @@ onShow(() => {
onHide(() => { onHide(() => {
uni.$off("update-user", emitUpdateUser); uni.$off("update-user", emitUpdateUser);
uni.$off("update-online", emitUpdateOnline);
websocket.closeWebSocket(); websocket.closeWebSocket();
}); });
</script> </script>

View File

@@ -20,9 +20,9 @@ onBeforeUnmount(() => {
</script> </script>
<template> <template>
<view class="container" :style="{ opacity: power > 0 ? 1 : 0 }"> <view class="container">
<image src="../static/b-power.png" mode="widthFix" /> <image src="../static/b-power.png" mode="widthFix" />
<view>电量{{ power }}%</view> <view>电量{{ power || 1 }}%</view>
</view> </view>
</template> </template>

View File

@@ -25,6 +25,8 @@ export const MESSAGETYPES = {
TeamUpdate: 4168086616, TeamUpdate: 4168086616,
InvalidShot: 4168086617, InvalidShot: 4168086617,
Calibration: 4168086625, Calibration: 4168086625,
DeviceOnline: 4168086626,
DeviceOffline: 4168086627,
}; };
export const topThreeColors = ["#FFD947", "#D2D2D2", "#FFA515"]; export const topThreeColors = ["#FFD947", "#D2D2D2", "#FFA515"];

View File

@@ -11,7 +11,7 @@ import { getRoomAPI, joinRoomAPI, isGamingAPI, getBattleDataAPI } from "@/apis";
import useStore from "@/store"; import useStore from "@/store";
import { storeToRefs } from "pinia"; import { storeToRefs } from "pinia";
const store = useStore(); const store = useStore();
const { user } = storeToRefs(store); const { user, device, online } = storeToRefs(store);
import { debounce } from "@/util"; import { debounce } from "@/util";
const showModal = ref(false); const showModal = ref(false);
@@ -19,7 +19,33 @@ const warnning = ref("");
const roomNumber = ref(""); const roomNumber = ref("");
const data = ref({}); const data = ref({});
const checkBeforeEnter = async () => {
if (!device.value.deviceId) {
uni.showToast({
title: "请先绑定设备",
icon: "none",
});
return true;
}
if (!online.value) {
uni.showToast({
title: "智能弓未连接",
icon: "none",
});
return true;
}
if (!user.value.trio) {
uni.showToast({
title: "请先完成新手试炼",
icon: "none",
});
return true;
}
return false;
};
const enterRoom = debounce(async () => { const enterRoom = debounce(async () => {
if (checkBeforeEnter()) return;
const isGaming = await isGamingAPI(); const isGaming = await isGamingAPI();
if (isGaming) { if (isGaming) {
uni.$showHint(1); uni.$showHint(1);
@@ -54,6 +80,7 @@ const enterRoom = debounce(async () => {
} }
}); });
const onCreateRoom = async () => { const onCreateRoom = async () => {
if (checkBeforeEnter()) return;
const isGaming = await isGamingAPI(); const isGaming = await isGamingAPI();
if (isGaming) { if (isGaming) {
uni.$showHint(1); uni.$showHint(1);

View File

@@ -15,18 +15,25 @@ import {
getRankListAPI, getRankListAPI,
getHomeData, getHomeData,
getMyDevicesAPI, getMyDevicesAPI,
getDeviceBatteryAPI,
} from "@/apis"; } from "@/apis";
import { topThreeColors } from "@/constants"; import { topThreeColors } from "@/constants";
import useStore from "@/store"; import useStore from "@/store";
import { storeToRefs } from "pinia"; import { storeToRefs } from "pinia";
const store = useStore(); const store = useStore();
const { updateConfig, updateUser, updateDevice, updateRank, getLvlName } = const {
store; updateConfig,
// 使用storeToRefs用于UI里显示保持响应性 updateUser,
const { user, device, rankData } = storeToRefs(store); updateDevice,
updateRank,
getLvlName,
updateOnline,
} = store;
const { user, device, rankData, online } = storeToRefs(store);
const showModal = ref(false); const showModal = ref(false);
const showGuide = ref(false); const showGuide = ref(false);
const calibration = ref(false);
const showTheUser = ref(false); const showTheUser = ref(false);
const toPage = async (path) => { const toPage = async (path) => {
@@ -34,34 +41,22 @@ const toPage = async (path) => {
showModal.value = true; showModal.value = true;
return; return;
} }
if ( if (path === "/pages/first-try") {
"/pages/first-try,/pages/practise,/pages/friend-battle".indexOf(path) !== -1
) {
if (!device.value.deviceId) { if (!device.value.deviceId) {
return uni.showToast({ return uni.showToast({
title: "请先绑定设备", title: "请先绑定设备",
icon: "none", icon: "none",
}); });
} }
if ( if (!online.value) {
!calibration.value &&
uni.getAccountInfoSync().miniProgram.envVersion === "release"
) {
return uni.$showHint(4);
}
if ("/pages/first-try".indexOf(path) === -1 && !user.value.trio) {
return uni.showToast({ return uni.showToast({
title: "请先完成新手试炼", title: "智能弓未连接",
icon: "none", icon: "none",
}); });
} }
}
if (path === "/pages/first-try") {
await uni.$checkAudio(); await uni.$checkAudio();
} }
uni.navigateTo({ uni.navigateTo({ url: path });
url: path,
});
}; };
const toRankListPage = () => { const toRankListPage = () => {
@@ -133,10 +128,8 @@ onMounted(async () => {
const config = await getAppConfig(); const config = await getAppConfig();
updateConfig(config); updateConfig(config);
console.log("全局配置:", config); console.log("全局配置:", config);
}); const data = await getDeviceBatteryAPI();
updateOnline(data.online);
onShow(() => {
calibration.value = uni.getStorageSync("calibration");
}); });
onShareAppMessage(() => { onShareAppMessage(() => {
@@ -165,18 +158,22 @@ onShareTimeline(() => {
<view class="feature-grid"> <view class="feature-grid">
<view class="bow-card"> <view class="bow-card">
<image <image
v-if="online"
src="https://static.shelingxingqiu.com/attachment/2025-08-07/dbvt1o6dvhr2rop3kn.webp" src="https://static.shelingxingqiu.com/attachment/2025-08-07/dbvt1o6dvhr2rop3kn.webp"
mode="widthFix" mode="widthFix"
@click="() => toPage('/pages/my-device')" @click="() => toPage('/pages/my-device')"
/> />
<text v-if="!user.id">我的弓箭</text> <image
<text v-if="user.id && !device.deviceId">连接智能弓箭</text> v-else
<text src="https://static.shelingxingqiu.com/attachment/2025-12-31/dfc2em8qkf2wkls5fm.png"
v-if="user.id && device.deviceId" mode="widthFix"
class="truncate" @click="() => toPage('/pages/my-device')"
:style="{ width: '90%', textAlign: 'center' }" />
>{{ device.deviceName }}</text <block v-if="user.id">
> <text v-if="!device.deviceId">绑定我的智能弓</text>
<text v-else-if="!online">设备离线</text>
<text v-else-if="online">设备在线</text>
</block>
<image <image
src="../static/first-try.png" src="../static/first-try.png"
mode="widthFix" mode="widthFix"

View File

@@ -9,20 +9,31 @@ import { getPractiseDataAPI } from "@/apis";
import useStore from "@/store"; import useStore from "@/store";
import { storeToRefs } from "pinia"; import { storeToRefs } from "pinia";
const store = useStore(); const store = useStore();
const { user } = storeToRefs(store); const { user, device, online } = storeToRefs(store);
const data = ref({}); const data = ref({});
const toPractiseOne = async () => { const goPractise = async (type) => {
await uni.$checkAudio(); if (!device.value.deviceId) {
uni.navigateTo({ return uni.showToast({
url: "/pages/practise-one", title: "请先绑定设备",
icon: "none",
}); });
}; }
if (!online.value) {
const toPractiseTwo = async () => { return uni.showToast({
title: "智能弓未连接",
icon: "none",
});
}
if (!user.value.trio) {
return uni.showToast({
title: "请先完成新手试炼",
icon: "none",
});
}
await uni.$checkAudio(); await uni.$checkAudio();
uni.navigateTo({ uni.navigateTo({
url: "/pages/practise-two", url: `/pages/practise-${type}`,
}); });
}; };
@@ -78,14 +89,14 @@ onShow(async () => {
</view> </view>
</view> </view>
</view> </view>
<view class="practise-btn" @click="toPractiseOne"> <view class="practise-btn" @click="() => goPractise('one')">
<image <image
src="https://static.shelingxingqiu.com/attachment/2025-07-12/db9x668e2vdtqh0otq.png" src="https://static.shelingxingqiu.com/attachment/2025-07-12/db9x668e2vdtqh0otq.png"
class="practise1" class="practise1"
mode="widthFix" mode="widthFix"
/> />
</view> </view>
<view class="practise-btn" @click="toPractiseTwo"> <view class="practise-btn" @click="() => goPractise('two')">
<image <image
src="https://static.shelingxingqiu.com/attachment/2025-07-12/db9x668eehkvyicc08.png" src="https://static.shelingxingqiu.com/attachment/2025-07-12/db9x668eehkvyicc08.png"
class="practise2" class="practise2"

View File

@@ -8,7 +8,7 @@ import { isGamingAPI, getHomeData } from "@/apis";
import useStore from "@/store"; import useStore from "@/store";
import { storeToRefs } from "pinia"; import { storeToRefs } from "pinia";
const store = useStore(); const store = useStore();
const { user, device } = storeToRefs(store); const { user, device, online } = storeToRefs(store);
const { getLvlName } = store; const { getLvlName } = store;
const defaultSeasonData = { const defaultSeasonData = {
@@ -26,7 +26,6 @@ const seasonData = ref([]);
const rankData = ref({ user: {} }); const rankData = ref({ user: {} });
const showSeasonList = ref(false); const showSeasonList = ref(false);
const currentSeasonData = ref(defaultSeasonData); const currentSeasonData = ref(defaultSeasonData);
const calibration = ref(false);
const handleSelect = (index) => { const handleSelect = (index) => {
selectedIndex.value = index; selectedIndex.value = index;
@@ -48,11 +47,11 @@ const toMatchPage = async (gameType, teamSize) => {
icon: "none", icon: "none",
}); });
} }
if ( if (!online.value) {
!calibration.value && return uni.showToast({
uni.getAccountInfoSync().miniProgram.envVersion === "release" title: "智能弓未连接",
) { icon: "none",
return uni.$showHint(4); });
} }
if (!user.value.trio) { if (!user.value.trio) {
return uni.showToast({ return uni.showToast({
@@ -125,7 +124,6 @@ const updateData = () => {
} }
}; };
onShow(async () => { onShow(async () => {
calibration.value = uni.getStorageSync("calibration");
const result = await getHomeData(); const result = await getHomeData();
rankData.value = result; rankData.value = result;
handleSelect(selectedIndex.value); handleSelect(selectedIndex.value);

View File

@@ -79,6 +79,10 @@ function createWebSocket(token, onMessage) {
uni.setStorageSync("latestRank", msg.lvl); uni.setStorageSync("latestRank", msg.lvl);
} else if (msg.constructor === MESSAGETYPES.LvlUpdate) { } else if (msg.constructor === MESSAGETYPES.LvlUpdate) {
uni.setStorageSync("latestLvl", msg.lvl); uni.setStorageSync("latestLvl", msg.lvl);
} else if (msg.constructor === MESSAGETYPES.DeviceOnline) {
uni.$emit("update-online");
} else if (msg.constructor === MESSAGETYPES.DeviceOffline) {
uni.$emit("update-online");
} }
}); });