Files
tunnel-cloud-web/src/components/content/fanInfo/FanInfo.vue
2024-01-07 21:47:32 +08:00

809 lines
21 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div id="fan_info">
<div class="title">风机</div>
<div v-if="socketData==null||socketData.length===0" class="showNull ">
<div class="loading" v-if="loading===0"></div>
{{loading===0?'加载中...':'暂无数据~'}}
</div>
<div v-else class="fans">
<div class="fan-item" v-for="(item,index) in socketData" :key="item.equipmentId">
<div>
<!-- echarts -->
<div class="echart"></div>
<!-- 风机名 -->
<div class="fan-name">{{ changeNum(index + 1) }}号风机</div>
<!-- 功能 -->
<div class="option-nav">
<div>
<div class="state " :class="{ 'blue-state': !item.breakdown }">
<div :class="{ stopColor: item.breakdown }">
<div :style="{ backgroundImage: 'url(' +getImageUrl(item.breakdown)+')' }" class="state-icon"></div>
状态{{ item.breakdown ? '故障' : '运行' }}
</div>
<div class="switch">
<div
id="auto"
:class="{ active: item.running }"
@click="item.running = true"
>
启动
</div>
<div
id="stop"
:class="{ active: !item.running }"
@click="item.running = false"
>
停止
</div>
</div>
</div>
<div class="power">
<div class="check-box">
<el-radio-group v-model="item.autoMode" class="radio-group">
<el-radio :label="true">自动</el-radio>
<el-radio :label="false">手动</el-radio>
</el-radio-group>
</div>
<div class="edit-power">
<span style="color: white">当前功率</span>
<span class="units"
><input
type="number"
min="0"
v-model="item.frequencySetting"
:disabled="item.autoMode"
/></span>
</div>
</div>
</div>
<div class="shuntThreshold">
<div class="fenliu-icon"></div>
分流阀值
<span class="units"
><input
type="number"
min="0"
v-model="shuntThreshold"
/></span>
</div>
</div>
</div>
<div class="current" @click="handleOpenChart(item,index)">
<fan-info-item :wp="transducerData[index]" />
</div>
</div>
</div>
<div class="digital-tunnel">
<el-dialog :close-on-click-modal="false" v-model="isVisited" :title="changeNum(fanIndex)+'号风机电流监控数据'" width="2175px"
:modal="false">
<div class="left-top-icon"></div>
<div class="right-top-icon"></div>
<div class="loading-block" v-if="showLoading">
<div class="loading" ></div>
<span>加载中...</span>
</div>
<div class="chat-dialog" v-else>
<div id="containerFan"></div>
<div style="width: 1px;"></div>
</div>
<!-- <div class="time-select">-->
<!-- <time-range-btn-->
<!-- :buttonList="timeList"-->
<!-- v-model="selectTimeButton"-->
<!-- @select="timeSelect"-->
<!-- />-->
<!-- </div>-->
<div class="left-bottom-icon"></div>
<div class="right-bottom-icon"></div>
</el-dialog>
</div>
</div>
</template>
<script setup>
import * as echarts from "echarts";
import FanInfoItem from "./FanInfoItem.vue";
import {getFanEchartsInfo} from "../../../api/largeScreen";
const props = defineProps({
list: Array,
fanData: Array,
transducerData: Array,
loading: Number,
});
const socketData = ref()
let Echarts_info1 = null;
let fan01_option = reactive();
const shuntThreshold = ref(23)
const transducerData = ref([])
const stateA = ref(false)
const stateB = ref(false)
const stateC = ref(false)
const isVisited = ref(false)
const showLoading = ref(false)
const fanIndex = ref(0)
let myEcharts = reactive({});
watch(() => props.loading, (now) => {
props.loading=now
}, {deep: true});
watch(() => props.transducerData, (now) => {
getTransData(now.frequencyChangerList)
}, {deep: true});
watch(() => props.fanData, (now) => {
getBasicData(now.frequencyChangerList)
}, {deep: true});
watch(() => props.list, (now) => {
socketData.value.forEach(item => {
now.forEach(newItem => {
if (item.equipmentId === newItem.equipmentId) {
if (newItem.frequencyFeedback) {
item.frequencySetting = newItem.frequencySetting
item.frequencyFeedback = newItem.frequencyFeedback
}
}
})
})
transducerData.value.forEach(item => {
now.forEach(newItem => {
if (item.equipmentId === newItem.equipmentId) {
if (newItem.frequencyFeedback) {
item.frequencySetting = newItem.frequencySetting
item.frequencyFeedback = newItem.frequencyFeedback
} else if (newItem.phaseCurrentA) {
item.valueA = newItem.phaseCurrentA
item.valueB = newItem.phaseCurrentB
item.valueC = newItem.phaseCurrentC
}
}
})
})
handleOnMounted()
}, {deep: true});
const getFanInfo = (equipmentId) => {
isVisited.value = true
showLoading.value=true
getFanEchartsInfo(equipmentId).then(res => {
if (res?.code === 1000) {
showLoading.value=false
nextTick(() => {
initChart(res.data.dates, res.data.currentsA,res.data.currentsB,res.data.currentsC)
})
}
})
}
const handleOpenChart = (item,index) => {
getFanInfo(item.equipmentId)
fanIndex.value=index+1
}
const getTransData = (data) => {
let tranObj = {}
let tranArr = []
data?.map(item => {
tranObj = {
equipmentId: item.equipmentId,
max: 800,
valueA: item.phaseCurrentA,
pointA: item.phaseCurrentAThreshold,
valueB: item.phaseCurrentB,
pointB: item.phaseCurrentBThreshold,
valueC: item.phaseCurrentC,
pointC: item.phaseCurrentCThreshold,
frequencySetting: item.frequencySetting,
frequencyFeedback: item.frequencyFeedback,
}
stateA.value = item.phaseCurrentA > item.phaseCurrentAThreshold
stateB.value = item.phaseCurrentB > item.phaseCurrentBThreshold
stateC.value = item.phaseCurrentC > item.phaseCurrentCThreshold
tranArr.push(tranObj)
})
transducerData.value = tranArr
}
const getImage = (type) => {
switch (type) {
case false:
return "blue-state-icon.png";
case true:
return "red-state-icon.png";
}
}
const changeNum = (index) => {
switch (index) {
case 1:
return '一';
case 2:
return '二';
case 3:
return '三';
}
}
const getBasicData = (data) => {
let tranObj = {}
let tranArr = []
data?.map(item => {
tranObj = {
equipmentId: item.equipmentId,
autoMode: item.autoMode,//自动模式
breakdown: item.breakdown,//故障
running: item.running,//启动,
frequencyFeedback: item.frequencyFeedback,//当前功率
frequencySetting: item.frequencySetting//当前功率
}
tranArr.push(tranObj)
})
socketData.value = tranArr
nextTick(() => {
handleOnMounted()
})
}
const handleOnMounted = () => {
// console.log('socketData.value[i]',socketData.value)
const chart = document.getElementsByClassName('echart');
for (let i = 0; i < chart.length; i++) {
Echarts_info1 = echarts.init(chart[i]);
fan01_option = {
series: [
{
type: "gauge",
startAngle: -120,
endAngle: -420,
pointer: {
show: false,
},
progress: {
show: true,
overlap: false,
roundCap: true,
clip: false,
itemStyle: {
borderWidth: 10,
borderColor: {
type: "linear",
x: 0,
y: 1,
x2: 0,
y2: 0,
colorStops: [
{
offset: 0,
color: "#4BB10E", // 0% 处的颜色
},
{
offset: 0.25,
color: "#B1AD0E", // 100% 处的颜色
},
{
offset: 0.75,
color: "#B1880E", // 100% 处的颜色
},
{
offset: 1,
color: "#D77E01", // 100% 处的颜色
},
],
global: false, // 缺省为 false
},
color: {
type: "linear",
x: 0,
y: 1,
x2: 0,
y2: 0,
colorStops: [
{
offset: 0,
color: "#4BB10E", // 0% 处的颜色
},
{
offset: 0.25,
color: "#B1AD0E", // 100% 处的颜色
},
{
offset: 0.75,
color: "#B1880E", // 100% 处的颜色
},
{
offset: 1,
color: "#D77E01", // 100% 处的颜色
},
],
global: false, // 缺省为 false
}
},
},
max: 1000,
splitLine: {
show: false,
},
axisTick: {
show: true,
splitNumber: 1,
length: 10,
},
axisLabel: {
show: false,
},
data: [
{
value: socketData.value[i].frequencyFeedback,
fontSize: 2100,
detail: {
valueAnimation: true,
offsetCenter: ["0%", "0%"],
fontSize: 40,
color: "white",
},
},
],
axisLine: {
lineStyle: {
width: 3,
color: [[1, "#155F7C"]],
},
},
detail: {
width: 100,
height: 14,
fontSize: 26,
color: "inherit",
formatter: "{value}",
},
},
],
}
fan01_option && Echarts_info1.setOption(fan01_option);
}
}
const getImageUrl = (name) => {
let icon = getImage(name)
return new URL(`../../../assets/images/fanInfo/${icon}`, import.meta.url).href
}
/**
* 初始化echarts实例方法
*/
const initChart = (type, valueA,valueB,valueC) => {
//3.初始化container容器
myEcharts = echarts.init(document.getElementById('containerFan'));
//5.传入数据
let option = {
//图例
legend: {
left: 0,
textStyle: {
color: '#FFFFFF',
fontSize: 45
},
itemWidth: 30,
itemHeight: 30,
icon: "circle",
},
//离容器四侧的距离
grid: {
left: 0, // 左边距
right: 20, // 右边距
top: 80, // 顶边距
bottom: 0, // 底边距
containLabel: true,
},
//提示框组件
tooltip: {
show: true,
trigger: 'axis',
backgroundColor: "transparent", // 设置背景颜色为透明
borderColor: "transparent", // 设置边框颜色为透明
padding: 0, // 设置内边距为0
textStyle: {
fontSize: 40
},
formatter: function (params) {
let content = `
<div style="background: linear-gradient(180deg, #254062 0%, rgba(20,36,51,0.3) 100%);;border: 2px solid #6087BA;border-radius: 4px;padding: 8px 16px;">
<div style="font-size: 52px;font-family: PingFang SC-Regular, PingFang SC;font-weight: 400;color: #EFEEEE;margin-bottom: 8px;">${params[0].name}</div>
<div style="font-size: 52px;line-height: 48px;font-family: Bebas Neue-Regular, Bebas Neue;font-weight: 400;margin-top: 20px"><span style="background: linear-gradient(180deg, #F5B85F 0%, #FFFFFF 100%);background-clip: text;-webkit-background-clip: text;-webkit-text-fill-color: transparent;">${params[0].value}</span></div>
</div>`;
return content;
},
},
toolbox: {
show: false,
right: 10,
feature: {
dataZoom: {
yAxisIndex: 'none'
}
}
},
dataZoom: [{
type: 'inside'
}],
//X轴
xAxis: {
type: 'category',
// data: ['00:00', '01:00', '02:00', '03:00', '04:00', '05:00', '06:00','07:00', '08:00', '09:00', '10:00', '11:00', '12:00', '13:00', '14:00', '15:00', '16:00', '17:00', '18:00','19:00', '20:00', '21:00', '22:00', '23:00','24:00'],
data: type,
axisLabel: {
textStyle: {
fontSize: 45,
color: '#D6F1FA'
},
},
},
//Y轴
yAxis: {
type: 'value',
axisLabel: {
textStyle: {
fontSize: 45,
color: '#D6F1FA'
},
},
},
//配置项
series: [
{
// data: [56, 12, 89, 34, 71, 43, 67, 20, 98, 72, 19, 61, 3, 85, 47, 92, 17, 76, 69, 25, 31, 49, 81, 63],
name:'A相电流',
data: valueA,
type: 'line',
smooth: true,
symbolSize: 24,
lineStyle: {
width: 5
},
},
{
name:'B相电流',
data: valueB,
type: 'line',
smooth: true,
symbolSize: 24,
lineStyle: {
width: 5
},
},
{
name:'C相电流',
data: valueC,
type: 'line',
smooth: true,
symbolSize: 24,
lineStyle: {
width: 5
},
}
]
}
myEcharts.setOption(option);
//图表大小自适应窗口大小变化
window.onresize = () => {
myEcharts.resize();
}
}
</script>
<style lang="scss" scoped>
:deep( .el-radio__input.is-checked + .el-radio__label) {
color: #38CAFB;
}
:deep( .el-radio__input.is-checked .el-radio__inner) {
border-color: #062247;
background: #38CAFB;
}
:deep( .el-radio__inner) {
border: none;
background: none;
}
:deep(.el-radio__inner::after) {
display: none;
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
}
input[type="number"] {
-moz-appearance: textfield;
}
:deep( .el-radio__input) {
width: 24px;
height: 24px;
border: 2px solid #38cafb;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
:deep( .el-radio__label) {
font-size: 28px;
color: #38cafb;
line-height: 37px;
}
#fan_info {
//height: 1465px;
//height: 1000px;
min-height: 350px;
width: 830px;
//position: absolute;
z-index: 100;
//top: 184px;
//left: 68px;
padding: 10px 10px 20px 10px;
background-image: url(../../../assets/images/fanInfo/bg.png);
color: #2fb0df;
box-sizing: border-box;
.title {
width: 40%;
text-align: left;
padding: 0 0 0 50px;
font-size: 38px;
font-weight: bold;
color: #38cafb;
line-height: 42px;
}
.fans {
height: calc(100% - 30px);
.fan-item {
//height: 33.5%;
height: 50%;
padding-bottom:10px;
display: flex;
flex-direction: column;
font-size: 14px;
//border-bottom: 2px solid rgba(107, 163, 237, 0.4);
> div:first-child {
display: flex;
.echart {
height: 270px;
width: 34%;
margin: 0px 0px 0px 10px;
position: relative;
}
.echart::after {
content: "Hz";
font-size: 24px;
font-weight: bold;
color: #ffffff;
line-height: 31px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, 60%);
}
.fan-name {
width: 39px;
height: 140px;
font-size: 26px;
color: #38cafb;
line-height: 35px;
text-align: center;
margin-right: 42px;
transform: translateY(33%);
}
.option-nav {
display: flex;
flex-direction: column;
width: 70%;
> div:first-child {
margin-top: 48px;
display: flex;
align-items: center;
.state {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
font-size: 26px;
color: #38cafb;
line-height: 35px;
gap: 40px;
.blue-state {
> div:first-child:hover {
color: #fff;
background-color: #127399;
width: 180px;
padding-left: 5px;
border-radius: 8px;
> div:first-child {
background-image: url('../../../assets/images/fanInfo/white-state-icon.png') !important;
}
}
}
> div:first-child {
display: flex;
align-items: center;
padding-left: 5px;
> div {
margin-right: 10px;
}
}
img {
margin-right: 4px;
transform: translateY(15%);
}
.state-icon {
width: 26px;
height: 26px;
}
.switch {
display: flex;
width: 160px;
height: 40px;
border-radius: 22px;
border: 2px solid #0f82af;
overflow: hidden;
font-weight: bold;
color: #127399;
line-height: 35px;
& > div {
flex: 1;
text-align: center;
cursor: pointer;
}
}
}
.power {
flex: 1.3;
display: flex;
flex-direction: column;
justify-content: center;
//padding: 0 20px;
font-size: 28px;
color: #38cafb;
line-height: 37px;
gap: 33px;
.edit-power {
margin-top: 10px;
.units {
position: relative;
}
.units::after {
content: "Hz";
position: absolute;
right: 6px;
top: 50%;
transform: translateY(-50%);
font-size: 28px;
color: #38cafb;
line-height: 37px;
}
input {
width: 130px;
height: 44px;
border: 2px solid #0f82af;
background: transparent;
margin-left: 14px;
outline: none;
font-size: 28px;
font-weight: bold;
color: #38cafb;
line-height: 37px;
}
}
}
}
.shuntThreshold {
display: flex;
align-items: center;
justify-content: flex-end;
//align-items: center;
//width: 112px;
padding-top: 30px;
padding-right: 25px;
font-size: 28px;
color: #FFFFFF;
.fenliu-icon {
margin-right: 9px;
width: 31px;
height: 28px;
background-image: url('../../../assets/images/fanInfo/fsp_icon_flf.png');
}
.units {
z-index: 22;
position: relative;
}
input {
width: 130px;
height: 44px;
border: 2px solid #0f82af;
background: transparent;
margin-left: 14px;
outline: none;
font-size: 28px;
font-weight: bold;
color: #38cafb;
line-height: 37px;
}
.units::after {
content: "%";
position: absolute;
right: 6px;
top: 40%;
bottom: 0;
transform: translateY(-50%);
font-size: 28px;
color: #38cafb;
line-height: 37px;
}
}
}
}
.current {
margin-top: 30px;
margin-right: 20px;
margin-left: 26px;
//height: 37px;
font-size: 28px;
color: #FFFFFF;
cursor: pointer;
&:hover{
background-color: #2E5589;
border-radius: 6px;
}
}
}
}
}
.active {
color: white;
background: #0f7da9;
}
.stopColor {
color: red;
}
.stopColor:hover {
color: #fff;
width: 180px;
background: #9B2222;
border-radius: 8px;
> div:first-child {
background-image: url('../../../assets/images/fanInfo/white-state-icon.png') !important;
}
}
</style>