趋势图

This commit is contained in:
sjl
2025-12-10 11:17:19 +08:00
parent 389857ac7e
commit 61ee760f52
3 changed files with 344 additions and 0 deletions

View File

@@ -0,0 +1,72 @@
const dataProcessing = (arr: any[]) => {
return arr
.filter(item => typeof item === 'number' || (typeof item === 'string' && !isNaN(parseFloat(item))))
.map(item => (typeof item === 'number' ? item : parseFloat(item)))
}
const calculateValue = (o: number, value: number, num: number, isMin: boolean) => {
if (value === 0) {
return 0
} else if (value > 0 && Math.abs(value) < 1 && isMin == true) {
return 0
} else if (value > -1 && value < 0 && isMin == false) {
return 0
}
let base
if (Math.abs(o) >= 100) {
base = 100
} else if (Math.abs(o) >= 10) {
base = 10
} else if (Math.abs(o) >= 1) {
base = 1
} else {
const multiple = 1 / 0.1
base = Math.ceil(Math.abs(o) * multiple) / multiple
}
let calculatedValue
if (isMin) {
if (value < 0) {
calculatedValue = value + num * value
} else {
calculatedValue = value - num * value
}
} else {
if (value < 0) {
calculatedValue = value - num * value
} else {
calculatedValue = value + num * value
}
}
if (base === 0.1) {
return parseFloat(calculatedValue.toFixed(1))
} else if (isMin) {
return Math.floor(calculatedValue / base) * base
} else {
return Math.ceil(calculatedValue / base) * base
}
}
// 处理y轴最大最小值
export const yMethod = (arr: any) => {
const num = 0.2
const numList = dataProcessing(arr)
let maxValue = 0
let minValue = 0
let max = 0
let min = 0
maxValue = Math.max(...numList)
minValue = Math.min(...numList)
const o = maxValue - minValue == 0 ? maxValue : maxValue - minValue
min = calculateValue(o, minValue, num, true)
max = calculateValue(o, maxValue, num, false)
return [min, max]
}

View File

