自动化界面暂时提交
parent
a885f458bc
commit
fe134407d3
|
|
@ -1,51 +1,9 @@
|
|||
<template>
|
||||
<view>
|
||||
|
||||
<uni-section title="实时温湿度" titleFontSize="16px" type="line" v-if="value!== 1">
|
||||
<uni-section title="卷被卷膜控制" titleFontSize="16px" type="line"
|
||||
v-if="value!== 1 && !['862538065276939','A','B','C'].includes(value)">
|
||||
<template v-slot:right>
|
||||
{{ temp }}
|
||||
</template>
|
||||
|
||||
<view>
|
||||
<!-- 优化:温度卡片循环渲染 -->
|
||||
<view class="uni-flex_control uni-row" >
|
||||
<view
|
||||
class="text uni-flex_control_one uni-view"
|
||||
v-for="item in sensorCards.temp"
|
||||
:key="item.key"
|
||||
@click="openDataModal(item)"
|
||||
>
|
||||
<text class="data" :style="fontStyle">
|
||||
{{ liveData[item.key] }}
|
||||
<text v-if="isEffectiveValue(liveData[item.key])" class="tempStyle">℃</text>
|
||||
</text>
|
||||
<text class="data" v-if="dtu_remark[item.key]">{{ dtu_remark[item.key] }}</text>
|
||||
<text class="data" v-else>{{ item.label }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 优化:湿度卡片循环渲染 -->
|
||||
<view class="uni-flex_control uni-row" >
|
||||
<view
|
||||
class="text uni-flex_control_two uni-view"
|
||||
v-for="item in sensorCards.humi"
|
||||
:key="item.key"
|
||||
@click="openDataModal(item)"
|
||||
>
|
||||
<text class="data" :style="fontStyle">
|
||||
{{ liveData[item.key] }}
|
||||
<text v-if="isEffectiveValue(liveData[item.key])" class="humiStyle"> %RH</text>
|
||||
</text>
|
||||
<text class="data" v-if="dtu_remark[item.key]">{{ dtu_remark[item.key] }}</text>
|
||||
<text class="data" v-else>{{ item.label }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-section>
|
||||
|
||||
<uni-section title="设备控制" titleFontSize="16px" type="line" v-if="value!== 1 && !['862538065276939','A','B','C'].includes(imei)">
|
||||
<template v-slot:right >
|
||||
{{ control }}
|
||||
{{ status.deviceTime }}
|
||||
</template>
|
||||
<!-- 优化:设备卡片循环渲染 -->
|
||||
<view class="card-grid">
|
||||
|
|
@ -61,11 +19,14 @@
|
|||
<view class="card-sub-wrapper">
|
||||
<text class="card-sub" v-if="showStatusText">{{ show[card.type] || '未知' }}</text>
|
||||
<text class="limit-time">
|
||||
运行时间:{{ limitTimes[`${card.type}Limit`] && limitTimes[`${card.type}Limit`]!=='0' ? `${limitTimes[`${card.type}Limit`]} s` : '- -' }}
|
||||
运行时间:{{
|
||||
limitTimes[`${card.type}Limit`] && limitTimes[`${card.type}Limit`] !== '0' ? `${limitTimes[`${card.type}Limit`]} s` : '- -'
|
||||
}}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="showFlag" class="card-icon" :class="{ active: status[card.type] === 1 }" @click.stop="handleCardClick(1 - status[card.type], card.type)">
|
||||
<view v-if="showFlag" 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'"
|
||||
|
|
@ -75,22 +36,15 @@
|
|||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-section>
|
||||
<!---->
|
||||
<view class="film-roller">
|
||||
<tn-subsection :list="filmRollerList"
|
||||
current="2"
|
||||
:bold="true"
|
||||
:height="80"></tn-subsection>
|
||||
</view>
|
||||
|
||||
<uni-popup ref="inputNamelog" mode="center" >
|
||||
<!-- 新增:修改运行时间的弹窗 -->
|
||||
<view class="modal-container">
|
||||
<view class="modal-title">{{ `【${selectedText} - 实时温湿度】别名设置` }}</view>
|
||||
<view class="modal-input-wrap" >
|
||||
<text class="modal-label">别名设置:</text>
|
||||
<uni-easyinput style="width: 100px" v-model="remark" placeholder="不填展示默认备注" />
|
||||
</view>
|
||||
<view class="modal-btn-wrap">
|
||||
<button class="modal-btn cancel" @click="closeModalDataName">取消</button>
|
||||
<button class="modal-btn confirm" @click="confirmModifyName">确定</button>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</uni-section>
|
||||
|
||||
<uni-popup ref="inputDialog" mode="center">
|
||||
<!-- 新增:修改运行时间的弹窗 -->
|
||||
|
|
@ -126,112 +80,98 @@
|
|||
|
||||
<script>
|
||||
// 优化:抽离魔法值常量
|
||||
import UniPopupDialog from "../../../uni_modules/uni-popup/components/uni-popup-dialog/uni-popup-dialog.vue";
|
||||
|
||||
const SENSOR_MAP = {
|
||||
temp1: "201", temp2: "202", temp3: "203", temp4: "204",
|
||||
humi1: "101", humi2: "102", humi3: "103", humi4: "104"
|
||||
};
|
||||
const MQTT_TOPIC_SUFFIX = { UP: "/+", DOWN: "/control" };
|
||||
|
||||
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';
|
||||
import UniNumberBox from "../../../uni_modules/uni-number-box/components/uni-number-box/uni-number-box.vue";
|
||||
import {addLimit, getAgriByImei, updateLimit} from "../../../api/system/assets/limit";
|
||||
import {listAgri} from "../../../api/system/assets/agri";
|
||||
import {getNewSpecialData} from "../../../api/data/specialData";
|
||||
import store from "../../../store";
|
||||
import {addRemark, getRemarkByImei, updateRemark} from "../../../api/system/assets/remark";
|
||||
import CustomRefresher from "../../../components/custom-refresher/custom-refresher.vue";
|
||||
import ZPaging from "../../../uni_modules/z-paging/components/z-paging/z-paging.vue";
|
||||
import {addRemark, updateRemark} from "../../../api/system/assets/remark";
|
||||
|
||||
export default {
|
||||
dicts: ['sys_data_map'],
|
||||
name: "manual",
|
||||
props: {
|
||||
// 尺寸
|
||||
value: {
|
||||
type: String,
|
||||
default: "1"
|
||||
},
|
||||
// 打开时的背景颜色
|
||||
activeColor: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
dtu_remark: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
status: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
liveData: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
show: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
selectedText: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
agriId: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
deep: true, // 监听对象内部属性变化(防止数据是对象时监听不到)
|
||||
immediate: true, // 关键:进入组件就执行,不用等数据变化
|
||||
handler(newVal) {
|
||||
// 确保数据有值后执行方法
|
||||
if (newVal) {
|
||||
this.imei = this.value
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
ZPaging,
|
||||
UniNumberBox,
|
||||
UniPopupDialog,
|
||||
UniDatetimePicker,
|
||||
CustomRefresher,
|
||||
UniPopup // 注册弹窗组件
|
||||
},
|
||||
name: "automatic",
|
||||
mounted() {
|
||||
this.refresh()
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showFlag:true,
|
||||
temp: "",
|
||||
mqttConfig: {
|
||||
subscribeTopic:'/listener',
|
||||
},
|
||||
value: 1,
|
||||
selectedText: '',
|
||||
// 优化:语义化变量名(替换原 hide: false)
|
||||
showStatusText: false,
|
||||
control: '正在加载中...',
|
||||
// range: [],
|
||||
agriId:'',
|
||||
imei:'',
|
||||
publishTopic: '/control',
|
||||
title:'',
|
||||
message: {},
|
||||
// 优化:声明响应式变量 connected
|
||||
connected: false,
|
||||
remark:'',
|
||||
dtu_remark:{},
|
||||
liveData: {
|
||||
temp1: '数据加载中...',
|
||||
temp2: '数据加载中...',
|
||||
temp3: '数据加载中...',
|
||||
temp4: '数据加载中...',
|
||||
humi1: '数据加载中...',
|
||||
humi2: '数据加载中...',
|
||||
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' }
|
||||
]
|
||||
},
|
||||
sensorCard:{},
|
||||
// 优化:设备卡片配置(固定顺序)
|
||||
fontStyle: '',
|
||||
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关' },
|
||||
{type: 'jlk', name: '卷帘开'},
|
||||
{type: 'jlg', name: '卷帘关'},
|
||||
],
|
||||
// 卡片状态
|
||||
show: {
|
||||
jbk: "暂停",
|
||||
jbg: "暂停",
|
||||
jlg: "暂停",
|
||||
jlk: "暂停",
|
||||
jm1k: "暂停",
|
||||
jm1g: "暂停",
|
||||
jm2k: "暂停",
|
||||
jm2g: "暂停",
|
||||
jm3k: "暂停",
|
||||
jm3g: "暂停"
|
||||
},
|
||||
// 优化:语义化变量名(替换原 hide: false)
|
||||
showStatusText: false,
|
||||
showFlag: true,
|
||||
remark: '',
|
||||
// 新增:弹窗相关变量
|
||||
currentCard: {}, // 当前点击的卡片信息
|
||||
currentCardTime: '', // 当前卡片的运行时间
|
||||
newLimitTime: 0, // 新的运行时间
|
||||
message: {},
|
||||
// 优化:声明响应式变量 connected
|
||||
connected: false,
|
||||
imei: '',
|
||||
// 新增:限位时间配置
|
||||
limitTimes: {
|
||||
jbkLimit: 0,
|
||||
|
|
@ -245,222 +185,43 @@ export default {
|
|||
jm3kLimit: 0,
|
||||
jm3gLimit: 0
|
||||
},
|
||||
status: {
|
||||
jbk: 0,
|
||||
jbg: 0,
|
||||
jlk: 0,
|
||||
jlg: 0,
|
||||
jm1k: 0,
|
||||
jm1g: 0,
|
||||
jm2k: 0,
|
||||
jm2g: 0,
|
||||
jm3k: 0,
|
||||
jm3g: 0
|
||||
},
|
||||
testMsg:'由于线上为真实数据。任何操作均可影响线上功能,故仅作演示',
|
||||
fontStyle: '',
|
||||
// 新增:弹窗相关变量
|
||||
currentCard: {}, // 当前点击的卡片信息
|
||||
currentCardTime: '', // 当前卡片的运行时间
|
||||
newLimitTime: 0, // 新的运行时间
|
||||
filmRollerList:['卷膜1',"卷膜2","卷膜3"]
|
||||
};
|
||||
},
|
||||
onLoad(option) {
|
||||
console.info("自动模式")
|
||||
if (option.agriInfo) {
|
||||
const decodedStr = decodeURIComponent(option.agriInfo);
|
||||
const agriInfo = JSON.parse(decodedStr); // 反序列化为原对象
|
||||
this.value = agriInfo.imei;
|
||||
this.selectedText = agriInfo.agriName;
|
||||
this.agriId = agriInfo.agriId;
|
||||
this.change(this.value)
|
||||
}
|
||||
|
||||
this.title="";
|
||||
// 定义所有互斥的键对:[k键, g键]
|
||||
const mutexPairs = [
|
||||
['jbk', 'jbg'],
|
||||
['jlk', 'jlg'],
|
||||
['jm1k', 'jm1g'],
|
||||
['jm2k', 'jm2g'],
|
||||
['jm3k', 'jm3g']
|
||||
];
|
||||
|
||||
// 遍历处理每一组互斥规则(k=1则g=0,g=1则k=0)
|
||||
mutexPairs.forEach(([kKey, gKey]) => {
|
||||
if (this.status[kKey] === 1) this.status[gKey] = 0;
|
||||
if (this.status[gKey] === 1) this.status[kKey] = 0;
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
refresh() {
|
||||
// this.getAgriList()
|
||||
this.change(this.imei)
|
||||
mqttUtil.setOnMessageCallback(this.ackMessage);
|
||||
this.$refs.paging.complete();
|
||||
},
|
||||
getNewSpecialData() {
|
||||
getNewSpecialData().then(response => {
|
||||
if (response.code === 200 && response.data) {
|
||||
this.makeSpecialData(response.data,false);
|
||||
this.temp = "最后更新时间:"+response.data.time;
|
||||
this.fontStyle = 'font-size:16px;'
|
||||
}
|
||||
})
|
||||
},
|
||||
change(e) {
|
||||
this.imei = e;
|
||||
var clientId = mqttUtil.getMqttState().clientId;
|
||||
this.connected = mqttUtil.getMqttState().isConnected;
|
||||
if ((e === 'A' || e==='B' || e==='C')
|
||||
&& store.getters && store.getters.name === 'admin' ) {
|
||||
this.getNewSpecialData(e);
|
||||
this.mqttConfig.subscribeTopic = `frontend/${clientId}/dtu/862538065276061`;
|
||||
}
|
||||
// const selectedItem = this.range.find(item => item.value === e);
|
||||
// if (selectedItem) {
|
||||
// this.selectedText = selectedItem.text; // 获取展示文本
|
||||
// this.agriId = selectedItem.agriId;
|
||||
// this.title= this.selectedText;
|
||||
if (e !== 'A' && e!=='B' && e!=='C') {
|
||||
// 优化:使用常量拼接MQTT主题
|
||||
this.publishTopic = `frontend/${clientId}${MQTT_TOPIC_SUFFIX.DOWN}/${this.imei}`;
|
||||
this.mqttConfig.subscribeTopic = `frontend/${clientId}/dtu/${this.imei}`;
|
||||
var queryParams = {
|
||||
imei: this.imei
|
||||
}
|
||||
// 最新温湿度数据
|
||||
findDtuDataByInfo(queryParams).then(response => {
|
||||
Object.keys(response.data).forEach(key => {
|
||||
this.liveData[key] = response.data[key] || '已离线..';
|
||||
});
|
||||
this.temp = "最后更新时间:"+response.data.time;
|
||||
this.fontStyle = 'font-size:16px;'
|
||||
})
|
||||
// 限位
|
||||
this.showFlag = !((store.getters && store.getters.name !== 'admin') && this.$auth.hasRole("test"))
|
||||
this.getAgriByImei();
|
||||
// 备注
|
||||
this.getRemarkByImei();
|
||||
if (e!=="862538065276939"){
|
||||
this.message=JSON.stringify({jbk: 0,read:true})
|
||||
this.publishMessage()
|
||||
}
|
||||
}
|
||||
// } else {
|
||||
// this.selectedText = ''; // 无匹配项时清空
|
||||
// this.title='';
|
||||
// this.value=1;
|
||||
// this.agriId = '';
|
||||
// }
|
||||
this.reset();
|
||||
this.style="";
|
||||
},
|
||||
getRemarkByImei() {
|
||||
getRemarkByImei({imei:this.imei}).then(response => {
|
||||
if (response.code===200 && (response.data)) {
|
||||
this.dtu_remark={...response.data}
|
||||
}
|
||||
});
|
||||
},
|
||||
getAgriByImei() {
|
||||
getAgriByImei(this.imei).then(response => {
|
||||
if (response.code === 200) {
|
||||
if (!response.data) {
|
||||
openDataModal(sensorCard) {
|
||||
if ((store.getters && store.getters.name !== 'admin')
|
||||
&& this.$auth.hasRole("test")) {
|
||||
return;
|
||||
}
|
||||
this.limitTimes = response.data;
|
||||
}
|
||||
})
|
||||
this.sensorCard = sensorCard;
|
||||
this.remark = this.dtu_remark[sensorCard.key] || sensorCard.label;
|
||||
},
|
||||
getAgriList() {
|
||||
listAgri().then(response => {
|
||||
if (response.code === 200) {
|
||||
this.range = response.rows.map(item => ({
|
||||
agriId: item.id,
|
||||
text: item.agriName,
|
||||
value: item.imei // 提取并改名
|
||||
}));
|
||||
|
||||
if (store.getters && store.getters.name === 'admin') {
|
||||
this.range.push(
|
||||
{
|
||||
text:"八方南棚",
|
||||
value:"A"
|
||||
// 优化:封装温湿度单位判断函数
|
||||
isEffectiveValue(value) {
|
||||
return this.testNumber(value);
|
||||
},
|
||||
{
|
||||
text:"九方春棚",
|
||||
value:"B"
|
||||
testNumber(data) {
|
||||
const reg = /^-?\d+(\.\d+)?$/;
|
||||
return reg.test(String(data).trim());
|
||||
},
|
||||
{
|
||||
text:"十二方棚",
|
||||
value:"C"
|
||||
// 新增:打开修改运行时间的弹窗
|
||||
openTimeModal(card) {
|
||||
if ((store.getters && store.getters.name !== 'admin')
|
||||
&& this.$auth.hasRole("test")) {
|
||||
return;
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
testFunction(content) {
|
||||
uni.showModal({
|
||||
title: '操作提示:',
|
||||
content: content,
|
||||
cancelText: '确定',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
makeSpecialData(msgData, tag) {
|
||||
const div10 = (v) => (v == null ? null : Math.round((Number(v)/10)*10)/10);
|
||||
|
||||
// 1. 提取B/C的tag对应键名(精简重复三元)
|
||||
const B_KEYS = {
|
||||
true: {temp1:'205',humi1:'105',temp2:'206',humi2:'106',temp3:'207',humi3:'107',temp4:'208',humi4:'108'},
|
||||
false: {temp1:'temp5',humi1:'humi5',temp2:'temp6',humi2:'humi6',temp3:'temp7',humi3:'humi7',temp4:'temp8',humi4:'humi8'}
|
||||
};
|
||||
const C_KEYS = {
|
||||
true: {temp1:'209',humi1:'109',temp2:'210',humi2:'110',temp3:'211',humi3:'111',temp4:'212',humi4:'112'},
|
||||
false: {temp1:'temp9',humi1:'humi9',temp2:'temp10',humi2:'humi10',temp3:'temp11',humi3:'humi11',temp4:'temp12',humi4:'humi12'}
|
||||
};
|
||||
|
||||
// 2. 简化传感器键名映射表
|
||||
const IMEI_SENSOR_MAP = {
|
||||
A: SENSOR_MAP,
|
||||
B: B_KEYS[tag], // 直接取tag对应的键名,替代三元
|
||||
C: C_KEYS[tag]
|
||||
};
|
||||
|
||||
// 3. 确定传感器键名(精简变量名)
|
||||
const isAdmin = store.getters?.name === 'admin';
|
||||
const sk = (isAdmin && ['A','B','C'].includes(this.imei)) ? IMEI_SENSOR_MAP[this.imei] : IMEI_SENSOR_MAP.A;
|
||||
// 4. 简化liveData的嵌套三元(核心优化)
|
||||
this.liveData = Object.fromEntries(
|
||||
Object.entries(sk).map(([k, skVal]) => [
|
||||
k,
|
||||
(tag
|
||||
? div10(msgData[skVal])
|
||||
: (this.imei === 'A' ? msgData[k] : msgData[skVal]))
|
||||
|| "已离线..."
|
||||
])
|
||||
);
|
||||
},
|
||||
reset() {
|
||||
Object.keys(this.show).forEach(key => {
|
||||
this.show[key] = "暂停";
|
||||
});
|
||||
Object.keys(this.status).forEach(key => {
|
||||
this.status[key] = 0;
|
||||
});
|
||||
Object.keys(this.liveData).forEach(key => {
|
||||
this.liveData[key] = '数据加载中...';
|
||||
});
|
||||
Object.keys(this.limitTimes).forEach(key => {
|
||||
this.limitTimes[key] = 0;
|
||||
});
|
||||
this.control = '正在加载中...';
|
||||
this.message = {};
|
||||
this.temp = '';
|
||||
this.currentCard = card; // 记录当前卡片信息
|
||||
this.currentCardTime = this.limitTimes[`${card.type}Limit`]; // 记录当前时间
|
||||
this.newLimitTime = this.currentCardTime; // 默认填充当前时间
|
||||
this.remark = this.dtu_remark[card.type] || card.name;
|
||||
this.$refs.inputDialog.open()
|
||||
},
|
||||
// 卡片点击事件(实际项目中调用接口修改状态) 功能标识
|
||||
handleCardClick(status, type) {
|
||||
|
|
@ -503,7 +264,6 @@ export default {
|
|||
}
|
||||
if (this.value === 1) {
|
||||
this.$modal.msgError("设备控制失败!");
|
||||
console.info("大棚选取失败!")
|
||||
return;
|
||||
}
|
||||
uni.showModal({
|
||||
|
|
@ -516,7 +276,7 @@ export default {
|
|||
// 组装消息
|
||||
this.message = JSON.stringify({[`${type}1`]: status})
|
||||
// 控制设备
|
||||
this.publishMessage();
|
||||
this.$emit("publicMsg", this.message)
|
||||
//todo
|
||||
// this.testAuto(type);
|
||||
|
||||
|
|
@ -524,244 +284,12 @@ export default {
|
|||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 测试专用
|
||||
testAuto(type) {
|
||||
this.$set(this.status, type, this.status[type] === 0 ? 1 : 0);
|
||||
this.$set(this.show, type, this.status[type] === 0 ? "暂停" : "运行");
|
||||
},
|
||||
publishMessage() {
|
||||
if (!this.connected || !this.publishTopic || !this.message) {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 调用全局MQTT工具类发布消息
|
||||
const publishSuccess = mqttUtil.publishMqtt(this.publishTopic, this.message);
|
||||
if (publishSuccess) {
|
||||
this.addMessage(`【指令已发送】imei: ${this.publishTopic},指令: ${this.message}`);
|
||||
} else {
|
||||
this.addMessage(`发布失败:设备:[${this.publishTopic}]`)
|
||||
}
|
||||
this.message = {};
|
||||
},
|
||||
|
||||
// 消息回调逻辑完全保留(仅依赖全局工具类转发消息)
|
||||
ackMessage(topic, payload) {
|
||||
// 1. 先判断是否是目标订阅主题(如frontend/\\w+/control/\\w+")
|
||||
if ((topic !== this.mqttConfig.subscribeTopic+"/ack")
|
||||
&& (topic !== this.mqttConfig.subscribeTopic+"/listener")) return;
|
||||
let msgData = {};
|
||||
// 优化:捕获JSON解析异常
|
||||
try {
|
||||
msgData = JSON.parse(payload);
|
||||
} catch (e) {
|
||||
console.error("MQTT消息解析失败:", e, payload);
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. 区分“回执”和“其他内容”
|
||||
if (msgData.prop && "suc" in msgData) {
|
||||
this.handleCommandAck(msgData);
|
||||
} else if ("msg" in msgData && "clientId" in msgData) {
|
||||
if (mqttUtil.getMqttState().clientId === msgData.clientId) {
|
||||
this.$modal.msg(
|
||||
`${msgData.msg}`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
this.handleOtherContent(msgData,payload)
|
||||
}
|
||||
},
|
||||
|
||||
addMessage(content) {
|
||||
console.info("提示消息:" + content)
|
||||
},
|
||||
|
||||
// 处理指令回执的函数(核心修改:添加定时器+快照)
|
||||
handleCommandAck(ackData) {
|
||||
// 拿到指令字段(如jm2k)和执行状态(suc)
|
||||
const commandField = Object.keys(ackData.prop)[0]; // 这里是"jm2k"
|
||||
const commandValue = ackData.prop[commandField]; // 这里是0/1
|
||||
const isSuccess = ackData.suc; // 这里是true
|
||||
|
||||
const type = commandField.substring(0,commandField.length -1);
|
||||
if (isSuccess) {
|
||||
// 优化:使用$set确保响应式更新
|
||||
this.$set(this.status, type, commandValue);
|
||||
this.$set(this.show, type, commandValue === 0 ? "暂停" : "运行");
|
||||
console.info(`收到回执,更新功能码成功:{"${type}":${commandValue}}`)
|
||||
}
|
||||
|
||||
|
||||
// ========== 修改:自动停止指令不弹窗 ==========
|
||||
if (ackData.clientId && (ackData.clientId===mqttUtil.getMqttState().clientId)) {
|
||||
console.info("用户提示成功!")
|
||||
this.$modal[isSuccess ? 'msgSuccess' : 'msgError'](
|
||||
`设备操作${isSuccess ? "成功" : "失败"}!`
|
||||
);
|
||||
}
|
||||
console.log(`指令[${commandField}=${commandValue}]执行${isSuccess ? "成功" : "失败"}`);
|
||||
},
|
||||
|
||||
handleOtherContent(msgData,payload) {
|
||||
// 业务逻辑:处理传感器数据、设备状态等
|
||||
// 设备状态展示
|
||||
if (this.value !== 1) {
|
||||
var arr = ['jbk', "jbg", "jm1k", "jm1g", "jm2k", "jm2g", "jm3k", "jm3g","jlk","jlg"]
|
||||
const allKeysNumeric = Object.keys(msgData).some(key => arr.includes(key));
|
||||
if (allKeysNumeric) {
|
||||
this.status = {...msgData}
|
||||
Object.keys(msgData).forEach(key => {
|
||||
const value = msgData[key];
|
||||
this.show[key] = value === 0 ? '暂停' : '运行';
|
||||
});
|
||||
this.control = '最后更新时间:' + this.getCurrentTime();
|
||||
}
|
||||
const allKeysNumeric2 = Object.keys(msgData).every(key => /^\d+$/.test(key));
|
||||
if (Object.keys(msgData).length > 0 && allKeysNumeric2) {
|
||||
this.temp = "最后更新时间:" + this.getCurrentTime();
|
||||
this.fontStyle = 'font-size:16px;'
|
||||
|
||||
this.makeSpecialData(msgData, true);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取格式化后的当前时间
|
||||
* @returns {string} 格式为 YYYY-MM-DD HH:mm:ss 的当前时间
|
||||
*/
|
||||
getCurrentTime() {
|
||||
const now = new Date();
|
||||
|
||||
// 获取年、月、日(补零确保两位数)
|
||||
const year = now.getFullYear();
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0'); // 月份从 0 开始,需 +1
|
||||
const day = String(now.getDate()).padStart(2, '0');
|
||||
|
||||
// 获取时、分、秒(补零确保两位数)
|
||||
const hours = String(now.getHours()).padStart(2, '0');
|
||||
const minutes = String(now.getMinutes()).padStart(2, '0');
|
||||
const seconds = String(now.getSeconds()).padStart(2, '0');
|
||||
|
||||
// 拼接成标准格式
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||
},
|
||||
|
||||
testNumber(data) {
|
||||
const reg = /^-?\d+(\.\d+)?$/;
|
||||
return reg.test(String(data).trim());
|
||||
},
|
||||
|
||||
// 优化:封装温湿度单位判断函数
|
||||
isEffectiveValue(value) {
|
||||
return this.testNumber(value);
|
||||
},
|
||||
|
||||
// 新增:打开修改运行时间的弹窗
|
||||
openTimeModal(card) {
|
||||
if ((store.getters && store.getters.name !== 'admin')
|
||||
&& this.$auth.hasRole("test")) {
|
||||
return;
|
||||
}
|
||||
this.currentCard = card; // 记录当前卡片信息
|
||||
this.currentCardTime = this.limitTimes[`${card.type}Limit`]; // 记录当前时间
|
||||
this.newLimitTime = this.currentCardTime; // 默认填充当前时间
|
||||
this.remark = this.dtu_remark[card.type] || card.name;
|
||||
this.$refs.inputDialog.open()
|
||||
},
|
||||
openDataModal(sensorCard) {
|
||||
if ((store.getters && store.getters.name !== 'admin')
|
||||
&& this.$auth.hasRole("test")) {
|
||||
return;
|
||||
}
|
||||
this.sensorCard = sensorCard;
|
||||
this.remark=this.dtu_remark[sensorCard.key] || sensorCard.label;
|
||||
this.$refs.inputNamelog.open()
|
||||
},
|
||||
confirmModifyName() {
|
||||
const funcMsg = "该功能用来设置温湿度卡片别名,如若不填则展示默认备注"
|
||||
if ((store.getters && store.getters.name !== 'admin')
|
||||
&& this.$auth.hasRole("test")) {
|
||||
// this.testFunction(`${this.testMsg}\n${funcMsg}`)
|
||||
this.$refs?.inputNamelog?.close();
|
||||
return;
|
||||
}
|
||||
// 1. 解构赋值优化:直接拆分sensorCard的key/label,减少冗余
|
||||
let {
|
||||
selectedText,
|
||||
dtu_remark,
|
||||
imei,
|
||||
sensorCard: { key: sensorKey, label: sensorLabel },
|
||||
remark
|
||||
} = this;
|
||||
|
||||
remark = remark || sensorLabel;
|
||||
// 2. 语义化判定:别名是否修改
|
||||
const isRemarkModified = remark !== (dtu_remark[sensorKey] || sensorLabel);
|
||||
if (!isRemarkModified) {
|
||||
// 统一关闭弹窗方式
|
||||
this.$refs?.inputNamelog?.close();
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. 确认弹窗(async/await处理异步请求)
|
||||
uni.showModal({
|
||||
title: '温馨提示:',
|
||||
content: `确定将${selectedText}-${sensorLabel}别名设置为:${remark}?`, // 修复文案冗余冒号,补全remark变量
|
||||
cancelText: '取消',
|
||||
confirmText: '确定',
|
||||
success: async (res) => {
|
||||
// 关闭弹窗(无论确认/取消都关闭)
|
||||
this.$refs?.inputNamelog?.close();
|
||||
|
||||
if (!res.confirm) return; // 取消操作直接返回
|
||||
|
||||
try {
|
||||
// 4. 设置loading(可选,防止重复点击)
|
||||
// uni.showLoading({ title: '处理中...' });
|
||||
|
||||
// 5. 更新响应式数据
|
||||
this.$set(dtu_remark, sensorKey, remark); // sensorKey本身是字符串,无需拼接
|
||||
// 补全imei字段(确保非空)
|
||||
if (!dtu_remark.imei) {
|
||||
this.$set(dtu_remark, 'imei', imei);
|
||||
}
|
||||
|
||||
// 6. 异步请求:await等待结果(核心修复)
|
||||
const remarkRes = dtu_remark.id ? await updateRemark(dtu_remark) : await addRemark(dtu_remark);
|
||||
|
||||
// 7. 根据接口响应提示
|
||||
const isSuccess = remarkRes.code === 200;
|
||||
this.$modal[isSuccess ? 'msgSuccess' : 'msgError'](
|
||||
isSuccess ? '修改成功' : '修改失败'
|
||||
);
|
||||
|
||||
// 8. 仅成功时刷新数据(失败时不刷新,避免覆盖现有数据)
|
||||
if (isSuccess) {
|
||||
this.getRemarkByImei();
|
||||
}
|
||||
} catch (error) {
|
||||
// 捕获网络异常/接口报错
|
||||
console.error('别名修改失败:', error);
|
||||
this.$modal.msgError('修改失败,请重试');
|
||||
} finally {
|
||||
// 无论成功/失败,关闭loading
|
||||
// uni.hideLoading();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
closeModalDataName() {
|
||||
this.$refs.inputNamelog.close()
|
||||
},
|
||||
close() {
|
||||
this.$refs.inputDialog.close()
|
||||
},
|
||||
// 新增:确认修改运行时间
|
||||
// 确认修改运行时间
|
||||
confirmModifyTime() {
|
||||
confirmModifyTime: function () {
|
||||
const funcMsg = "该功能用来设置设备运行时间及设备别名,设备运行时间即开启设备后到达运行时间自行暂停设备;设备别名不填则展示默认设备名称"
|
||||
if ((store.getters && store.getters.name !== 'admin')
|
||||
&& this.$auth.hasRole("test")) {
|
||||
|
|
@ -814,7 +342,7 @@ export default {
|
|||
|
||||
if (!res.confirm) return; // 取消操作则直接返回
|
||||
|
||||
let isAllSuccess = true; // 统一判定所有请求是否成功
|
||||
let isAllSuccess = false; // 统一判定所有请求是否成功
|
||||
|
||||
try {
|
||||
// 7. 处理运行时间修改
|
||||
|
|
@ -830,9 +358,10 @@ export default {
|
|||
const limitRes = limitTimes.id
|
||||
? await updateLimit(limitTimes)
|
||||
: await addLimit(limitTimes);
|
||||
if (limitRes.code !== 200) isAllSuccess = false;
|
||||
// 新增后刷新数据
|
||||
if (!limitTimes.imei) this.getAgriByImei();
|
||||
if (limitRes.code === 200) {
|
||||
isAllSuccess = true;
|
||||
this.getAgriByImei();
|
||||
}
|
||||
}
|
||||
|
||||
// 8. 处理别名修改
|
||||
|
|
@ -846,9 +375,10 @@ export default {
|
|||
const remarkRes = dtu_remark.id
|
||||
? await updateRemark(dtu_remark)
|
||||
: await addRemark(dtu_remark);
|
||||
if (remarkRes.code !== 200) isAllSuccess = false;
|
||||
// 新增后刷新数据
|
||||
if (!dtu_remark.imei) this.getRemarkByImei();
|
||||
if (remarkRes.code === 200) {
|
||||
this.$emit("getRemark")
|
||||
isAllSuccess = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 9. 正确的提示逻辑(修复原本文案反写的问题)
|
||||
|
|
@ -862,30 +392,26 @@ export default {
|
|||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
getAgriByImei() {
|
||||
getAgriByImei(this.imei).then(response => {
|
||||
if (response.code === 200) {
|
||||
if (!response.data) {
|
||||
return;
|
||||
}
|
||||
this.limitTimes = response.data;
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
@import '@/tuniao-ui/index.scss';
|
||||
@import "@/colorui/main.css";
|
||||
@import "@/colorui/icon.css";
|
||||
|
||||
/deep/ .z-paging-content-fixed {
|
||||
padding: 20rpx !important;
|
||||
/* 可选:防止margin塌陷,加overflow */
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 控制设置标题 */
|
||||
.control-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
margin-bottom: 30rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* 2列栅格布局 */
|
||||
.card-grid {
|
||||
|
|
@ -941,6 +467,7 @@ export default {
|
|||
/* 可选:加固定左边距,确保和暂停的间距统一 */
|
||||
margin-left: 0rpx;
|
||||
}
|
||||
|
||||
/* 卡片图标容器 */
|
||||
.card-icon {
|
||||
width: 48rpx;
|
||||
|
|
@ -956,6 +483,7 @@ export default {
|
|||
.card-icon.active {
|
||||
background-color: #007aff;
|
||||
}
|
||||
|
||||
.uni-px-5 {
|
||||
padding-left: 20rpx;
|
||||
padding-right: 20rpx;
|
||||
|
|
@ -1001,11 +529,13 @@ export default {
|
|||
line-height: 23px;
|
||||
color: #3a3a3a;
|
||||
}
|
||||
|
||||
.data:nth-child(even) {
|
||||
font-size: 12px;
|
||||
margin-top: 3px;
|
||||
color: #9c9c9c;
|
||||
}
|
||||
|
||||
/deep/ .uni-section-header__slot-right {
|
||||
color: green;
|
||||
}
|
||||
|
|
@ -1017,6 +547,7 @@ export default {
|
|||
border-radius: 16rpx;
|
||||
padding: 30rpx 20rpx;
|
||||
}
|
||||
|
||||
.modal-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
|
|
@ -1024,6 +555,7 @@ export default {
|
|||
margin-bottom: 40rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.modal-input-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
@ -1031,14 +563,17 @@ export default {
|
|||
font-size: 26rpx;
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
|
||||
.modal-label {
|
||||
width: 160rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.modal-current {
|
||||
margin-left: 14rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.modal-input {
|
||||
height: 60rpx;
|
||||
border: 1px solid #eee;
|
||||
|
|
@ -1047,35 +582,39 @@ export default {
|
|||
font-size: 26rpx;
|
||||
width: 80rpx;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin-left: 15rpx
|
||||
}
|
||||
.uni-stat-tooltip {
|
||||
width: 300rpx;
|
||||
}
|
||||
|
||||
/deep/ .is-input-border {
|
||||
width: 340rpx;
|
||||
}
|
||||
|
|
@ -1084,5 +623,8 @@ export default {
|
|||
border-radius: 20rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
.film-roller {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
</style>
|
||||
Loading…
Reference in New Issue