forked from github/dataease
Merge pull request #3206 from dataease/pr@dev@feat_percentage_stack_bar
feat(视图): 百分比堆叠柱状图
This commit is contained in:
commit
2321a27aa9
1
frontend/src/icons/svg/percentage-bar-stack.svg
Normal file
1
frontend/src/icons/svg/percentage-bar-stack.svg
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1663834987781" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1963" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M128 810.666667h768v85.333333H128zM149.333333 469.333333h85.333334v298.666667H149.333333zM789.333333 725.333333h85.333334v42.666667h-85.333334zM256 512h85.333333v256h-85.333333zM362.666667 554.666667h85.333333v213.333333h-85.333333zM469.333333 597.333333h85.333334v170.666667h-85.333334zM576 640h85.333333v128h-85.333333zM682.666667 682.666667h85.333333v85.333333h-85.333333z" p-id="1964"></path><path d="M149.333333 234.666667h85.333334v213.333333H149.333333zM789.333333 490.666667h85.333334v213.333333h-85.333334zM256 277.333333h85.333333v213.333334h-85.333333zM362.666667 320h85.333333v213.333333h-85.333333zM469.333333 362.666667h85.333334v213.333333h-85.333334zM576 405.333333h85.333333v213.333334h-85.333333zM682.666667 448h85.333333v213.333333h-85.333333z" opacity=".6" p-id="1965"></path><path d="M789.333333 128h85.333334v341.333333h-85.333334zM149.333333 128h85.333334v85.333333H149.333333zM682.666667 128h85.333333v298.666667h-85.333333zM576 128h85.333333v256h-85.333333zM469.333333 128h85.333334v213.333333h-85.333334zM362.666667 128h85.333333v170.666667h-85.333333zM256 128h85.333333v128h-85.333333z" p-id="1966"></path></svg>
|
After Width: | Height: | Size: 1.4 KiB |
@ -1041,6 +1041,7 @@ export default {
|
||||
label_shadow: 'Label Shadow',
|
||||
label_shadow_color: 'Shadow Color',
|
||||
content_formatter: 'Content Format',
|
||||
label_reserve_decimal_count: 'Reserve Decimal',
|
||||
inside: 'Inside',
|
||||
tooltip: 'Tips',
|
||||
tooltip_item: 'Data Item',
|
||||
@ -1117,6 +1118,7 @@ export default {
|
||||
chart_card: 'KPI Card',
|
||||
chart_bar: 'Base Bar',
|
||||
chart_bar_stack: 'Stack Bar',
|
||||
chart_percentage_bar_stack: 'Percentage Stack Bar',
|
||||
chart_bar_horizontal: 'Horizontal Bar',
|
||||
chart_bar_stack_horizontal: 'Stack Horizontal Bar',
|
||||
chart_line: 'Base Line',
|
||||
|
@ -1038,6 +1038,7 @@ export default {
|
||||
circle: '圓形',
|
||||
label: '標簽',
|
||||
label_position: '標簽位置',
|
||||
label_reserve_decimal_count: '保留小数',
|
||||
label_bg: '標簽背景',
|
||||
label_shadow: '標簽陰影',
|
||||
label_shadow_color: '陰影顏色',
|
||||
@ -1117,6 +1118,7 @@ export default {
|
||||
chart_card: '指標卡',
|
||||
chart_bar: '基礎柱狀圖',
|
||||
chart_bar_stack: '堆疊柱狀圖',
|
||||
chart_percentage_bar_stack: '百分比柱狀圖',
|
||||
chart_bar_horizontal: '橫嚮柱狀圖',
|
||||
chart_bar_stack_horizontal: '橫嚮堆疊柱狀圖',
|
||||
chart_line: '基礎摺線圖',
|
||||
|
@ -1040,6 +1040,7 @@ export default {
|
||||
label_bg: '标签背景',
|
||||
label_shadow: '标签阴影',
|
||||
label_shadow_color: '阴影颜色',
|
||||
label_reserve_decimal_count: '保留小数',
|
||||
content_formatter: '内容格式',
|
||||
inside: '内',
|
||||
tooltip: '提示',
|
||||
@ -1116,6 +1117,7 @@ export default {
|
||||
chart_card: '指标卡',
|
||||
chart_bar: '基础柱状图',
|
||||
chart_bar_stack: '堆叠柱状图',
|
||||
chart_percentage_bar_stack: '百分比柱状图',
|
||||
chart_bar_horizontal: '横向柱状图',
|
||||
chart_bar_stack_horizontal: '横向堆叠柱状图',
|
||||
chart_line: '基础折线图',
|
||||
|
@ -93,6 +93,8 @@ export function baseBarOptionAntV(plot, container, chart, action, isGroup, isSta
|
||||
} else {
|
||||
delete options.isStack
|
||||
}
|
||||
// 目前只有百分比堆叠柱状图需要这个属性,先直接在这边判断而不作为参数传过来
|
||||
options.isPercent = chart.type === 'percentage-bar-stack'
|
||||
// custom color
|
||||
options.color = antVCustomColor(chart)
|
||||
|
||||
|
@ -129,7 +129,8 @@ export const DEFAULT_LABEL = {
|
||||
suffix: '', // 单位后缀
|
||||
decimalCount: 2, // 小数位数
|
||||
thousandSeparator: true// 千分符
|
||||
}
|
||||
},
|
||||
reserveDecimalCount: 2 // 百分比堆叠柱状图保留小数位数
|
||||
}
|
||||
export const DEFAULT_TOOLTIP = {
|
||||
show: true,
|
||||
|
@ -52,7 +52,7 @@ export function getTheme(chart) {
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
const theme = {
|
||||
styleSheet: {
|
||||
brandColor: colors[0],
|
||||
paletteQualitative10: colors,
|
||||
@ -102,6 +102,12 @@ export function getTheme(chart) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// 百分比堆叠柱状图需要取消 offset,因为在顶部类别占比较低的时候有可能会把标签挤出去
|
||||
// 并且视觉上也比较不舒服
|
||||
if (chart.type === 'percentage-bar-stack') {
|
||||
theme.innerLabels.offset = 0
|
||||
}
|
||||
return theme
|
||||
}
|
||||
// 通用label
|
||||
export function getLabel(chart) {
|
||||
@ -148,27 +154,35 @@ export function getLabel(chart) {
|
||||
extStack = JSON.parse(JSON.stringify(chart.extStack))
|
||||
}
|
||||
|
||||
if (chart.type === 'bar-stack' || chart.type === 'line-stack' || chart.type === 'bar-stack-horizontal') {
|
||||
if (chart.type === 'bar-stack' ||
|
||||
chart.type === 'line-stack' ||
|
||||
chart.type === 'bar-stack-horizontal' ||
|
||||
chart.type === 'percentage-bar-stack'
|
||||
) {
|
||||
let f
|
||||
if (extStack && extStack.length > 0) {
|
||||
const f = yAxis[0]
|
||||
if (f.formatterCfg) {
|
||||
res = valueFormatter(param.value, f.formatterCfg)
|
||||
} else {
|
||||
res = valueFormatter(param.value, formatterItem)
|
||||
}
|
||||
f = yAxis[0]
|
||||
} else {
|
||||
for (let i = 0; i < yAxis.length; i++) {
|
||||
const f = yAxis[i]
|
||||
if (f.name === param.category) {
|
||||
if (f.formatterCfg) {
|
||||
res = valueFormatter(param.value, f.formatterCfg)
|
||||
} else {
|
||||
res = valueFormatter(param.value, formatterItem)
|
||||
}
|
||||
if (yAxis[i].name === param.category) {
|
||||
f = yAxis[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!f) {
|
||||
return res
|
||||
}
|
||||
if (!f.formatterCfg) {
|
||||
f.formatterCfg = formatterItem
|
||||
}
|
||||
// 百分比堆叠柱状图保留小数处理
|
||||
if (chart.type === 'percentage-bar-stack') {
|
||||
f.formatterCfg.type = 'percent'
|
||||
f.formatterCfg.decimalCount = l.reserveDecimalCount
|
||||
f.formatterCfg.thousandSeparator = false
|
||||
}
|
||||
res = valueFormatter(param.value, f.formatterCfg)
|
||||
} else if (chart.type === 'bar-group') {
|
||||
const f = yAxis[0]
|
||||
if (f.formatterCfg) {
|
||||
@ -214,7 +228,7 @@ export function getTooltip(chart) {
|
||||
if (chart.type && chart.type !== 'waterfall') {
|
||||
tooltip.formatter = function(param) {
|
||||
let yAxis, extStack
|
||||
let res
|
||||
let res = param.value
|
||||
try {
|
||||
yAxis = JSON.parse(chart.yaxis)
|
||||
} catch (e) {
|
||||
@ -227,29 +241,37 @@ export function getTooltip(chart) {
|
||||
}
|
||||
|
||||
let obj
|
||||
if (chart.type === 'bar-stack' || chart.type === 'line-stack' || chart.type === 'bar-stack-horizontal') {
|
||||
if (chart.type === 'bar-stack' ||
|
||||
chart.type === 'line-stack' ||
|
||||
chart.type === 'bar-stack-horizontal' ||
|
||||
chart.type === 'percentage-bar-stack') {
|
||||
let f
|
||||
if (extStack && extStack.length > 0) {
|
||||
obj = { name: param.category, value: param.value }
|
||||
const f = yAxis[0]
|
||||
if (f.formatterCfg) {
|
||||
res = valueFormatter(param.value, f.formatterCfg)
|
||||
} else {
|
||||
res = valueFormatter(param.value, formatterItem)
|
||||
}
|
||||
f = yAxis[0]
|
||||
} else {
|
||||
obj = { name: param.category, value: param.value }
|
||||
for (let i = 0; i < yAxis.length; i++) {
|
||||
const f = yAxis[i]
|
||||
if (f.name === param.category) {
|
||||
if (f.formatterCfg) {
|
||||
res = valueFormatter(param.value, f.formatterCfg)
|
||||
} else {
|
||||
res = valueFormatter(param.value, formatterItem)
|
||||
}
|
||||
if (yAxis[i].name === param.category) {
|
||||
f = yAxis[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!f) {
|
||||
return res
|
||||
}
|
||||
if (!f.formatterCfg) {
|
||||
f.formatterCfg = formatterItem
|
||||
}
|
||||
if (chart.type === 'percentage-bar-stack') {
|
||||
// 保留小数位数和标签保持一致,这边拿一下标签的配置
|
||||
const l = JSON.parse(JSON.stringify(customAttr.label))
|
||||
f.formatterCfg.type = 'percent'
|
||||
f.formatterCfg.decimalCount = l.reserveDecimalCount
|
||||
f.formatterCfg.thousandSeparator = false
|
||||
}
|
||||
res = valueFormatter(param.value, f.formatterCfg)
|
||||
} else if (chart.type === 'word-cloud') {
|
||||
obj = { name: param.text, value: param.value }
|
||||
for (let i = 0; i < yAxis.length; i++) {
|
||||
@ -311,7 +333,13 @@ export function getTooltip(chart) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tooltip = false
|
||||
// 百分比堆叠柱状图隐藏 tooltip 设置 show 为 false 或者直接设置 tooltip 为 false 都无效,会变成分组显示,
|
||||
// 需要将容器(container)或者内容框(showContent)设置为 false 或者 null 才可以隐藏
|
||||
if (chart.type === 'percentage-bar-stack') {
|
||||
tooltip.showContent = false
|
||||
} else {
|
||||
tooltip = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -390,7 +418,8 @@ export function getLegend(chart) {
|
||||
offsetY: offsetY,
|
||||
marker: {
|
||||
symbol: legendSymbol
|
||||
}
|
||||
},
|
||||
radio: false // 柱状图图例的聚焦功能,默认先关掉
|
||||
}
|
||||
} else {
|
||||
legend = false
|
||||
|
@ -1168,6 +1168,87 @@ export const TYPE_CONFIGS = [
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
render: 'antv',
|
||||
category: 'chart.chart_type_compare',
|
||||
value: 'percentage-bar-stack',
|
||||
title: 'chart.chart_percentage_bar_stack',
|
||||
icon: 'percentage-bar-stack',
|
||||
properties: [
|
||||
'color-selector',
|
||||
'size-selector-ant-v',
|
||||
'label-selector-ant-v',
|
||||
'tooltip-selector-ant-v',
|
||||
'x-axis-selector-ant-v',
|
||||
'y-axis-selector-ant-v',
|
||||
'title-selector-ant-v',
|
||||
'legend-selector-ant-v'
|
||||
],
|
||||
propertyInner: {
|
||||
'color-selector': [
|
||||
'value',
|
||||
'colorPanel',
|
||||
'customColor',
|
||||
'alpha'
|
||||
],
|
||||
'size-selector-ant-v': [
|
||||
'barDefault',
|
||||
'barGap'
|
||||
],
|
||||
'label-selector-ant-v': [
|
||||
'show',
|
||||
'fontSize',
|
||||
'color',
|
||||
'position-v',
|
||||
'reserve-decimal-count'
|
||||
],
|
||||
'tooltip-selector-ant-v': [
|
||||
'show',
|
||||
'textStyle'
|
||||
],
|
||||
'x-axis-selector-ant-v': [
|
||||
'show',
|
||||
'position',
|
||||
'name',
|
||||
'nameTextStyle',
|
||||
'splitLine',
|
||||
'axisForm',
|
||||
'axisLabel'
|
||||
],
|
||||
'y-axis-selector-ant-v': [
|
||||
'show',
|
||||
'position',
|
||||
'name',
|
||||
'nameTextStyle',
|
||||
'axisValue',
|
||||
'splitLine',
|
||||
'axisForm',
|
||||
'axisLabel'
|
||||
],
|
||||
'title-selector-ant-v': [
|
||||
'show',
|
||||
'title',
|
||||
'fontSize',
|
||||
'color',
|
||||
'hPosition',
|
||||
'isItalic',
|
||||
'isBolder',
|
||||
'remarkShow',
|
||||
'fontFamily',
|
||||
'letterSpace',
|
||||
'fontShadow'
|
||||
],
|
||||
'legend-selector-ant-v': [
|
||||
'show',
|
||||
'icon',
|
||||
'orient',
|
||||
'textStyle',
|
||||
'hPosition',
|
||||
'vPosition'
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
render: 'antv',
|
||||
category: 'chart.chart_type_distribute',
|
||||
|
@ -196,6 +196,8 @@ export default {
|
||||
this.myChart = baseBarOptionAntV(this.myChart, this.chartId, chart, this.antVAction, true, false)
|
||||
} else if (chart.type === 'bar-stack') {
|
||||
this.myChart = baseBarOptionAntV(this.myChart, this.chartId, chart, this.antVAction, false, true)
|
||||
} else if (chart.type === 'percentage-bar-stack') {
|
||||
this.myChart = baseBarOptionAntV(this.myChart, this.chartId, chart, this.antVAction, false, true)
|
||||
} else if (chart.type === 'bar-horizontal') {
|
||||
this.myChart = hBaseBarOptionAntV(this.myChart, this.chartId, chart, this.antVAction, true, false)
|
||||
} else if (chart.type === 'bar-stack-horizontal') {
|
||||
|
@ -29,6 +29,11 @@
|
||||
<el-option v-for="option in labelPositionH" :key="option.value" :label="option.name" :value="option.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-show="showProperty('reserve-decimal-count')" :label="$t('chart.label_reserve_decimal_count')" class="form-item">
|
||||
<el-radio-group v-model="labelForm.reserveDecimalCount" :label="$t('chart.label_reserve_decimal_count')" @change="changeLabelAttr('reserveDecimalCount')">
|
||||
<el-radio v-for="option in reserveDecimalCountOptions" :key="option.value" :label="option.value">{{ option.name }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
|
||||
@ -93,7 +98,7 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
data: function() {
|
||||
return {
|
||||
labelForm: JSON.parse(JSON.stringify(DEFAULT_LABEL)),
|
||||
fontSize: [],
|
||||
@ -115,7 +120,12 @@ export default {
|
||||
],
|
||||
predefineColors: COLOR_PANEL,
|
||||
typeList: formatterType,
|
||||
unitList: unitList
|
||||
unitList: unitList,
|
||||
reserveDecimalCountOptions: [
|
||||
{ name: '取整', value: 0 },
|
||||
{ name: '一位', value: 1 },
|
||||
{ name: '两位', value: 2 }
|
||||
]
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@ -179,11 +189,17 @@ export default {
|
||||
this.labelPosition = this.labelPositionH
|
||||
} else if (type.includes('pie')) {
|
||||
this.labelPosition = this.labelPositionPie
|
||||
} else if (type === 'percentage-bar-stack') {
|
||||
// 百分比堆叠柱状图的标签位置为 top 的话最顶上的标签会看不到,这个是 G2plot 的 bug,所以这边暂时先把默认值设置为 middle
|
||||
this.labelForm.position = 'middle'
|
||||
} else {
|
||||
this.labelPosition = this.labelPositionV
|
||||
}
|
||||
}
|
||||
},
|
||||
/*
|
||||
判断该属性是否应该出现在当前视图的标签属性编辑列表中
|
||||
*/
|
||||
showProperty(property) {
|
||||
return this.propertyInner.includes(property)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user