<template>
|
<div class="p-main">
|
<el-tabs
|
class="tab"
|
type="border-card"
|
v-model="acTab"
|
@tab-click="tabClick"
|
>
|
<el-tab-pane name="pdg" label="交流/直流配电柜">
|
<div class="tab-content content1 flex-r">
|
<panel class="panel left" title="交流/直流配电柜遥测量">
|
<div class="content">
|
<div class="row row1">
|
<div class="card has-title">
|
<div class="card-title">第1路交流三相输入电压(V)</div>
|
<div class="card-content">
|
<bar1 ref="bar1" unit="V"></bar1>
|
</div>
|
</div>
|
<div class="card has-title">
|
<div class="card-title">第2路交流三相输入电压(V)</div>
|
<div class="card-content">
|
<bar1 ref="bar2" unit="V"></bar1>
|
</div>
|
</div>
|
</div>
|
<div class="row row3">
|
<div class="card has-title">
|
<div class="card-title">第1路交流三相输入电流(A)</div>
|
<div class="card-content">
|
<gauge3 unit="A" ref="board1"></gauge3>
|
</div>
|
</div>
|
<div class="card has-title">
|
<div class="card-title">第2路交流三相输入电流(A)</div>
|
<div class="card-content">
|
<gauge3 unit="A" ref="board2"></gauge3>
|
</div>
|
</div>
|
</div>
|
<div class="card row2">
|
<list-card
|
:datas="props1"
|
:rows="4"
|
:valueObj="rtData"
|
></list-card>
|
</div>
|
<div class="card card2 row4">
|
<list-card
|
:datas="props2"
|
:rows="3"
|
:valueObj="rtData"
|
></list-card>
|
</div>
|
</div>
|
</panel>
|
<panel class="panel right" title="交流/直流配电柜遥信量">
|
<div class="content">
|
<alarm-legend class="legend"></alarm-legend>
|
<div class="state-row">
|
<el-row :gutter="30">
|
<el-col
|
:span="8"
|
v-for="(item, idx) in alarmList1"
|
:key="'alarm1_' + idx"
|
>
|
<alarm-card
|
class="state-item"
|
:level="item.level"
|
:name="item.label"
|
:flag="getValue(item)"
|
:childrenCount="item.childrenCount"
|
@click.native="cardChildShow(item)"
|
></alarm-card>
|
</el-col>
|
</el-row>
|
</div>
|
<div class="state-row">
|
<el-row :gutter="30">
|
<el-col
|
:span="8"
|
v-for="(item, idx) in alarmList2"
|
:key="'alarm2_' + idx"
|
>
|
<alarm-card
|
:level="item.level"
|
:name="item.label"
|
:flag="getValue(item)"
|
:childrenCount="item.childrenCount"
|
@click.native="cardChildShow(item)"
|
></alarm-card>
|
</el-col>
|
</el-row>
|
</div>
|
</div>
|
</panel>
|
</div>
|
</el-tab-pane>
|
<el-tab-pane name="kgg" label="高频开关整流柜">
|
<div class="tab-content content2 flex-r">
|
<panel class="panel left" title="高频开关整流柜遥测量">
|
<div class="content">
|
<div class="row row1">
|
<div class="card has-title">
|
<div class="card-title">第1路交流三相输入电压(V)</div>
|
<div class="card-content">
|
<bar1 ref="bar3" unit="V"></bar1>
|
</div>
|
</div>
|
<div class="card has-title">
|
<div class="card-title">第2路交流三相输入电压(V)</div>
|
<div class="card-content">
|
<bar1 ref="bar4" unit="V"></bar1>
|
</div>
|
</div>
|
</div>
|
<div class="row row3">
|
<div class="card has-title">
|
<div class="card-title">三相交流输出电压(V)</div>
|
<div class="card-content">
|
<gauge3 unit="V" :range="[0, 300]" ref="board3"></gauge3>
|
</div>
|
</div>
|
<div class="card has-title">
|
<div class="card-title">三相交流输出电流(A)</div>
|
<div class="card-content">
|
<gauge3 unit="A" ref="board4"></gauge3>
|
</div>
|
</div>
|
</div>
|
<div class="card row2">
|
<list-card
|
:datas="props3"
|
:rows="4"
|
:valueObj="rtData"
|
></list-card>
|
</div>
|
<div class="card card2 row4">
|
<list-card
|
:datas="props4"
|
:rows="3"
|
:valueObj="rtData"
|
></list-card>
|
</div>
|
</div>
|
</panel>
|
<panel class="panel right" title="高频开关整流柜遥信量">
|
<div class="content">
|
<alarm-legend class="legend"></alarm-legend>
|
<div class="state-row">
|
<el-row :gutter="30">
|
<el-col
|
:span="8"
|
v-for="(item, idx) in alarmList3"
|
:key="'alarm1_' + idx"
|
>
|
<alarm-card
|
class="state-item"
|
:level="item.level"
|
:name="item.label"
|
:flag="getValue(item)"
|
:childrenCount="item.childrenCount"
|
@click.native="cardChildShow(item)"
|
></alarm-card>
|
</el-col>
|
</el-row>
|
</div>
|
</div>
|
</panel>
|
</div>
|
</el-tab-pane>
|
<el-tab-pane name="hr" label="核容装置">
|
<div class="tab-content content3 flex-r">
|
<panel class="panel left" title="核容装置遥测量">
|
<div class="content">
|
<div class="row row5">
|
<div class="card has-title">
|
<div class="card-title">核容装置与电池组</div>
|
<div class="card-content">
|
<list-card
|
class="hr-list"
|
:datas="props5"
|
:rows="4"
|
:cols="3"
|
:valueObj="rtData"
|
></list-card>
|
</div>
|
</div>
|
</div>
|
<div class="row">
|
<div class="card has-title">
|
<div class="card-title">单体信息</div>
|
<div class="card-content">
|
<div class="h3">
|
<!-- 1-24节单体电压 -->
|
<div class="info-title">
|
1-{{ rtMonData.length }}节单体{{ battInfoTypeStr }}
|
</div>
|
<!-- 电压 内阻 温度 剩余容量 均衡电流 -->
|
<el-radio-group
|
v-model="battInfoType"
|
class="radio-grp"
|
size="mini"
|
>
|
<el-radio-button :label="0">电压</el-radio-button>
|
<el-radio-button :label="1">内阻</el-radio-button>
|
<el-radio-button :label="2">温度</el-radio-button>
|
<el-radio-button :label="3">均衡电流</el-radio-button>
|
<!-- <el-radio-button :label="3">剩余容量</el-radio-button> -->
|
</el-radio-group>
|
</div>
|
<div class="batt-contain">
|
<el-row
|
class="el_row"
|
:gutter="10"
|
v-for="i in 2"
|
:key="'row_' + i"
|
>
|
<el-col
|
class="el_col"
|
:span="2"
|
v-for="idx in 12"
|
:key="'batt_' + i + '_' + idx"
|
>
|
<div
|
class="batt"
|
v-if="(i - 1) * 12 + idx <= rtMonData.length"
|
>
|
<div class="name"># {{ (i - 1) * 12 + idx }}</div>
|
<div class="value">
|
{{
|
rtMonData[(i - 1) * 12 + idx - 1][battInfoType]
|
}}
|
</div>
|
</div>
|
</el-col>
|
</el-row>
|
</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
</panel>
|
<!-- <panel class="panel right" title="核容装置遥信量">
|
<div class="content">
|
<div class="state-row">
|
<div class="title1">核容装置与电池组</div>
|
<div class="state-content">
|
<alarm-legend class="legend"></alarm-legend>
|
<el-row :gutter="30">
|
<el-col
|
:span="12"
|
v-for="(item, idx) in alarmList4"
|
:key="'alarm1_' + idx"
|
>
|
<alarm-card
|
class="state-item"
|
:level="item.level"
|
:name="item.label"
|
:flag="getValue(item)"
|
:childrenCount="item.childrenCount"
|
@click.native="cardChildShow(item)"
|
></alarm-card>
|
</el-col>
|
</el-row>
|
</div>
|
</div>
|
<div class="state-row">
|
<div class="title1">单体信息</div>
|
<el-row :gutter="30">
|
<el-col
|
:span="12"
|
v-for="(item, idx) in alarmList5"
|
:key="'alarm2_' + idx"
|
>
|
<alarm-card
|
:level="item.level"
|
:name="item.label"
|
:flag="getValue(item)"
|
:childrenCount="item.childrenCount"
|
@click.native="cardChildShow(item)"
|
></alarm-card>
|
</el-col>
|
</el-row>
|
</div>
|
</div>
|
</panel> -->
|
</div>
|
</el-tab-pane>
|
</el-tabs>
|
<!-- childrenState -->
|
<alarm-card-pop
|
:visible.sync="childrenVisible"
|
:title="childrenTitle"
|
:value="childrenState"
|
:level="childrenLevel"
|
:count="childrenCount"
|
></alarm-card-pop>
|
</div>
|
</template>
|
|
<script>
|
import { mapState } from "vuex";
|
import Panel from "@/components/panel.vue";
|
import ListCard from "@/components/listCard.vue";
|
import AlarmCard from "@/components/alarmCard.vue";
|
import AlarmCardPop from "@/components/alarmCardPop.vue";
|
import AlarmLegend from "@/components/alarmLegend.vue";
|
import gauge3 from "@/components/gauge3";
|
import bar1 from "@/components/bar1";
|
|
import getBinaryDigits from "@/assets/js/getBinaryDigits";
|
import bitArray2num from "@/assets/js/bitArray2num";
|
|
import const_props from "./js/const_props";
|
import createWs from "@/assets/js/websocket/plus";
|
const WSMixin = createWs("ckRtAndSignalAndHr", "ckDevRsAndRtAlm");
|
|
export default {
|
name: "realtime",
|
mixins: [WSMixin],
|
components: {
|
Panel,
|
ListCard,
|
AlarmCard,
|
AlarmCardPop,
|
AlarmLegend,
|
gauge3,
|
bar1,
|
},
|
data() {
|
const {
|
props1,
|
props2,
|
props3,
|
props4,
|
props5,
|
alarmList1,
|
alarmList2,
|
alarmList3,
|
// alarmList4,
|
// alarmList5,
|
} = const_props;
|
const tabIdx = this.$route.params.tabIdx;
|
const tabs = ["pdg", "kgg", "hr"];
|
return {
|
// 单体实时数据
|
monData: [],
|
rtData: {},
|
currAlarmItem: {},
|
acTab: tabs[tabIdx ? tabIdx : 0],
|
childrenVisible: false,
|
childrenTitle: "",
|
childrenCount: 0,
|
// childrenState: [0],
|
childrenLevel: 0,
|
battInfoType: 0,
|
props1,
|
props2,
|
props3,
|
props4,
|
props5,
|
alarmList1,
|
alarmList2,
|
alarmList3,
|
// alarmList4,
|
// alarmList5,
|
};
|
},
|
mounted() {},
|
watch: {},
|
methods: {
|
getValue(obj) {
|
let rtData = this.rtData;
|
if (Array.isArray(obj.flag)) {
|
return obj.flag.map((v, i) =>
|
this.getValues(rtData[v], rtData[obj.key1[i]], rtData[obj.key0[i]])
|
);
|
} else {
|
return rtData[obj.flag] ? rtData[obj.key1] : rtData[obj.key0];
|
}
|
},
|
getValues(flags, key1s, key0s) {
|
const _flags = getBinaryDigits(flags);
|
const _key1s = getBinaryDigits(key1s);
|
const _key0s = getBinaryDigits(key0s);
|
let arr = _flags.map((v, i) => (v ? _key1s[i] : _key0s[i]));
|
return bitArray2num(arr);
|
},
|
tabClick() {
|
this.$nextTick(() => {
|
this.$refs.bar1.resize();
|
this.$refs.bar2.resize();
|
this.$refs.bar3.resize();
|
this.$refs.bar4.resize();
|
this.$refs.board1.resize();
|
this.$refs.board2.resize();
|
this.$refs.board3.resize();
|
this.$refs.board4.resize();
|
});
|
},
|
cardChildShow(obj) {
|
console.log("enter", obj);
|
if (obj.childrenCount) {
|
this.childrenTitle = obj.label;
|
this.childrenCount = obj.childrenCount;
|
this.currAlarmItem = obj;
|
// this.childrenState = this.getValue(obj);
|
this.childrenLevel = obj.level;
|
this.childrenVisible = true;
|
}
|
},
|
onWSOpen1() {
|
this.$nextTick(() => {
|
this.sendMessage1();
|
});
|
},
|
sendMessage1() {
|
if (!this.isWSOpen1) {
|
return false;
|
}
|
this.SOCKET1.send("");
|
},
|
onWSMessage1(res) {
|
let { data, data2, data3, data4 } = JSON.parse(res.data);
|
// console.log(data, "=====data", data2);
|
// this.paramsAlram(data);
|
this.rtData = {
|
...data,
|
...data2,
|
...data3,
|
};
|
this.monData = data4;
|
this.updateChart();
|
},
|
onWSMessage2(res) {
|
let {
|
data: {
|
rsAlmRes: {
|
data2: [rsAlm],
|
},
|
rtAlmRes: {
|
data2: [rtAlm],
|
},
|
},
|
} = JSON.parse(res.data);
|
// console.log(rsAlm, "=====data", rtAlm);
|
// this.paramsAlram(data);
|
// this.rtData = {
|
// ...data,
|
// ...data2,
|
// };
|
},
|
getBarData(idx, data) {
|
let name = "";
|
switch (idx) {
|
case 1:
|
name = "acIn1Vol";
|
break;
|
|
case 2:
|
name = "acIn2Vol";
|
break;
|
case 3:
|
name = "ac1InVol";
|
break;
|
case 4:
|
name = "ac2InVol";
|
}
|
return ["A", "B", "C"].map((v) => {
|
return data[name + v + "St"]
|
? data[name + v + "Fake"]
|
: data[name + v + "Real"];
|
});
|
},
|
getBoardData(idx, data) {
|
let name = "";
|
switch (idx) {
|
case 1:
|
name = "acIn1Curr";
|
break;
|
|
case 2:
|
name = "acIn2Curr";
|
break;
|
case 3:
|
name = "acOutVol";
|
break;
|
case 4:
|
name = "acOutCurr";
|
break;
|
}
|
return ["A", "B", "C"].map((v) => {
|
return data[name + v + "St"]
|
? data[name + v + "Fake"]
|
: data[name + v + "Real"];
|
});
|
},
|
updateChart() {
|
let rtData = this.rtData;
|
[1, 2, 3, 4].forEach((v) => {
|
let data = this.getBarData(v, rtData);
|
this.$refs["bar" + v].setData({
|
xLabel: ["A相", "B相", "C相"],
|
sData: data,
|
});
|
let data2 = this.getBoardData(v, rtData);
|
this.$refs["board" + v].setData(data2);
|
});
|
},
|
},
|
beforeDestroy() {
|
// 销毁resize事件
|
},
|
computed: {
|
...mapState({
|
cachedViews: (state) => state.tagsView.cachedViews,
|
}),
|
battInfoTypeStr() {
|
// return ["电压", "内阻", "温度", "剩余容量", "均衡电流"][
|
// this.battInfoType
|
// ];
|
return ["电压", "内阻", "温度", "均衡电流"][
|
this.battInfoType
|
];
|
},
|
childrenState() {
|
if (this.childrenVisible) {
|
const obj = this.currAlarmItem;
|
let rtData = this.rtData;
|
return obj.flag.map((v, i) =>
|
this.getValues(rtData[v], rtData[obj.key1[i]], rtData[obj.key0[i]])
|
);
|
} else {
|
return [0];
|
}
|
},
|
// 单体实时数据 生成一个二维数组 每个元素为单体的数据 ["电压", "内阻", "温度", "剩余容量", "均衡电流"]
|
rtMonData() {
|
return this.monData.map((v) => {
|
let {
|
monVolReal,
|
monVolFake,
|
monVolSt,
|
monResReal,
|
monResFake,
|
monResSt,
|
monTmpReal,
|
monTmpFake,
|
monTmpSt,
|
// monRestCapReal,
|
// monRestCapFake,
|
// monRestCapSt,
|
monJhCurrReal,
|
monJhCurrFake,
|
monJhCurrSt,
|
} = v;
|
let vol = monVolSt ? monVolFake : monVolReal;
|
let res = monResSt ? monResFake : monResReal;
|
let tmp = monTmpSt ? monTmpFake : monTmpReal;
|
// let cap = monRestCapSt ? monRestCapFake : monRestCapReal;
|
let curr = monJhCurrSt ? monJhCurrFake : monJhCurrReal;
|
// return [vol + "V", res + "Ω", tmp + "℃", cap + "AH", curr + "A"];
|
return [vol + "V", res + "Ω", tmp + "℃", curr + "A"];
|
});
|
},
|
},
|
};
|
</script>
|
|
<style scoped lang="less">
|
.p-main {
|
height: 100%;
|
.tab {
|
height: 100%;
|
background: transparent;
|
border: 0 none;
|
box-shadow: none;
|
display: flex;
|
flex-direction: column;
|
:deep(.el-tabs__header) {
|
border: 0 none;
|
background-color: transparent;
|
}
|
:deep(.el-tabs__content) {
|
flex: 1;
|
padding: 4px;
|
.el-tab-pane {
|
height: 100%;
|
}
|
}
|
.flex-c {
|
display: flex;
|
flex-direction: column;
|
}
|
.flex-r {
|
display: flex;
|
flex-direction: row;
|
}
|
.tab-content {
|
height: 100%;
|
}
|
:deep(.el-tabs__header) .el-tabs__item {
|
background: #78eef8;
|
color: #000;
|
border-radius: 4px;
|
font-weight: bold;
|
height: 30px;
|
line-height: 30px;
|
font-size: 16px;
|
border: 0 none;
|
& + .el-tabs__item {
|
margin-left: 6px;
|
}
|
&.is-active {
|
color: #fff;
|
background-color: #0081ff;
|
}
|
}
|
}
|
|
.panel {
|
color: #fff;
|
// height: 100%;
|
flex: 1;
|
&.right {
|
margin-left: 10px;
|
flex: 1.44;
|
.content {
|
height: 100%;
|
padding: 10px 30px;
|
position: relative;
|
display: flex;
|
flex-direction: column;
|
justify-content: space-between;
|
.legend {
|
position: absolute;
|
bottom: 100%;
|
right: 6px;
|
width: 286px;
|
}
|
.state-row {
|
:deep(.el-col):nth-child(n + 4) {
|
margin-top: 10px;
|
}
|
}
|
}
|
}
|
&.left .content {
|
height: 100%;
|
padding: 10px;
|
display: flex;
|
flex-direction: column;
|
|
& > div:not(:first-child) {
|
margin-top: 10px;
|
}
|
.row {
|
flex: 2.5;
|
display: flex;
|
}
|
.row2 {
|
flex: 1.66;
|
}
|
.row4 {
|
flex: 1.3;
|
}
|
}
|
}
|
.tab-content.content3 {
|
.panel.left {
|
flex: 1.43;
|
.row .card-content {
|
padding: 4px;
|
display: flex;
|
flex-direction: column;
|
}
|
.row5 .card-content {
|
padding: 10px;
|
}
|
|
.card .h3 {
|
padding-left: 8px;
|
color: #f69f40;
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
background: #153953;
|
}
|
.batt-contain {
|
margin-top: 4px;
|
padding: 6px;
|
flex: 1;
|
display: flex;
|
flex-direction: column;
|
.el_row {
|
flex: 1;
|
& ~ .el_row {
|
margin-top: 8px;
|
}
|
}
|
.el_col {
|
height: 100%;
|
}
|
.batt {
|
height: 100%;
|
background: url("./images/batt.png") 50% 50% / 100% 100% no-repeat;
|
text-align: center;
|
position: relative;
|
.name {
|
color: #011f39;
|
font-weight: bold;
|
font-size: 12px;
|
position: absolute;
|
top: 42%;
|
left: 50%;
|
transform: translate(-50%, -50%);
|
}
|
.value {
|
position: absolute;
|
top: 54%;
|
left: 18%;
|
right: 18%;
|
bottom: 16%;
|
background: #f69f40;
|
border-radius: 4px;
|
text-align: center;
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
color: #000;
|
font-weight: 700;
|
}
|
}
|
}
|
}
|
.panel.right {
|
flex: 1;
|
.state-row {
|
:deep(.el-col) {
|
margin-top: 10px;
|
}
|
&:first-child {
|
display: flex;
|
flex-direction: column;
|
}
|
.title1 {
|
font-size: 18px;
|
padding-top: 8px;
|
}
|
.state-content {
|
position: relative;
|
flex: 1;
|
}
|
}
|
}
|
}
|
.card {
|
border-radius: 6px;
|
border: 1px #4392a2 solid;
|
padding: 10px;
|
background: #011f39;
|
overflow: hidden;
|
&.has-title {
|
padding: 0;
|
flex: 1;
|
display: flex;
|
flex-direction: column;
|
& + .has-title {
|
margin-left: 10px;
|
}
|
.card-title {
|
background: #0c4d77;
|
line-height: 38px;
|
height: 38px;
|
font-size: 20px;
|
text-align: center;
|
}
|
}
|
}
|
}
|
.card-content {
|
flex: 1;
|
}
|
.hr-list :deep(.content) .value {
|
width: 22em;
|
}
|
.radio-grp {
|
// #007BA4;
|
:deep(.el-radio-button__inner) {
|
color: #fff;
|
background: #007ba4;
|
border: 1px solid #007ba4;
|
}
|
:deep(.el-radio-button:not(:last-child)) .el-radio-button__inner {
|
border-right-color: #32a4b7;
|
}
|
:deep(.el-radio-button__orig-radio:checked) + .el-radio-button__inner {
|
background-color: #46b5be;
|
border-color: #46b5be;
|
box-shadow: -1px 0 0 0 #46b5be;
|
}
|
}
|
</style>
|