NEZ-2769 feat:dashboard增加 Rose chart(玫瑰图)图表类型

This commit is contained in:
zyh
2023-04-21 09:59:31 +08:00
parent 57469d2bcf
commit f0d369e98a
13 changed files with 477 additions and 31 deletions

View File

@@ -721,7 +721,6 @@
pointer-events: none !important;
}
}
.foreign{
overflow: visible;
.foreign-label-wrap{
@@ -733,15 +732,13 @@
align-items: center;
}
}
.funnel-label{
cursor: pointer;
pointer-events: auto;
line-height: 16px;
color: $--color-text-primary;
}
.doughnut-label{
.doughnut-label,.rose-label{
cursor: pointer;
pointer-events: auto;
font-size: 12px;

View File

@@ -136,6 +136,7 @@ export default {
case 'gauge' :
case 'pie' :
case 'doughnut' :
case 'rose' :
case 'treemap' :
case 'log' :
case 'hexagon' :

View File

@@ -36,6 +36,15 @@
:is-fullscreen="isFullscreen"
@chartIsNoData="chartIsNoData"
></chart-doughnut>
<chart-rose
:ref="'chart' + chartInfo.id"
v-if="isRose(chartInfo.type)"
:chart-data="chartData"
:chart-info="chartInfo"
:chart-option="chartOption"
:is-fullscreen="isFullscreen"
@chartIsNoData="chartIsNoData"
></chart-rose>
<chart-bar
:ref="'chart' + chartInfo.id"
v-if="isChartBar(chartInfo.type)"
@@ -249,6 +258,7 @@ import chartLog from './chart/chartLog'
import chartNoData from './chart/chartNoData'
import chartPie from './chart/chartPie'
import chartDoughnut from './chart/chartDoughnut'
import chartRose from './chart/chartRose'
import chartStat from './chart/chartStat'
import chartTable from './chart/chartTable'
import chartText from './chart/chartText'
@@ -263,7 +273,7 @@ import chartBubble from './chart/chartBubble'
import chartRank from './chart/chartRank'
import chartSankey from './chart/chartSankey'
import chartFunnel from './chart/chartFunnelNew'
import { getOption, isTimeSeries, isHexagon, isUrl, isText, isChartPie, isDoughnut, isChartBar, isTreemap, isLog, isStat, isDiagram, isGroup, isAutotopology, isMap, isAssetInfo, isEndpointInfo, isTable, isGauge, isClock, isTopology, isChartBubble, isChartRank, isSankey, isFunnel } from './chart/tools'
import { getOption, isTimeSeries, isHexagon, isUrl, isText, isChartPie, isDoughnut, isRose, isChartBar, isTreemap, isLog, isStat, isDiagram, isGroup, isAutotopology, isMap, isAssetInfo, isEndpointInfo, isTable, isGauge, isClock, isTopology, isChartBubble, isChartRank, isSankey, isFunnel } from './chart/tools'
import lodash from 'lodash'
export default {
@@ -282,6 +292,7 @@ export default {
chartNoData,
chartPie,
chartDoughnut,
chartRose,
chartStat,
chartTable,
chartText,
@@ -354,6 +365,7 @@ export default {
isHexagon,
isChartPie,
isDoughnut,
isRose,
isChartBar,
isUrl,
isText,

View File

@@ -2,16 +2,16 @@
<div
:class="legendPlacement"
ref="doughnut-chart-box"
class="nz-chart__component nz-chart__component--time-series"
class="nz-chart__component"
>
<div :id="`chart-canvas-${chartId}`" class="chart__canvas"></div>
<div :id="`chart-canvas-${chartId}`" class="chart__canvas" style="overflow: hidden;"></div>
<chart-legend
v-if="hasLegend"
:chart-data="chartData"
:chart-info="chartInfo"
:legends="legends"
:is-fullscreen="isFullscreen"
@clickLegendDoughnut="clickLegendDoughnut"
@clickLegendD3="clickLegendD3"
></chart-legend>
<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">
@@ -120,7 +120,7 @@ export default {
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.doughnutData.push({
value: value,
value: Number(value),
realValue: value,
showValue: showValue,
name: legend.name,
@@ -141,7 +141,6 @@ export default {
this.$emit('chartIsNoData', this.isNoData)
},
drawDoughnutChart (animate) {
this.dispose()
const svgDom = document.getElementById(`chart-canvas-${this.chartId}`)
if (!svgDom) {
return false
@@ -160,8 +159,17 @@ export default {
const width = svgDom.getBoundingClientRect().width
const height = svgDom.getBoundingClientRect().height
this.svg = d3.select(`#chart-canvas-${this.chartId}`).append('svg').attr('height', height).attr('width', width).attr('viewBox', [-width / 2, -height / 2, width, height]).style('display', 'block')
const chart = this.svg.append('g')
let chart
if (this.svg) {
chart = this.svg.select('g')
} else {
this.svg = d3.select(`#chart-canvas-${this.chartId}`).append('svg').style('display', 'block')
chart = this.svg.append('g')
}
this.svg
.attr('width', width)
.attr('height', height)
.attr('viewBox', [-width / 2, -height / 2, width, height])
const outerRadius = (Math.min(width, height) / 2) * 0.6 // outer radius of pie, in pixels
const innerRadius = outerRadius * 0.67 // inner radius of pie, in pixels (non-zero for donut)
@@ -174,15 +182,15 @@ export default {
const arcs = pie(doughnutData)
function doughnutOver (e, d) {
d3.select(chart.selectAll('path').nodes()[d.index])
chart.select('.path-' + d.index)
.transition()
.attr('d', d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius * 1.05)
.outerRadius(outerRadius * 1.06)
)
}
function doughnutOut (e, d) {
d3.select(chart.selectAll('path').nodes()[d.index])
chart.select('.path-' + d.index)
.transition()
.attr('d', d3.arc()
.innerRadius(innerRadius)
@@ -190,28 +198,30 @@ export default {
)
}
const that = this
// 图形
chart.selectAll('path')
.data(arcs)
.data(arcs.filter(function (d) {
return d.data.value
}))
.join('path')
.attr('fill', d => d.data.background)
.attr('d', arc)
.attr('class', (d) => 'path-' + d.index)
.style('cursor', 'pointer')
.classed('no-events', true)
.on('mouseover', doughnutOver)
.on('mouseout', doughnutOut)
.on('mouseenter', that.doughnutEnter)
.on('mousemove', that.doughnutMove)
.on('mouseleave', that.doughnutLeave)
.on('mouseenter', this.doughnutEnter)
.on('mousemove', this.doughnutMove)
.on('mouseleave', this.doughnutLeave)
.transition().duration(animate === true ? 600 : 0)
.attrTween('d', (d) => {
.attrTween('d', function (d) {
let currentArc = this._current
if (!currentArc) {
currentArc = { startAngle: 0, endAngle: 0 }
}
const i = d3.interpolate(currentArc, d)
this._current = i(0) // 当饼图更新时,从当前角度过渡到新角度
this._current = i(1) // 当饼图更新时,从当前角度过渡到新角度
return function (t) {
return arc(i(t))
}
@@ -243,6 +253,7 @@ export default {
d3.select(this).classed('no-events', false)
})
},
// 处理label
formatterLabel ({ data }) {
let str = ''
@@ -327,7 +338,7 @@ export default {
this.tooltip.x = e.pageX + 15
}
},
clickLegendDoughnut (isGrey) {
clickLegendD3 (isGrey) {
const data = this.doughnutData.filter((item, i) => !isGrey[i])
this.selectData = this.$loadsh.cloneDeep(data)
this.drawDoughnutChart(true)

View File

@@ -2,7 +2,7 @@
<div
:class="legendPlacement"
ref="pie-chart-box"
class="nz-chart__component nz-chart__component--time-series" @mouseenter="mouseEnterChart"
class="nz-chart__component" @mouseenter="mouseEnterChart"
@mouseleave="mouseLeaveChart"
>
<div :id="`chart-canvas-${chartId}`" class="chart__canvas"></div>

View File

@@ -0,0 +1,395 @@
<template>
<div
:class="legendPlacement"
ref="rose-chart-box"
class="nz-chart__component"
>
<div :id="`chart-canvas-${chartId}`" class="chart__canvas" style="overflow: hidden;"></div>
<chart-legend
v-if="hasLegend"
:chart-data="chartData"
:chart-info="chartInfo"
:legends="legends"
:is-fullscreen="isFullscreen"
@clickLegendD3="clickLegendD3"
></chart-legend>
<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 * as d3 from 'd3'
import lodash from 'lodash'
import chartFormat from '@/components/chart/chartFormat'
import chartMixin from '@/components/chart/chartMixin'
import chartDataFormat from '@/components/chart/chartDataFormat'
import { getMetricTypeValue } from '@/components/common/js/tools'
import { initColor } from '@/components/chart/chart/tools'
import legend from '@/components/chart/chart/legend'
import { chartLegendPlacement } from '@/components/common/js/constants'
export default {
name: 'chart-rose',
components: {
chartLegend: legend
},
mixins: [chartMixin, chartFormat],
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: [],
isInit: true, // 是否是初始化初始化时为true图表初始化结束后设为false
chartId: '',
roseData: [],
selectData: [],
tooltip: {
x: 0,
y: 0,
title: 0,
value: 0,
mapping: {},
show: false
},
svg: null
}
},
methods: {
initChart (animate) {
this.legends = []
this.initRoseData(this.chartInfo, this.chartData)
this.selectData = this.$loadsh.cloneDeep(this.roseData)
if (this.isNoData) {
return
}
/* 使用setTimeout延迟渲染图表避免样式错乱 */
setTimeout(() => {
this.drawRoseChart(animate)
this.isInit = false
}, 200)
},
initRoseData (chartInfo, originalDatas) {
this.roseData = []
let colorIndex = 0
const decimals = this.chartInfo.param.decimals || 2
this.isNoData = true
originalDatas.forEach((originalData, expressionIndex) => {
originalData.forEach((data, dataIndex) => {
this.isNoData = false
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.roseData.push({
value: Number(value),
realValue: value,
showValue: showValue,
name: legend.name,
alias: legend.alias,
labels: {
...data.metric,
legend: legend.alias
},
seriesIndex: expressionIndex,
dataIndex: dataIndex,
mapping: mapping,
background: mapping ? mapping.color.bac : this.colorList[colorIndex]
})
colorIndex++
})
})
this.$emit('chartIsNoData', this.isNoData)
},
drawRoseChart (animate) {
const svgDom = document.getElementById(`chart-canvas-${this.chartId}`)
if (!svgDom) {
return false
}
// 如果数据全为0 则设置默认值(否则图表不显示)
let roseData = lodash.cloneDeep(this.selectData)
if (roseData.every(item => item.value == 0)) {
roseData = roseData.map(item => {
return {
...item,
value: 100
}
})
}
const width = svgDom.getBoundingClientRect().width
const height = svgDom.getBoundingClientRect().height
let chart
if (this.svg) {
chart = this.svg.select('g')
} else {
this.svg = d3.select(`#chart-canvas-${this.chartId}`).append('svg').style('display', 'block')
chart = this.svg.append('g')
}
this.svg.attr('width', width)
.attr('height', height)
.attr('viewBox', [-width / 2, -height / 2, width, height])
const outerRadius = (Math.min(width, height) / 2) * 0.6 // outer radius of pie, in pixels
const innerRadius = 20 // inner radius of pie, in pixels (non-zero for donut)
const padAngle = 0 // angular separation between wedges
const radius = 4
const scale = d3.scaleRadial()
.domain([0, d3.max(roseData, d => d.value)])
.range([innerRadius, outerRadius])
const arc = d3.arc()
.innerRadius(innerRadius)
.outerRadius(d => {
return scale(d.data.value)
})
.cornerRadius(radius)
const pie = d3.pie()
.padAngle(padAngle)
.sort((a, b) => b.value - a.value)
.value(d => d.value)
const arcs = pie(roseData)
function roseOver (e, d) {
chart.select('.path-' + d.index)
.transition()
.attr('d', d3.arc()
.innerRadius(innerRadius)
.outerRadius(d => {
return scale(d.data.value) * 1.06
})
.cornerRadius(radius)
)
}
function roseOut (e, d) {
chart.select('.path-' + d.index)
.transition()
.attr('d', d3.arc()
.innerRadius(innerRadius)
.outerRadius(d => scale(d.data.value))
.cornerRadius(radius)
)
}
// 图形
chart.selectAll('path')
.data(arcs.filter(function (d) {
return d.data.value
}))
.join('path')
.attr('fill', d => d.data.background)
.attr('d', arc)
.attr('class', (d) => 'path-' + d.index)
.style('cursor', 'pointer')
.classed('no-events', true)
.on('mouseover', roseOver)
.on('mouseout', roseOut)
.on('mouseenter', this.roseEnter)
.on('mousemove', this.roseMove)
.on('mouseleave', this.roseLeave)
.transition().duration(animate === true ? 600 : 0)
.attrTween('d', function (d) {
let currentArc = this._current
if (!currentArc) {
currentArc = { startAngle: 0, endAngle: 0 }
}
const i = d3.interpolate(currentArc, d)
this._current = i(1) // 当饼图更新时,从当前角度过渡到新角度
const arc = d3.arc()
.innerRadius(innerRadius)
.outerRadius(scale(d.value))
.cornerRadius(radius)
return function (t) {
return arc(i(t))
}
})
.on('end', function () {
d3.select(this).classed('no-events', false)
})
// 文本
chart
.selectAll('foreignObject')
.data(arcs)
.join('foreignObject')
.attr('transform', d => `translate(${arc.centroid(d)})`)
.attr('class', 'foreign')
.classed('no-events', true)
.on('mouseover', roseOver)
.on('mouseout', roseOut)
.on('mouseenter', this.roseEnter)
.on('mousemove', this.roseMove)
.on('mouseleave', this.roseLeave)
.style('opacity', 0)
.html((d) => {
return d.endAngle - d.startAngle > 0.25 ? this.formatterLabel(d) : ''
})
.transition('opacity').duration(animate === true ? 600 : 0)
.style('opacity', 1)
.on('end', function () {
d3.select(this).classed('no-events', false)
})
},
// 处理label
formatterLabel ({ data }) {
let str = ''
let valueStr = ''
if (this.chartInfo.param.text === 'all') {
str += data.alias
valueStr = data.mapping && data.mapping.display ? this.handleDisplay(data.mapping.display, { ...data.labels, value: data.showValue }) : data.showValue
}
if (this.chartInfo.param.text === 'value' || !this.chartInfo.param.text) {
valueStr = data.mapping && data.mapping.display ? this.handleDisplay(data.mapping.display, { ...data.labels, value: data.showValue }) : data.showValue
}
if (this.chartInfo.param.text === 'legend') {
str += data.alias
}
if (this.chartInfo.param.text === 'none') {
str += ''
}
if (str && valueStr) {
return `<div class="foreign-label-wrap">
<p class="rose-label" style="color: ${data.mapping && data.mapping.color && data.mapping.color.text};">
<span>${str}</span>
</p>
<p class="rose-label" style="color: ${data.mapping && data.mapping.color && data.mapping.color.text};">
<i class="${data.mapping && data.mapping.icon}" style="color: ${data.mapping && data.mapping.color && data.mapping.color.icon};font-size:1em;"></i>
<span>${valueStr}</span>
</p>
</div>
`
} else if (str) {
return `<div class="foreign-label-wrap">
<p class="rose-label" style="color: ${data.mapping && data.mapping.color && data.mapping.color.text};">
<i class="${data.mapping && data.mapping.icon}" style="color: ${data.mapping && data.mapping.color && data.mapping.color.icon};font-size:1em;"></i>
<span>${str}</span>
</p>
</div>
`
} else if (valueStr) {
return `<div class="foreign-label-wrap">
<p class="rose-label" style="color: ${data.mapping && data.mapping.color && data.mapping.color.text};">
<i class="${data.mapping && data.mapping.icon}" style="color: ${data.mapping && data.mapping.color && data.mapping.color.icon};font-size:1em;"></i>
<span>${valueStr}</span>
</p>
</div>
`
}
},
roseEnter (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)
},
roseMove (e) { // 气泡内移动
if (this.tooltip.show) {
this.tooltip.show = true
this.setPosition(e)
}
},
roseLeave () { // 移出气泡
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
}
},
clickLegendD3 (isGrey) {
const data = this.roseData.filter((item, i) => !isGrey[i])
this.selectData = this.$loadsh.cloneDeep(data)
this.drawRoseChart(true)
},
resize () {
setTimeout(() => {
this.drawRoseChart(false)
}, 50)
},
dispose () {
if (this.svg) {
this.svg.selectAll('path').on('mouseover', null)
this.svg.selectAll('path').on('mouseout', null)
this.svg.selectAll('path').on('mouseenter', null)
this.svg.selectAll('path').on('mousemove', null)
this.svg.selectAll('path').on('mouseleave', null)
this.svg.selectAll('foreignObject').on('mouseover', null)
this.svg.selectAll('foreignObject').on('mouseout', null)
this.svg.selectAll('foreignObject').on('mouseenter', null)
this.svg.selectAll('foreignObject').on('mousemove', null)
this.svg.selectAll('foreignObject').on('mouseleave', null)
this.svg.remove()
this.svg = null
}
}
},
mounted () {
this.colorList = initColor(20)
this.chartInfo.loaded && this.initChart(true)
},
beforeDestroy () {
this.dispose()
}
}
</script>

View File

@@ -139,8 +139,8 @@ export default {
this.clickLegendTreemap(legendName, index, hasGrey, curIsGrey, currentIsTheOnlyOneHighlight)
return
}
if (this.chartInfo.type === 'doughnut') {
this.clickLegendDoughnut(legendName, index, hasGrey, curIsGrey, currentIsTheOnlyOneHighlight)
if (this.chartInfo.type === 'doughnut' || this.chartInfo.type === 'rose') {
this.clickLegendD3(legendName, index, hasGrey, curIsGrey, currentIsTheOnlyOneHighlight)
return
}
@@ -232,7 +232,7 @@ export default {
})
}
},
clickLegendDoughnut (legendName, index, hasGrey, curIsGrey, currentIsTheOnlyOneHighlight) {
clickLegendD3 (legendName, index, hasGrey, curIsGrey, currentIsTheOnlyOneHighlight) {
if (!hasGrey) { // 1.除当前legend外全置灰
this.isGrey = this.isGrey.map((g, i) => i !== index)
} else if (currentIsTheOnlyOneHighlight) { // 2.全高亮
@@ -240,7 +240,7 @@ export default {
} else { // 对应高亮
this.$set(this.isGrey, index, !this.isGrey[index])
}
this.$emit('clickLegendDoughnut', this.isGrey)
this.$emit('clickLegendD3', this.isGrey)
},
// 四舍五入保留2位小数不够位数则用0替补
keepTwoDecimalFull (num) {

View File

@@ -76,6 +76,9 @@ export function isChartPie (type) {
export function isDoughnut (type) {
return type === chartType.doughnut
}
export function isRose (type) {
return type === chartType.rose
}
export function isChartBar (type) {
return type === chartType.bar
}

View File

@@ -289,6 +289,10 @@ export const chart = {
value: 'doughnut',
label: i18n.t('dashboard.dashboard.chartForm.typeVal.doughnut.label')
},
{
value: 'rose',
label: i18n.t('dashboard.dashboard.chartForm.typeVal.rose.label')
},
{
value: 'table',
label: i18n.t('dashboard.dashboard.chartForm.typeVal.table.label')
@@ -475,6 +479,7 @@ export const chartType = {
gauge: 'gauge',
pie: 'pie',
doughnut: 'doughnut',
rose: 'rose',
treemap: 'treemap',
log: 'log',
text: 'text',

View File

@@ -1272,7 +1272,8 @@ export default {
case 'treemap':
case 'pie':
case 'doughnut':
if (this.oldType === 'bar' || this.oldType === 'treemap' || this.oldType === 'pie' || this.oldType === 'doughnut') {
case 'rose':
if (this.oldType === 'bar' || this.oldType === 'treemap' || this.oldType === 'pie' || this.oldType === 'doughnut' || this.oldType === 'rose') {
break
}
this.chartConfig.param = {

View File

@@ -56,6 +56,7 @@ export default {
case 'gauge':
case 'pie':
case 'doughnut':
case 'rose':
return false
default: return false
}
@@ -74,6 +75,7 @@ export default {
case 'gauge':
case 'pie':
case 'doughnut':
case 'rose':
case 'bubble':
case 'rank':
case 'sankey':
@@ -90,6 +92,7 @@ export default {
case 'treemap':
case 'pie':
case 'doughnut':
case 'rose':
case 'bar':
return true
case 'table':
@@ -113,6 +116,7 @@ export default {
case 'treemap':
case 'pie':
case 'doughnut':
case 'rose':
case 'bar':
return false
default: return false
@@ -141,6 +145,7 @@ export default {
case 'treemap':
case 'pie':
case 'doughnut':
case 'rose':
case 'bubble':
case 'rank':
case 'sankey':
@@ -156,6 +161,7 @@ export default {
case 'treemap':
case 'pie':
case 'doughnut':
case 'rose':
case 'stat':
case 'hexagon':
case 'gauge':
@@ -174,6 +180,7 @@ export default {
case 'treemap':
case 'pie':
case 'doughnut':
case 'rose':
case 'stat':
case 'hexagon':
case 'gauge':
@@ -210,6 +217,7 @@ export default {
case 'treemap':
case 'pie':
case 'doughnut':
case 'rose':
case 'stat':
case 'hexagon':
case 'gauge':

View File

@@ -251,6 +251,10 @@ export default {
id: 'doughnut',
name: this.$t('dashboard.dashboard.chartForm.typeVal.doughnut.label')
},
{
id: 'rose',
name: this.$t('dashboard.dashboard.chartForm.typeVal.rose.label')
},
{
id: 'bubble',
name: this.$t('dashboard.dashboard.chartForm.typeVal.bubble.label')
@@ -314,6 +318,10 @@ export default {
id: 'doughnut',
name: this.$t('dashboard.dashboard.chartForm.typeVal.doughnut.label')
},
{
id: 'rose',
name: this.$t('dashboard.dashboard.chartForm.typeVal.rose.label')
},
{
id: 'bubble',
name: this.$t('dashboard.dashboard.chartForm.typeVal.bubble.label')

View File

@@ -894,6 +894,10 @@ export default {
id: 'doughnut',
name: this.$t('dashboard.dashboard.chartForm.typeVal.doughnut.label')
},
{
id: 'rose',
name: this.$t('dashboard.dashboard.chartForm.typeVal.rose.label')
},
{
id: 'bubble',
name: this.$t('dashboard.dashboard.chartForm.typeVal.bubble.label')
@@ -1006,7 +1010,8 @@ export default {
case 'treemap':
case 'pie':
case 'doughnut':
if (this.oldType === 'bar' || this.oldType === 'treemap' || this.oldType === 'pie' || this.oldType === 'doughnut') {
case 'rose':
if (this.oldType === 'bar' || this.oldType === 'treemap' || this.oldType === 'pie' || this.oldType === 'doughnut' || this.oldType === 'rose') {
break
}
this.chartConfig.param = {