const app = getApp(); import $ from "../../utils/request"; /** * 根据生日计算年龄 * @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() { // 4. 在组件销毁时取消监听,防止内存泄漏 if (this._connectStateWatcher) { app.unwatch('ppScale.device.connectState', this._connectStateWatcher); } } }, // 组件的方法 methods: { // 手动重连设备 connectedDevice() { app.resetReconnectCount(); this.triggerEvent('connectedDeviceEvent', { device: this.data.device }); }, addUser() { if (this.data.userList.length >= 10) { wx.showToast({ title: "超过最大用户数", icon: "none" }); return; } this.selectComponent("#configureDevice2AddUser").showModal(); }, getAddUserInfo() { this.fetchUserList(); }, // 获取设备绑定的用户列表 fetchUserList() { 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 }); 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) { wx.hideLoading(); wx.showToast({ title: "用户信息已同步", icon: "success" }) setTimeout(() => { this.triggerEvent('deviceEvent', { status: true }); }, 1500) return; } let index = 0; const syncNext = () => { if (index >= needSyncList.length) { wx.hideLoading(); wx.showToast({ title: "用户信息下发成功", icon: "success" }) setTimeout(() => { this.triggerEvent('deviceEvent', { status: true }); }, 1500) return; } let user = needSyncList[index]; 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: "", // 理想体重(通常由系统根据身高、年龄自动计算得出)。 recentData: [], }, (res) => { if (res == 0) { index++; syncNext(); } else { wx.hideLoading(); console.log("dataSyncUserInfo", res); wx.showToast({ title: "用户信息下发失败,请重试。", icon: "none" }) } }) }; syncNext(); }); }, } });