[AI Generated]: feat(*): 修复连接设备页及配网页交互逻辑、蓝牙状态显示与设备名获取

This commit is contained in:
17792275749
2026-05-14 17:18:10 +08:00
parent 29680cb7a4
commit 00a1529256
14 changed files with 402 additions and 155 deletions
@@ -1,103 +1,189 @@
import { lefuService } from '../../lefu/index'
import type { ScannedDevice } from '../../lefu/index'
/** 展示用设备项 */
/** 展示用设备项(仅存入 setData,不含复杂对象) */
interface DeviceItem {
/** 设备名称 */
name: string
/** 是否已连接 */
connected: boolean
/** 原始设备对象(连接时传回给 SDK) */
_raw: ScannedDevice
}
/** 页面状态 */
type DeviceStatus = 'idle' | 'searching' | 'found' | 'empty'
/** 页面级原始设备缓存,不进入 setData 避免序列化异常 */
let _rawDevices: ScannedDevice[] = []
const TAG = '[connectedDevice]'
Page({
data: {
/**
* 页面状态
* - idle: 未搜索(进入页面默认态)
* - searching: 扫描中
* - found: 扫描完成且有设备
* - empty: 扫描完成但无设备
*/
status: 'idle' as DeviceStatus,
/** 扫描到的设备列表 */
deviceList: [] as DeviceItem[],
/** 防止权限弹框重入 */
_modalLock: false,
},
onShow() {
// 注册回调后开始扫描
lefuService.onDevicesList((devices) => {
if (!devices.length) {
this.setData({ status: 'empty', deviceList: [] })
return
}
const list: DeviceItem[] = devices.map(d => ({
name: d.name,
connected: false,
_raw: d,
}))
this.setData({ status: 'found', deviceList: list })
})
lefuService.onConnectState((state) => {
const plugin = lefuService['_plugin']
if (!plugin) return
if (state === plugin.BLUE_STATE.CONNECTSUCCESS) {
// 蓝牙连接成功,存储设备信息后跳配网页
const connected = this.data.deviceList.find(d => d.connected)
if (connected) {
wx.setStorageSync('connectDeviceInfo', { name: connected.name })
}
wx.navigateTo({ url: '/pages/connectedWifi/connectedWifi' })
} else if (state === plugin.BLUE_STATE.WIFISUCCESS) {
// 设备已配网,直接进首页
wx.reLaunch({ url: '/pages/home/home' })
}
})
this.onStartSearch()
console.log(TAG, 'onShow')
},
onHide() {
// 页面隐藏时停止扫描,释放 bus 订阅
console.log(TAG, 'onHide, 停止扫描')
lefuService.stopScan()
},
onUnload() {
console.log(TAG, 'onUnload, 停止扫描')
lefuService.stopScan()
},
/** 开始 / 重新搜索 */
onStartSearch() {
/** 点击「开始搜索 / 重新搜索」按钮:先验权限,再扫描 */
async onStartSearch() {
console.log(TAG, 'onStartSearch, _modalLock:', this.data._modalLock)
if (this.data._modalLock) return
_rawDevices = []
this.setData({ status: 'searching', deviceList: [] })
await this._checkPermissionAndScan()
},
/** 检查蓝牙 + 位置权限,通过后开始扫描 */
async _checkPermissionAndScan() {
console.log(TAG, '_checkPermissionAndScan 开始')
try {
const { authSetting } = await wx.getSetting()
const setting = authSetting as Record<string, boolean | undefined>
const hasBle = setting['scope.bluetooth']
const hasLoc = setting['scope.userLocation']
console.log(TAG, '权限状态 → 蓝牙:', hasBle, '位置:', hasLoc)
if (hasBle && hasLoc) {
await this._openAdapterAndScan()
return
}
// 逐个申请缺失权限
const missing: Array<{ scope: string; label: string }> = []
if (!hasBle) missing.push({ scope: 'scope.bluetooth', label: '蓝牙' })
if (!hasLoc) missing.push({ scope: 'scope.userLocation', label: '位置' })
console.log(TAG, '缺失权限:', missing.map(m => m.label))
try {
for (const item of missing) {
console.log(TAG, '申请权限:', item.scope)
await wx.authorize({ scope: item.scope })
console.log(TAG, '权限申请成功:', item.scope)
}
await this._openAdapterAndScan()
} catch (err) {
console.warn(TAG, '权限申请被拒绝:', err)
this._showPermissionModal(missing.map(m => m.label).join('和'))
}
} catch (err) {
console.error(TAG, 'getSetting 失败:', err)
wx.showToast({ title: '获取权限设置失败', icon: 'none' })
this.setData({ status: 'idle' })
}
},
/** 引导用户去设置页开启权限 */
_showPermissionModal(permissionNames: string) {
console.log(TAG, '弹出权限引导框, 缺失:', permissionNames)
this.setData({ _modalLock: true })
wx.showModal({
title: '需要授权',
content: `小程序需要您的${permissionNames}权限才能搜索蓝牙设备,请前往手机设置开启。`,
confirmText: '去开启',
cancelText: '取消',
success: (res) => {
console.log(TAG, '权限弹框结果:', res.confirm ? '去开启' : '取消')
this.setData({ _modalLock: false, status: 'idle' })
if (res.confirm) {
wx.openSetting({
success: () => this.onStartSearch(),
})
}
},
fail: () => {
this.setData({ _modalLock: false, status: 'idle' })
},
})
},
/** 打开蓝牙适配器,成功后启动扫描 */
async _openAdapterAndScan() {
console.log(TAG, 'wx.openBluetoothAdapter() 开始')
try {
await wx.openBluetoothAdapter()
console.log(TAG, 'wx.openBluetoothAdapter() 成功')
this._startScan()
} catch (err: any) {
console.error(TAG, 'wx.openBluetoothAdapter() 失败, errCode:', err?.errCode, err?.errMsg)
if (err?.errCode === 10001) {
wx.showModal({
title: '蓝牙未开启',
content: '请先开启手机蓝牙后重试',
showCancel: false,
confirmText: '知道了',
success: () => this.setData({ status: 'idle' }),
})
} else {
wx.showToast({ title: '蓝牙初始化失败', icon: 'none' })
this.setData({ status: 'idle' })
}
}
},
/** 权限已就绪,注册设备列表回调并启动扫描 */
_startScan() {
console.log(TAG, '_startScan 启动')
lefuService.onDevicesList((devices) => {
console.log(TAG, 'onDevicesList 回调, 设备数:', devices.length, devices.map(d => d.name))
if (!devices.length) {
_rawDevices = []
this.setData({ status: 'empty', deviceList: [] })
return
}
_rawDevices = devices
// 保留已连接设备的状态,避免扫描刷新时把 connected 重置为 false
const connectedName = this.data.deviceList.find(d => d.connected)?.name
const list: DeviceItem[] = devices.map(d => ({
name: d.name,
connected: d.name === connectedName,
}))
this.setData({ status: 'found', deviceList: list })
})
lefuService.startScan()
console.log(TAG, 'lefuService.startScan() 已调用')
},
/** 连接指定设备 */
onConnect(e: WechatMiniprogram.TouchEvent) {
const index = e.currentTarget.dataset.index as number
const target = this.data.deviceList[index]
if (!target) return
const raw = _rawDevices[index]
console.log(TAG, 'onConnect, index:', index, 'device:', raw)
if (!raw) {
console.warn(TAG, 'onConnect: 找不到对应 raw device, index:', index)
return
}
// 更新 UI 连接状态
const list = this.data.deviceList.map((item, i) => ({
...item,
connected: i === index,
}))
this.setData({ deviceList: list })
// 调用 SDK 连接(BleAdv 类型已在 startScan 内自动处理,BleConnect 类型需此处触发)
lefuService.connect(target._raw)
wx.showLoading({ title: '连接中...', mask: true })
lefuService.connect(raw)
lefuService.onDeviceConnect(() => {
const list = this.data.deviceList.map((item, i) => ({
...item,
connected: i === index,
}))
this.setData({ deviceList: list })
wx.hideLoading()
console.log(TAG, '设备连接就绪,跳转配网页')
wx.navigateTo({ url: '/pages/connectedWifi/connectedWifi' })
})
},
/** 断开当前连接 */
onDisconnect() {
console.log(TAG, 'onDisconnect')
const list = this.data.deviceList.map(item => ({ ...item, connected: false }))
this.setData({ deviceList: list })
lefuService.disconnect()