页面订阅topic,收到mqtt传送过来的数据,大量的数据如何按照需求只选取个别的数据?
要通过唯一的标识,例如attributeId这种字段来取值(不能通过索引取值,因为索引值可能发生变化,导致全部数据紊乱)
举个例子:
pcsList:
通过setData方法将数据设置为键值对的方式:
控制台的this.svgDataAll数据:
页面效果图如下:
页面完整代码如下:
<template>
<div>
<div class="container">
<!-- 左侧PCS系统信息 -->
<div class="left">
<!-- 左侧:收益 -->
<div class="left_top">
<div class="title_message">收益</div>
<div class="earn_container">
<div class="earn_item">
<div>今日收益 (元) </div>
<div class="earn_item_value">{{ curobj.p2.earn }}</div>
</div>
<div class="earn_item" style=" background-color: #E7FAFF;">
<div>月收益 (元) </div>
<div class="earn_item_value">{{ curobj.p3.monthEarn }}</div>
</div>
<div class="earn_item" style=" background-color: #FFF3DC;">
<div>年收益 (元) </div>
<div class="earn_item_value">{{ curobj.p3.allEarn }}</div>
</div>
<div class="earn_item" style=" background-color: #F2E8FE;">
<div>累计收益 (元) </div>
<div class="earn_item_value">{{ curobj.p3.allEarn }}</div>
</div>
</div>
</div>
<!-- 左侧:收益信息 -->
<div class="left_middle">
<div class="title_message">电量</div>
<div class="electric_container">
<div class="electric_item">
<div>总充电量 (kWh) </div>
<div class="earn_item_value">{{ curobj.p4.allEnter }}</div>
</div>
<div class="electric_item">
<div>总放电量 (kWh) </div>
<div class="earn_item_value">{{ curobj.p4.allOut }}</div>
</div>
</div>
</div>
<!-- 左侧:PCS系统信息 -->
<div class="left_bottom">
<div class="title_message">PCS系统信息</div>
<div class="pcs_container">
<div class="pcs_item" v-for="(item, index) in pcsList" :key="index">
<span>{{ item.attributeName }}</span>
<span class="first">{{ valueFormat(chartData['dName_' + code2did.pcs + '_' + item.attrId])}}
</span>
</div>
</div>
</div>
</div>
<!-- 右侧PCS运行监控 -->
<div class="right">
<div class="top_title">
<div class="title_message" style="padding-top: 3px;">PCS运行监控</div>
</div>
<div class="main">
<div class="mixture_container">
<!-- 运行状态、SVG图、PCS监测数据等 -->
<!-- 运行状态 -->
<div class="status">
<div class="title_message part">运行状态</div>
<div style="display: flex;flex-wrap: wrap;margin-top: 10px;justify-content: center;">
<div class="status_item" v-for="(item, index) in runList" :key="index + 1">
<span class="status_name">{{ item.name }}</span>
<div v-if="index == 0" style="display:flex;padding-left: 20px;">
<div class="circle" :style="operation"></div>
运行
<div class="circle" :style="shutdown"></div>
停机
<div class="circle" :style="standby"></div>
待机
</div>
<div class="status_value">
<div v-if="index == 1" style="display:flex">
<div class="circle" :style="gridConnected"></div>
并网
</div>
<div v-if="index == 2">
<div class="circle" :style="breakdown"></div>
</div>
<div v-if="index == 3">
<div class="circle" :style="alarm"></div>
</div>
<div v-if="index == 4">
<div class="circle" :style="longrange"></div>
</div>
<div v-if="index == 5">
<div class="circle" :style="scram"></div>
</div>
</div>
</div>
</div>
</div>
<!-- SVG图 -->
<div class="image">
<svgNew />
<div style="position: relative;top: -95px;left: 210px;width: 50px;">
<electric :percent="valueFormat(chartData['dName_' + code2did.bms + '_30'])"
:skin="valueFormat(chartData['dName_' + code2did.bms + '_30']) <= 20 ? 2 : 1"></electric>
</div>
<!-- <svgSingle svgValue="4"></svgSingle> -->
</div>
<!-- PCS监测数据 -->
<div class="monitor">
<div class="title_message part">PCS监测数据</div>
<div style="display: flex;flex-wrap: wrap;margin-top: 10px;justify-content: center;">
<div class="monitor_attribute">
<div></div>
<div></div>
<div></div>
<div>A相</div>
<div>B相</div>
<div>C相</div>
</div>
<div class="monitor_item" v-for="(item, index) in mergedList" :key="index">
<span v-if="index == 0 || index == 1" class="firstAndsecond">{{ item[3].name
}}</span>
<span v-else>{{ item[3].name }}</span>
<span class="monitor_value">{{ item[0].value }}</span>
<span class="monitor_value">{{ item[1].value }}</span>
<span class="monitor_value">{{ item[2].value }}</span>
</div>
</div>
</div>
</div>
<!-- BMS电池信息 -->
<div class="bms_container">
<div class="title_message part">BMS电池信息</div>
<div class="bms_parent" style="display: flex;flex-wrap: wrap;margin-top: 10px;">
<div class="bms_item" v-for="(item, index) in bmsList" :key="index + 2">
<span>{{ item.name }}</span>
<span v-if="index == 0" class="first">{{ item.value }}</span>
<span v-else class="bms_value"
:class="'bms_value_' + valueFormat(chartData['dNameWarnType_' + code2did.bms + '_' + item.attrId])">{{
valueFormat(chartData['dName_' +
code2did.bms + '_' + item.attrId]) }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import {
getTimeData,
getEarnInfo,
getPowerInfo,
} from "@/api/overview.js";
import svgSingle from "@/views/business/monitor/single";
import svgNew from "./component/svg_New.vue";
import { listSvg, getSvgData } from "@/api/business/svg";
import MQTT from "@/utils/mqtt.js";
import electric from './component/electric.vue'
export default {
components: {
svgNew,
svgSingle,
electric
},
props: {
curdeptId: {
type: Number,
default: 100
}
},
data() {
return {
range: '',
various: 0,
display: false,
aList: [
{
value: ''
},
{
value: ''
},
{
value: ''
},
{
value: ''
},
{
value: ''
}
],
bList: [
{
value: ''
},
{
value: ''
},
{
value: ''
},
{
value: ''
},
{
value: ''
}
],
cList: [
{
value: ''
},
{
value: ''
},
{
value: ''
},
{
value: ''
},
{
value: ''
}
],
mergedList: [],
curobj: {
p1: {},
p2: {},
p3: {},
p4: {}
},
pcsList: [
{
attributeName: '总输出视在功率(kW)',
attrId:19
},
{
attributeName: '总输出有功功率(kW)',
attrId:11
},
{
attributeName: '总输出无功功率(kW)',
attrId:15
},
{
attributeName: '输入功率(kW)',
attrId:20
},
{
attributeName: '输入电压(V)',
attrId:21
},
{
attributeName: '输入电流(A)',
attrId:22
}
],
pcsNewList: [],
object: {
color: 'red',
height: 80
},
bmsList: [
{
name: 'BMS当前状态',
value: '充电',
attrId: 37
},
{
name: '单体最高电压 (V)',
value: 10,
attrId: 37
},
{
name: '可充电电量 (kWh)',
value: 10,
attrId: 31
},
{
name: '单体最高SOC',
value: 120.00,
attrId: 35
},
{
name: '总电流 (A)',
value: 1,
attrId: 34
},
{
name: '单体最低电压 (V)',
value: 546.45,
attrId: 38
},
{
name: '可放点电量 (kWh)',
value: 546.45,
attrId: 32
},
{
name: '单体最高SOC',
value: 546.45,
attrId: 36
},
{
name: '总电压 (V)',
value: 546.45,
attrId: 33
},
{
name: '单体最高温度 (℃)',
value: 546.45,
attrId: 39
},
{
name: '允许充电电流 (A)',
value: 546.45,
attrId: 28
},
{
name: '允许充电功率',
value: 546.45,
attrId: 41
},
{
name: 'SOC (%) ',
value: 546.45,
attrId: 30
},
{
name: '单体最高温度 (℃)',
value: 546.45,
attrId: 40
},
{
name: '允许放电电流 (A)',
value: 546.45,
attrId: 29
},
{
name: '允许放电功率',
value: 546.45,
attrId: 42
}
],
monitorList: [
{
name: ' 电压'
},
{
name: ' 电流'
},
{
name: '输出有功功率'
},
{
name: '输出无功功率'
},
{
name: '输出视在功率'
},
],
attributeList: [
{
name: ''
},
{
name: 'A相'
},
{
name: 'B相'
},
{
name: 'C相'
},
],
statusList: [],
runList: [
{
name: '运行状态',
},
{
name: '并网状态'
}, {
name: '总故障状态'
}, {
name: '总报警状态'
}, {
name: '远程状态'
}, {
name: '急停输入模式'
},
],
operation: {
backgroundColor: 'white'
},
shutdown: {
backgroundColor: 'white'
},
standby: {
backgroundColor: 'white'
},
gridConnected: {
backgroundColor: 'white'
},
breakdown: {
backgroundColor: 'white'
},
alarm: {
backgroundColor: 'white'
},
longrange: {
backgroundColor: 'white'
},
scram: {
backgroundColor: 'white'
},
timer: String(Date.now()),
svgType: '',
svgDataAll: {},
chartData: {},
deviceName: '',
topics: [],
code2did: {
pcs: 1,
bms: 2
}
}
},
created() {
this.getInfo()
this.mergedList = this.aList.map((item, index) => [item, this.bList[index], this.cList[index], this.monitorList[index]]);
// 初始化mqtt
MQTT.initMqtt();
// this.getList();
this.groupDevice(2);
},
beforeDestroy() {
// 离开页面前就订阅取消掉
this.unsubscribeMqtt();
},
methods: {
// 点击div盒子增高高度
testClick() {
this.object.height += 10
},
// 获取收益和电量信息
getInfo() {
getTimeData().then(res => {
let data = res.data;
this.curobj.p2 = data;
});
getEarnInfo().then(res => {
let data = res.data;
this.curobj.p3 = data;
});
getPowerInfo().then(res => {
let data = res.data;
this.curobj.p4 = data;
});
},
// 取消订阅消息
unsubscribeMqtt() {
if (this.topics.length) {
this.topics.forEach(topic => {
MQTT.unsubscribe(topic, 1);
})
}
},
setData(key1, val1) {
this.chartData[key1] = val1;
},
getSvgData(svgId) {
getSvgData({ svgId: svgId, placeId: this.curdeptId }).then((res) => {
let svgDataList = res.data || [];
svgDataList.forEach(ele => {
if (ele.attr && ele.attr.length) {
ele.attr.forEach(item => {
this.setData("dName_" + ele.deviceId + "_" + item.id, item.val);//直接填结果
this.setData("dNameUnit_" + ele.deviceId + "_" + item.id, item.unit);//
})
}
});
this.svgDataAll = JSON.parse(JSON.stringify(this.chartData))
})
},
// setData方法的设置
setData(key1, val1) {
this.chartData[key1] = val1;
},
valueFormat(val) {
if (val == undefined || val == null) return '';
return val;
},
getList(data, topic) {
this.isFullscreen()
let info = data[topic];
info.map((item) => {
// that.setData("dName_" + deviceId, deviceName);//设备名称
this.setData("dName_" + item.deviceId + "_" + item.attributeId, item.attributeValue);//直接填结果
this.setData("dNameUnit_" + item.deviceId + "_" + item.attributeId, item.unit);//
this.setData("dNameWarnType_" + item.deviceId + "_" + item.attributeId, item.warningType);//
})
this.svgDataAll = JSON.parse(JSON.stringify(this.chartData))
console.log(this.svgDataAll, 'scgdataall');
this.aList[0].value = this.chartData['dName_' + this.code2did.pcs + '_1']
this.aList[1].value = this.chartData['dName_' + this.code2did.pcs + '_4']
this.aList[2].value = this.chartData['dName_' + this.code2did.pcs + '_8']
this.aList[3].value = this.chartData['dName_' + this.code2did.pcs + '_12']
this.aList[4].value = this.chartData['dName_' + this.code2did.pcs + '_16']
this.bList[0].value = this.chartData['dName_' + this.code2did.pcs + '_2']
this.bList[1].value = this.chartData['dName_' + this.code2did.pcs + '_5']
this.bList[2].value = this.chartData['dName_' + this.code2did.pcs + '_9']
this.bList[3].value = this.chartData['dName_' + this.code2did.pcs + '_13']
this.bList[4].value = this.chartData['dName_' + this.code2did.pcs + '_17']
this.cList[0].value = this.chartData['dName_' + this.code2did.pcs + '_3']
this.cList[1].value = this.chartData['dName_' + this.code2did.pcs + '_6']
this.cList[2].value = this.chartData['dName_' + this.code2did.pcs + '_10']
this.cList[3].value = this.chartData['dName_' + this.code2did.pcs + '_14']
this.cList[4].value = this.chartData['dName_' + this.code2did.pcs + '_18']
this.mergedList = this.aList.map((item, index) => [item, this.bList[index], this.cList[index], this.monitorList[index]]);
let a = this.chartData['dName_' + this.code2did.bms + '_27']
if (a == 52428) {
this.bmsList[0].value = '告警'
} else if (a == 48059) {
this.bmsList[0].value = '正常'
} else if (a == 43690) {
this.bmsList[0].value = '故障'
} else if (a == 21845) {
this.bmsList[0].value = '待机'
} else if (a == 4369) {
this.bmsList[0].value = '禁充'
} else if (a == 8738) {
this.bmsList[0].value = '禁放'
}
// 21845
if (topic == 'PCS_pt') {
// 调用pcs运行状态的获取列表方法
this.getStutusList(data)
}
},
isFullscreen() {
return document.fullScreenElement && document.fullScreenElement !== null;
},
getStutusList(data) {
this.statusList[0] = this.chartData['dName_' + this.code2did.pcs + '_46']
this.statusList[1] = this.chartData['dName_' + this.code2did.pcs + '_44']
this.statusList[2] = this.chartData['dName_' + this.code2did.pcs + '_45']
this.statusList[3] = this.chartData['dName_' + this.code2did.pcs + '_51']
this.statusList[4] = this.chartData['dName_' + this.code2did.pcs + '_47']
this.statusList[5] = this.chartData['dName_' + this.code2did.pcs + '_48']
this.statusList[6] = this.chartData['dName_' + this.code2did.pcs + '_49']
this.statusList[7] = this.chartData['dName_' + this.code2did.pcs + '_50']
this.statusList.map((item, index) => {
if (index == 0) {
if (item == 1) {
this.operation.backgroundColor = 'green'
}
} else if (index == 1) {
if (item == 1) {
this.shutdown.backgroundColor = 'red'
}
} else if (index == 2) {
if (item == 1) {
this.standby.backgroundColor = '#FDBF5E'
}
} else if (index == 3) {
if (item == 1) {
this.gridConnected.backgroundColor = '#19A589'
}
} else if (index == 4) {
if (item == 1) {
this.breakdown.backgroundColor = 'red'
}
} else if (index == 5) {
if (item == 1) {
this.alarm.backgroundColor = 'red'
}
} else if (index == 6) {
if (item == 1) {
this.longrange.backgroundColor = 'red'
}
} else if (index == 7) {
if (item == 1) {
this.scram.backgroundColor = 'red'
}
}
})
},
initMqtt() {
let self = this;
if (this.topics.length) {
this.topics.forEach(ele => {
MQTT.subscribe(ele, 0);
MQTT.addHandler(ele, function (res) {
try {
let data = JSON.parse(res);
console.log(data, 'PCSdata');
self.getList(data, ele);
} catch (e) {
if (res.indexOf("设备不在线") !== -1) {
}
}
});
})
}
},
/** 查询列表svg绑定的设备 */
groupDevice(svgVal) {
let topics = [];
this.getSvgData(svgVal);
listSvg({ deptId: this.curdeptId, svgValue: svgVal }).then((res) => {
let svgInfo = res.rows || [];
if (svgInfo.length) {
svgInfo.forEach(ele => {
topics.push(ele.abbrPt);
})
this.topics = topics;
this.initMqtt();
return;
}
this.$modal.msgError("SVG监控数据为空!");
});
}
}
}
</script>
<style scoped>
.container {
min-width: 1600px;
overflow: auto;
height: 100vh;
width: 100%;
padding: 24px;
display: flex;
}
.left {
flex: 0 1 28%;
height: 100%;
border-radius: 5px;
display: flex;
flex-direction: column;
/* justify-content: space-around; */
margin-bottom: 50px;
/* background-color: pink; */
}
.left_top {
flex: 0 27%;
background-color: #FFFFFF;
border-radius: 5px;
}
.left_middle {
flex: 0 1 18%;
background-color: #FFFFFF;
border-radius: 5px;
margin-top: 15px;
}
.left_bottom {
flex: 0 1 46%;
background-color: #FFFFFF;
border-radius: 5px;
margin-top: 15px;
}
.right {
flex: 0 1 72%;
height: 100%;
margin-left: 13px;
border-radius: 5px;
/* background-color: pink; */
/* border: 1px solid #747F91; */
}
.title_message {
font-size: 22px;
color: #fff;
text-align: center;
height: 45px;
line-height: 45px;
/* padding-top: 13px; */
padding-bottom: 13px;
background-color: #8291A9;
border-radius: 8px 8px 0 0;
}
.pcs_value {
height: 95%;
width: 90%;
background-color: #747F91;
margin: 0 13px 0 13px;
display: flex;
justify-content: center;
box-shadow: 0 0 5px 2px rgba(0, 0, 0, 0.25) inset;
border-radius: 10px;
backdrop-filter: blur(10px);
}
.pcs_container {
/* height: calc(100% - 45px); */
width: 100%;
height: 85%;
display: flex;
flex-wrap: wrap;
justify-content: center;
margin-top: 15px;
}
.pcs_item {
border: 1px solid #E0E0E0;
background-color: #152E4A;
width: 95%;
margin-top: 20px;
display: flex;
justify-content: space-around;
align-items: center;
}
.pcs_item {
height: 50px;
width: 90%;
margin: 0 10px 7px 10px;
background-color: #E6E8F0;
border-radius: 5px;
}
.top_title {
/* height: 80px; */
width: 100%;
border: 1px solid #E0E0E0;
background-color: #DEE1E6;
border-radius: 12px 12px 0 0;
}
.directive {
flex: 0 1 50%;
}
.state {
flex: 0 1 50%;
}
.test {
width: 80px;
background-color: antiquewhite;
}
.bms_item {
height: 50px;
flex: 0 1 24%;
border-radius: 8px;
background-color: #E6E8F0;
flex-basis: calc(25% - 10px);
margin: 5px;
display: inline-block;
display: flex;
justify-content: space-around;
align-items: center;
}
.earn_container {
display: flex;
justify-content: center;
flex-wrap: wrap;
padding-top: 10px;
padding-bottom: 10px;
}
.earn_item {
height: 95px;
flex-basis: calc(46% - 10px);
background-color: #FFEBF6;
margin: 5px 5px 5px 5px;
border-radius: 12px;
font-size: 17px;
/* padding: 15px 0 0 28px; */
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.earn_item_value {
font-size: 24px;
font-weight: 600;
margin-top: 10px;
}
.electric_container {
display: flex;
align-items: center;
justify-content: center;
}
.electric_item {
flex: 0 1 43%;
height: 100px;
background-color: #E6E8F0;
margin: 12px;
border-radius: 12px;
font-size: 18px;
/* padding: 15px 0 0 28px; */
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.main {
height: 89%;
width: 100%;
display: flex;
flex-direction: column;
background-color: #FFFFFF;
}
.mixture_container {
flex: 0 1 53%;
display: flex;
justify-content: space-between;
align-items: center;
padding-left: 15px;
padding-right: 15px;
}
.bms_container {
flex: 0 1 42%;
background-color: #F8F9FB;
border-radius: 5px;
margin: 8px;
}
.status {
flex: 0 1 28%;
height: 88%;
}
.image {
flex: 0 1 28%;
height: 88%;
/* position: relative; */
}
.status {
background-color: rgba(248, 249, 251, 1.2);
border-radius: 5px;
}
/* .image {
background-image: url(../../assets/images/EnergyStorage_unit.png);
background-size: 85% 100%;
background-repeat: no-repeat;
background-position: center;
} */
.monitor {
flex: 0 1 40%;
height: 88%;
background-color: #F8F9FB;
border-radius: 5px;
}
.part {
color: #1E1E1E;
background-color: #CCD2E3;
font-weight: 600;
}
.first {
color: #1E1E1E;
font-weight: 600;
font-size: 20px;
}
.monitor_item {
height: 50px;
flex: 0 1 24%;
border-radius: 5px;
background-color: #E6E8F0;
flex-basis: calc(90% - 10px);
margin: 5px;
display: flex;
align-items: center;
/* justify-content: flex-end; */
justify-content: space-around;
}
.monitor_attribute {
height: 50px;
flex: 0 1 24%;
border-radius: 5px;
background-color: #E6E8F0;
flex-basis: calc(90% - 10px);
margin: 5px;
display: flex;
justify-content: space-around;
align-items: center;
}
.firstAndsecond {
padding-left: 15%;
}
.monitor_value {
font-size: 20px;
color: #7084FD;
font-weight: 600;
}
.circle {
height: 16px;
width: 16px;
border-radius: 50%;
}
.status_item {
height: 50px;
flex: 0 1 24%;
border-radius: 5px;
background-color: #E6E8F0;
flex-basis: calc(90% - 10px);
margin: 5px;
display: flex;
align-items: center;
/* justify-content: space-around; */
position: relative;
}
.status_name {
padding-left: 20px;
}
.status_value {
position: absolute;
left: 60%;
}
.bms_value {
color: #2CAB93;
font-weight: 600;
font-size: 20px;
}
.bms_value_0 {
color: #2CAB93;
}
.bms_value_1 {
color: #FECE0A;
}
.bms_value_2 {
color: #FF9B00;
}
.bms_value_3 {
color: #E82E2E;
}
</style>