Files
bodyWeight/miniprogram/pages/connectedWifi/connectedWifi.ts
T
17792275749andClaude Opus 4.7 dbb2ab8423 fix: 修复蓝牙连接误报与 WiFi 列表获取问题,完善一键添加本人
- connectedDevice 忽略 connect 过程中的 UNAVAILABLE 抖动,避免误报蓝牙关闭
- getWifiList 加 settled 保护,onStartSearch 加防重入
- userManagement 一键添加本人(仅加后台、不下发设备)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-08-27 14:02:21 +08:00

179 lines
6.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { leFuService } from '../../lefu/index'
/** 连接状态事件的取消订阅句柄 */
let unsubDisconnected: (() => void) | null = null
let unsubDeviceConnect: (() => void) | null = null
let retryTimer: number | null = null
/** 获取 WiFi 列表防重入标记 */
let searching = false
/** 渲染用的 WiFi 项(在 SSID 基础上追加连接状态) */
interface WifiItem {
ssid: string
connected: boolean
}
type WifiStatus = 'idle' | 'searching' | 'list' | 'empty' | 'password' | 'configuring'
type BleStatus = 'connected' | 'failed' | 'connecting'
Page({
data: {
status: 'idle' as WifiStatus,
deviceName: '智能体重秤',
bleStatus: 'connected' as BleStatus,
wifiList: [] as WifiItem[],
hasConnected: false,
selectedSsid: '',
selectWifiPWD: '',
type: true,
},
onLoad() {
this._initDeviceInfo()
this._subscribeDisconnect()
this.onStartSearch()
},
onUnload() {
wx.hideLoading()
if (retryTimer !== null) { clearTimeout(retryTimer); retryTimer = null }
unsubDisconnected?.()
unsubDeviceConnect?.()
unsubDisconnected = null
unsubDeviceConnect = null
leFuService.exitWifiConfig()
},
/** 订阅连接状态事件:断开 / 重连时同步状态到 UI */
_subscribeDisconnect() {
unsubDisconnected?.()
unsubDeviceConnect?.()
unsubDisconnected = leFuService.onDisconnected(() => {
this.setData({ bleStatus: 'failed' })
})
unsubDeviceConnect = leFuService.onDeviceConnect(() => {
this.setData({ bleStatus: 'connected' })
})
},
/** 初始化设备信息:读取缓存设备名 + 同步蓝牙连接状态 */
_initDeviceInfo() {
const cached = wx.getStorageSync('connectDeviceInfo') as Record<string, any> | null
const deviceName = cached?.scaleDeviceName || cached?.name
if (deviceName) {
this.setData({ deviceName })
}
this.setData({ bleStatus: leFuService.isConnected ? 'connected' : 'failed' })
},
/** 校验设备连接状态:未连接则同步状态 + 提示,返回是否可继续操作 */
_ensureConnected(): boolean {
if (leFuService.isConnected) return true
this.setData({ bleStatus: 'failed' })
wx.showToast({ title: '设备已断开,请重新连接', icon: 'none' })
return false
},
/** 通过设备协议获取周围 WiFi 列表 */
async onStartSearch() {
if (searching) return
if (!this._ensureConnected()) {
this.setData({ status: 'idle', wifiList: [] })
return
}
searching = true
this.setData({ status: 'searching', wifiList: [] })
wx.showLoading({ title: '正在获取 WiFi 列表...', mask: true })
try {
const list = await leFuService.getWifiList()
wx.hideLoading()
if (!list.length) {
this.setData({ status: 'empty', wifiList: [] })
return
}
this.setData({
status: 'list',
wifiList: list.map(item => ({ ssid: item.ssid, connected: false })),
})
} catch {
wx.hideLoading()
this.setData({ status: 'empty', wifiList: [] })
wx.showToast({ title: '获取 WiFi 列表失败', icon: 'none' })
} finally {
searching = false
}
},
onRefresh() {
this.onStartSearch()
},
onTapWifi(e: WechatMiniprogram.TouchEvent) {
if (!this._ensureConnected()) return
const ssid = e.currentTarget.dataset.ssid as string
const target = this.data.wifiList.find(item => item.ssid === ssid)
if (!target || target.connected) return
this.setData({ status: 'password', selectedSsid: ssid, selectWifiPWD: '', type: true })
},
passwordInput(e: WechatMiniprogram.Input) {
this.setData({ selectWifiPWD: e.detail.value })
},
inputTypeChange() {
this.setData({ type: !this.data.type })
},
onCancelPwd() {
this.setData({ status: 'list', selectedSsid: '', selectWifiPWD: '' })
},
/** 下发配网指令,成功后标记对应 WiFi 已连接 */
async onConfirmPwd() {
if (!this._ensureConnected()) return
const { selectedSsid, selectWifiPWD } = this.data
if (!selectedSsid) return
const pwd = selectWifiPWD.trim()
if (!pwd) {
wx.showToast({ title: '请输入 Wi-Fi 密码', icon: 'none' })
return
}
if (pwd.length < 8 || pwd.length > 16) {
wx.showToast({ title: '密码长度需为 8-16 位', icon: 'none' })
return
}
this.setData({ status: 'configuring' })
wx.showLoading({ title: '正在配网...', mask: true })
try {
await leFuService.configWifi(selectedSsid, pwd)
wx.hideLoading()
// 配网成功:立即退出配网模式(跳转走 onHide,不触发 onUnload
leFuService.exitWifiConfig()
this.setData({
status: 'list',
wifiList: this.data.wifiList.map(item => ({ ...item, connected: item.ssid === selectedSsid })),
hasConnected: true,
selectedSsid: '',
selectWifiPWD: '',
})
wx.showToast({ title: '配网成功', icon: 'success' })
} catch (err: any) {
wx.hideLoading()
this.setData({ selectedSsid: '', selectWifiPWD: '' })
wx.showToast({ title: err?.message || '配网失败', icon: 'none' })
// 配网失败:延时 1.5s 后清空数据并重新获取 WiFi 列表
if (retryTimer !== null) { clearTimeout(retryTimer); retryTimer = null }
retryTimer = setTimeout(() => {
retryTimer = null
this.onStartSearch()
}, 1500)
}
},
onConfirm() {
if (!this.data.hasConnected) return
if (!this._ensureConnected()) return
wx.reLaunch({ url: '/pages/equipment/equipment' })
},
})