Merge branch 'dev-3.4' of https://git.mesalab.cn/nezha/nezha-fronted into dev-3.4
This commit is contained in:
@@ -13,6 +13,7 @@ const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
|
||||
// const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin')
|
||||
const fileManagerPlugin = require('filemanager-webpack-plugin')
|
||||
const WebpackZipPlugin = require('webpack-zip-plugin')
|
||||
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
|
||||
// const GitRevisionPlugin = require('git-revision-webpack-plugin')
|
||||
const GenerateAssetPlugin = require('generate-asset-webpack-plugin')
|
||||
const WebpackShellPlugin = require('webpack-shell-plugin')
|
||||
@@ -63,19 +64,18 @@ if (arg === 'html') {
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': env
|
||||
}),
|
||||
// new ParallelUglifyPlugin({
|
||||
// cacheDir: '.cache/',
|
||||
// uglifyJS: {
|
||||
// output: {
|
||||
// comments: false
|
||||
// },
|
||||
// warnings: false,
|
||||
// compress: {
|
||||
// drop_debugger: true,
|
||||
// drop_console: true
|
||||
// }
|
||||
// }
|
||||
// }),
|
||||
new UglifyJsPlugin({
|
||||
uglifyOptions: {
|
||||
compress: {
|
||||
warnings: false,
|
||||
drop_console: true,
|
||||
pure_funcs: ['console.log']
|
||||
}
|
||||
},
|
||||
exclude: /manifest.+js/,
|
||||
sourceMap: config.build.productionSourceMap,
|
||||
parallel: true
|
||||
}),
|
||||
// extract css into its own file
|
||||
new ExtractTextPlugin({
|
||||
filename: utils.assetsPath('css/[name].[contenthash].css'),
|
||||
@@ -207,19 +207,18 @@ if (arg === 'html') {
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': env
|
||||
}),
|
||||
// new ParallelUglifyPlugin({
|
||||
// cacheDir: '.cache/',
|
||||
// uglifyJS: {
|
||||
// output: {
|
||||
// comments: false
|
||||
// },
|
||||
// warnings: false,
|
||||
// compress: {
|
||||
// drop_debugger: true,
|
||||
// drop_console: true
|
||||
// }
|
||||
// }
|
||||
// }),
|
||||
new UglifyJsPlugin({
|
||||
uglifyOptions: {
|
||||
compress: {
|
||||
warnings: false,
|
||||
drop_console: true,
|
||||
pure_funcs: ['console.log']
|
||||
}
|
||||
},
|
||||
exclude: /manifest.+js/,
|
||||
sourceMap: config.build.productionSourceMap,
|
||||
parallel: true
|
||||
}),
|
||||
// extract css into its own file
|
||||
new ExtractTextPlugin({
|
||||
filename: utils.assetsPath('css/[name].[contenthash].css'),
|
||||
|
||||
@@ -1,19 +1,32 @@
|
||||
<template>
|
||||
<div
|
||||
ref="pie-chart-box"
|
||||
class="nz-chart__component nz-chart__component--time-series" @mouseenter="mouseEnterChart"
|
||||
@mouseleave="mouseLeaveChart"
|
||||
class="nz-chart__component"
|
||||
>
|
||||
<div :id="`chart-canvas-${chartId}`" class="chart__canvas"></div>
|
||||
<div :id="`chart-canvas-${chartId}`" class="chart__canvas">
|
||||
<svg :id="`bubble-svg-${chartId}`" width="100%" height="100%"></svg>
|
||||
</div>
|
||||
<div :class="`chart-canvas-tooltip-${chartId}`" :id="`chart-canvas-tooltip-${chartId}`" class="chart-canvas-tooltip" :style="{left:tooltip.x+'px',top:tooltip.y+'px'}" v-if="tooltip.show">
|
||||
<div class="chart-canvas-tooltip-title tooltip-title">
|
||||
{{tooltip.title}}
|
||||
</div>
|
||||
<div class="chart-canvas-tooltip-content">
|
||||
<div>value</div>
|
||||
<div>
|
||||
<div v-if="tooltip.mapping && tooltip.mapping.icon" style="display: inline-block">
|
||||
<i :class="tooltip.mapping.icon" :style="{color: tooltip.mapping.color.icon}"></i>
|
||||
</div>
|
||||
<div style="display: inline-block">{{tooltip.value}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import chartMixin from '@/components/chart/chartMixin'
|
||||
import chartFormat from '@/components/chart/chartFormat'
|
||||
import * as echarts from 'echarts'
|
||||
import * as d3 from 'd3'
|
||||
import { getChart, setChart } from '@/components/common/js/common'
|
||||
import { getMetricTypeValue } from '@/components/common/js/tools'
|
||||
import chartDataFormat from '@/components/chart/chartDataFormat'
|
||||
import { initColor } from '@/components/chart/chart/tools'
|
||||
@@ -31,214 +44,238 @@ export default {
|
||||
isFullscreen: Boolean
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
colorList: [],
|
||||
chartDot: 2,
|
||||
isInit: true, // 是否是初始化,初始化时为true,图表初始化结束后设为false
|
||||
chartId: ''
|
||||
chartId: '',
|
||||
bubbleData: [],
|
||||
tooltip: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
title: 0,
|
||||
value: 0,
|
||||
mapping: {},
|
||||
show: false
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initChart (chartOption = this.chartOption) {
|
||||
this.legends = []
|
||||
const parentNode = {
|
||||
id: 'parentNode',
|
||||
name: 'parentNode',
|
||||
depth: -1
|
||||
}
|
||||
chartOption.dataset.source = [parentNode, ...this.initBubbleData(this.chartInfo, [], this.chartData)]
|
||||
initChart () {
|
||||
this.initBubbleData(this.chartInfo, this.chartData)
|
||||
if (this.isNoData) {
|
||||
return
|
||||
}
|
||||
chartOption.series[0].renderItem = this.renderItem
|
||||
chartOption.tooltip.formatter = this.formatterFunc
|
||||
chartOption.tooltip.position = this.tooltipPosition
|
||||
/* 使用setTimeout延迟渲染图表,避免样式错乱 */
|
||||
setTimeout(() => {
|
||||
const myChart = this.isInit ? echarts.init(document.getElementById(`chart-canvas-${this.chartId}`)) : getChart(this.chartId)
|
||||
if (!myChart) {
|
||||
return
|
||||
}
|
||||
myChart.setOption(chartOption)
|
||||
this.isInit && setChart(this.chartId, myChart) // 缓存;不使用vue的data是为避免整个chart被监听导致卡顿
|
||||
this.drawBubbleChart()
|
||||
this.isInit = false
|
||||
}, 200)
|
||||
},
|
||||
initBubbleData (chartInfo, seriesTemplate, originalDatas) {
|
||||
initBubbleData (chartInfo, originalDatas) {
|
||||
this.bubbleData = []
|
||||
let colorIndex = 0
|
||||
const decimals = this.chartInfo.param.decimals || 2
|
||||
const s = lodash.cloneDeep(seriesTemplate)
|
||||
this.isNoData = true
|
||||
originalDatas.forEach((originalData, expressionIndex) => {
|
||||
originalData.forEach((data, dataIndex) => {
|
||||
this.isNoData = false
|
||||
if (s) {
|
||||
const value = getMetricTypeValue(data.values, chartInfo.param.statistics)
|
||||
const showValue = chartDataFormat.getUnit(chartInfo.unit ? chartInfo.unit : 2).compute(value, null, -1, decimals)
|
||||
const mapping = this.selectMapping(value, chartInfo.param.valueMapping, chartInfo.param.enable && this.chartInfo.param.enable.valueMapping)
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
mapping && this.chartOption.color && (this.chartOption.color[colorIndex] = mapping.color.bac)
|
||||
const legend = this.handleLegend(chartInfo, data, expressionIndex, dataIndex, colorIndex)
|
||||
s.push({
|
||||
value: value,
|
||||
realValue: value,
|
||||
showValue: showValue,
|
||||
name: legend.name,
|
||||
alias: legend.alias,
|
||||
labels: data.metric,
|
||||
seriesIndex: expressionIndex,
|
||||
dataIndex: dataIndex,
|
||||
mapping: mapping,
|
||||
id: colorIndex, // 气泡id
|
||||
background: mapping ? mapping.color.bac : this.colorList[colorIndex] // 气泡颜色
|
||||
})
|
||||
colorIndex++
|
||||
}
|
||||
const value = getMetricTypeValue(data.values, chartInfo.param.statistics)
|
||||
const showValue = chartDataFormat.getUnit(chartInfo.unit ? chartInfo.unit : 2).compute(value, null, -1, decimals)
|
||||
const mapping = this.selectMapping(value, chartInfo.param.valueMapping, chartInfo.param.enable && this.chartInfo.param.enable.valueMapping)
|
||||
const legend = this.handleLegend(chartInfo, data, expressionIndex, dataIndex, colorIndex)
|
||||
this.bubbleData.push({
|
||||
value: value,
|
||||
realValue: value,
|
||||
showValue: showValue,
|
||||
name: legend.name,
|
||||
alias: legend.alias,
|
||||
labels: data.metric,
|
||||
seriesIndex: expressionIndex,
|
||||
dataIndex: dataIndex,
|
||||
mapping: mapping,
|
||||
background: mapping ? mapping.color.bac : this.colorList[colorIndex] // 气泡颜色
|
||||
})
|
||||
colorIndex++
|
||||
})
|
||||
})
|
||||
this.$emit('chartIsNoData', this.isNoData)
|
||||
return s
|
||||
},
|
||||
formatterFunc: function (params, ticket, callback) {
|
||||
const self = this
|
||||
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 class="tooltip-title" style="max-width: 500px;white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis;margin-bottom: 5px">${params.data.alias}</div>
|
||||
<div style="font-size:12px;display:flex;justify-content: space-between;">
|
||||
<div>value</div>
|
||||
<div>
|
||||
<div style="display: ${params.data.mapping && params.data.mapping.icon ? 'inline-block' : 'none'}">
|
||||
<i class="${params.data.mapping && params.data.mapping.icon}" style="color: ${params.data.mapping && params.data.mapping.color && params.data.mapping.color.icon}"></i>
|
||||
</div>
|
||||
<div style="display: ${params.data.mapping && params.data.mapping.display ? 'none' : 'inline-block'}">${params.data.showValue}</div>
|
||||
<div style="display: ${params.data.mapping && params.data.mapping.display ? 'inline-block' : 'none'}">${self.handleDisplay(params.data.mapping.display, { ...params.data.labels, value: params.data.showValue })}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
},
|
||||
renderItem (params, api) {
|
||||
// 如果数据全为0 则设置默认值(否则图表不显示)
|
||||
let seriesData = lodash.cloneDeep(this.chartOption.dataset.source)
|
||||
if (seriesData.every(item => !item.value || item.value == 0)) {
|
||||
seriesData = seriesData.map(item => {
|
||||
if (item.id !== 'parentNode') {
|
||||
drawBubbleChart () {
|
||||
this.$nextTick(() => {
|
||||
d3.select(`#bubble-svg-${this.chartId}`).selectAll('g').remove()// 清空作图区域
|
||||
let width
|
||||
let height
|
||||
try {
|
||||
const chartWrap = document.getElementById(`chart-canvas-${this.chartId}`)
|
||||
width = chartWrap.clientWidth
|
||||
height = chartWrap.clientHeight
|
||||
} catch (error) {
|
||||
}
|
||||
// 定义布局方式
|
||||
const pack = d3.pack()
|
||||
.size([width, height])
|
||||
.padding(6)
|
||||
// 如果数据全为0 则设置默认值(否则图表不显示)
|
||||
let bubbleData = lodash.cloneDeep(this.bubbleData)
|
||||
if (bubbleData.every(item => !item.value || item.value == 0)) {
|
||||
bubbleData = bubbleData.map(item => {
|
||||
return {
|
||||
...item,
|
||||
value: 100
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
...item
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
const displayRoot = stratify()
|
||||
function stratify () {
|
||||
return d3
|
||||
.stratify()
|
||||
.parentId(function (d) {
|
||||
// 判断是否是父节点
|
||||
if (d.id !== 'parentNode') {
|
||||
return 'parentNode'
|
||||
}
|
||||
})(seriesData)
|
||||
})
|
||||
}
|
||||
const data = d3.hierarchy({ children: bubbleData })
|
||||
.sum(function (d) {
|
||||
return d.value || 0
|
||||
})
|
||||
.sort(function (a, b) {
|
||||
return b.value - a.value
|
||||
})
|
||||
}
|
||||
function overallLayout (params, api) {
|
||||
const context = params.context
|
||||
d3
|
||||
.pack()
|
||||
.size([api.getWidth() - 2, api.getHeight() - 2])
|
||||
.padding(6)(displayRoot)
|
||||
context.nodes = {}
|
||||
displayRoot.descendants().forEach(function (node) {
|
||||
context.nodes[node.id] = node
|
||||
})
|
||||
}
|
||||
const context = params.context
|
||||
// Only do that layout once in each time `setOption` called.
|
||||
// 每次调用“setOption”时,只能进行一次布局。
|
||||
if (!context.layout) {
|
||||
context.layout = true
|
||||
overallLayout(params, api)
|
||||
}
|
||||
const nodePath = api.value('id')
|
||||
// const nodeName = nodePath
|
||||
// .slice(nodePath.lastIndexOf('.') + 1)
|
||||
// .split(/(?=[A-Z][^A-Z])/g)
|
||||
// .join('')
|
||||
const node = context.nodes[nodePath]
|
||||
if (node.id === 'parentNode') {
|
||||
node.r = 0
|
||||
}
|
||||
if (!node) {
|
||||
// Reder nothing.
|
||||
return
|
||||
}
|
||||
const z2 = api.value('depth') * 2
|
||||
return {
|
||||
type: 'circle',
|
||||
shape: {
|
||||
cx: node.x,
|
||||
cy: node.y,
|
||||
r: node.r
|
||||
},
|
||||
transition: ['shape'],
|
||||
z2: z2,
|
||||
textContent: {
|
||||
type: 'text',
|
||||
style: {
|
||||
// transition: isLeaf ? 'fontSize' : null,
|
||||
text: this.pieFormatterLabel(node),
|
||||
fill: node.data.mapping ? node.data.mapping.color.text : '#000000',
|
||||
width: node.r * 1.3,
|
||||
overflow: 'truncate',
|
||||
fontSize: node.r / 3,
|
||||
lineHeight: node.r / 2.2
|
||||
const nodes = pack(data).descendants()
|
||||
const bubbles = d3.select(`#bubble-svg-${this.chartId}`).selectAll('.bubble')
|
||||
.data(nodes)
|
||||
.enter()
|
||||
.filter(function (d) {
|
||||
return !d.children
|
||||
})
|
||||
.append('g')
|
||||
.attr('class', 'bubble')
|
||||
|
||||
},
|
||||
emphasis: {
|
||||
style: {
|
||||
// overflow: null,
|
||||
// fontSize: Math.max(node.r / 3, 12)
|
||||
}
|
||||
}
|
||||
},
|
||||
textConfig: {
|
||||
position: 'inside'
|
||||
},
|
||||
style: {
|
||||
fill: node.data.background
|
||||
},
|
||||
emphasis: {
|
||||
style: {
|
||||
// shadowBlur: 20,
|
||||
// shadowOffsetX: 3,
|
||||
// shadowOffsetY: 5,
|
||||
// shadowColor: 'rgba(0,0,0,0.3)'
|
||||
}
|
||||
bubbles.append('circle')
|
||||
.style('fill', function (d) {
|
||||
return d.data.background
|
||||
})
|
||||
.attr('cx', function (d) {
|
||||
return d.x
|
||||
})
|
||||
.attr('cy', function (d) {
|
||||
return d.y
|
||||
})
|
||||
.attr('r', function (d) {
|
||||
return d.r
|
||||
})
|
||||
bubbles.append('foreignObject')
|
||||
.attr('width', function (d) {
|
||||
return d.r * 2
|
||||
})
|
||||
.attr('height', function (d) {
|
||||
return d.r * 2
|
||||
})
|
||||
.attr('x', function (d) {
|
||||
return d.x - d.r
|
||||
})
|
||||
.attr('y', function (d) {
|
||||
return d.y - d.r
|
||||
})
|
||||
.style('font-size', function (d) {
|
||||
return d.r / 3 > 10 ? d.r / 3 : 0
|
||||
})
|
||||
.html((d) => {
|
||||
return this.bubbleFormatterLabel(d)
|
||||
})
|
||||
bubbles.on('mouseenter', this.bubbleEnter)
|
||||
bubbles.on('mousemove', this.bubbleMove)
|
||||
bubbles.on('mouseleave', this.bubbleLeave)
|
||||
})
|
||||
},
|
||||
// 处理label
|
||||
bubbleFormatterLabel (node) {
|
||||
let str = ''
|
||||
let valueStr = ''
|
||||
if (this.chartInfo.param.text === 'all') {
|
||||
str += node.data.alias
|
||||
valueStr = node.data.mapping && node.data.mapping.display ? this.handleDisplay(node.data.mapping.display, { ...node.data.labels, value: node.data.showValue }) : node.data.showValue
|
||||
}
|
||||
if (this.chartInfo.param.text === 'value' || !this.chartInfo.param.text) {
|
||||
valueStr = node.data.mapping && node.data.mapping.display ? this.handleDisplay(node.data.mapping.display, { ...node.data.labels, value: node.data.showValue }) : node.data.showValue
|
||||
}
|
||||
if (this.chartInfo.param.text === 'legend') {
|
||||
str += node.data.alias
|
||||
}
|
||||
if (this.chartInfo.param.text === 'none') {
|
||||
str += ''
|
||||
}
|
||||
if (str && valueStr) {
|
||||
return `
|
||||
<div style="width:100%;height: 100%;display: flex;align-items: center;justify-content: center;flex-direction: column;cursor: pointer;">
|
||||
<p style="width: 80%;text-overflow: ellipsis;white-space: nowrap;overflow:hidden;text-align:center">
|
||||
<span>${str}</span>
|
||||
</p>
|
||||
<p style="width: 80%;text-overflow: ellipsis;white-space: nowrap;overflow:hidden;text-align:center">
|
||||
<i class="${node.data.mapping && node.data.mapping.icon}" style="color: ${node.data.mapping && node.data.mapping.color && node.data.mapping.color.icon};font-size:1em;"></i>
|
||||
<span>${valueStr}</span>
|
||||
</p>
|
||||
</div>
|
||||
`
|
||||
} else if (str) {
|
||||
return `
|
||||
<div style="width:100%;height: 100%;display: flex;align-items: center;justify-content: center;flex-direction: column;cursor: pointer;">
|
||||
<p style="width: 80%;text-overflow: ellipsis;white-space: nowrap;overflow:hidden;text-align:center">
|
||||
<i class="${node.data.mapping && node.data.mapping.icon}" style="color: ${node.data.mapping && node.data.mapping.color && node.data.mapping.color.icon};font-size:1em;"></i>
|
||||
<span>${str}</span>
|
||||
</p>
|
||||
</div>
|
||||
`
|
||||
} else if (valueStr) {
|
||||
return `
|
||||
<div style="width:100%;height: 100%;display: flex;align-items: center;justify-content: center;flex-direction: column;cursor: pointer;">
|
||||
<p style="width: 80%;text-overflow: ellipsis;white-space: nowrap;overflow:hidden;text-align:center">
|
||||
<i class="${node.data.mapping && node.data.mapping.icon}" style="color: ${node.data.mapping && node.data.mapping.color && node.data.mapping.color.icon};font-size:1em;"></i>
|
||||
<span>${valueStr}</span>
|
||||
</p>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
},
|
||||
resize () {
|
||||
setTimeout(() => {
|
||||
this.drawBubbleChart()
|
||||
}, 50)
|
||||
},
|
||||
bubbleEnter (e, node) { // 移入六边形
|
||||
this.tooltip.title = node.data.alias
|
||||
this.tooltip.value = node.data.showValue
|
||||
this.tooltip.mapping = node.data.mapping
|
||||
this.tooltip.show = true
|
||||
this.setPosition(e)
|
||||
},
|
||||
bubbleMove (e) { // 六边形内移动
|
||||
if (this.tooltip.show) {
|
||||
this.setPosition(e)
|
||||
}
|
||||
},
|
||||
bubbleLeave () {
|
||||
this.tooltip.show = false
|
||||
},
|
||||
setPosition (e) {
|
||||
const windowWidth = window.innerWidth// 窗口宽度
|
||||
const windowHeight = window.innerHeight// 窗口高度
|
||||
const box = document.getElementById(`chart-canvas-tooltip-${this.chartId}`)
|
||||
if (box) {
|
||||
const boxWidth = box.offsetWidth
|
||||
const boxHeight = box.offsetHeight
|
||||
if (e.pageX < (windowWidth / 2)) { // 说明鼠标在左边放不下提示框
|
||||
this.tooltip.x = e.pageX + 15
|
||||
} else {
|
||||
this.tooltip.x = e.pageX - boxWidth - 15
|
||||
}
|
||||
if (e.pageY + 50 + boxHeight < windowHeight) { // 说明鼠标上面放不下提示框
|
||||
this.tooltip.y = e.pageY + 15
|
||||
} else {
|
||||
this.tooltip.y = e.pageY - boxHeight - 10
|
||||
}
|
||||
} else {
|
||||
this.tooltip.y = e.pageY + 15
|
||||
this.tooltip.x = e.pageX + 15
|
||||
}
|
||||
}
|
||||
},
|
||||
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.colorList = initColor(20)
|
||||
this.chartInfo.loaded && this.initChart(this.chartOption)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,10 +11,11 @@
|
||||
background:item.mapping ? item.mapping.color.bac : (statData.length===1 ? '' : colorList[index]),
|
||||
height:item.height+'px',
|
||||
width:item.width + 'px',
|
||||
fontSize: setFontSize(item)
|
||||
fontSize: item.fontSize,
|
||||
}"
|
||||
>
|
||||
<span v-if="chartInfo.param.text==='all'">
|
||||
<div>
|
||||
<span v-if="chartInfo.param.text==='all'">
|
||||
<span v-if="item.mapping" :style="{color:item.mapping.color.text}">
|
||||
{{item.legend}}<br/>
|
||||
<template v-if="item.mapping && item.mapping.icon">
|
||||
@@ -24,7 +25,7 @@
|
||||
</span>
|
||||
<span v-else>{{item.legend}}<br/><span>{{item.showValue}}</span></span>
|
||||
</span>
|
||||
<span v-if="chartInfo.param.text==='legend'">
|
||||
<span v-if="chartInfo.param.text==='legend'">
|
||||
<span v-if="item.mapping" :style="{color:item.mapping.color.text}">
|
||||
{{item.legend}}<br/>
|
||||
<template v-if="item.mapping && item.mapping.icon">
|
||||
@@ -34,7 +35,7 @@
|
||||
</span>
|
||||
<span v-else>{{item.legend}}</span>
|
||||
</span>
|
||||
<span v-if="chartInfo.param.text==='value'|| !chartInfo.param.text">
|
||||
<span v-if="chartInfo.param.text==='value'|| !chartInfo.param.text">
|
||||
<span v-if="item.mapping" :style="{color:item.mapping.color.text}">
|
||||
<template v-if="item.mapping && item.mapping.icon">
|
||||
<i :class="item.mapping.icon" :style="{color: item.mapping.color.icon,fontSize:'1em'}"></i>
|
||||
@@ -43,7 +44,8 @@
|
||||
</span>
|
||||
<span v-else>{{item.showValue}}</span>
|
||||
</span>
|
||||
<span v-if="chartInfo.param.text==='none'"></span>
|
||||
<span v-if="chartInfo.param.text==='none'"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div :class="`chart-canvas-tooltip-${chartId}`" :id="`chart-canvas-tooltip-${chartId}`" class="chart-canvas-tooltip" :style="{left:tooltip.x+'px',top:tooltip.y+'px'}" v-if="tooltip.show">
|
||||
<div class="chart-canvas-tooltip-title tooltip-title">
|
||||
@@ -59,6 +61,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span class="temp-dom--12" ref="temp-dom"></span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -90,6 +93,7 @@ export default {
|
||||
show: false
|
||||
},
|
||||
fontSize: 12,
|
||||
customFontSize: '',
|
||||
minFontSzie: 12,
|
||||
defaultUnit: 60 // 根据stat的长宽取 需要的字体 = (取最短的边 / defaultUnit) * fontSize 因为 需要的字体/fontSize = 实际宽 / defaultUnit
|
||||
}
|
||||
@@ -164,9 +168,9 @@ export default {
|
||||
}
|
||||
},
|
||||
statMouseEnter (that, e) {
|
||||
this.tooltip.title = that.legend
|
||||
this.tooltip.value = that.showValue
|
||||
this.tooltip.mapping = that.mapping
|
||||
this.tooltip.title = this.$loadsh.cloneDeep(that.legend)
|
||||
this.tooltip.value = this.$loadsh.cloneDeep(that.showValue)
|
||||
this.tooltip.mapping = this.$loadsh.cloneDeep(that.mapping)
|
||||
this.tooltip.show = true
|
||||
this.$nextTick(() => {
|
||||
const windowWidth = window.innerWidth// 窗口宽度
|
||||
@@ -229,6 +233,7 @@ export default {
|
||||
})
|
||||
},
|
||||
renderStat (layout) {
|
||||
let isDouble = false
|
||||
const width = this.boxWidth / layout.col
|
||||
const height = this.boxHeight / layout.row
|
||||
const integer = Math.floor(this.statData.length / layout.col)
|
||||
@@ -242,6 +247,82 @@ export default {
|
||||
} else {
|
||||
item.width = width
|
||||
}
|
||||
let font = '' // 获取显示的字体
|
||||
let display = ''
|
||||
if (item.mapping) {
|
||||
display = this.handleDisplay(item.mapping.display, { ...item.label, value: item.showValue })
|
||||
}
|
||||
switch (this.chartInfo.param.text) {
|
||||
case 'all':
|
||||
if (item.mapping) {
|
||||
isDouble = true
|
||||
if (item.legend.length > item.showValue.length + 2) {
|
||||
font = item.legend
|
||||
} else {
|
||||
font = display
|
||||
if (item.mapping.icon) {
|
||||
font += 'AA'
|
||||
}
|
||||
}
|
||||
} else {
|
||||
isDouble = true
|
||||
if (item.legend.length > item.showValue.length) {
|
||||
font = item.legend
|
||||
} else {
|
||||
font = item.showValue
|
||||
}
|
||||
}
|
||||
break
|
||||
case 'legend':
|
||||
if (item.mapping) {
|
||||
isDouble = true
|
||||
if (item.legend.length > item.showValue.length + 2) {
|
||||
font = item.legend
|
||||
} else {
|
||||
font = display
|
||||
if (item.mapping.icon) {
|
||||
font += 'AA'
|
||||
}
|
||||
}
|
||||
} else {
|
||||
font = item.legend
|
||||
}
|
||||
break
|
||||
|
||||
case 'none':
|
||||
font = ''
|
||||
break
|
||||
case 'value':
|
||||
default:
|
||||
if (item.mapping) {
|
||||
font = display
|
||||
if (item.mapping.icon) {
|
||||
font += 'AA'
|
||||
}
|
||||
} else {
|
||||
font = item.showValue
|
||||
}
|
||||
break
|
||||
}
|
||||
const el = this.$refs['temp-dom']
|
||||
el.innerText = font
|
||||
const elWidth = el.offsetWidth
|
||||
const elHeight = el.offsetHeight
|
||||
const dimension = Math.min(item.width, item.height * 1.3)
|
||||
const fontScale = parseInt('80%', 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 + 'px'
|
||||
})
|
||||
this.isInit = false
|
||||
},
|
||||
@@ -257,9 +338,24 @@ export default {
|
||||
}, 50)
|
||||
},
|
||||
setFontSize (item) {
|
||||
let fontSize = item.height > item.width ? (14 * (item.width / 60)) : (14 * (item.height / 60))
|
||||
let fontSize = ''
|
||||
|
||||
fontSize = item.height > item.width ? (14 * (item.width / 60)) : (14 * (item.height / 60))
|
||||
fontSize = fontSize > 12 ? fontSize : this.minFontSzie
|
||||
return fontSize + 'px'
|
||||
},
|
||||
strlen (str) {
|
||||
let len = 0
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
const c = str.charCodeAt(i)
|
||||
// 单字节加1
|
||||
if ((c >= 0x0001 && c <= 0x007e) || (c >= 0xff60 && c <= 0xff9f)) {
|
||||
len++
|
||||
} else {
|
||||
len += 2
|
||||
}
|
||||
}
|
||||
return len
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
const chartBubble = {
|
||||
dataset: {
|
||||
source: []
|
||||
},
|
||||
tooltip: {
|
||||
show: true,
|
||||
trigger: 'item',
|
||||
confine: false,
|
||||
extraCssText: 'z-index:1000;',
|
||||
z: 9,
|
||||
animation: false,
|
||||
appendToBody: true,
|
||||
className: 'chart-bubble'
|
||||
},
|
||||
hoverLayerThreshold: Infinity,
|
||||
series: [{
|
||||
type: 'custom',
|
||||
renderItem: undefined,
|
||||
progressive: 0,
|
||||
coordinateSystem: 'none'
|
||||
}]
|
||||
}
|
||||
export default chartBubble
|
||||
@@ -1,7 +1,6 @@
|
||||
import { chartType } from '@/components/common/js/constants'
|
||||
import chartBarOption from './options/chartBar'
|
||||
import chartPieOption from './options/chartPie'
|
||||
import chartBubbleOption from './options/chartBubble'
|
||||
import lodash from 'lodash'
|
||||
import {
|
||||
chartTimeSeriesLineOption,
|
||||
@@ -40,10 +39,6 @@ export function getOption (type) {
|
||||
chartOption = lodash.cloneDeep(chartPieOption)
|
||||
break
|
||||
}
|
||||
case chartType.bubble: {
|
||||
chartOption = lodash.cloneDeep(chartBubbleOption)
|
||||
break
|
||||
}
|
||||
case chartType.treemap: {
|
||||
chartOption = lodash.cloneDeep(chartTreemapOption)
|
||||
break
|
||||
|
||||
@@ -441,7 +441,6 @@ export default {
|
||||
},
|
||||
// 比较变量 图表是否显示/隐藏
|
||||
compareVariables () {
|
||||
console.log(123123123123)
|
||||
if (!this.panelLock) {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -546,22 +546,22 @@ export default {
|
||||
},
|
||||
variablesReplace (expression) {
|
||||
let str = expression
|
||||
let confirmReg = ''
|
||||
let confirmRegItem = ''
|
||||
let confirmReg = []
|
||||
this.variablesArr.forEach(item => {
|
||||
const reg = '$' + item.name // 后续需要考虑 item,name 使用特殊字符的问题
|
||||
const index = expression.indexOf(reg)
|
||||
if (index !== -1) {
|
||||
if (reg.length > confirmReg.length) {
|
||||
confirmReg = reg
|
||||
confirmRegItem = item
|
||||
}
|
||||
confirmReg.push(item)
|
||||
}
|
||||
})
|
||||
if (confirmReg) {
|
||||
const index = expression.indexOf(confirmReg)
|
||||
const replaceStr = confirmRegItem.checked.map(label => label.replace(/\"/g, '\\"').replace(/\'/g, "\\'")).join('|')
|
||||
str = str.substring(0, index) + replaceStr + str.substring(index + confirmReg.length)
|
||||
confirmReg = this.$loadsh.orderBy(confirmReg, function (item) { // 根据 匹配的name的长度排序 避免匹配的 $a 没匹配 $asset的问题
|
||||
return item.name.length
|
||||
}, 'desc')
|
||||
if (confirmReg.length) {
|
||||
confirmReg.forEach(item => {
|
||||
const reg = new RegExp('\\$' + item.name, 'g') // 后续需要考虑 item,name 使用特殊字符的问题
|
||||
str = str.replace(reg, item.checked.map(label => label.replace(/\"/g, '\\"').replace(/\'/g, "\\'")).join('|'))
|
||||
})
|
||||
}
|
||||
return str
|
||||
},
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
/>
|
||||
</div>
|
||||
<div v-else-if="item.key === 'trbShot' && activeName === 'trbShot'">
|
||||
<div v-html="infoData.alertRule.trbShot">
|
||||
<div v-html="infoData.alertRule.trbShot" v-if="infoData.alertRule.trbShot">
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
@@ -108,7 +108,7 @@ export default {
|
||||
this.cardNames.push(item)
|
||||
}
|
||||
})
|
||||
if (n.alertRule && n.alertRule.trbShot) {
|
||||
if (n.alertRule && n.alertRule.trbShot && n.alertRule.trbShot != '<div class="editor-core ql-container ql-snow"><div class="ql-editor"><p><br></p></div></div>') {
|
||||
this.cardNames.push({
|
||||
key: 'trbShot',
|
||||
label: this.$t('alert.config.trbShot')
|
||||
|
||||
@@ -507,6 +507,9 @@ export default {
|
||||
method: this.editAlertRule.method.join(','),
|
||||
type: this.editAlertRule.type
|
||||
}
|
||||
if (this.editAlertRule.trbShot && this.editAlertRule.trbShot == '<div class="editor-core ql-container ql-snow"><div class="ql-editor"><p><br></p></div></div>') {
|
||||
this.editAlertRule.trbShot = ''
|
||||
}
|
||||
this.$refs.alertRuleForm.validate((valid) => {
|
||||
if (valid) {
|
||||
params.receiver = this.editAlertRule.receiverShow.join(',')
|
||||
|
||||
@@ -150,7 +150,7 @@
|
||||
</el-form-item>
|
||||
|
||||
<!-- visibility -->
|
||||
<div>
|
||||
<div v-if="params.type === 'group'">
|
||||
<div class="form__sub-title">
|
||||
<span>{{$t('dashboard.panel.showHidden')}}</span>
|
||||
<el-switch
|
||||
|
||||
@@ -680,7 +680,7 @@
|
||||
</div>
|
||||
|
||||
<!-- visibility -->
|
||||
<div>
|
||||
<div v-if="params.type === 'group'">
|
||||
<div class="form__sub-title">
|
||||
<span>{{$t('dashboard.panel.showHidden')}}</span>
|
||||
<el-switch
|
||||
|
||||
@@ -1504,7 +1504,6 @@ export default {
|
||||
immediate: true,
|
||||
deep: true,
|
||||
handler (n, o) {
|
||||
console.log('11111')
|
||||
}
|
||||
},
|
||||
module: {
|
||||
|
||||
Reference in New Issue
Block a user