[AI Generated]: feat(*): 新增蓝牙保活机制、设备初始化功能及用户双向同步逻辑
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
0a6578c2c9
commit
c41c7d9f63
@@ -59,6 +59,32 @@ Component({
|
||||
|
||||
// 组件的方法
|
||||
methods: {
|
||||
// 长按型号区域初始化设备
|
||||
onDeviceLongPress() {
|
||||
wx.showModal({
|
||||
title: "提示",
|
||||
content: "确定要初始化设备吗?将清除设备中的所有数据(用户信息、历史数据、配网数据、设置信息)。",
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
wx.showLoading({ title: "正在初始化设备...", mask: true });
|
||||
app.globalData.ppScale.activeProtocol.codeClearDeviceData("00", (status) => {
|
||||
wx.hideLoading();
|
||||
if (status == 0) {
|
||||
wx.showToast({ title: "设备初始化成功", icon: "success" });
|
||||
// 断开蓝牙连接并返回上一页
|
||||
app.globalData.ppScale.plugin.Blue.stop();
|
||||
setTimeout(() => {
|
||||
wx.navigateBack({ delta: 1 });
|
||||
}, 1500);
|
||||
} else {
|
||||
wx.showToast({ title: "设备初始化失败,请重试", icon: "none" });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// 手动重连设备
|
||||
connectedDevice() {
|
||||
app.resetReconnectCount();
|
||||
@@ -148,68 +174,104 @@ Component({
|
||||
return;
|
||||
}
|
||||
|
||||
// 先获取设备端已有用户,只下发新用户
|
||||
wx.showLoading({ title: "正在下发用户信息...", mask: true });
|
||||
// 获取设备端已有用户,与用户列表做双向同步
|
||||
wx.showLoading({ title: "正在同步用户信息...", mask: true });
|
||||
app.globalData.ppScale.activeProtocol.dataFetchUserID((deviceUserIds) => {
|
||||
console.log("设备端已有用户ID列表", deviceUserIds);
|
||||
let rawList = Array.isArray(deviceUserIds) ? deviceUserIds : [];
|
||||
// 兼容对象数组和纯ID数组,统一转为字符串比对
|
||||
let existIds = rawList.map(item => String(item.userID || item));
|
||||
let needSyncList = userList.filter(user => !existIds.includes(String(user.id)));
|
||||
console.log(needSyncList);
|
||||
if (!needSyncList.length) {
|
||||
let deviceIds = rawList.map(item => ({
|
||||
userID: String(item.userID || item),
|
||||
memberID: String(item.memberID || "")
|
||||
}));
|
||||
let localIds = userList.map(user => String(user.id));
|
||||
|
||||
// 秤有、列表没有 → 需要从秤删除
|
||||
let needDeleteList = deviceIds.filter(d => !localIds.includes(d.userID));
|
||||
|
||||
// 秤没有、列表有 → 需要下发到秤
|
||||
let needSyncList = userList.filter(user => !deviceIds.some(d => d.userID === String(user.id)));
|
||||
|
||||
console.log("需删除", needDeleteList, "需下发", needSyncList);
|
||||
|
||||
// 无需操作时直接完成
|
||||
if (!needDeleteList.length && !needSyncList.length) {
|
||||
wx.hideLoading();
|
||||
wx.showToast({
|
||||
title: "用户信息已同步",
|
||||
icon: "success"
|
||||
})
|
||||
wx.showToast({ title: "用户信息已同步", icon: "success" });
|
||||
setTimeout(() => {
|
||||
this.triggerEvent('deviceEvent', { status: true });
|
||||
}, 1500)
|
||||
}, 1500);
|
||||
return;
|
||||
}
|
||||
|
||||
let index = 0;
|
||||
// 第一步:逐个下发新用户到秤
|
||||
let syncIndex = 0;
|
||||
const syncNext = () => {
|
||||
if (index >= needSyncList.length) {
|
||||
wx.hideLoading();
|
||||
wx.showToast({
|
||||
title: "用户信息下发成功",
|
||||
icon: "success"
|
||||
})
|
||||
setTimeout(() => {
|
||||
this.triggerEvent('deviceEvent', { status: true });
|
||||
}, 1500)
|
||||
if (syncIndex >= needSyncList.length) {
|
||||
// 下发完成,开始删除
|
||||
if (needDeleteList.length) {
|
||||
wx.showLoading({ title: "正在删除多余用户...", mask: true });
|
||||
}
|
||||
deleteNext();
|
||||
return;
|
||||
}
|
||||
let user = needSyncList[index];
|
||||
wx.showLoading({ title: "正在下发第" + (syncIndex + 1) + "/" + needSyncList.length + "个用户...", mask: true });
|
||||
let user = needSyncList[syncIndex];
|
||||
app.globalData.ppScale.activeProtocol.dataSyncUserInfo({
|
||||
userID: user.id, // 用户唯一标识 ID。
|
||||
userName: user.realname, // 用户昵称/姓名。
|
||||
memberID: "", // 成员 ID(用于区分主账号下的子成员,例如一家人共用一台体脂秤)。
|
||||
age: user.age, // 年龄。
|
||||
gender: user.sex, // 性别(通常 0 代表女性,1 代表男性,或者根据具体协议定义)。
|
||||
height: user.height, // 身高(单位通常为 cm)。
|
||||
isAthleteMode: 0, // 运动员模式开关(0 表示普通人,1 表示运动员。该模式会影响体脂率等算法的计算)。
|
||||
deviceHeaderIndex: index, // 设备头像索引(用于在秤端或 App 列表显示的头像图标编号)。
|
||||
currentWeight: String(user.weight), // 当前体重。
|
||||
targetWeight: "", // 目标体重。
|
||||
idealWeight: "", // 理想体重(通常由系统根据身高、年龄自动计算得出)。
|
||||
userID: user.id,
|
||||
userName: user.realname,
|
||||
memberID: "",
|
||||
age: user.age,
|
||||
gender: user.sex,
|
||||
height: user.height,
|
||||
isAthleteMode: 0,
|
||||
deviceHeaderIndex: syncIndex,
|
||||
currentWeight: String(user.weight),
|
||||
targetWeight: "",
|
||||
idealWeight: "",
|
||||
recentData: [],
|
||||
}, (res) => {
|
||||
if (res == 0) {
|
||||
index++;
|
||||
syncIndex++;
|
||||
syncNext();
|
||||
} else {
|
||||
wx.hideLoading();
|
||||
console.log("dataSyncUserInfo", res);
|
||||
wx.showToast({
|
||||
title: "用户信息下发失败,请重试。",
|
||||
icon: "none"
|
||||
})
|
||||
console.log("dataSyncUserInfo 失败", res);
|
||||
wx.showToast({ title: "用户信息下发失败,请重试。", icon: "none" });
|
||||
}
|
||||
})
|
||||
});
|
||||
};
|
||||
|
||||
// 第二步:逐个删除秤端多余用户
|
||||
let delIndex = 0;
|
||||
const deleteNext = () => {
|
||||
if (delIndex >= needDeleteList.length) {
|
||||
// 全部完成
|
||||
wx.hideLoading();
|
||||
wx.showToast({ title: "用户信息同步成功", icon: "success" });
|
||||
setTimeout(() => {
|
||||
this.triggerEvent('deviceEvent', { status: true });
|
||||
}, 1500);
|
||||
return;
|
||||
}
|
||||
wx.showLoading({ title: "正在删除第" + (delIndex + 1) + "/" + needDeleteList.length + "个多余用户...", mask: true });
|
||||
let item = needDeleteList[delIndex];
|
||||
app.globalData.ppScale.activeProtocol.dataDeleteUser({
|
||||
userID: item.userID,
|
||||
memberID: item.memberID
|
||||
}, (status) => {
|
||||
if (status == 0) {
|
||||
delIndex++;
|
||||
deleteNext();
|
||||
} else {
|
||||
wx.hideLoading();
|
||||
console.log("dataDeleteUser 失败", status);
|
||||
wx.showToast({ title: "删除设备用户失败,请重试。", icon: "none" });
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 从下发开始执行
|
||||
syncNext();
|
||||
});
|
||||
},
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<view class="header">
|
||||
<view>
|
||||
<view>智能蓝牙秤</view>
|
||||
<view>型号:{{device.name}}</view>
|
||||
<view bind:longpress="onDeviceLongPress">型号:{{device.name}}</view>
|
||||
</view>
|
||||
<view>
|
||||
<block wx:if="{{connectState == BLUE_STATE.CONNECTSUCCESS || connectState == BLUE_STATE.WIFISUCCESS}}">
|
||||
|
||||
@@ -100,7 +100,7 @@ Component({
|
||||
},
|
||||
|
||||
netWorkCallBack(res) {
|
||||
if(res === 23) {
|
||||
if(res == 23) {
|
||||
app.globalData.ppScale.wifi.ssid = this.data.selectWifi.ssid;
|
||||
app.globalData.ppScale.wifi.password = this.data.selectWifiPWD;
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ Page({
|
||||
ppScale.device.connection = this.data.device;
|
||||
|
||||
wx.hideLoading();
|
||||
this._startKeepAlive();
|
||||
|
||||
// 配网步骤:重新获取 WiFi 列表
|
||||
if (currentStep === 2) {
|
||||
@@ -68,6 +69,7 @@ Page({
|
||||
console.log("===》codeSyncTime", codeSyncTime)
|
||||
|
||||
wx.hideLoading();
|
||||
this._startKeepAlive();
|
||||
ppScale.device.name = this.data.device.name;
|
||||
ppScale.device.connection = this.data.device;
|
||||
const nameArr = this.data.device.name.split("-");
|
||||
@@ -175,6 +177,25 @@ Page({
|
||||
}
|
||||
},
|
||||
|
||||
// 启动保活定时器,每10秒发送一次保活指令
|
||||
_keepAliveTimer: null,
|
||||
_startKeepAlive() {
|
||||
this._stopKeepAlive();
|
||||
this._keepAliveTimer = setInterval(() => {
|
||||
if (ppScale.activeProtocol) {
|
||||
ppScale.activeProtocol.sendKeepAliveCode();
|
||||
}
|
||||
}, 15000);
|
||||
},
|
||||
|
||||
// 清除保活定时器
|
||||
_stopKeepAlive() {
|
||||
if (this._keepAliveTimer) {
|
||||
clearInterval(this._keepAliveTimer);
|
||||
this._keepAliveTimer = null;
|
||||
}
|
||||
},
|
||||
|
||||
checkBluetoothPermissionAndInit() {
|
||||
wx.getSetting({
|
||||
success: (res) => {
|
||||
@@ -233,6 +254,7 @@ Page({
|
||||
|
||||
onHide() {
|
||||
console.log("configureDevice onHide");
|
||||
this._stopKeepAlive();
|
||||
// 配网步骤:立即清空 WiFi 列表(stop 后数据已失效)
|
||||
if (this.data.progress.index === 2) {
|
||||
const comp = this.selectComponent('#configureDevice3');
|
||||
@@ -254,6 +276,7 @@ Page({
|
||||
|
||||
onUnload() {
|
||||
console.log("configureDevice onUnload");
|
||||
this._stopKeepAlive();
|
||||
app.resetReconnectCount();
|
||||
app.setGlobalData('ppScale.device.connectState', null);
|
||||
this._connectReady = false;
|
||||
|
||||
@@ -64,6 +64,7 @@ Page({
|
||||
app.globalData.ppScale.version = nameArr.length === 5 ? "domain2" : "domain1";
|
||||
|
||||
wx.hideLoading();
|
||||
this._startKeepAlive();
|
||||
// 仅在 WiFi 列表步骤时获取列表(组件只在 progress === 0 时渲染)
|
||||
if (this.data.progress === 0) {
|
||||
const comp = this.selectComponent('#replaceNetwork1Component');
|
||||
@@ -275,8 +276,28 @@ Page({
|
||||
}
|
||||
},
|
||||
|
||||
// 启动保活定时器,每10秒发送一次保活指令
|
||||
_keepAliveTimer: null,
|
||||
_startKeepAlive() {
|
||||
this._stopKeepAlive();
|
||||
this._keepAliveTimer = setInterval(() => {
|
||||
if (app.globalData.ppScale.activeProtocol) {
|
||||
app.globalData.ppScale.activeProtocol.sendKeepAliveCode();
|
||||
}
|
||||
}, 15000);
|
||||
},
|
||||
|
||||
// 清除保活定时器
|
||||
_stopKeepAlive() {
|
||||
if (this._keepAliveTimer) {
|
||||
clearInterval(this._keepAliveTimer);
|
||||
this._keepAliveTimer = null;
|
||||
}
|
||||
},
|
||||
|
||||
onHide() {
|
||||
console.log("replaceNetwork onHide");
|
||||
this._stopKeepAlive();
|
||||
app.resetReconnectCount();
|
||||
app.setGlobalData('ppScale.device.connectState', null);
|
||||
app.globalData.ppScale.plugin.Blue.stop();
|
||||
@@ -285,6 +306,7 @@ Page({
|
||||
// 卸载事件监听
|
||||
onUnload() {
|
||||
console.log("replaceNetwork onUnload");
|
||||
this._stopKeepAlive();
|
||||
app.resetReconnectCount();
|
||||
app.setGlobalData('ppScale.device.connectState', null);
|
||||
app.globalData.ppScale.plugin.Blue.stop();
|
||||
|
||||
Reference in New Issue
Block a user