Merge branch 'dev-3.2' of https://git.mesalab.cn/nezha/nezha-fronted into dev-3.2
This commit is contained in:
@@ -17,6 +17,13 @@
|
||||
:chart-option="chartOption"
|
||||
:is-fullscreen="isFullscreen"
|
||||
></chart-pie>
|
||||
<chart-bar
|
||||
v-if="isChartBar(chartInfo.type)"
|
||||
:chart-data="chartData"
|
||||
:chart-info="chartInfo"
|
||||
:chart-option="chartOption"
|
||||
:is-fullscreen="isFullscreen"
|
||||
></chart-bar>
|
||||
<chartHexagon
|
||||
:ref="'chart'+chartInfo.id"
|
||||
v-if="isHexagonFigure(chartInfo.type)"
|
||||
@@ -60,7 +67,7 @@ import chartTreemap from './chart/chartTreemap'
|
||||
import chartUrl from './chart/chartUrl'
|
||||
import chartValue from './chart/chartValue'
|
||||
import chartHexagon from './chart/chartHexagon'
|
||||
import { getOption, isTimeSeries, isHexagonFigure, isUrl, isText, isChartPie } from './chart/tools'
|
||||
import { getOption, isTimeSeries, isHexagonFigure, isUrl, isText, isChartPie, isChartBar } from './chart/tools'
|
||||
import lodash from 'lodash'
|
||||
|
||||
export default {
|
||||
@@ -109,6 +116,7 @@ export default {
|
||||
isTimeSeries,
|
||||
isHexagonFigure,
|
||||
isChartPie,
|
||||
isChartBar,
|
||||
isUrl,
|
||||
isText,
|
||||
resize () {
|
||||
|
||||
@@ -1,10 +1,229 @@
|
||||
<template>
|
||||
|
||||
<div
|
||||
:class="legendPlacement"
|
||||
ref="pie-chart-box"
|
||||
class="nz-chart__component nz-chart__component--time-series" @mouseenter="mouseEnterChart"
|
||||
@mouseleave="mouseLeaveChart"
|
||||
>
|
||||
<div :id="`chart-canvas-${chartId}`" class="chart__canvas"></div>
|
||||
<chart-legend
|
||||
v-if="hasLegend"
|
||||
:chart-data="chartData"
|
||||
:chart-info="chartInfo"
|
||||
:legends="legends"
|
||||
:is-fullscreen="isFullscreen"
|
||||
></chart-legend>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import legend from '@/components/chart/chart/legend'
|
||||
import chartMixin from '@/components/chart/chartMixin'
|
||||
import { chartLegendPlacement } from '@/components/common/js/constants'
|
||||
import * as echarts from 'echarts'
|
||||
import { getChart, setChart } from '@/components/common/js/common'
|
||||
import moment from 'moment-timezone'
|
||||
import bus from '@/libs/bus'
|
||||
import { formatScientificNotation, getMetricTypeValue } from '@/components/common/js/tools'
|
||||
import chartDataFormat from '@/components/charts/chartDataFormat'
|
||||
import { randomcolor } from '@/components/common/js/radomcolor/randomcolor'
|
||||
import { initColor } from '@/components/chart/chart/tools'
|
||||
import lodash from 'lodash'
|
||||
|
||||
export default {
|
||||
name: 'chart-bar'
|
||||
name: 'chart-bar',
|
||||
components: {
|
||||
chartLegend: legend
|
||||
},
|
||||
mixins: [chartMixin],
|
||||
props: {
|
||||
chartInfo: Object,
|
||||
chartData: Array,
|
||||
chartOption: Object,
|
||||
isFullscreen: Boolean
|
||||
},
|
||||
computed: {
|
||||
hasLegend () {
|
||||
try {
|
||||
return [chartLegendPlacement.bottom, chartLegendPlacement.left, chartLegendPlacement.right].indexOf(this.chartInfo.param.legend.placement) > -1
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
},
|
||||
legendPlacement () {
|
||||
try {
|
||||
switch (this.chartInfo.param.legend.placement) {
|
||||
case 'left':
|
||||
case 'right':
|
||||
case 'bottom': {
|
||||
return `nz-chart__component--${this.chartInfo.param.legend.placement}`
|
||||
}
|
||||
default: return ''
|
||||
}
|
||||
} catch (e) {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
colorList: [],
|
||||
chartDot: 2,
|
||||
isInit: true, // 是否是初始化,初始化时为true,图表初始化结束后设为false
|
||||
legends: [], // { name, alias, color, statistics: [{type: min, value: xxx}, ...] }
|
||||
toolboxIconColor: {
|
||||
active: '#53a3cb',
|
||||
inactive: '#7e7e7e'
|
||||
},
|
||||
chartId: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initChart (chartOption) {
|
||||
const self = this
|
||||
this.legends = []
|
||||
chartOption.series = this.initPieData(this.chartInfo, chartOption.series[0], this.chartData) // 生成series和legends
|
||||
chartOption.xAxis.data = chartOption.series.data.map(item => item.name)
|
||||
chartOption.axisLabel = {
|
||||
margin: 8,
|
||||
formatter (params) {
|
||||
const dataLength = chartOption.series.data.length || 1
|
||||
const chartWidth = (document.getElementById('chart-canvas-' + self.chartInfo.id).offsetWidth - 80) / dataLength// 容器宽 - padding - 空余
|
||||
const length = Math.ceil((chartWidth) / 16)
|
||||
let val = ''
|
||||
if (params.length > length) {
|
||||
val = params.substr(0, length) + '...'
|
||||
return val
|
||||
} else {
|
||||
return params
|
||||
}
|
||||
}
|
||||
}
|
||||
chartOption.tooltip.formatter = this.formatterFunc
|
||||
/* 使用setTimeout延迟渲染图表,避免样式错乱 */
|
||||
setTimeout(() => {
|
||||
const myChart = this.isInit ? echarts.init(document.getElementById(`chart-canvas-${this.chartId}`)) : getChart(this.chartId)
|
||||
myChart.setOption(chartOption)
|
||||
this.isInit && setChart(this.chartId, myChart) // 缓存;不使用vue的data是为避免整个chart被监听导致卡顿
|
||||
this.isInit = false
|
||||
}, 200)
|
||||
},
|
||||
getMinMaxFromData (originalDatas) {
|
||||
let minTime = null
|
||||
let maxTime = null
|
||||
let minValue = null
|
||||
let maxValue = null
|
||||
// 将数据提为二维数组
|
||||
let datas = []
|
||||
originalDatas.forEach((originalData, expressionIndex) => {
|
||||
originalData.forEach((data, dataIndex) => {
|
||||
datas = [...datas, ...data.values]
|
||||
})
|
||||
})
|
||||
const timeSorted = datas.sort((a, b) => {
|
||||
return a[0] - b[0]
|
||||
})
|
||||
const valueSorted = datas.sort((a, b) => {
|
||||
return a[1] - b[1]
|
||||
})
|
||||
minTime = timeSorted.length ? timeSorted[0][0] : ''
|
||||
maxTime = timeSorted.length ? timeSorted[timeSorted.length - 1][0] : ''
|
||||
minValue = valueSorted.length ? valueSorted[0][1] : ''
|
||||
maxValue = valueSorted.length ? valueSorted[valueSorted.length - 1][1] : ''
|
||||
return { minTime, maxTime, minValue, maxValue }
|
||||
},
|
||||
initPieData (chartInfo, seriesTemplate, originalDatas) {
|
||||
let colorIndex = 0
|
||||
const s = lodash.cloneDeep(seriesTemplate)
|
||||
s.data = []
|
||||
originalDatas.forEach((originalData, expressionIndex) => {
|
||||
originalData.forEach((data, dataIndex) => {
|
||||
if (s) {
|
||||
const value = getMetricTypeValue(data.values, chartInfo.param.statistics)
|
||||
const mapping = this.selectMapping(value, chartInfo.param.valueMapping)
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
mapping && (this.chartOption.color[colorIndex] = mapping.color.bac)
|
||||
s.data.push({
|
||||
value: chartDataFormat.getUnit(chartInfo.unit ? chartInfo.unit : 2).compute(value, null, -1, 2),
|
||||
realValue: value,
|
||||
name: this.handleLegend(chartInfo, data, expressionIndex, dataIndex, colorIndex),
|
||||
labels: data.metric,
|
||||
seriesIndex: expressionIndex,
|
||||
dataIndex: dataIndex,
|
||||
mapping: mapping,
|
||||
label: {
|
||||
...s.label,
|
||||
formatter: this.pieFormatterLabel,
|
||||
rich: {
|
||||
color: {
|
||||
color: mapping ? mapping.color.text : '#000000'
|
||||
}
|
||||
}
|
||||
},
|
||||
itemStyle: {
|
||||
color: mapping ? mapping.color.bac : this.colorList[colorIndex]
|
||||
}
|
||||
})
|
||||
colorIndex++
|
||||
}
|
||||
})
|
||||
})
|
||||
return s
|
||||
},
|
||||
pieFormatterLabel (params) {
|
||||
let str = '{color|'
|
||||
if (this.chartInfo.param.text === 'all') {
|
||||
str += params.data.name
|
||||
str += ' : '
|
||||
str += params.data.mapping && params.data.mapping.display ? params.data.mapping.display : params.data.value
|
||||
}
|
||||
if (this.chartInfo.param.text === 'value') {
|
||||
str += params.data.mapping && params.data.mapping.display ? params.data.mapping.display : params.data.value
|
||||
}
|
||||
if (this.chartInfo.param.text === 'legend') {
|
||||
str += params.data.name
|
||||
}
|
||||
if (this.chartInfo.param.text === 'none') {
|
||||
str += ''
|
||||
}
|
||||
str += '}'
|
||||
return str
|
||||
},
|
||||
formatterFunc (params, ticket, callback) {
|
||||
const chartInfo = this.chartData
|
||||
return `
|
||||
<div>
|
||||
<div style="white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis; min-width: 150px; max-width: 600px; line-height: 18px; font-size: 14px;">
|
||||
<div style="max-width: 500px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-bottom: 5px">${params.data.name}</div>
|
||||
<div style="font-size:12px;display:flex;justify-content: space-between;">
|
||||
<div>value</div>
|
||||
<div style="display: ${params.data.mapping && params.data.mapping.display ? 'none' : 'inline-block'}">${chartDataFormat.getUnit(chartInfo.unit ? chartInfo.unit : 2).compute(params.value, null, -1, 2)}</div>
|
||||
<div style="display: ${params.data.mapping && params.data.mapping.display ? 'inline-block' : 'none'}">${params.data.mapping.display}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
chartData: {
|
||||
deep: true,
|
||||
handler (n) {
|
||||
if (!this.isInit) {
|
||||
this.initChart(this.chartOption)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
this.chartOption.color || (this.chartOption.color = initColor(20))
|
||||
this.colorList = this.chartOption.color
|
||||
try {
|
||||
this.isStack = this.chartInfo.param.stack
|
||||
} catch (e) {}
|
||||
this.initChart(this.chartOption)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -193,9 +193,11 @@ export default {
|
||||
chartData: {
|
||||
deep: true,
|
||||
handler (n) {
|
||||
if (!this.isInit) {
|
||||
this.initChart(this.chartOption)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
|
||||
@@ -1,4 +1,32 @@
|
||||
const chartBarOption = {
|
||||
|
||||
tooltip: {
|
||||
trigger: 'item'
|
||||
},
|
||||
legend: {
|
||||
show: false
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category'
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: 'bar',
|
||||
data: [],
|
||||
label: {
|
||||
show: true,
|
||||
color: '#333',
|
||||
width: 100,
|
||||
align: 'center',
|
||||
overflow: 'break',
|
||||
ellipsis: '...'
|
||||
},
|
||||
labelLine: {
|
||||
show: true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
export default chartBarOption
|
||||
|
||||
@@ -15,7 +15,6 @@ const chartPieOption = {
|
||||
show: true,
|
||||
color: '#333',
|
||||
position: 'inside',
|
||||
rotate: true,
|
||||
width: 200,
|
||||
overflow: 'truncate',
|
||||
ellipsis: '...'
|
||||
|
||||
@@ -57,6 +57,9 @@ export function isHexagonFigure (type) {
|
||||
export function isChartPie (type) {
|
||||
return type === chartType.pie
|
||||
}
|
||||
export function isChartBar (type) {
|
||||
return type === chartType.bar
|
||||
}
|
||||
export function isUrl (type) {
|
||||
return type === chartType.url
|
||||
}
|
||||
|
||||
@@ -136,11 +136,11 @@ export default {
|
||||
this.noData = !n || n.length < 1
|
||||
this.copyDataList = n.map(item => {
|
||||
let param = item.param
|
||||
try {
|
||||
param = JSON.parse(item.param)
|
||||
} catch (e) {
|
||||
console.info(e)
|
||||
}
|
||||
// try {
|
||||
// param = JSON.parse(item.param)
|
||||
// } catch (e) {
|
||||
// console.info(e)
|
||||
// }
|
||||
param.showHeader = true
|
||||
return {
|
||||
...item,
|
||||
|
||||
@@ -902,7 +902,7 @@ const chartData = {
|
||||
height: 4,
|
||||
updateBy: 1,
|
||||
updateAt: '2021-11-10 07:06:09',
|
||||
type: 'pie',
|
||||
type: 'bar',
|
||||
unit: 2,
|
||||
weight: 0,
|
||||
param: JSON.stringify(
|
||||
|
||||
@@ -320,6 +320,12 @@ function randomcolor () {
|
||||
return n()
|
||||
}
|
||||
|
||||
export {
|
||||
randomcolor
|
||||
function ColorReverse (OldColorValue) {
|
||||
const newValue = '0x' + OldColorValue.replace(/#/g, '')
|
||||
const str = '000000' + (0xFFFFFF - newValue).toString(16)
|
||||
return '#' + str.substring(str.length - 6, str.length)
|
||||
}
|
||||
export {
|
||||
randomcolor,
|
||||
ColorReverse
|
||||
}
|
||||
|
||||
@@ -513,6 +513,7 @@
|
||||
size="small"
|
||||
v-model.number="item.value"
|
||||
placeholder="value"
|
||||
@change="change"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
@@ -526,6 +527,7 @@
|
||||
size="small"
|
||||
v-model.number="item.from"
|
||||
placeholder="from"
|
||||
@change="change"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
@@ -538,6 +540,7 @@
|
||||
:controls="false"
|
||||
size="small"
|
||||
v-model.number="item.to"
|
||||
@change="change"
|
||||
placeholder="to"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
@@ -551,6 +554,7 @@
|
||||
size="small"
|
||||
v-model="item.regx"
|
||||
placeholder="regx"
|
||||
@change="change"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
</el-row>
|
||||
@@ -559,7 +563,7 @@
|
||||
<div class='mapping-display'>Display</div>
|
||||
</div>
|
||||
<el-form-item :prop="'param.valueMapping.mapping.' + index + '.display'" :rules="{ required: true, message: $t('validate.required'), trigger: 'change'}" class="thresholds-from-item">
|
||||
<el-input v-model="item.display" style="margin-right: 10px" :placeholder="$t('placeholder.chart.display')" size="small"/>
|
||||
<el-input v-model="item.display" style="margin-right: 10px" :placeholder="$t('placeholder.chart.display')" size="small" @change="change"/>
|
||||
</el-form-item>
|
||||
<nezhaColor :color-val="item.color" :single="false" :value-arr="[{name:'bac',value:item.color.bac,key:'bac'},{name:'text',value:item.color.text,key:'text'}]" @colorChange="(val,key)=>{colorChange(val, key, index)}"/>
|
||||
</el-row>
|
||||
@@ -605,7 +609,7 @@
|
||||
<div class='mapping-display'>Title</div>
|
||||
</div>
|
||||
<el-form-item :prop="'param.columns.' + index + '.title'" :rules="{ required: true, message: $t('validate.required'), trigger: 'change'}" class="thresholds-from-item" style="flex: 1">
|
||||
<el-input size="small" v-model="item.title" placeholder="regx"></el-input>
|
||||
<el-input size="small" v-model="item.title" placeholder="regx" @change="change"></el-input>
|
||||
</el-form-item>
|
||||
<div>
|
||||
<div class='mapping-display'>Unit</div>
|
||||
@@ -624,7 +628,7 @@
|
||||
<div class='mapping-display'>Display</div>
|
||||
</div>
|
||||
<el-form-item :prop="'param.columns.' + index + '.display'" :rules="{ required: true, message: $t('validate.required'), trigger: 'change'}" class="thresholds-from-item">
|
||||
<el-input v-model="item.display" style="margin-right: 10px" size="small"/>
|
||||
<el-input v-model="item.display" style="margin-right: 10px" size="small" @change="change"/>
|
||||
</el-form-item>
|
||||
</el-row>
|
||||
</transition-group>
|
||||
@@ -645,7 +649,7 @@ import publicConfig from '@/components/common/rightBox/chart/publicConfig'
|
||||
import chartTypeShow from '@/components/common/rightBox/chart/chartTypeShow'
|
||||
import VueTagsInput from '@johmun/vue-tags-input'
|
||||
import draggable from 'vuedraggable'
|
||||
import { randomcolor } from '@/components/common/js/radomcolor/randomcolor'
|
||||
import { randomcolor, ColorReverse } from '@/components/common/js/radomcolor/randomcolor'
|
||||
export default {
|
||||
name: 'chartConfig',
|
||||
components: {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import chartDataFormat from '@/components/charts/chartDataFormat'
|
||||
import { getUUID, resetZIndex } from '@/components/common/js/common'
|
||||
import { randomcolor } from '@/components/common/js/radomcolor/randomcolor'
|
||||
import { randomcolor, ColorReverse } from '@/components/common/js/radomcolor/randomcolor'
|
||||
const rz = {
|
||||
methods: {
|
||||
rz (e) {
|
||||
@@ -304,8 +304,8 @@ export default {
|
||||
value: undefined,
|
||||
display: '',
|
||||
color: {
|
||||
bac: bacColor,
|
||||
text: randomcolor()
|
||||
bac: bacColor + 'FF',
|
||||
text: ColorReverse(bacColor) + 'FF'
|
||||
}
|
||||
})
|
||||
this.change()
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
class="form-item--half-width"
|
||||
prop="param.limit"
|
||||
>
|
||||
<el-input :controls="false" v-model.number="chartConfig.param.limit" :placeholder="$t('placeholder.system.limit')" size="small"/>
|
||||
<el-input :controls="false" v-model.number="chartConfig.param.limit" :placeholder="$t('placeholder.system.limit')" size="small" @change="change"/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</div>
|
||||
@@ -258,6 +258,7 @@
|
||||
size="small"
|
||||
v-model.number="item.value"
|
||||
placeholder="value"
|
||||
@change="change"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
@@ -271,6 +272,7 @@
|
||||
size="small"
|
||||
v-model.number="item.from"
|
||||
placeholder="from"
|
||||
@change="change"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
@@ -284,6 +286,7 @@
|
||||
size="small"
|
||||
v-model.number="item.to"
|
||||
placeholder="to"
|
||||
@change="change"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
@@ -296,6 +299,7 @@
|
||||
size="small"
|
||||
v-model="item.regx"
|
||||
placeholder="regx"
|
||||
@change="change"
|
||||
></el-input>
|
||||
</el-form-item>
|
||||
</el-row>
|
||||
@@ -304,7 +308,7 @@
|
||||
<div class='mapping-display'>Display</div>
|
||||
</div>
|
||||
<el-form-item :prop="'param.valueMapping.mapping.' + index + '.display'" :rules="{ required: true, message: $t('validate.required'), trigger: 'change'}" class="thresholds-from-item">
|
||||
<el-input v-model="item.display" style="margin-right: 10px" size="small"/>
|
||||
<el-input v-model="item.display" style="margin-right: 10px" size="small" @change="change"/>
|
||||
</el-form-item>
|
||||
<nezhaColor :color-val="item.color" :single="false" :value-arr="[{name:'bac',value:item.color.bac,key:'bac'},{name:'text',value:item.color.text,key:'text'}]" @colorChange="(val,key)=>{colorChange(val, key, index)}"/>
|
||||
</el-row>
|
||||
@@ -350,7 +354,7 @@
|
||||
<div class='mapping-display'>Title</div>
|
||||
</div>
|
||||
<el-form-item :prop="'param.columns.' + index + 'title'" :rules="{ required: true, message: $t('validate.required'), trigger: 'change'}" class="thresholds-from-item" style="flex: 1">
|
||||
<el-input size="small" v-model="item.title" placeholder="regx"></el-input>
|
||||
<el-input size="small" v-model="item.title" placeholder="regx" @change="change"></el-input>
|
||||
</el-form-item>
|
||||
<div>
|
||||
<div class='mapping-display'>Unit</div>
|
||||
@@ -369,7 +373,7 @@
|
||||
<div class='mapping-display'>Display</div>
|
||||
</div>
|
||||
<el-form-item :prop="'param.columns.' + index + 'display'" :rules="{ required: true, message: $t('validate.required'), trigger: 'change'}" class="thresholds-from-item">
|
||||
<el-input v-model="item.display" style="margin-right: 10px" size="small"/>
|
||||
<el-input v-model="item.display" style="margin-right: 10px" size="small" @change="change"/>
|
||||
</el-form-item>
|
||||
</el-row>
|
||||
</transition-group>
|
||||
|
||||
@@ -400,7 +400,6 @@ export default {
|
||||
this.chart.panelId = this.showPanel.id
|
||||
this.chart.panelName = this.showPanel.name
|
||||
this.chart.param = JSON.parse(this.chart.param)
|
||||
this.chart.datasource = 'metrics'
|
||||
if (!this.chart.groupId || this.chart.groupId == -1) {
|
||||
this.chart.groupId = ''
|
||||
}
|
||||
@@ -503,7 +502,7 @@ export default {
|
||||
this.$get('visual/panel/chart?panelId=' + params.panelId + '&groupId=0' + '&pageSize=-1').then(response => {
|
||||
if (response.code === 200) {
|
||||
this.chartListLoading = false
|
||||
this.dataList = chartData.data.list.map(item => {
|
||||
this.dataList = response.data.list.map(item => {
|
||||
return {
|
||||
...item,
|
||||
hide: item.name.indexOf(this.filter.searchName) === -1, // 搜索条件
|
||||
|
||||
Reference in New Issue
Block a user