楼宇能效监测控制系统
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

1619 lines
47 KiB

<template>
<div class="app-container">
<div class="left-tree">
<!-- el-tree 设置一个固定的高度和滚动条 -->
<div style="height: 7rem; overflow-y: auto">
<el-tree
ref="tree"
:data="treeData"
node-key="id"
:default-expand-all="false"
:default-expanded-keys="expandedKeys"
:auto-expand-parent="true"
icon-class="none"
@node-expand="handleNodeExpand"
@node-collapse="handleNodeCollapse"
:highlight-current="true"
@node-click="handleNodeClick"
>
<template #default="{ node }">
<span class="custom-tree-node">
<!-- 根据节点状态动态设置图标类名 -->
<div class="tree-left">
<i :class="getIconClass(node)" class="custom-tree-icon"></i>
<span class="tree-label">{{ node.label }}</span>
</div>
</span>
</template>
</el-tree>
</div>
</div>
<div class="right-monitor">
<div class="buildingDiv">
<img
class="title-bg"
src="../../../assets/images/title-bg.png"
alt=""
/>
<div class="title-word">位置{{ currentName }}</div>
</div>
<div class="mostDiv">
<div class="windC">
<!-- 定时开关机定位 -->
<div class="menu-title" @click="openTimeSwitch">
<div @click="openTimeSwitch">定时开关机</div>
</div>
<!-- 空调风柜定位 -->
<img
class="wind-img"
src="../../../assets/images/fenggui.png"
alt=""
/>
<!-- 风扇定位 -->
<img
class="windMove"
:class="{ tunCircle: runStatusObj.collectValue }"
src="../../../assets/images/fengshan.png"
alt=""
/>
<!-- 箭头定位 -->
<div class="arrow-flex">
<img
class="wind-arrow"
src="../../../assets/images/orange-arrow.png"
alt=""
/>
<img
class="wind-arrow"
src="../../../assets/images/orange-arrow.png"
alt=""
/>
<img
class="wind-arrow"
src="../../../assets/images/orange-arrow.png"
alt=""
/>
<img
class="wind-arrow"
src="../../../assets/images/orange-arrow.png"
alt=""
/>
</div>
<div class="arrow-flex2">
<img
class="wind-arrow"
src="../../../assets/images/blue-arrow.png"
alt=""
/>
<img
class="wind-arrow"
src="../../../assets/images/blue-arrow.png"
alt=""
/>
<img
class="wind-arrow"
src="../../../assets/images/blue-arrow.png"
alt=""
/>
<img
class="wind-arrow"
src="../../../assets/images/blue-arrow.png"
alt=""
/>
</div>
<div class="arrow-flex3">
<img
class="wind-arrow"
src="../../../assets/images/blue-arrow.png"
alt=""
/>
<img
class="wind-arrow"
src="../../../assets/images/blue-arrow.png"
alt=""
/>
<img
class="wind-arrow"
src="../../../assets/images/blue-arrow.png"
alt=""
/>
<img
class="wind-arrow"
src="../../../assets/images/blue-arrow.png"
alt=""
/>
</div>
<div class="wind-tem1" v-if="isObjectValid(airSupplyObj)">
<div class="wind-text">回风温度</div>
<el-input
@keyup.enter.native="handleEnter(backAirObj, $event, '℃')"
@input="handleInput(backAirObj)"
@blur="handleBlur()"
v-model="backAirObj.collectValue"
size="mini"
>
<svg-icon slot="prefix" icon-class="tem_icon" class="tem-icon" />
</el-input>
</div>
<div class="wind-tem2" v-if="isObjectValid(airSupplyObj)">
<div class="wind-text">送风温度</div>
<el-input
@keyup.enter.native="handleEnter(airSupplyObj, $event, '℃')"
@input="handleInput(airSupplyObj)"
@blur="handleBlur()"
disabled
v-model="airSupplyObj.collectValue"
size="mini"
>
<svg-icon slot="prefix" icon-class="tem_icon" class="tem-icon" />
</el-input>
</div>
<div class="fan-satatus3">
<div class="context-li" v-if="isObjectValid(faultAlarmObj)">
<div class="wind-text">风机故障状态:</div>
<div class="badStautus" v-if="faultAlarmObj.collectValue">
故障
</div>
<div class="goodStautus" v-else>正常</div>
</div>
<div class="context-li" v-if="isObjectValid(runStatusObj)">
<div class="wind-text">风机运行状态:</div>
<div class="goodStautus" v-if="runStatusObj.collectValue">
运行
</div>
<div class="noneStautus" v-else>不运行</div>
</div>
<div class="context-li" v-if="isObjectValid(pressureObj)">
<div class="wind-text">风机压差:</div>
<div class="badStautus" v-if="pressureObj.collectValue">故障</div>
<div class="goodStautus" v-else>正常</div>
</div>
</div>
<div class="fan-satatus1">
<div class="context-li" v-if="isObjectValid(automaticObj)">
<div class="wind-text">风机手自动状态</div>
<el-switch
style="display: block"
v-model="automaticObj.collectValue"
active-color="#13ce66"
inactive-color="#ff4949"
active-text="手动"
inactive-text="自动"
@change="handleAutomaticText(automaticObj)"
>
</el-switch>
</div>
<div class="context-li" v-if="isObjectValid(startControlObj)">
<div class="wind-text">风机启停控制</div>
<el-switch
style="display: block"
v-model="startControlObj.collectValue"
active-color="#13ce66"
inactive-color="#ff4949"
active-text="开启"
inactive-text="停止"
@change="handleControlText(startControlObj)"
>
</el-switch>
</div>
</div>
<div class="fan-satatus2">
<div class="context-li" v-if="isObjectValid(waterSupplyObj)">
<div class="wind-text">供水温度</div>
<el-input
@keyup.enter.native="handleEnter(waterSupplyObj, $event, '℃')"
@input="handleInput(waterSupplyObj)"
@blur="handleBlur()"
disabled
v-model="waterSupplyObj.collectValue"
size="mini"
>
<svg-icon
slot="prefix"
icon-class="tem_icon"
class="tem-icon"
/>
</el-input>
</div>
<div class="context-li" v-if="isObjectValid(backwaterObj)">
<div class="wind-text">回水温度</div>
<el-input
@keyup.enter.native="handleEnter(backwaterObj, $event, '℃')"
@input="handleInput(backwaterObj)"
@blur="handleBlur()"
disabled
v-model="backwaterObj.collectValue"
size="mini"
>
<svg-icon
slot="prefix"
icon-class="tem_icon"
class="tem-icon"
/>
</el-input>
</div>
<div class="context-li" v-if="isObjectValid(waterValveObj)">
<div class="wind-text">水阀调节</div>
<el-input
@keyup.enter.native="handleEnter(waterValveObj, $event, '%')"
@input="handleInput(waterValveObj)"
@blur="handleBlur()"
v-model="waterValveObj.collectValue"
size="mini"
>
<svg-icon
slot="prefix"
icon-class="percentage-icon"
class="percentage-icon"
/>
</el-input>
</div>
</div>
<div class="wind-valve" v-if="isObjectValid(airValveBackObj)">
<div class="wind-text">新风阀反馈:</div>
<div>{{ airValveBackObj.collectValue }}%</div>
</div>
<div class="wind-valve2" v-if="isObjectValid(airValveObj)">
<div class="wind-text">新风阀调节</div>
<el-input
@keyup.enter.native="handleEnter(airValveObj, $event, '%')"
@input="handleInput(airValveObj)"
@blur="handleBlur()"
v-model="airValveObj.collectValue"
size="mini"
>
<svg-icon
slot="prefix"
icon-class="percentage-icon"
class="percentage-icon"
/>
</el-input>
</div>
</div>
</div>
</div>
<!-- 定时开关内容 -->
<el-dialog
title="定时开关机功能"
:visible.sync="isOpenTimeSwitch"
append-to-body
>
<div class="device-container" v-loading="loading">
<div class="device-li">
<div class="device-name">定时名称</div>
<div class="device-name">定时开机</div>
<div class="device-name">定时关机</div>
<div class="device-name">启动状态</div>
</div>
<div class="device-li" v-for="(item, index) in delayList" :key="index">
<div class="device-name">{{ item.name }}</div>
<div class="device-name">
<el-input
size="mini"
v-model="item.delayOpenHour"
@keyup.enter.native="handleSwitchEnter(item, 'openHour', $event)"
@input="handleSwitchInput(item, 'delayOpenHour', 'hour')"
></el-input>
<div class="slip">:</div>
<el-input
size="mini"
v-model="item.delayOpenMinute"
@keyup.enter.native="
handleSwitchEnter(item, 'openMinute', $event)
"
@input="handleSwitchInput(item, 'delayOpenMinute', 'minute')"
></el-input>
</div>
<div class="device-name">
<el-input
size="mini"
v-model="item.delayCloseHour"
@keyup.enter.native="handleSwitchEnter(item, 'closeHour', $event)"
@input="handleSwitchInput(item, 'delayCloseHour', 'hour')"
></el-input>
<div class="slip">:</div>
<el-input
size="mini"
v-model="item.delayCloseMinute"
@keyup.enter.native="
handleSwitchEnter(item, 'closeMinute', $event)
"
@input="handleSwitchInput(item, 'delayCloseMinute', 'minute')"
></el-input>
</div>
<div class="device-name">
<el-switch
style="display: block"
active-color="#13ce66"
inactive-color="#ff4949"
active-text="开启"
inactive-text="停用"
v-model="item.delayStatus"
@change="handleSwitchStatus(item)"
>
</el-switch>
</div>
</div>
</div>
</el-dialog>
</div>
</template>
<script>
import { spaceTree } from "@/api/region";
import { windList, timeList, undateTime } from "@/api/aircAndWindc/index";
import { operationConrol } from "@/api/hotWater/waterControl";
export default {
data() {
return {
loading: false,
treeData: [],
defaultProps: {
children: "children",
label: "label",
},
deviceList: [],
expandedKeys: [],
currentId: "", //当前选中高亮的id
currentName: "", //当前选中的名称
currentLevel: "", //当前节点的层级
currentParentId: "", //当前节点的上级的id
backwaterObj: {}, //回水温度
airValveObj: {}, //风阀调节
airValveBackObj: {}, //风阀反馈
waterValveObj: {}, //水阀调节
startControlObj: {}, //启停控制
runStatusObj: {}, //运行状态
airSupplyObj: {}, //送风温度
pressureObj: {}, //压差
automaticObj: {}, //手自动状态
backAirObj: {}, //回风温度
faultAlarmObj: {}, //故障报警
waterSupplyObj: {}, //供水温度
tableData: [], //系统状态表格数据
temValue: "℃", //回风温度
valvePercent: "%", //阀比例
runStatus: false, //运行状态
autoStatus: false, //手自动状态
startStatus: false, //启停控制
frequency: "v",
isOpenTimeSwitch: false,
delayList: [],
};
},
watch: {
temValue(newVal) {
let valueWithoutTem = newVal.replace(/℃/g, "");
if (valueWithoutTem === "") {
this.temValue = "℃";
} else {
this.temValue = valueWithoutTem + "℃";
}
},
valvePercent(newVal) {
// 去除输入值中的 %
let valueWithoutPercent = newVal.replace(/%/g, "");
// 如果输入值为空,保持 %
if (valueWithoutPercent === "") {
this.temValue = "%";
} else {
// 否则在输入值后面添加 %
this.temValue = valueWithoutPercent + "%";
}
},
frequency(newVal) {
let valueWithoutFrequency = newVal.replace(/v/g, "");
if (valueWithoutFrequency === "") {
this.temValue = "v";
} else {
this.temValue = valueWithoutFrequency + "v";
}
},
},
mounted() {
this.getSysBuild();
},
methods: {
// 判断对象是否有效(不为空且不为 undefined)
isObjectValid(obj) {
return obj && Object.keys(obj).length > 0;
},
getSysBuild() {
spaceTree().then((res) => {
if (res.code == 200) {
// 只需要保留热水的系统
console.log("楼栋返回值", res);
let newRes = { ...res };
if (newRes.data && newRes.data[0] && newRes.data[0].children) {
newRes.data[0].children = newRes.data[0].children.filter((item) => {
// 假设子项有一个 label属性,用于检查是否包含 "热水"
return item.label && item.label.includes("空调风柜");
});
}
// 指定要保留的最大层级(从 1 开始计数),这里假设指定为第 5 级
const targetLevel = 5;
// 从 data[0] 开始处理,当前层级为 1
if (newRes.data[0]) {
this.removeChildrenAfterLevel(newRes.data[0], 1, targetLevel);
}
console.log("筛选后的新结果", newRes);
this.treeData = newRes.data;
this.$nextTick(() => {
// 默认展开节点
this.getExpandedKeys(this.treeData, 1);
if (this.treeData.length > 0) {
// 找到最后一层的第一个子节点
const lastLevelFirstChild = this.findLastLevelFirstChild(
this.treeData[0]
);
// this.$refs.tree.setCurrentKey(
// this.treeData[0].children[0].children[0].children[0].id
// );
// 设置当前选中的节点,默认高亮
this.$refs.tree.setCurrentKey(lastLevelFirstChild.id);
// 更新当前节点的信息
this.currentId = lastLevelFirstChild.id;
this.currentLevel = lastLevelFirstChild.level;
this.currentName = lastLevelFirstChild.label;
console.log("当前选中节点ID", this.currentId);
console.log("当前选中节点层级", this.currentLevel);
console.log("当前选中节点名称", this.currentName);
this.getWindList();
}
});
}
});
},
// 递归函数,用于去除指定层级往后的 children 数据
removeChildrenAfterLevel(obj, currentLevel, targetLevel) {
if (currentLevel >= targetLevel) {
// 当达到指定层级时,将 children 属性置为空数组
obj.children = [];
return;
}
if (obj.children && obj.children.length > 0) {
// 若存在 children 数组,则递归处理每个子项
for (let i = 0; i < obj.children.length; i++) {
this.removeChildrenAfterLevel(
obj.children[i],
currentLevel + 1,
targetLevel
);
}
}
},
// 递归函数,找到最后一层的第一个子节点
findLastLevelFirstChild(node, level = 1) {
if (!node.children || node.children.length === 0) {
return {
id: node.id,
level,
label: node.label,
};
}
return this.findLastLevelFirstChild(node.children[0], level + 1);
},
// 默认只展示一二级菜单
getExpandedKeys(nodes, level) {
nodes.forEach((node) => {
if (level <= this.currentId + 4) {
this.expandedKeys.push(node.id);
}
if (node.children) {
this.getExpandedKeys(node.children, level + 1);
}
});
},
// 更换图标
getIconClass(node) {
// console.log("当前图标的节点内容", node);
if (node.level === 5) {
// 5级菜单时的图标
if (node.expanded) {
return "el-icon-document-opened"; // 5级菜单展开时的图标类名
}
return "el-icon-document"; // 5级菜单收缩时的图标类名
}
if (node.expanded) {
return "el-icon-folder-opened"; // 非5级菜单展开时的图标类名
}
return "el-icon-folder-add"; // 非5级菜单收缩时的图标类名
},
handleNodeExpand(node) {
// 节点展开时触发
},
handleNodeCollapse(node) {
// 节点收缩时触发
},
// 点击当前节点,保存节点内容
handleNodeClick(node, data) {
console.log("点击的当前节点", node, data);
if (data.level !== 5) {
console.log("不是第5层000");
// 设置当前选中的节点,默认高亮
this.$refs.tree.setCurrentKey(this.currentId);
console.log("当前选中节点ID", this.currentId);
console.log("当前选中节点层级", this.currentLevel);
console.log("当前选中节点名称", this.currentName);
} else {
console.log("第5层111");
this.currentId = node.id;
this.currentLevel = data.level;
this.currentName = node.label;
// 设置当前选中的节点,默认高亮
this.$refs.tree.setCurrentKey(this.currentId);
console.log("当前选中节点ID", this.currentId);
console.log("当前选中节点层级", this.currentLevel);
console.log("当前选中节点名称", this.currentName);
this.getWindList();
}
},
// 请求数据
getWindList() {
return new Promise((resolve, reject) => {
let data = {
systemType: "2",
houseId: this.currentId,
};
windList(data)
.then((res) => {
console.log("风柜系统查询返回", res);
if (res.code == 200 && res.rows.length > 0) {
let data = res.rows[0].values;
this.backwaterObj = {}; //回水温度
this.airValveObj = {}; //风阀调节
this.airValveBackObj = {}; //风阀反馈
this.waterValveObj = {}; //水阀调节
this.startControlObj = {}; //启停控制
this.runStatusObj = {}; //运行状态
this.airSupplyObj = {}; //送风温度
this.pressureObj = {}; //压差
this.automaticObj = {}; //手自动状态
this.backAirObj = {}; //回风温度
this.faultAlarmObj = {}; //故障报警
this.waterSupplyObj = {}; //供水温度
data.forEach((item) => {
// 回水温度
if (
item.paramType === "12" &&
item.collectName.includes("回水")
) {
this.backwaterObj = item;
}
//风阀调节
else if (
item.paramType === "3" &&
item.collectName.includes("新风阀")
) {
this.airValveObj = item;
}
//风阀反馈
else if (item.paramType === "4") {
this.airValveBackObj = item;
}
//水阀调节
else if (
item.paramType === "3" &&
item.collectName.includes("水阀调节")
) {
this.waterValveObj = item;
}
//启停控制 0停止1开启
else if (item.paramType === "2") {
this.startControlObj = item;
this.startControlObj.collectValue =
Number(item.collectValue) == 0 ? false : true;
}
//运行状态 0不运行1运行
else if (item.paramType === "1") {
this.runStatusObj = item;
this.runStatusObj.collectValue =
Number(item.collectValue) == 0 ? false : true;
}
//送风温度
else if (
item.paramType === "12" &&
item.collectName.includes("送风")
) {
this.airSupplyObj = item;
}
//压差 0正常1故障(true)
else if (item.paramType === "33") {
this.pressureObj = item;
this.pressureObj.collectValue =
Number(item.collectValue) == 0 ? false : true;
}
//手自动状态 0自动1手动
else if (item.paramType === "6") {
this.automaticObj = item;
this.automaticObj.collectValue =
Number(item.collectValue) == 0 ? false : true;
}
//回风温度
else if (
item.paramType === "12" &&
item.collectName.includes("回风")
) {
this.backAirObj = item;
}
//故障报警 0正常 1故障
else if (item.paramType === "5") {
this.faultAlarmObj = item;
this.faultAlarmObj.collectValue =
Number(item.collectValue) == 0 ? false : true;
}
//供水温度
else if (
item.paramType === "12" &&
item.collectName.includes("供水")
) {
this.waterSupplyObj = item;
}
});
} else {
this.backwaterObj = {};
this.airValveObj = {};
this.airValveBackObj = {};
this.waterValveObj = {};
this.startControlObj = {};
this.runStatusObj = {};
this.airSupplyObj = {};
this.pressureObj = {};
this.automaticObj = {};
this.backAirObj = {};
this.faultAlarmObj = {};
this.waterSupplyObj = {};
}
// 成功时解析 Promise
resolve(res);
})
.catch((error) => {
// 失败时拒绝 Promise
reject(error);
});
});
},
// 处理输入事件,过滤非数字字符
handleInput(item) {
console.log("校验");
// 实时校验并过滤非数字字符
item.collectValue = String(item.collectValue).replace(/[^\d]/g, "");
},
// 失去焦点
handleBlur() {
// this.currentFocusIndex = "";
},
handleEnter(item, event, unit) {
console.log("请求后端");
// 失去焦点
event.target.blur();
this.$confirm(
`确定要修改"${item.collectName}"为:${item.collectValue} ${unit}吗?`,
"提示",
{
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}
)
.then(() => {
this.hadleOperationConrol(item.id, item.collectValue);
})
.catch(() => {
// 用户取消操作,需要更新原来的频率
// this.$emit("upList");
});
},
// 手自动切换
handleAutomaticText(item) {
this.$confirm(
`确定要切换设备的状态为:${item.collectValue ? "手动" : "自动 吗?"}`,
"提示",
{
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}
)
.then(() => {
// 这里调用请求函数
let param = null;
if (item.collectValue) {
param = 1;
} else {
param = 0;
}
this.hadleOperationConrol(item.id, param);
})
.catch(() => {
// 用户取消操作,恢复开关状态
item.collectValue = !item.collectValue;
console.log("不请求后台");
});
},
//启停控制/手动控制
handleControlText(item) {
this.$confirm(
`确定要切换设备的状态为:${item.collectValue ? "开启" : "停止 吗?"}`,
"提示",
{
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}
)
.then(() => {
let param = null;
if (item.collectValue) {
param = 1;
} else {
param = 0;
}
this.hadleOperationConrol(item.id, param);
})
.catch(() => {
// 用户取消操作,恢复开关状态
item.collectValue = !item.collectValue;
console.log("不请求后台");
});
},
// 操作
hadleOperationConrol(id, param) {
let data = {
id: id,
param: param,
};
console.log("操作参数", data);
operationConrol([data])
.then((res) => {
if (res.code == 200) {
this.$modal.msgSuccess("指令下发成功!");
// 开启 loading 效果
this.loading = true;
// 更新所有设备状态;
setTimeout(() => {
this.getWindList().finally(() => {
// 关闭 loading 效果
this.loading = false;
});
}, 5000);
} else {
// this.$modal.msgError("操作失败");
console.log("应该更新状态的");
// 更新所有设备状态;
this.getWindList();
}
})
.catch((error) => {
console.log("请求发生错误,更新设备状态", error);
// 更新所有设备状态;
this.getWindList();
});
},
// 打开定时开关弹框
openTimeSwitch() {
this.isOpenTimeSwitch = true;
this.getPolicyList();
},
// 请求列表
getPolicyList() {
return new Promise((resolve, reject) => {
let data = {
systemType: "2",
funPolicyType: "3",
houseId: this.currentId,
};
timeList(data)
.then((res) => {
console.log("设备定时开关返回res", res);
if (res.code === 200) {
let handleList = res.rows;
this.delayList = [];
// 定义一个数组来映射数字到中文
const chineseNumbers = ["一", "二", "三", "四", "五", "六", "日"];
handleList.forEach((element, index) => {
if (element.values && element.values.length > 0) {
// 初始化一个空对象来存储非蝶阀处理后的结果
let delayItem = {
name: element.name,
};
const limitedChildren = element.values;
limitedChildren.forEach((child) => {
// console.log("定时${index}开_时", `定时${index}开_时`);
// console.log("child.pointName", child.pointName);
if (child.pointName) {
// 获取对应的中文数字
const chineseNumber = chineseNumbers[index];
// 定时开机-小时
if (child.pointName == `星期${chineseNumber}开_时`) {
// console.log("定时开机-时·························");
delayItem.delayOpenHour = child.curValue;
delayItem.delayOpenHourId = child.id;
}
// 定时开机-分钟
else if (
child.pointName.includes(`星期${chineseNumber}开_分`)
) {
delayItem.delayOpenMinute = child.curValue;
delayItem.delayOpenMinuteId = child.id;
}
// 定时关机-小时
else if (
child.pointName.includes(`星期${chineseNumber}关_时`)
) {
delayItem.delayCloseHour = child.curValue;
delayItem.delayCloseHourId = child.id;
}
// 定时关机-分钟
else if (
child.pointName.includes(`星期${chineseNumber}关_分`)
) {
delayItem.delayCloseMinute = child.curValue;
delayItem.delayCloseMinuteId = child.id;
}
// 启动状态
else if (child.pointName.includes(`启动标志`)) {
delayItem.delayStatus =
Number(child.curValue) == 0 ? false : true;
delayItem.delayStatusId = child.id;
}
}
});
// 将处理后的对象添加到 delayList 中
if (Object.keys(delayItem).length > 1) {
this.delayList.push(delayItem);
}
}
});
console.log("处理后的数组", this.delayList);
// this.delayList = res.rows;
} else {
this.delayList = [];
}
// 成功时解析 Promise
resolve(res);
})
.catch((error) => {
// 失败时拒绝 Promise
reject(error);
});
});
},
// 处理输入事件,过滤非数字字符
handleSwitchInput(item, propertyName, name) {
console.log("校验", item[propertyName]);
// 如果值为空,不进行后续校验
if (item[propertyName] === "") {
return;
}
let isValid = true;
// 实时校验并过滤非数字字符
let inputValue = String(item[propertyName]).replace(/[^\d]/g, "");
if (name === "hour") {
isValid =
!isNaN(inputValue) &&
parseInt(inputValue) >= 0 &&
parseInt(inputValue) <= 23;
if (!isValid) {
this.$message.error("输入值在0-23区间,请重新输入");
item[propertyName] = "";
return;
}
} else if (name === "minute") {
isValid =
!isNaN(inputValue) &&
parseInt(inputValue) >= 0 &&
parseInt(inputValue) <= 59;
if (!isValid) {
this.$message.error("输入值在0-59区间,请重新输入");
item[propertyName] = "";
return;
}
}
item[propertyName] = inputValue;
},
handleSwitchEnter(item, name, event) {
// 失去焦点
event.target.blur();
let id = "";
let value = "";
let title = "";
let unit = "";
if (name === "openHour") {
id = item.delayOpenHourId;
value = item.delayOpenHour;
title = "定时开机-小时";
unit = "时";
} else if (name === "openMinute") {
id = item.delayOpenMinuteId;
value = item.delayOpenMinute;
title = "定时开机-分钟";
unit = "分";
} else if (name === "closeHour") {
id = item.delayCloseHourId;
value = item.delayCloseHour;
title = "定时关机-小时";
unit = "时";
} else if (name === "closeMinute") {
id = item.delayCloseMinuteId;
value = item.delayCloseMinute;
title = "定时关机-分钟";
unit = "分";
}
if (value === "") {
this.$message.warning("请输入当前设置值!");
return;
}
console.log("请求后端", item);
this.$confirm(
`确定要把"${item.name}"的${title}设置为:${value} ${unit}吗?`,
"提示",
{
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}
)
.then(() => {
this.handleSwitchOperationConrol(id, value);
})
.catch(() => {
// 用户取消操作,需要更新原来的频率
this.getPolicyList();
});
},
handleSwitchOperationConrol(id, param) {
let data = {
policyId: id,
timeValue: param,
};
console.log("操作参数", data);
undateTime(data)
.then((res) => {
if (res.code == 200) {
this.$modal.msgSuccess("指令下发成功!");
// 开启 loading 效果
this.loading = true;
// 更新所有设备状态;
setTimeout(() => {
this.getPolicyList().finally(() => {
// 关闭 loading 效果
this.loading = false;
});
}, 500);
} else {
// this.$modal.msgError("操作失败");
console.log("应该更新状态的");
// 更新所有设备状态;
this.getPolicyList();
}
})
.catch((error) => {
console.log("请求发生错误,更新设备状态", error);
// 更新所有设备状态;
this.getPolicyList();
});
},
// 启用状态
handleSwitchStatus(item) {
this.$confirm(
`确定要切换"${item.name}"的状态为:${
item.delayStatus ? "开启" : "停用 吗?"
}`,
"提示",
{
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}
)
.then(() => {
// 这里调用请求函数
console.log("请求后台", item.delayStatus);
let param = null;
if (item.delayStatus) {
param = 1;
} else {
param = 0;
}
this.handleSwitchOperationConrol(item.delayStatusId, param);
})
.catch(() => {
// 用户取消操作,恢复开关状态
item.delayStatus = !item.delayStatus;
console.log("不请求后台");
});
},
},
};
</script>
<style lang="scss" scoped>
.buildingDiv {
padding-left: 54px;
display: flex;
flex-direction: row;
align-items: center;
margin-bottom: 20px;
position: relative;
.title-bg {
width: 208px;
height: 38px;
position: absolute;
left: 0;
z-index: 0;
}
.title-word {
z-index: 10;
font-family: YouSheBiaoTiHei;
font-size: 24px;
color: #ffffff;
white-space: nowrap;
}
}
.mostDiv {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.windC {
width: 13rem;
height: 5.38rem;
position: relative;
.menu-title {
color: #e1f4ff;
font-size: 0.18rem;
--bRadius: 0.05rem;
text-align: center;
position: absolute;
top: 0;
right: 0.5rem;
width: 1.25rem;
cursor: pointer;
z-index: 999;
div {
position: relative;
text-align: center;
border-radius: var(--bRadius);
transition: all 0.3s;
padding: 0.01rem 0.02rem;
background-color: rgba(85, 139, 211, 0.2);
cursor: pointer;
&::before,
&::after {
content: "";
position: absolute;
top: -10px;
left: -10px;
right: -10px;
bottom: -10px;
border: 2px solid #46b2f1;
transition: all 0.5s;
border-radius: var(--bRadius);
animation: clippath 3s infinite linear;
cursor: pointer;
}
&::after {
animation: clippath 3s infinite -1.5s linear;
}
@keyframes clippath {
0%,
100% {
clip-path: inset(0 0 98% 0);
}
25% {
clip-path: inset(0 98% 0 0);
}
50% {
clip-path: inset(98% 0 0 0);
}
75% {
clip-path: inset(0 0 0 98%);
}
}
}
}
.wind-img {
width: 13.1rem;
height: 5.5rem;
position: absolute;
top: 0;
left: 0;
z-index: 1;
}
.wind-tem1 {
z-index: 10;
width: 1.3rem;
position: absolute;
top: 0.3rem;
left: 7.3rem;
display: flex;
flex-direction: column;
align-items: center;
.wind-text {
color: #00d2ff;
font-size: 0.18rem;
margin-bottom: 0.15rem;
}
}
.wind-tem2 {
z-index: 10;
width: 1.3rem;
position: absolute;
top: 1.7rem;
right: 0.3rem;
display: flex;
flex-direction: column;
align-items: center;
.wind-text {
color: #00d2ff;
font-size: 0.18rem;
margin-bottom: 0.15rem;
}
}
.fan-frequency {
z-index: 10;
position: absolute;
top: 1.7rem;
left: 8.5rem;
width: 1.3rem;
display: flex;
flex-direction: column;
align-items: center;
.wind-text {
color: #00d2ff;
font-size: 0.18rem;
margin-bottom: 0.15rem;
}
}
.fan-satatus1 {
position: absolute;
top: 4.5rem;
left: 8.5rem;
display: flex;
flex-direction: column;
align-items: flex-start;
.context-li {
z-index: 10;
// width: 2rem;
margin-bottom: 0.1rem;
display: flex;
flex-direction: row;
align-items: center;
}
.wind-text {
color: #00d2ff;
font-size: 0.18rem;
margin-right: 0.15rem;
white-space: nowrap;
}
}
.fan-satatus2 {
position: absolute;
top: 5.5rem;
left: 6rem;
display: flex;
flex-direction: column;
align-items: flex-start;
.context-li {
z-index: 10;
width: 2rem;
margin-bottom: 0.1rem;
display: flex;
flex-direction: row;
align-items: center;
}
.wind-text {
color: #00d2ff;
font-size: 0.18rem;
margin-right: 0.15rem;
white-space: nowrap;
}
}
.fan-satatus3 {
position: absolute;
top: 1.7rem;
left: 8.5rem;
display: flex;
flex-direction: column;
align-items: flex-start;
.context-li {
z-index: 10;
// width: 2rem;
margin-bottom: 0.1rem;
display: flex;
flex-direction: row;
align-items: center;
}
.wind-text {
color: #00d2ff;
font-size: 0.18rem;
margin-right: 0.15rem;
white-space: nowrap;
}
.goodStautus {
color: rgb(57, 248, 51);
font-size: 0.18rem;
font-weight: bold;
display: flex;
flex-direction: row;
align-items: center;
}
.goodStautus::before {
content: "";
display: inline-block;
width: 0.1rem;
height: 0.1rem;
margin-right: 0.1rem;
border-radius: 50%;
background-color: rgb(57, 248, 51);
}
.badStautus {
color: rgb(248, 48, 41);
font-size: 0.18rem;
font-weight: bold;
display: flex;
flex-direction: row;
align-items: center;
animation: blink 1s infinite;
}
.badStautus::before {
content: "";
display: inline-block;
width: 0.1rem;
height: 0.1rem;
margin-right: 0.1rem;
border-radius: 50%;
background-color: rgb(248, 48, 41);
animation: blink 1s infinite;
}
.noneStautus {
color: rgb(194, 191, 191);
font-size: 0.18rem;
font-weight: bold;
display: flex;
flex-direction: row;
align-items: center;
}
.noneStautus::before {
content: "";
display: inline-block;
width: 0.1rem;
height: 0.1rem;
margin-right: 0.1rem;
border-radius: 50%;
background-color: rgb(194, 191, 191);
}
}
/* 定义灯闪烁的动画 */
@keyframes blink {
0% {
opacity: 1;
}
50% {
opacity: 0.7;
}
100% {
opacity: 1;
}
}
.wind-valve {
z-index: 10;
position: absolute;
top: 4.6rem;
left: 3rem;
width: 2rem;
display: flex;
flex-direction: row;
align-items: center;
font-size: 0.18rem;
.wind-text {
color: #00d2ff;
font-size: 0.18rem;
white-space: nowrap;
}
}
.wind-valve2 {
z-index: 10;
position: absolute;
top: 5rem;
left: 3rem;
width: 2rem;
display: flex;
flex-direction: row;
align-items: center;
.wind-text {
color: #00d2ff;
font-size: 0.18rem;
margin-right: 0.1rem;
white-space: nowrap;
}
}
.windMove {
width: 0.72rem;
height: 0.73rem;
position: absolute;
top: 3.23rem;
right: 3.81rem;
z-index: 10;
}
.tunCircle {
/* 应用动画 */
animation: rotate 2s linear infinite;
} /* 定义旋转动画 */
@keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.arrow-flex {
display: flex;
flex-direction: row;
align-items: center;
z-index: 10;
position: absolute;
top: 3.2rem;
left: -0.1rem;
}
.arrow-flex2 {
display: flex;
flex-direction: row;
align-items: center;
z-index: 10;
position: absolute;
top: 3.2rem;
right: 0.6rem;
}
.arrow-flex3 {
display: flex;
flex-direction: row;
align-items: center;
z-index: 10;
position: absolute;
top: 0.6rem;
right: 6rem;
transform: rotateY(180deg);
}
.wind-arrow {
width: 0.4rem;
height: 0.6rem;
margin-right: 0.15rem;
animation: moveArrow 2s linear infinite;
}
/* 定义每个箭头的透明度 */
.wind-arrow:nth-child(1) {
opacity: 1;
}
.wind-arrow:nth-child(2) {
opacity: 0.6;
}
.wind-arrow:nth-child(3) {
opacity: 0.4;
}
.wind-arrow:nth-child(4) {
opacity: 0.2;
}
/* 定义箭头移动的动画 */
@keyframes moveArrow {
0% {
transform: translateX(0);
}
100% {
transform: translateX(0.2rem);
/* 箭头向右移动的距离 */
}
}
}
.app-container {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: stretch;
height: 100%;
.left-tree {
width: 256px;
padding: 15px 10px 10px 10px;
border: 1px solid #004b8c;
.status {
display: flex;
flex-direction: row;
justify-content: space-between;
flex-wrap: wrap;
margin-top: 20px;
.status-li {
width: 50%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin-bottom: 15px;
}
.status1,
.status2,
.status3,
.status4 {
display: flex;
flex-direction: row;
align-items: center;
margin-bottom: 5px;
}
.status1::before {
content: "";
width: 10px;
height: 10px;
border-radius: 50%;
background-color: #00d2ff;
margin-right: 5px;
}
.status2::before {
content: "";
width: 10px;
height: 10px;
border-radius: 50%;
background-color: #ff2f2f;
margin-right: 5px;
}
.status3::before {
content: "";
width: 10px;
height: 10px;
border-radius: 50%;
background-color: #ff9908;
margin-right: 5px;
}
.status4::before {
content: "";
width: 10px;
height: 10px;
border-radius: 50%;
background-color: #7398c7;
margin-right: 5px;
}
}
}
.right-monitor {
width: calc(100% - 280px);
display: flex;
flex-direction: column;
justify-content: flex-start;
}
}
.tree-container {
height: 300px; /* 设置固定高度 */
overflow-y: auto; /* 启用垂直滚动条 */
}
// 滚动条
:-webkit-scrollbar {
width: 10px; /* 滚动条宽度 */
}
::-webkit-scrollbar-track {
background: transparent !important; /* 滚动条轨道背景色 */
}
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
.tree-left {
.custom-tree-icon {
margin-right: 5px;
}
}
}
.device-container {
display: flex;
flex-direction: column;
width: 100%;
min-height: 530px;
background-color: #142c4e;
padding: 10px 10px 30px 10px;
border-radius: 10px;
font-size: 14px;
.device-li {
width: 100%;
display: flex;
flex-direction: row;
align-items: center;
padding: 12px 0;
color: #abcdfc;
border-bottom: 1px dashed #0349ac;
.device-name {
flex: 1;
white-space: nowrap;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
flex-wrap: nowrap;
padding: 0 5px;
.slip {
margin: 0 5px;
color: #1282d8;
font-weight: bold;
}
}
}
.device-li:nth-child(1) {
color: #9ca3af;
}
}
// 媒体查询,适配大于2000px分辨率的大屏样式
@media (min-width: 2000px) {
.device-container {
min-height: 7rem !important;
padding: 0.1rem 0.1rem 0.3rem 0.1rem !important;
border-radius: 0.1rem !important;
font-size: 0.14rem !important;
.device-li {
padding: 0.12rem 0 !important;
.device-name {
.slip {
margin: 0 0.05rem !important;
}
}
}
}
}
@media (min-width: 1360px) and (max-width: 1680px) {
.windC {
transform: scale(0.9);
}
}
@media (min-width: 1160px) and (max-width: 1360px) {
.windC {
transform: scale(0.8);
}
}
@media (min-width: 990px) and (max-width: 1160px) {
.windC {
transform: scale(0.7);
}
}
</style>
<style scoped>
/* 自定义高亮颜色 */
.left-tree
>>> .el-tree--highlight-current
.el-tree-node.is-current
> .el-tree-node__content {
background-color: #285b9e !important;
/* color: #f56c6c; */
color: #25f1f8;
}
.windC >>> .el-input__inner {
background-color: #04193a;
border: 1px solid #1262db;
color: #3ef0fd;
font-weight: 700;
text-align: center;
padding: 0 0.1rem !important;
font-size: 0.18rem !important;
}
.windC >>> .el-input__prefix {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
.windC >>> .svg-icon {
width: 0.2rem !important;
height: 0.2rem !important;
fill: #ffffff !important;
}
</style>