diff --git a/src/App.vue b/src/App.vue index 738dbbb..5ccb912 100644 --- a/src/App.vue +++ b/src/App.vue @@ -8,9 +8,6 @@ } from "@dcloudio/uni-app"; import websocket from "@/websocket"; import matchWebsocket from "@/matchWebsocket"; - import { - getDeviceBatteryAPI - } from "@/apis"; import { MESSAGETYPES } from "@/constants"; @@ -27,8 +24,9 @@ } = storeToRefs(store); const { updateUser, - updateOnline, - updateDeviceBattery, + updateDeviceStatus, + setDeviceOnline, + clearDeviceStatus, showDeviceChargingDialog, clearSessionState, clearDevice @@ -70,14 +68,19 @@ }); } - async function emitUpdateOnline() { - const data = await getDeviceBatteryAPI(); + function emitUpdateOnline(nextOnline) { const wasOnline = Boolean(online.value); - const nextOnline = Boolean(data.online); - updateOnline(nextOnline); - updateDeviceBattery(nextOnline ? data?.battery ?? data?.power : null); - if (!device.value.deviceId || wasOnline === nextOnline) return; - audioManager.play(nextOnline ? "设备已连接" : "设备连接已断开"); + setDeviceOnline(nextOnline === true); + if (!device.value.deviceId || wasOnline === (nextOnline === true)) return; + audioManager.play(nextOnline === true ? "设备已连接" : "设备连接已断开"); + } + + function onDeviceStatusPush(status) { + updateDeviceStatus(status); + } + + function onShootSocketDisconnected() { + clearDeviceStatus(); } function onDeviceBindInvalid() { @@ -113,6 +116,10 @@ } function onShootWsMsg(content) { + if (content?.event === "/addons/shoot/battery") { + onDeviceStatusPush(content.data); + return; + } if(content.type === 'shoot-trigger'){ onDeviceShoot() } @@ -124,6 +131,7 @@ void audioManager.warmButton(); uni.$on("update-user", emitUpdateUser); uni.$on("update-online", emitUpdateOnline); + uni.$on("shoot-socket-disconnected", onShootSocketDisconnected); uni.$on("session-kicked-out", onSessionKickedOut); uni.$on("device-bind-invalid", onDeviceBindInvalid); uni.$on("device-charging", onDeviceCharging); @@ -150,6 +158,7 @@ onHide(() => { uni.$off("update-user", emitUpdateUser); uni.$off("update-online", emitUpdateOnline); + uni.$off("shoot-socket-disconnected", onShootSocketDisconnected); uni.$off("session-kicked-out", onSessionKickedOut); uni.$off("device-bind-invalid", onDeviceBindInvalid); uni.$off("device-charging", onDeviceCharging); @@ -159,6 +168,7 @@ matchWebsocket.closeMatchWebSocket({ reason: "app-hide" }); + clearDeviceStatus(); websocket.closeWebSocket(); }); diff --git a/src/apis.js b/src/apis.js index 837ddd2..eb5690a 100644 --- a/src/apis.js +++ b/src/apis.js @@ -285,6 +285,10 @@ export const getDeviceDetailAPI = (deviceId) => { return request("GET", `/user/device/getDetail?deviceId=${encodeURIComponent(deviceId)}`); }; +export const updateDeviceAliasAPI = (deviceId, alias) => { + return request("POST", "/user/device/updateAlias", {deviceId, alias}); +}; + export const createPractiseAPI = (arrows, time, target) => { return request("POST", "/user/practice/create", { shootNumber: arrows, @@ -565,10 +569,6 @@ export const laserCloseAPI = async () => { return request("POST", "/user/device/closeAim"); }; -export const getDeviceBatteryAPI = async () => { - return request("GET", "/user/device/battery"); -}; - // 设备连接指定 WiFi,只下发 WiFi 凭证,不触发 OTA 升级。 export const connectDeviceWifiAPI = async (ssid, password) => { return request("POST", "/user/hardwareBox/connectWifi", {ssid, password}); diff --git a/src/components/BowPower.vue b/src/components/BowPower.vue index 528c1e7..c0c3083 100644 --- a/src/components/BowPower.vue +++ b/src/components/BowPower.vue @@ -1,44 +1,15 @@ diff --git a/src/components/OtaModal.vue b/src/components/OtaModal.vue index 303c1a0..4861667 100644 --- a/src/components/OtaModal.vue +++ b/src/components/OtaModal.vue @@ -1,10 +1,11 @@ + + + + diff --git a/src/pages/device/my-device.vue b/src/pages/device/my-device.vue index 66e6e67..8cae4fd 100644 --- a/src/pages/device/my-device.vue +++ b/src/pages/device/my-device.vue @@ -1,10 +1,15 @@ diff --git a/src/static/device-assets/device-avatar.png b/src/static/device-assets/device-avatar.png index 3d75f21..309eef3 100644 Binary files a/src/static/device-assets/device-avatar.png and b/src/static/device-assets/device-avatar.png differ diff --git a/src/static/device-assets/device-bind-failure-hero.png b/src/static/device-assets/device-bind-failure-hero.png index ca06f28..634fcff 100644 Binary files a/src/static/device-assets/device-bind-failure-hero.png and b/src/static/device-assets/device-bind-failure-hero.png differ diff --git a/src/static/device-assets/device-bind-success-confetti.png b/src/static/device-assets/device-bind-success-confetti.png index a43543f..df398ee 100644 Binary files a/src/static/device-assets/device-bind-success-confetti.png and b/src/static/device-assets/device-bind-success-confetti.png differ diff --git a/src/static/device-assets/device-bind-success-hero-first.png b/src/static/device-assets/device-bind-success-hero-first.png index b4d3d51..2fa5898 100644 Binary files a/src/static/device-assets/device-bind-success-hero-first.png and b/src/static/device-assets/device-bind-success-hero-first.png differ diff --git a/src/static/device-assets/device-bind-success-hero-nonfirst.png b/src/static/device-assets/device-bind-success-hero-nonfirst.png index c59cce5..b0ad3a9 100644 Binary files a/src/static/device-assets/device-bind-success-hero-nonfirst.png and b/src/static/device-assets/device-bind-success-hero-nonfirst.png differ diff --git a/src/static/device-assets/device-bind-success-reward-gift.png b/src/static/device-assets/device-bind-success-reward-gift.png index c949b62..83d619c 100644 Binary files a/src/static/device-assets/device-bind-success-reward-gift.png and b/src/static/device-assets/device-bind-success-reward-gift.png differ diff --git a/src/static/device-assets/device-bind-success-title.png b/src/static/device-assets/device-bind-success-title.png index 655b282..c12b0d7 100644 Binary files a/src/static/device-assets/device-bind-success-title.png and b/src/static/device-assets/device-bind-success-title.png differ diff --git a/src/static/device-assets/device-help.png b/src/static/device-assets/device-help.png index 6ce237f..8fe1879 100644 Binary files a/src/static/device-assets/device-help.png and b/src/static/device-assets/device-help.png differ diff --git a/src/static/device-assets/device-qrcode.png b/src/static/device-assets/device-qrcode.png index 16ccccd..e0bc225 100644 Binary files a/src/static/device-assets/device-qrcode.png and b/src/static/device-assets/device-qrcode.png differ diff --git a/src/static/device-assets/my-device-avatar.png b/src/static/device-assets/my-device-avatar.png index 3d75f21..309eef3 100644 Binary files a/src/static/device-assets/my-device-avatar.png and b/src/static/device-assets/my-device-avatar.png differ diff --git a/src/static/device-assets/my-device-qrcode.png b/src/static/device-assets/my-device-qrcode.png index 16ccccd..e0bc225 100644 Binary files a/src/static/device-assets/my-device-qrcode.png and b/src/static/device-assets/my-device-qrcode.png differ diff --git a/src/static/device-assets/my-device-unbound-background.png b/src/static/device-assets/my-device-unbound-background.png index 370aa1c..4222faf 100644 Binary files a/src/static/device-assets/my-device-unbound-background.png and b/src/static/device-assets/my-device-unbound-background.png differ diff --git a/src/static/device-assets/my-device-unbound-help.png b/src/static/device-assets/my-device-unbound-help.png index 6ce237f..8fe1879 100644 Binary files a/src/static/device-assets/my-device-unbound-help.png and b/src/static/device-assets/my-device-unbound-help.png differ diff --git a/src/static/device-assets/my-device-unbound-product.png b/src/static/device-assets/my-device-unbound-product.png index 830a936..c1335f2 100644 Binary files a/src/static/device-assets/my-device-unbound-product.png and b/src/static/device-assets/my-device-unbound-product.png differ diff --git a/src/static/device-assets/my-device-unbound-qr-sample.png b/src/static/device-assets/my-device-unbound-qr-sample.png index d51d824..42f85fa 100644 Binary files a/src/static/device-assets/my-device-unbound-qr-sample.png and b/src/static/device-assets/my-device-unbound-qr-sample.png differ diff --git a/src/static/device-assets/my-device-unbound-scan.png b/src/static/device-assets/my-device-unbound-scan.png index 55c0540..f3aeacc 100644 Binary files a/src/static/device-assets/my-device-unbound-scan.png and b/src/static/device-assets/my-device-unbound-scan.png differ diff --git a/src/static/home-device/device-action-bg--bind.png b/src/static/home-device/device-action-bg--bind.png index 80e0eba..021b20f 100644 Binary files a/src/static/home-device/device-action-bg--bind.png and b/src/static/home-device/device-action-bg--bind.png differ diff --git a/src/static/home-device/device-action-wifi.png b/src/static/home-device/device-action-wifi.png index 8a592b3..438927f 100644 Binary files a/src/static/home-device/device-action-wifi.png and b/src/static/home-device/device-action-wifi.png differ diff --git a/src/static/home-device/device-bow--offline.png b/src/static/home-device/device-bow--offline.png index 736c36e..411cf13 100644 Binary files a/src/static/home-device/device-bow--offline.png and b/src/static/home-device/device-bow--offline.png differ diff --git a/src/static/home-device/device-bow--online.png b/src/static/home-device/device-bow--online.png index 219d280..80109f5 100644 Binary files a/src/static/home-device/device-bow--online.png and b/src/static/home-device/device-bow--online.png differ diff --git a/src/static/home-device/device-bow--unbound.png b/src/static/home-device/device-bow--unbound.png index e914429..19ed666 100644 Binary files a/src/static/home-device/device-bow--unbound.png and b/src/static/home-device/device-bow--unbound.png differ diff --git a/src/static/home-device/device-bow.png b/src/static/home-device/device-bow.png index 2e2776d..c5b5db3 100644 Binary files a/src/static/home-device/device-bow.png and b/src/static/home-device/device-bow.png differ diff --git a/src/static/home-device/device-card-bg--bound.png b/src/static/home-device/device-card-bg--bound.png index c1c487e..1a8aa09 100644 Binary files a/src/static/home-device/device-card-bg--bound.png and b/src/static/home-device/device-card-bg--bound.png differ diff --git a/src/static/home-device/device-card-bg--unbound.png b/src/static/home-device/device-card-bg--unbound.png index 2f8eb8a..673c250 100644 Binary files a/src/static/home-device/device-card-bg--unbound.png and b/src/static/home-device/device-card-bg--unbound.png differ diff --git a/src/static/home-device/device-edit.png b/src/static/home-device/device-edit.png index 3de03f7..1ba518d 100644 Binary files a/src/static/home-device/device-edit.png and b/src/static/home-device/device-edit.png differ diff --git a/src/static/home-device/device-id-hidden.png b/src/static/home-device/device-id-hidden.png new file mode 100644 index 0000000..17eb29d Binary files /dev/null and b/src/static/home-device/device-id-hidden.png differ diff --git a/src/static/home-device/device-id-visibility.png b/src/static/home-device/device-id-visible.png similarity index 100% rename from src/static/home-device/device-id-visibility.png rename to src/static/home-device/device-id-visible.png diff --git a/src/static/home-device/device-name-confirm.png b/src/static/home-device/device-name-confirm.png new file mode 100644 index 0000000..29d2e84 Binary files /dev/null and b/src/static/home-device/device-name-confirm.png differ diff --git a/src/static/home-device/device-name-mascot.png b/src/static/home-device/device-name-mascot.png new file mode 100644 index 0000000..8829e06 Binary files /dev/null and b/src/static/home-device/device-name-mascot.png differ diff --git a/src/static/home-device/device-platform.png b/src/static/home-device/device-platform.png index b7eb152..1f177ac 100644 Binary files a/src/static/home-device/device-platform.png and b/src/static/home-device/device-platform.png differ diff --git a/src/static/home-device/device-state-battery.png b/src/static/home-device/device-state-battery.png index 274b829..29bd1c7 100644 Binary files a/src/static/home-device/device-state-battery.png and b/src/static/home-device/device-state-battery.png differ diff --git a/src/static/home-device/device-state-dot--offline.png b/src/static/home-device/device-state-dot--offline.png index 32e32e7..30cc493 100644 Binary files a/src/static/home-device/device-state-dot--offline.png and b/src/static/home-device/device-state-dot--offline.png differ diff --git a/src/static/home-device/device-state-dot--online.png b/src/static/home-device/device-state-dot--online.png index 7d69c0f..96938f8 100644 Binary files a/src/static/home-device/device-state-dot--online.png and b/src/static/home-device/device-state-dot--online.png differ diff --git a/src/static/home-device/device-state-refresh.png b/src/static/home-device/device-state-refresh.png index 7957a13..9dd1d7b 100644 Binary files a/src/static/home-device/device-state-refresh.png and b/src/static/home-device/device-state-refresh.png differ diff --git a/src/static/home-device/device-unbind.png b/src/static/home-device/device-unbind.png index bc8d472..fe5823e 100644 Binary files a/src/static/home-device/device-unbind.png and b/src/static/home-device/device-unbind.png differ diff --git a/src/store.js b/src/store.js index 6df144b..6e0599f 100644 --- a/src/store.js +++ b/src/store.js @@ -17,6 +17,15 @@ const getDefaultDevice = () => ({ deviceName: "", }); +const getDefaultDeviceStatus = () => ({ + battery: null, + version: "", + online: false, + netType: "", + onlineDuration: null, + receivedAt: 0, +}); + const getDefaultGame = () => ({ roomID: "", inBattle: false, @@ -102,6 +111,8 @@ export default defineStore("store", { online: false, // 设备电量属于运行时状态,null 表示当前没有有效数据。 deviceBattery: null, + // WebSocket 实时推送的设备状态,不参与持久化。 + deviceStatus: getDefaultDeviceStatus(), game: { roomID: "", inBattle: false, @@ -136,7 +147,7 @@ export default defineStore("store", { this.rankData = { ...(data || {}) }; }, updateOnline(online) { - this.online = online; + this.setDeviceOnline(online); }, updateDeviceBattery(value) { if (value === null || value === undefined || value === "") { @@ -149,6 +160,43 @@ export default defineStore("store", { ? Math.min(100, Math.max(0, battery)) : null; }, + updateDeviceStatus(status = {}) { + const battery = Number(status.battery ?? status.power); + const onlineDuration = Number(status.onlineDuration); + const online = status.online === true; + const nextStatus = { + battery: Number.isFinite(battery) + ? Math.min(100, Math.max(0, battery)) + : null, + version: String(status.version ?? "").trim(), + online, + netType: String(status.netType ?? "").trim().toLowerCase(), + onlineDuration: + Number.isFinite(onlineDuration) && onlineDuration >= 0 + ? onlineDuration + : null, + receivedAt: Date.now(), + }; + + this.deviceStatus = nextStatus; + this.online = online; + this.deviceBattery = online ? nextStatus.battery : null; + }, + setDeviceOnline(online) { + const nextOnline = online === true; + this.online = nextOnline; + if (nextOnline) { + this.deviceStatus = { ...this.deviceStatus, online: true }; + return; + } + this.deviceBattery = null; + this.deviceStatus = getDefaultDeviceStatus(); + }, + clearDeviceStatus() { + this.online = false; + this.deviceBattery = null; + this.deviceStatus = getDefaultDeviceStatus(); + }, async updateUser(user = {}) { this.user = { ...getDefaultUser(), ...user }; this.user.lvlName = getLvlNameByScore(this.user.scores, this.config.randInfos) @@ -158,13 +206,15 @@ export default defineStore("store", { ); }, updateDevice(deviceId, deviceName) { + if (String(this.device.deviceId || "") !== String(deviceId || "")) { + this.clearDeviceStatus(); + } this.device.deviceId = deviceId; this.device.deviceName = deviceName; }, clearDevice() { this.device = getDefaultDevice(); - this.online = false; - this.deviceBattery = null; + this.clearDeviceStatus(); }, async updateConfig(config) { this.config = config; @@ -214,6 +264,7 @@ export default defineStore("store", { device: getDefaultDevice(), online: false, deviceBattery: null, + deviceStatus: getDefaultDeviceStatus(), game: getDefaultGame(), dailyCount: getDefaultDailyCount(), deviceChargingDialogVisible: false, diff --git a/src/websocket.js b/src/websocket.js index 9a1902a..34be35a 100644 --- a/src/websocket.js +++ b/src/websocket.js @@ -77,17 +77,33 @@ function createWebSocket(token, onMessage) { socketTask.onMessage((res) => { if (socket !== socketTask) return; - const { data, event } = JSON.parse(res.data); + let response; + try { + response = JSON.parse(res.data); + } catch (err) { + console.error("WebSocket 消息解析失败", err); + return; + } + + const { data, event, code, timestamp } = response || {}; if (event === "pong") return; - if (data.type) { + if (event === "/addons/shoot/battery") { + if ((code == null || Number(code) === 0) && onMessage && data && typeof data === "object") { + onMessage({ event, data, code, timestamp }); + } + return; + } + if (data?.type) { if (ENABLE_REALTIME_MESSAGE_LOG) { console.log("收到 WebSocket 消息", getMessageTypeName(data.type)); } if (onMessage) onMessage({ ...(data.data || {}), type: data.type }); return; } - if (onMessage && data.updates) onMessage(data.updates); - const msg = data.updates[0]; + const updates = Array.isArray(data?.updates) ? data.updates : []; + if (!updates.length) return; + if (onMessage) onMessage(updates); + const msg = updates[0]; if (msg) { if (ENABLE_REALTIME_MESSAGE_LOG) { console.log( @@ -101,9 +117,9 @@ function createWebSocket(token, onMessage) { } else if (msg.constructor === MESSAGETYPES.LvlUpdate) { uni.setStorageSync("latestLvl", msg.lvl); } else if (msg.constructor === MESSAGETYPES.DeviceOnline) { - uni.$emit("update-online"); + uni.$emit("update-online", true); } else if (msg.constructor === MESSAGETYPES.DeviceOffline) { - uni.$emit("update-online"); + uni.$emit("update-online", false); } else if (msg.constructor === MESSAGETYPES.DeviceCharging) { uni.$emit("device-charging"); } @@ -121,6 +137,7 @@ function createWebSocket(token, onMessage) { stopHeartbeat(); socket = null; isConnecting = false; + uni.$emit("shoot-socket-disconnected"); if (manualClose || kickedOut) return; await handleUnexpectedClose(onMessage);