From 347082bb303cd3f59aafcad639dcb416642beb13 Mon Sep 17 00:00:00 2001 From: xce Date: Sat, 10 Jan 2026 07:51:06 +0800 Subject: [PATCH] =?UTF-8?q?=E8=87=AA=E5=8A=A8=E6=9A=82=E5=81=9C+=E8=AE=BE?= =?UTF-8?q?=E5=A4=87=E6=9A=82=E5=81=9C=E8=BF=90=E8=A1=8C=E4=B8=8D=E5=BC=B9?= =?UTF-8?q?=E7=AA=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pages/control/index.vue | 122 +++++++++++++++++++++++++++++++++++----- 1 file changed, 107 insertions(+), 15 deletions(-) diff --git a/pages/control/index.vue b/pages/control/index.vue index acd72d8..c0d540a 100644 --- a/pages/control/index.vue +++ b/pages/control/index.vue @@ -222,7 +222,9 @@ export default { // 新增:弹窗相关变量 currentCard: {}, // 当前点击的卡片信息 currentCardTime: 0, // 当前卡片的运行时间 - newLimitTime: 0 // 新的运行时间 + newLimitTime: 0, // 新的运行时间 + // 新增:存储定时器(含快照信息),key=type,value={timerId, snapInfo} + timers: {} }; }, onLoad() { @@ -251,8 +253,19 @@ export default { onUnload() { // 移除MQTT消息回调(避免内存泄漏) mqttUtil.removeOnMessageCallback(); + // 清除所有定时器 + this.clearAllTimers(); }, methods: { + // 新增:清除所有定时器(防止内存泄漏) + clearAllTimers() { + Object.keys(this.timers).forEach(type => { + if (this.timers[type]?.timerId) { + clearTimeout(this.timers[type].timerId); + } + }); + this.timers = {}; + }, change(e) { this.imei = e; // 优化:使用常量拼接MQTT主题 @@ -317,13 +330,13 @@ export default { }); this.limitTimes= { jbkLimit: 0, - jbgLimit: 0, - jm1kLimit: 0, - jm1gLimit: 0, - jm2kLimit: 0, - jm2gLimit: 0, - jm3kLimit: 0, - jm3gLimit: 0 + jbgLimit: 0, + jm1kLimit: 0, + jm1gLimit: 0, + jm2kLimit: 0, + jm2gLimit: 0, + jm3kLimit: 0, + jm3gLimit: 0 }; this.deviceType = ''; this.control = '正在加载中...'; @@ -376,13 +389,13 @@ export default { // 组装消息 this.message = JSON.stringify({[type]: status}) // 控制设备 - // this.publishMessage(); + this.publishMessage(); // 设备回执 this.deviceType = type; //todo - this.$set(this.status, type, this.status[type] === 0 ? 1 : 0); - this.$set(this.show, type, this.status[type] === 0 ? "暂停" : "运行"); + // this.$set(this.status, type, this.status[type] === 0 ? 1 : 0); + // this.$set(this.show, type, this.status[type] === 0 ? "暂停" : "运行"); } } @@ -433,23 +446,99 @@ export default { console.info("提示消息:" + content) }, - // 处理指令回执的函数(完全保留) + // 处理指令回执的函数(核心修改:添加定时器+快照) handleCommandAck(ackData, type) { // 拿到指令字段(如jm2k)和执行状态(suc) const commandField = Object.keys(ackData.prop)[0]; // 这里是"jm2k" - const commandValue = ackData.prop[commandField]; // 这里是0 + const commandValue = ackData.prop[commandField]; // 这里是0/1 const isSuccess = ackData.suc; // 这里是true if (isSuccess) { // 优化:使用$set确保响应式更新 this.$set(this.status, type, this.status[type] === 0 ? 1 : 0); this.$set(this.show, type, this.status[type] === 0 ? "暂停" : "运行"); + + // ========== 核心新增:开启指令成功后启动定时器(带快照) ========== + const isStartCommand = commandValue === 1; // 1=开启指令,0=停止指令 + if (isStartCommand) { + // 1. 清除同type旧定时器(避免重复计时) + if (this.timers[type]?.timerId) { + clearTimeout(this.timers[type].timerId); + delete this.timers[type]; + } + + // 2. 快照:保存当前所有关键数据(值拷贝,永不改变) + const snapInfo = { + imei: this.imei, // 旧大棚imei + publishTopic: this.publishTopic, // 旧大棚Topic + delayTime: Number(this.limitTimes[`${type}Limit`] || 0) * 1000, // 旧运行时长(毫秒) + deviceType: type, // 设备类型 + connected: this.connected // 连接状态 + }; + + // 3. 仅当设置了运行时间才启动定时器 + if (snapInfo.delayTime && snapInfo.delayTime > 0) { + // 4. 启动定时器,存储timerId和快照 + const timerId = setTimeout(() => { + // 计时结束:执行自动停止逻辑(使用快照数据) + this.sendAutoStopCommand(snapInfo); + // 清除当前定时器记录 + delete this.timers[type]; + }, snapInfo.delayTime); + + // 5. 保存定时器信息 + this.timers[type] = { + timerId: timerId, + snapInfo: snapInfo + }; + } + } } + this.deviceType = ''; - this.$modal.msgSuccess("设备操作成功!") + // ========== 修改:自动停止指令不弹窗 ========== + + if (commandValue === 1) this.$modal.msgSuccess("设备操作成功!"); + console.log(`指令[${commandField}=${commandValue}]执行${isSuccess ? "成功" : "失败"}`); }, + // 新增:发送自动停止指令(使用快照数据,避免变量覆盖) + sendAutoStopCommand(snapInfo) { + // 1. 校验快照数据完整性 + if (!snapInfo || !snapInfo.imei || !snapInfo.publishTopic || !snapInfo.deviceType) { + this.addMessage(`【自动停止失败】快照数据缺失`); + return; + } + + // 2. 校验设备当前状态(若切回旧大棚,才判断状态) + let needStop = true; + if (this.imei === snapInfo.imei) { + needStop = this.status[snapInfo.deviceType] === 1; + } + + if (needStop) { + // 3. 组装停止指令(使用快照中的设备类型) + const stopMessage = JSON.stringify({[snapInfo.deviceType]: 0}); + + // 4. 使用快照中的Topic发送指令(精准发往旧大棚) + const publishSuccess = mqttUtil.publishMqtt(snapInfo.publishTopic, stopMessage); + if (publishSuccess) { + this.addMessage(`【自动停止-旧大棚${snapInfo.imei}】设备${snapInfo.deviceType},指令: ${stopMessage}`); + + // 5. 若当前选中的是旧大棚,更新页面状态 + if (this.imei === snapInfo.imei) { + this.$set(this.status, snapInfo.deviceType, 0); + this.$set(this.show, snapInfo.deviceType, "暂停"); + } + } else { + this.addMessage(`【自动停止失败-旧大棚${snapInfo.imei}】设备${snapInfo.deviceType}`); + } + } else { + this.addMessage(`【自动停止跳过】旧大棚${snapInfo.imei}设备${snapInfo.deviceType}已非运行状态`); + } + }, + handleOtherContent(msgData,payload) { // 业务逻辑:处理传感器数据、设备状态等 // 设备状态展示 @@ -572,9 +661,13 @@ export default { }, onHide() { mqttUtil.removeOnMessageCallback(); + // 隐藏时清除定时器 + this.clearAllTimers(); }, beforeDestroy() { mqttUtil.removeOnMessageCallback(); + // 销毁时清除所有定时器 + this.clearAllTimers(); }, }; @@ -781,5 +874,4 @@ export default { .uni-stat-tooltip { width: 300rpx; } - \ No newline at end of file