feat(图表-漏斗图): 支持展示转化率

This commit is contained in:
jianneng-fit2cloud 2024-08-09 22:15:43 +08:00
parent 9c605faf9e
commit 40c5884a96
4 changed files with 147 additions and 15 deletions

View File

@ -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
}

View File

@ -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 }
]
</script>
<template>
@ -1251,6 +1260,54 @@ const isGroupBar = computed(() => {
{{ t('chart.show_gap') }}
</el-checkbox>
</el-form-item>
<el-form-item
class="form-item"
:class="'form-item-' + themes"
v-if="showProperty('conversionTag')"
>
<el-checkbox
:effect="themes"
@change="changeLabelAttr('conversionTag')"
v-model="state.labelForm.conversionTag.show"
>
转化率
</el-checkbox>
</el-form-item>
<div style="padding-left: 22px">
<el-row :gutter="8">
<el-col :span="12">
<el-form-item label="保留小数" class="form-item" :class="'form-item-' + themes">
<el-select
size="small"
style="width: 108px"
:effect="themes"
:disabled="!state.labelForm.conversionTag.show"
v-model.number="state.labelForm.conversionTag.precision"
@change="changeLabelAttr('conversionTag')"
>
<el-option
v-for="option in conversionPrecision"
:key="option.value"
:label="option.name"
:value="option.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="转化率名称" class="form-item" :class="'form-item-' + themes">
<el-input
:effect="themes"
v-model="state.labelForm.conversionTag.text"
size="small"
maxlength="100"
:disabled="!state.labelForm.conversionTag.show"
@blur="changeLabelAttr('conversionTag')"
/>
</el-form-item>
</el-col>
</el-row>
</div>
</el-form>
</template>

View File

@ -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,

View File

@ -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<FunnelOptions, G2Funnel> {
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<FunnelOptions, G2Funnel> {
xField: 'field',
yField: 'value',
appendPadding: getPadding(chart),
conversionTag: false,
interactions: [
{
type: 'legend-active',
@ -111,15 +112,58 @@ export class Funnel extends G2PlotChartView<FunnelOptions, G2Funnel> {
}
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<ChartAttr>
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<FunnelOptions, G2Funnel> {
}
customAttr.label = {
...label,
show: true
show: true,
showQuota: true,
conversionTag: {
show: false,
precision: 2,
text: '转化率'
}
}
const { legend } = customStyle
legend.show = false