[AI Generated]: feat(*): 新增配网状态检测与SDK超时保护,优化配置流程稳定性

This commit is contained in:
17792275749
2026-04-09 10:35:58 +08:00
parent e7c890fee4
commit 65acceba2a
6 changed files with 235 additions and 110 deletions
+44 -22
View File
@@ -303,31 +303,53 @@ App({
* @param {*} value 要设置的新值 * @param {*} value 要设置的新值
*/ */
setGlobalData(keyPath, value) { setGlobalData(keyPath, value) {
const keys = keyPath.split('.'); const keys = keyPath.split('.');
let current = this.globalData; let current = this.globalData;
let oldValue = undefined; let oldValue = undefined;
// 遍历到目标属性的父级 // 遍历到目标属性的父级
for (let i = 0; i < keys.length - 1; i++) { for (let i = 0; i < keys.length - 1; i++) {
if (!current[keys[i]]) { if (!current[keys[i]]) {
current[keys[i]] = {}; // 如果路径不存在,创建空对象 current[keys[i]] = {}; // 如果路径不存在,创建空对象
} }
current = current[keys[i]]; current = current[keys[i]];
} }
// 获取旧值 // 获取旧值
oldValue = current[keys[keys.length - 1]]; oldValue = current[keys[keys.length - 1]];
// 只有当值发生变化时才更新并通知 // 只有当值发生变化时才更新并通知
if (oldValue !== value) { if (oldValue !== value) {
current[keys[keys.length - 1]] = value; // 设置新值 current[keys[keys.length - 1]] = value; // 设置新值
// 触发监听器 // 触发监听器
if (this.globalData._callbacks[keyPath]) { if (this.globalData._callbacks[keyPath]) {
this.globalData._callbacks[keyPath].forEach(callback => { this.globalData._callbacks[keyPath].forEach(callback => {
callback(value, oldValue); 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);
});
}, },
}) })
@@ -1,6 +1,9 @@
const app = getApp(); const app = getApp();
import $ from "../../utils/request"; import $ from "../../utils/request";
// 超时时间:15 秒
const SDK_TIMEOUT = 15000;
/** /**
* 根据生日计算年龄 * 根据生日计算年龄
* @param {string} birthday 生日字符串,如 "1990-05-20" * @param {string} birthday 生日字符串,如 "1990-05-20"
@@ -187,7 +190,10 @@ Component({
// 获取设备端已有用户,与用户列表做双向同步 // 获取设备端已有用户,与用户列表做双向同步
wx.showLoading({ title: "正在同步用户信息...", mask: true }); 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); console.log("设备端已有用户ID列表", deviceUserIds);
// 回调返回非数组视为获取失败 // 回调返回非数组视为获取失败
@@ -211,7 +217,7 @@ Component({
// 秤没有、列表有 → 需要下发到秤 // 秤没有、列表有 → 需要下发到秤
let needSyncList = userList.filter(user => !deviceIds.some(d => d.userID === String(user.userId))); let needSyncList = userList.filter(user => !deviceIds.some(d => d.userID === String(user.userId)));
console.log("需删除", needDeleteList, "需下发", needSyncList); console.log("需删除", needDeleteList, "需下发", needSyncList);
// 无需操作时直接完成 // 无需操作时直接完成
@@ -219,7 +225,7 @@ Component({
wx.hideLoading(); wx.hideLoading();
wx.showToast({ title: "用户信息已同步", icon: "success" }); wx.showToast({ title: "用户信息已同步", icon: "success" });
setTimeout(() => { setTimeout(() => {
this.triggerEvent('deviceEvent', { status: true }); this._checkWifiAndNext();
}, 1500); }, 1500);
return; return;
} }
@@ -237,29 +243,37 @@ Component({
} }
wx.showLoading({ title: "正在下发第" + (syncIndex + 1) + "/" + needSyncList.length + "个用户...", mask: true }); wx.showLoading({ title: "正在下发第" + (syncIndex + 1) + "/" + needSyncList.length + "个用户...", mask: true });
let user = needSyncList[syncIndex]; let user = needSyncList[syncIndex];
app.globalData.ppScale.activeProtocol.dataSyncUserInfo({ app.callWithTimeout(
userID: user.userId, (done) => app.globalData.ppScale.activeProtocol.dataSyncUserInfo({
userName: user.realname, userID: user.userId,
memberID: "", userName: user.realname,
age: user.age || '', memberID: "",
gender: user.sex === 2 ? 0 : user.sex, age: user.age || '',
height: String(user.height || ''), gender: user.sex === 2 ? 0 : user.sex,
isAthleteMode: 0, height: String(user.height || ''),
deviceHeaderIndex: syncIndex, isAthleteMode: 0,
currentWeight: String(user.weight || ''), deviceHeaderIndex: syncIndex,
targetWeight: "", currentWeight: String(user.weight || ''),
idealWeight: "", targetWeight: "",
recentData: [], idealWeight: "",
}, (res) => { recentData: [],
if (res == 0) { }, done),
syncIndex++; SDK_TIMEOUT,
syncNext(); (res) => {
} else { if (res == 0) {
syncIndex++;
syncNext();
} else {
wx.hideLoading();
console.log("dataSyncUserInfo 失败", res);
wx.showToast({ title: "用户信息下发失败,请重试。", icon: "none" });
}
},
() => {
wx.hideLoading(); wx.hideLoading();
console.log("dataSyncUserInfo 失败", res); wx.showToast({ title: "用户下发超时,请重试", icon: "none" });
wx.showToast({ title: "用户信息下发失败,请重试。", icon: "none" });
} }
}); );
}; };
// 第二步:逐个删除秤端多余用户 // 第二步:逐个删除秤端多余用户
@@ -270,30 +284,66 @@ Component({
wx.hideLoading(); wx.hideLoading();
wx.showToast({ title: "用户信息同步成功", icon: "success" }); wx.showToast({ title: "用户信息同步成功", icon: "success" });
setTimeout(() => { setTimeout(() => {
this.triggerEvent('deviceEvent', { status: true }); this._checkWifiAndNext();
}, 1500); }, 1500);
return; return;
} }
wx.showLoading({ title: "正在删除第" + (delIndex + 1) + "/" + needDeleteList.length + "个多余用户...", mask: true }); wx.showLoading({ title: "正在删除第" + (delIndex + 1) + "/" + needDeleteList.length + "个多余用户...", mask: true });
let item = needDeleteList[delIndex]; let item = needDeleteList[delIndex];
app.globalData.ppScale.activeProtocol.dataDeleteUser({ app.callWithTimeout(
userID: item.userID, (done) => app.globalData.ppScale.activeProtocol.dataDeleteUser({
memberID: "" userID: item.userID,
}, (status) => { memberID: ""
if (status == 0) { }, done),
delIndex++; SDK_TIMEOUT,
deleteNext(); (status) => {
} else { if (status == 0) {
delIndex++;
deleteNext();
} else {
wx.hideLoading();
console.log("dataDeleteUser 失败", status);
wx.showToast({ title: "删除设备用户失败,请重试。", icon: "none" });
}
},
() => {
wx.hideLoading(); wx.hideLoading();
console.log("dataDeleteUser 失败", status); wx.showToast({ title: "删除用户超时,请重试", icon: "none" });
wx.showToast({ title: "删除设备用户失败,请重试。", icon: "none" });
} }
}); );
}; };
// 从下发开始执行 // 从下发开始执行
syncNext(); 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" });
}
);
}, },
} }
}); });
@@ -1,5 +1,7 @@
const app = getApp(); const app = getApp();
import $ from "../../utils/request";
// 超时时间:15 秒
const SDK_TIMEOUT = 15000;
Component({ Component({
data: { data: {
@@ -32,10 +34,18 @@ Component({
wx.showToast({ title: '设备未连接,请重试', icon: 'none' }); wx.showToast({ title: '设备未连接,请重试', icon: 'none' });
return; return;
} }
activeProtocol.dataFindSurroundDevice((res) => { app.callWithTimeout(
wx.hideLoading(); (done) => activeProtocol.dataFindSurroundDevice(done),
this.setData({ wifiList: Array.isArray(res) ? res : [] }); SDK_TIMEOUT,
}); (res) => {
wx.hideLoading();
this.setData({ wifiList: Array.isArray(res) ? res : [] });
},
() => {
wx.hideLoading();
wx.showToast({ title: "获取Wi-Fi列表超时,请重试", icon: "none" });
}
);
}, },
// 最小化后重连,重置所有状态并重新获取 WiFi 列表 // 最小化后重连,重置所有状态并重新获取 WiFi 列表
@@ -69,34 +79,46 @@ Component({
}, },
setWifiPWD() { setWifiPWD() {
this.setData({ this.setData({ progress: 2 });
progress: 2
})
let version = app.globalData.ppScale.version; let version = app.globalData.ppScale.version;
if (version === 'domain1') { if (version === 'domain1') {
app.globalData.ppScale.activeProtocol.dataConfigNetWork({ app.callWithTimeout(
domain: app.globalData.ppScale.domain1, (done) => app.globalData.ppScale.activeProtocol.dataConfigNetWork({
ssid: this.data.selectWifi.ssid, domain: app.globalData.ppScale.domain1,
password: this.data.selectWifiPWD ssid: this.data.selectWifi.ssid,
}, (res) => { password: this.data.selectWifiPWD
console.log("setNetwork.js dataConfigNetWork 1", res); }, done),
SDK_TIMEOUT,
this.netWorkCallBack(res); (res) => {
}) console.log("setNetwork.js dataConfigNetWork 1", res);
this.netWorkCallBack(res);
},
() => {
this.setData({ progress: 1 });
wx.showToast({ title: "配网超时,请重试", icon: "none" });
}
);
} }
if (version === 'domain2') { if (version === 'domain2') {
app.globalData.ppScale.activeProtocol.dataConfigUserNetWork({ app.callWithTimeout(
domain: app.globalData.ppScale.domain2, (done) => app.globalData.ppScale.activeProtocol.dataConfigUserNetWork({
ssid: this.data.selectWifi.ssid, domain: app.globalData.ppScale.domain2,
password: this.data.selectWifiPWD, ssid: this.data.selectWifi.ssid,
userName: "apiUser", password: this.data.selectWifiPWD,
userPassword: "3acebb95eb49577e9c2a2082589b9bd6", userName: "apiUser",
}, (res) => { userPassword: "3acebb95eb49577e9c2a2082589b9bd6",
console.log("setNetwork.js dataConfigUserNetWork 2", res); }, done),
SDK_TIMEOUT,
this.netWorkCallBack(res); (res) => {
}) console.log("setNetwork.js dataConfigUserNetWork 2", res);
this.netWorkCallBack(res);
},
() => {
this.setData({ progress: 1 });
wx.showToast({ title: "配网超时,请重试", icon: "none" });
}
);
} }
}, },
+41 -20
View File
@@ -1,6 +1,9 @@
const app = getApp(); const app = getApp();
import $ from "../../utils/request"; import $ from "../../utils/request";
// 超时时间:15 秒
const SDK_TIMEOUT = 15000;
Component({ Component({
properties: { properties: {
ssid: { ssid: {
@@ -34,28 +37,46 @@ Component({
let password = this.properties.password; let password = this.properties.password;
let version = app.globalData.ppScale.version; let version = app.globalData.ppScale.version;
if (version === 'domain1') { if (version === 'domain1') {
app.globalData.ppScale.activeProtocol.dataConfigNetWork({ app.callWithTimeout(
domain: app.globalData.ppScale.domain1, (done) => app.globalData.ppScale.activeProtocol.dataConfigNetWork({
ssid: ssid, domain: app.globalData.ppScale.domain1,
password: password ssid: ssid,
}, (res) => { password: password
console.log("setNetwork.js dataConfigNetWork 1", res); }, done),
SDK_TIMEOUT,
this.netWorkCallBack(res); (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') { if (version === 'domain2') {
app.globalData.ppScale.activeProtocol.dataConfigUserNetWork({ app.callWithTimeout(
domain: app.globalData.ppScale.domain2, (done) => app.globalData.ppScale.activeProtocol.dataConfigUserNetWork({
ssid: ssid, domain: app.globalData.ppScale.domain2,
password: password, ssid: ssid,
userName: "apiUser", password: password,
userPassword: "3acebb95eb49577e9c2a2082589b9bd6" userName: "apiUser",
}, (res) => { userPassword: "3acebb95eb49577e9c2a2082589b9bd6"
console.log("setNetwork.js dataConfigUserNetWork 2", res); }, done),
SDK_TIMEOUT,
this.netWorkCallBack(res); (res) => {
}) console.log("setNetwork.js dataConfigUserNetWork 2", res);
this.netWorkCallBack(res);
},
() => {
wx.showToast({ title: "配网超时,请重试", icon: "none" });
setTimeout(() => {
this.triggerEvent('wifiEvent', { status: false });
}, 1500);
}
);
} }
}, },
+12 -2
View File
@@ -132,9 +132,14 @@ Page({
}, },
setDeviceUserList(e) { setDeviceUserList(e) {
let status = e.detail.status; let { status, progressIndex } = e.detail;
if (status) { if (status) {
this.setProgress(); // progressIndex 由子组件根据配网状态决定:2=进入配网,3=跳过配网
if (progressIndex !== undefined) {
this.setProgressTo(progressIndex);
} else {
this.setProgress();
}
} }
}, },
@@ -154,6 +159,11 @@ Page({
setProgress() { setProgress() {
const newIndex = this.data.progress.index + 1; const newIndex = this.data.progress.index + 1;
this.setProgressTo(newIndex);
},
// 直接跳转到指定步骤,统一处理各步骤的初始化副作用
setProgressTo(newIndex) {
this.setData({ "progress.index": newIndex }); this.setData({ "progress.index": newIndex });
// 进入步骤2(配网)时,等待组件渲染完成后由父页面显式触发 WiFi 列表获取 // 进入步骤2(配网)时,等待组件渲染完成后由父页面显式触发 WiFi 列表获取
if (newIndex === 2) { if (newIndex === 2) {
+1 -1
View File
@@ -209,7 +209,7 @@ Page({
}, },
getDeviceSettingList() { getDeviceSettingList() {
app.globalData.ppScale.plugin.Blue.visibleLog(true); // app.globalData.ppScale.plugin.Blue.visibleLog(true);
this.setData({ this.setData({
initText: "设备搜索中..." initText: "设备搜索中..."
}); });