[AI Generated]: feat(*): 修复连接设备页及配网页交互逻辑、蓝牙状态显示与设备名获取
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
height: 100%;
|
||||
padding: 48rpx 30rpx 0;
|
||||
box-sizing: border-box;
|
||||
background-color: #ffffff;
|
||||
|
||||
/* 三层同心圆波纹动画 */
|
||||
.ripple {
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
<!-- 找到设备:统一循环,内部按 connected 切换 UI -->
|
||||
<block wx:if="{{ status === 'found' }}">
|
||||
<view class="device-list">
|
||||
<block wx:for="{{ deviceList }}" wx:key="id">
|
||||
<block wx:for="{{ deviceList }}" wx:key="name">
|
||||
<view class="device-card">
|
||||
<view class="card-icon"></view>
|
||||
<view class="card-info">
|
||||
|
||||
Reference in New Issue
Block a user