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.
1470 lines
48 KiB
1470 lines
48 KiB
<template> |
|
<div class="app-container" v-loading="loading"> |
|
<div class="left-tree"> |
|
<!-- 为 el-tree 设置一个固定的高度和滚动条 --> |
|
<div style="height: 7.5rem; 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="details-header"> |
|
<el-tabs v-model="activeName" @tab-click="handleClick"> |
|
<!-- 使用 v-for 指令遍历 tabsList 数组 --> |
|
<el-tab-pane |
|
v-for="device in tabsList" |
|
:key="device.id" |
|
:label="device.name" |
|
:name="device.name" |
|
> |
|
<!-- 这里可以添加每个 tab 对应的内容 --> |
|
</el-tab-pane> |
|
</el-tabs> |
|
</div> |
|
<div class="monitor-context"> |
|
<div |
|
class="monitor-li" |
|
v-for="item in devicesList" |
|
:key="item.deviceId" |
|
> |
|
<div class="monitor-title">{{ item.name }}</div> |
|
<div class="monitor-flex"> |
|
<!-- 热泵 --> |
|
<div class="monitor-flex-left" v-if="activeName.includes('热泵')"> |
|
<div class="control-top"> |
|
<img |
|
class="monitor-img1" |
|
src="../../../assets/images/starthotpum.png" |
|
/> |
|
<div class="monitor-words"> |
|
<div class="words-li"> |
|
<div class="ash">开关状态:</div> |
|
<div class="white"> |
|
<el-select |
|
v-model="item.hotPumpStatus" |
|
placeholder="请选择" |
|
@change="handleHotPump(item)" |
|
> |
|
<el-option |
|
v-for="item in hotPumpOptions" |
|
:key="item.value" |
|
:label="item.label" |
|
:value="item.value" |
|
> |
|
</el-option> |
|
</el-select> |
|
</div> |
|
</div> |
|
<div class="words-li"> |
|
<div class="ash">故障信息:</div> |
|
<el-tag |
|
size="mini" |
|
v-if="item.alarmStatus === '无故障'" |
|
type="success" |
|
>{{ item.alarmStatus }}</el-tag |
|
> |
|
<el-tag size="mini" v-else type="danger">{{ |
|
item.alarmStatus |
|
}}</el-tag> |
|
</div> |
|
<div class="words-li"> |
|
<div class="ash">实际温度:</div> |
|
<div class="white">{{ item.temp }}℃</div> |
|
</div> |
|
<div class="words-li"> |
|
<div class="ash">设定温度:</div> |
|
<div class="white"> |
|
<el-input |
|
size="mini" |
|
v-model="item.tempSet" |
|
placeholder="请输入" |
|
@keyup.enter.native=" |
|
handleEnter( |
|
item, |
|
item.tempSet, |
|
item.tempSetId, |
|
'设定温度', |
|
'℃' |
|
) |
|
" |
|
@input="handleInput(item)" |
|
@blur="handleBlur()" |
|
></el-input> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
<!-- 裙楼供水泵、高区供水泵、中厨供水泵 --> |
|
<div class="monitor-flex-left" v-if="activeName.includes('供水泵')"> |
|
<div class="control-top"> |
|
<img |
|
class="monitor-img2" |
|
src="../../../assets/images/startpum.png" |
|
/> |
|
<div class="monitor-words"> |
|
<div class="words-li"> |
|
<div class="ash" style="letter-spacing: 5px"> |
|
频率手自动: |
|
</div> |
|
<div class="white"> |
|
<el-switch |
|
style="display: block" |
|
v-model="item.handAutomaticSwitch" |
|
active-color="#13ce66" |
|
active-text="手动" |
|
inactive-text="自动" |
|
@change="handAutomatic(item)" |
|
> |
|
</el-switch> |
|
</div> |
|
</div> |
|
<div class="words-li"> |
|
<div class="ash" style="letter-spacing: 7px"> |
|
启停 控制: |
|
</div> |
|
<div class="white"> |
|
<el-switch |
|
style="display: block" |
|
v-model="item.switchStatus" |
|
active-color="#13ce66" |
|
active-text="开启" |
|
inactive-text="停止" |
|
@change="handleSwitch(item)" |
|
> |
|
</el-switch> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
<div class="control-bottom"> |
|
<div class="words-li"> |
|
<div class="ash">故障信息:</div> |
|
<el-tag |
|
size="mini" |
|
v-if="item.alarmStatus === '无故障'" |
|
type="success" |
|
>{{ item.alarmStatus }}</el-tag |
|
> |
|
<el-tag size="mini" v-else type="danger">{{ |
|
item.alarmStatus |
|
}}</el-tag> |
|
</div> |
|
<div class="words-li"> |
|
<div class="ash">运行状态:</div> |
|
<el-tag |
|
size="mini" |
|
v-if="item.runningStatus === '运行'" |
|
type="success" |
|
>{{ item.runningStatus }}</el-tag |
|
> |
|
<el-tag size="mini" v-else type="danger">{{ |
|
item.runningStatus |
|
}}</el-tag> |
|
</div> |
|
<div class="words-li"> |
|
<div class="ash">当前频率:</div> |
|
<div class="white">{{ item.frequency }}Hz</div> |
|
</div> |
|
<div class="words-li"> |
|
<div class="ash">频率设置:</div> |
|
<el-input |
|
v-model="item.frequencySet" |
|
@keyup.enter.native=" |
|
handleEnter( |
|
item, |
|
item.frequencySet, |
|
item.frequencySetId, |
|
'频率设置', |
|
'Hz' |
|
) |
|
" |
|
@input="handleInput(item)" |
|
@blur="handleBlur()" |
|
size="mini" |
|
></el-input> |
|
<div class="white">Hz</div> |
|
</div> |
|
<div class="words-li"> |
|
<div class="ash">压力设置:</div> |
|
<el-input |
|
v-model="item.pressureSet" |
|
@keyup.enter.native=" |
|
handleEnter( |
|
item, |
|
item.pressureSet, |
|
item.pressureSetId, |
|
'压力设置', |
|
'bar' |
|
) |
|
" |
|
@input="handleInput(item)" |
|
@blur="handleBlur()" |
|
size="mini" |
|
></el-input> |
|
<div class="white">bar</div> |
|
</div> |
|
<div class="words-li"> |
|
<div class="ash">停机延时:</div> |
|
<el-input |
|
v-model="item.delayTimeSet" |
|
@keyup.enter.native=" |
|
handleEnter( |
|
item, |
|
item.delayTimeSet, |
|
item.delayTimeSetId, |
|
'停机延时', |
|
'S' |
|
) |
|
" |
|
@input="handleInput(item)" |
|
@blur="handleBlur()" |
|
size="mini" |
|
></el-input> |
|
<div class="white">S</div> |
|
</div> |
|
<div class="words-li"> |
|
<div class="ash">换机时间:</div> |
|
<el-input |
|
v-model="item.counterSet" |
|
@keyup.enter.native=" |
|
handleEnter( |
|
item, |
|
item.counterSet, |
|
item.counterSetId, |
|
'换机时间', |
|
'次' |
|
) |
|
" |
|
@input="handleInput(item)" |
|
@blur="handleBlur()" |
|
size="mini" |
|
></el-input> |
|
<div class="white">次</div> |
|
</div> |
|
<div class="words-li"> |
|
<div class="white">一次50分钟</div> |
|
</div> |
|
</div> |
|
</div> |
|
<!-- 裙楼供水泵、高区供水泵、中厨回水泵 --> |
|
<div class="monitor-flex-left" v-if="activeName.includes('回水')"> |
|
<div class="control-top"> |
|
<img |
|
class="monitor-img3" |
|
src="../../../assets/images/pump.png" |
|
/> |
|
<div class="monitor-words"> |
|
<div class="words-li"> |
|
<div class="ash">回水温度:</div> |
|
<div class="white">{{ item.temp }}℃</div> |
|
</div> |
|
<div class="words-li"> |
|
<div class="ash">回水温度设置:</div> |
|
<el-input |
|
v-model="item.tempSet" |
|
@keyup.enter.native=" |
|
handleEnter( |
|
item, |
|
item.tempSet, |
|
item.tempSetId, |
|
'回水温度', |
|
'℃' |
|
) |
|
" |
|
@input="handleInput(item)" |
|
@blur="handleBlur()" |
|
size="mini" |
|
></el-input> |
|
<div class="white">℃</div> |
|
</div> |
|
<div class="words-li"> |
|
<div class="ash">回水温度设定差值:</div> |
|
<el-input |
|
v-model="item.diffValueSet" |
|
@keyup.enter.native=" |
|
handleEnter( |
|
item, |
|
item.diffValueSet, |
|
item.diffValueSetId, |
|
'回水温度设定差值', |
|
'℃' |
|
) |
|
" |
|
@input="handleInput(item)" |
|
@blur="handleBlur()" |
|
size="mini" |
|
></el-input> |
|
<div class="white">℃</div> |
|
</div> |
|
<div class="words-li"> |
|
<div class="ash">回水温度设定延时时间:</div> |
|
<el-input |
|
v-model="item.delayTimeSet" |
|
@keyup.enter.native=" |
|
handleEnter( |
|
item, |
|
item.delayTimeSet, |
|
item.delayTimeSetId, |
|
'回水温度设定延时时间', |
|
'S' |
|
) |
|
" |
|
@input="handleInput(item)" |
|
@blur="handleBlur()" |
|
size="mini" |
|
></el-input> |
|
<div class="white">min</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
<!-- 水箱 --> |
|
<div class="monitor-flex-left" v-if="activeName.includes('水箱')"> |
|
<div class="control-top"> |
|
<water-tank :waterLevel="item.waterLevel"></water-tank> |
|
<div class="monitor-words"> |
|
<div class="words-li"> |
|
<div class="ash">补水阀启停:</div> |
|
<div class="white"> |
|
<el-switch |
|
style="display: block" |
|
v-model="item.switchStatus" |
|
active-color="#13ce66" |
|
active-text="开启" |
|
inactive-text="停止" |
|
@change="handleSwitch(item)" |
|
> |
|
</el-switch> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
<div class="control-bottom"> |
|
<div class="words-li words-li5"> |
|
<div class="ash">实际液位:</div> |
|
<div class="white">{{ item.waterLevel }} %</div> |
|
</div> |
|
<div class="words-li words-li5"> |
|
<div class="ash ash2">设置液位:</div> |
|
<el-input |
|
size="mini" |
|
v-model="item.waterLevelSet" |
|
placeholder="请输入" |
|
@keyup.enter.native=" |
|
handleEnter( |
|
item, |
|
item.waterLevelSet, |
|
item.waterLevelSetId, |
|
'液位设置', |
|
'%' |
|
) |
|
" |
|
@input="handleWaterInput(item)" |
|
></el-input> |
|
<div class="white">%</div> |
|
</div> |
|
<div class="words-li words-li6"> |
|
<div class="ash">液位设定延时时间:</div> |
|
<el-input |
|
size="mini" |
|
v-model="item.delayTimeSet" |
|
placeholder="请输入" |
|
@keyup.enter.native=" |
|
handleEnter( |
|
item, |
|
item.delayTimeSet, |
|
item.delayTimeSetId, |
|
'液位设定延时时间', |
|
'min' |
|
) |
|
" |
|
@input="handleWaterInput(item)" |
|
></el-input> |
|
<div class="white">min</div> |
|
</div> |
|
<div class="words-li words-li2"> |
|
<div class="ash ash2">液位误差值:</div> |
|
<el-input |
|
size="mini" |
|
v-model="item.diffValueSet" |
|
placeholder="请输入" |
|
@keyup.enter.native=" |
|
handleEnter( |
|
item, |
|
item.diffValueSet, |
|
item.diffValueSetId, |
|
'液位误差值', |
|
'%' |
|
) |
|
" |
|
@input="handleWaterInput(item)" |
|
></el-input> |
|
<div class="white">%</div> |
|
</div> |
|
<div class="words-li words-li2"> |
|
<div class="ash">时间:</div> |
|
<div class="white">{{ item.curTime }}</div> |
|
</div> |
|
</div> |
|
</div> |
|
<!-- 高区、中厨、中区、裙楼 --> |
|
<div |
|
class="monitor-flex-left" |
|
v-if=" |
|
activeName === '裙楼' || |
|
activeName === '中厨' || |
|
activeName === '高区' || |
|
activeName === '中区' |
|
" |
|
> |
|
<div class="control-top"> |
|
<img |
|
class="monitor-img2" |
|
src="../../../assets/images/startpum.png" |
|
/> |
|
<div class="monitor-words"> |
|
<div class="words-li"> |
|
<div class="ash" style="letter-spacing: 8px">一键启动:</div> |
|
<div class="white"> |
|
<el-switch |
|
style="display: block" |
|
v-model="item.openSwitch" |
|
active-color="#13ce66" |
|
active-text="开启" |
|
inactive-text="停止" |
|
@change="handleAllStart(item)" |
|
> |
|
</el-switch> |
|
</div> |
|
</div> |
|
<!-- <div class="words-li"> |
|
<div class="ash">停止:</div> |
|
<div class="white"> |
|
<el-switch |
|
style="display: block" |
|
v-model="item.closeSwitch" |
|
active-color="#13ce66" |
|
active-text="" |
|
inactive-text="" |
|
@change="handleAllEnd(item)" |
|
> |
|
</el-switch> |
|
</div> |
|
</div> --> |
|
</div> |
|
</div> |
|
<div class="control-bottom"> |
|
<div class="words-li words-li3"> |
|
<div class="ash">供水温度:</div> |
|
<div class="white">{{ item.temp }}℃</div> |
|
</div> |
|
<div class="words-li words-li4"> |
|
<div class="ash">供水温度设定:</div> |
|
<el-input |
|
v-model="item.tempSet" |
|
size="mini" |
|
@keyup.enter.native=" |
|
handleEnter( |
|
item, |
|
item.tempSet, |
|
item.tempSetId, |
|
'供水温度设定', |
|
'℃' |
|
) |
|
" |
|
@input="handleInput(item)" |
|
@blur="handleBlur()" |
|
></el-input> |
|
<div class="white">℃</div> |
|
</div> |
|
<div class="words-li words-li3"> |
|
<div class="ash">供水压力</div> |
|
<div class="white">{{ item.pressure }}bar</div> |
|
</div> |
|
<div class="words-li words-li4"> |
|
<div class="ash">温度偏差值:</div> |
|
<el-input |
|
v-model="item.diffValueSet" |
|
@keyup.enter.native=" |
|
handleEnter( |
|
item, |
|
item.diffValueSet, |
|
item.diffValueSetId, |
|
'温度偏差值', |
|
'℃' |
|
) |
|
" |
|
@input="handleInput(item)" |
|
@blur="handleBlur()" |
|
size="mini" |
|
></el-input> |
|
<div class="white">℃</div> |
|
</div> |
|
<div class="words-li words-li3"> |
|
<div class="ash">故障信息:</div> |
|
<el-tag |
|
size="mini" |
|
v-if="item.alarmStatus === '无故障'" |
|
type="success" |
|
>{{ item.alarmStatus }}</el-tag |
|
> |
|
<el-tag size="mini" v-else type="danger">{{ |
|
item.alarmStatus |
|
}}</el-tag> |
|
</div> |
|
<!-- <div class="words-li words-li4"> |
|
<div class="ash">补水延时时间设定:</div> |
|
<el-input |
|
v-model="item.delayTimeSet" |
|
@keyup.enter.native=" |
|
handleEnter( |
|
item, |
|
item.delayTimeSet, |
|
item.delayTimeSetId, |
|
'补水延时时间设定', |
|
'S' |
|
) |
|
" |
|
@input="handleInput(item)" |
|
@blur="handleBlur()" |
|
size="mini" |
|
></el-input> |
|
<div class="white">S</div> |
|
</div> --> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</template> |
|
|
|
<script> |
|
import { spaceTree } from "@/api/region"; |
|
import { waterOperateList, operationConrol } from "@/api/hotWater/waterControl"; |
|
import waterTank from "../../components/waterTank.vue"; |
|
export default { |
|
name: "WaterControl", |
|
components: { waterTank }, |
|
data() { |
|
return { |
|
loading: false, |
|
treeData: [], |
|
defaultProps: { |
|
children: "children", |
|
label: "label", |
|
}, |
|
tabsList: [], |
|
expandedKeys: [], |
|
hotPumpOptions: [ |
|
{ |
|
label: "关机", |
|
value: 0, |
|
}, |
|
{ |
|
label: "制冷", |
|
value: 2, |
|
}, |
|
{ |
|
label: "制热", |
|
value: 3, |
|
}, |
|
{ |
|
label: "热水", |
|
value: 4, |
|
}, |
|
], |
|
currentId: "", //当前选中高亮的id |
|
currentName: "", //当前选中的名称 |
|
currentLevel: "", //当前节点的层级 |
|
|
|
activeName: "", //默认选中 |
|
tabsList: [], //tab列表 |
|
devicesList: [], //设备列表 |
|
isInitialPage: true, //记录是否初始页面 |
|
isNodeClicked: false, //记录是否点击了tree |
|
}; |
|
}, |
|
mounted() { |
|
this.getSysBuild(); |
|
}, |
|
methods: { |
|
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 开始计数),这里假设指定为第 4 级 |
|
const targetLevel = 4; |
|
// 从 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, 2); |
|
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.getWaterList(); |
|
} |
|
}); |
|
} |
|
}); |
|
}, |
|
// 递归函数,用于去除指定层级往后的 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 === 4) { |
|
// 4级菜单时的图标 |
|
if (node.expanded) { |
|
return "el-icon-document-opened"; // 三级菜单展开时的图标类名 |
|
} |
|
return "el-icon-document"; // 三级菜单收缩时的图标类名 |
|
} |
|
if (node.expanded) { |
|
return "el-icon-folder-opened"; // 非三级菜单展开时的图标类名 |
|
} |
|
return "el-icon-folder-add"; // 非三级菜单收缩时的图标类名 |
|
}, |
|
handleNodeExpand(node) { |
|
// 节点展开时触发 |
|
}, |
|
handleNodeCollapse(node) { |
|
// 节点收缩时触发 |
|
}, |
|
// 点击当前节点,保存节点内容 |
|
handleNodeClick(node, data) { |
|
console.log("点击的当前节点", node, data); |
|
this.isNodeClicked = true; // 设置标志位为 true,表示节点被点击 |
|
if (data.level !== 4) { |
|
console.log("不是第4层000"); |
|
// 设置当前选中的节点,默认高亮 |
|
this.$refs.tree.setCurrentKey(this.currentId); |
|
console.log("当前选中节点ID", this.currentId); |
|
console.log("当前选中节点层级", this.currentLevel); |
|
console.log("当前选中节点名称", this.currentName); |
|
} else { |
|
console.log("第4层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.getWaterList(); |
|
} |
|
}, |
|
handleClick(tab, event) { |
|
this.isNodeClicked = false; // 表示切换tab但并未点击tree |
|
console.log(tab, event); |
|
console.log("activeName", this.activeName); |
|
// 根据 tab 的 name 从 tabsList 中找到对应的 item,处理得到devicesList |
|
const currentItem = this.tabsList.find((item) => item.name === tab.name); |
|
console.log("currentItem--=----", currentItem); |
|
if (currentItem.children.length > 0) { |
|
this.devicesList = []; |
|
currentItem.children.forEach((item) => { |
|
if (item.name) { |
|
// 在每次迭代时创建一个新的 deviceItem 对象 |
|
let deviceItem = { |
|
...item, |
|
waterLevel: Number(item.waterLevel), |
|
runningStatus: Number(item.runningStatus) == 0 ? "停止" : "运行", //运行状态 |
|
hotPumpStatus: item.switchStatus, //热泵开关状态 |
|
switchStatus: Number(item.switchStatus) == 0 ? false : true, //启停控制 |
|
alarmStatus: Number(item.alarmStatus) == 0 ? "无故障" : "故障", //故障状态 |
|
handAutomaticSwitch: |
|
Number(item.handAutomaticSwitch) == 1 ? false : true, //手自动状态 |
|
openSwitch: Number(item.openSwitch) == 0 ? false : true, //一键启动 |
|
closeSwitch: Number(item.closeSwitch) == 0 ? false : true, //一键停止 |
|
}; |
|
// 将处理后的对象添加到 devicesList 中 |
|
this.devicesList.push(deviceItem); |
|
} |
|
}); |
|
console.log("当前楼层water列表", this.devicesList); |
|
} |
|
}, |
|
// 失去焦点 |
|
handleBlur() {}, |
|
// 获取热水设备列表 |
|
getWaterList() { |
|
return new Promise((resolve, reject) => { |
|
let data = { |
|
systemType: "1", |
|
floorId: this.currentId, |
|
}; |
|
waterOperateList(data) |
|
.then((res) => { |
|
if (res.code == 200 && res.rows.length > 0) { |
|
console.log("页面请求数据了~~~~~~~~~~~", res.rows); |
|
this.tabsList = res.rows; |
|
// 初始页面的时候默认选择第一个tabs,否则不设置 |
|
if (this.isInitialPage) { |
|
this.activeName = res.rows[0].name; |
|
this.isInitialPage = false; |
|
console.log("初始页面默认tabs", this.activeName); |
|
} else { |
|
console.log("非初始页面默认tabs", this.activeName); |
|
// 判断是勾选了tree还是tabs控制更新, |
|
if (this.isNodeClicked) { |
|
// tree |
|
this.activeName = res.rows[0].name; |
|
console.log("非初始页面默认tabs-点击tree", this.activeName); |
|
} else { |
|
this.activeName = this.activeName; |
|
console.log("非初始页面默认tabs-tabs中更新", this.activeName); |
|
} |
|
} |
|
// 根据 tab 的 name 从 tabsList 中找到对应的 item,处理得到devicesList |
|
const currentItem = this.tabsList.find( |
|
(item) => item.name === this.activeName |
|
); |
|
console.log("currentItem--=----", currentItem); |
|
if (currentItem.children.length > 0) { |
|
this.devicesList = []; |
|
currentItem.children.forEach((item) => { |
|
if (item.name) { |
|
// 在每次迭代时创建一个新的 deviceItem 对象 |
|
let deviceItem = { |
|
...item, |
|
waterLevel: Number(item.waterLevel), |
|
runningStatus: |
|
Number(item.runningStatus) == 0 ? "运行" : "停止", //运行状态 |
|
hotPumpStatus: item.switchStatus, //热泵开关状态 |
|
switchStatus: |
|
Number(item.switchStatus) == 0 ? false : true, //启停控制 |
|
alarmStatus: |
|
Number(item.alarmStatus) == 0 ? "无故障" : "故障", //故障状态 |
|
handAutomaticSwitch: |
|
Number(item.handAutomaticSwitch) == 0 ? false : true, //手自动状态 |
|
openSwitch: Number(item.openSwitch) == 0 ? false : true, //一键启动 |
|
closeSwitch: Number(item.closeSwitch) == 0 ? false : true, //一键停止 |
|
}; |
|
// 将处理后的对象添加到 devicesList 中 |
|
this.devicesList.push(deviceItem); |
|
} |
|
}); |
|
console.log("当前楼层water列表", this.devicesList); |
|
} |
|
} else { |
|
this.tabsList = []; |
|
this.devicesList = []; |
|
this.activeName = ""; |
|
} |
|
// 成功时解析 Promise |
|
resolve(res); |
|
}) |
|
.catch((error) => { |
|
// 失败时拒绝 Promise |
|
reject(error); |
|
}); |
|
}); |
|
}, |
|
// 一键启动 |
|
handleAllStart(item) { |
|
this.$confirm( |
|
`确定要 ${item.openSwitch ? "一键开启" : "关闭一键开启"} ${ |
|
item.name |
|
}的设备吗?`, |
|
"提示", |
|
{ |
|
confirmButtonText: "确定", |
|
cancelButtonText: "取消", |
|
type: "warning", |
|
} |
|
) |
|
.then(() => { |
|
console.log("请求后台", item.openSwitch); |
|
let param = null; |
|
if (item.openSwitch) { |
|
param = 1; |
|
} else { |
|
param = 0; |
|
} |
|
this.hadleOperationConrol(item.openSwitchId, param); |
|
}) |
|
.catch(() => { |
|
// 用户取消操作,恢复开关状态 |
|
item.openSwitch = !item.openSwitch; |
|
}); |
|
}, |
|
// 一键停止 |
|
handleAllEnd(item) { |
|
this.$confirm( |
|
`确定要 ${item.closeSwitch ? "一键停止" : "关闭一键停止"} ${ |
|
item.name |
|
}的设备吗?`, |
|
"提示", |
|
{ |
|
confirmButtonText: "确定", |
|
cancelButtonText: "取消", |
|
type: "warning", |
|
} |
|
) |
|
.then(() => { |
|
console.log("请求后台", item.closeSwitch); |
|
let param = null; |
|
if (item.closeSwitch) { |
|
param = 1; |
|
} else { |
|
param = 0; |
|
} |
|
this.hadleOperationConrol(item.closeSwitchId, param); |
|
}) |
|
.catch(() => { |
|
// 用户取消操作,恢复开关状态 |
|
item.closeSwitch = !item.closeSwitch; |
|
}); |
|
}, |
|
// input设置 |
|
handleEnter(item, value, id, set, unit) { |
|
this.$confirm( |
|
`确定要修改"${item.name}"的${set}为:${value} ${unit}吗?`, |
|
"提示", |
|
{ |
|
confirmButtonText: "确定", |
|
cancelButtonText: "取消", |
|
type: "warning", |
|
} |
|
) |
|
.then(() => { |
|
this.hadleOperationConrol(id, value); |
|
}) |
|
.catch(() => {}); |
|
}, |
|
// 设置热泵开关状态 |
|
handleHotPump(item) { |
|
// 记录原始状态 |
|
const originalStatus = item.hotPumpStatus; |
|
// 根据 value 值获取对应的 label |
|
let statusLabel = ""; |
|
switch (item.hotPumpStatus) { |
|
case 0: |
|
statusLabel = "关机"; |
|
break; |
|
case 2: |
|
statusLabel = "制冷"; |
|
break; |
|
case 3: |
|
statusLabel = "制热"; |
|
break; |
|
case 4: |
|
statusLabel = "热水"; |
|
break; |
|
} |
|
this.$confirm( |
|
`确定要切换设备"${item.name}"的状态为:${statusLabel} 吗?"`, |
|
"提示", |
|
{ |
|
confirmButtonText: "确定", |
|
cancelButtonText: "取消", |
|
type: "warning", |
|
} |
|
) |
|
.then(() => { |
|
this.hadleOperationConrol(item.switchStatusId, item.hotPumpStatus); |
|
}) |
|
.catch(() => { |
|
// 用户取消操作,恢复状态 |
|
item.hotPumpStatus = originalStatus; |
|
}); |
|
}, |
|
// 设置供水泵手自动状态 |
|
handAutomatic(item) { |
|
this.$confirm( |
|
`确定要切换设备"${item.name}"的状态为:${ |
|
item.handAutomaticSwitch ? "手动" : "自动 吗?" |
|
}`, |
|
"提示", |
|
{ |
|
confirmButtonText: "确定", |
|
cancelButtonText: "取消", |
|
type: "warning", |
|
} |
|
) |
|
.then(() => { |
|
// 这里调用请求函数,示例中只是简单打印信息 |
|
console.log("请求后台", item.handAutomaticSwitch); |
|
let param = null; |
|
if (item.handAutomaticSwitch) { |
|
param = 0; |
|
} else { |
|
param = 1; |
|
} |
|
this.hadleOperationConrol(item.handAutomaticSwitchId, param); |
|
}) |
|
.catch(() => { |
|
// 用户取消操作,恢复开关状态 |
|
item.handAutomaticSwitch = !item.handAutomaticSwitch; |
|
}); |
|
}, |
|
// 设置启停控制 |
|
handleSwitch(item) { |
|
this.$confirm( |
|
`确定要切换设备"${item.name}"的状态为:${ |
|
item.switchStatus ? "开启" : "停止 吗?" |
|
}`, |
|
"提示", |
|
{ |
|
confirmButtonText: "确定", |
|
cancelButtonText: "取消", |
|
type: "warning", |
|
} |
|
) |
|
.then(() => { |
|
// 这里调用请求函数,示例中只是简单打印信息 |
|
console.log("请求后台", item.switchStatus); |
|
let param = null; |
|
if (item.switchStatus) { |
|
param = 1; |
|
} else { |
|
param = 0; |
|
} |
|
this.hadleOperationConrol(item.switchStatusId, param); |
|
}) |
|
.catch(() => { |
|
// 用户取消操作,恢复开关状态 |
|
item.switchStatus = !item.switchStatus; |
|
}); |
|
}, |
|
// 处理输入事件,过滤非数字字符 |
|
handleInput(item) { |
|
console.log("校验"); |
|
// 实时校验并过滤非数字和非小数点字符 |
|
item.tempSet = String(item.tempSet).replace(/[^\d.]/g, ""); |
|
// 确保只有一个小数点 |
|
const parts = item.tempSet.split("."); |
|
if (parts.length > 2) { |
|
// 如果有多个小数点,只保留第一个小数点及之前的部分和第一个小数点之后的部分 |
|
item.tempSet = parts[0] + "." + parts[1]; |
|
} |
|
// 确保小数点后最多两位 |
|
if (parts.length === 2) { |
|
item.tempSet = parts[0] + "." + parts[1].slice(0, 2); |
|
} |
|
}, |
|
handleWaterInput(item) { |
|
item.waterLevelSet = String(item.waterLevelSet).replace(/[^\d.]/g, ""); |
|
// 确保只有一个小数点 |
|
const parts = item.waterLevelSet.split("."); |
|
if (parts.length > 2) { |
|
// 如果有多个小数点,只保留第一个小数点及之前的部分和第一个小数点之后的部分 |
|
item.waterLevelSet = parts[0] + "." + parts[1]; |
|
} |
|
// 确保小数点后最多两位 |
|
if (parts.length === 2) { |
|
item.waterLevelSet = parts[0] + "." + parts[1].slice(0, 2); |
|
} |
|
}, |
|
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.getWaterList().finally(() => { |
|
// 关闭 loading 效果 |
|
this.loading = false; |
|
}); |
|
}, 5000); |
|
} else { |
|
// this.$modal.msgError("操作失败"); |
|
console.log("应该更新状态的"); |
|
// 更新所有设备状态; |
|
this.getWaterList(); |
|
} |
|
}) |
|
.catch((error) => { |
|
console.log("请求发生错误,更新设备状态", error); |
|
// 更新所有设备状态; |
|
this.getWaterList(); |
|
}); |
|
}, |
|
}, |
|
}; |
|
</script> |
|
|
|
<style lang="scss" scoped> |
|
.app-container { |
|
display: flex; |
|
flex-direction: row; |
|
justify-content: space-between; |
|
align-items: stretch; |
|
height: 100%; |
|
.left-tree { |
|
width: 256px; |
|
padding: 15px 10px; |
|
border: 1px solid #004b8c; |
|
min-height: 800px; |
|
.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; |
|
.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; |
|
} |
|
} |
|
.monitor-context { |
|
height: 640px; |
|
width: 100%; |
|
overflow-y: auto; |
|
display: flex; |
|
flex-direction: row; |
|
align-items: flex-start; |
|
justify-content: flex-start; |
|
flex-wrap: wrap; |
|
align-content: flex-start; |
|
} |
|
} |
|
.monitor-context { |
|
height: 650px; |
|
width: 100%; |
|
overflow-y: auto; |
|
display: flex; |
|
flex-direction: row; |
|
align-items: flex-start; |
|
justify-content: flex-start; |
|
flex-wrap: wrap; |
|
align-content: flex-start; |
|
.monitor-li { |
|
display: flex; |
|
flex-direction: column; |
|
align-items: center; |
|
min-height: 160px; |
|
width: calc(33.33% - 20px); |
|
margin: 0 10px; |
|
padding-bottom: 25px; |
|
margin-bottom: 16px !important; |
|
background: linear-gradient( |
|
to top, |
|
rgba(0, 94, 173, 0.6) 0%, |
|
rgba(0, 94, 173, 0.1) 100% |
|
); |
|
overflow: hidden; |
|
position: relative; |
|
border-radius: 10px; |
|
.monitor-title { |
|
width: 100%; |
|
height: 50px; |
|
background-image: url(../../../assets/images/gate-title.png); |
|
background-size: 100% 100%; |
|
background-repeat: no-repeat; |
|
font-family: SourceHanSansCN-Bold; |
|
font-size: 18px; |
|
line-height: 40px; |
|
letter-spacing: 0px; |
|
color: #ffffff; |
|
text-align: center; |
|
} |
|
.monitor-flex { |
|
width: 100%; |
|
display: flex; |
|
flex: 1; |
|
flex-direction: row; |
|
align-items: center; |
|
justify-content: space-between; |
|
margin-top: 20px; |
|
.monitor-flex-left { |
|
padding: 0 0.2rem; |
|
display: flex; |
|
flex-direction: column; |
|
width: 100%; |
|
.control-top { |
|
display: flex; |
|
flex-direction: row; |
|
align-items: center; |
|
justify-content: space-between; |
|
width: 100%; |
|
.monitor-img1 { |
|
width: 1.2rem; |
|
height: 1.2rem; |
|
} |
|
.monitor-img2 { |
|
width: 1.2rem; |
|
height: 0.8rem; |
|
} |
|
.monitor-img3 { |
|
width: 1.2rem; |
|
height: 0.8rem; |
|
} |
|
} |
|
.control-bottom { |
|
width: 100%; |
|
display: flex; |
|
flex-direction: row; |
|
align-items: center; |
|
justify-content: space-between; |
|
margin-top: 20px; |
|
} |
|
.ash { |
|
color: #b8bfcb; |
|
white-space: nowrap; |
|
margin-right: 8px; |
|
} |
|
.white { |
|
color: #ffffff; |
|
} |
|
.words-li { |
|
display: flex; |
|
flex-direction: row; |
|
align-items: center; |
|
font-family: SourceHanSansCN-Regular; |
|
font-size: 16px; |
|
line-height: 28px; |
|
margin-bottom: 10px; |
|
} |
|
.monitor-words { |
|
flex-wrap: wrap; |
|
.words-li { |
|
width: 100%; |
|
} |
|
} |
|
.control-bottom { |
|
flex-wrap: wrap; |
|
.words-li { |
|
width: 45%; |
|
flex-wrap: nowrap; |
|
} |
|
.words-li2 { |
|
width: 100%; |
|
display: flex; |
|
flex-direction: row; |
|
align-items: center; |
|
} |
|
.words-li3 { |
|
width: 36%; |
|
} |
|
.words-li4 { |
|
width: 60%; |
|
.ash { |
|
width: 130px; |
|
} |
|
} |
|
.words-li5 { |
|
width: 45%; |
|
.ash2 { |
|
width: 100px; |
|
} |
|
} |
|
.words-li6 { |
|
width: 70%; |
|
.ash2 { |
|
width: 100px; |
|
} |
|
} |
|
} |
|
.sigClass { |
|
width: 40%; |
|
flex-wrap: wrap; |
|
.words-li { |
|
width: 100%; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
.monitor-li::before { |
|
content: ""; |
|
position: absolute; |
|
top: 0; |
|
left: 0; |
|
right: 0; |
|
bottom: 0; |
|
border-radius: 10px; |
|
border: 1px solid transparent; |
|
background: linear-gradient( |
|
0deg, |
|
#0088f0 0%, |
|
rgba(19, 213, 255, 0.2) 100% |
|
) |
|
border-box; |
|
mask: linear-gradient(#fff 0 0) padding-box, |
|
/* 内部透明 */ linear-gradient(#fff 0 0); /* 填充整个区域 */ |
|
mask-composite: exclude; /* 关键属性 */ |
|
pointer-events: none; /* 防止遮挡点击事件 */ |
|
} |
|
} |
|
} |
|
.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; |
|
} |
|
} |
|
} |
|
@media (min-width: 1350px) and (max-width: 1460px) { |
|
.monitor-img3 { |
|
} |
|
} |
|
@media (min-width: 1350px) and (max-width: 1850px) { |
|
.monitor-li { |
|
width: calc(49% - 10px) !important; |
|
margin: 0 5px !important; |
|
} |
|
.monitor-img1 { |
|
width: 100px !important; |
|
height: 100px !important; |
|
} |
|
.monitor-img2 { |
|
width: 100px !important; |
|
height: 60px !important; |
|
} |
|
.monitor-img3 { |
|
width: 1.2rem !important; |
|
height: 0.9rem !important; |
|
} |
|
} |
|
@media (max-width: 1350px) { |
|
.monitor-li { |
|
width: 100% !important; |
|
margin: 0 !important; |
|
margin-right: 10px !important; |
|
.monitor-img1 { |
|
width: 100px !important; |
|
height: 100px !important; |
|
} |
|
.monitor-img2 { |
|
width: 100px !important; |
|
height: 80px !important; |
|
} |
|
.monitor-img3 { |
|
width: 100px !important; |
|
height: 80px !important; |
|
} |
|
.monitor-flex-left { |
|
padding: 0 30px !important; |
|
} |
|
} |
|
} |
|
</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; |
|
} |
|
.monitor-flex-left >>> .el-input { |
|
width: 80px !important; |
|
margin: 0 5px; |
|
} |
|
.monitor-flex-left >>> .el-input__inner { |
|
background-color: #04193a; |
|
border: 1px solid #1262db; |
|
color: #3ef0fd; |
|
font-weight: 700; |
|
text-align: center; |
|
padding: 0 0.1rem !important; |
|
} |
|
/* // 媒体查询,适配大于2000px分辨率的大屏样式 */ |
|
@media (min-width: 2000px) { |
|
.monitor-flex-left >>> .el-input { |
|
width: 0.8rem !important; |
|
margin: 0 0.15rem 0 0.05rem !important; |
|
} |
|
} |
|
</style>
|
|
|