update:提交我的设备改版

This commit is contained in:
2026-09-17 18:23:41 +08:00
parent 46cbd37102
commit b060d8f987
50 changed files with 897 additions and 590 deletions
+74 -74
View File
@@ -1,15 +1,19 @@
<script setup>
import { ref, computed, onMounted, onUnmounted } from "vue";
import { ref, computed, onMounted, onUnmounted, watch } from "vue";
import { onLoad, onShow } from "@dcloudio/uni-app";
import Container from "@/components/Container.vue";
import ScreenHint from "@/components/ScreenHint.vue";
import {
connectDeviceWifiAPI,
getDeviceBatteryAPI,
getHardwareBoxTaskStatusAPI,
getHardwareBoxVersionAPI,
sendHardwareBoxUpdateAPI,
} from "@/apis";
import useStore from "@/store";
import { storeToRefs } from "pinia";
const store = useStore();
const { deviceStatus } = storeToRefs(store);
const STATES = {
SCANNING: "SCANNING",
@@ -48,14 +52,13 @@ const progress = ref(0);
let progressTimer = null;
let timeoutTimer = null;
let statusTimer = null;
let wifiConnectTimer = null;
let wifiConnectTimeoutTimer = null;
let stopWifiStatusWatcher = null;
let settleWifiConnectWaiting = null;
let wifiConnectRequestId = 0;
let wifiConnectPollCount = 0;
const WIFI_CONNECT_POLL_INTERVAL = 2000;
const WIFI_CONNECT_MAX_POLL_COUNT = 30;
const WIFI_CONNECT_TIMEOUT = 60000;
const DEVICE_STATUS_STALE_TIME = 6000;
const WIFI_CONNECT_FAILED_TEXT = "连接失败,请检查WiFi密码或WiFi状态";
const OTA_MIN_BATTERY = 50;
const OTA_LOW_BATTERY_TEXT = "电量不足 50%,暂不支持 OTA 升级";
// 控制授权拒绝弹窗显示/隐藏
const wifiAuthDeniedVisible = ref(false);
@@ -207,7 +210,7 @@ const startScanning = () => {
// 选择列表中的 WiFi,并打开密码输入弹窗。
const selectWifi = (wifi) => {
cancelWifiConnectPolling();
cancelWifiConnectWaiting();
connectingWifi.value = wifi;
connectInput.value = { ssid: wifi.SSID, password: "" };
connectMode.value = wifi.secure ? "secure" : "open";
@@ -217,7 +220,7 @@ const selectWifi = (wifi) => {
// 选择手动输入 WiFi,并打开手动输入弹窗。
const selectOther = () => {
cancelWifiConnectPolling();
cancelWifiConnectWaiting();
connectingWifi.value = null;
connectInput.value = { ssid: "", password: "" };
connectMode.value = "manual";
@@ -225,9 +228,9 @@ const selectOther = () => {
currentState.value = STATES.CONNECTING;
};
// 关闭连接弹窗,并停止当前 WiFi 连接轮询。
// 关闭连接弹窗,并停止等待当前 WiFi 连接结果。
const closeConnectSheet = () => {
cancelWifiConnectPolling();
cancelWifiConnectWaiting();
connectError.value = "";
currentState.value = connectedWifi.value ? STATES.CONNECTED : STATES.LIST;
};
@@ -257,89 +260,84 @@ const wifiListScrollHeight = computed(() => {
return `${Math.min(itemCount * 92, maxHeight)}rpx`;
});
// 清理 WiFi 连接轮询定时器。
const clearWifiConnectTimer = () => {
clearTimeout(wifiConnectTimer);
wifiConnectTimer = null;
wifiConnectPollCount = 0;
// 清理本次 WiFi 连接状态监听和超时计时器。
const clearWifiConnectWatcher = () => {
clearTimeout(wifiConnectTimeoutTimer);
wifiConnectTimeoutTimer = null;
if (stopWifiStatusWatcher) {
stopWifiStatusWatcher();
stopWifiStatusWatcher = null;
}
};
// 取消当前 WiFi 连接轮询,并恢复弹窗提交状态。
const cancelWifiConnectPolling = () => {
// 取消当前 WiFi 连接确认,并恢复弹窗提交状态。
const cancelWifiConnectWaiting = () => {
wifiConnectRequestId += 1;
clearWifiConnectTimer();
if (settleWifiConnectWaiting) {
settleWifiConnectWaiting(false);
}
clearWifiConnectWatcher();
connectStatusText.value = "";
isSubmittingWifi.value = false;
uni.hideLoading();
};
// 判断设备电量接口返回的 online/netType 字段,确定设备是否已通过 WiFi 在线。
// 返回值含义:true → WiFi 在线成功;"net_fail" → 设备走 4g 失败;false → 未就绪,需继续轮询。
// 根据实时推送的 online/netType 判断设备是否已通过 WiFi 在线。
// 返回值含义:true → WiFi 在线成功;"net_fail" → 设备走 4g 失败;false → 未就绪。
const isDeviceConnectedByWifi = (deviceStatus) => {
// online 不为 true → 设备不在线,需继续轮询
// online 不为 true → 设备尚未在线,继续等待推送
if (deviceStatus?.online !== true) return false;
const netType = String(deviceStatus?.netType || "").toLowerCase();
// online:true + netType:4g → 设备已切 4g,WiFi 连接失败
if (netType === "4g") return "net_fail";
// online:true + netType:wifi → WiFi 连接成功
// online:true + netType:"" → 设备在线但 netType 暂未上报,继续轮询等待
// online:true + netType:"" → 设备在线但 netType 暂未上报,继续等待推送
return netType === "wifi";
};
// 轮询设备电量接口,等待设备切到 WiFi 在线;netType:4g 快速失败,超时 30 次后放弃。
const waitForDeviceWifiConnected = (requestId) => {
// 等待提交配置后的新 WS 状态;忽略提交前的旧状态,超时后按连接失败处理。
const waitForDeviceWifiConnected = (requestId, receivedAfter) => {
return new Promise((resolve) => {
const poll = async () => {
if (requestId !== wifiConnectRequestId) {
resolve(false);
return;
}
wifiConnectPollCount += 1;
try {
const deviceStatus = await getDeviceBatteryAPI();
if (requestId !== wifiConnectRequestId) {
resolve(false);
return;
}
const connResult = isDeviceConnectedByWifi(deviceStatus);
// online:true + netType:wifi → 成功
if (connResult === true) {
resolve(true);
return;
}
// online:true + netType:4g → 立即失败(设备已切 4g,WiFi 连不上)
if (connResult === "net_fail") {
resolve(false);
return;
}
// online:false + netType:"" → 继续轮询
// online:true + netType:"" → 忽略,继续轮询(netType 暂未上报)
} catch (err) {
if (requestId !== wifiConnectRequestId) {
resolve(false);
return;
}
}
if (wifiConnectPollCount >= WIFI_CONNECT_MAX_POLL_COUNT) {
resolve(false);
return;
}
wifiConnectTimer = setTimeout(poll, WIFI_CONNECT_POLL_INTERVAL);
let settled = false;
const finish = (result) => {
if (settled) return;
settled = true;
clearWifiConnectWatcher();
settleWifiConnectWaiting = null;
resolve(result);
};
poll();
settleWifiConnectWaiting = finish;
stopWifiStatusWatcher = watch(
deviceStatus,
(status) => {
if (requestId !== wifiConnectRequestId) {
finish(false);
return;
}
if (Number(status?.receivedAt) <= receivedAfter) return;
const connResult = isDeviceConnectedByWifi(status);
if (connResult === true) {
finish(true);
} else if (connResult === "net_fail") {
finish(false);
}
}
);
wifiConnectTimeoutTimer = setTimeout(
() => finish(false),
WIFI_CONNECT_TIMEOUT
);
});
};
// 提交 WiFi 配置给游戏设备,并轮询确认设备真实连上 WiFi 后再展示成功。
// 提交 WiFi 配置给游戏设备,并通过 WS 确认设备真实连上 WiFi 后再展示成功。
const submitDeviceWifiConfig = async ({ ssid, password }) => {
if (isSubmittingWifi.value) return;
wifiConnectRequestId += 1;
const requestId = wifiConnectRequestId;
clearWifiConnectTimer();
clearWifiConnectWatcher();
isSubmittingWifi.value = true;
connectStatusText.value = "WiFi连接中...";
uni.showLoading({
@@ -348,7 +346,8 @@ const submitDeviceWifiConfig = async ({ ssid, password }) => {
});
try {
await connectDeviceWifiAPI(ssid, password);
const isConnected = await waitForDeviceWifiConnected(requestId);
if (requestId !== wifiConnectRequestId) return;
const isConnected = await waitForDeviceWifiConnected(requestId, Date.now());
if (requestId !== wifiConnectRequestId) return;
if (!isConnected) {
connectError.value = WIFI_CONNECT_FAILED_TEXT;
@@ -369,7 +368,7 @@ const submitDeviceWifiConfig = async ({ ssid, password }) => {
}
} finally {
if (requestId === wifiConnectRequestId) {
clearWifiConnectTimer();
clearWifiConnectWatcher();
connectStatusText.value = "";
isSubmittingWifi.value = false;
uni.hideLoading();
@@ -456,7 +455,9 @@ const pollUpdateTaskStatus = (taskId) => {
// 判断设备是否满足 OTA 更新条件,不满足时返回精确提示文案。
const getUpdateDisabledReason = (deviceStatus) => {
if (deviceStatus?.online !== true) return "请先开启智能弓";
if (Number(deviceStatus?.battery) <= OTA_MIN_BATTERY) return OTA_LOW_BATTERY_TEXT;
if (Date.now() - Number(deviceStatus?.receivedAt || 0) > DEVICE_STATUS_STALE_TIME) {
return "设备状态同步中,请稍后重试";
}
if (String(deviceStatus?.netType || "").toLowerCase() !== "wifi") return "设备当前未连接 WiFi,请先连接 WiFi 后再更新";
return "";
};
@@ -480,8 +481,7 @@ const startUpdate = async () => {
isStartingUpdate.value = true;
try {
const deviceStatus = await getDeviceBatteryAPI();
const disabledReason = getUpdateDisabledReason(deviceStatus);
const disabledReason = getUpdateDisabledReason(deviceStatus.value);
if (disabledReason) {
isStartingUpdate.value = false;
uni.showToast({
@@ -612,7 +612,7 @@ onUnmounted(() => {
if (typeof uni.offKeyboardHeightChange === "function") {
uni.offKeyboardHeightChange(handleKeyboardHeightChange);
}
cancelWifiConnectPolling();
cancelWifiConnectWaiting();
clearUpdateTimers();
wx.offGetWifiList && wx.offGetWifiList();
});