|
|
|
|
@ -8,48 +8,39 @@
|
|
|
|
|
</view>
|
|
|
|
|
</uni-section>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<uni-section title="实时温湿度" titleFontSize="16px" type="line" v-if="value!== 1">
|
|
|
|
|
<uni-section title="实时温湿度" titleFontSize="16px" type="line" v-if="value!== 1">
|
|
|
|
|
<template v-slot:right >
|
|
|
|
|
{{ temp }}
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<view>
|
|
|
|
|
<!-- 优化:温度卡片循环渲染 -->
|
|
|
|
|
<view class="uni-flex_control uni-row" >
|
|
|
|
|
<view class="text uni-flex_control_one uni-view">
|
|
|
|
|
<text class="data" :style="fontStyle">{{ liveData.temp1 }}<p v-if=(testNumber(liveData.temp1)) class="tempStyle">℃</p></text>
|
|
|
|
|
<text class="data">温度1</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="text uni-flex_control_one uni-view">
|
|
|
|
|
<text class="data" :style="fontStyle">{{ liveData.temp2 }}<p v-if=(testNumber(liveData.temp2)) class="tempStyle">℃</p></text>
|
|
|
|
|
<text class="data">温度2</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="text uni-flex_control_one uni-view">
|
|
|
|
|
<text class="data" :style="fontStyle">{{ liveData.temp3 }}<p v-if=(testNumber(liveData.temp3)) class="tempStyle">℃</p></text>
|
|
|
|
|
<text class="data">温度3</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="text uni-flex_control_one uni-view">
|
|
|
|
|
<text class="data" :style="fontStyle">{{ liveData.temp4 }}<p v-if=(testNumber(liveData.temp4)) class="tempStyle">℃</p></text>
|
|
|
|
|
<text class="data">温度4</text>
|
|
|
|
|
<view
|
|
|
|
|
class="text uni-flex_control_one uni-view"
|
|
|
|
|
v-for="item in sensorCards.temp"
|
|
|
|
|
:key="item.key"
|
|
|
|
|
>
|
|
|
|
|
<text class="data" :style="fontStyle">
|
|
|
|
|
{{ liveData[item.key] }}
|
|
|
|
|
<p v-if="isEffectiveValue(liveData[item.key])" class="tempStyle">℃</p>
|
|
|
|
|
</text>
|
|
|
|
|
<text class="data">{{ item.label }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- 优化:湿度卡片循环渲染 -->
|
|
|
|
|
<view class="uni-flex_control uni-row" >
|
|
|
|
|
<view class="text uni-flex_control_two uni-view">
|
|
|
|
|
<text class="data" :style="fontStyle">{{ liveData.humi1 }}<p v-if=(testNumber(liveData.humi1)) class="humiStyle"> %RH</p></text>
|
|
|
|
|
<text class="data">湿度1</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="text uni-flex_control_two uni-view">
|
|
|
|
|
<text class="data" :style="fontStyle">{{ liveData.humi2 }}<p v-if=(testNumber(liveData.humi2)) class="humiStyle"> %RH</p></text>
|
|
|
|
|
<text class="data">湿度2</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="text uni-flex_control_two uni-view">
|
|
|
|
|
<text class="data" :style="fontStyle">{{ liveData.humi3 }}<p v-if=(testNumber(liveData.humi3)) class="humiStyle"> %RH</p></text>
|
|
|
|
|
<text class="data">湿度3</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="text uni-flex_control_two uni-view">
|
|
|
|
|
<text class="data" :style="fontStyle">{{ liveData.humi4 }}<p v-if=(testNumber(liveData.humi4)) class="humiStyle"> %RH</p></text>
|
|
|
|
|
<text class="data">湿度4</text>
|
|
|
|
|
<view
|
|
|
|
|
class="text uni-flex_control_two uni-view"
|
|
|
|
|
v-for="item in sensorCards.humi"
|
|
|
|
|
:key="item.key"
|
|
|
|
|
>
|
|
|
|
|
<text class="data" :style="fontStyle">
|
|
|
|
|
{{ liveData[item.key] }}
|
|
|
|
|
<p v-if="isEffectiveValue(liveData[item.key])" class="humiStyle"> %RH</p>
|
|
|
|
|
</text>
|
|
|
|
|
<text class="data">{{ item.label }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
@ -59,147 +50,99 @@
|
|
|
|
|
<template v-slot:right >
|
|
|
|
|
{{ control }}
|
|
|
|
|
</template>
|
|
|
|
|
<!-- 卷膜/卷被卡片容器(2列栅格布局) -->
|
|
|
|
|
<!-- 优化:设备卡片循环渲染 -->
|
|
|
|
|
<view class="card-grid">
|
|
|
|
|
<!-- 卷被开卡片 -->
|
|
|
|
|
<view class="control-card" @click="handleCardClick(1-status.jbk, 'jbk')">
|
|
|
|
|
<view
|
|
|
|
|
class="control-card"
|
|
|
|
|
v-for="card in deviceCards"
|
|
|
|
|
:key="card.type"
|
|
|
|
|
@click="openTimeModal(card)"
|
|
|
|
|
>
|
|
|
|
|
<view class="card-text">
|
|
|
|
|
<text class="card-main">卷被开</text>
|
|
|
|
|
<!-- 核心修改:添加限位时间,与暂停/运行同行靠右 -->
|
|
|
|
|
<text class="card-main">{{ card.name }}</text>
|
|
|
|
|
<view class="card-sub-wrapper">
|
|
|
|
|
<text class="card-sub" v-if="hide">{{ show.jbk }}</text>
|
|
|
|
|
<text class="limit-time">运行时间:{{ limitTimes.jbk }} s</text>
|
|
|
|
|
<text class="card-sub" v-if="showStatusText">{{ show[card.type] || '未知' }}</text>
|
|
|
|
|
<text class="limit-time">运行时间:{{ limitTimes[card.type] || 0 }} s</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="card-icon" :class="{ active: status.jbk === 1 }">
|
|
|
|
|
<uni-icons :type=" (status.jbk === 1)?'circle':'circle-filled'" size="24" color="#fff"/>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- 卷被关卡片 -->
|
|
|
|
|
<view class="control-card" @click="handleCardClick(1-status.jbg,'jbg')">
|
|
|
|
|
<view class="card-text">
|
|
|
|
|
<text class="card-main">卷被关</text>
|
|
|
|
|
<view class="card-sub-wrapper">
|
|
|
|
|
<text class="card-sub" v-if="hide">{{ show.jbg }}</text>
|
|
|
|
|
<text class="limit-time">运行时间:{{ limitTimes.jbg }} s</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="card-icon" :class="{ active: status.jbg === 1 }">
|
|
|
|
|
<uni-icons :type=" (status.jbg === 1)?'circle':'circle-filled'" size="24" color="#fff"/>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- 卷膜1开卡片 -->
|
|
|
|
|
<view class="control-card" @click="handleCardClick(1-status.jm1k, 'jm1k')">
|
|
|
|
|
<view class="card-text">
|
|
|
|
|
<text class="card-main">卷膜1开</text>
|
|
|
|
|
<view class="card-sub-wrapper">
|
|
|
|
|
<text class="card-sub" v-if="hide">{{ show.jm1k }}</text>
|
|
|
|
|
<text class="limit-time">运行时间:{{ limitTimes.jm1k }} s</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="card-icon" :class="{ active: status.jm1k === 1 }">
|
|
|
|
|
<uni-icons :type="(status.jm1k === 1)?'circle':'circle-filled'" size="24" color="#fff"/>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- 卷膜1关卡片 -->
|
|
|
|
|
<view class="control-card" @click="handleCardClick(1-status.jm1g, 'jm1g')">
|
|
|
|
|
<view class="card-text">
|
|
|
|
|
<text class="card-main">卷膜1关</text>
|
|
|
|
|
<view class="card-sub-wrapper">
|
|
|
|
|
<text class="card-sub" v-if="hide">{{ show.jm1g }}</text>
|
|
|
|
|
<text class="limit-time">运行时间:{{ limitTimes.jm1g }} s</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="card-icon" :class="{ active: status.jm1g === 1 }">
|
|
|
|
|
<uni-icons :type="(status.jm1g === 1)?'circle':'circle-filled'" size="24" color="#fff"/>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- 卷膜2卡片 -->
|
|
|
|
|
<view class="control-card" @click="handleCardClick(1-status.jm2k, 'jm2k')">
|
|
|
|
|
<view class="card-text">
|
|
|
|
|
<text class="card-main">卷膜2开</text>
|
|
|
|
|
<view class="card-sub-wrapper">
|
|
|
|
|
<text class="card-sub" v-if="hide">{{ show.jm2k }}</text>
|
|
|
|
|
<text class="limit-time">运行时间:{{ limitTimes.jm2k }} s</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="card-icon" :class="{ active: status.jm2k === 1 }">
|
|
|
|
|
<uni-icons :type="(status.jm2k === 1)?'circle':'circle-filled'" size="24" color="#fff"/>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- 卷膜2关卡片 -->
|
|
|
|
|
<view class="control-card" @click="handleCardClick(1-status.jm2g, 'jm2g')">
|
|
|
|
|
<view class="card-text">
|
|
|
|
|
<text class="card-main">卷膜2关</text>
|
|
|
|
|
<view class="card-sub-wrapper">
|
|
|
|
|
<text class="card-sub" v-if="hide">{{ show.jm2g }}</text>
|
|
|
|
|
<text class="limit-time">运行时间:{{ limitTimes.jm2g }} s</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="card-icon" :class="{ active: status.jm2g === 1 }">
|
|
|
|
|
<uni-icons :type="(status.jm2g === 1)?'circle':'circle-filled'" size="24" color="#fff"/>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<!-- 卷膜3开卡片 -->
|
|
|
|
|
<view class="control-card" @click="handleCardClick(1-status.jm3k, 'jm3k')">
|
|
|
|
|
<view class="card-text">
|
|
|
|
|
<text class="card-main">卷膜3开</text>
|
|
|
|
|
<view class="card-sub-wrapper">
|
|
|
|
|
<text class="card-sub" v-if="hide">{{ show.jm3k }}</text>
|
|
|
|
|
<text class="limit-time">运行时间:{{ limitTimes.jm3k }} s</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="card-icon" :class="{ active: status.jm3k === 1 }">
|
|
|
|
|
<uni-icons :type="(status.jm3k === 1)?'circle':'circle-filled'" size="24" color="#fff"/>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
|
|
|
|
|
<!-- 卷膜3关卡片 -->
|
|
|
|
|
<view class="control-card" @click="handleCardClick(1-status.jm3g, 'jm3g')">
|
|
|
|
|
<view class="card-text">
|
|
|
|
|
<text class="card-main">卷膜3关</text>
|
|
|
|
|
<view class="card-sub-wrapper">
|
|
|
|
|
<text class="card-sub" v-if="hide">{{ show.jm3g }}</text>
|
|
|
|
|
<text class="limit-time">运行时间:{{ limitTimes.jm3g }} s</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="card-icon" :class="{ active: status.jm3g === 1 }">
|
|
|
|
|
<uni-icons :type="(status.jm3g === 1)?'circle':'circle-filled'" size="24" color="#fff"/>
|
|
|
|
|
<view class="card-icon" :class="{ active: status[card.type] === 1 }" @click.stop="handleCardClick(1 - status[card.type], card.type)">
|
|
|
|
|
<!-- 加@click.stop防止冒泡触发卡片点击的弹窗事件 -->
|
|
|
|
|
<uni-icons
|
|
|
|
|
:type="status[card.type] === 1 ? 'circle' : 'circle-filled'"
|
|
|
|
|
size="24"
|
|
|
|
|
color="#fff"
|
|
|
|
|
/>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</uni-section>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 输入框示例 -->
|
|
|
|
|
<!-- <uni-popup ref="inputDialog" type="dialog">-->
|
|
|
|
|
<!-- <uni-popup-dialog ref="inputClose" mode="input" title="输入内容" value="对话框预置提示内容!"-->
|
|
|
|
|
<!-- placeholder="请输入内容" @confirm="confirmModifyTime"></uni-popup-dialog>-->
|
|
|
|
|
<!-- </uni-popup>-->
|
|
|
|
|
<uni-popup v-model="timeModalVisible" ref="inputDialog" mode="center" :z-index="99999">
|
|
|
|
|
|
|
|
|
|
<!-- 新增:修改运行时间的弹窗 -->
|
|
|
|
|
<!-- <uni-popup v-model="timeModalVisible" mode="center">-->
|
|
|
|
|
<view class="modal-container">
|
|
|
|
|
<view class="modal-title">修改{{ currentCard.name }}运行时间</view>
|
|
|
|
|
<view class="modal-input-wrap">
|
|
|
|
|
<text class="modal-label">当前时间:</text>
|
|
|
|
|
<text class="modal-current">{{ currentCardTime }} s</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="modal-input-wrap">
|
|
|
|
|
<text class="modal-label">新时间:</text>
|
|
|
|
|
<input
|
|
|
|
|
class="modal-input"
|
|
|
|
|
type="number"
|
|
|
|
|
v-model.number="newTime"
|
|
|
|
|
placeholder="请输入1-60的数字"
|
|
|
|
|
min="1"
|
|
|
|
|
max="60"
|
|
|
|
|
/>
|
|
|
|
|
<text class="modal-unit">s</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="modal-btn-wrap">
|
|
|
|
|
<button class="modal-btn cancel" @click="">取消</button>
|
|
|
|
|
<button class="modal-btn confirm" @click="confirmModifyTime">确定</button>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</uni-popup>
|
|
|
|
|
</view>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
// ========== 修改:替换原有mqtt引入为全局工具类 ==========
|
|
|
|
|
// import mqtt from 'mqtt' // 移除原有mqtt直接引入
|
|
|
|
|
// 优化:抽离魔法值常量
|
|
|
|
|
const SENSOR_MAP = {
|
|
|
|
|
temp1: "201", temp2: "202", temp3: "203", temp4: "204",
|
|
|
|
|
humi1: "101", humi2: "102", humi3: "103", humi4: "104"
|
|
|
|
|
};
|
|
|
|
|
const MQTT_TOPIC_SUFFIX = { UP: "/up", DOWN: "/down" };
|
|
|
|
|
|
|
|
|
|
import UniDatetimePicker from "../../uni_modules/uni-datetime-picker/components/uni-datetime-picker/uni-datetime-picker.vue";
|
|
|
|
|
import UniPopup from "../../uni_modules/uni-popup/components/uni-popup/uni-popup.vue"; // 引入弹窗组件
|
|
|
|
|
import { findDtuDataByInfo } from "@/api/system/data";
|
|
|
|
|
import mqttUtil from '@/utils/mqtt'; // 引入全局MQTT工具类
|
|
|
|
|
import mqttUtil from '@/utils/mqtt';
|
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
dicts: ['sys_data_map'],
|
|
|
|
|
components: {
|
|
|
|
|
UniDatetimePicker
|
|
|
|
|
UniDatetimePicker,
|
|
|
|
|
UniPopup // 注册弹窗组件
|
|
|
|
|
},
|
|
|
|
|
data() {
|
|
|
|
|
return {
|
|
|
|
|
// ========== 修改:移除原有mqttClient相关变量 ==========
|
|
|
|
|
// mqttClient: null,
|
|
|
|
|
temp: "",
|
|
|
|
|
// ========== 修改:简化mqttConfig,仅保留订阅/发布主题(全局配置已移到工具类) ==========
|
|
|
|
|
mqttConfig: {
|
|
|
|
|
subscribeTopic:'/up',
|
|
|
|
|
},
|
|
|
|
|
value: 1,
|
|
|
|
|
hide: false,
|
|
|
|
|
// 优化:语义化变量名(替换原 hide: false)
|
|
|
|
|
showStatusText: false,
|
|
|
|
|
control: '正在加载中...',
|
|
|
|
|
range: [{
|
|
|
|
|
"value": '864865085016294',
|
|
|
|
|
@ -215,8 +158,8 @@ export default {
|
|
|
|
|
publishTopic: '/down',
|
|
|
|
|
title:'',
|
|
|
|
|
message: {},
|
|
|
|
|
// ========== 修改:从全局工具类获取连接状态 ==========
|
|
|
|
|
// connected:false,
|
|
|
|
|
// 优化:声明响应式变量 connected
|
|
|
|
|
connected: false,
|
|
|
|
|
liveData: {
|
|
|
|
|
temp1: '数据加载中...',
|
|
|
|
|
temp2: '数据加载中...',
|
|
|
|
|
@ -227,7 +170,33 @@ export default {
|
|
|
|
|
humi3: '数据加载中...',
|
|
|
|
|
humi4: '数据加载中...'
|
|
|
|
|
},
|
|
|
|
|
// 卡片状态(模拟后端返回数据)
|
|
|
|
|
// 优化:温湿度卡片配置(固定顺序:温度1→2→3→4,湿度1→2→3→4)
|
|
|
|
|
sensorCards: {
|
|
|
|
|
temp: [
|
|
|
|
|
{ label: '温度1', key: 'temp1' },
|
|
|
|
|
{ label: '温度2', key: 'temp2' },
|
|
|
|
|
{ label: '温度3', key: 'temp3' },
|
|
|
|
|
{ label: '温度4', key: 'temp4' }
|
|
|
|
|
],
|
|
|
|
|
humi: [
|
|
|
|
|
{ label: '湿度1', key: 'humi1' },
|
|
|
|
|
{ label: '湿度2', key: 'humi2' },
|
|
|
|
|
{ label: '湿度3', key: 'humi3' },
|
|
|
|
|
{ label: '湿度4', key: 'humi4' }
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
// 优化:设备卡片配置(固定顺序)
|
|
|
|
|
deviceCards: [
|
|
|
|
|
{ type: 'jbk', name: '卷被开' },
|
|
|
|
|
{ type: 'jbg', name: '卷被关' },
|
|
|
|
|
{ type: 'jm1k', name: '卷膜1开' },
|
|
|
|
|
{ type: 'jm1g', name: '卷膜1关' },
|
|
|
|
|
{ type: 'jm2k', name: '卷膜2开' },
|
|
|
|
|
{ type: 'jm2g', name: '卷膜2关' },
|
|
|
|
|
{ type: 'jm3k', name: '卷膜3开' },
|
|
|
|
|
{ type: 'jm3g', name: '卷膜3关' }
|
|
|
|
|
],
|
|
|
|
|
// 卡片状态
|
|
|
|
|
show: {
|
|
|
|
|
jbk: "暂停",
|
|
|
|
|
jbg: "暂停",
|
|
|
|
|
@ -238,7 +207,7 @@ export default {
|
|
|
|
|
jm3k: "暂停",
|
|
|
|
|
jm3g: "暂停"
|
|
|
|
|
},
|
|
|
|
|
// 新增:限位时间配置(你可以根据实际需求修改数值)
|
|
|
|
|
// 新增:限位时间配置
|
|
|
|
|
limitTimes: {
|
|
|
|
|
jbk: 30,
|
|
|
|
|
jbg: 25,
|
|
|
|
|
@ -260,7 +229,12 @@ export default {
|
|
|
|
|
jm3k: 0,
|
|
|
|
|
jm3g: 0
|
|
|
|
|
},
|
|
|
|
|
fontStyle: ''
|
|
|
|
|
fontStyle: '',
|
|
|
|
|
// 新增:弹窗相关变量
|
|
|
|
|
timeModalVisible: false, // 弹窗显示状态
|
|
|
|
|
currentCard: {}, // 当前点击的卡片信息
|
|
|
|
|
currentCardTime: 0, // 当前卡片的运行时间
|
|
|
|
|
newTime: 0 // 新的运行时间
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
onLoad() {
|
|
|
|
|
@ -280,24 +254,21 @@ export default {
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
onShow() {
|
|
|
|
|
// ========== 修改:替换原有connectMqtt为注册消息回调 ==========
|
|
|
|
|
// this.connectMqtt();
|
|
|
|
|
// 注册MQTT消息回调(接收设备消息)
|
|
|
|
|
mqttUtil.setOnMessageCallback(this.ackMessage);
|
|
|
|
|
// 更新连接状态
|
|
|
|
|
this.connected = mqttUtil.getMqttState().isConnected;
|
|
|
|
|
},
|
|
|
|
|
onUnload() {
|
|
|
|
|
// ========== 修改:移除原有disconnectMqtt,改为移除回调 ==========
|
|
|
|
|
// this.disconnectMqtt()
|
|
|
|
|
// 移除MQTT消息回调(避免内存泄漏)
|
|
|
|
|
mqttUtil.removeOnMessageCallback();
|
|
|
|
|
},
|
|
|
|
|
methods: {
|
|
|
|
|
change(e) {
|
|
|
|
|
this.imei = e;
|
|
|
|
|
this.publishTopic = "dtu/"+this.imei+"/down";
|
|
|
|
|
this.mqttConfig.subscribeTopic = "dtu/"+this.imei+"/up";
|
|
|
|
|
// 优化:使用常量拼接MQTT主题
|
|
|
|
|
this.publishTopic = `dtu/${this.imei}${MQTT_TOPIC_SUFFIX.DOWN}`;
|
|
|
|
|
this.mqttConfig.subscribeTopic = `dtu/${this.imei}${MQTT_TOPIC_SUFFIX.UP}`;
|
|
|
|
|
const selectedItem = this.range.find(item => item.value === e);
|
|
|
|
|
if (selectedItem) {
|
|
|
|
|
this.selectedText = selectedItem.text; // 获取展示文本
|
|
|
|
|
@ -332,7 +303,6 @@ export default {
|
|
|
|
|
this.liveData[key] = '数据加载中...';
|
|
|
|
|
});
|
|
|
|
|
this.deviceType = '';
|
|
|
|
|
|
|
|
|
|
this.control = '正在加载中...';
|
|
|
|
|
this.message = {};
|
|
|
|
|
this.temp = '';
|
|
|
|
|
@ -383,25 +353,19 @@ export default {
|
|
|
|
|
// 组装消息
|
|
|
|
|
this.message = JSON.stringify({[type]: status})
|
|
|
|
|
// 控制设备
|
|
|
|
|
this.publishMessage();
|
|
|
|
|
// this.publishMessage();
|
|
|
|
|
// 设备回执
|
|
|
|
|
this.deviceType = type;
|
|
|
|
|
//todo
|
|
|
|
|
|
|
|
|
|
// this.status[type] = this.status[type] === 0 ? 1 : 0;
|
|
|
|
|
// 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 ? "暂停" : "运行");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
// ========== 删除:原有connectMqtt方法(全局工具类已处理) ==========
|
|
|
|
|
// connectMqtt() { ... },
|
|
|
|
|
|
|
|
|
|
// ========== 删除:原有disconnectMqtt方法(全局工具类已处理) ==========
|
|
|
|
|
// disconnectMqtt() { ... },
|
|
|
|
|
|
|
|
|
|
// ========== 修改:替换原有publishMessage为调用全局工具类 ==========
|
|
|
|
|
publishMessage() {
|
|
|
|
|
if (!this.connected || !this.publishTopic || !this.message) {
|
|
|
|
|
uni.showToast({
|
|
|
|
|
@ -418,7 +382,6 @@ export default {
|
|
|
|
|
} else {
|
|
|
|
|
this.addMessage(`发布失败:设备:[${this.publishTopic}]`)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.message = {};
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
@ -426,14 +389,12 @@ export default {
|
|
|
|
|
ackMessage(topic, payload) {
|
|
|
|
|
// 1. 先判断是否是目标订阅主题(如dtu/xxx/up)
|
|
|
|
|
if (topic !== this.mqttConfig.subscribeTopic) return;
|
|
|
|
|
// console.log(`监听到消息:topic=${topic},message=${payload}`)
|
|
|
|
|
|
|
|
|
|
// 2. 解析消息体(注意异常捕获)
|
|
|
|
|
let msgData = {};
|
|
|
|
|
// 优化:捕获JSON解析异常
|
|
|
|
|
try {
|
|
|
|
|
msgData = JSON.parse(payload);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
console.error("消息解析失败:", e);
|
|
|
|
|
console.error("MQTT消息解析失败:", e, payload);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -444,6 +405,7 @@ export default {
|
|
|
|
|
this.handleOtherContent(msgData,payload)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
addMessage(content) {
|
|
|
|
|
console.info("提示消息:" + content)
|
|
|
|
|
},
|
|
|
|
|
@ -456,20 +418,17 @@ export default {
|
|
|
|
|
const isSuccess = ackData.suc; // 这里是true
|
|
|
|
|
|
|
|
|
|
if (isSuccess) {
|
|
|
|
|
this.status[type] = this.status[type] === 0 ? 1 : 0;
|
|
|
|
|
this.show[type] = this.status[type] === 0 ? "暂停" : "运行";
|
|
|
|
|
// 优化:使用$set确保响应式更新
|
|
|
|
|
this.$set(this.status, type, this.status[type] === 0 ? 1 : 0);
|
|
|
|
|
this.$set(this.show, type, this.status[type] === 0 ? "暂停" : "运行");
|
|
|
|
|
}
|
|
|
|
|
this.deviceType = '';
|
|
|
|
|
this.$modal.msgSuccess("设备操作成功!")
|
|
|
|
|
console.log(`指令[${commandField}=${commandValue}]执行${isSuccess ? "成功" : "失败"}`);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 处理其他内容的函数(完全保留)
|
|
|
|
|
handleOtherContent(msgData,payload) {
|
|
|
|
|
// 业务逻辑:处理传感器数据、设备状态等
|
|
|
|
|
// console.log("收到其他内容:", msgData);
|
|
|
|
|
// 例如:更新温湿度显示、设备在线状态等
|
|
|
|
|
|
|
|
|
|
// 设备状态展示
|
|
|
|
|
if (this.value !== 1) {
|
|
|
|
|
var arr = ['jbk', "jbg", "jm1k", "jm1g", "jm2k", "jm2g", "jm3k", "jm3g"]
|
|
|
|
|
@ -485,17 +444,17 @@ export default {
|
|
|
|
|
const allKeysNumeric2 = Object.keys(msgData).every(key => /^\d+$/.test(key));
|
|
|
|
|
if (Object.keys(msgData).length > 0 && allKeysNumeric2) {
|
|
|
|
|
const div10 = (v) => (v == null ? null : Math.round((Number(v)/10)*10)/10)
|
|
|
|
|
|
|
|
|
|
// 优化:使用常量获取传感器数据
|
|
|
|
|
this.liveData = {
|
|
|
|
|
temp1: div10(msgData["201"]) || "已离线...",
|
|
|
|
|
humi1: div10(msgData["101"]) || "已离线...",
|
|
|
|
|
temp2: div10(msgData["202"]) || "已离线...",
|
|
|
|
|
humi2: div10(msgData["102"]) || "已离线...",
|
|
|
|
|
temp3: div10(msgData["203"]) || "已离线...",
|
|
|
|
|
humi3: div10(msgData["103"]) || "已离线...",
|
|
|
|
|
temp4: div10(msgData["204"]) || "已离线...",
|
|
|
|
|
humi4: div10(msgData["104"]) || "已离线...",
|
|
|
|
|
}
|
|
|
|
|
temp1: div10(msgData[SENSOR_MAP.temp1]) || "已离线...",
|
|
|
|
|
humi1: div10(msgData[SENSOR_MAP.humi1]) || "已离线...",
|
|
|
|
|
temp2: div10(msgData[SENSOR_MAP.temp2]) || "已离线...",
|
|
|
|
|
humi2: div10(msgData[SENSOR_MAP.humi2]) || "已离线...",
|
|
|
|
|
temp3: div10(msgData[SENSOR_MAP.temp3]) || "已离线...",
|
|
|
|
|
humi3: div10(msgData[SENSOR_MAP.humi3]) || "已离线...",
|
|
|
|
|
temp4: div10(msgData[SENSOR_MAP.temp4]) || "已离线...",
|
|
|
|
|
humi4: div10(msgData[SENSOR_MAP.humi4]) || "已离线...",
|
|
|
|
|
};
|
|
|
|
|
this.temp = "最后更新时间:" + this.getCurrentTime();
|
|
|
|
|
this.fontStyle = 'font-size:16px;'
|
|
|
|
|
}
|
|
|
|
|
@ -526,19 +485,50 @@ export default {
|
|
|
|
|
testNumber(data) {
|
|
|
|
|
const reg = /^-?\d+(\.\d+)?$/;
|
|
|
|
|
return reg.test(String(data).trim());
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 优化:封装温湿度单位判断函数
|
|
|
|
|
isEffectiveValue(value) {
|
|
|
|
|
return this.testNumber(value);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 新增:打开修改运行时间的弹窗
|
|
|
|
|
openTimeModal(card) {
|
|
|
|
|
this.currentCard = card; // 记录当前卡片信息
|
|
|
|
|
this.currentCardTime = this.limitTimes[card.type]; // 记录当前时间
|
|
|
|
|
this.newTime = this.currentCardTime; // 默认填充当前时间
|
|
|
|
|
this.timeModalVisible = true; // 显示弹窗
|
|
|
|
|
console.info(`this.timeModalVisible:${this.timeModalVisible}`);
|
|
|
|
|
this.$refs.inputDialog.open()
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// 新增:确认修改运行时间
|
|
|
|
|
confirmModifyTime() {
|
|
|
|
|
// 校验输入:必须是1-60的数字
|
|
|
|
|
if (!this.newTime || this.newTime < 1 || this.newTime > 60) {
|
|
|
|
|
uni.showToast({
|
|
|
|
|
title: '请输入1-60的有效数字',
|
|
|
|
|
icon: 'none'
|
|
|
|
|
});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// 修改limitTimes(用$set确保响应式)
|
|
|
|
|
this.$set(this.limitTimes, this.currentCard.type, this.newTime);
|
|
|
|
|
// 提示修改成功
|
|
|
|
|
uni.showToast({
|
|
|
|
|
title: '运行时间修改成功',
|
|
|
|
|
icon: 'success'
|
|
|
|
|
});
|
|
|
|
|
// 关闭弹窗
|
|
|
|
|
this.$refs.inputDialog.close()
|
|
|
|
|
// (可选)这里可以加接口请求,把新时间同步到后端
|
|
|
|
|
// this.saveLimitTimeToServer(this.currentCard.type, this.newTime);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onHide() {
|
|
|
|
|
// ========== 修改:移除页面隐藏时的断开逻辑(全局App.vue已处理) ==========
|
|
|
|
|
// this.disconnectMqtt();
|
|
|
|
|
// 仅移除回调,避免后台接收消息导致异常
|
|
|
|
|
mqttUtil.removeOnMessageCallback();
|
|
|
|
|
},
|
|
|
|
|
beforeDestroy() {
|
|
|
|
|
// ========== 修改:移除原有client断开逻辑(全局工具类已处理) ==========
|
|
|
|
|
// if (this.client) {
|
|
|
|
|
// this.client.end()
|
|
|
|
|
// }
|
|
|
|
|
mqttUtil.removeOnMessageCallback();
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
@ -681,4 +671,63 @@ export default {
|
|
|
|
|
/deep/ .uni-section-header__slot-right {
|
|
|
|
|
color: green;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 新增:弹窗样式 */
|
|
|
|
|
.modal-container {
|
|
|
|
|
width: 600rpx;
|
|
|
|
|
background: #fff;
|
|
|
|
|
border-radius: 16rpx;
|
|
|
|
|
padding: 30rpx 20rpx;
|
|
|
|
|
}
|
|
|
|
|
.modal-title {
|
|
|
|
|
font-size: 30rpx;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
text-align: center;
|
|
|
|
|
margin-bottom: 30rpx;
|
|
|
|
|
color: #333;
|
|
|
|
|
}
|
|
|
|
|
.modal-input-wrap {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
margin-bottom: 25rpx;
|
|
|
|
|
font-size: 26rpx;
|
|
|
|
|
}
|
|
|
|
|
.modal-label {
|
|
|
|
|
width: 120rpx;
|
|
|
|
|
color: #666;
|
|
|
|
|
}
|
|
|
|
|
.modal-current {
|
|
|
|
|
color: #333;
|
|
|
|
|
}
|
|
|
|
|
.modal-input {
|
|
|
|
|
flex: 1;
|
|
|
|
|
height: 60rpx;
|
|
|
|
|
border: 1px solid #eee;
|
|
|
|
|
border-radius: 8rpx;
|
|
|
|
|
padding: 0 15rpx;
|
|
|
|
|
font-size: 26rpx;
|
|
|
|
|
}
|
|
|
|
|
.modal-unit {
|
|
|
|
|
margin-left: 10rpx;
|
|
|
|
|
color: #666;
|
|
|
|
|
}
|
|
|
|
|
.modal-btn-wrap {
|
|
|
|
|
display: flex;
|
|
|
|
|
gap: 20rpx;
|
|
|
|
|
margin-top: 40rpx;
|
|
|
|
|
}
|
|
|
|
|
.modal-btn {
|
|
|
|
|
flex: 1;
|
|
|
|
|
height: 70rpx;
|
|
|
|
|
border-radius: 8rpx;
|
|
|
|
|
font-size: 26rpx;
|
|
|
|
|
}
|
|
|
|
|
.modal-btn.cancel {
|
|
|
|
|
background: #f5f5f5;
|
|
|
|
|
color: #666;
|
|
|
|
|
}
|
|
|
|
|
.modal-btn.confirm {
|
|
|
|
|
background: #007aff;
|
|
|
|
|
color: #fff;
|
|
|
|
|
}
|
|
|
|
|
</style>
|