重构
This commit is contained in:
@ -1,229 +1,239 @@
|
||||
<template>
|
||||
<div v-loading="loading">
|
||||
<div>
|
||||
<div class="pcs-tags">
|
||||
<el-tag
|
||||
size="small"
|
||||
:type="selectedSectionKey ? 'info' : 'primary'"
|
||||
:effect="selectedSectionKey ? 'plain' : 'dark'"
|
||||
class="pcs-tag-item"
|
||||
@click="handleTagClick('')"
|
||||
>
|
||||
全部
|
||||
</el-tag>
|
||||
<el-tag
|
||||
v-for="(group, index) in sectionGroups"
|
||||
:key="index + 'dbTag'"
|
||||
size="small"
|
||||
:type="selectedSectionKey === group.sectionKey ? 'primary' : 'info'"
|
||||
:effect="selectedSectionKey === group.sectionKey ? 'dark' : 'plain'"
|
||||
class="pcs-tag-item"
|
||||
@click="handleTagClick(group.sectionKey)"
|
||||
>
|
||||
{{ group.displayName || "电表" }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<el-card
|
||||
v-for="(item,index) in list"
|
||||
:key="index+'dbList'"
|
||||
shadow="always"
|
||||
class="sbjk-card-container list"
|
||||
:class="{
|
||||
'timing-card-container':!['0','2'].includes(item.emsCommunicationStatus),
|
||||
'warning-card-container':item.emsCommunicationStatus === '2',
|
||||
'running-card-container':item.emsCommunicationStatus === '0'
|
||||
}"
|
||||
v-for="(group, index) in filteredSectionGroups"
|
||||
:key="index + 'dbSection'"
|
||||
class="sbjk-card-container list running-card-container"
|
||||
shadow="always"
|
||||
>
|
||||
<div slot="header">
|
||||
<span class="large-title">{{ item.deviceName }}</span>
|
||||
<span class="large-title">{{ group.displayName || "电表" }}</span>
|
||||
<div class="info">
|
||||
<div>
|
||||
{{
|
||||
communicationStatusOptions[item.emsCommunicationStatus] || '-'
|
||||
}}
|
||||
</div>
|
||||
<div>数据更新时间:{{ item.dataUpdateTime || '-' }}</div>
|
||||
</div>
|
||||
<div class="alarm">
|
||||
<el-button type="primary" round size="small" style="margin-right:20px;" @click="pointDetail(item,'point')">
|
||||
详细
|
||||
</el-button>
|
||||
<el-badge :hidden="!item.alarmNum" :value="item.alarmNum || 0" class="item">
|
||||
<i
|
||||
class="el-icon-message-solid alarm-icon"
|
||||
@click="pointDetail(item,'alarmPoint')"
|
||||
></i>
|
||||
</el-badge>
|
||||
<div>状态:{{ group.statusText }}</div>
|
||||
<div>数据更新时间:{{ group.updateTimeText }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-row class="device-info-row">
|
||||
<el-col v-for="(tempDataItem,tempDataIndex) in (deviceIdTypeMsg[item.deviceId] || otherTypeMsg)"
|
||||
:key="tempDataIndex+'dbTempData'"
|
||||
:span="8" class="device-info-col">
|
||||
<span class="pointer" @click="showChart(tempDataItem.pointName,item.deviceId)">
|
||||
<span class="left">{{ tempDataItem.name }}</span> <span class="right">{{ item[tempDataItem.attr] || '-' }}<span
|
||||
v-html="tempDataItem.unit"></span></span>
|
||||
</span>
|
||||
<el-col
|
||||
v-for="(item, dataIndex) in group.items"
|
||||
:key="dataIndex + 'dbField'"
|
||||
:span="8"
|
||||
class="device-info-col"
|
||||
>
|
||||
<span class="left">{{ item.fieldName }}</span>
|
||||
<span class="right">
|
||||
<i v-if="isPointLoading(item.fieldValue)" class="el-icon-loading point-loading-icon"></i>
|
||||
<span v-else>{{ displayValue(item.fieldValue) | formatNumber }}</span>
|
||||
</span>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
<el-empty v-show="list.length<=0" :image-size="200"></el-empty>
|
||||
<point-chart ref="pointChart" :site-id="siteId"/>
|
||||
<point-table ref="pointTable"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import pointChart from "./../PointChart.vue";
|
||||
import getQuerySiteId from "@/mixins/ems/getQuerySiteId";
|
||||
import {getAmmeterDataList} from "@/api/ems/dzjk";
|
||||
import intervalUpdate from "@/mixins/ems/intervalUpdate";
|
||||
import PointTable from "@/views/ems/site/sblb/PointTable.vue";
|
||||
import {mapState} from "vuex";
|
||||
import { getProjectDisplayData } from "@/api/ems/dzjk";
|
||||
import { getDeviceList } from "@/api/ems/site";
|
||||
|
||||
export default {
|
||||
name: "DzjkSbjkDb",
|
||||
mixins: [getQuerySiteId, intervalUpdate],
|
||||
components: {PointTable, pointChart},
|
||||
computed: {
|
||||
|
||||
...mapState({
|
||||
communicationStatusOptions: state => state?.ems?.communicationStatusOptions || {},
|
||||
})
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
list: [],
|
||||
deviceIdTypeMsg: {
|
||||
'LOAD': [
|
||||
{
|
||||
name: '正向有功电能',
|
||||
attr: 'forwardActive',
|
||||
pointName: '正向有功电能',
|
||||
unit: 'kWh'
|
||||
},
|
||||
{
|
||||
name: '反向有功电能',
|
||||
attr: 'reverseActive',
|
||||
pointName: '反向有功电能',
|
||||
unit: 'kWh'
|
||||
},
|
||||
{
|
||||
name: '正向无功电能',
|
||||
attr: 'forwardReactive',
|
||||
pointName: '正向无功电能',
|
||||
unit: 'kvarh'
|
||||
},
|
||||
{
|
||||
name: '反向无功电能',
|
||||
attr: 'reverseReactive',
|
||||
pointName: '反向无功电能',
|
||||
unit: 'kvarh'
|
||||
},
|
||||
{
|
||||
name: '有功功率',
|
||||
attr: 'activePower',
|
||||
pointName: '总有功功率',
|
||||
unit: 'kW'
|
||||
},
|
||||
{
|
||||
name: '无功功率',
|
||||
attr: 'reactivePower',
|
||||
pointName: '总无功功率',
|
||||
unit: 'kvar'
|
||||
}
|
||||
],
|
||||
'METE': [
|
||||
{
|
||||
name: '正向有功电能',
|
||||
attr: 'forwardActive',
|
||||
pointName: '正向有功电能',
|
||||
unit: 'kWh'
|
||||
},
|
||||
{
|
||||
name: '反向有功电能',
|
||||
attr: 'reverseActive',
|
||||
pointName: '反向有功电能',
|
||||
unit: 'kWh'
|
||||
},
|
||||
{
|
||||
name: '正向无功电能',
|
||||
attr: 'forwardReactive',
|
||||
pointName: '正向无功电能',
|
||||
unit: 'kvarh'
|
||||
},
|
||||
{
|
||||
name: '反向无功电能',
|
||||
attr: 'reverseReactive',
|
||||
pointName: '反向无功电能',
|
||||
unit: 'kvarh'
|
||||
},
|
||||
{
|
||||
name: '有功功率',
|
||||
attr: 'activePower',
|
||||
pointName: '总有功功率',
|
||||
unit: 'kW'
|
||||
},
|
||||
{
|
||||
name: '无功功率',
|
||||
attr: 'reactivePower',
|
||||
pointName: '总无功功率',
|
||||
unit: 'kvar'
|
||||
}
|
||||
],
|
||||
'METEGF': [
|
||||
{
|
||||
name: '有功电能',
|
||||
attr: 'activeEnergy',
|
||||
pointName: '有功电能',
|
||||
unit: 'kWh'
|
||||
},
|
||||
{
|
||||
name: '无功电能',
|
||||
attr: 'reactiveEnergy',
|
||||
pointName: '无功电能',
|
||||
unit: 'kvarh'
|
||||
},
|
||||
{
|
||||
name: '有功功率',
|
||||
attr: 'activePower',
|
||||
pointName: '总有功功率',
|
||||
unit: 'kW'
|
||||
},
|
||||
{
|
||||
name: '无功功率',
|
||||
attr: 'reactivePower',
|
||||
pointName: '总无功功率',
|
||||
unit: 'kvar'
|
||||
}
|
||||
]
|
||||
},
|
||||
otherTypeMsg: [
|
||||
{
|
||||
name: '正向有功电能',
|
||||
attr: 'forwardActive',
|
||||
pointName: '正向有功电能',
|
||||
unit: 'kWh'
|
||||
},
|
||||
{
|
||||
name: '反向有功电能',
|
||||
attr: 'reverseActive',
|
||||
pointName: '反向有功电能',
|
||||
unit: 'kWh'
|
||||
},
|
||||
{
|
||||
name: '有功功率',
|
||||
attr: 'activePower',
|
||||
pointName: '总有功功率',
|
||||
unit: 'kW'
|
||||
},
|
||||
]
|
||||
displayData: [],
|
||||
selectedSectionKey: "",
|
||||
ammeterDeviceList: [],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
// 查看设备电位表格
|
||||
pointDetail(row, dataType) {
|
||||
const {deviceId} = row
|
||||
this.$refs.pointTable.showTable({siteId: this.siteId, deviceId, deviceCategory: 'AMMETER'}, dataType)
|
||||
computed: {
|
||||
moduleDisplayData() {
|
||||
return (this.displayData || []).filter((item) => item.menuCode === "SBJK_DB");
|
||||
},
|
||||
showChart(pointName, deviceId) {
|
||||
pointName && this.$refs.pointChart.showChart({pointName, deviceCategory: 'AMMETER', deviceId})
|
||||
dbTemplateFields() {
|
||||
const source = this.moduleDisplayData || [];
|
||||
const result = [];
|
||||
const seen = new Set();
|
||||
source.forEach((item) => {
|
||||
const fieldName = String(item?.fieldName || "").trim();
|
||||
if (!fieldName || seen.has(fieldName)) {
|
||||
return;
|
||||
}
|
||||
seen.add(fieldName);
|
||||
result.push(fieldName);
|
||||
});
|
||||
return result.length > 0 ? result : this.fallbackFields;
|
||||
},
|
||||
sectionGroups() {
|
||||
const source = this.moduleDisplayData || [];
|
||||
const devices = (this.ammeterDeviceList || []).length > 0
|
||||
? this.ammeterDeviceList
|
||||
: [{ deviceId: "", deviceName: "电表" }];
|
||||
|
||||
return devices.map((device, index) => {
|
||||
const deviceId = String(device?.deviceId || device?.id || "").trim();
|
||||
const sectionKey = deviceId || `AMMETER_${index}`;
|
||||
const displayName = String(device?.deviceName || device?.name || deviceId || `电表${index + 1}`).trim();
|
||||
const exactRows = source.filter((item) => String(item?.deviceId || "").trim() === deviceId);
|
||||
const fallbackRows = source.filter((item) => !String(item?.deviceId || "").trim());
|
||||
|
||||
const exactValueMap = {};
|
||||
exactRows.forEach((item) => {
|
||||
const key = String(item?.fieldName || "").trim();
|
||||
if (key) {
|
||||
exactValueMap[key] = item;
|
||||
}
|
||||
});
|
||||
const fallbackValueMap = {};
|
||||
fallbackRows.forEach((item) => {
|
||||
const key = String(item?.fieldName || "").trim();
|
||||
if (key && fallbackValueMap[key] === undefined) {
|
||||
fallbackValueMap[key] = item;
|
||||
}
|
||||
});
|
||||
|
||||
const items = (this.dbTemplateFields || []).map((fieldName) => {
|
||||
const row = exactValueMap[fieldName] || fallbackValueMap[fieldName] || {};
|
||||
return {
|
||||
fieldName,
|
||||
fieldValue: row.fieldValue,
|
||||
valueTime: row.valueTime,
|
||||
};
|
||||
});
|
||||
|
||||
const statusItem = (items || []).find((it) => String(it.fieldName || "").includes("状态"));
|
||||
const timestamps = [...exactRows, ...fallbackRows]
|
||||
.map((it) => new Date(it?.valueTime).getTime())
|
||||
.filter((ts) => !isNaN(ts));
|
||||
|
||||
return {
|
||||
sectionName: displayName,
|
||||
sectionKey,
|
||||
displayName,
|
||||
deviceId,
|
||||
items,
|
||||
statusText: this.displayValue(statusItem ? statusItem.fieldValue : "-"),
|
||||
updateTimeText: timestamps.length > 0 ? this.formatDate(new Date(Math.max(...timestamps))) : "-",
|
||||
};
|
||||
});
|
||||
},
|
||||
displaySectionGroups() {
|
||||
if (this.sectionGroups.length > 0) {
|
||||
return this.sectionGroups;
|
||||
}
|
||||
return [
|
||||
{
|
||||
sectionName: "电参量",
|
||||
sectionKey: "电参量",
|
||||
displayName: "电表",
|
||||
items: this.fallbackFields.map((fieldName) => ({ fieldName, fieldValue: "-" })),
|
||||
statusText: "-",
|
||||
updateTimeText: "-",
|
||||
},
|
||||
];
|
||||
},
|
||||
filteredSectionGroups() {
|
||||
const groups = this.displaySectionGroups || [];
|
||||
if (!this.selectedSectionKey) {
|
||||
return groups;
|
||||
}
|
||||
return groups.filter((group) => group.sectionKey === this.selectedSectionKey);
|
||||
},
|
||||
fallbackFields() {
|
||||
return [
|
||||
"正向有功电能",
|
||||
"反向有功电能",
|
||||
"正向无功电能",
|
||||
"反向无功电能",
|
||||
"有功功率",
|
||||
"无功功率",
|
||||
];
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleTagClick(sectionKey) {
|
||||
this.selectedSectionKey = sectionKey || "";
|
||||
},
|
||||
displayValue(value) {
|
||||
return value === undefined || value === null || value === "" ? "-" : value;
|
||||
},
|
||||
isPointLoading(value) {
|
||||
return this.loading && (value === undefined || value === null || value === "" || value === "-");
|
||||
},
|
||||
formatDate(date) {
|
||||
if (!(date instanceof Date) || isNaN(date.getTime())) {
|
||||
return "-";
|
||||
}
|
||||
const p = (n) => String(n).padStart(2, "0");
|
||||
return `${date.getFullYear()}-${p(date.getMonth() + 1)}-${p(date.getDate())} ${p(date.getHours())}:${p(
|
||||
date.getMinutes()
|
||||
)}:${p(date.getSeconds())}`;
|
||||
},
|
||||
resolveDbDisplayName(sectionName) {
|
||||
const key = String(sectionName || "").trim();
|
||||
if (!key) {
|
||||
return "电表";
|
||||
}
|
||||
const list = this.ammeterDeviceList || [];
|
||||
const matched = list.find((item) => {
|
||||
const deviceId = String(item.deviceId || item.id || "").trim();
|
||||
const deviceName = String(item.deviceName || item.name || "").trim();
|
||||
return key === deviceId || key === deviceName;
|
||||
});
|
||||
if (matched) {
|
||||
return matched.deviceName || matched.name || key;
|
||||
}
|
||||
return key;
|
||||
},
|
||||
getAmmeterDeviceList() {
|
||||
return getDeviceList(this.siteId)
|
||||
.then((response) => {
|
||||
const list = response?.data || [];
|
||||
this.ammeterDeviceList = list.filter((item) => item.deviceCategory === "AMMETER");
|
||||
})
|
||||
.catch(() => {
|
||||
this.ammeterDeviceList = [];
|
||||
});
|
||||
},
|
||||
updateData() {
|
||||
this.loading = true;
|
||||
getAmmeterDataList(this.siteId)
|
||||
.then((response) => {
|
||||
this.list = response?.data || []
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
Promise.all([getProjectDisplayData(this.siteId), this.getAmmeterDeviceList()])
|
||||
.then(([response]) => {
|
||||
this.displayData = response?.data || [];
|
||||
})
|
||||
.finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
init() {
|
||||
this.updateData()
|
||||
this.updateInterval(this.updateData)
|
||||
this.updateData();
|
||||
this.updateInterval(this.updateData);
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@ -232,6 +242,38 @@ export default {
|
||||
&.list:not(:last-child) {
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.info {
|
||||
float: right;
|
||||
text-align: right;
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
line-height: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
.pcs-tags {
|
||||
margin: 0 0 12px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.pcs-tag-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.point-loading-icon {
|
||||
color: #409eff;
|
||||
display: inline-block;
|
||||
transform-origin: center;
|
||||
animation: pointLoadingSpinPulse 1.1s linear infinite;
|
||||
}
|
||||
@keyframes pointLoadingSpinPulse {
|
||||
0% { opacity: 0.45; transform: rotate(0deg) scale(0.9); }
|
||||
50% { opacity: 1; transform: rotate(180deg) scale(1.08); }
|
||||
100% { opacity: 0.45; transform: rotate(360deg) scale(0.9); }
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user