const app = getApp(); import $ from "../../utils/request"; // 超时时间:15 秒 const SDK_TIMEOUT = 15000; /** * 根据生日计算年龄 * @param {string} birthday 生日字符串,如 "1990-05-20" * @returns {number|null} 年龄,无法计算时返回 null */ function calcAge(birthday) { if (!birthday) return null; let birthDate = new Date(birthday.replace(/-/g, '/')); if (isNaN(birthDate.getTime())) return null; let today = new Date(); let age = today.getFullYear() - birthDate.getFullYear(); let monthDiff = today.getMonth() - birthDate.getMonth(); // 未过生日则减一岁 if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) { age--; } return age; } Component({ data: { BLUE_STATE: {}, device: null, connectState: "", userList: [], }, // 存储回调函数的引用,以便在 detached 时取消监听 _connectStateWatcher: null, lifetimes: { attached() { console.log(`[Component] connectState 获取: ${app.globalData.ppScale.device.connectState}`); this.setData({ BLUE_STATE: app.globalData.ppScale.plugin.BLUE_STATE, connectState: app.globalData.ppScale.device.connectState, device: app.globalData.ppScale.device.connection }) this._connectStateWatcher = (newValue, oldValue) => { console.log(`[Component] connectState 变化: ${oldValue} -> ${newValue}`); this.setData({ connectState: newValue || '' }); }; app.watch('ppScale.device.connectState', this._connectStateWatcher); this.fetchUserList(); }, detached() { if (this._connectStateWatcher) { app.unwatch('ppScale.device.connectState', this._connectStateWatcher); } if (this._sdkCancel) { this._sdkCancel(); this._sdkCancel = null; } } }, // 组件的方法 methods: { // 长按型号区域初始化设备 onDeviceLongPress() { wx.showModal({ title: "提示", content: "确定要初始化设备吗?将清除设备中的所有数据(用户信息、历史数据、配网数据、设置信息)。", success: (res) => { if (res.confirm) { if (!app.globalData.ppScale.activeProtocol) { wx.showToast({ title: "设备未连接,请重试", icon: "none" }); return; } 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(); this.triggerEvent('connectedDeviceEvent', { device: this.data.device }); }, addUser() { if (this.data.userList.length >= 5) { wx.showToast({ title: "超过最大用户数", icon: "none" }); return; } this.selectComponent("#configureDevice2AddUser").showModal(); }, getAddUserInfo() { this.fetchUserList(); }, // 获取设备绑定的用户列表 fetchUserList() { if (!app.globalData.ppScale.device.mac) { wx.showToast({ title: '设备 MAC 地址为空,请重新连接', icon: 'none' }); return; } let sn = app.globalData.ppScale.device.mac.replace(/:/g, ''); $.ajax("weighingScale/v2/select/user", { sn }, "GET", true, "正在获取用户列表...").then(res => { if (res.result && res.result.length) { let list = res.result.map(user => { // 没有 age 时通过 birthday 计算 if (!user.age && user.birthday) { user.age = calcAge(user.birthday); } return user; }); this.setData({ userList: list }); } else { this.setData({ userList: [] }); } }).catch(() => { wx.showToast({ title: "用户列表获取失败", icon: "none" }) }) }, // 删除用户 delUserClick(e) { let id = e.currentTarget.dataset.id; wx.showModal({ title: "提示", content: "确定要删除该用户吗?", success: (res) => { if (res.confirm) { $.ajax("weighingScale/v2/del/user", { id }, "DELETE", true, "正在删除...", "application/x-www-form-urlencoded").then(() => { wx.showToast({ title: "删除成功", icon: "success" }) setTimeout(() => { this.fetchUserList(); }, 1500) }).catch(() => { wx.showToast({ title: "删除失败,请重试", icon: "none" }) }) } } }) }, setUserInfo() { if (this.data.connectState != this.data.BLUE_STATE.CONNECTSUCCESS && this.data.connectState != this.data.BLUE_STATE.WIFISUCCESS) { wx.showToast({ title: "设备连接失败,请重试。", icon: "none" }) return; } let userList = this.data.userList; if (!userList.length) { wx.showToast({ title: "暂无用户信息,请先添加用户", icon: "none" }) return; } // 获取设备端已有用户,与用户列表做双向同步 wx.showLoading({ title: "正在同步用户信息...", mask: true }); this._sdkCancel = app.callWithTimeout( (done) => app.globalData.ppScale.activeProtocol.dataFetchUserID(done), SDK_TIMEOUT, (deviceUserIds) => { console.log("设备端已有用户ID列表", deviceUserIds); // 回调返回非数组视为获取失败 if (!Array.isArray(deviceUserIds)) { wx.hideLoading(); wx.showToast({ title: "获取设备用户列表失败,请重试", icon: "none" }); return; } let rawList = deviceUserIds; // SDK 返回的是 userID 数组,统一转为对象方便后续操作 let deviceIds = rawList.map(item => ({ userID: String(item), memberID: "" })); // 本地列表的 userId 统一转字符串,与 SDK 侧类型对齐 let localIds = userList.map(user => String(user.userId)); // 秤有、列表没有 → 需要从秤删除 let needDeleteList = deviceIds.filter(d => !localIds.includes(d.userID)); // 秤没有、列表有 → 需要下发到秤 let needSyncList = userList.filter(user => !deviceIds.some(d => d.userID === String(user.userId))); console.log("需删除", needDeleteList, "需下发", needSyncList); // 无需操作时直接完成 if (!needDeleteList.length && !needSyncList.length) { wx.hideLoading(); wx.showToast({ title: "用户信息已同步", icon: "success" }); setTimeout(() => { this._checkWifiAndNext(); }, 1500); return; } // 第一步:逐个下发新用户到秤 let syncIndex = 0; const syncNext = () => { if (syncIndex >= needSyncList.length) { // 下发完成,开始删除 if (needDeleteList.length) { wx.showLoading({ title: "正在删除多余用户...", mask: true }); } deleteNext(); return; } wx.showLoading({ title: "正在下发第" + (syncIndex + 1) + "/" + needSyncList.length + "个用户...", mask: true }); let user = needSyncList[syncIndex]; this._sdkCancel = 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(); wx.showToast({ title: "用户下发超时,请重试", icon: "none" }); } ); }; // 第二步:逐个删除秤端多余用户 let delIndex = 0; const deleteNext = () => { if (delIndex >= needDeleteList.length) { // 全部完成 wx.hideLoading(); wx.showToast({ title: "用户信息同步成功", icon: "success" }); setTimeout(() => { this._checkWifiAndNext(); }, 1500); return; } wx.showLoading({ title: "正在删除第" + (delIndex + 1) + "/" + needDeleteList.length + "个多余用户...", mask: true }); let item = needDeleteList[delIndex]; this._sdkCancel = 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(); wx.showToast({ title: "删除用户超时,请重试", icon: "none" }); } ); }; // 从下发开始执行 syncNext(); }, () => { wx.hideLoading(); wx.showToast({ title: "获取设备用户超时,请重试", icon: "none" }); } ); }, /** * 同步完成后检测配网状态,决定跳转到哪一步 * 已配网(0x01) → progressIndex: 3,跳过配网步骤 * 未配网 → progressIndex: 2,进入配网步骤 */ _checkWifiAndNext() { wx.showLoading({ title: "正在检测配网状态...", mask: true }); this._sdkCancel = 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" }); } ); }, } });