NEZ-3278 perf:stat chart 样式优化
This commit is contained in:
6
nezha-fronted/package-lock.json
generated
6
nezha-fronted/package-lock.json
generated
@@ -22765,9 +22765,9 @@
|
|||||||
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
|
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
|
||||||
},
|
},
|
||||||
"tinycolor2": {
|
"tinycolor2": {
|
||||||
"version": "1.4.2",
|
"version": "1.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz",
|
||||||
"integrity": "sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA=="
|
"integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw=="
|
||||||
},
|
},
|
||||||
"tinyqueue": {
|
"tinyqueue": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
|
|||||||
@@ -92,6 +92,7 @@
|
|||||||
"showdown": "^2.1.0",
|
"showdown": "^2.1.0",
|
||||||
"spark-md5": "^3.0.2",
|
"spark-md5": "^3.0.2",
|
||||||
"speed-measure-webpack-plugin": "^1.5.0",
|
"speed-measure-webpack-plugin": "^1.5.0",
|
||||||
|
"tinycolor2": "^1.6.0",
|
||||||
"uplot": "^1.6.26",
|
"uplot": "^1.6.26",
|
||||||
"uplot-vue": "^1.1.5",
|
"uplot-vue": "^1.1.5",
|
||||||
"v-selectpage": "^2.1.4",
|
"v-selectpage": "^2.1.4",
|
||||||
|
|||||||
@@ -556,6 +556,10 @@
|
|||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
position: relative;
|
position: relative;
|
||||||
border: 1px solid $--background-color-empty;
|
border: 1px solid $--background-color-empty;
|
||||||
|
.stat-text{
|
||||||
|
text-align: center;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
.sparkline{
|
.sparkline{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 40%;
|
height: 40%;
|
||||||
|
|||||||
@@ -16,43 +16,52 @@
|
|||||||
background:item.mapping ? item.mapping.color.bac : (statData.length===1 ? '' : colorList[index]),
|
background:item.mapping ? item.mapping.color.bac : (statData.length===1 ? '' : colorList[index]),
|
||||||
height:item.height+'px',
|
height:item.height+'px',
|
||||||
width:item.width + 'px',
|
width:item.width + 'px',
|
||||||
fontSize: item.fontSize + 'px',
|
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<div style="maxWidth:100%;z-index: 10;">
|
<div style="maxWidth:100%;z-index: 10;">
|
||||||
<!-- all -->
|
<!-- all -->
|
||||||
<template v-if="chartInfo.param.text==='all'">
|
<template v-if="chartInfo.param.text==='all'">
|
||||||
<div v-if="item.mapping" :style="{color:item.mapping.color.text}">
|
<div v-if="item.mapping" :style="{color:item.mapping.color.text}">
|
||||||
<p style="white-space: nowrap;">{{item.legend}}</p>
|
<p class="stat-text" :style="{fontSize: item.titleFontSize + 'px'}">{{item.legend}}</p>
|
||||||
<template v-if="item.mapping && item.mapping.icon">
|
<p class="stat-text" :style="{fontSize: item.valueFontSize + 'px'}">
|
||||||
<i :class="item.mapping.icon" :style="{color: item.mapping.color.icon,fontSize:'1em'}"></i>
|
<template v-if="item.mapping && item.mapping.icon">
|
||||||
</template>
|
<i :class="item.mapping.icon" :style="{color: item.mapping.color.icon,fontSize:'1em'}"></i>
|
||||||
<span style="white-space: nowrap;">{{handleDisplay(item.mapping.display, { ...item.label, value: item.showValue })}}</span>
|
</template>
|
||||||
|
<span>{{handleDisplay(item.mapping.display, { ...item.label, value: item.showValue })}}</span>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
<p style="white-space: nowrap;">{{item.legend}}</p>
|
<p class="stat-text" :style="{fontSize: item.titleFontSize + 'px'}">{{item.legend}}</p>
|
||||||
<span style="white-space: nowrap;">{{item.showValue}}</span>
|
<p class="stat-text" :style="{fontSize: item.valueFontSize + 'px'}">{{item.showValue}}</p>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<!-- legend -->
|
<!-- legend -->
|
||||||
<template v-if="chartInfo.param.text==='legend'">
|
<template v-if="chartInfo.param.text==='legend'">
|
||||||
<div v-if="item.mapping" :style="{color:item.mapping.color.text}">
|
<div v-if="item.mapping" :style="{color:item.mapping.color.text}">
|
||||||
<template v-if="item.mapping && item.mapping.icon">
|
<p class="stat-text" :style="{fontSize: item.valueFontSize + 'px'}">
|
||||||
<i :class="item.mapping.icon" :style="{color: item.mapping.color.icon,fontSize:'1em'}"></i>
|
<template v-if="item.mapping && item.mapping.icon">
|
||||||
</template>
|
<i :class="item.mapping.icon" :style="{color: item.mapping.color.icon,fontSize:'1em'}"></i>
|
||||||
<span style="white-space: nowrap;">{{item.legend}}</span>
|
</template>
|
||||||
|
<span>{{item.legend}}</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
<p class="stat-text" :style="{fontSize: item.valueFontSize + 'px'}">{{item.legend}}</p>
|
||||||
</div>
|
</div>
|
||||||
<div v-else style="white-space: nowrap;">{{item.legend}}</div>
|
|
||||||
</template>
|
</template>
|
||||||
<!-- value -->
|
<!-- value -->
|
||||||
<template v-if="chartInfo.param.text==='value'|| !chartInfo.param.text">
|
<template v-if="chartInfo.param.text==='value'|| !chartInfo.param.text">
|
||||||
<div v-if="item.mapping" :style="{color:item.mapping.color.text}">
|
<div v-if="item.mapping" :style="{color:item.mapping.color.text}">
|
||||||
<template v-if="item.mapping && item.mapping.icon">
|
<p class="stat-text" :style="{fontSize: item.valueFontSize + 'px'}">
|
||||||
<i :class="item.mapping.icon" :style="{color: item.mapping.color.icon,fontSize:'1em'}"></i>
|
<template v-if="item.mapping && item.mapping.icon">
|
||||||
</template>
|
<i :class="item.mapping.icon" :style="{color: item.mapping.color.icon,fontSize:'1em'}"></i>
|
||||||
<span style="white-space: nowrap;">{{handleDisplay(item.mapping.display, { ...item.label, value: item.showValue })}}</span>
|
</template>
|
||||||
|
<span>{{handleDisplay(item.mapping.display, { ...item.label, value: item.showValue })}}</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div v-else style="white-space: nowrap;">
|
||||||
|
<p class="stat-text" :style="{fontSize: item.valueFontSize + 'px'}">{{item.showValue}}</p>
|
||||||
</div>
|
</div>
|
||||||
<div v-else style="white-space: nowrap;">{{item.showValue}}</div>
|
|
||||||
</template>
|
</template>
|
||||||
<!-- none -->
|
<!-- none -->
|
||||||
<template v-if="chartInfo.param.text==='none'"></template>
|
<template v-if="chartInfo.param.text==='none'"></template>
|
||||||
@@ -118,7 +127,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span class="temp-dom--12" ref="temp-dom"></span>
|
<span class="temp-dom" ref="temp-dom"></span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -133,6 +142,7 @@ import { initColor } from '@/components/chart/chart/tools'
|
|||||||
import * as echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import chartSparklineOption from './options/chartSparkline'
|
import chartSparklineOption from './options/chartSparkline'
|
||||||
import lodash from 'lodash'
|
import lodash from 'lodash'
|
||||||
|
import tinycolor from 'tinycolor2'
|
||||||
export default {
|
export default {
|
||||||
name: 'chart-stat',
|
name: 'chart-stat',
|
||||||
mixins: [chartMixin, chartFormat],
|
mixins: [chartMixin, chartFormat],
|
||||||
@@ -291,7 +301,6 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
renderStat (layout) {
|
renderStat (layout) {
|
||||||
let isDouble = false
|
|
||||||
const width = this.boxWidth / layout.col
|
const width = this.boxWidth / layout.col
|
||||||
const height = this.boxHeight / layout.row
|
const height = this.boxHeight / layout.row
|
||||||
const integer = Math.floor(this.statData.length / layout.col)
|
const integer = Math.floor(this.statData.length / layout.col)
|
||||||
@@ -305,86 +314,62 @@ export default {
|
|||||||
} else {
|
} else {
|
||||||
item.width = width
|
item.width = width
|
||||||
}
|
}
|
||||||
let font = '' // 获取显示的字体
|
|
||||||
let display = ''
|
let display = ''
|
||||||
if (item.mapping) {
|
if (item.mapping) {
|
||||||
display = this.handleDisplay(item.mapping.display, { ...item.label, value: item.showValue })
|
display = this.handleDisplay(item.mapping.display, { ...item.label, value: item.showValue })
|
||||||
}
|
}
|
||||||
|
let titleFont = ''
|
||||||
|
let valueFont = ''
|
||||||
|
let titleFontSize = ''
|
||||||
|
let valueFontSize = ''
|
||||||
|
const padding = 10
|
||||||
switch (this.chartInfo.param.text) {
|
switch (this.chartInfo.param.text) {
|
||||||
case 'all':
|
case 'all':
|
||||||
|
titleFont = item.legend
|
||||||
if (item.mapping) {
|
if (item.mapping) {
|
||||||
isDouble = true
|
valueFont = display
|
||||||
if (item.legend.length > item.showValue.length + 2) {
|
if (item.mapping.icon) {
|
||||||
font = item.legend
|
valueFont += 'AA'
|
||||||
} else {
|
|
||||||
font = display
|
|
||||||
if (item.mapping.icon) {
|
|
||||||
font += 'AA'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
isDouble = true
|
valueFont = item.showValue
|
||||||
if (item.legend.length > item.showValue.length) {
|
|
||||||
font = item.legend
|
|
||||||
} else {
|
|
||||||
font = item.showValue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
titleFontSize = this.calculateFontSize(titleFont, (item.width - padding * 2), (item.height - padding * 2) * 0.4, 30)
|
||||||
|
valueFontSize = this.calculateFontSize(valueFont, (item.width - padding * 2), (item.height - padding * 2) * 0.4)
|
||||||
|
titleFontSize = Math.min(valueFontSize * 0.7, titleFontSize)
|
||||||
break
|
break
|
||||||
case 'legend':
|
case 'legend':
|
||||||
|
titleFont = item.legend
|
||||||
if (item.mapping) {
|
if (item.mapping) {
|
||||||
isDouble = true
|
if (item.mapping.icon) {
|
||||||
if (item.legend.length > item.showValue.length + 2) {
|
titleFont += 'AA'
|
||||||
font = item.legend
|
|
||||||
} else {
|
|
||||||
font = display
|
|
||||||
if (item.mapping.icon) {
|
|
||||||
font += 'AA'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
font = item.legend
|
|
||||||
}
|
}
|
||||||
|
valueFontSize = this.calculateFontSize(titleFont, (item.width - padding * 2), (item.height - padding * 2) * 0.4)
|
||||||
break
|
break
|
||||||
|
|
||||||
case 'none':
|
case 'none':
|
||||||
font = ''
|
titleFontSize = ''
|
||||||
|
valueFontSize = ''
|
||||||
break
|
break
|
||||||
case 'value':
|
case 'value':
|
||||||
default:
|
default:
|
||||||
if (item.mapping) {
|
if (item.mapping) {
|
||||||
font = display
|
valueFont = display
|
||||||
if (item.mapping.icon) {
|
if (item.mapping.icon) {
|
||||||
font += 'AA'
|
valueFont += 'AA'
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
font = item.showValue
|
valueFont = item.showValue
|
||||||
}
|
}
|
||||||
|
valueFontSize = this.calculateFontSize(valueFont, (item.width - padding * 2), (item.height - padding * 2) * 0.4)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
const el = this.$refs['temp-dom']
|
item.titleFontSize = titleFontSize
|
||||||
el.innerText = font
|
item.valueFontSize = valueFontSize
|
||||||
const elWidth = el.offsetWidth
|
|
||||||
const elHeight = el.offsetHeight
|
|
||||||
const dimension = Math.min(item.width, item.height * 1.3)
|
|
||||||
const fontScale = parseInt('70%', 10) / 100
|
|
||||||
let fontSize = Math.min(dimension / 5, 100) * fontScale
|
|
||||||
let scale = item.width / elWidth
|
|
||||||
if (scale * elHeight > item.height) {
|
|
||||||
scale = item.height / elHeight
|
|
||||||
}
|
|
||||||
if (isDouble) {
|
|
||||||
if (scale * elHeight * 2.5 > item.height) {
|
|
||||||
scale = item.height / elHeight * 2.5
|
|
||||||
}
|
|
||||||
}
|
|
||||||
item.scale = scale < 1 ? 1 : parseFloat(scale)
|
|
||||||
fontSize = fontSize > 12 ? fontSize : this.minFontSzie
|
|
||||||
item.fontSize = fontSize
|
|
||||||
|
|
||||||
if (fontSize > 36) {
|
if (item.valueFontSize > 36) {
|
||||||
item.comparisonFont = 16
|
item.comparisonFont = 16
|
||||||
} else if (fontSize > 24) {
|
} else if (item.valueFontSize > 24) {
|
||||||
item.comparisonFont = 14
|
item.comparisonFont = 14
|
||||||
} else {
|
} else {
|
||||||
item.comparisonFont = 12
|
item.comparisonFont = 12
|
||||||
@@ -392,28 +377,43 @@ export default {
|
|||||||
})
|
})
|
||||||
this.isInit = false
|
this.isInit = false
|
||||||
},
|
},
|
||||||
|
|
||||||
|
calculateFontSize (text, width, height, maxSize, lineHeight = 1.2) {
|
||||||
|
const el = this.$refs['temp-dom']
|
||||||
|
el.innerText = text
|
||||||
|
const elWidth = el.offsetWidth
|
||||||
|
const fontSizeBasedOnWidth = (width / (elWidth + 2)) * 14
|
||||||
|
const fontSizeBasedOnHeight = height / lineHeight
|
||||||
|
|
||||||
|
const optimalSize = Math.min(fontSizeBasedOnHeight, fontSizeBasedOnWidth)
|
||||||
|
return Math.min(optimalSize, maxSize || optimalSize)
|
||||||
|
},
|
||||||
|
|
||||||
// 绘制图表
|
// 绘制图表
|
||||||
drawChart () {
|
drawChart () {
|
||||||
this.statData.forEach((item, index) => {
|
this.statData.forEach((item, index) => {
|
||||||
const chart = this.sparkline[index] ? this.sparkline[index] : echarts.init(document.getElementById(`chart-canvas-${this.chartId}-${index}`))
|
const chart = this.sparkline[index] ? this.sparkline[index] : echarts.init(document.getElementById(`chart-canvas-${this.chartId}-${index}`))
|
||||||
const chartOption = lodash.cloneDeep(chartSparklineOption)
|
const chartOption = lodash.cloneDeep(chartSparklineOption)
|
||||||
// sparkline 颜色和 字体颜色 保持一致
|
|
||||||
const theme = localStorage.getItem(`nz-user-${localStorage.getItem('nz-user-id')}-theme`) || 'light'
|
// sparkline 颜色根据背景色计算
|
||||||
let color = theme === 'light' ? '#666666' : '#BEBEBE'
|
const color = item.mapping ? item.mapping.color.bac : this.colorList[index]
|
||||||
if (item.mapping) {
|
const lineColor = tinycolor(color).brighten(40).toRgbString()
|
||||||
color = item.mapping.color.text
|
let areaColor = 'rgba(255,255,255,0.4)'
|
||||||
|
if (this.statData.length === 1 && !item.mapping) {
|
||||||
|
areaColor = tinycolor(color).setAlpha(0.2).toRgbString()
|
||||||
}
|
}
|
||||||
|
|
||||||
chartOption.series = [{
|
chartOption.series = [{
|
||||||
...chartOption.series[0],
|
...chartOption.series[0],
|
||||||
data: item.data,
|
data: item.data,
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
color
|
width: 1,
|
||||||
|
color: lineColor
|
||||||
}
|
}
|
||||||
}]
|
}]
|
||||||
if (this.chartInfo.param.sparklineMode === 'area') {
|
if (this.chartInfo.param.sparklineMode === 'area') {
|
||||||
chartOption.series[0].areaStyle = {
|
chartOption.series[0].areaStyle = {
|
||||||
color: color,
|
color: areaColor
|
||||||
opacity: 0.1
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
chartOption.yAxis.max = this.maxValue
|
chartOption.yAxis.max = this.maxValue
|
||||||
|
|||||||
Reference in New Issue
Block a user