From 58d0ee8ad722b5696d2fa662d912216c583142da Mon Sep 17 00:00:00 2001 From: ozh Date: Wed, 9 Sep 2026 17:43:22 +0800 Subject: [PATCH] =?UTF-8?q?fix(device):=20=E4=BF=AE=E5=A4=8D=E9=85=8D?= =?UTF-8?q?=E7=BD=91=E9=A1=B5=E8=93=9D=E7=89=99=E6=90=9C=E7=B4=A2=E6=97=A0?= =?UTF-8?q?=E6=B3=95=E5=81=9C=E6=AD=A2=E4=B8=8E=E7=BD=91=E7=BB=9C=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E6=8C=89=E9=92=AE=E5=A4=B1=E6=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 与重构前 uni-app 版逐项对比定位三处回归: - useDidHide 停搜索:旧版 onHide/onUnload 双触发,迁移版只有 useEffect 卸载清理,navigateTo 进入配网页或切后台时组件不卸载,扫描持续空转 - prepareWifiConfig 加 60s 超时兜底:createBLEConnection 在部分机型 失败后不回调,discoverServices/notify 无原生超时,loading 遮罩 永不撤除导致按钮永久禁用 - 连接失败后安全断开(对齐旧版 safeDisconnect):清掉 OS 层残留连接, 避免"已连接(10010)"卡死后续重试;并补回"设备已连接"成功提示 --- src/pages/device/ble-config.tsx | 38 ++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/src/pages/device/ble-config.tsx b/src/pages/device/ble-config.tsx index a134a25..5121b8b 100644 --- a/src/pages/device/ble-config.tsx +++ b/src/pages/device/ble-config.tsx @@ -1,20 +1,35 @@ import { useEffect, useState } from 'react' -import Taro from '@tarojs/taro' +import Taro, { useDidHide } from '@tarojs/taro' import { View, Text } from '@tarojs/components' import { Navbar } from '@/components/navbar' import { useBle } from '@/ble/hooks/useBle' import { navigateTo } from '@/utils/navigation' import { ROUTES } from '@/constants/routes' import { getErrorMessage } from '@/utils/error' +import { showToast } from '@/utils/toast' import { DEVICE_ACTION_KEYS, ACTION_REGISTRY, isEp832Device } from '@/constants/deviceActions' import type { BleDevice } from '@/ble/hooks/useBle' import styles from './ble-config.module.scss' +// createBLEConnection 最多 3 次尝试(15s 超时 + 1.2s 重试间隔)约 47s, +// 兜底覆盖 discoverServices/notify 无原生超时的场景,保证 loading 遮罩必然撤除 +const PREPARE_WIFI_TIMEOUT_MS = 60000 + +function withTimeout(promise: Promise, ms: number, message: string): Promise { + return Promise.race([ + promise, + new Promise((_, reject) => { + setTimeout(() => reject(new Error(message)), ms) + }) + ]) +} + export default function DeviceBleConfig() { const { state, discovery } = useBle() const [preparingId, setPreparingId] = useState('') - // 页面隐藏/卸载时清理搜索(对齐旧版 onHide/onUnload),连接保持供配网页使用 + // 页面隐藏(navigateTo 配网页/切后台)与卸载(返回)时停搜索,连接保持供配网页使用。 + // useEffect 的清理只在卸载触发,压栈后台时组件不卸载,必须补 useDidHide(对齐旧版 onHide/onUnload) useEffect(() => { return () => { if (discovery.getState().isSearching) { @@ -24,6 +39,12 @@ export default function DeviceBleConfig() { // eslint-disable-next-line react-hooks/exhaustive-deps }, []) + useDidHide(() => { + if (discovery.getState().isSearching) { + discovery.stopSearch(false) + } + }) + const startScan = async () => { if (state.searching) { await discovery.stopSearch() @@ -46,10 +67,19 @@ export default function DeviceBleConfig() { let prepError: unknown = null try { - await discovery.prepareWifiConfig(deviceId) + // createBLEConnection 部分机型失败后不回调(微信基础库缺陷), + // discoverServices/notify 也无原生超时;不设兜底会导致 loading 永不消失、按钮永久失效 + await withTimeout( + discovery.prepareWifiConfig(deviceId), + PREPARE_WIFI_TIMEOUT_MS, + `连接设备超时(${PREPARE_WIFI_TIMEOUT_MS / 1000}s),请重试` + ) navigateTo(ROUTES.DEVICE_CONFIG) } catch (error) { prepError = error + // 对齐旧版 safeDisconnect:连接半途失败时清掉 OS 层残留连接, + // 否则后续重试会被"已连接(10010)"错误卡死 + discovery.disconnectDevice().catch(() => {}) } finally { setPreparingId('') // showLoading 与 showToast 共用同一遮罩层,必须先 hideLoading 再弹提示 @@ -64,6 +94,8 @@ export default function DeviceBleConfig() { showCancel: false, confirmText: '知道了' }) + } else { + showToast('设备已连接,请填写WiFi信息') } }