WIP: 绘制监控图表
This commit is contained in:
parent
12f010ecb8
commit
20aad9d71d
|
@ -59,6 +59,9 @@ export default {
|
|||
if (val) {
|
||||
this.innerFullscreen = false
|
||||
}
|
||||
},
|
||||
innerFullscreen(val) {
|
||||
this.$emit('fullscreen', val)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -57,9 +57,6 @@ import CustomModal from '@/components/CustomModal'
|
|||
import CustomDatePicker from '@/components/CustomDatePicker'
|
||||
import CustomMonthPicker from '@/components/CustomMonthPicker'
|
||||
import CustomEmpty from '@/components/CustomEmpty'
|
||||
import CustomChart from '@/components/CustomChart'
|
||||
console.log('%c [ CustomChart ]-61', 'font-size:13px; background:pink; color:#bf2c9f;', CustomChart)
|
||||
|
||||
|
||||
Vue.prototype.rules = rules
|
||||
Vue.config.productionTip = false
|
||||
|
@ -81,7 +78,6 @@ Vue.component('custom-modal', CustomModal)
|
|||
Vue.component('custom-date-picker', CustomDatePicker)
|
||||
Vue.component('custom-month-picker', CustomMonthPicker)
|
||||
Vue.component('custom-empty', CustomEmpty)
|
||||
Vue.component('custom-chart', CustomChart)
|
||||
|
||||
SSO.init(() => {
|
||||
main()
|
||||
|
|
|
@ -127,6 +127,7 @@
|
|||
title="Data Recevice status Monitoring"
|
||||
:width="1230"
|
||||
:showFooter="false"
|
||||
@fullscreen="onModalFullScreen"
|
||||
>
|
||||
<div class="data-receive-status">
|
||||
<!-- 左侧配置栏 -->
|
||||
|
@ -184,7 +185,20 @@
|
|||
|
||||
<!-- 右侧图表展示栏 -->
|
||||
<div class="data-receive-status-chart" :class="{ 'on-screen': !leftPaneShow }">
|
||||
<custom-chart :option="option"></custom-chart>
|
||||
<!-- 图例 -->
|
||||
<div class="legend">
|
||||
<div class="legend-item" v-for="(legend, index) in legendList" :key="index">
|
||||
<span class="legend-item-color" :style="{ backgroundColor: legend.color }"></span>
|
||||
<span>{{ legend.title }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 图例结束 -->
|
||||
<template v-if="showChart">
|
||||
<template v-for="(item, index) in statusList">
|
||||
<RealTimeDataChart :legendList="legendList" :title="item.title" :key="index" />
|
||||
<a-divider :key="index + '_divider'" v-if="index !== statusList.length - 1"></a-divider>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
<!-- 右侧图表展示栏结束 -->
|
||||
</div>
|
||||
|
@ -196,7 +210,7 @@
|
|||
import CustomModal from '@/components/CustomModal/index.vue'
|
||||
import FilterImage from './filterImage'
|
||||
import CustomTree from '@/components/CustomTree/index.vue'
|
||||
import * as echarts from 'echarts'
|
||||
import RealTimeDataChart from './RealTimeDataChart.vue'
|
||||
|
||||
// Filter中的筛选列表
|
||||
const filterList = [
|
||||
|
@ -339,122 +353,39 @@ const dataSource = [
|
|||
}
|
||||
]
|
||||
|
||||
var data = []
|
||||
var dataCount = 10
|
||||
var startTime = +new Date()
|
||||
var categories = ['categoryA', 'categoryB', 'categoryC']
|
||||
var types = [
|
||||
{ name: 'JS Heap', color: '#7b9ce1' },
|
||||
{ name: 'Documents', color: '#bd6d6c' },
|
||||
{ name: 'Nodes', color: '#75d874' },
|
||||
{ name: 'Listeners', color: '#e0bc78' },
|
||||
{ name: 'GPU Memory', color: '#dc77dc' },
|
||||
{ name: 'GPU', color: '#72b362' }
|
||||
const legendList = [
|
||||
{
|
||||
title: 'SPHDPREL',
|
||||
color: '#17a840'
|
||||
},
|
||||
{
|
||||
title: 'SPHDF',
|
||||
color: '#0cbfb0'
|
||||
},
|
||||
{
|
||||
title: 'QC',
|
||||
color: '#1c82eb'
|
||||
},
|
||||
{
|
||||
title: 'GASBKPHDPREL',
|
||||
color: '#d3ad16'
|
||||
},
|
||||
{
|
||||
title: 'GASBKPHDF',
|
||||
color: '#db6423'
|
||||
},
|
||||
{
|
||||
title: 'SOH/MET',
|
||||
color: '#8852da'
|
||||
}
|
||||
]
|
||||
|
||||
// Generate mock data
|
||||
categories.forEach(function(category, index) {
|
||||
var baseTime = startTime
|
||||
for (var i = 0; i < dataCount; i++) {
|
||||
var typeItem = types[Math.round(Math.random() * (types.length - 1))]
|
||||
var duration = Math.round(Math.random() * 10000)
|
||||
data.push({
|
||||
name: typeItem.name,
|
||||
value: [index, baseTime, (baseTime += duration), duration],
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: typeItem.color
|
||||
}
|
||||
}
|
||||
})
|
||||
baseTime += Math.round(Math.random() * 2000)
|
||||
}
|
||||
})
|
||||
const statusList = [{
|
||||
title: 'JPX38 23803',
|
||||
|
||||
function renderItem(params, api) {
|
||||
var categoryIndex = api.value(0)
|
||||
var start = api.coord([api.value(1), categoryIndex])
|
||||
var end = api.coord([api.value(2), categoryIndex])
|
||||
var height = api.size([0, 1])[1] * 0.6
|
||||
|
||||
var 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',
|
||||
transition: ['shape'],
|
||||
shape: rectShape,
|
||||
style: api.style()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const option = {
|
||||
tooltip: {
|
||||
formatter: function(params) {
|
||||
return params.marker + params.name + ': ' + params.value[3] + ' ms'
|
||||
}
|
||||
},
|
||||
title: {
|
||||
text: '2021-9-10 性能分析',
|
||||
left: 'center'
|
||||
},
|
||||
dataZoom: [
|
||||
{
|
||||
type: 'slider',
|
||||
filterMode: 'weakFilter',
|
||||
showDataShadow: false,
|
||||
top: 10,
|
||||
labelFormatter: ''
|
||||
},
|
||||
{
|
||||
type: 'inside',
|
||||
filterMode: 'weakFilter'
|
||||
}
|
||||
],
|
||||
grid: {
|
||||
height: 300
|
||||
},
|
||||
xAxis: {
|
||||
min: startTime,
|
||||
scale: true,
|
||||
axisLabel: {
|
||||
formatter: function(val) {
|
||||
return Math.max(0, val - startTime) + 'ms'
|
||||
}
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
data: categories
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: 'custom',
|
||||
renderItem: renderItem,
|
||||
itemStyle: {
|
||||
opacity: 0.8
|
||||
},
|
||||
encode: {
|
||||
x: [1, 2],
|
||||
y: 0
|
||||
},
|
||||
data: data
|
||||
}
|
||||
]
|
||||
}
|
||||
}, {
|
||||
title: 'JPX38 23804'
|
||||
}]
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
@ -469,7 +400,8 @@ export default {
|
|||
},
|
||||
components: {
|
||||
CustomModal,
|
||||
CustomTree
|
||||
CustomTree,
|
||||
RealTimeDataChart
|
||||
},
|
||||
data() {
|
||||
this.columns = columns
|
||||
|
@ -489,14 +421,16 @@ export default {
|
|||
|
||||
leftPaneShow: true, // 左侧抽屉
|
||||
|
||||
option // echarts配置
|
||||
legendList, // 图例列表
|
||||
statusList,
|
||||
showChart: true
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.initParentProps()
|
||||
this.initParentMapProps()
|
||||
},
|
||||
methods: {
|
||||
initParentProps() {
|
||||
initParentMapProps() {
|
||||
const { getZoom, setZoom, maxZoom, minZoom } = this.$parent
|
||||
this.getZoom = getZoom
|
||||
this.setZoom = setZoom
|
||||
|
@ -545,6 +479,13 @@ export default {
|
|||
if (zoom > this.minZoom) {
|
||||
this.setZoom(zoom - 1)
|
||||
}
|
||||
},
|
||||
|
||||
onModalFullScreen() {
|
||||
this.showChart = false
|
||||
this.$nextTick(() => {
|
||||
this.showChart = true
|
||||
})
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -920,12 +861,42 @@ export default {
|
|||
right: 15px;
|
||||
width: calc(100% - 270px);
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
padding: 0 15px 10px;
|
||||
border: 1px solid @borderColor;
|
||||
transition: width 0.3s cubic-bezier(0.075, 0.82, 0.165, 1);
|
||||
|
||||
&.on-screen {
|
||||
width: calc(100% - 30px);
|
||||
}
|
||||
|
||||
.ant-divider {
|
||||
margin: 34px 0 40px;
|
||||
background-color: rgba(65, 111, 127, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
.legend {
|
||||
margin: 32px 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
||||
&-item {
|
||||
color: #ade6ee;
|
||||
line-height: 12px;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
&-color {
|
||||
display: inline-block;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 4px;
|
||||
margin-right: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
113
src/views/stationOperation/components/RealTimeDataChart.vue
Normal file
113
src/views/stationOperation/components/RealTimeDataChart.vue
Normal file
|
@ -0,0 +1,113 @@
|
|||
<template>
|
||||
<v-chart :force-fit="true" :height="height" :data="dataSource" :padding="[0, 0, 40, 60]">
|
||||
<v-axis
|
||||
data-key="name"
|
||||
:title="{ text: title, textStyle: { fill: '#5b9cba', fontSize: 14 }, offset: 45 }"
|
||||
:label="{ textStyle: { fill: '#ade6ee' } }"
|
||||
:grid="{ lineStyle: { stroke: '#406979', strokeOpacity: 0.2, lineDash: [0, 0] } }"
|
||||
:line="{ stroke: '#406979', strokeOpacity: 0.5 }"
|
||||
/>
|
||||
<v-axis
|
||||
data-key="time"
|
||||
:label="{ textStyle: { fill: '#ade6ee' }, offset: 25 }"
|
||||
:grid="{ lineStyle: { stroke: '#406979', strokeOpacity: 0.2, lineDash: [0, 0] }, hideLastLine: true }"
|
||||
:line="{ stroke: '#406979', strokeOpacity: 0.5 }"
|
||||
:tick-line="null"
|
||||
/>
|
||||
<v-polygon position="time*name" shape="custom" :v-style="{ lineWidth: 0 }" />
|
||||
</v-chart>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { registerShape } from 'viser-vue'
|
||||
|
||||
registerShape('polygon', 'custom', {
|
||||
draw: function(cfg, container) {
|
||||
const color = cfg.origin._origin.color // 颜色,取自datasource原始数据中的color
|
||||
|
||||
// 绘制色块
|
||||
return color
|
||||
? container.addShape('rect', {
|
||||
attrs: {
|
||||
x: cfg.x - 32,
|
||||
y: cfg.y - 10,
|
||||
width: 32,
|
||||
height: 20,
|
||||
fill: color,
|
||||
stroke: color
|
||||
}
|
||||
})
|
||||
: null
|
||||
}
|
||||
})
|
||||
|
||||
const timeList = [
|
||||
'08:00\n04/06',
|
||||
'10:00\n04/06',
|
||||
'12:00\n04/06',
|
||||
'14:00\n04/06',
|
||||
'16:00\n04/06',
|
||||
'18:00\n04/06',
|
||||
'20:00\n04/06',
|
||||
'22:00\n04/06',
|
||||
'00:00\n04/07',
|
||||
'02:00\n04/07',
|
||||
'04:00\n04/07',
|
||||
'06:00\n04/07',
|
||||
// '08:00\n04/07'
|
||||
]
|
||||
|
||||
const typeList = ['MET', 'SOH', 'QC', 'PHD']
|
||||
|
||||
export default {
|
||||
props: {
|
||||
legendList: {
|
||||
type: Array
|
||||
},
|
||||
height: {
|
||||
type: Number,
|
||||
default: 250
|
||||
},
|
||||
title: {
|
||||
type: String
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dataSource: []
|
||||
}
|
||||
},
|
||||
created() {
|
||||
const dataSource = typeList.reduce((prev, type) => {
|
||||
return prev.concat(
|
||||
timeList.map(time => {
|
||||
return {
|
||||
name: type,
|
||||
color: '',
|
||||
time
|
||||
}
|
||||
})
|
||||
)
|
||||
}, [])
|
||||
|
||||
dataSource[36].color = '#d3ad16'
|
||||
dataSource[37].color = '#d3ad16'
|
||||
dataSource[38].color = '#d3ad16'
|
||||
dataSource[39].color = '#d3ad16'
|
||||
dataSource[40].color = '#db6423'
|
||||
dataSource[41].color = '#17a840'
|
||||
dataSource[42].color = '#17a840'
|
||||
dataSource[43].color = '#17a840'
|
||||
dataSource[44].color = '#17a840'
|
||||
dataSource[45].color = '#17a840'
|
||||
dataSource[46].color = '#8c6513'
|
||||
dataSource[47].color = '#d3ad16'
|
||||
dataSource[28].color = '#1c82eb'
|
||||
dataSource[34].color = '#1c82eb'
|
||||
|
||||
this.dataSource = dataSource
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style></style>
|
Loading…
Reference in New Issue
Block a user