Files
bodyWeight/miniprogram/pages/connectedWifi/connectedWifi.ts
T
17792275749andClaude Opus 4.7 db865748f2 fix(device): 修复设备连接与配网多场景问题,同名设备用 deviceId 区分
- 连接中关闭蓝牙立即结束 loading,不再卡到超时
- onShow 已连接时同步标记,重新搜索不误标已连接设备
- 连接中防重入,搜索中切后台重置状态
- 配网成功立即退出配网模式,密码必填且 8-16 位
- 配网失败重试定时器可清理
- 同名设备改用 deviceId 唯一标识并展示

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-08-21 09:35:18 +08:00

173 lines
5.9 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 项(在 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 (!this._ensureConnected()) {
this.setData({ status: 'idle', wifiList: [] })
return
}
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' })
}
},
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.navigateTo({ url: '/pages/equipment/equipment' })
},
})