绘制关键指标概览页面
This commit is contained in:
@@ -34,8 +34,8 @@
|
||||
item.devType == 'Direct_Connected_Device' ? '治理设备' : '监测设备' }}</text>
|
||||
</view>
|
||||
<view class="event-desc">
|
||||
<text>工程名称:{{ item.engineeringName }}</text>
|
||||
<text>项目名称:{{ item.projectName }}</text>
|
||||
<text>工程:{{ item.engineeringName }}</text>
|
||||
<text>项目:{{ item.projectName }}</text>
|
||||
<!-- <text v-if="item.dataDetails.onlineRate.isAbnormal">在线率:{{
|
||||
item.dataDetails.onlineRate.value }}% 限值:{{ item.dataDetails.onlineRate.threshold
|
||||
}}% </text> -->
|
||||
@@ -55,7 +55,7 @@
|
||||
数据完整性:
|
||||
<view class="data-table">
|
||||
<view class="table-header">
|
||||
<text>监测点名称</text>
|
||||
<text>监测点</text>
|
||||
<text>完整性</text>
|
||||
</view>
|
||||
<view class="table-row"
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
</view>
|
||||
<view class="detail-content">
|
||||
<view class="detail-content-title mb20">基础信息</view>
|
||||
<view class="mb5"> 工程名称:{{ detail.engineeringName }} </view>
|
||||
<view class="mb5"> 项目名称:{{ detail.projectName }} </view>
|
||||
<view class="mb5"> 设备名称:{{ detail.devName }} </view>
|
||||
<view class="mb5"> 监测点名称:{{ detail.lineName }}</view>
|
||||
<view class="mb5"> 工程:{{ detail.engineeringName }} </view>
|
||||
<view class="mb5"> 项目:{{ detail.projectName }} </view>
|
||||
<view class="mb5"> 设备:{{ detail.devName }} </view>
|
||||
<view class="mb5"> 监测点:{{ detail.lineName }}</view>
|
||||
<view class="mb5" style="display: flex">
|
||||
越限详情:
|
||||
<view style="flex: 1" class="details">{{ detail.overLimitDesc }}</view>
|
||||
|
||||
@@ -6,14 +6,15 @@
|
||||
</view>
|
||||
<view class="detail-content">
|
||||
<view class="detail-content-title mb20">基础信息</view>
|
||||
<view class="mb5"> 工程名称:{{ detail.engineeringName }} </view>
|
||||
<view class="mb5"> 项目名称:{{ detail.projectName }} </view>
|
||||
<view class="mb5"> 设备名称:{{ detail.equipmentName }}</view>
|
||||
<view class="mb5"> 监测点名称:{{ detail.lineName }}</view>
|
||||
<view class="mb5"> 工程:{{ detail.engineeringName }} </view>
|
||||
<view class="mb5"> 项目:{{ detail.projectName }} </view>
|
||||
<view class="mb5"> 设备:{{ detail.equipmentName }}</view>
|
||||
<view class="mb5"> 监测点:{{ detail.lineName }}</view>
|
||||
<view class="mb5"> 暂态类型:{{ detail.showName }}</view>
|
||||
<view class="mb5" v-if="detail.evtParamTm"> 持续时间:{{ detail.evtParamTm }}s</view>
|
||||
<view class="mb5" v-if="detail.evtParamVVaDepth"> 幅值:{{ detail.evtParamVVaDepth }}%</view>
|
||||
<view class="mb5" v-if="detail.evtParamPhase"> 相别:{{ detail.evtParamPhase }}</view>
|
||||
<view class="mb5" v-if="detail.landPoint"> 落点区域:{{ detail.landPoint }}</view>
|
||||
</view>
|
||||
<view class="detail-tabs">
|
||||
<uni-segmented-control :current="detailTab" active-color="#376cf3" :values="['波形图', 'ITIC', 'F47']"
|
||||
@@ -22,14 +23,24 @@
|
||||
<view v-if="detailTab == 0">
|
||||
<view class="detail-content">
|
||||
<view class="detail-content-title mb20">瞬时波形图</view>
|
||||
<image style="width: 100%" :src="detail.instantPics" mode="widthFix" v-if="detail.instantPics"
|
||||
<!-- <image style="width: 100%" :src="detail.instantPics" mode="widthFix" v-if="detail.instantPics"
|
||||
@click="previewImage(detail.instantPics)" />
|
||||
<text v-else>暂无</text> -->
|
||||
<view v-if="listWaveData.length > 0">
|
||||
<waveform v-for="(value, ind) in listWaveData" :index="ind" :unit="unit" :data="value"
|
||||
style="height: 150px;" />
|
||||
</view>
|
||||
<text v-else>暂无</text>
|
||||
</view>
|
||||
<view class="detail-content">
|
||||
<view class="detail-content-title mb20">RMS波形图</view>
|
||||
<image style="width: 100%" :src="detail.rmsPics" mode="widthFix" v-if="detail.rmsPics"
|
||||
<!-- <image style="width: 100%" :src="detail.rmsPics" mode="widthFix" v-if="detail.rmsPics"
|
||||
@click="previewImage(detail.rmsPics)" />
|
||||
<text v-else>暂无</text> -->
|
||||
<view v-if="listRmsData.length > 0">
|
||||
<waveform v-for="(value, ind) in listRmsData" :index="ind" :unit="unit" :data="value"
|
||||
style="height: 150px;" />
|
||||
</view>
|
||||
<text v-else>暂无</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -46,14 +57,21 @@
|
||||
import { updateStatus } from '@/common/api/message'
|
||||
import ITIC from './ITIC.vue'
|
||||
import F47 from './F47.vue'
|
||||
import waveform from './waveform.vue'
|
||||
import { analyseWave } from '@/common/api/harmonic.js';
|
||||
|
||||
export default {
|
||||
components: { ITIC, F47 },
|
||||
components: { ITIC, F47, waveform },
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
detail: {},
|
||||
detailTab: 0,
|
||||
listWaveData: [],
|
||||
listRmsData: [],
|
||||
unit: [],
|
||||
list: {},
|
||||
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -74,6 +92,7 @@ export default {
|
||||
},
|
||||
},
|
||||
onLoad(options) {
|
||||
console.log("🚀 ~ options:", options)
|
||||
this.detail = JSON.parse(decodeURIComponent(options.detail).replace(/百分比/g, '%'))
|
||||
this.detail.rmsPics && (this.detail.rmsPics = this.$config.static + this.detail.rmsPics)
|
||||
this.detail.instantPics && (this.detail.instantPics = this.$config.static + this.detail.instantPics)
|
||||
@@ -84,6 +103,31 @@ export default {
|
||||
eventIds: [this.detail.id],
|
||||
})
|
||||
}
|
||||
analyseWave({
|
||||
eventId: this.detail.id,
|
||||
isApp: true
|
||||
}).then(res => {
|
||||
this.list = res.data
|
||||
this.uni = []
|
||||
// 数据
|
||||
this.listWaveData = this.bindChartClickEvent(this.list.listWaveData)
|
||||
this.listRmsData = this.bindChartClickEvent(this.list.listRmsData)
|
||||
// 单位
|
||||
this.unit = this.list.waveTitle.slice(1).reduce((acc, _, i, arr) => {
|
||||
if (i % 3 === 0) {
|
||||
const group = arr.slice(i, i + 3);
|
||||
const type = group[0]?.startsWith('U') ? 'kV' :
|
||||
group[0]?.startsWith('I') ? 'A' : '';
|
||||
acc.push(type);
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
},
|
||||
methods: {
|
||||
onDetailTabChange(e) {
|
||||
@@ -94,6 +138,44 @@ export default {
|
||||
url: `/pages/message1/comp/preview?url=${encodeURIComponent(url)}`,
|
||||
})
|
||||
},
|
||||
bindChartClickEvent(data) {
|
||||
let unit = this.list.waveTitle.slice(1).reduce((acc, _, i, arr) => {
|
||||
const group = arr.slice(i, i + 3);
|
||||
const type = group[0]?.startsWith('U') ? 'kV' :
|
||||
group[0]?.startsWith('I') ? 'A' : '';
|
||||
acc.push(type);
|
||||
return acc;
|
||||
|
||||
}, []);
|
||||
|
||||
const result = [];
|
||||
// 从第2列开始遍历(索引1),每3个一列分组
|
||||
for (let i = 1; i < data[0].length; i += 3) {
|
||||
|
||||
|
||||
const group = {
|
||||
A: data.map(row => [row[0], this.calculate(row[i], unit[i])]), // 每组第1个 → A
|
||||
B: data.map(row => [row[0], this.calculate(row[i + 1], unit[i])]), // 每组第2个 → B
|
||||
C: data.map(row => [row[0], this.calculate(row[i + 2], unit[i])]), // 每组第3个 → C
|
||||
};
|
||||
result.push(group);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
calculate(num, key) {
|
||||
if (num === null) return null
|
||||
let nums = ''
|
||||
switch (key) {
|
||||
case 'kV':
|
||||
nums = num * Number(this.list.pt) / 1000
|
||||
break
|
||||
case 'A':
|
||||
nums = num * Number(this.list.ct)
|
||||
break
|
||||
}
|
||||
return nums
|
||||
}
|
||||
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
237
pages/message1/comp/waveform.vue
Normal file
237
pages/message1/comp/waveform.vue
Normal file
@@ -0,0 +1,237 @@
|
||||
<template>
|
||||
<!-- ITIC -->
|
||||
<view>
|
||||
|
||||
<l-echart ref="echartRef" @finished="initChart"></l-echart>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
|
||||
const echarts = require('../../../uni_modules/lime-echart/static/echarts.min')
|
||||
export default {
|
||||
components: {},
|
||||
props: {
|
||||
data: {
|
||||
type: [Object],
|
||||
},
|
||||
index: {
|
||||
type: [Number],
|
||||
},
|
||||
unit: {
|
||||
type: [Array],
|
||||
}
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
option: {
|
||||
backgroundColor: '#fff',
|
||||
grid: {
|
||||
left: '0px',
|
||||
right: '10rpx',
|
||||
bottom: '0rpx',
|
||||
top: '25px',
|
||||
containLabel: true,
|
||||
},
|
||||
legend: {
|
||||
right: '10px',
|
||||
top: '0px',
|
||||
icon: 'rect',
|
||||
itemWidth: 20,
|
||||
itemHeight: 2,
|
||||
itemGap: 8,
|
||||
itemStyle: {
|
||||
borderWidth: 0,
|
||||
},
|
||||
textStyle: {
|
||||
fontSize: 10,
|
||||
},
|
||||
padding: [5, 5, 5, 10],
|
||||
},
|
||||
|
||||
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
splitLine: { show: false },
|
||||
axisLine: { show: true },
|
||||
axisTick: { show: false },
|
||||
axisLabel: {
|
||||
fontSize: 10,
|
||||
interval: 0,
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
name: '',
|
||||
nameLocation: 'end',
|
||||
nameGap: 10,
|
||||
minInterval: 1,
|
||||
nameTextStyle: {
|
||||
fontSize: 12,
|
||||
padding: [28, 10, 0, 0],
|
||||
},
|
||||
axisLine: {
|
||||
show: true,
|
||||
|
||||
},
|
||||
axisTick: {
|
||||
show: true,
|
||||
|
||||
},
|
||||
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: 'A相',
|
||||
type: 'line',
|
||||
data: [
|
||||
|
||||
],
|
||||
showSymbol: false,
|
||||
smooth: true,
|
||||
tooltips: {
|
||||
show: false,
|
||||
},
|
||||
color: '#DAA520',
|
||||
},
|
||||
{
|
||||
name: 'B相',
|
||||
type: 'line',
|
||||
data: [
|
||||
|
||||
],
|
||||
showSymbol: false,
|
||||
smooth: true,
|
||||
tooltips: {
|
||||
show: false,
|
||||
},
|
||||
color: '#2E8B57',
|
||||
},
|
||||
{
|
||||
name: 'C相',
|
||||
type: 'line',
|
||||
data: [
|
||||
|
||||
],
|
||||
showSymbol: false,
|
||||
smooth: true,
|
||||
tooltips: {
|
||||
show: false,
|
||||
},
|
||||
color: '#A52a2a',
|
||||
},
|
||||
],
|
||||
},
|
||||
status: 'loading',
|
||||
echartRef: null,
|
||||
pointI: [],
|
||||
xLabelShowIndices: new Set(),
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// this.initChart()
|
||||
// console.log('🚀 ~ props.data:', this.props.data)
|
||||
},
|
||||
|
||||
methods: {
|
||||
init() { },
|
||||
async initChart() {
|
||||
if (!this.$refs.echartRef) return
|
||||
try {
|
||||
this.echartRef = await this.$refs.echartRef.init(echarts)
|
||||
this.setOption()
|
||||
|
||||
|
||||
this.echartRef.setOption(this.option, true)
|
||||
} catch (error) {
|
||||
console.error('图表初始化失败:', error)
|
||||
}
|
||||
},
|
||||
formatXAxisLabel(val, index) {
|
||||
return this.xLabelShowIndices.has(index) ? String(val) : ''
|
||||
},
|
||||
getYAxisRange() {
|
||||
const values = []
|
||||
;['A', 'B', 'C'].forEach((key) => {
|
||||
; (this.data[key] || []).forEach((p) => {
|
||||
const v = p[1]
|
||||
if (v !== null && v !== undefined && !Number.isNaN(Number(v))) {
|
||||
values.push(Number(v))
|
||||
}
|
||||
})
|
||||
})
|
||||
if (!values.length) return {}
|
||||
const dataMax = Math.max(...values)
|
||||
const dataMin = Math.min(...values)
|
||||
let min = 0
|
||||
let max = 0
|
||||
if (dataMin > 0) {
|
||||
min = Math.floor(dataMin / 1.3)
|
||||
} else {
|
||||
min = Math.floor(dataMin * 1.3)
|
||||
}
|
||||
if (dataMax > 0) {
|
||||
max = Math.ceil(dataMax * 1.3)
|
||||
} else {
|
||||
max = Math.ceil(dataMax / 1.3)
|
||||
}
|
||||
|
||||
|
||||
if (min === max) {
|
||||
min -= 1
|
||||
max += 1
|
||||
}
|
||||
return { min, max }
|
||||
},
|
||||
buildXLabelShowIndices(xLabels) {
|
||||
const len = xLabels.length
|
||||
if (len === 0) return new Set()
|
||||
const showIndices = new Set([0, len - 1])
|
||||
const zeroIdx = xLabels.findIndex((x) => Number(x) === 0)
|
||||
if (zeroIdx >= 0) {
|
||||
showIndices.add(zeroIdx)
|
||||
} else if (len > 2) {
|
||||
showIndices.add(Math.floor((len - 1) / 2))
|
||||
}
|
||||
return showIndices
|
||||
},
|
||||
setOption() {
|
||||
if (!this.data) return
|
||||
if (this.index == 0) {
|
||||
this.option.legend.show = true
|
||||
} else {
|
||||
this.option.legend.show = false
|
||||
}
|
||||
this.option.yAxis.name = this.unit[this.index]
|
||||
|
||||
const points = this.data.A || []
|
||||
const xLabels = points.map((p) => p[0])
|
||||
this.xLabelShowIndices = this.buildXLabelShowIndices(xLabels)
|
||||
|
||||
this.option.xAxis.data = xLabels
|
||||
this.option.xAxis.axisLabel.formatter = (val, index) => this.formatXAxisLabel(val, index)
|
||||
this.option.series[0].data = points.map((p) => p[1])
|
||||
this.option.series[1].data = (this.data.B || []).map((p) => p[1])
|
||||
this.option.series[2].data = (this.data.C || []).map((p) => p[1])
|
||||
|
||||
const { min, max } = this.getYAxisRange()
|
||||
this.option.yAxis.min = min
|
||||
this.option.yAxis.max = max
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
},
|
||||
|
||||
computed: {},
|
||||
|
||||
watch: {
|
||||
|
||||
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
Reference in New Issue
Block a user