diff --git a/app.js b/app.js index a262dda..133b06c 100644 --- a/app.js +++ b/app.js @@ -303,31 +303,53 @@ App({ * @param {*} value 要设置的新值 */ setGlobalData(keyPath, value) { - const keys = keyPath.split('.'); - let current = this.globalData; - let oldValue = undefined; + const keys = keyPath.split('.'); + let current = this.globalData; + let oldValue = undefined; - // 遍历到目标属性的父级 - for (let i = 0; i < keys.length - 1; i++) { - if (!current[keys[i]]) { - current[keys[i]] = {}; // 如果路径不存在,创建空对象 - } - current = current[keys[i]]; - } + // 遍历到目标属性的父级 + for (let i = 0; i < keys.length - 1; i++) { + if (!current[keys[i]]) { + current[keys[i]] = {}; // 如果路径不存在,创建空对象 + } + current = current[keys[i]]; + } - // 获取旧值 - oldValue = current[keys[keys.length - 1]]; + // 获取旧值 + oldValue = current[keys[keys.length - 1]]; - // 只有当值发生变化时才更新并通知 - if (oldValue !== value) { - current[keys[keys.length - 1]] = value; // 设置新值 + // 只有当值发生变化时才更新并通知 + if (oldValue !== value) { + current[keys[keys.length - 1]] = value; // 设置新值 - // 触发监听器 - if (this.globalData._callbacks[keyPath]) { - this.globalData._callbacks[keyPath].forEach(callback => { - callback(value, oldValue); - }); - } - } + // 触发监听器 + if (this.globalData._callbacks[keyPath]) { + this.globalData._callbacks[keyPath].forEach(callback => { + callback(value, oldValue); + }); + } + } + }, + + /** + * 给回调式 SDK 调用包裹超时保护,防止设备无响应时 UI 永久卡死 + * @param {Function} caller 接收 done 回调的执行函数,形如 (done) => sdk.method(params, done) + * @param {number} timeout 超时毫秒数 + * @param {Function} onResult 正常回调,参数与 SDK 原始回调一致 + * @param {Function} onTimeout 超时后执行,负责 hideLoading + 提示 + */ + callWithTimeout(caller, timeout, onResult, onTimeout) { + let settled = false; + const timer = setTimeout(() => { + if (settled) return; + settled = true; + onTimeout(); + }, timeout); + caller((res) => { + if (settled) return; + settled = true; + clearTimeout(timer); + onResult(res); + }); }, }) \ No newline at end of file diff --git a/components/configureDevice_2/configureDevice_2.js b/components/configureDevice_2/configureDevice_2.js index bf5ce78..43082f6 100644 --- a/components/configureDevice_2/configureDevice_2.js +++ b/components/configureDevice_2/configureDevice_2.js @@ -1,6 +1,9 @@ const app = getApp(); import $ from "../../utils/request"; +// 超时时间:15 秒 +const SDK_TIMEOUT = 15000; + /** * 根据生日计算年龄 * @param {string} birthday 生日字符串,如 "1990-05-20" @@ -187,7 +190,10 @@ Component({ // 获取设备端已有用户,与用户列表做双向同步 wx.showLoading({ title: "正在同步用户信息...", mask: true }); - app.globalData.ppScale.activeProtocol.dataFetchUserID((deviceUserIds) => { + app.callWithTimeout( + (done) => app.globalData.ppScale.activeProtocol.dataFetchUserID(done), + SDK_TIMEOUT, + (deviceUserIds) => { console.log("设备端已有用户ID列表", deviceUserIds); // 回调返回非数组视为获取失败 @@ -211,7 +217,7 @@ Component({ // 秤没有、列表有 → 需要下发到秤 let needSyncList = userList.filter(user => !deviceIds.some(d => d.userID === String(user.userId))); - + console.log("需删除", needDeleteList, "需下发", needSyncList); // 无需操作时直接完成 @@ -219,7 +225,7 @@ Component({ wx.hideLoading(); wx.showToast({ title: "用户信息已同步", icon: "success" }); setTimeout(() => { - this.triggerEvent('deviceEvent', { status: true }); + this._checkWifiAndNext(); }, 1500); return; } @@ -237,29 +243,37 @@ Component({ } wx.showLoading({ title: "正在下发第" + (syncIndex + 1) + "/" + needSyncList.length + "个用户...", mask: true }); let user = needSyncList[syncIndex]; - app.globalData.ppScale.activeProtocol.dataSyncUserInfo({ - userID: user.userId, - userName: user.realname, - memberID: "", - age: user.age || '', - gender: user.sex === 2 ? 0 : user.sex, - height: String(user.height || ''), - isAthleteMode: 0, - deviceHeaderIndex: syncIndex, - currentWeight: String(user.weight || ''), - targetWeight: "", - idealWeight: "", - recentData: [], - }, (res) => { - if (res == 0) { - syncIndex++; - syncNext(); - } else { + app.callWithTimeout( + (done) => app.globalData.ppScale.activeProtocol.dataSyncUserInfo({ + userID: user.userId, + userName: user.realname, + memberID: "", + age: user.age || '', + gender: user.sex === 2 ? 0 : user.sex, + height: String(user.height || ''), + isAthleteMode: 0, + deviceHeaderIndex: syncIndex, + currentWeight: String(user.weight || ''), + targetWeight: "", + idealWeight: "", + recentData: [], + }, done), + SDK_TIMEOUT, + (res) => { + if (res == 0) { + syncIndex++; + syncNext(); + } else { + wx.hideLoading(); + console.log("dataSyncUserInfo 失败", res); + wx.showToast({ title: "用户信息下发失败,请重试。", icon: "none" }); + } + }, + () => { wx.hideLoading(); - console.log("dataSyncUserInfo 失败", res); - wx.showToast({ title: "用户信息下发失败,请重试。", icon: "none" }); + wx.showToast({ title: "用户下发超时,请重试", icon: "none" }); } - }); + ); }; // 第二步:逐个删除秤端多余用户 @@ -270,30 +284,66 @@ Component({ wx.hideLoading(); wx.showToast({ title: "用户信息同步成功", icon: "success" }); setTimeout(() => { - this.triggerEvent('deviceEvent', { status: true }); + this._checkWifiAndNext(); }, 1500); return; } wx.showLoading({ title: "正在删除第" + (delIndex + 1) + "/" + needDeleteList.length + "个多余用户...", mask: true }); let item = needDeleteList[delIndex]; - app.globalData.ppScale.activeProtocol.dataDeleteUser({ - userID: item.userID, - memberID: "" - }, (status) => { - if (status == 0) { - delIndex++; - deleteNext(); - } else { + app.callWithTimeout( + (done) => app.globalData.ppScale.activeProtocol.dataDeleteUser({ + userID: item.userID, + memberID: "" + }, done), + SDK_TIMEOUT, + (status) => { + if (status == 0) { + delIndex++; + deleteNext(); + } else { + wx.hideLoading(); + console.log("dataDeleteUser 失败", status); + wx.showToast({ title: "删除设备用户失败,请重试。", icon: "none" }); + } + }, + () => { wx.hideLoading(); - console.log("dataDeleteUser 失败", status); - wx.showToast({ title: "删除设备用户失败,请重试。", icon: "none" }); + wx.showToast({ title: "删除用户超时,请重试", icon: "none" }); } - }); + ); }; // 从下发开始执行 syncNext(); - }); + }, + () => { + wx.hideLoading(); + wx.showToast({ title: "获取设备用户超时,请重试", icon: "none" }); + } + ); + }, + + /** + * 同步完成后检测配网状态,决定跳转到哪一步 + * 已配网(0x01) → progressIndex: 3,跳过配网步骤 + * 未配网 → progressIndex: 2,进入配网步骤 + */ + _checkWifiAndNext() { + wx.showLoading({ title: "正在检测配网状态...", mask: true }); + app.callWithTimeout( + (done) => app.globalData.ppScale.activeProtocol.codeFetchWifiConfig(done), + SDK_TIMEOUT, + (res) => { + wx.hideLoading(); + // 0x01 表示已配网,跳过配网步骤直接进入下一步 + const progressIndex = res === 0x01 ? 3 : 2; + this.triggerEvent('deviceEvent', { status: true, progressIndex }); + }, + () => { + wx.hideLoading(); + wx.showToast({ title: "检测配网状态超时,请重试。", icon: "none" }); + } + ); }, } }); \ No newline at end of file diff --git a/components/configureDevice_3/configureDevice_3.js b/components/configureDevice_3/configureDevice_3.js index 81b96df..817a785 100644 --- a/components/configureDevice_3/configureDevice_3.js +++ b/components/configureDevice_3/configureDevice_3.js @@ -1,5 +1,7 @@ const app = getApp(); -import $ from "../../utils/request"; + +// 超时时间:15 秒 +const SDK_TIMEOUT = 15000; Component({ data: { @@ -32,10 +34,18 @@ Component({ wx.showToast({ title: '设备未连接,请重试', icon: 'none' }); return; } - activeProtocol.dataFindSurroundDevice((res) => { - wx.hideLoading(); - this.setData({ wifiList: Array.isArray(res) ? res : [] }); - }); + app.callWithTimeout( + (done) => activeProtocol.dataFindSurroundDevice(done), + SDK_TIMEOUT, + (res) => { + wx.hideLoading(); + this.setData({ wifiList: Array.isArray(res) ? res : [] }); + }, + () => { + wx.hideLoading(); + wx.showToast({ title: "获取Wi-Fi列表超时,请重试", icon: "none" }); + } + ); }, // 最小化后重连,重置所有状态并重新获取 WiFi 列表 @@ -69,34 +79,46 @@ Component({ }, setWifiPWD() { - this.setData({ - progress: 2 - }) + this.setData({ progress: 2 }); let version = app.globalData.ppScale.version; if (version === 'domain1') { - app.globalData.ppScale.activeProtocol.dataConfigNetWork({ - domain: app.globalData.ppScale.domain1, - ssid: this.data.selectWifi.ssid, - password: this.data.selectWifiPWD - }, (res) => { - console.log("setNetwork.js dataConfigNetWork 1", res); - - this.netWorkCallBack(res); - }) + app.callWithTimeout( + (done) => app.globalData.ppScale.activeProtocol.dataConfigNetWork({ + domain: app.globalData.ppScale.domain1, + ssid: this.data.selectWifi.ssid, + password: this.data.selectWifiPWD + }, done), + SDK_TIMEOUT, + (res) => { + console.log("setNetwork.js dataConfigNetWork 1", res); + this.netWorkCallBack(res); + }, + () => { + this.setData({ progress: 1 }); + wx.showToast({ title: "配网超时,请重试", icon: "none" }); + } + ); } if (version === 'domain2') { - app.globalData.ppScale.activeProtocol.dataConfigUserNetWork({ - domain: app.globalData.ppScale.domain2, - ssid: this.data.selectWifi.ssid, - password: this.data.selectWifiPWD, - userName: "apiUser", - userPassword: "3acebb95eb49577e9c2a2082589b9bd6", - }, (res) => { - console.log("setNetwork.js dataConfigUserNetWork 2", res); - - this.netWorkCallBack(res); - }) + app.callWithTimeout( + (done) => app.globalData.ppScale.activeProtocol.dataConfigUserNetWork({ + domain: app.globalData.ppScale.domain2, + ssid: this.data.selectWifi.ssid, + password: this.data.selectWifiPWD, + userName: "apiUser", + userPassword: "3acebb95eb49577e9c2a2082589b9bd6", + }, done), + SDK_TIMEOUT, + (res) => { + console.log("setNetwork.js dataConfigUserNetWork 2", res); + this.netWorkCallBack(res); + }, + () => { + this.setData({ progress: 1 }); + wx.showToast({ title: "配网超时,请重试", icon: "none" }); + } + ); } }, diff --git a/components/replaceNetwork_3/replaceNetwork_3.js b/components/replaceNetwork_3/replaceNetwork_3.js index 3a75349..0a1c60c 100644 --- a/components/replaceNetwork_3/replaceNetwork_3.js +++ b/components/replaceNetwork_3/replaceNetwork_3.js @@ -1,6 +1,9 @@ const app = getApp(); import $ from "../../utils/request"; +// 超时时间:15 秒 +const SDK_TIMEOUT = 15000; + Component({ properties: { ssid: { @@ -34,28 +37,46 @@ Component({ let password = this.properties.password; let version = app.globalData.ppScale.version; if (version === 'domain1') { - app.globalData.ppScale.activeProtocol.dataConfigNetWork({ - domain: app.globalData.ppScale.domain1, - ssid: ssid, - password: password - }, (res) => { - console.log("setNetwork.js dataConfigNetWork 1", res); - - this.netWorkCallBack(res); - }) + app.callWithTimeout( + (done) => app.globalData.ppScale.activeProtocol.dataConfigNetWork({ + domain: app.globalData.ppScale.domain1, + ssid: ssid, + password: password + }, done), + SDK_TIMEOUT, + (res) => { + console.log("setNetwork.js dataConfigNetWork 1", res); + this.netWorkCallBack(res); + }, + () => { + wx.showToast({ title: "配网超时,请重试", icon: "none" }); + setTimeout(() => { + this.triggerEvent('wifiEvent', { status: false }); + }, 1500); + } + ); } if (version === 'domain2') { - app.globalData.ppScale.activeProtocol.dataConfigUserNetWork({ - domain: app.globalData.ppScale.domain2, - ssid: ssid, - password: password, - userName: "apiUser", - userPassword: "3acebb95eb49577e9c2a2082589b9bd6" - }, (res) => { - console.log("setNetwork.js dataConfigUserNetWork 2", res); - - this.netWorkCallBack(res); - }) + app.callWithTimeout( + (done) => app.globalData.ppScale.activeProtocol.dataConfigUserNetWork({ + domain: app.globalData.ppScale.domain2, + ssid: ssid, + password: password, + userName: "apiUser", + userPassword: "3acebb95eb49577e9c2a2082589b9bd6" + }, done), + SDK_TIMEOUT, + (res) => { + console.log("setNetwork.js dataConfigUserNetWork 2", res); + this.netWorkCallBack(res); + }, + () => { + wx.showToast({ title: "配网超时,请重试", icon: "none" }); + setTimeout(() => { + this.triggerEvent('wifiEvent', { status: false }); + }, 1500); + } + ); } }, diff --git a/pages/configureDevice/configureDevice.js b/pages/configureDevice/configureDevice.js index b3e1cb3..ba9dfa1 100644 --- a/pages/configureDevice/configureDevice.js +++ b/pages/configureDevice/configureDevice.js @@ -132,9 +132,14 @@ Page({ }, setDeviceUserList(e) { - let status = e.detail.status; + let { status, progressIndex } = e.detail; if (status) { - this.setProgress(); + // progressIndex 由子组件根据配网状态决定:2=进入配网,3=跳过配网 + if (progressIndex !== undefined) { + this.setProgressTo(progressIndex); + } else { + this.setProgress(); + } } }, @@ -154,6 +159,11 @@ Page({ setProgress() { const newIndex = this.data.progress.index + 1; + this.setProgressTo(newIndex); + }, + + // 直接跳转到指定步骤,统一处理各步骤的初始化副作用 + setProgressTo(newIndex) { this.setData({ "progress.index": newIndex }); // 进入步骤2(配网)时,等待组件渲染完成后由父页面显式触发 WiFi 列表获取 if (newIndex === 2) { diff --git a/pages/searchDevice/searchDevice.js b/pages/searchDevice/searchDevice.js index d8dc87b..b3bd417 100644 --- a/pages/searchDevice/searchDevice.js +++ b/pages/searchDevice/searchDevice.js @@ -209,7 +209,7 @@ Page({ }, getDeviceSettingList() { - app.globalData.ppScale.plugin.Blue.visibleLog(true); + // app.globalData.ppScale.plugin.Blue.visibleLog(true); this.setData({ initText: "设备搜索中..." });