@@ -0,0 +1,265 @@
<template>
<!-- 历史趋势数据 -->
<div class="history_chart">
<MyEchart ref="historyChart" :options="echartsData"/>
</div>
</template>
<script lang="ts" setup>
import { ref, watch } from 'vue'
import { yMethod } from '@/utils/echartMethod'
import MyEchart from '@/components/echarts/line/index.vue'
import { CheckData } from '@/api/check/interface'
const prop = defineProps({
tableData: {
type: Array as () => CheckData.TableRow[],
default: []
},
})
// 监听 tableData 变化并触发 setEchart
watch(() => prop.tableData, (newTableData) => {
console.log("🚀 ~ .then ~ newTableData:", newTableData)
// // 更新 chartsList 数据
// chartsList.value = newTableData
// // 调用 setEchart 更新图表
// setEchart()
}, {
immediate: true, // 立即执行一次
deep: true // 深度监听
})
const color = [
'var(--el-color-primary)',
'#07CCCA',
'#00BFF5',
'#FFBF00',
'#77DA63',
'#D5FF6B',
'#Ff6600',
'#FF9100',
'#5B6E96',
'#66FFCC',
'#B3B3B3'
]
const chartsList = ref<any>([])
const echartsData = ref<any>(null)
//初始化趋势图
const lineStyle = [{ type: 'solid' }, { type: 'dashed' }, { type: 'dotted' }]
const setEchart = () => {
echartsData.value = {}
//icon图标替换legend图例
// y轴单位数组
let unitList: any = []
let groupedData = chartsList.value.reduce((acc: any, item: any) => {
let key = ''
if (item.phase == null) {
key = item.unit
} else {
key = item.anotherName
}
if (!acc[key]) {
acc[key] = []
}
acc[key].push(item)
return acc
}, {})
let result = Object.values(groupedData)
console.log("🚀 ~ .then ~ result:", result)
if (chartsList.value.length > 0) {
unitList = result.map((item: any) => {
return item[0].unit
})
}
echartsData.value = {
legend: {
itemWidth: 20,
itemHeight: 20,
itemStyle: { opacity: 0 }, //去圆点
type: 'scroll', // 开启滚动分页
// orient: 'vertical', // 垂直排列
top: 5,
right: 70
// width: 550,
// height: 50
},
grid: {
top: '80px'
},
tooltip: {
axisPointer: {
type: 'cross',
label: {
color: '#fff',
fontSize: 16
}
},
textStyle: {
color: '#fff',
fontStyle: 'normal',
opacity: 0.35,
fontSize: 14
},
backgroundColor: 'rgba(0,0,0,0.55)',
borderWidth: 0,
formatter(params: any) {
const xname = params[0].value[0]
let str = `${xname}<br>`
params.forEach((el: any, index: any) => {
let marker = ''
if (el.value[3] == 'dashed') {
for (let i = 0; i < 3; i++) {
marker += `<span style="display:inline-block;border: 2px ${el.color} solid;margin-right:5px;width:10px;height:0px;background-color:#ffffff00;"></span>`
}
} else {
marker = `<span style="display:inline-block;border: 2px ${el.color} ${el.value[3]};margin-right:5px;width:40px;height:0px;background-color:#ffffff00;"></span>`
}
let unit = el.value[2] ? el.value[2] : ''
str += `${marker}${el.seriesName.split('(')[0]}${el.value[1]}${unit}
<br>`
})
return str
}
},
color: ['#DAA520', '#2E8B57', '#A52a2a', ...color],
xAxis: {
type: 'time',
axisLabel: {
formatter: {
day: '{MM}-{dd}',
month: '{MM}',
year: '{yyyy}'
}
}
},
yAxis: [{}],
options: {
series: []
}
}
if (chartsList.value.length > 0) {
let yData: any = []
echartsData.value.yAxis = []
let setList = [...new Set(unitList)]
setList.forEach((item: any, index: any) => {
if (index > 2) {
echartsData.value.grid.right = (index - 1) * 80
}
yData.push([])
let right = {
position: 'right',
offset: (index - 1) * 80
}
echartsData.value.yAxis.push({
name: item,
yAxisIndex: index,
splitNumber: 5,
minInterval: 1,
splitLine: {
show: false
},
...(index > 0 ? right : null)
})
})
let ABCName = [
...new Set(
chartsList.value.map((item: any) => {
return item.anotherName == '电压负序分量'
? '电压不平衡'
: item.anotherName == '电压正序分量'
? '电压不平衡'
: item.anotherName == '电压零序分量'
? '电压不平衡'
: item.anotherName
})
)
]
result.forEach((item: any, index: any) => {
let yMethodList: any = []
let ABCList = Object.values(
item.reduce((acc, item) => {
let key = ''
if (item.phase == null) {
key = item.anotherName
} else {
key = item.phase
}
if (!acc[key]) {
acc[key] = []
}
acc[key].push(item)
return acc
}, {})
)
ABCList.forEach((kk: any) => {
let colorName = kk[0].phase?.charAt(0).toUpperCase()
let lineS = ABCName.findIndex(
item =>
item ===
(kk[0].anotherName == '电压负序分量'
? '电压不平衡'
: kk[0].anotherName == '电压正序分量'
? '电压不平衡'
: kk[0].anotherName == '电压零序分量'
? '电压不平衡'
: kk[0].anotherName)
)
let seriesList: any = []
kk.forEach((cc: any) => {
if (cc.statisticalData !== null) {
yData[setList.indexOf(kk[0].unit)].push(cc.statisticalData?.toFixed(2))
}
seriesList.push([cc.time, cc.statisticalData?.toFixed(2), cc.unit, lineStyle[lineS].type])
})
echartsData.value.options.series.push({
name: kk[0].phase ? kk[0].phase + '相' + kk[0].anotherName : kk[0].anotherName,
type: 'line',
smooth: true,
color:
colorName == 'A' ? '#DAA520' : colorName == 'B' ? '#2E8B57' : colorName == 'C' ? '#A52a2a' : '',
symbol: 'none',
data: seriesList,
lineStyle: lineStyle[lineS],
yAxisIndex: setList.indexOf(kk[0].unit)
})
})
// let [min, max] = yMethod(yMethodList)
// echartsData.value.yAxis[index].min = min
// echartsData.value.yAxis[index].max = max
})
yData.forEach((item: any, index: any) => {
let [min, max] = yMethod(item)
echartsData.value.yAxis[index].min = min
echartsData.value.yAxis[index].max = max
})
// console.log("🚀 ~ result.forEach ~ echartsData.value:", echartsData.value)
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@@ -160,6 +160,12 @@
:currentScriptTypeName="currentScriptTypeName"
/>
</el-tab-pane>
<el-tab-pane label="历史趋势" name="chartTab">
<CompareDataCheckChart
v-if="activeTab === 'chartTab'"
:tableData="rawTableData.length == 0 ? [] : currentRawTableData"
/>
</el-tab-pane>
</el-tabs>
</div>
</div>
@@ -172,6 +178,7 @@ import { dialogBig } from '@/utils/elementBind'
import { computed, reactive, ref } from 'vue'
import CompareDataCheckResultTable from './compareDataCheckResultTable.vue'
import CompareDataCheckRawDataTable from './compareDataCheckRawDataTable.vue'
import CompareDataCheckChart from './compareDataCheckChart.vue'
import { CheckData } from '@/api/check/interface'
import { useCheckStore } from '@/stores/modules/check'
import { Histogram, Postcard } from '@element-plus/icons-vue'