- 连接中关闭蓝牙立即结束 loading,不再卡到超时 - onShow 已连接时同步标记,重新搜索不误标已连接设备 - 连接中防重入,搜索中切后台重置状态 - 配网成功立即退出配网模式,密码必填且 8-16 位 - 配网失败重试定时器可清理 - 同名设备改用 deviceId 唯一标识并展示 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
173 lines
5.9 KiB
TypeScript
173 lines
5.9 KiB
TypeScript
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' })
|
||
},
|
||
})
|