diff --git a/miniprogram/lefu/service.ts b/miniprogram/lefu/service.ts index b0c0c2d..63b9764 100644 --- a/miniprogram/lefu/service.ts +++ b/miniprogram/lefu/service.ts @@ -142,7 +142,7 @@ class LeFuService { }) plugin.bus.subscribe('deviceInfo', (res: DeviceInfo) => { - console.log(TAG, 'bus[deviceInfo]:', res?.modelNumber) + console.log(TAG, 'bus[deviceInfo]:', res) this._deviceInfo = res this._onDeviceInfoCb?.(res) }) diff --git a/miniprogram/pages/connectedDevice/connectedDevice.ts b/miniprogram/pages/connectedDevice/connectedDevice.ts index 6f056f5..d4efd5a 100644 --- a/miniprogram/pages/connectedDevice/connectedDevice.ts +++ b/miniprogram/pages/connectedDevice/connectedDevice.ts @@ -171,7 +171,14 @@ Page({ wx.showLoading({ title: '连接中...', mask: true }) lefuService.connect(raw) + lefuService.onConnectState((state) => { + if (state === lefuService.BLUE_STATE.CONNECTFAILED) { + wx.hideLoading() + wx.showToast({ title: '连接失败,请重试', icon: 'none' }) + } + }) lefuService.onDeviceConnect(() => { + wx.setStorageSync('connectDeviceInfo', { ...raw.raw, scaleDeviceName: raw.raw.name }) const list = this.data.deviceList.map((item, i) => ({ ...item, connected: i === index, diff --git a/miniprogram/pages/equipment/equipment.ts b/miniprogram/pages/equipment/equipment.ts index 609b41c..b0ce340 100644 --- a/miniprogram/pages/equipment/equipment.ts +++ b/miniprogram/pages/equipment/equipment.ts @@ -1,4 +1,6 @@ import { get } from '../../utils/request/index' +import { lefuService } from '../../lefu/index' +import type { RawDevice } from '../../lefu/types' /** API 返回的设备记录 */ interface DeviceRecord { @@ -38,6 +40,8 @@ interface DeviceRecord { interface DeviceItem { id: string scaleDeviceId: string + scaleDeviceName: string + connectDeviceInfo: string realname: string /** 蓝牙连接状态,接口不返回,由业务层更新 */ connected: boolean @@ -49,47 +53,127 @@ Page({ deviceList: [] as DeviceItem[], }, - onLoad() { + onShow() { this.loadData() }, - /** 拉取已绑定设备列表 */ + onUnload() { + lefuService.stopScan() + lefuService.onDeviceConnect(() => {}) + lefuService.onDeviceInfo(() => {}) + }, + + /** 拉取已绑定设备列表,加载完成后检查缓存自动连接 */ loadData() { this.setData({ loading: true }) - get('weighingScale/v3/list/device') + const userInfo = wx.getStorageSync('userInfo') + get('weighingScale/v3/list/device', { userId: userInfo?.userId }) .then(res => { - const list: DeviceItem[] = res.result.map(item => ({ - id: item.id, - scaleDeviceId: item.scaleDeviceId, - realname: item.realname, - connected: false, - })) - this.setData({ deviceList: list }) + const list: DeviceItem[] = res.result.map(item => { + let scaleDeviceName = '' + try { + const info = JSON.parse(item.connectDeviceInfo || '{}') + scaleDeviceName = info.name ?? '' + } catch {} + return { + id: item.id, + scaleDeviceId: item.scaleDeviceId, + scaleDeviceName, + connectDeviceInfo: item.connectDeviceInfo ?? '', + realname: item.realname, + connected: false, + } + }) + this.setData({ deviceList: list }, () => { + this._checkAndAutoConnect() + }) }) .finally(() => { this.setData({ loading: false }) }) }, - /* 点击「连接」→ 跳转设备搜索页 */ - onTapConnect() { - wx.navigateTo({ - url: '/pages/connectedDevice/connectedDevice' - }) + /** 检查缓存设备:已连接则直接标记,未连接则扫描自动连接 */ + _checkAndAutoConnect() { + const cachedRaw = wx.getStorageSync('connectDeviceInfo') as RawDevice | null + if (!cachedRaw) return + + // 已连接且 deviceInfo 就绪,直接标记列表 + if (lefuService.isConnected && lefuService.deviceInfo?.serialNumber) { + this._markConnected(lefuService.deviceInfo.serialNumber as string) + return + } + + // 未连接,直接用缓存对象连,不走扫描 + wx.showLoading({ title: '连接中...', mask: true }) + wx.openBluetoothAdapter({ + success: () => { + const target = { name: cachedRaw.scaleDeviceName ?? cachedRaw.name ?? '', raw: cachedRaw, model: {} } + lefuService.connect(target) + lefuService.onDeviceConnect(() => { + wx.hideLoading() + }) + lefuService.onDeviceInfo((info) => { + this._markConnected(info.serialNumber as string) + }) + }, + fail: () => { + wx.hideLoading() + }, + }) }, - /* 点击「成员管理」→ 跳转成员管理页,传 SN;userId 由目标页从缓存读取 */ - onTapMember(e: WechatMiniprogram.TouchEvent) { - const sn = e.currentTarget.dataset.sn as string - wx.navigateTo({ - url: `/pages/equipmentMember/equipmentMember?sn=${sn}` - }) + /** 将 serialNumber 对应的列表项标记为已连接,其余置为未连接 */ + _markConnected(serialNumber: string) { + const list = this.data.deviceList.map(item => ({ + ...item, + connected: item.scaleDeviceId === serialNumber, + })) + this.setData({ deviceList: list }) + }, + + /** 点击「连接」:断开当前、直接用 connectDeviceInfo 连接指定设备 */ + onTapConnect(e: WechatMiniprogram.TouchEvent) { + const connectDeviceInfoStr = e.currentTarget.dataset.connectDeviceInfo as string + let rawDevice: RawDevice | null = null + try { + rawDevice = JSON.parse(connectDeviceInfoStr || '{}') + } catch {} + if (!rawDevice) return + + if (lefuService.isConnected) { + lefuService.disconnect() + } + const list = this.data.deviceList.map(item => ({ ...item, connected: false })) + this.setData({ deviceList: list }) + + wx.showLoading({ title: '连接中...', mask: true }) + wx.openBluetoothAdapter({ + success: () => { + const target = { name: rawDevice!.scaleDeviceName ?? rawDevice!.name ?? '', raw: rawDevice!, model: {} } + lefuService.connect(target) + lefuService.onDeviceConnect(() => { + wx.hideLoading() + wx.setStorageSync('connectDeviceInfo', rawDevice) + }) + lefuService.onDeviceInfo((info) => { + this._markConnected(info.serialNumber as string) + }) + }, + fail: () => { + wx.hideLoading() + wx.showToast({ title: '蓝牙未开启', icon: 'none' }) + }, + }) + }, + + /* 点击「成员管理」→ 跳转成员管理页,sn 由目标页从缓存读取 */ + onTapMember() { + wx.navigateTo({ url: '/pages/equipmentMember/equipmentMember' }) }, /* 点击「添加设备」→ 跳转设备搜索页 */ onTapAdd() { - wx.navigateTo({ - url: '/pages/connectedDevice/connectedDevice' - }) + wx.navigateTo({ url: '/pages/connectedDevice/connectedDevice' }) }, }) diff --git a/miniprogram/pages/equipment/equipment.wxml b/miniprogram/pages/equipment/equipment.wxml index 17a1f53..b18bb7e 100644 --- a/miniprogram/pages/equipment/equipment.wxml +++ b/miniprogram/pages/equipment/equipment.wxml @@ -12,8 +12,7 @@ - {{ item.scaleDeviceId }} - {{ item.realname }} + {{ item.scaleDeviceName }} @@ -36,14 +35,14 @@ - 成员管理 + 成员管理 - 连接 - 成员管理 + 连接 + 成员管理 diff --git a/miniprogram/pages/equipmentMember/equipmentMember.ts b/miniprogram/pages/equipmentMember/equipmentMember.ts index e2548b8..200c2e9 100644 --- a/miniprogram/pages/equipmentMember/equipmentMember.ts +++ b/miniprogram/pages/equipmentMember/equipmentMember.ts @@ -1,4 +1,4 @@ -import { get } from '../../utils/request/index' +import { get, del } from '../../utils/request/index' import { lefuService } from '../../lefu/index' import type { DeviceMember } from '../../lefu/index' @@ -116,13 +116,12 @@ function syncToDevice(members: MemberDisplay[]): void { /** * 设备成员管理页 - * 通过 URL 参数 sn + 缓存中的 userId 拉取成员列表 - * 连接状态实时读取 lefuService + * sn 与设备名直接读 lefuService.deviceInfo,连接状态实时同步 */ Page({ data: { connected: false, - /** 当前设备 SN,由 onLoad 从 URL 参数写入 */ + /** 当前设备 SN,来自 lefuService.deviceInfo.serialNumber */ sn: '', loading: false, deviceCard: { @@ -133,14 +132,23 @@ Page({ memberList: [] as MemberDisplay[], }, - onLoad(options: Record) { - const sn = options.sn ?? '' + onLoad() { + const deviceInfo = lefuService.deviceInfo this.setData({ - sn, - // 读取 lefuService 当前连接状态作为初始值 + sn: deviceInfo?.serialNumber ?? '', connected: lefuService.isConnected, + 'deviceCard.name': deviceInfo?.name ?? '', + }) + // deviceInfo 实时同步:进页面时可能还未到达 + lefuService.onDeviceInfo((info) => { + this.setData({ + sn: info.serialNumber ?? '', + 'deviceCard.name': info.name ?? '', + }) + if (!this.data.memberList.length && info.serialNumber) { + this._loadData(info.serialNumber) + } }) - // 监听蓝牙连接/断连,实时更新状态 lefuService.onDeviceConnect(() => { this.setData({ connected: true }) }) @@ -150,16 +158,15 @@ Page({ }, onShow() { - // 每次页面显示(含首次进入和从子页返回)均刷新列表 if (this.data.sn) { this._loadData(this.data.sn) } }, onUnload() { - // 页面销毁时清空回调,避免对已卸载页面调用 setData lefuService.onDeviceConnect(() => {}) lefuService.onDisconnected(() => {}) + lefuService.onDeviceInfo(() => {}) }, /** @@ -188,18 +195,10 @@ Page({ age, } }) - // 设备名取首条记录的 scaleDeviceId,兜底用传入的 sn - const name = res.result[0]?.scaleDeviceId ?? sn this.setData({ memberList: list, - 'deviceCard.name': name, 'deviceCard.capacityUsed': list.length, }) - // 列表有变更且已连接时才同步到设备 - const hasChange = JSON.stringify(this.data.memberList) !== JSON.stringify(list) - if (this.data.connected && hasChange) { - syncToDevice(list) - } }) .finally(() => { this.setData({ loading: false }) @@ -212,15 +211,36 @@ Page({ wx.showToast({ title: `编辑 ${id}`, icon: 'none' }) }, - /** 删除成员(接口待接入) */ + /** 删除成员 */ onTapDelete(e: WechatMiniprogram.TouchEvent) { const id = e.currentTarget.dataset.id as string + const target = this.data.memberList.find(m => m.id === id) + if (!target) return + + // 主用户有子用户时不允许删除 + if (target.userType === 1) { + const hasSubUser = this.data.memberList.some(m => m.userType !== 1) + if (hasSubUser) { + wx.showToast({ title: '请先删除所有普通用户', icon: 'none' }) + return + } + } + wx.showModal({ title: '提示', - content: '确定删除该成员?', + content: '确定要删除该用户吗?', success: (res) => { if (!res.confirm) return - wx.showToast({ title: '删除功能待接入', icon: 'none' }) + del('weighingScale/v2/del/user', { id }, { loadingTitle: '正在删除...' }) + .then(() => { + wx.showToast({ title: '删除成功', icon: 'success' }) + setTimeout(() => { + this._loadData(this.data.sn) + }, 1500) + }) + .catch(() => { + wx.showToast({ title: '删除失败,请重试', icon: 'none' }) + }) }, }) }, diff --git a/miniprogram/pages/equipmentMember/equipmentMember.wxml b/miniprogram/pages/equipmentMember/equipmentMember.wxml index 0d78f60..2e0d593 100644 --- a/miniprogram/pages/equipmentMember/equipmentMember.wxml +++ b/miniprogram/pages/equipmentMember/equipmentMember.wxml @@ -16,7 +16,7 @@ {{ deviceCard.name }} - {{ connected ? '蓝牙已连接' : '未连接' }} + {{ connected ? '设备已连接' : '未连接' }} diff --git a/miniprogram/pages/login/login.ts b/miniprogram/pages/login/login.ts index f414167..32e141b 100644 --- a/miniprogram/pages/login/login.ts +++ b/miniprogram/pages/login/login.ts @@ -1,7 +1,7 @@ import { post } from '../../utils/request/index' /** 通过 OpenID 登录的用户信息 */ -interface CheckOpenIdLoginResult { +interface UserInfo { id: string userId: string parentUserId: string | null @@ -33,6 +33,12 @@ interface CheckOpenIdLoginResult { connectDeviceInfo: string } +/** 登录接口 result 结构 */ +interface CheckOpenIdLoginResult { + user: UserInfo | null + token: string +} + Page({ data: { loading: false, @@ -55,11 +61,11 @@ Page({ success: ({ code }) => { post('weighingScale/v2/checkOpenIdLogin', { code }) .then(({ result }) => { - /* 存储用户信息 */ - wx.setStorageSync('userInfo', result) + wx.setStorageSync('token', result.token) + wx.setStorageSync('userInfo', result.user) /* 上次连接设备不为空对象则直接进首页 */ - const connectDeviceInfo = result.connectDeviceInfo + const connectDeviceInfo = result.user?.connectDeviceInfo if (connectDeviceInfo && connectDeviceInfo !== '{}') { wx.setStorageSync('connectDeviceInfo', JSON.parse(connectDeviceInfo)) wx.reLaunch({ url: '/pages/home/home' }) diff --git a/miniprogram/pages/supplementPersonal/supplementPersonal.ts b/miniprogram/pages/supplementPersonal/supplementPersonal.ts index c26ec6c..af01803 100644 --- a/miniprogram/pages/supplementPersonal/supplementPersonal.ts +++ b/miniprogram/pages/supplementPersonal/supplementPersonal.ts @@ -1,4 +1,5 @@ import { get, put } from '../../utils/request/index' +import { lefuService } from '../../lefu/index' /** 表单数据模型 */ interface PersonalForm { @@ -182,7 +183,7 @@ Page({ this.setData({ querying: true, serverResult: null }) get('weighingScale/v3/getUserInfoByIdcard', { - sn: '', + sn: lefuService.deviceInfo?.serialNumber ?? '', idCard, realname: name }, { loading: false })