diff --git a/pages/home/control/automatic.vue b/pages/home/control/automatic.vue index e3edf60..bb104f7 100644 --- a/pages/home/control/automatic.vue +++ b/pages/home/control/automatic.vue @@ -864,6 +864,13 @@ export default { "操作提示"); return; } + // 300/2.13 + const isValidTotalLen = this.rollerParam.manualTotalLen > 300 || this.rollerParam.autoTotalLen > 300; + if (isValidTotalLen) { + this.$modal.alert(`风口长度设置不能大于300cm!`, + "操作提示"); + return; + } if (!(this.rollerParam.reservedLen && this.rollerParam.reservedLen > 0)) { this.$modal.alert(`请填写预留风口!`, "操作提示"); @@ -948,6 +955,11 @@ export default { validate: (rollerParam, term) => !((rollerParam.manualTotalLen && rollerParam.manualTotalLen > 0) || (rollerParam.autoTotalLen && rollerParam.autoTotalLen > 0)) }, + { + tip: '风口长度设置不能大于300cm!', + validate: (rollerParam, term) => (rollerParam.manualTotalLen && rollerParam.manualTotalLen > 300) || + (rollerParam.autoTotalLen && rollerParam.autoTotalLen > 300) + }, { tip: '预留风口长度未设置,请点击相应页签右上角设置后重试!', validate: (rollerParam, term) => !(rollerParam.reservedLen && rollerParam.reservedLen > 0) diff --git a/pages/index.vue b/pages/index.vue index eaee265..2a6a431 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -96,6 +96,7 @@ import TimeUtil from "../utils/TimeUtil"; import {getNewSpecialData} from "../api/data/specialData"; import AddAgri from "../components/addAgri/addAgri.vue"; import {removeAgri} from "../api/system/assets/userAgri"; +import * as mqttUtil from "../utils/mqtt"; export default { computed: { @@ -135,32 +136,33 @@ export default { // vertical: 'bottom', // direction: 'horizontal', searchValue: null, - /* pattern: { - color: '#7A7E83', - backgroundColor: '#fff', - selectedColor: '#007AFF', - buttonColor: '#007AFF', - iconColor: '#fff' - }, - content: [{ - iconPath: '/static/image.png', - selectedIconPath: '/static/image-active.png', - text: '添加大棚', - active: false - }, - { - iconPath: '/static/home.png', - selectedIconPath: '/static/home-active.png', - text: '', - active: false - }, - { - iconPath: '/static/star.png', - selectedIconPath: '/static/star-active.png', - text: '收藏', - active: false - } - ]*/ + imeiToDeviceMap: new Map(), + /* pattern: { + color: '#7A7E83', + backgroundColor: '#fff', + selectedColor: '#007AFF', + buttonColor: '#007AFF', + iconColor: '#fff' + }, + content: [{ + iconPath: '/static/image.png', + selectedIconPath: '/static/image-active.png', + text: '添加大棚', + active: false + }, + { + iconPath: '/static/home.png', + selectedIconPath: '/static/home-active.png', + text: '', + active: false + }, + { + iconPath: '/static/star.png', + selectedIconPath: '/static/star-active.png', + text: '收藏', + active: false + } + ]*/ } }, @@ -172,12 +174,15 @@ export default { return false*/ }, onShow() { - + mqttUtil.setOnMessageCallback(this.ackMessage); }, onLoad() { this.$modal.loading("数据加载中,请耐心等待...") this.refresh(); }, + onHide() { + mqttUtil.removeOnMessageCallback(); + }, onReady() { }, @@ -239,23 +244,27 @@ export default { getAgriInfo().then(response => { if (response.code === 200) { + // 先清空旧索引 + this.imeiToDeviceMap.clear(); // 1. 用 map 处理数据,返回新数组,避免 forEach 返回 undefined // 2. 区分刷新/加载更多,更新 listData this.listData = response.data.map(item => { - // 返回完整的列表项结构(和模板中需要的字段对应) - return { + const deviceItem = { ...item, deviceStatus: TimeUtil.isLessThanSpecifiedSeconds(item.time, 90) ? '在线' : '离线', - online: TimeUtil.isLessThanSpecifiedSeconds(item.time, 90) ? '在线' : '离线', // 兼容模板中的 online 字段 + online: TimeUtil.isLessThanSpecifiedSeconds(item.time, 90) ? '在线' : '离线', agriName: item.agriName || '未知大棚', imei: `${item.imei || '未知'}`, - workModeDesc: item.workMode === 0? '手动模式':'自动模式', + workModeDesc: item.workMode === 0 ? '手动模式':'自动模式', workMode: item.workMode, temp1: item.temp1, temp2: item.temp2, temp3: item.temp3, temp4: item.temp4 }; + // 存入索引Map + this.imeiToDeviceMap.set(deviceItem.imei, deviceItem); + return deviceItem; }); // 5. 判断是否还有更多数据 this.noMore = this.listData.length >= this.total; @@ -280,6 +289,7 @@ export default { } }, refresh() { + mqttUtil.setOnMessageCallback(this.ackMessage); this.getListData(); }, onDeleteItem(item, agri) { @@ -358,6 +368,33 @@ export default { }, ) }, + ackMessage(topic, payload) { + const regex2 = /^device\/\d+\/status$/; + if (!regex2.test(topic)) return; + + let msgData = {}; + // 优化:捕获JSON解析异常 + try { + msgData = JSON.parse(payload); + } catch (e) { + console.error("MQTT消息解析失败:", e, payload); + return; + } + // 设备在线状态 + if (msgData.online && "time" in msgData && "imei" in msgData) { + this.updateDeviceStatusFast(msgData.imei, msgData.online) + } + }, + updateDeviceStatusFast(targetImei, isOnline) { + // 直接从Map里取设备项,无需遍历数组 + const targetDevice = this.imeiToDeviceMap.get(targetImei); + if (!targetDevice) return; + + const statusText = isOnline ? '在线' : '离线'; + // 直接修改对象属性,响应式正常生效 + targetDevice.deviceStatus = statusText; + targetDevice.online = statusText; + } } } diff --git a/utils/mqtt.js b/utils/mqtt.js index 6d4cc07..45b6b4c 100644 --- a/utils/mqtt.js +++ b/utils/mqtt.js @@ -345,6 +345,7 @@ export function updateSubscribeTopic() { response.rows.forEach(item => { if (item?.imei) { subscribeList.push(`frontend/${clientId}/dtu/${item.imei}/+`); + subscribeList.push(`device/${item.imei}/+`); } }); // 管理员额外订阅指定设备