From a38db163bde31847d5ce7cc72af8dfbfb25762af Mon Sep 17 00:00:00 2001
From: 17792275749 <812100002@qq.com>
Date: Wed, 8 Apr 2026 11:09:30 +0800
Subject: [PATCH] =?UTF-8?q?[AI=20Generated]:=20fix(*):=20=E4=BF=AE?=
=?UTF-8?q?=E5=A4=8D=E8=93=9D=E7=89=99=E8=BF=9E=E6=8E=A5=E5=85=A8=E9=93=BE?=
=?UTF-8?q?=E8=B7=AF=E9=97=AE=E9=A2=98=EF=BC=8C=E5=8C=85=E5=90=AB=20bus=20?=
=?UTF-8?q?=E9=87=8D=E5=A4=8D=E8=AE=A2=E9=98=85=E3=80=81activeProtocol=20?=
=?UTF-8?q?=E7=A9=BA=E6=8C=87=E9=92=88=E3=80=81stop=20=E7=AB=9E=E9=80=9F?=
=?UTF-8?q?=E3=80=81=E9=87=8D=E8=BF=9E=E8=AE=A1=E6=95=B0=E5=99=A8=E8=B7=A8?=
=?UTF-8?q?=E9=A1=B5=E9=9D=A2=E5=85=B1=E4=BA=AB=E3=80=81OTA=20=E8=B6=85?=
=?UTF-8?q?=E6=97=B6=E4=BF=9D=E6=8A=A4=E3=80=81=E7=A1=AC=E8=B6=85=E6=97=B6?=
=?UTF-8?q?=E6=94=B9=E4=BA=8B=E4=BB=B6=E9=A9=B1=E5=8A=A8=E3=80=81=E4=BF=9D?=
=?UTF-8?q?=E6=B4=BB=E5=AE=9A=E6=97=B6=E5=99=A8=E6=B3=84=E6=BC=8F=E5=8F=8A?=
=?UTF-8?q?=E5=9B=9E=E8=B0=83=E9=94=99=E8=AF=AF=E5=A4=84=E7=90=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
app.js | 152 +++++++++++-------
.../configureDevice_2/configureDevice_2.js | 25 ++-
.../configureDevice_3/configureDevice_3.js | 29 ++--
.../configureDevice_4/configureDevice_4.js | 38 ++++-
pages/configureDevice/configureDevice.js | 70 ++++++--
pages/configureDevice/configureDevice.wxml | 2 +-
6 files changed, 219 insertions(+), 97 deletions(-)
diff --git a/app.js b/app.js
index ef920a8..9c2bfa6 100644
--- a/app.js
+++ b/app.js
@@ -6,7 +6,7 @@ App({
globalData: {
// wx.request 请求的服务地址
// wxRequestUrl: "https://device.shuziweidao.com/gateway/",
- wxRequestUrl: "http://192.168.1.209:8889/",
+ wxRequestUrl: "http://192.168.1.207:8889/",
// 秤的所有信息
ppScale: {
@@ -14,8 +14,8 @@ App({
plugin: null,
activeProtocol: null,
- domain1: "http://device.shuziweidao.com:80/gateway", // 老版本 没有鉴权
- domain2: "http://device.shuziweidao.com:80/weight", // 新版本 有鉴权
+ domain1: "http://192.168.1.207:8889", // 老版本 没有鉴权
+ domain2: "http://192.168.1.207:8889/weight", // 新版本 有鉴权
wifi: {
ssid: "",
password: ""
@@ -136,75 +136,118 @@ App({
mac: null, // 选中的设备mac地址/SN码
connection: null, // 默认选中连接的设备
connectState: null, // 当前连接设备的状态
+ },
+ reconnect: {
+ count: 0, // 当前已重连次数
+ max: 3, // 最大重连次数
+ timer: null // 重连定时器
}
},
_callbacks: {} // 用于存储所有 globalData 属性的监听回调
},
- _reconnectCount: 0, // 自动重连已尝试次数
- _reconnectMax: 3, // 最大自动重连次数
- _reconnectTimer: null, // 重连定时器
+ _reconnectCount: 0, // 已废弃,保留兼容,实际使用 globalData.ppScale.reconnect.count
+ _reconnectMax: 3, // 已废弃,保留兼容,实际使用 globalData.ppScale.reconnect.max
+ _reconnectTimer: null, // 已废弃,保留兼容,实际使用 globalData.ppScale.reconnect.timer
initPpScale() {
this.globalData.ppScale.plugin = requirePlugin('ppScale-plugin');
},
- /**
- * 注册全局 bus 事件监听(connectState / syncDeviceTimeSuccess / deviceWillDisconnect)
- * stop() 会销毁所有订阅,页面在 onShow 中需重新调用此方法
- */
- registerBusListeners() {
- const plugin = this.globalData.ppScale.plugin;
-
- // 蓝牙连接状态监听
- plugin.bus.subscribe("connectState", (res) => {
- console.log("app.js ===> connectState", res);
- this.setGlobalData('ppScale.device.connectState', res);
-
- // 连接成功,重置重连计数
- if (res == plugin.BLUE_STATE.CONNECTSUCCESS) {
- this._reconnectCount = 0;
- }
-
- // 连接失败,自动重连(最多重试3次)
- if (res == plugin.BLUE_STATE.CONNECTFAILED) {
- this.reconnectDevice();
- }
-
- wx.hideLoading();
- });
-
- // 同步时间
- plugin.bus.subscribe("syncDeviceTimeSuccess", (res) => {
- console.log("app.js ===> syncDeviceTimeSuccess", res);
- });
-
- // 设备自动断开监听
- plugin.bus.subscribe("deviceWillDisconnect", (res) => {
- console.log("app.js ===> deviceWillDisconnect", res);
- this.setGlobalData('ppScale.device.connectState', plugin.BLUE_STATE.CONNECTFAILED);
- });
+ // 存储 app 级 bus 回调引用,用于精准 unsubscribe
+ _busCallbacks: {
+ connectState: null,
+ syncDeviceTimeSuccess: null,
+ deviceWillDisconnect: null,
},
/**
- * 自动重连设备,最多重试 _reconnectMax 次,超过后停止,由用户手动重连
- * 流程:先断开旧连接,再重新扫描设备,由页面级 devicesList 订阅自动接管连接
+ * 注销全局 bus 事件监听,防止重复订阅叠加
+ */
+ unregisterBusListeners() {
+ const plugin = this.globalData.ppScale.plugin;
+ if (!plugin) return;
+ const cbs = this._busCallbacks;
+ if (cbs.connectState) {
+ plugin.bus.unsubscribe('connectState', cbs.connectState);
+ cbs.connectState = null;
+ }
+ if (cbs.syncDeviceTimeSuccess) {
+ plugin.bus.unsubscribe('syncDeviceTimeSuccess', cbs.syncDeviceTimeSuccess);
+ cbs.syncDeviceTimeSuccess = null;
+ }
+ if (cbs.deviceWillDisconnect) {
+ plugin.bus.unsubscribe('deviceWillDisconnect', cbs.deviceWillDisconnect);
+ cbs.deviceWillDisconnect = null;
+ }
+ },
+
+ /**
+ * 注册全局 bus 事件监听(connectState / syncDeviceTimeSuccess / deviceWillDisconnect)
+ * 调用前先 unsubscribe 旧的,防止多次 onShow 导致回调叠加
+ */
+ registerBusListeners() {
+ this.unregisterBusListeners();
+ const plugin = this.globalData.ppScale.plugin;
+
+ // 蓝牙连接状态监听
+ this._busCallbacks.connectState = (res) => {
+ console.log("app.js ===> connectState", res);
+ this.setGlobalData('ppScale.device.connectState', res);
+ if (res == plugin.BLUE_STATE.CONNECTSUCCESS) {
+ this.globalData.ppScale.reconnect.count = 0;
+ }
+ if (res == plugin.BLUE_STATE.CONNECTFAILED) {
+ this.reconnectDevice();
+ }
+ wx.hideLoading();
+ };
+
+ // 同步时间
+ this._busCallbacks.syncDeviceTimeSuccess = (res) => {
+ console.log("app.js ===> syncDeviceTimeSuccess", res);
+ };
+
+ // 设备自动断开监听
+ this._busCallbacks.deviceWillDisconnect = (res) => {
+ console.log("app.js ===> deviceWillDisconnect", res);
+ this.setGlobalData('ppScale.device.connectState', plugin.BLUE_STATE.CONNECTFAILED);
+ };
+
+ plugin.bus.subscribe('connectState', this._busCallbacks.connectState);
+ plugin.bus.subscribe('syncDeviceTimeSuccess', this._busCallbacks.syncDeviceTimeSuccess);
+ plugin.bus.subscribe('deviceWillDisconnect', this._busCallbacks.deviceWillDisconnect);
+ },
+
+ /**
+ * 自动重连设备,最多重试 max 次,超过后停止,由用户手动重连
+ * 只在配置页(configureDevice)活跃时执行,防止跨页面干扰
*/
reconnectDevice() {
- if (this._reconnectCount >= this._reconnectMax) {
+ const reconnect = this.globalData.ppScale.reconnect;
+
+ // 仅在配置页活跃时执行重连
+ const pages = getCurrentPages();
+ const currentPage = pages[pages.length - 1];
+ if (!currentPage || !currentPage.route || !currentPage.route.includes('configureDevice')) {
+ console.log("app.js ===> 非配置页,跳过自动重连");
+ return;
+ }
+
+ if (reconnect.count >= reconnect.max) {
console.log("app.js ===> 自动重连已达上限,等待用户手动重试");
return;
}
- this._reconnectCount++;
- console.log(`app.js ===> 自动重连第 ${this._reconnectCount}/${this._reconnectMax} 次`);
+ reconnect.count++;
+ console.log(`app.js ===> 自动重连第 ${reconnect.count}/${reconnect.max} 次`);
// 延迟 2 秒后重连,避免连续冲突
- if (this._reconnectTimer) {
- clearTimeout(this._reconnectTimer);
+ if (reconnect.timer) {
+ clearTimeout(reconnect.timer);
}
- this._reconnectTimer = setTimeout(() => {
+ reconnect.timer = setTimeout(() => {
this.globalData.ppScale.plugin.Blue.disconnect((disres) => {
if (disres.errCode == 0) {
console.log("app.js ===> 断开成功,开始重新扫描设备");
@@ -217,13 +260,14 @@ App({
},
/**
- * 重置重连计数,用于用户手动点击重试时调用
+ * 重置重连计数,用于用户手动点击重试或页面离开时调用
*/
resetReconnectCount() {
- this._reconnectCount = 0;
- if (this._reconnectTimer) {
- clearTimeout(this._reconnectTimer);
- this._reconnectTimer = null;
+ const reconnect = this.globalData.ppScale.reconnect;
+ reconnect.count = 0;
+ if (reconnect.timer) {
+ clearTimeout(reconnect.timer);
+ reconnect.timer = null;
}
},
diff --git a/components/configureDevice_2/configureDevice_2.js b/components/configureDevice_2/configureDevice_2.js
index 1e33205..9ad3cbd 100644
--- a/components/configureDevice_2/configureDevice_2.js
+++ b/components/configureDevice_2/configureDevice_2.js
@@ -95,7 +95,10 @@ Component({
addUser() {
if (this.data.userList.length >= 10) {
- wx.showToast({ title: "超过最大用户数", icon: "none" });
+ wx.showToast({
+ title: "超过最大用户数",
+ icon: "none"
+ });
return;
}
this.selectComponent("#configureDevice2AddUser").showModal();
@@ -178,19 +181,27 @@ Component({
wx.showLoading({ title: "正在同步用户信息...", mask: true });
app.globalData.ppScale.activeProtocol.dataFetchUserID((deviceUserIds) => {
console.log("设备端已有用户ID列表", deviceUserIds);
- let rawList = Array.isArray(deviceUserIds) ? deviceUserIds : [];
+
+ // 回调返回非数组视为获取失败
+ if (!Array.isArray(deviceUserIds)) {
+ wx.hideLoading();
+ wx.showToast({ title: "获取设备用户列表失败,请重试", icon: "none" });
+ return;
+ }
+
+ let rawList = deviceUserIds;
// 兼容对象数组和纯ID数组,统一转为字符串比对
let deviceIds = rawList.map(item => ({
id: item,
memberID: ""
}));
- let localIds = userList.map(user => user.id);
+ let localIds = userList.map(user => user.userId);
// 秤有、列表没有 → 需要从秤删除
- let needDeleteList = deviceIds.filter(d => !localIds.includes(d.id));
+ let needDeleteList = deviceIds.filter(d => !localIds.includes(d.userId));
// 秤没有、列表有 → 需要下发到秤
- let needSyncList = userList.filter(user => !deviceIds.some(d => d.userID == user.id));
+ let needSyncList = userList.filter(user => !deviceIds.some(d => d.userID == user.userId));
console.log("需删除", needDeleteList, "需下发", needSyncList);
@@ -218,7 +229,7 @@ Component({
wx.showLoading({ title: "正在下发第" + (syncIndex + 1) + "/" + needSyncList.length + "个用户...", mask: true });
let user = needSyncList[syncIndex];
app.globalData.ppScale.activeProtocol.dataSyncUserInfo({
- userID: user.id,
+ userID: user.userId,
userName: user.realname,
memberID: "",
age: user.age || '',
@@ -257,7 +268,7 @@ Component({
wx.showLoading({ title: "正在删除第" + (delIndex + 1) + "/" + needDeleteList.length + "个多余用户...", mask: true });
let item = needDeleteList[delIndex];
app.globalData.ppScale.activeProtocol.dataDeleteUser({
- userID: item.id,
+ userID: item.userId,
memberID: ""
}, (status) => {
if (status == 0) {
diff --git a/components/configureDevice_3/configureDevice_3.js b/components/configureDevice_3/configureDevice_3.js
index 34b7fc6..cbade93 100644
--- a/components/configureDevice_3/configureDevice_3.js
+++ b/components/configureDevice_3/configureDevice_3.js
@@ -14,31 +14,28 @@ Component({
lifetimes: {
attached() {
- this.initWifi();
+ // WiFi 列表获取由父页面在 activeProtocol 就绪后显式调用,此处不自动触发
},
detached() {
- // 在组件实例被从页面节点树移除时执行
- console.log('MyComponent detached!');
+ console.log('configureDevice3 detached');
}
},
// 组件的方法
methods: {
initWifi() {
- wx.showLoading({
- title: "正在获取Wi-Fi列表...",
- mask: true
+ wx.showLoading({ title: "正在获取Wi-Fi列表...", mask: true });
+ // activeProtocol 由父页面在 deviceConnect 回调中赋值,此处直接使用
+ const activeProtocol = app.globalData.ppScale.activeProtocol;
+ if (!activeProtocol) {
+ wx.hideLoading();
+ wx.showToast({ title: '设备未连接,请重试', icon: 'none' });
+ return;
+ }
+ activeProtocol.dataFindSurroundDevice((res) => {
+ wx.hideLoading();
+ this.setData({ wifiList: res });
});
- // 重新获取协议实例,避免用户同步操作后旧引用失效
- setTimeout(() => {
- app.globalData.ppScale.activeProtocol = app.globalData.ppScale.plugin.ScaleAction.getActiveProtocol();
- app.globalData.ppScale.activeProtocol.dataFindSurroundDevice((res) => {
- wx.hideLoading();
- this.setData({
- wifiList: res
- })
- })
- }, 1500);
},
// 最小化后重连,重置所有状态并重新获取 WiFi 列表
diff --git a/components/configureDevice_4/configureDevice_4.js b/components/configureDevice_4/configureDevice_4.js
index cb09624..86c6309 100644
--- a/components/configureDevice_4/configureDevice_4.js
+++ b/components/configureDevice_4/configureDevice_4.js
@@ -1,5 +1,8 @@
const app = getApp();
+// OTA 超时时间:3 分钟
+const OTA_TIMEOUT_MS = 3 * 60 * 1000;
+
Component({
data: {
otaProgress: 0,
@@ -9,8 +12,11 @@ Component({
lifetimes: {
attached() {
- // 组件挂载后自动触发 OTA 升级
- this.startOtaUpgrade();
+ // OTA 升级由父页面在 activeProtocol 就绪后显式调用,此处不自动触发
+ },
+ detached() {
+ // 组件销毁时清除超时定时器,防止泄漏
+ this._clearOtaTimer();
}
},
@@ -20,6 +26,14 @@ Component({
this.triggerEvent('deviceEvent', { status: true });
},
+ // 清除 OTA 超时定时器
+ _clearOtaTimer() {
+ if (this._otaTimer) {
+ clearTimeout(this._otaTimer);
+ this._otaTimer = null;
+ }
+ },
+
// 开始 OTA 升级
startOtaUpgrade() {
const activeProtocol = app.globalData.ppScale.activeProtocol;
@@ -37,6 +51,13 @@ Component({
otaMessage: '升级初始化中...'
});
+ // 启动超时保护,3 分钟内未完成则视为失败
+ this._clearOtaTimer();
+ this._otaTimer = setTimeout(() => {
+ console.log('OTA 升级超时');
+ this.handleOtaFailed('升级超时,设备即将重启');
+ }, OTA_TIMEOUT_MS);
+
// 回调参数为 { progress, isFailed }
activeProtocol.codeOtaUpdate((res) => {
console.log('OTA 升级回调:', res);
@@ -49,8 +70,10 @@ Component({
}
if (res && res.isFailed === false) {
+ this._clearOtaTimer();
this.handleOtaSuccess();
} else if (res && res.isFailed === true) {
+ this._clearOtaTimer();
this.handleOtaFailed();
}
});
@@ -66,21 +89,22 @@ Component({
});
wx.showToast({ title: 'OTA 升级成功', icon: 'success', duration: 2000 });
setTimeout(() => {
- this.triggerEvent('deviceEvent', { status: true });
+ this.bindOk();
}, 2000);
},
// OTA 升级失败处理
- handleOtaFailed() {
+ handleOtaFailed(msg) {
wx.hideLoading();
+ const message = msg || '升级失败,设备即将重启';
this.setData({
otaProgress: 0,
otaStatus: 'failed',
- otaMessage: '升级失败,设备即将重启'
+ otaMessage: message
});
- wx.showToast({ title: '升级失败,设备即将重启', icon: 'none', duration: 2000 });
+ wx.showToast({ title: message, icon: 'none', duration: 2000 });
setTimeout(() => {
- this.triggerEvent('deviceEvent', { status: true });
+ this.bindOk();
}, 2000);
}
}
diff --git a/pages/configureDevice/configureDevice.js b/pages/configureDevice/configureDevice.js
index aab08ae..771ab43 100644
--- a/pages/configureDevice/configureDevice.js
+++ b/pages/configureDevice/configureDevice.js
@@ -16,22 +16,46 @@ Page({
// 一次性数据初始化,订阅逻辑在 onShow 中注册
},
+ // 存储页面级 bus 回调引用,用于精准 unsubscribe
+ _pageHandlers: {
+ devicesModel: null,
+ deviceConnect: null,
+ devicesList: null,
+ },
+
+ // 注销页面级 bus 订阅
+ _unsubscribePageBus() {
+ const bus = ppScale.plugin.bus;
+ const h = this._pageHandlers;
+ if (h.devicesModel) { bus.unsubscribe('devicesModel', h.devicesModel); h.devicesModel = null; }
+ if (h.deviceConnect) { bus.unsubscribe('deviceConnect', h.deviceConnect); h.deviceConnect = null; }
+ if (h.devicesList) { bus.unsubscribe('devicesList', h.devicesList); h.devicesList = null; }
+ },
+
+ // 记录 stop() 调用时间,用于 onShow 动态计算安全延迟
+ _stopTime: 0,
+
onShow() {
console.log("configureDevice onShow");
- // 延迟 300ms 确保 stop() 完全释放后再重新注册(参照官方 demo)
+ // 动态计算距上次 stop() 已过去的时间,确保间隔至少 500ms 再重新注册
+ const elapsed = Date.now() - (this._stopTime || 0);
+ const delay = Math.max(0, 500 - elapsed);
setTimeout(() => {
- // 重新注册 app 级别的全局 bus 订阅
+ // 重新注册 app 级别的全局 bus 订阅(内部已做 unsubscribe 防重)
app.registerBusListeners();
- // 页面级 bus 订阅
- ppScale.plugin.bus.subscribe("devicesModel", (res) => {
+ // 页面级 bus 订阅(先清理旧的,防止重复叠加)
+ this._unsubscribePageBus();
+
+ this._pageHandlers.devicesModel = (res) => {
console.log("===》devicesModel", res);
ppScale.device.mac = res.deviceMac;
this._macReady = true;
this._tryProgress();
- });
+ };
+ ppScale.plugin.bus.subscribe("devicesModel", this._pageHandlers.devicesModel);
- ppScale.plugin.bus.subscribe("deviceConnect", (res) => {
+ this._pageHandlers.deviceConnect = (res) => {
console.log('===》deviceConnect', res);
ppScale.plugin.ScaleAction.startDataProgress(true);
@@ -78,18 +102,20 @@ Page({
this._tryProgress();
})
});
- });
+ };
+ ppScale.plugin.bus.subscribe("deviceConnect", this._pageHandlers.deviceConnect);
// 如果之前已选择过设备,自动扫描并重连
if (this.data.device) {
wx.showLoading({ title: "正在重新连接...", mask: true });
- ppScale.plugin.bus.subscribe("devicesList", (res) => {
+ this._pageHandlers.devicesList = (res) => {
let fIndex = res.findIndex(item => item.deviceId === this.data.device.deviceId);
if (fIndex >= 0) {
ppScale.plugin.Blue.stopBluetoothDevicesDiscovery();
ppScale.plugin.Blue.createBLEConnection(res[fIndex]);
}
- });
+ };
+ ppScale.plugin.bus.subscribe("devicesList", this._pageHandlers.devicesList);
}
// 通过完整链路重新初始化蓝牙(权限检查 → 打开适配器 → start)
@@ -153,6 +179,7 @@ Page({
},
setConfigSuccessful() {
+ this._stopKeepAlive();
ppScale.plugin.Blue.stop();
wx.switchTab({
url: "/pages/home/home"
@@ -160,9 +187,22 @@ Page({
},
setProgress() {
- this.setData({
- ["progress.index"]: this.data.progress.index + 1
- })
+ const newIndex = this.data.progress.index + 1;
+ this.setData({ "progress.index": newIndex });
+ // 进入步骤2(配网)时,等待组件渲染完成后由父页面显式触发 WiFi 列表获取
+ if (newIndex === 2) {
+ setTimeout(() => {
+ const comp = this.selectComponent('#configureDevice3');
+ if (comp) comp.initWifi();
+ }, 100);
+ }
+ // 进入步骤3(OTA升级)时,等待组件渲染完成后由父页面显式触发升级
+ if (newIndex === 3) {
+ setTimeout(() => {
+ const comp = this.selectComponent('#configureDevice4');
+ if (comp) comp.startOtaUpgrade();
+ }, 100);
+ }
},
// 连接完成 + mac 获取完成,双条件满足后才进入下一步
@@ -255,6 +295,8 @@ Page({
onHide() {
console.log("configureDevice onHide");
this._stopKeepAlive();
+ this._unsubscribePageBus();
+ app.unregisterBusListeners();
// 配网步骤:立即清空 WiFi 列表(stop 后数据已失效)
if (this.data.progress.index === 2) {
const comp = this.selectComponent('#configureDevice3');
@@ -271,16 +313,20 @@ Page({
app.setGlobalData('ppScale.device.connectState', null);
this._connectReady = false;
this._macReady = false;
+ this._stopTime = Date.now();
ppScale.plugin.Blue.stop();
},
onUnload() {
console.log("configureDevice onUnload");
this._stopKeepAlive();
+ this._unsubscribePageBus();
+ app.unregisterBusListeners();
app.resetReconnectCount();
app.setGlobalData('ppScale.device.connectState', null);
this._connectReady = false;
this._macReady = false;
+ this._stopTime = Date.now();
ppScale.plugin.Blue.stop();
}
})
\ No newline at end of file
diff --git a/pages/configureDevice/configureDevice.wxml b/pages/configureDevice/configureDevice.wxml
index bfdb988..cfcbef6 100644
--- a/pages/configureDevice/configureDevice.wxml
+++ b/pages/configureDevice/configureDevice.wxml
@@ -21,7 +21,7 @@
-
+
\ No newline at end of file