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.
779 lines
22 KiB
779 lines
22 KiB
<template> |
|
<div class="app-container" v-loading="loading"> |
|
<!-- <img |
|
class="right-line" |
|
src="../../../assets/images/right_line.png" |
|
alt="" |
|
/> --> |
|
<!-- <div class="delay-title">自动开关机时间设置</div> --> |
|
<div class="delaySwitch"> |
|
<div class="delay-li" v-for="(item, index) in delayList" :key="index"> |
|
<div class="buildingDiv"> |
|
<img |
|
class="title-bg" |
|
src="../../../assets/images/title-bg.png" |
|
alt="" |
|
/> |
|
<div class="title-word">{{ item.name }}:</div> |
|
</div> |
|
<div class="delay-bottom"> |
|
<div class="start"> |
|
<div>初始化</div> |
|
<img |
|
class="start-img" |
|
src="../../../assets/images/start.png" |
|
alt="" |
|
/> |
|
</div> |
|
<div class="delay-right"> |
|
<div |
|
class="delay-context" |
|
v-for="(children, subIndex) in item.values" |
|
:key="subIndex + 1" |
|
> |
|
<div class="device-arrow"> |
|
<div class="delay-input"> |
|
<el-input |
|
size="mini" |
|
v-model="children.curValue" |
|
@keyup.enter.native="handleEnter(children, $event)" |
|
@input="handleInput(children)" |
|
@focus="handleFocus(index, subIndex)" |
|
@blur="handleBlur()" |
|
></el-input |
|
>S |
|
</div> |
|
<!-- 将 isHovered 状态传递给 dynamic-arrow 组件 --> |
|
<dynamic-arrow |
|
:is-hovered="currentFocusIndex === `${index}-${subIndex}`" |
|
></dynamic-arrow> |
|
</div> |
|
<div class="device-body"> |
|
<div>{{ children.pointName }}</div> |
|
<img |
|
v-if="children.pointName === '冷却泵'" |
|
src="../../../assets/images/coolingPump.png" |
|
class="butterflyValve" |
|
alt="" |
|
/> |
|
<img |
|
v-if="children.pointName === '冷冻泵'" |
|
src="../../../assets/images/freezingPump.png" |
|
class="butterflyValve" |
|
alt="" |
|
/> |
|
<img |
|
v-if="children.pointName.includes('主机')" |
|
src="../../../assets/images/host.png" |
|
class="hostImg" |
|
alt="" |
|
/> |
|
<img |
|
v-if="children.pointName.includes('塔')" |
|
src="../../../assets/images/coolingTower.png" |
|
class="butterflyValve" |
|
alt="" |
|
/> |
|
<img |
|
v-if="children.pointName.includes('阀')" |
|
src="../../../assets/images/butterflyValve.png" |
|
class="valveImg" |
|
alt="" |
|
/> |
|
<img |
|
v-if="children.pointName.includes('泵')" |
|
src="../../../assets/images/valve.png" |
|
class="pumpImg" |
|
alt="" |
|
/> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
<!-- 第一组冷却塔放在冷却泵连接处 --> |
|
<div class="last closeLast" v-if="item.name === '自动关机'"> |
|
<div class="reverse-img"> |
|
<img src="../../../assets/images/yuan.png" class="yuan" alt="" /> |
|
<img src="../../../assets/images/yuan.png" class="yuan" alt="" /> |
|
<img src="../../../assets/images/yuan.png" class="yuan" alt="" /> |
|
<img src="../../../assets/images/yuan.png" class="yuan" alt="" /> |
|
<img src="../../../assets/images/yuan.png" class="yuan" alt="" /> |
|
<img src="../../../assets/images/yuan.png" class="yuan" alt="" /> |
|
<img src="../../../assets/images/yuan.png" class="yuan" alt="" /> |
|
</div> |
|
<div class="lastTower"> |
|
<div class="device-arrow"> |
|
<div class="delay-input"> |
|
<el-input |
|
size="mini" |
|
v-model="closeTower.curValue" |
|
@keyup.enter.native="handleEnter(closeTower, $event)" |
|
@input="handleInput(closeTower)" |
|
@focus="handleFocus('closeTower')" |
|
@blur="handleBlur()" |
|
></el-input |
|
>S |
|
</div> |
|
<!-- 将 isHovered 状态传递给 dynamic-arrow 组件 --> |
|
<dynamic-arrow :is-hovered="isOpenTowerHover"></dynamic-arrow> |
|
</div> |
|
<div class="device-body"> |
|
<img |
|
src="../../../assets/images/coolingTower.png" |
|
class="butterflyValve" |
|
alt="" |
|
/> |
|
<div>{{ closeTower.pointName }}</div> |
|
</div> |
|
</div> |
|
</div> |
|
<!-- 第二组冷却塔放在主机连接处 --> |
|
<div class="last openLast" v-if="item.name === '自动开机'"> |
|
<div class="reverse-img"> |
|
<img src="../../../assets/images/yuan.png" class="yuan" alt="" /> |
|
<img src="../../../assets/images/yuan.png" class="yuan" alt="" /> |
|
<img src="../../../assets/images/yuan.png" class="yuan" alt="" /> |
|
<img src="../../../assets/images/yuan.png" class="yuan" alt="" /> |
|
<img src="../../../assets/images/yuan.png" class="yuan" alt="" /> |
|
<img src="../../../assets/images/yuan.png" class="yuan" alt="" /> |
|
<img src="../../../assets/images/yuan.png" class="yuan" alt="" /> |
|
</div> |
|
<div class="lastTower"> |
|
<div class="device-arrow"> |
|
<div class="delay-input"> |
|
<el-input |
|
size="mini" |
|
v-model="openTower.curValue" |
|
@keyup.enter.native="handleEnter(openTower, $event)" |
|
@input="handleInput(openTower)" |
|
@focus="handleFocus('openTower')" |
|
@blur="handleBlur()" |
|
></el-input |
|
>S |
|
</div> |
|
<!-- 将 isHovered 状态传递给 dynamic-arrow 组件 --> |
|
<dynamic-arrow :is-hovered="isCloseTowerHover"></dynamic-arrow> |
|
</div> |
|
<div class="device-body"> |
|
<img |
|
src="../../../assets/images/coolingTower.png" |
|
class="butterflyValve" |
|
alt="" |
|
/> |
|
<div>{{ openTower.pointName }}</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
<!-- <img class="left-line" src="../../../assets/images/left_line.png" alt="" /> --> |
|
</div> |
|
</template> |
|
|
|
<script> |
|
import { policyListData } from "@/api/centerairC/strategy"; |
|
import dynamicArrow from "../../components/dynamicArrow.vue"; |
|
import { operationConrol } from "@/api/hotWater/waterControl"; |
|
export default { |
|
components: { dynamicArrow }, |
|
data() { |
|
return { |
|
loading: false, |
|
delayList: [], |
|
openTower: {}, |
|
closeTower: {}, |
|
isOpenTowerHover: false, |
|
isCloseTowerHover: false, |
|
currentFocusIndex: -1, // 用于记录当前鼠标悬停的索引 |
|
}; |
|
}, |
|
mounted() { |
|
this.getPolicyList(); |
|
}, |
|
methods: { |
|
// 请求列表 |
|
getPolicyList() { |
|
return new Promise((resolve, reject) => { |
|
let data = { |
|
systemType: "0", |
|
funPolicyType: "2", |
|
}; |
|
policyListData(data) |
|
.then((res) => { |
|
console.log("设备延时开关返回res", res); |
|
if (res.code == 200) { |
|
// 深拷贝 res.rows 到 delayList |
|
this.delayList = JSON.parse(JSON.stringify(res.rows)); |
|
// 处理 closeTower |
|
if (this.delayList[0] && this.delayList[0].values.length > 0) { |
|
// 这里pop已影响到原数组,不用额外处理去掉 delayList 里每个对象 values 数组的最后一个对象 |
|
this.closeTower = { ...this.delayList[0].values.pop() }; |
|
} |
|
// 处理 openTower |
|
if (this.delayList[1] && this.delayList[1].values.length > 0) { |
|
this.openTower = { ...this.delayList[1].values.pop() }; |
|
} |
|
} else { |
|
this.delayList = []; |
|
this.openTower = {}; |
|
this.closeTower = {}; |
|
} |
|
// 成功时解析 Promise |
|
resolve(res); |
|
}) |
|
.catch((error) => { |
|
// 失败时拒绝 Promise |
|
reject(error); |
|
}); |
|
}); |
|
}, |
|
handleFocus(index, subIndex) { |
|
console.log("index", index); |
|
// 当 el-input 获得焦点时,更新 focusedIndex |
|
this.currentFocusIndex = `${index}-${subIndex}`; |
|
if (index === "openTower") { |
|
this.isOpenTowerHover = true; |
|
} |
|
if (index === "closeTower") { |
|
this.isCloseTowerHover = true; |
|
} |
|
}, |
|
// 失去焦点 |
|
handleBlur() { |
|
this.currentFocusIndex = ""; |
|
this.isOpenTowerHover = false; |
|
this.isCloseTowerHover = false; |
|
}, |
|
// 处理输入事件,过滤非数字字符 |
|
handleInput(item) { |
|
console.log("校验"); |
|
// 实时校验并过滤非数字和非小数点字符 |
|
item.curValue = String(item.curValue).replace(/[^\d.]/g, ""); |
|
// 确保只有一个小数点 |
|
const parts = item.curValue.split("."); |
|
if (parts.length > 2) { |
|
// 如果有多个小数点,只保留第一个小数点及之前的部分和第一个小数点之后的部分 |
|
item.curValue = parts[0] + "." + parts[1]; |
|
} |
|
// 确保小数点后最多两位 |
|
if (parts.length === 2) { |
|
item.curValue = parts[0] + "." + parts[1].slice(0, 2); |
|
} |
|
}, |
|
// 设置延时时间 |
|
handleEnter(item, event) { |
|
// 失去焦点 |
|
event.target.blur(); |
|
console.log("item", item); |
|
console.log("event", event); |
|
this.$confirm( |
|
`确定要修改"${item.pointName}"的延迟时间为:${item.curValue} S吗?`, |
|
"提示", |
|
{ |
|
confirmButtonText: "确定", |
|
cancelButtonText: "取消", |
|
type: "warning", |
|
} |
|
) |
|
.then(() => { |
|
this.hadleOperationConrol(item.cpmId, item.curValue); |
|
this.currentFocusIndex = ""; |
|
}) |
|
.catch(() => { |
|
// // 失去焦点 |
|
// event.target.blur(); |
|
// this.currentFocusIndex = ""; |
|
}); |
|
}, |
|
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.getPolicyList().finally(() => { |
|
// 关闭 loading 效果 |
|
this.loading = false; |
|
}); |
|
}, 4000); |
|
} else { |
|
// this.$modal.msgError("操作失败"); |
|
console.log("应该更新状态的"); |
|
// 更新所有设备状态; |
|
this.getPolicyList(); |
|
} |
|
}) |
|
.catch((error) => { |
|
console.log("请求发生错误,更新设备状态", error); |
|
// 更新所有设备状态; |
|
this.getPolicyList(); |
|
}); |
|
}, |
|
}, |
|
}; |
|
</script> |
|
|
|
<style lang="scss" scoped> |
|
.app-container { |
|
position: relative; |
|
padding: 0px; |
|
.delay-title { |
|
/* 基础样式 */ |
|
display: inline-block; |
|
padding: 10px; |
|
font-family: "Arial Rounded MT Bold", sans-serif; |
|
font-size: 18px; |
|
font-weight: 700; |
|
color: #e6f3ff; |
|
text-shadow: 0 2px 4px rgba(0, 60, 120, 0.4); |
|
letter-spacing: 2px; |
|
position: relative; |
|
overflow: hidden; |
|
cursor: default; |
|
|
|
/* 双背景叠加 */ |
|
background: linear-gradient( |
|
65deg, |
|
rgba(1, 11, 24, 0.8) 0%, |
|
rgba(36, 91, 146, 0.6) 50%, |
|
rgba(18, 53, 95, 0.5) 100% |
|
), |
|
linear-gradient(-25deg, #0b274b 20%, #2b4d6b 80%); |
|
background-blend-mode: overlay; |
|
|
|
/* 动态边框 */ |
|
border: 2px solid; |
|
border-image: linear-gradient(45deg, #026bbb, transparent) 1; |
|
|
|
/* 主流光动画 */ |
|
&::before { |
|
content: ""; |
|
position: absolute; |
|
top: -50%; |
|
left: -100%; |
|
width: 250%; |
|
height: 200%; |
|
background: linear-gradient( |
|
60deg, |
|
transparent 20%, |
|
rgba(255, 255, 255, 0.3) 50%, |
|
transparent 80% |
|
); |
|
animation: shine 2.5s infinite linear; |
|
} |
|
|
|
/* 副流光动画 */ |
|
&::after { |
|
content: ""; |
|
position: absolute; |
|
top: -30%; |
|
left: -50%; |
|
width: 200%; |
|
height: 160%; |
|
background: linear-gradient( |
|
-30deg, |
|
transparent 30%, |
|
rgba(255, 255, 255, 0.2) 50%, |
|
transparent 70% |
|
); |
|
animation: shineReverse 3s infinite linear; |
|
animation-delay: 0.8s; |
|
} |
|
} |
|
|
|
/* 主流光动画 */ |
|
@keyframes shine { |
|
0% { |
|
transform: translateX(-20%) rotate(60deg); |
|
} |
|
100% { |
|
transform: translateX(120%) rotate(60deg); |
|
} |
|
} |
|
|
|
/* 反向副流光 */ |
|
@keyframes shineReverse { |
|
0% { |
|
transform: translateX(20%) rotate(-30deg); |
|
} |
|
100% { |
|
transform: translateX(-120%) rotate(-30deg); |
|
} |
|
} |
|
.right-line { |
|
position: absolute; |
|
top: 0; |
|
left: 0; |
|
width: 170px; |
|
height: 40px; |
|
} |
|
.left-line { |
|
position: absolute; |
|
right: 0; |
|
bottom: 0; |
|
width: 50px; |
|
height: 220px; |
|
} |
|
} |
|
.delaySwitch { |
|
display: flex; |
|
flex-direction: column; |
|
background-color: #142c4e; |
|
border-radius: 10px; |
|
padding: 0 20px; |
|
font-size: 18px; |
|
color: rgb(166, 217, 252); |
|
.delay-li { |
|
display: flex; |
|
flex-direction: column; |
|
align-items: flex-start; |
|
padding: 25px 0; |
|
border-bottom: 1px dashed #0349ac; |
|
.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; |
|
} |
|
} |
|
.delay-bottom { |
|
display: flex; |
|
flex-direction: row; |
|
align-items: flex-start; |
|
.start { |
|
margin-right: 20px; |
|
margin-top: 10px; |
|
white-space: nowrap; |
|
display: flex; |
|
flex-direction: column; |
|
align-items: center; |
|
.start-img { |
|
width: 70px; |
|
height: 70px; |
|
margin-top: 10px; |
|
animation: rotateZ 5s linear infinite; |
|
transition: 0.6s; /* 设置过渡时间,控制翻转速度 */ |
|
transform-style: preserve-3d; /* 保持子元素的 3D 效果 */ |
|
position: relative; |
|
} |
|
} |
|
/* 定义旋转动画 */ |
|
@keyframes rotateZ { |
|
0% { |
|
transform: rotateY(0deg); /* 初始状态,不旋转 */ |
|
} |
|
50% { |
|
transform: rotateY(180deg); /* 旋转到 180 度,呈现翻面效果 */ |
|
} |
|
100% { |
|
transform: rotateY(360deg); /* 旋转回 360 度,回到初始状态 */ |
|
} |
|
} |
|
.delay-right { |
|
display: flex; |
|
flex-direction: row; |
|
align-items: center; |
|
flex-wrap: nowrap; |
|
} |
|
} |
|
.delay-context { |
|
display: flex; |
|
flex-direction: row; |
|
align-items: center; |
|
margin-bottom: 20px; |
|
min-width: 150px; |
|
} |
|
.butterflyValve { |
|
width: 120px; |
|
height: 120px; |
|
margin-top: 10px; |
|
padding: 5px; |
|
border-radius: 5px; |
|
background-color: #2c4970; |
|
} |
|
.hostImg { |
|
width: 130px; |
|
height: 130px; |
|
margin-top: 10px; |
|
padding: 5px; |
|
border-radius: 5px; |
|
background-color: #2c4970; |
|
} |
|
.valveImg { |
|
width: 120px; |
|
height: 120px; |
|
margin-top: 10px; |
|
padding: 5px; |
|
border-radius: 5px; |
|
background-color: #2c4970; |
|
} |
|
.pumpImg { |
|
width: 120px; |
|
height: 120px; |
|
margin-top: 10px; |
|
padding: 5px 20px; |
|
border-radius: 5px; |
|
background-color: #2c4970; |
|
} |
|
.device-arrow { |
|
display: flex; |
|
flex-direction: column; |
|
align-items: center; |
|
} |
|
.delay-input { |
|
display: flex; |
|
flex-direction: row; |
|
align-items: center; |
|
flex-wrap: nowrap; |
|
margin-bottom: 10px; |
|
} |
|
.device-body { |
|
display: flex; |
|
flex-direction: column; |
|
align-items: center; |
|
margin: 0px 30px; |
|
padding: 10px; |
|
} |
|
.last { |
|
display: flex; |
|
flex-direction: row; |
|
align-items: center; |
|
} |
|
.openLast { |
|
margin-top: -22px; |
|
margin-left: 535px; |
|
display: flex; |
|
flex-direction: row; |
|
align-items: flex-start; |
|
} |
|
.closeLast { |
|
margin-top: -22px; |
|
margin-left: 300px; |
|
display: flex; |
|
flex-direction: row; |
|
align-items: flex-start; |
|
} |
|
.reverse-img { |
|
display: flex; |
|
flex-direction: column; |
|
align-items: center; |
|
justify-content: center; |
|
.yuan { |
|
width: 6px; |
|
height: 6px; |
|
margin-bottom: 10px; |
|
} |
|
} |
|
.lastTower { |
|
display: flex; |
|
flex-direction: row; |
|
align-items: flex-start; |
|
margin-left: 0px; |
|
margin-top: 50px; |
|
.device-body { |
|
flex-direction: row !important; |
|
margin-left: 0px !important; |
|
} |
|
.butterflyValve { |
|
margin-right: 10px; |
|
margin-top: 0 !important; |
|
} |
|
} |
|
} |
|
.delay-li:nth-last-child(1) { |
|
border-bottom: none; |
|
} |
|
} |
|
@media (min-width: 1605px) and (max-width: 1730px) { |
|
.app-container { |
|
transform: scale(0.9); |
|
transform-origin: top left; |
|
width: 110%; |
|
} |
|
} |
|
@media (min-width: 1450px) and (max-width: 1605px) { |
|
.app-container { |
|
transform: scale(0.8); |
|
transform-origin: top left; |
|
width: 125%; |
|
} |
|
} |
|
@media (min-width: 1330px) and (max-width: 1450px) { |
|
.app-container { |
|
transform: scale(0.7); |
|
transform-origin: top left; |
|
width: 140%; |
|
} |
|
} |
|
@media (min-width: 1260px) and (max-width: 1450px) { |
|
.app-container { |
|
transform: scale(0.65); |
|
transform-origin: top left; |
|
width: 155%; |
|
} |
|
} |
|
@media (min-width: 1170px) and (max-width: 1260px) { |
|
.app-container { |
|
transform: scale(0.6); |
|
transform-origin: top left; |
|
width: 165%; |
|
} |
|
} |
|
@media (min-width: 980px) and (max-width: 1170px) { |
|
.app-container { |
|
transform: scale(0.55); |
|
transform-origin: top left; |
|
width: 180%; |
|
} |
|
} |
|
@media (min-width: 900px) and (max-width: 1100px) { |
|
.app-container { |
|
transform: scale(0.5); |
|
transform-origin: top left; |
|
width: 200%; |
|
} |
|
} |
|
@media (min-width: 0px) and (max-width: 900px) { |
|
.app-container { |
|
transform: scale(0.55); |
|
transform-origin: top left; |
|
width: 180%; |
|
} |
|
} |
|
// 媒体查询,适配大于2000px分辨率的大屏样式 |
|
@media (min-width: 2000px) { |
|
.app-container { |
|
padding: 0.2rem !important; |
|
.delay-title { |
|
font-size: 0.18rem !important; |
|
letter-spacing: 0.02rem !important; |
|
.right-line { |
|
width: 1.7rem !important; |
|
height: 0.4rem !important; |
|
} |
|
.left-line { |
|
width: 0.5rem !important; |
|
height: 2.2rem !important; |
|
} |
|
} |
|
} |
|
.delaySwitch { |
|
border-radius: 0.1rem !important; |
|
padding: 0 0.2rem !important; |
|
font-size: 0.18rem !important; |
|
.delay-li { |
|
padding: 0.4rem 0 !important; |
|
border-bottom: 0.01rem dashed #0349ac !important; |
|
.buildingDiv { |
|
padding-left: 0.54rem !important; |
|
margin-bottom: 0.2rem !important; |
|
.title-bg { |
|
width: 2.08rem !important; |
|
height: 0.28rem !important; |
|
} |
|
.title-word { |
|
font-size: 0.24rem !important; |
|
} |
|
} |
|
.delay-bottom { |
|
.start { |
|
margin-right: 0.2rem !important; |
|
margin-top: 0.1rem !important; |
|
.start-img { |
|
width: 0.7rem !important; |
|
height: 0.7rem !important; |
|
margin-top: 0.1rem !important; |
|
} |
|
} |
|
} |
|
.delay-context { |
|
margin-bottom: 0.2rem !important; |
|
min-width: 1.5rem !important; |
|
} |
|
.butterflyValve { |
|
width: 0.7rem !important; |
|
height: 0.7rem !important; |
|
margin-top: 0.1rem !important; |
|
padding: 0.05rem !important; |
|
border-radius: 0.05rem !important; |
|
} |
|
.delay-input { |
|
margin-bottom: 0.1rem !important; |
|
} |
|
.device-body { |
|
margin: 0px 0.3rem !important; |
|
padding: 0.1rem !important; |
|
} |
|
.openLast { |
|
margin-top: -0.22rem !important; |
|
margin-left: 5.35rem !important; |
|
} |
|
.closeLast { |
|
margin-top: -0.22rem !important; |
|
margin-left: 2.75rem !important; |
|
} |
|
.reverse-img { |
|
.yuan { |
|
width: 0.06rem !important; |
|
height: 0.06rem !important; |
|
margin-bottom: 0.1rem !important; |
|
} |
|
} |
|
.lastTower { |
|
margin-top: 0.56rem !important; |
|
.butterflyValve { |
|
margin-right: 0.1rem !important; |
|
} |
|
} |
|
} |
|
.delay-li:nth-last-child(1) { |
|
border-bottom: none !important; |
|
} |
|
} |
|
} |
|
</style> |
|
<style scoped> |
|
.delay-input >>> .el-input { |
|
width: 80px !important; |
|
margin: 0 15px 0 5px; |
|
} |
|
.delay-input >>> .el-input__inner { |
|
background-color: #04193a; |
|
border: 1px solid #1262db; |
|
font-weight: 700; |
|
text-align: center; |
|
padding: 0 0.1rem !important; |
|
color: #3efdf3; |
|
font-size: 17px !important; |
|
} |
|
/* // 媒体查询,适配大于2000px分辨率的大屏样式 */ |
|
@media (min-width: 2000px) { |
|
.delay-input >>> .el-input { |
|
width: 0.8rem !important; |
|
margin: 0 0.15rem 0 0.05rem !important; |
|
} |
|
} |
|
</style>
|
|
|