2026-04-13 10:12:04 +08:00
|
|
|
<template>
|
|
|
|
|
<view>
|
2026-06-29 11:01:44 +08:00
|
|
|
<uni-load-more status="loading" v-if="!isDataReady"></uni-load-more>
|
|
|
|
|
<view class="basic mt10" v-else>
|
|
|
|
|
<view class="params-wrap" v-for="(section, ind) in sections" :key="section.title">
|
|
|
|
|
<view class="section-title-row">
|
|
|
|
|
<view class="section-title">
|
|
|
|
|
<view class="grid-card-title-with-icon"></view>
|
|
|
|
|
<text>{{ section.title }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="legend-row" v-if="ind == 0">
|
|
|
|
|
<view class="legend-item" v-for="phase in phaseColors" :key="phase.name">
|
|
|
|
|
<view class="legend-dot" :style="{ background: phase.color }" />
|
|
|
|
|
<text class="legend-text">{{ phase.name }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
2026-04-13 10:12:04 +08:00
|
|
|
</view>
|
2026-06-29 11:01:44 +08:00
|
|
|
<view class="params-section">
|
|
|
|
|
<view v-for="(rowItems, rowIdx) in chunkedChildren(getSectionCards(section))" :key="rowIdx"
|
|
|
|
|
class="double-row">
|
|
|
|
|
<view v-for="(child, childIdx) in rowItems" :key="childIdx" class="param-group">
|
|
|
|
|
<view class="param-title">
|
|
|
|
|
<text>{{ child.name }}</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="phase-vertical">
|
|
|
|
|
<view class="phase-item-vertical">
|
|
|
|
|
<text class="phase-value-vertical" :style="{ color: phaseColors[0].color }">{{
|
|
|
|
|
child.A
|
|
|
|
|
}}</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="phase-divider" />
|
|
|
|
|
<view class="phase-item-vertical">
|
|
|
|
|
<text class="phase-value-vertical" :style="{ color: phaseColors[1].color }">{{
|
|
|
|
|
child.B
|
|
|
|
|
}}</text>
|
|
|
|
|
</view>
|
|
|
|
|
<view class="phase-divider" />
|
|
|
|
|
<view class="phase-item-vertical">
|
|
|
|
|
<text class="phase-value-vertical" :style="{ color: phaseColors[2].color }">{{
|
|
|
|
|
child.C
|
|
|
|
|
}}</text>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
2026-04-13 10:12:04 +08:00
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</view>
|
|
|
|
|
</template>
|
|
|
|
|
<script>
|
2026-06-29 11:01:44 +08:00
|
|
|
const SECTIONS = [
|
|
|
|
|
{
|
|
|
|
|
title: '电网电流',
|
|
|
|
|
dataKey: '电网电流',
|
|
|
|
|
metrics: [
|
|
|
|
|
{ label: '有效值(A)', field: 'Apf_RmsI_Sys(A)' },
|
|
|
|
|
{ label: '畸变率(%)', field: 'Apf_ThdA_Sys(%)' },
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '电网电压',
|
|
|
|
|
dataKey: '电网电压',
|
|
|
|
|
metrics: [
|
|
|
|
|
{ label: '电压(V)', field: 'Apf_PhV_Sys(V)' },
|
|
|
|
|
{ label: '频率(Hz)', field: 'Apf_Freq(Hz)' },
|
|
|
|
|
{ label: '畸变率(%)', field: 'Apf_ThdU_Sys(%)' },
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '负载电流',
|
|
|
|
|
dataKey: '负载电流',
|
|
|
|
|
metrics: [
|
|
|
|
|
{ label: '有效值(A)', field: 'Apf_RmsI_Load(A)' },
|
|
|
|
|
{ label: '畸变率(%)', field: 'Apf_ThdA_Load(%)' },
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
title: '补偿电流',
|
|
|
|
|
dataKey: '补偿电流',
|
|
|
|
|
metrics: [
|
|
|
|
|
{ label: '有效值(A)', field: 'Apf_RmsI_TolOut(A)' },
|
|
|
|
|
{ label: '负载率(%)', field: 'load_Rate' },
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
|
2026-04-13 10:12:04 +08:00
|
|
|
export default {
|
2026-06-29 11:01:44 +08:00
|
|
|
props: {
|
|
|
|
|
basicData: {
|
|
|
|
|
type: Array,
|
|
|
|
|
default: () => [],
|
|
|
|
|
},
|
|
|
|
|
},
|
2026-04-13 10:12:04 +08:00
|
|
|
data() {
|
|
|
|
|
return {
|
2026-06-29 11:01:44 +08:00
|
|
|
sections: SECTIONS,
|
|
|
|
|
phaseColors: [
|
|
|
|
|
{ name: 'A相', color: '#F1B22E' },
|
|
|
|
|
{ name: 'B相', color: '#2BA471' },
|
|
|
|
|
{ name: 'C相', color: '#D54941' },
|
|
|
|
|
],
|
2026-04-13 10:12:04 +08:00
|
|
|
renderData: {
|
|
|
|
|
电网电流: [],
|
|
|
|
|
电网电压: [],
|
|
|
|
|
负载电流: [],
|
|
|
|
|
补偿电流: [],
|
|
|
|
|
未知: [],
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
},
|
2026-06-29 11:01:44 +08:00
|
|
|
computed: {
|
|
|
|
|
isDataReady() {
|
|
|
|
|
return (
|
|
|
|
|
this.renderData.电网电流.length > 0 &&
|
|
|
|
|
this.renderData.电网电压.length > 0 &&
|
|
|
|
|
this.renderData.负载电流.length > 0 &&
|
|
|
|
|
this.renderData.补偿电流.length > 0
|
|
|
|
|
)
|
2026-04-13 10:12:04 +08:00
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
watch: {
|
|
|
|
|
basicData: {
|
2026-06-29 11:01:44 +08:00
|
|
|
handler(newVal) {
|
|
|
|
|
this.renderData = {
|
|
|
|
|
电网电流: [],
|
|
|
|
|
电网电压: [],
|
|
|
|
|
负载电流: [],
|
|
|
|
|
补偿电流: [],
|
|
|
|
|
未知: [],
|
|
|
|
|
}
|
|
|
|
|
; (newVal || []).forEach((item) => {
|
|
|
|
|
if (item.phase === 'avg') {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
const key = this.getDataKey(item.statisticalName)
|
|
|
|
|
const index = this.renderData[key].findIndex((item2) => item2.phase === item.phase)
|
|
|
|
|
if (index > -1) {
|
|
|
|
|
this.renderData[key][index][item.statisticalName] = item.statisticalData
|
|
|
|
|
} else {
|
|
|
|
|
this.renderData[key].push({
|
|
|
|
|
phase: item.phase,
|
|
|
|
|
[item.statisticalName]: item.statisticalData,
|
|
|
|
|
})
|
|
|
|
|
}
|
2026-04-13 10:12:04 +08:00
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
deep: true,
|
|
|
|
|
immediate: true,
|
|
|
|
|
},
|
|
|
|
|
},
|
2026-06-29 11:01:44 +08:00
|
|
|
methods: {
|
|
|
|
|
getDataKey(statisticalName) {
|
|
|
|
|
switch (statisticalName) {
|
|
|
|
|
case 'Apf_RmsI_Sys(A)':
|
|
|
|
|
case 'Apf_ThdA_Sys(%)':
|
|
|
|
|
return '电网电流'
|
|
|
|
|
case 'Apf_PhV_Sys(V)':
|
|
|
|
|
case 'Apf_Freq(Hz)':
|
|
|
|
|
case 'Apf_ThdU_Sys(%)':
|
|
|
|
|
return '电网电压'
|
|
|
|
|
case 'Apf_RmsI_Load(A)':
|
|
|
|
|
case 'Apf_ThdA_Load(%)':
|
|
|
|
|
return '负载电流'
|
|
|
|
|
case 'Apf_RmsI_TolOut(A)':
|
|
|
|
|
case 'load_Rate':
|
|
|
|
|
return '补偿电流'
|
|
|
|
|
default:
|
|
|
|
|
return '未知'
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
getSectionCards(section) {
|
|
|
|
|
const list = this.renderData[section.dataKey] || []
|
|
|
|
|
return section.metrics.map((metric) => ({
|
|
|
|
|
name: metric.label,
|
|
|
|
|
A: this.getPhaseValue(list, metric.field, 'A'),
|
|
|
|
|
B: this.getPhaseValue(list, metric.field, 'B'),
|
|
|
|
|
C: this.getPhaseValue(list, metric.field, 'C'),
|
|
|
|
|
}))
|
|
|
|
|
},
|
|
|
|
|
getPhaseValue(list, field, phase) {
|
|
|
|
|
const item = list.find(
|
|
|
|
|
(row) => String(row.phase || '').toUpperCase() === phase,
|
|
|
|
|
)
|
|
|
|
|
return this.formatValue(item[field])
|
|
|
|
|
},
|
|
|
|
|
formatValue(value) {
|
|
|
|
|
if (value == 3.1415926) return '-'
|
|
|
|
|
if (value === undefined || value === null || value === '') return '-'
|
|
|
|
|
const num = Number(value)
|
|
|
|
|
if (Number.isNaN(num)) return value
|
|
|
|
|
return num > 0 ? num.toFixed(2) : num
|
|
|
|
|
},
|
|
|
|
|
chunkedChildren(children) {
|
|
|
|
|
const result = []
|
|
|
|
|
for (let i = 0; i < children.length; i += 2) {
|
|
|
|
|
result.push(children.slice(i, i + 2))
|
|
|
|
|
}
|
|
|
|
|
return result
|
|
|
|
|
},
|
|
|
|
|
},
|
2026-04-13 10:12:04 +08:00
|
|
|
}
|
|
|
|
|
</script>
|
2026-06-29 11:01:44 +08:00
|
|
|
<style lang="scss" scoped>
|
2026-06-01 20:36:04 +08:00
|
|
|
.basic {
|
2026-06-29 11:01:44 +08:00
|
|
|
.params-wrap {
|
|
|
|
|
margin-bottom: 20rpx;
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
border-radius: 10rpx;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.section-title-row {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
gap: 12rpx;
|
|
|
|
|
padding: 20rpx 20rpx 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.section-title {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
font-size: 30rpx;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
color: #333;
|
|
|
|
|
}
|
|
|
|
|
|
2026-06-01 20:36:04 +08:00
|
|
|
.grid-card-title-with-icon {
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
position: relative;
|
2026-06-29 11:01:44 +08:00
|
|
|
width: 8rpx;
|
|
|
|
|
height: 28rpx;
|
|
|
|
|
margin-right: 12rpx;
|
|
|
|
|
background: $uni-theme-color;
|
|
|
|
|
border-radius: 3rpx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.legend-row {
|
|
|
|
|
display: flex;
|
|
|
|
|
gap: 20rpx;
|
|
|
|
|
align-items: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.legend-item {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
gap: 8rpx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.legend-dot {
|
|
|
|
|
width: 16rpx;
|
|
|
|
|
height: 16rpx;
|
|
|
|
|
border-radius: 50%;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.legend-text {
|
|
|
|
|
font-size: 24rpx;
|
|
|
|
|
color: #666666;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.params-section {
|
|
|
|
|
padding: 16rpx 16rpx 20rpx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.double-row {
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: repeat(2, 1fr);
|
|
|
|
|
gap: 16rpx;
|
|
|
|
|
margin-bottom: 16rpx;
|
|
|
|
|
|
|
|
|
|
&:last-child {
|
|
|
|
|
margin-bottom: 0;
|
2026-06-01 20:36:04 +08:00
|
|
|
}
|
|
|
|
|
}
|
2026-06-29 11:01:44 +08:00
|
|
|
|
|
|
|
|
.param-group {
|
|
|
|
|
min-width: 0;
|
|
|
|
|
background: #f3f3f3;
|
|
|
|
|
border-radius: 16rpx;
|
|
|
|
|
padding: 16rpx 8rpx 12rpx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.param-title {
|
|
|
|
|
font-size: 26rpx;
|
|
|
|
|
color: #666666;
|
|
|
|
|
margin-bottom: 8rpx;
|
|
|
|
|
padding-left: 4rpx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.phase-vertical {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: stretch;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.phase-item-vertical {
|
|
|
|
|
flex: 1;
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
align-items: center;
|
|
|
|
|
padding: 4rpx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.phase-value-vertical {
|
|
|
|
|
font-size: 28rpx;
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.phase-divider {
|
|
|
|
|
width: 1px;
|
|
|
|
|
background: #d2d2d2;
|
|
|
|
|
margin: 8rpx 0;
|
|
|
|
|
}
|
2026-06-01 20:36:04 +08:00
|
|
|
}
|
2026-04-13 10:12:04 +08:00
|
|
|
</style>
|