/** * 设备详情页 - 实时数据(纯视图) * * 连接与上报全部由应用级网关(gateway)承担,本页仅: * - 订阅网关快照,实时展示该设备的 hex 原始帧与统计 * - 提供”启用网关采集”开关(单 enabled,开启即停其他设备) * - 手动补传离线缓存 / 清空 */ const { gateway } = require('../../../services/gateway.js'); const storage = require('../../../utils/storage.js'); const app = getApp(); Page({ data: { device: null, enabled: false, // 网关快照(该设备是否为当前采集对象) isActive: false, activeSn: '', running: false, bleConnected: false, mqttConnected: false, phaseText: '未启用', lastError: null, // 数据列表与统计 dataList: [], stats: { received: 0, uploaded: 0, failed: 0 }, offlineCount: 0, }, onLoad(options) { const sn = options.sn; if (!sn) { wx.showToast({ title: '设备信息缺失', icon: 'none' }); setTimeout(() => wx.navigateBack(), 500); return; } // 从全局或存储获取设备信息 let device = app.globalData.currentDevice; if (!device || device.serialNumber !== sn) { device = storage.getDevice(sn); } if (!device) { wx.showToast({ title: '设备不存在', icon: 'none' }); setTimeout(() => wx.navigateBack(), 500); return; } this.sn = sn; this.setData({ device, enabled: !!device.enabled, }); }, onShow() { // 订阅网关,实时渲染 if (!this._unsub) { this._unsub = gateway.subscribe((snap) => this._apply(snap)); } this._apply(gateway.getSnapshot()); // 本设备已启用时,确保网关在采集(幂等) if (this.data.device && this.data.device.enabled) { gateway.ensureStarted(); } }, onHide() { this._unsubscribe(); }, onUnload() { this._unsubscribe(); }, _unsubscribe() { if (this._unsub) { this._unsub(); this._unsub = null; } }, /** * 应用网关快照到页面 */ _apply(snap) { const dev = this.data.device; const isActive = !!(snap.device && dev && snap.device.serialNumber === dev.serialNumber); this.setData({ isActive, activeSn: snap.device ? snap.device.serialNumber : '', bleConnected: isActive && snap.bleConnected, mqttConnected: isActive && snap.mqttConnected, running: isActive && snap.phase === 'running', phaseText: snap.phaseText, lastError: isActive ? snap.lastError : null, dataList: isActive ? snap.dataList : [], stats: isActive ? snap.stats : { received: 0, uploaded: 0, failed: 0 }, offlineCount: snap.offlineCount, }); }, /** * 启用/停用网关采集(单 enabled) */ async handleEnableToggle(e) { const enabled = e.detail.value; const device = this.data.device; if (!device) return; if (enabled) { // 本设备成为唯一启用,并立即启动采集 storage.activateDevice(device.serialNumber); this.setData({ enabled: true, device: { ...device, enabled: true }, }); const target = storage.getDevice(device.serialNumber); gateway.start(target || { ...device, enabled: true }); } else { storage.deactivateDevice(device.serialNumber); this.setData({ enabled: false, device: { ...device, enabled: false }, }); // 停用后若无其他启用设备,网关停止 await gateway.ensureStarted(); } }, /** * 发送命令 - 跳转命令管理页 */ handleSendCommand() { const device = this.data.device; if (!device) return; wx.navigateTo({ url: `/pages/device/command/command?sn=${device.serialNumber}`, }); }, /** * 手动补传离线缓存 */ async handleFlushOffline() { const { offlineCount } = this.data; if (!this.data.mqttConnected) { wx.showToast({ title: 'MQTT 未连接', icon: 'none' }); return; } if (offlineCount === 0) { wx.showToast({ title: '暂无离线数据', icon: 'none' }); return; } wx.showLoading({ title: '上传中...', mask: true }); const before = gateway.getSnapshot().offlineCount; await gateway.flushOffline(); wx.hideLoading(); const after = gateway.getSnapshot().offlineCount; wx.showToast({ title: `已上传 ${before - after} 条`, icon: 'none', }); }, /** * 清空展示数据 */ handleClearData() { wx.showModal({ title: '清空数据', content: '确定清空当前实时数据与统计吗?(不影响离线缓存)', success: (res) => { if (res.confirm) { gateway.clearHistory(); } }, }); }, });