AnalysisSystemForRadionucli.../src/views/stationOperation/components/RealTimeDataChart.vue

382 lines
8.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div style="width: 100%; height: 100%; overflow: auto; padding-top: 76px">
<!-- 图例 -->
<div class="legend">
<div
class="legend-item"
:class="{ active: legend.isShow }"
v-for="(legend, index) in legendList"
:key="index"
@click="handleLegendChange(legend)"
>
<span class="legend-item-color" :style="{ backgroundColor: legend.color }"></span>
<span>{{ legend.title }}</span>
</div>
</div>
<!-- 图例结束 -->
<custom-chart
ref="customChartRef"
:option="option"
:opts="{ notMerge: true }"
:height="list.length * 295"
@dataZoom="handleZoomChange"
></custom-chart>
<a-spin style="z-index: 11; position: absolute; top: 45%; left: 48%" :spinning="spinning" />
</div>
</template>
<script>
import CustomChart from '@/components/CustomChart/index.vue'
import * as echarts from 'echarts'
import dayjs from 'dayjs'
import utc from 'dayjs/plugin/utc'
import { cloneDeep } from 'lodash'
dayjs.extend(utc)
const typeList = ['MET', 'SOH', 'QC', 'PHD'] //
// 自定义图例列表
const legendList = [
{
title: 'SPHDPREL',
color: '#17a840',
isShow: true,
},
{
title: 'SPHDF',
color: '#0cbfb0',
isShow: true,
},
{
title: 'QC',
color: '#1c82eb',
isShow: true,
},
{
title: 'GASBKPHDPREL',
color: '#d3ad16',
isShow: true,
},
{
title: 'GASBKPHDF',
color: '#db6423',
isShow: true,
},
{
title: 'SOH/MET',
color: '#8852da',
isShow: true,
},
]
// 图表配置
const initialOption = {
tooltip: {
formatter: (params) => {
// return `
// <div>${params.marker}${params.name}</div>
// <div>START${dayjs(new Date(params.value[4])).format('YYYY-MM-DD HH:mm:ss')}</div>
// <div style="white-space: pre"> END${dayjs(new Date(params.value[2])).format('YYYY-MM-DD HH:mm:ss')}</div>
// `
return `
<div>${params.marker}${params.name}</div>
<div>START${dayjs.utc(params.value[4]).format('YYYY-MM-DD HH:mm:ss')}</div>
<div style="white-space: pre"> END${dayjs.utc(params.value[2]).format('YYYY-MM-DD HH:mm:ss')}</div>
`
},
},
grid: [],
xAxis: [],
yAxis: [],
series: [],
dataZoom: [],
}
export default {
props: {
title: {
type: String,
},
spinning: {
type: Boolean,
},
list: {
type: Array,
default: () => [],
},
scaleSettings: {
type: Object,
required: true,
},
},
components: {
CustomChart,
},
data() {
return {
legendList: cloneDeep(legendList),
option: {},
zoomDataAll: [],
}
},
methods: {
handleZoomChange(params) {
this.zoomDataAll = this.option.dataZoom.map((item) => {
if (item.id == params.batch[0].dataZoomId) {
return {
id: params.batch[0].dataZoomId,
start: params.batch[0].start,
end: params.batch[0].end,
}
} else {
return item
}
})
},
renderItem(params, api) {
let categoryIndex = api.value(0)
let start = api.coord([api.value(1), categoryIndex])
let end = api.coord([api.value(2), categoryIndex])
let height = 20
let rectShape = echarts.graphic.clipRectByRect(
{
x: start[0],
y: start[1] - height / 2,
width: end[0] - start[0],
height: height,
},
{
x: params.coordSys.x,
y: params.coordSys.y,
width: params.coordSys.width,
height: params.coordSys.height,
}
)
return (
rectShape && {
type: 'rect',
shape: rectShape,
style: api.style(),
}
)
},
convertStatus(item) {
switch (item.status) {
case 'SFULL':
item.status = 'SPHDF'
break
case 'SPREL':
item.status = 'SPHDPREL'
break
case 'GPREL':
item.status = 'GASBKPHDPREL'
break
case 'GFULL':
item.status = 'GASBKPHDF'
break
case 'QC':
item.status = 'QC'
break
case 'SOH':
case 'MET':
item.status = 'SOH/MET'
break
}
},
initChartOption(val) {
let now = dayjs(new Date())
now = now.add(1, 'hour').set('minute', 0).set('second', 0).set('millisecond', 0)
const max = now.valueOf()
const min = max - this.scaleSettings.cacheTime * 24 * 60 * 60 * 1000
const option = cloneDeep(initialOption)
const { grid, xAxis, yAxis, series, dataZoom } = option
this.list.forEach((item, index) => {
grid.push({
left: 70,
right: 20,
top: 70 * index + 225 * index,
height: 225,
})
xAxis.push({
gridIndex: index,
min,
max,
interval: this.scaleSettings.scaleInterval * 60 * 1000,
axisLabel: {
show: true,
formatter: (val) => {
// let dateTime = new Date(val)
// return dayjs.utc(dateTime).format('HH:mm\nMM/DD')
return dayjs.utc(val).format('HH:mm\nMM/DD')
},
color: '#ade6ee',
},
splitLine: {
lineStyle: {
color: '#214751',
},
},
})
yAxis.push({
gridIndex: index,
name: item.title,
nameLocation: 'middle', // 设置标题位置为中间
nameTextStyle: {
// 设置标题样式
fontSize: 14,
color: '#5b9cba',
},
nameGap: 46,
data: typeList,
splitLine: {
show: true,
lineStyle: {
color: '#214751',
},
},
axisLine: {
lineStyle: {
color: '#214751',
},
},
axisTick: {
show: false,
},
axisLabel: {
color: '#ade6ee',
},
})
const data = []
item.dataList.forEach((item) => {
this.convertStatus(item)
let originalTime = new Date(item.beginTime * 1000).getTime()
let startTime = new Date(item.beginTime * 1000).getTime()
if (item.type == 'PHD') {
startTime = item.endTime * 1000 - 60 * 1000 * 30
}
const endTime = new Date(item.endTime * 1000).getTime()
const duration = endTime - startTime
const index = typeList.findIndex((type) => item.type == type)
const find = this.legendList.find((legendItem) => legendItem.title == item.status)
if (find.isShow) {
data.push({
name: item.status,
value: [index, startTime, endTime, duration, originalTime],
itemStyle: {
normal: {
color: find.color,
},
},
})
}
})
series.push({
type: 'custom',
renderItem: this.renderItem,
encode: {
x: [1, 2],
y: 0,
},
data: data,
xAxisIndex: index,
yAxisIndex: index,
})
if (!val) {
dataZoom.push({
type: 'inside',
id: index,
xAxisIndex: index,
start: 100 - (this.scaleSettings.timelineLength / (this.scaleSettings.cacheTime * 24 * 60)) * 100,
end: 100,
zoomLock: true,
})
}
})
this.option = option
},
// 图例控制图表
handleLegendChange(legend) {
legend.isShow = !legend.isShow
this.initChartOption()
this.option.dataZoom = this.zoomDataAll.map((item, index) => {
return {
type: 'inside',
id: item.id,
xAxisIndex: index,
start: item.start,
end: item.end,
zoomLock: true,
}
})
},
resize() {
this.$refs.customChartRef.resize()
},
},
watch: {
list: {
handler() {
this.initChartOption()
},
immediate: true,
},
},
}
</script>
<style lang="less" scoped>
.legend {
width: 100%;
padding: 25px 0;
display: flex;
justify-content: center;
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
background: #022024;
z-index: 11;
&-item {
color: #ade6ee;
line-height: 12px;
cursor: pointer;
user-select: none;
display: flex;
&:not(:last-child) {
margin-right: 30px;
}
&-color {
display: inline-block;
width: 12px;
height: 12px;
border-radius: 4px;
margin-right: 6px;
vertical-align: baseline;
filter: grayscale(1);
}
&.active {
.legend-item-color {
filter: grayscale(0);
}
}
}
}
</style>