forked from github/dataease
feat(图表): 饼图/环形图支持合并数据为其他
This commit is contained in:
parent
a8eee9ca20
commit
991a95bb5d
@ -1113,7 +1113,11 @@ export default {
|
|||||||
word_spacing: '文字间隔',
|
word_spacing: '文字间隔',
|
||||||
table_layout_mode: '展示形式',
|
table_layout_mode: '展示形式',
|
||||||
table_layout_grid: '平铺展示',
|
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: {
|
dataset: {
|
||||||
scope_edit: '仅编辑时生效',
|
scope_edit: '仅编辑时生效',
|
||||||
|
@ -217,6 +217,18 @@ declare interface ChartBasicStyle {
|
|||||||
* 地图缩放按钮背景颜色
|
* 地图缩放按钮背景颜色
|
||||||
*/
|
*/
|
||||||
zoomBackground: string
|
zoomBackground: string
|
||||||
|
/**
|
||||||
|
* 是否合并数据为其他
|
||||||
|
*/
|
||||||
|
calcTopN: boolean
|
||||||
|
/**
|
||||||
|
* 只展示 TopN 项,其他合并为一项
|
||||||
|
*/
|
||||||
|
topN: number
|
||||||
|
/**
|
||||||
|
* 其他项的标签
|
||||||
|
*/
|
||||||
|
topNLabel: string
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 表头属性
|
* 表头属性
|
||||||
|
@ -5,7 +5,11 @@ import { useI18n } from '@/hooks/web/useI18n'
|
|||||||
import CustomColorStyleSelect from '@/views/chart/components/editor/editor-style/components/CustomColorStyleSelect.vue'
|
import CustomColorStyleSelect from '@/views/chart/components/editor/editor-style/components/CustomColorStyleSelect.vue'
|
||||||
import { cloneDeep, defaultsDeep } from 'lodash-es'
|
import { cloneDeep, defaultsDeep } from 'lodash-es'
|
||||||
import { SERIES_NUMBER_FIELD } from '@antv/s2'
|
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 { t } = useI18n()
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
chart: {
|
chart: {
|
||||||
@ -466,6 +470,7 @@ onMounted(() => {
|
|||||||
<el-select
|
<el-select
|
||||||
v-model="state.fieldColumnWidth.fieldId"
|
v-model="state.fieldColumnWidth.fieldId"
|
||||||
:effect="themes"
|
:effect="themes"
|
||||||
|
:disabled="batchOptStatus"
|
||||||
@change="changeFieldColumn()"
|
@change="changeFieldColumn()"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
@ -482,6 +487,7 @@ onMounted(() => {
|
|||||||
:min="0"
|
:min="0"
|
||||||
:max="100"
|
:max="100"
|
||||||
:effect="themes"
|
:effect="themes"
|
||||||
|
:disabled="batchOptStatus"
|
||||||
@change="changeFieldColumnWidth()"
|
@change="changeFieldColumnWidth()"
|
||||||
>
|
>
|
||||||
<template #append>%</template>
|
<template #append>%</template>
|
||||||
@ -762,6 +768,46 @@ onMounted(() => {
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- pie/rose start -->
|
<!-- 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')">
|
<div class="alpha-setting" v-if="showProperty('innerRadius')">
|
||||||
<label class="alpha-label" :class="{ dark: 'dark' === themes }">
|
<label class="alpha-label" :class="{ dark: 'dark' === themes }">
|
||||||
{{ t('chart.pie_inner_radius_percent') }}
|
{{ 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>
|
</style>
|
||||||
|
@ -1383,7 +1383,10 @@ export const DEFAULT_BASIC_STYLE: ChartBasicStyle = {
|
|||||||
showZoom: true,
|
showZoom: true,
|
||||||
zoomButtonColor: '#aaa',
|
zoomButtonColor: '#aaa',
|
||||||
zoomBackground: '#fff',
|
zoomBackground: '#fff',
|
||||||
tableLayoutMode: 'grid'
|
tableLayoutMode: 'grid',
|
||||||
|
calcTopN: false,
|
||||||
|
topN: 5,
|
||||||
|
topNLabel: '其他'
|
||||||
}
|
}
|
||||||
|
|
||||||
export const BASE_VIEW_CONFIG = {
|
export const BASE_VIEW_CONFIG = {
|
||||||
|
@ -23,7 +23,10 @@ const DEFAULT_DATA = []
|
|||||||
export class Pie extends G2PlotChartView<PieOptions, G2Pie> {
|
export class Pie extends G2PlotChartView<PieOptions, G2Pie> {
|
||||||
axis: AxisType[] = PIE_AXIS_TYPE
|
axis: AxisType[] = PIE_AXIS_TYPE
|
||||||
properties = PIE_EDITOR_PROPERTY
|
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
|
axisConfig = PIE_AXIS_CONFIG
|
||||||
|
|
||||||
drawChart(drawOptions: G2PlotDrawOptions<G2Pie>): G2Pie {
|
drawChart(drawOptions: G2PlotDrawOptions<G2Pie>): G2Pie {
|
||||||
@ -212,9 +215,37 @@ export class Pie extends G2PlotChartView<PieOptions, G2Pie> {
|
|||||||
|
|
||||||
protected configBasicStyle(chart: Chart, options: PieOptions): PieOptions {
|
protected configBasicStyle(chart: Chart, options: PieOptions): PieOptions {
|
||||||
const customAttr = parseJson(chart.customAttr)
|
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 {
|
return {
|
||||||
...options,
|
...options,
|
||||||
radius: customAttr.basicStyle.radius / 100
|
radius: basicStyle.radius / 100
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setupDefaultOptions(chart: ChartObj): ChartObj {
|
setupDefaultOptions(chart: ChartObj): ChartObj {
|
||||||
@ -253,14 +284,15 @@ export class Pie extends G2PlotChartView<PieOptions, G2Pie> {
|
|||||||
export class PieDonut extends Pie {
|
export class PieDonut extends Pie {
|
||||||
propertyInner: EditorPropertyInner = {
|
propertyInner: EditorPropertyInner = {
|
||||||
...PIE_EDITOR_PROPERTY_INNER,
|
...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 {
|
protected configBasicStyle(chart: Chart, options: PieOptions): PieOptions {
|
||||||
const customAttr = parseJson(chart.customAttr)
|
const tmp = super.configBasicStyle(chart, options)
|
||||||
|
const { basicStyle } = parseJson(chart.customAttr)
|
||||||
return {
|
return {
|
||||||
...options,
|
...tmp,
|
||||||
radius: customAttr.basicStyle.radius / 100,
|
radius: basicStyle.radius / 100,
|
||||||
innerRadius: customAttr.basicStyle.innerRadius / 100
|
innerRadius: basicStyle.innerRadius / 100
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user