diff --git a/core/core-frontend/src/models/chart/chart-attr.d.ts b/core/core-frontend/src/models/chart/chart-attr.d.ts index d1bbd37b84..3810916b25 100644 --- a/core/core-frontend/src/models/chart/chart-attr.d.ts +++ b/core/core-frontend/src/models/chart/chart-attr.d.ts @@ -813,6 +813,11 @@ declare interface ChartLabelAttr { * 显示极值 */ showExtremum?: boolean + + /** + * 转化率标签 + */ + conversionTag: ConversionTagAtt } /** * 提示设置 @@ -1080,3 +1085,18 @@ declare interface CarouselAttr { */ intervalTime: number } + +declare interface ConversionTagAtt { + /** + * 是否显示 + */ + show: boolean + /** + * 文本 + */ + text: string + /** + * 精度 + */ + precision: number +} diff --git a/core/core-frontend/src/views/chart/components/editor/editor-style/components/LabelSelector.vue b/core/core-frontend/src/views/chart/components/editor/editor-style/components/LabelSelector.vue index b733d039c6..73b0962a27 100644 --- a/core/core-frontend/src/views/chart/components/editor/editor-style/components/LabelSelector.vue +++ b/core/core-frontend/src/views/chart/components/editor/editor-style/components/LabelSelector.vue @@ -2,7 +2,7 @@ import { computed, onMounted, PropType, reactive, ref, watch } from 'vue' import { useI18n } from '@/hooks/web/useI18n' import { COLOR_PANEL, DEFAULT_LABEL } from '@/views/chart/components/editor/util/chart' -import { ElIcon, ElSpace } from 'element-plus-secondary' +import { ElFormItem, ElIcon, ElInput, ElSpace } from 'element-plus-secondary' import { formatterType, unitType } from '../../../js/formatter' import { defaultsDeep, cloneDeep, intersection, union, defaultTo, map } from 'lodash-es' import { includesAny } from '../../util/StringUtils' @@ -231,7 +231,8 @@ const state = reactive<{ labelForm: ChartLabelAttr | any }>({ labelForm: { quotaLabelFormatter: DEFAULT_LABEL.quotaLabelFormatter, seriesLabelFormatter: [], - labelFormatter: DEFAULT_LABEL.labelFormatter + labelFormatter: DEFAULT_LABEL.labelFormatter, + conversionTag: DEFAULT_LABEL.conversionTag } }) @@ -255,6 +256,9 @@ const init = () => { } } const checkLabelContent = contentProp => { + if (chartType.value === 'funnel') { + return false + } const propIntersection = intersection(props.propertyInner, [ 'showDimension', 'showQuota', @@ -373,6 +377,11 @@ onMounted(() => { const isGroupBar = computed(() => { return props.chart.type === 'bar-group' }) +const conversionPrecision = [ + { name: t('chart.reserve_zero'), value: 0 }, + { name: t('chart.reserve_one'), value: 1 }, + { name: t('chart.reserve_two'), value: 2 } +] diff --git a/core/core-frontend/src/views/chart/components/editor/util/chart.ts b/core/core-frontend/src/views/chart/components/editor/util/chart.ts index 465c81107f..3457ea031e 100644 --- a/core/core-frontend/src/views/chart/components/editor/util/chart.ts +++ b/core/core-frontend/src/views/chart/components/editor/util/chart.ts @@ -324,7 +324,12 @@ export const DEFAULT_LABEL: ChartLabelAttr = { showDimension: true, showQuota: false, showProportion: true, - seriesLabelFormatter: [] + seriesLabelFormatter: [], + conversionTag: { + show: false, + precision: 2, + text: '转化率' + } } export const DEFAULT_TOOLTIP: ChartTooltipAttr = { show: true, diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/others/funnel.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/others/funnel.ts index 0f9aa41d82..35d1b652e1 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/others/funnel.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/others/funnel.ts @@ -1,8 +1,10 @@ import type { FunnelOptions, Funnel as G2Funnel } from '@antv/g2plot/esm/plots/funnel' import { G2PlotChartView, G2PlotDrawOptions } from '../../types/impl/g2plot' -import { flow, setUpSingleDimensionSeriesColor } from '@/views/chart/components/js/util' +import { flow, parseJson, setUpSingleDimensionSeriesColor } from '@/views/chart/components/js/util' import { getPadding } from '../../common/common_antv' import { useI18n } from '@/hooks/web/useI18n' +import { Datum } from '@antv/g2plot/esm/types/common' +import { valueFormatter } from '@/views/chart/components/js/formatter' const { t } = useI18n() @@ -23,7 +25,7 @@ export class Funnel extends G2PlotChartView { propertyInner: EditorPropertyInner = { 'background-overall-component': ['all'], 'basic-style-selector': ['colors', 'alpha', 'seriesColor'], - 'label-selector': ['fontSize', 'color', 'hPosition', 'labelFormatter'], + 'label-selector': ['fontSize', 'color', 'hPosition', 'showQuota', 'conversionTag'], 'tooltip-selector': ['color', 'fontSize', 'backgroundColor', 'seriesTooltipFormatter', 'show'], 'title-selector': [ 'show', @@ -64,7 +66,6 @@ export class Funnel extends G2PlotChartView { xField: 'field', yField: 'value', appendPadding: getPadding(chart), - conversionTag: false, interactions: [ { type: 'legend-active', @@ -111,15 +112,58 @@ export class Funnel extends G2PlotChartView { } protected configLabel(chart: Chart, options: FunnelOptions): FunnelOptions { - const tmpOptions = super.configLabel(chart, options) - if (!tmpOptions.label) { - return tmpOptions + let label + let conversionTag + let customAttr: DeepPartial + if (chart.customAttr) { + customAttr = parseJson(chart.customAttr) + const showQuota = customAttr.label.showQuota + const l = customAttr.label + if (customAttr.label?.show) { + // label + if (showQuota) { + label = { + position: l.position, + layout: [{ type: 'limit-in-canvas' }], + style: { + fill: l.color, + fontSize: l.fontSize + }, + formatter: function (param: Datum) { + return valueFormatter(param.value, l.quotaLabelFormatter) + } + } + const position = label.position + if (position === 'right') { + label.offsetX = -40 + } + } + // 转化率 + const conversionTagAtt = parseJson(chart.customAttr).label.conversionTag + if (conversionTagAtt && conversionTagAtt.show) { + conversionTag = { + style: { + fill: l.color, + fontSize: l.fontSize + }, + formatter: datum => { + const rate = ( + (datum['$$conversion$$'][1] / datum['$$conversion$$'][0]) * + 100 + ).toFixed(conversionTagAtt.precision) + return `${conversionTagAtt.text ?? ''}${rate}%` + } + } + } + } + return { + ...options, + label, + conversionTag, + maxSize: conversionTag ? 0.8 : 1 + } } - const position = tmpOptions.label.position - if (position === 'right') { - tmpOptions.label.offsetX = -40 - } - return tmpOptions + return options } public setupSeriesColor(chart: ChartObj, data?: any[]): ChartBasicStyle['seriesColor'] { @@ -142,7 +186,13 @@ export class Funnel extends G2PlotChartView { } customAttr.label = { ...label, - show: true + show: true, + showQuota: true, + conversionTag: { + show: false, + precision: 2, + text: '转化率' + } } const { legend } = customStyle legend.show = false