Merge pull request #9313 from dataease/pr@dev-v2@feat_pie_top_n

feat(图表): 饼图/环形图支持合并数据为其他
This commit is contained in:
wisonic-s 2024-04-24 18:38:14 +08:00 committed by GitHub
commit 79d66ff537
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 115 additions and 9 deletions

View File

@ -1113,7 +1113,11 @@ export default {
word_spacing: '文字间隔',
table_layout_mode: '展示形式',
table_layout_grid: '平铺展示',
table_layout_tree: '树形展示'
table_layout_tree: '树形展示',
top_n_desc: '合并数据',
top_n_input_1: '显示 Top',
top_n_input_2: ', 其余合并至其他',
top_n_label: '其他项名称'
},
dataset: {
scope_edit: '仅编辑时生效',

View File

@ -217,6 +217,18 @@ declare interface ChartBasicStyle {
* 地图缩放按钮背景颜色
*/
zoomBackground: string
/**
* 是否合并数据为其他
*/
calcTopN: boolean
/**
* 只展示 TopN 其他合并为一项
*/
topN: number
/**
* 其他项的标签
*/
topNLabel: string
}
/**
* 表头属性

View File

@ -5,7 +5,11 @@ import { useI18n } from '@/hooks/web/useI18n'
import CustomColorStyleSelect from '@/views/chart/components/editor/editor-style/components/CustomColorStyleSelect.vue'
import { cloneDeep, defaultsDeep } from 'lodash-es'
import { SERIES_NUMBER_FIELD } from '@antv/s2'
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import { storeToRefs } from 'pinia'
const dvMainStore = dvMainStoreWithOut()
const { batchOptStatus } = storeToRefs(dvMainStore)
const { t } = useI18n()
const props = defineProps({
chart: {
@ -466,6 +470,7 @@ onMounted(() => {
<el-select
v-model="state.fieldColumnWidth.fieldId"
:effect="themes"
:disabled="batchOptStatus"
@change="changeFieldColumn()"
>
<el-option
@ -482,6 +487,7 @@ onMounted(() => {
:min="0"
:max="100"
:effect="themes"
:disabled="batchOptStatus"
@change="changeFieldColumnWidth()"
>
<template #append>%</template>
@ -762,6 +768,46 @@ onMounted(() => {
</el-form-item>
<!-- pie/rose start -->
<div v-show="showProperty('topN')" class="top-n-setting">
<el-form-item class="form-item" :class="'form-item-' + themes">
<el-checkbox v-model="state.basicStyleForm.calcTopN" @change="changeBasicStyle('calcTopN')">
{{ $t('chart.top_n_desc') }}
</el-checkbox>
</el-form-item>
<el-form-item
class="form-item"
:class="'form-item-' + themes"
v-show="state.basicStyleForm.calcTopN"
>
<span>{{ $t('chart.top_n_input_1') }}</span>
<el-input-number
v-model="state.basicStyleForm.topN"
controls-position="right"
size="small"
:min="1"
:max="100"
:precision="0"
:step-strictly="true"
:value-on-clear="5"
@change="changeBasicStyle('topN')"
/>
<span>{{ $t('chart.top_n_input_2') }}</span>
</el-form-item>
<el-form-item
class="form-item"
:class="'form-item-' + themes"
:label="t('chart.top_n_label')"
v-show="state.basicStyleForm.calcTopN"
>
<el-input
:effect="themes"
v-model="state.basicStyleForm.topNLabel"
size="small"
:maxlength="50"
@blur="changeBasicStyle('topNLabel')"
/>
</el-form-item>
</div>
<div class="alpha-setting" v-if="showProperty('innerRadius')">
<label class="alpha-label" :class="{ dark: 'dark' === themes }">
{{ t('chart.pie_inner_radius_percent') }}
@ -905,4 +951,13 @@ onMounted(() => {
}
}
}
.top-n-setting {
.ed-input-number {
width: 80px !important;
margin: 0 2px;
}
:deep(span) {
font-size: 12px;
}
}
</style>

View File

@ -1383,7 +1383,10 @@ export const DEFAULT_BASIC_STYLE: ChartBasicStyle = {
showZoom: true,
zoomButtonColor: '#aaa',
zoomBackground: '#fff',
tableLayoutMode: 'grid'
tableLayoutMode: 'grid',
calcTopN: false,
topN: 5,
topNLabel: '其他'
}
export const BASE_VIEW_CONFIG = {

View File

@ -23,7 +23,10 @@ const DEFAULT_DATA = []
export class Pie extends G2PlotChartView<PieOptions, G2Pie> {
axis: AxisType[] = PIE_AXIS_TYPE
properties = PIE_EDITOR_PROPERTY
propertyInner = PIE_EDITOR_PROPERTY_INNER
propertyInner: EditorPropertyInner = {
...PIE_EDITOR_PROPERTY_INNER,
'basic-style-selector': ['colors', 'alpha', 'radius', 'topN']
}
axisConfig = PIE_AXIS_CONFIG
drawChart(drawOptions: G2PlotDrawOptions<G2Pie>): G2Pie {
@ -212,9 +215,37 @@ export class Pie extends G2PlotChartView<PieOptions, G2Pie> {
protected configBasicStyle(chart: Chart, options: PieOptions): PieOptions {
const customAttr = parseJson(chart.customAttr)
const { basicStyle } = customAttr
const { data } = options
if (data?.length && basicStyle.calcTopN && data.length > basicStyle.topN) {
data.sort((a, b) => b.value - a.value)
const otherItems = data.splice(basicStyle.topN)
const initOtherItem = {
...data[0],
dynamicTooltipValue: [],
field: basicStyle.topNLabel,
name: basicStyle.topNLabel,
value: 0
}
const dynamicTotalMap: Record<string, number> = {}
otherItems.reduce((p, n) => {
p.value += n.value ?? 0
n.dynamicTooltipValue?.forEach(val => {
dynamicTotalMap[val.fieldId] = (dynamicTotalMap[val.fieldId] || 0) + val.value
})
return p
}, initOtherItem)
for (const key in dynamicTotalMap) {
initOtherItem.dynamicTooltipValue.push({
fieldId: key,
value: dynamicTotalMap[key]
})
}
data.push(initOtherItem)
}
return {
...options,
radius: customAttr.basicStyle.radius / 100
radius: basicStyle.radius / 100
}
}
setupDefaultOptions(chart: ChartObj): ChartObj {
@ -253,14 +284,15 @@ export class Pie extends G2PlotChartView<PieOptions, G2Pie> {
export class PieDonut extends Pie {
propertyInner: EditorPropertyInner = {
...PIE_EDITOR_PROPERTY_INNER,
'basic-style-selector': ['colors', 'alpha', 'radius', 'innerRadius']
'basic-style-selector': ['colors', 'alpha', 'radius', 'innerRadius', 'topN']
}
protected configBasicStyle(chart: Chart, options: PieOptions): PieOptions {
const customAttr = parseJson(chart.customAttr)
const tmp = super.configBasicStyle(chart, options)
const { basicStyle } = parseJson(chart.customAttr)
return {
...options,
radius: customAttr.basicStyle.radius / 100,
innerRadius: customAttr.basicStyle.innerRadius / 100
...tmp,
radius: basicStyle.radius / 100,
innerRadius: basicStyle.innerRadius / 100
}
}