fastbee/yack-mini/miniprogram/pages/device/detail/detail.js

189 lines
4.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 设备详情页 - 实时数据(纯视图)
*
* 连接与上报全部由应用级网关(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();
}
},
});
},
});