From e95d28a87ba5217bdf804fc8f8c116ba9e7a1dc7 Mon Sep 17 00:00:00 2001 From: 17792275749 <812100002@qq.com> Date: Tue, 25 Aug 2026 20:57:00 +0800 Subject: [PATCH] =?UTF-8?q?feat(lefu):=20=E5=88=87=E5=90=8E=E5=8F=B0?= =?UTF-8?q?=E6=8C=82=E8=B5=B7=E8=BF=9E=E6=8E=A5=E3=80=81=E5=9B=9E=E5=89=8D?= =?UTF-8?q?=E5=8F=B0=E8=87=AA=E5=8A=A8=E9=87=8D=E8=BF=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.7 --- miniprogram/app.ts | 24 ++++++++++++++-- miniprogram/lefu/service.ts | 56 +++++++++++++++++++++++++++++++++---- 2 files changed, 73 insertions(+), 7 deletions(-) diff --git a/miniprogram/app.ts b/miniprogram/app.ts index 9aff22c..551d16b 100644 --- a/miniprogram/app.ts +++ b/miniprogram/app.ts @@ -1,6 +1,9 @@ - App({ + import { leFuService } from './lefu/index' + +App({ globalData: { - operationsEngineer: false + operationsEngineer: false, + wasConnected: false }, onLaunch() { @@ -15,6 +18,23 @@ } }, + onHide() { + // 切后台:记录连接状态,挂起(断开但保留缓存设备,回前台可重连) + const wasConnected = leFuService.isConnected + this.globalData.wasConnected = wasConnected + if (wasConnected) { + leFuService.suspend() + } + }, + + onShow() { + // 回前台:如果之前连接过,自动重连 + if (this.globalData.wasConnected) { + this.globalData.wasConnected = false + leFuService.autoConnect() + } + }, + getWxLoginCode(): Promise { return new Promise((resolve, reject) => { wx.login({ diff --git a/miniprogram/lefu/service.ts b/miniprogram/lefu/service.ts index 3691cd5..2b62dde 100644 --- a/miniprogram/lefu/service.ts +++ b/miniprogram/lefu/service.ts @@ -45,7 +45,18 @@ class LeFuService { private _reconnectTimer: number | null = null /** 保活心跳定时器 */ private _keepAliveTimer: number | null = null - /** 最近一次连接/扫描到的原始设备(用于断线重连) */ + /** + * 最近一次连接/扫描到的原始设备(内存缓存) + * 用途: + * 1. 意外断线时自动重连(_doReconnect / connectState READY 分支) + * 2. 切后台回前台后自动重连(autoConnect) + * 3. 业务层通过 lastRawDevice 判断「当前连接的是哪台设备」 + * 生命周期: + * - connect() 时写入 + * - disconnect() 主动断开时清空(用户主动断开,不再需要重连) + * - suspend() 切后台时保留(回前台 autoConnect 靠它重连) + * - 意外断开时保留(自动重连靠它) + */ private _lastRawDevice: RawDevice | null = null // ─── 事件回调(每个事件支持多个监听者,用 Set 存储) ─── @@ -211,8 +222,10 @@ class LeFuService { plugin.bus.subscribe('deviceWillDisconnect', () => { console.warn(TAG, 'bus[deviceWillDisconnect],intentionalConnect:', this._intentionalConnect) this._stopKeepAlive() - this._activeProtocol = null - this._onDisconnectedCbs.forEach(cb => cb()) + if (this._activeProtocol) { + this._activeProtocol = null + this._onDisconnectedCbs.forEach(cb => cb()) + } if (!this._intentionalConnect) { this._doReconnect() } @@ -245,14 +258,47 @@ class LeFuService { } /** - * 主动断开连接 - * 标记主动断开以阻止自动重连,并停止保活。 + * 主动断开连接(用户主动操作:断开、退出登录、取消配对) + * - 断开蓝牙连接、停止保活 + * - 清理 _activeProtocol(主动断开立即清,不依赖后台事件,避免残留) + * - 清空 _lastRawDevice(主动断开后不再需要自动重连,避免残留) */ disconnect(): void { console.log(TAG, 'disconnect()') this._intentionalConnect = true this._stopKeepAlive() plugin.Blue.disconnect() + if (this._activeProtocol) { + this._activeProtocol = null + this._onDisconnectedCbs.forEach(cb => cb()) + } + this._lastRawDevice = null + } + + /** + * 切后台挂起(小程序 onHide 时调用) + * 和 disconnect 的唯一区别:断开连接、清理 _activeProtocol,但【保留 _lastRawDevice】, + * 这样回前台时 autoConnect 才能用缓存的设备重连。 + */ + suspend(): void { + console.log(TAG, 'suspend()') + this._intentionalConnect = true + this._stopKeepAlive() + plugin.Blue.disconnect() + if (this._activeProtocol) { + this._activeProtocol = null + this._onDisconnectedCbs.forEach(cb => cb()) + } + } + + /** + * 回前台自动重连(小程序 onShow 时调用) + * 用 suspend 保留的 _lastRawDevice 重连;已连接或无缓存设备则跳过。 + */ + autoConnect(): void { + if (this.isConnected) return + if (!this._lastRawDevice) return + this.connect(this._lastRawDevice) } /**