fix(图表): 修复双轴图左右轴配置相同指标是,标签配置不能分别配置的问题

#10841
This commit is contained in:
ulleo 2024-07-31 16:41:32 +08:00
parent d4738ffc84
commit c3baf983fc
3 changed files with 127 additions and 70 deletions

View File

@ -134,6 +134,9 @@ declare interface SeriesFormatter extends Axis {
* 显示极值 * 显示极值
*/ */
showExtremum?: boolean showExtremum?: boolean
optionLabel?: string
optionShowName?: string
} }
declare interface Axis extends ChartViewField { declare interface Axis extends ChartViewField {

View File

@ -4,7 +4,7 @@ import { useI18n } from '@/hooks/web/useI18n'
import { COLOR_PANEL, DEFAULT_LABEL } from '@/views/chart/components/editor/util/chart' import { COLOR_PANEL, DEFAULT_LABEL } from '@/views/chart/components/editor/util/chart'
import { ElIcon, ElSpace } from 'element-plus-secondary' import { ElIcon, ElSpace } from 'element-plus-secondary'
import { formatterType, unitType } from '../../../js/formatter' import { formatterType, unitType } from '../../../js/formatter'
import { defaultsDeep, cloneDeep, intersection, union, defaultTo } from 'lodash-es' import { defaultsDeep, cloneDeep, intersection, union, defaultTo, map } from 'lodash-es'
import { includesAny } from '../../util/StringUtils' import { includesAny } from '../../util/StringUtils'
import { fieldType } from '@/utils/attr' import { fieldType } from '@/utils/attr'
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain' import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
@ -51,18 +51,44 @@ const changeDataset = () => {
} }
const { batchOptStatus } = storeToRefs(dvMainStore) const { batchOptStatus } = storeToRefs(dvMainStore)
watch( watch(
() => props.chart.customAttr.label, [() => props.chart.customAttr.label, () => props.chart.customAttr.label.show],
() => { () => {
init() init()
}, },
{ deep: true } { deep: false }
) )
const yAxis = computed(() => { const yAxis = computed(() => {
return union(defaultTo(props.chart.yAxis, []), defaultTo(props.chart.yAxisExt, [])) if (props.chart.type.includes('chart-mix')) {
return union(
defaultTo(
map(props.chart.yAxis, y => {
return { ...y, axisType: 'yAxis', seriesId: y.id + '-yAxis' }
}),
[]
),
defaultTo(
map(props.chart.yAxisExt, y => {
return { ...y, axisType: 'yAxisExt', seriesId: y.id + '-yAxisExt' }
}),
[]
)
)
} else {
return defaultTo(
map(props.chart.yAxis, y => {
return { ...y, axisType: 'yAxis', seriesId: y.id + '-yAxis' }
}),
[]
)
}
})
const yAxisIds = computed(() => {
return map(yAxis.value, y => y.seriesId)
}) })
watch( watch(
[() => yAxis.value, () => props.chart.type], [() => yAxisIds.value, () => props.chart.type],
() => { () => {
initSeriesLabel() initSeriesLabel()
}, },
@ -94,14 +120,34 @@ const initSeriesLabel = () => {
let initFlag = false let initFlag = false
const themeColor = dvMainStore.canvasStyleData.dashboard.themeColor const themeColor = dvMainStore.canvasStyleData.dashboard.themeColor
const axisMap = yAxis.value.reduce((pre, next) => { const axisMap = yAxis.value.reduce((pre, next) => {
const optionLabel: string = `${next.chartShowName ?? next.name}${
next.summary !== '' ? '(' + t('chart.' + next.summary) + ')' : ''
}${
props.chart.type.includes('chart-mix')
? next.axisType === 'yAxis'
? '(左轴)'
: '(右轴)'
: ''
}` as string
const optionShowName: string = `${next.chartShowName ?? next.name}${
next.summary !== '' ? '(' + t('chart.' + next.summary) + ')' : ''
}${
props.chart.type.includes('chart-mix')
? next.axisType === 'yAxis'
? '(左轴)'
: '(右轴)'
: ''
}` as string
let tmp = { let tmp = {
...next, ...next,
optionLabel: optionLabel,
optionShowName: optionShowName,
show: true, show: true,
color: themeColor === 'dark' ? '#fff' : '#000', color: themeColor === 'dark' ? '#fff' : '#000',
fontSize: COMPUTED_DEFAULT_LABEL.value.fontSize, fontSize: COMPUTED_DEFAULT_LABEL.value.fontSize,
showExtremum: false showExtremum: false
} as SeriesFormatter } as SeriesFormatter
if (seriesAxisMap[next.id]) { if (seriesAxisMap[next.seriesId]) {
tmp = { tmp = {
...tmp, ...tmp,
formatterCfg: seriesAxisMap[next.id].formatterCfg, formatterCfg: seriesAxisMap[next.id].formatterCfg,
@ -114,18 +160,19 @@ const initSeriesLabel = () => {
initFlag = true initFlag = true
} }
formatter.push(tmp) formatter.push(tmp)
pre[next.id] = tmp next.seriesId = next.seriesId ?? next.id
pre[next.seriesId] = tmp
return pre return pre
}, {}) }, {})
// //
if (initFlag) { if (initFlag) {
changeLabelAttr('seriesLabelFormatter', false) changeLabelAttr('seriesLabelFormatter', false)
} }
if (!curSeriesFormatter.value || !axisMap[curSeriesFormatter.value.id]) { if (!curSeriesFormatter.value || !axisMap[curSeriesFormatter.value.seriesId]) {
curSeriesFormatter.value = axisMap[formatter[0].id] curSeriesFormatter.value = axisMap[formatter[0].seriesId]
return return
} }
curSeriesFormatter.value = axisMap[curSeriesFormatter.value.id] curSeriesFormatter.value = axisMap[curSeriesFormatter.value.seriesId]
} }
const labelPositionR = [ const labelPositionR = [
@ -785,36 +832,29 @@ const isGroupBar = computed(() => {
:teleported="false" :teleported="false"
:disabled="!formatterEditable" :disabled="!formatterEditable"
ref="formatterSelector" ref="formatterSelector"
value-key="id" value-key="seriesId"
class="series-select" class="series-select"
size="small" size="small"
> >
<template #prefix> <template #prefix>
<el-icon v-if="curSeriesFormatter.id" style="font-size: 14px"> <el-icon v-if="curSeriesFormatter.seriesId" style="font-size: 14px">
<Icon <Icon
:className="`field-icon-${fieldType[curSeriesFormatter.deType]}`" :className="`field-icon-${fieldType[curSeriesFormatter.deType]}`"
:name="`field_${fieldType[curSeriesFormatter.deType]}`" :name="`field_${fieldType[curSeriesFormatter.deType]}`"
/> />
</el-icon> </el-icon>
</template> </template>
<el-option <template v-for="item in state.labelForm.seriesLabelFormatter" :key="item.seriesId">
class="series-select-option" <el-option class="series-select-option" :value="item" :label="item.optionLabel">
:key="item.id" <el-icon style="margin-right: 8px">
:value="item" <Icon
:label="`${item.chartShowName ?? item.name}${ :className="`field-icon-${fieldType[item.deType]}`"
item.summary !== '' ? '(' + t('chart.' + item.summary) + ')' : '' :name="`field_${fieldType[item.deType]}`"
}`" />
v-for="item in state.labelForm.seriesLabelFormatter" </el-icon>
> {{ item.optionShowName }}
<el-icon style="margin-right: 8px"> </el-option>
<Icon </template>
:className="`field-icon-${fieldType[item.deType]}`"
:name="`field_${fieldType[item.deType]}`"
/>
</el-icon>
{{ item.chartShowName ?? item.name }}
{{ item.summary !== '' ? '(' + t('chart.' + item.summary) + ')' : '' }}
</el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<template v-if="curSeriesFormatter?.id"> <template v-if="curSeriesFormatter?.id">

View File

@ -181,47 +181,61 @@ export class ColumnLineMix extends G2PlotChartView<DualAxesOptions, DualAxes> {
} }
const labelAttr = parseJson(chart.customAttr).label const labelAttr = parseJson(chart.customAttr).label
const formatterMap = labelAttr.seriesLabelFormatter?.reduce((pre, next) => { const axisFormatterMap = {}
pre[next.id] = next labelAttr.seriesLabelFormatter?.forEach(attr => {
return pre if (!axisFormatterMap[attr.axisType]) {
}, {}) axisFormatterMap[attr.axisType] = []
tempLabel.style.fill = DEFAULT_LABEL.color
const label = {
fields: [],
...tempLabel,
offsetY: -8,
formatter: (data: Datum) => {
if (!labelAttr.seriesLabelFormatter?.length) {
return data.value
}
const labelCfg = formatterMap?.[data.quotaList[0].id] as SeriesFormatter
if (!labelCfg) {
return data.value
}
if (!labelCfg.show) {
return
}
const value = valueFormatter(data.value, labelCfg.formatterCfg)
const group = new G2PlotChartView.engine.Group({})
group.addShape({
type: 'text',
attrs: {
x: 0,
y: 0,
text: value,
textAlign: 'start',
textBaseline: 'top',
fontSize: labelCfg.fontSize,
fill: labelCfg.color
}
})
return group
} }
} axisFormatterMap[attr.axisType].push(attr)
if (tmpOption.geometryOptions) { })
tmpOption.geometryOptions[0].label = label const axisTypes = ['yAxis', 'yAxisExt']
tmpOption.geometryOptions[1].label = label axisTypes.forEach(axisType => {
} const formatterMap = axisFormatterMap[axisType]?.reduce((pre, next) => {
pre[next.id] = next
return pre
}, {})
tempLabel.style.fill = DEFAULT_LABEL.color
const label = {
fields: [],
...tempLabel,
offsetY: -8,
formatter: (data: Datum) => {
if (!labelAttr.seriesLabelFormatter?.length) {
return data.value
}
const labelCfg = formatterMap?.[data.quotaList[0].id] as SeriesFormatter
if (!labelCfg) {
return data.value
}
if (!labelCfg.show) {
return
}
const value = valueFormatter(data.value, labelCfg.formatterCfg)
const group = new G2PlotChartView.engine.Group({})
group.addShape({
type: 'text',
attrs: {
x: 0,
y: 0,
text: value,
textAlign: 'start',
textBaseline: 'top',
fontSize: labelCfg.fontSize,
fill: labelCfg.color
}
})
return group
}
}
if (tmpOption.geometryOptions) {
if (axisType === 'yAxis') {
tmpOption.geometryOptions[0].label = label
} else if (axisType === 'yAxisExt') {
tmpOption.geometryOptions[1].label = label
}
}
})
return tmpOption return tmpOption
} }