Files
tunnel-cloud-web/src/components/content/fanInfo/FanInfo.vue
2024-02-26 17:47:15 +08:00

1020 lines
28 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(item) }}号风机</div>
<!-- 功能 -->
<div class="option-nav">
<div>
<div class="state" :class="{changeMargin: item.showTooltip}">
<div class="blue-state" :class="{ stopColor: item.breakdown }">
<div :style="{ backgroundImage: 'url(' +getImageUrl(item.breakdown)+')' }" class="state-icon"></div>
状态<span class="fan-state">{{ item.breakdown ? '故障' : '运行' }}</span>
</div>
<div class="switch">
<div
id="auto"
:class="{ active: item.running }"
@click="item.running = true;editOperate(item,'启动')"
>
启动
</div>
<div
id="stop"
:class="{ active: !item.running }"
@click="item.running = false;editOperate(item,'停止')"
>
停止
</div>
</div>
</div>
<div class="power">
<div class="check-box">
<el-radio-group v-model="item.autoMode" @change="changeModel(item)">
<el-radio :label="true">自动</el-radio>
<el-radio :label="false">手动</el-radio>
</el-radio-group>
</div>
<div class="edit-power">
<div>
<span style="color: white">给定频率</span>
<!-- <span class="units"-->
<!-- ><input-->
<!-- type="number"-->
<!-- min="0"-->
<!-- v-model="item.frequencySetting"-->
<!-- onchange="changeFrequency(item)"-->
<!-- :disabled="item.autoMode"-->
<!-- /></span>-->
<el-input type="number" min="0" v-model="item.frequencySetting" :disabled="item.autoMode" title=""
@change="changeFrequency(item)" @focus="item.showTooltip=true" @blur="item.showTooltip=false">
<template #suffix>
<span>Hz</span>
</template>
</el-input>
</div>
<span v-if="item.showTooltip">
正在输入中...
</span>
</div>
</div>
</div>
</div>
</div>
<div class="current" @click="handleOpenChart(item)">
<fan-info-item :wp="transducerData[index]"/>
</div>
<div class="line"></div>
</div>
<div class="shunt-box">
<div class="shuntThreshold" v-for="(item,index) in shuntList">
<div class="fenliu-icon"></div>
{{ index + 1 }}号分流阀值
<span class="units"
><input
type="number"
min="0"
v-model="item.shuntThreshold"
/></span>
</div>
</div>
</div>
<div class="digital-tunnel">
<el-dialog :close-on-click-modal="false" v-model="isVisited" :title="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 TimeRangeBtn from "@/components/timeRangeBtn/index.vue"
import {
editFrequency,
editFrequencyModelSwitch,
editFrequencyOperationSwitch,
getFanEchartsInfo
} from "@/api/largeScreen";
import {ElMessage, ElMessageBox} from "element-plus";
const timeList = ref(["年", "月", "日"]);
const selectTimeButton = ref(2);
const props = defineProps({
list: Array,
tunnelId: Number,
fanData: Array,
transducerData: Array,
loading: Number,
});
const socketData = ref()
let Echarts_info1 = null;
let fan01_option = reactive();
const transducerData = ref([])
const shuntList = ref([
{
shuntThreshold: 23
},
{
shuntThreshold: 14
},
{
shuntThreshold: 22
},
{
shuntThreshold: 46
},
])
const stateA = ref(false)
const stateB = ref(false)
const stateC = ref(false)
const isVisited = ref(false)
const showLoading = ref(false)
const fanIndex = ref('')
const openEquipmentId = ref(0)
let myEcharts = reactive({});
watch(() => props.loading, (now) => {
props.loading = now
}, {deep: true});
watch(() => props.tunnelId, (now) => {
props.tunnelId = 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 timeSelect = (index) => {
if (index === 0) {
getFanInfo(openEquipmentId.value, 'years')
} else if (index === 1) {
getFanInfo(openEquipmentId.value, 'month')
} else if (index === 2) {
getFanInfo(openEquipmentId.value, 'day')
}
};
const packageData = (item, type, flag) => {
let number = 0
if (item.equipmentType === "frequency1") {
number = 1
} else if (item.equipmentType === "frequency2") {
number = 2
}
if (flag) {
return {
number: number,
value: type,//浮点数
tunnelId: props.tunnelId,
}
} else {
return {
number: number,
state: type === true ? 0 : 1,
tunnelId: props.tunnelId,
}
}
}
//启动/停止
const editOperate = (item, type) => {
ElMessageBox.confirm(`是否${type}该风机?`, '系统提示', {
type: 'warning',
closeOnClickModal: false
}).then(() => {
const data = packageData(item, item.running)
editFrequencyOperationSwitch(data).then(res => {
console.log('修改风机启动', res)
if (res.code === 1000) {
ElMessage.success(res.msg)
} else {
ElMessage.error(res.msg)
}
})
})
}
const changeFrequency = (item) => {
console.log('修改频率')
const data = packageData(item, item.frequencySetting, true)
editFrequency(data).then(res => {
console.log('修改风机频率', res)
if (res.code === 1000) {
ElMessage.success(res.msg)
} else {
ElMessage.warning(res.msg)
}
})
}
const changeModel = (item) => {
const data = packageData(item, item.autoMode)
editFrequencyModelSwitch(data).then(res => {
console.log('修改自动模式', res)
if (res.code === 1000) {
ElMessage.success(res.msg)
} else {
ElMessage.warning(res.msg)
}
})
}
const getFanInfo = (equipmentId, type = 'day') => {
isVisited.value = true
showLoading.value = true
getFanEchartsInfo(equipmentId, type).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) => {
openEquipmentId.value = item.equipmentId
getFanInfo(item.equipmentId, 'day')
if (item.equipmentId === 22) {
fanIndex.value = '一'
} else {
fanIndex.value = '二'
}
}
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 = (item) => {
console.log('1号变频器')
switch (item.equipmentId) {
case 22:
return '一';
case 23:
return '二';
}
}
const getBasicData = (data) => {
let tranObj = {}
let tranArr = []
data?.map(item => {
tranObj = {
equipmentId: item.equipmentId,
equipmentName: item.equipmentName,
equipmentType: item.equipmentType,
autoMode: item.autoMode,//自动模式
breakdown: item.breakdown,//故障
running: item.running,//启动,
showTooltip:false,
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: 50,
splitLine: {
show: false,
},
axisTick: {
show: true,
splitNumber: 1,
length: 10,
},
axisLabel: {
show: false,
},
data: [
{
value: socketData.value[i].frequencySetting,
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: "rgba(20,36,51,0.7)", // 设置背景颜色为透明
borderColor: "#6087BA", // 设置边框颜色为透明
padding: 0, // 设置内边距为0
borderWidth: 2,
textStyle: {
fontSize: 40
},
formatter: (params) => {
let res = ` <div style="font-size: 52px;font-family: PingFang SC-Regular, PingFang SC;font-weight: 400;color: #EFEEEE;margin-bottom: -30px;margin-left: 20px">${params[0].name}</div>` + '<br/>'
for (let i = 0; i < params.length; i++) {
res += `
<div style="font-size: 52px;line-height: 48px;font-family: Bebas Neue-Regular, Bebas Neue;font-weight: 400;margin:0 20px 30px 20px;"><span style="color: #FFFFFF">${params[i].seriesName}: </span><span style="background: linear-gradient(180deg, #F5B85F 0%, #FFFFFF 100%);background-clip: text;-webkit-background-clip: text;-webkit-text-fill-color: transparent;">${params[i].value}</span></div>
`;
}
return res
// return content;
},
// 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 style="font-size: 52px;font-family: PingFang SC-Regular, PingFang SC;font-weight: 400;color: #EFEEEE;margin-bottom: 8px;">${params[1].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[1].value}</span></div>
// <div style="font-size: 52px;font-family: PingFang SC-Regular, PingFang SC;font-weight: 400;color: #EFEEEE;margin-bottom: 8px;">${params[2].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[2].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-group) {
.el-radio {
display: flex;
align-items: center;
}
}
:deep( .el-radio__input) {
width: 28px;
height: 28px;
border: 2px solid #38cafb;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
:deep( .el-radio__label) {
font-size: 28px;
color: #38cafb;
margin-top: -5px;
}
#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);
.shunt-box {
display: flex;
flex-wrap: wrap;
align-items: center;
margin-left: 15px;
margin-top: 15px;
.shuntThreshold {
display: flex;
align-items: center;
padding-bottom: 20px;
padding-right: 45px;
font-size: 28px;
color: #FFFFFF;
border-right: 2px solid #38CAFB;
margin-right: 45px;
&:nth-child(2n) {
border-right: none;
margin-right: 0;
padding-right: 0;
}
&:nth-child(3), &:nth-child(4) {
padding-bottom: 0;
}
.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;
}
}
}
.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: 245px;
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: 25px;
transform: translateY(33%);
}
.option-nav {
//display: flex;
//flex-direction: column;
width: 70%;
> div:first-child {
margin-top: 48px;
display: flex;
align-items: center;
.changeMargin{
margin-top: -40px;
}
.state {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
font-size: 28px;
color: #38cafb;
line-height: 35px;
gap: 40px;
.stopColor {
background-color: red !important;
}
.blue-state {
display: flex;
align-items: center;
height: 45px;
margin-right: 15px;
color: #fff;
background-color: #3eab3f;
padding-left: 10px;
border-radius: 8px;
margin-left: -5px;
.state-icon {
width: 28px;
height: 28px;
background-image: url('../../../assets/images/fanInfo/white-state-icon.png') !important;
margin-right: 10px;
}
.fan-state {
color: #FFFFFF;
}
}
.switch {
display: flex;
width: 165px;
height: 45px;
border-radius: 22px;
border: 2px solid #0f82af;
overflow: hidden;
font-weight: bold;
color: #127399;
line-height: 40px;
& > 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: 40px;
.check-box {
display: flex;
align-items: center;
justify-content: center;
//margin-left: 20px;
}
.edit-power {
margin-top: 10px;
display: flex;
flex-direction: column;
> div:first-child {
display: flex;
> span:first-child {
white-space: pre;
margin-right: 14px;
}
:deep(.el-input__wrapper) {
width: 160px;
height: 44px;
background-color: transparent;
box-shadow: none;
border: 1px solid #38CAFB;
transform: none;
transition: none;
margin-right: 10px;
.el-input__inner {
height: 44px;
font-size: 30px;
font-weight: bold;
color: #38CAFB;
}
.el-input__suffix-inner {
font-size: 30px;
color: #38CAFB;
line-height: 40px;
font-weight: bold;
}
}
}
//.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;
//}
}
}
}
}
}
.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;
}
}
.line {
margin-top: 20px;
margin-left: 15px;
width: 776px;
height: 2px;
background: rgba(107, 163, 237, 0.4);
border-radius: 10px;
}
}
}
}
.active {
color: white;
background: #0f7da9;
}
//.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>