From 0bbfb07ef9c5c94f57fb1a23776538c2e6375d0a Mon Sep 17 00:00:00 2001 From: jianneng-fit2cloud Date: Tue, 24 Dec 2024 17:54:27 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E5=9B=BE=E8=A1=A8):=20=E6=9F=B1=E6=9D=A1?= =?UTF-8?q?=E5=9B=BE=E6=94=AF=E6=8C=81=E6=9D=A1=E4=BB=B6=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/core-frontend/src/locales/en-US.ts | 5 +- core/core-frontend/src/locales/en.ts | 5 +- core/core-frontend/src/locales/tw.ts | 5 +- core/core-frontend/src/locales/zh-CN.ts | 5 +- .../components/dialog/LineThresholdEdit.vue | 147 +++++----- .../components/js/panel/charts/bar/bar.ts | 64 ++++- .../js/panel/charts/bar/bidirectional-bar.ts | 9 +- .../components/js/panel/charts/bar/common.ts | 9 +- .../js/panel/charts/bar/horizontal-bar.ts | 9 +- .../js/panel/charts/bar/progress-bar.ts | 11 +- .../js/panel/charts/bar/range-bar.ts | 2 +- .../js/panel/charts/bar/waterfall.ts | 17 +- .../components/js/panel/common/common_antv.ts | 256 +++++++++++++++++- .../components/js/panel/types/impl/g2plot.ts | 7 +- 14 files changed, 452 insertions(+), 99 deletions(-) diff --git a/core/core-frontend/src/locales/en-US.ts b/core/core-frontend/src/locales/en-US.ts index fddba51861..8b62a91b35 100644 --- a/core/core-frontend/src/locales/en-US.ts +++ b/core/core-frontend/src/locales/en-US.ts @@ -1936,7 +1936,10 @@ export default { circle_packing_value: 'Circle Size', circle_packing_border_color: 'Border color', circle_packing_border_width: 'Border width', - circle_packing_padding: 'Circle padding' + circle_packing_padding: 'Circle padding', + increase: 'Increase', + decrease: 'Decrease', + total: 'Total' }, dataset: { scope_edit: 'Only effective when editing', diff --git a/core/core-frontend/src/locales/en.ts b/core/core-frontend/src/locales/en.ts index 041c42aaad..38128cf1dd 100644 --- a/core/core-frontend/src/locales/en.ts +++ b/core/core-frontend/src/locales/en.ts @@ -1975,7 +1975,10 @@ Scatter chart (bubble) chart: {a} (series name), {b} (data name), {c} (value arr circle_packing_value: 'Circle size', circle_packing_border_color: 'Border color', circle_packing_border_width: 'Border width', - circle_packing_padding: 'Circle padding' + circle_packing_padding: 'Circle padding', + increase: 'Increase', + decrease: 'Decrease', + total: 'Total' }, dataset: { scope_edit: 'Only effective when editing', diff --git a/core/core-frontend/src/locales/tw.ts b/core/core-frontend/src/locales/tw.ts index 4bb23df1da..1b98a53eb9 100644 --- a/core/core-frontend/src/locales/tw.ts +++ b/core/core-frontend/src/locales/tw.ts @@ -1931,7 +1931,10 @@ export default { circle_packing_value: '圓形大小', circle_packing_border_color: '邊線顏色', circle_packing_border_width: '邊線寬度', - circle_packing_padding: '圓形間距' + circle_packing_padding: '圓形間距', + increase: '增加', + decrease: '減少', + total: '合計' }, dataset: { scope_edit: '僅編輯時生效', diff --git a/core/core-frontend/src/locales/zh-CN.ts b/core/core-frontend/src/locales/zh-CN.ts index 056ab229ab..f3a2113718 100644 --- a/core/core-frontend/src/locales/zh-CN.ts +++ b/core/core-frontend/src/locales/zh-CN.ts @@ -1933,7 +1933,10 @@ export default { circle_packing_value: '圆形大小', circle_packing_border_color: '边线颜色', circle_packing_border_width: '边线宽度', - circle_packing_padding: '圆形间距' + circle_packing_padding: '圆形间距', + increase: '增加', + decrease: '减少', + total: '合计' }, dataset: { scope_edit: '仅编辑时生效', diff --git a/core/core-frontend/src/views/chart/components/editor/editor-senior/components/dialog/LineThresholdEdit.vue b/core/core-frontend/src/views/chart/components/editor/editor-senior/components/dialog/LineThresholdEdit.vue index 3211947e01..919274389e 100644 --- a/core/core-frontend/src/views/chart/components/editor/editor-senior/components/dialog/LineThresholdEdit.vue +++ b/core/core-frontend/src/views/chart/components/editor/editor-senior/components/dialog/LineThresholdEdit.vue @@ -34,83 +34,77 @@ const thresholdCondition = { max: '1', type: 'fixed' } -const valueOptions = computed(() => { - if (props.chart.type === 'symbolic-map') { - return [ +const expressionList = [ + { + label: '', + options: [ { - label: '', - options: [ - { - value: 'eq', - label: t('chart.filter_eq') - }, - { - value: 'not_eq', - label: t('chart.filter_not_eq') - } - ] + value: 'eq', + label: t('chart.filter_eq') }, { - label: '', - options: [ - { - value: 'lt', - label: t('chart.filter_lt') - }, - { - value: 'gt', - label: t('chart.filter_gt') - } - ] + value: 'not_eq', + label: t('chart.filter_not_eq') + } + ] + }, + { + label: '', + options: [ + { + value: 'lt', + label: t('chart.filter_lt') }, { - label: '', - options: [ - { - value: 'le', - label: t('chart.filter_le') - }, - { - value: 'ge', - label: t('chart.filter_ge') - } - ] + value: 'gt', + label: t('chart.filter_gt') + } + ] + }, + { + label: '', + options: [ + { + value: 'le', + label: t('chart.filter_le') }, { - label: '', - options: [ - { - value: 'between', - label: t('chart.filter_between') - } - ] + value: 'ge', + label: t('chart.filter_ge') + } + ] + }, + { + label: '', + options: [ + { + value: 'between', + label: t('chart.filter_between') } ] } - return [ - { - label: '', - options: [ - { - value: 'lt', - label: t('chart.filter_lt') - }, - { - value: 'gt', - label: t('chart.filter_gt') - } - ] - }, - { - label: '', - options: [ - { - value: 'between', - label: t('chart.filter_between') - } - ] - } - ] +] +const filterExpressionListByValue = (list, values) => { + return list + .map(group => ({ + ...group, + options: group.options.filter(option => values.includes(option.value)) + })) + .filter(group => group.options.length > 0) +} +const valueOptions = computed(() => { + if (props.chart.type === 'symbolic-map') { + return filterExpressionListByValue(expressionList, [ + 'eq', + 'not_eq', + 'lt', + 'gt', + 'le', + 'ge', + 'between' + ]) + } + return filterExpressionListByValue(expressionList, ['lt', 'gt', 'le', 'ge', 'between']) }) const predefineColors = COLOR_PANEL @@ -142,11 +136,30 @@ const isSymbolicMap = computed(() => { return props.chart.type === 'symbolic-map' }) +const isProgressBar = computed(() => { + return props.chart.type === 'progress-bar' +}) + +const isBidirectionalBar = computed(() => { + return props.chart.type === 'bidirectional-bar' +}) + +const isRangeBar = computed(() => { + return props.chart.type === 'bar-range' +}) + const initFields = () => { let fields = [] if (isSymbolicMap.value) { const extBubble = JSON.parse(JSON.stringify(props.chart.extBubble)) fields = [...extBubble] + } else if (isProgressBar.value) { + const yAxisExt = JSON.parse(JSON.stringify(props.chart.yAxisExt)) + fields = [...yAxisExt] + } else if (isBidirectionalBar.value || isRangeBar.value) { + const yAxis = JSON.parse(JSON.stringify(props.chart.yAxis)) + const yAxisExt = JSON.parse(JSON.stringify(props.chart.yAxisExt)) + fields = [...yAxis, ...yAxisExt] } else { const yAxis = JSON.parse(JSON.stringify(props.chart.yAxis)) fields = [...yAxis] diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/bar/bar.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/bar/bar.ts index c1fd21efaa..a81fe56e81 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/bar/bar.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/bar/bar.ts @@ -7,6 +7,7 @@ import { import { flow, hexColorToRGBA, + hexToRgba, parseJson, setUpGroupSeriesColor, setUpStackSeriesColor @@ -243,7 +244,8 @@ export class Bar extends G2PlotChartView { this.configXAxis, this.configYAxis, this.configSlider, - this.configAnalyse + this.configAnalyse, + this.configBarConditions )(chart, options, {}, this) } @@ -396,7 +398,8 @@ export class StackBar extends Bar { this.configXAxis, this.configYAxis, this.configSlider, - this.configAnalyse + this.configAnalyse, + this.configBarConditions )(chart, options, {}, this) } @@ -477,7 +480,8 @@ export class GroupBar extends StackBar { this.configXAxis, this.configYAxis, this.configSlider, - this.configAnalyse + this.configAnalyse, + this.configBarConditions )(chart, options, {}, this) } @@ -565,6 +569,54 @@ export class GroupStackBar extends StackBar { } } + protected customConfigBarConditions(chart: Chart, options: ColumnOptions): ColumnOptions { + const { threshold } = parseJson(chart.senior) + if (!threshold.enable) return options + const conditions = threshold.lineThreshold ?? [] + const { basicStyle } = parseJson(chart.customAttr) + // 辅助函数:获取颜色,根据条件以及值计算 + const getColorByConditions = (currentValue: number) => { + for (let i = 0; i < conditions.length; i++) { + for (let j = 0; j < conditions[i].conditions?.length; j++) { + const tc = conditions[i].conditions[j] + if ( + (tc.term === 'between' && currentValue >= tc.min && currentValue <= tc.max) || + (tc.term === 'lt' && currentValue < tc.value) || + (tc.term === 'le' && currentValue <= tc.value) || + (tc.term === 'gt' && currentValue > tc.value) || + (tc.term === 'ge' && currentValue >= tc.value) + ) { + let tmpColor = tc.color + if (basicStyle.gradient) { + const tmp = hexToRgba(tmpColor, basicStyle.alpha) + tmpColor = setGradientColor(tmp, true, 270) + } + return { fill: tmpColor } + } + } + } + } + const tmpOptions = { + ...options, + columnStyle: data => { + return getColorByConditions(data.value) + }, + tooltip: { + ...options.tooltip, + customItems: originalItems => { + originalItems.forEach(item => { + const color = getColorByConditions(item.data?.value) + if (color) { + item.color = color.fill + } + }) + return originalItems + } + } + } + return tmpOptions + } + protected setupOptions(chart: Chart, options: ColumnOptions): ColumnOptions { return flow( this.configTheme, @@ -577,7 +629,8 @@ export class GroupStackBar extends StackBar { this.configXAxis, this.configYAxis, this.configSlider, - this.configAnalyse + this.configAnalyse, + this.customConfigBarConditions )(chart, options, {}, this) } @@ -662,7 +715,8 @@ export class PercentageStackBar extends GroupStackBar { this.configXAxis, this.configYAxis, this.configSlider, - this.configAnalyse + this.configAnalyse, + this.configBarConditions )(chart, options, {}, this) } constructor() { diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/bar/bidirectional-bar.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/bar/bidirectional-bar.ts index 1890c1a2f8..708f6aeb70 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/bar/bidirectional-bar.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/bar/bidirectional-bar.ts @@ -63,7 +63,8 @@ export class BidirectionalHorizontalBar extends G2PlotChartView< 'tooltip-selector', 'function-cfg', 'jump-set', - 'linkage' + 'linkage', + 'threshold' ] propertyInner = { 'background-overall-component': ['all'], @@ -96,7 +97,8 @@ export class BidirectionalHorizontalBar extends G2PlotChartView< 'legend-selector': ['icon', 'orient', 'fontSize', 'color', 'hPosition', 'vPosition'], 'function-cfg': ['emptyDataStrategy'], 'label-selector': ['hPosition', 'vPosition', 'seriesLabelFormatter'], - 'tooltip-selector': ['fontSize', 'color', 'backgroundColor', 'seriesTooltipFormatter', 'show'] + 'tooltip-selector': ['fontSize', 'color', 'backgroundColor', 'seriesTooltipFormatter', 'show'], + threshold: ['lineThreshold'] } selectorSpec: EditorSelectorSpec = { @@ -565,7 +567,8 @@ export class BidirectionalHorizontalBar extends G2PlotChartView< this.configYAxis, this.configAnalyse, this.configSlider, - this.configEmptyDataStrategy + this.configEmptyDataStrategy, + this.configBarConditions )(chart, options) } diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/bar/common.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/bar/common.ts index 8c1b2a3238..6421d1860b 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/bar/common.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/bar/common.ts @@ -11,7 +11,8 @@ export const BAR_EDITOR_PROPERTY: EditorProperty[] = [ 'function-cfg', 'assist-line', 'jump-set', - 'linkage' + 'linkage', + 'threshold' ] export const BAR_RANGE_EDITOR_PROPERTY: EditorProperty[] = [ 'background-overall-component', @@ -25,7 +26,8 @@ export const BAR_RANGE_EDITOR_PROPERTY: EditorProperty[] = [ 'legend-selector', 'function-cfg', 'jump-set', - 'linkage' + 'linkage', + 'threshold' ] export const BAR_EDITOR_PROPERTY_INNER: EditorPropertyInner = { @@ -68,7 +70,8 @@ export const BAR_EDITOR_PROPERTY_INNER: EditorPropertyInner = { 'fontShadow' ], 'legend-selector': ['icon', 'orient', 'fontSize', 'color', 'hPosition', 'vPosition'], - 'function-cfg': ['slider', 'emptyDataStrategy'] + 'function-cfg': ['slider', 'emptyDataStrategy'], + threshold: ['lineThreshold'] } export const BAR_AXIS_TYPE: AxisType[] = [ diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/bar/horizontal-bar.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/bar/horizontal-bar.ts index 349e92c2db..6064f37db7 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/bar/horizontal-bar.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/bar/horizontal-bar.ts @@ -277,7 +277,8 @@ export class HorizontalBar extends G2PlotChartView { this.configXAxis, this.configYAxis, this.configSlider, - this.configAnalyseHorizontal + this.configAnalyseHorizontal, + this.configBarConditions )(chart, options, {}, this) } @@ -394,7 +395,8 @@ export class HorizontalStackBar extends HorizontalBar { this.configXAxis, this.configYAxis, this.configSlider, - this.configAnalyseHorizontal + this.configAnalyseHorizontal, + this.configBarConditions )(chart, options, {}, this) } @@ -484,7 +486,8 @@ export class HorizontalPercentageStackBar extends HorizontalStackBar { this.configXAxis, this.configYAxis, this.configSlider, - this.configAnalyseHorizontal + this.configAnalyseHorizontal, + this.configBarConditions )(chart, options, {}, this) } diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/bar/progress-bar.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/bar/progress-bar.ts index 1e34063670..0d28c7446f 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/bar/progress-bar.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/bar/progress-bar.ts @@ -48,7 +48,8 @@ export class ProgressBar extends G2PlotChartView { 'title-selector', 'function-cfg', 'jump-set', - 'linkage' + 'linkage', + 'threshold' ] propertyInner = { ...BAR_EDITOR_PROPERTY_INNER, @@ -67,7 +68,8 @@ export class ProgressBar extends G2PlotChartView { 'position', 'showLengthLimit' ], - 'function-cfg': ['emptyDataStrategy'] + 'function-cfg': ['emptyDataStrategy'], + threshold: ['lineThreshold'] } axis: AxisType[] = [...BAR_AXIS_TYPE, 'yAxisExt'] protected baseOptions: BarOptions = { @@ -106,7 +108,7 @@ export class ProgressBar extends G2PlotChartView { // 目标与当前都为负 负向小于0为0 if (target < 0 && current < 0) { const completionRate = (2 - current / target) * 100 - return Math.max(completionRate, 0) + return Number(Math.max(completionRate, 0).toFixed(2)) } return 0 } @@ -374,7 +376,8 @@ export class ProgressBar extends G2PlotChartView { this.configTooltip, this.configLegend, this.configYAxis, - this.configEmptyDataStrategy + this.configEmptyDataStrategy, + this.configBarConditions )(chart, options) } diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/bar/range-bar.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/bar/range-bar.ts index 0fa6359d0d..d2e103ffa4 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/bar/range-bar.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/bar/range-bar.ts @@ -46,7 +46,7 @@ export class RangeBar extends G2PlotChartView { type: 'q' } } - properties = BAR_RANGE_EDITOR_PROPERTY + properties = BAR_RANGE_EDITOR_PROPERTY.filter(p => p !== 'threshold') propertyInner = { ...BAR_EDITOR_PROPERTY_INNER, 'label-selector': ['hPosition', 'color', 'fontSize', 'labelFormatter', 'showGap'], diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/bar/waterfall.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/bar/waterfall.ts index e905030c08..57f49e0738 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/bar/waterfall.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/bar/waterfall.ts @@ -29,7 +29,8 @@ export class Waterfall extends G2PlotChartView { 'title-selector', 'legend-selector', 'x-axis-selector', - 'y-axis-selector' + 'y-axis-selector', + 'threshold' ] propertyInner: EditorPropertyInner = { 'background-overall-component': ['all'], @@ -71,7 +72,8 @@ export class Waterfall extends G2PlotChartView { 'axisLabel', 'axisLabelFormatter', 'showLengthLimit' - ] + ], + threshold: ['lineThreshold'] } axis: AxisType[] = ['xAxis', 'yAxis', 'filter', 'drill', 'extLabel', 'extTooltip'] axisConfig = { @@ -155,7 +157,7 @@ export class Waterfall extends G2PlotChartView { return { ...options, total: { - label: '合计', + label: t('chart.total'), style: { fill: setGradientColor(hexColorToRGBA(totalColorRgba, alpha), gradient, 270) } @@ -275,7 +277,7 @@ export class Waterfall extends G2PlotChartView { ...tmp.legend, items: [ { - name: '增加', + name: t('chart.increase'), value: '', marker: { style: { @@ -284,7 +286,7 @@ export class Waterfall extends G2PlotChartView { } }, { - name: '减少', + name: t('chart.decrease'), value: '', marker: { style: { @@ -293,7 +295,7 @@ export class Waterfall extends G2PlotChartView { } }, { - name: '合计', + name: t('chart.total'), value: '', marker: { style: { @@ -315,7 +317,8 @@ export class Waterfall extends G2PlotChartView { this.configTooltip, this.configXAxis, this.configYAxis, - this.configMeta + this.configMeta, + this.configBarConditions )(chart, options) } diff --git a/core/core-frontend/src/views/chart/components/js/panel/common/common_antv.ts b/core/core-frontend/src/views/chart/components/js/panel/common/common_antv.ts index b673f5abc9..e2d90fa386 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/common/common_antv.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/common/common_antv.ts @@ -1,4 +1,4 @@ -import { hexColorToRGBA, isAlphaColor, isTransparent, measureText, parseJson } from '../../util' +import { hexColorToRGBA, hexToRgba, measureText, parseJson } from '../../util' import { DEFAULT_BASIC_STYLE, DEFAULT_LEGEND_STYLE, @@ -34,6 +34,8 @@ import { centroid } from '@turf/centroid' import type { Plot } from '@antv/g2plot' import type { PickOptions } from '@antv/g2plot/lib/core/plot' import { defaults } from 'lodash-es' +import { useI18n } from '@/hooks/web/useI18n' +const { t: tI18n } = useI18n() export function getPadding(chart: Chart): number[] { if (chart.drill) { @@ -1600,3 +1602,255 @@ export function configYaxisTitleLengthLimit(chart, plot) { ev.view.options.axes.yAxisExt.title.text = wrappedTitle }) } + +/** + * 处理柱条图的条件样式 + * @param chart + * @param options + */ +export function handelConditionsStyle(chart: Chart, options: O) { + const { threshold } = parseJson(chart.senior) + if (!threshold.enable) return options + const conditions = threshold.lineThreshold ?? [] + const { basicStyle } = parseJson(chart.customAttr) + // 获取图表类型 + const chartType = { + ...getChartTypeFlags(chart) + } + // 图表字段,用于rawFields + const { xField, yField, groupField, seriesField, color } = options + // 获取基础颜色 + const colors = + color && Array.isArray(color) + ? color + : basicStyle.gradient + ? getGradientColors(basicStyle, chartType) + : basicStyle.colors + const seriesFields = getSeriesFields(chart, options, chartType) + // 系列字段个数,瀑布图时默认3个,增加、减少、合计,当其他图表系列字段为空时,默认为1 + const seriesLength = chartType.isWaterfall ? 3 : seriesFields.length ? seriesFields.length : 1 + const seriesFieldLengthRef = { current: 0 } + const seriesFieldColorMap = getSeriesFieldColorMap(colors, chartType) + let rawFields = [xField, groupField, seriesField] + // 对称柱条图时,需要添加两个y轴字段 + rawFields = chartType.isBidirectionalBar + ? rawFields.concat(yField[0], yField[1]) + : rawFields.concat(yField) + const tmpOption = { + ...options, + rawFields, + color: ref => + getColor( + ref, + seriesFieldColorMap, + colors, + seriesFieldLengthRef, + seriesLength, + basicStyle, + conditions, + xField, + yField, + seriesField, + chart, + chartType + ) + } + return tmpOption +} + +/** + * 获取图表类型 + * @param chart + */ +function getChartTypeFlags(chart: Chart) { + // 在没有配置堆叠字段时,判定不是堆叠图 + const isStack = chart.type.includes('-stack') && chart.extStack?.length + // 分组柱状图 + const isGroupBar = chart.type === 'bar-group' + const isWaterfall = chart.type === 'waterfall' + // 条形图 + const isHorizontal = chart.type.includes('-horizontal') + const isProgressBar = chart.type === 'progress-bar' + const isBidirectionalBar = chart.type === 'bidirectional-bar' + return { + isStack, + isGroupBar, + isWaterfall, + isHorizontal, + isProgressBar, + isBidirectionalBar + } +} + +/** + * 获取渐变色 + * @param basicStyle + * @param chartType + */ +function getGradientColors(basicStyle, chartType) { + let vhAngle = chartType.isProgressBar ? 0 : 270 + return basicStyle.colors.map((ele, index) => { + const tmp = hexColorToRGBA(ele, basicStyle.alpha) + if (chartType.isBidirectionalBar) { + vhAngle = 180 - index * 180 + if (basicStyle.layout === 'vertical') { + vhAngle = index === 0 ? 280 : 90 + } + } + return setGradientColor(tmp, true, vhAngle) + }) +} + +/** + * 获取系列字段 + * @param chart + * @param options + * @param chartType + */ +function getSeriesFields(chart, options, chartType) { + let seriesFields = + chartType.isStack || chartType.isGroupBar + ? options.data?.reduce((acc, item) => { + const value = item[options.seriesField] + if (!acc.includes(value)) acc.push(value) + return acc + }, []) + : chart.yAxis.map(i => i.id) + if (chartType.isBidirectionalBar) { + seriesFields = [...seriesFields, ...chart.yAxisExt.map(i => i.id)] + } + return seriesFields.filter(item => item) +} + +/** + * 特殊图表颜色处理 + * 瀑布图固定系列字段:增加、减少、合计 + * @param colors + * @param chartType + */ +function getSeriesFieldColorMap(colors, chartType) { + const seriesFieldColorMap = new Map() + if (chartType.isWaterfall) { + seriesFieldColorMap.set(tI18n('chart.increase'), colors[0]) + seriesFieldColorMap.set(tI18n('chart.decrease'), colors[1]) + seriesFieldColorMap.set(tI18n('chart.total'), colors[2]) + } + return seriesFieldColorMap +} + +/** + * 获取颜色 + * @param ref 图库返回当前的数据项 + * @param seriesFieldColorMap 存储系列字段颜色的 Map + * @param colors 颜色数组 + * @param seriesFieldLengthRef 系列字段个数引用,图库color函数会多次调用,优先返回的是系列字段的包括颜色,之后才是系列字段数据项颜色 + * @param seriesLength 系列字段个数,用于排除掉序列字段的颜色 图表类型为堆叠或分组时,为系列字段的长度,否则为1 + * @param basicStyle + * @param conditions 条件样式 + * @param xField x轴字段 + * @param yField y轴字段 + * @param seriesField 系列字段 + * @param chart + * @param chartType 图表类型 + */ +function getColor( + ref, + seriesFieldColorMap, + colors, + seriesFieldLengthRef, + seriesLength, + basicStyle, + conditions, + xField, + yField, + seriesField, + chart, + chartType +) { + let vhAngle = chartType.isHorizontal || chartType.isProgressBar ? 0 : 270 + // 辅助函数:用于获取系列颜色 + const getColorFromMap = key => { + if (seriesFieldColorMap.has(key)) { + return seriesFieldColorMap.get(key) + } + seriesFieldColorMap.set(key, colors[seriesFieldLengthRef.current % colors.length]) + seriesFieldLengthRef.current++ + return seriesFieldColorMap.get(key) + } + // 进度条时,目标值不显示颜色 + if (chartType.isProgressBar && ref['type'] === 'target') return 'rgba(0, 0, 0, 0)' + if ( + !chartType.isWaterfall && + !chartType.isProgressBar && + !chartType.isBidirectionalBar && + seriesFieldLengthRef.current < seriesLength + ) { + return getColorFromMap(ref[seriesField]) + } + // 瀑布图时,合计字段颜色固定 + if (chartType.isWaterfall && ref['$$isTotal$$']) return seriesFieldColorMap.get(ref['field']) + // 对称条形图时,系列字段特殊处理 + if (chartType.isBidirectionalBar && seriesFieldLengthRef.current < seriesLength) { + return getColorFromMap(ref['series-field-key']) + } + // 获取当前系列字段的值 + // 条形图时,值是x轴字段的值 + let currentValue = chartType.isHorizontal ? ref[xField] : ref[yField] + // 进度条时,值是进度值,不计算目标值 + if (chartType.isProgressBar) currentValue = ref[xField]?.[1] * 100 + // 对称条形图时,取值字段通过series-field-key获取 + if (chartType.isBidirectionalBar) currentValue = ref[ref['series-field-key']] + // 当前值是数组时,取差值作为当前值,分组堆叠的值是数组 + if (Array.isArray(currentValue)) currentValue = currentValue[1] - currentValue[0] + if (currentValue) { + // 获获字段样式数据 + const fields = conditions.filter(i => { + if (chartType.isStack || chartType.isGroupBar || chartType.isWaterfall) { + return i.fieldId === chart.yAxis[0].id + } else if (chartType.isProgressBar) { + return i.fieldId === chart.yAxisExt[0].id + } else if (chartType.isBidirectionalBar) { + return ( + i.fieldId === + (ref['series-field-key'] === 'value' ? chart.yAxis[0].id : chart.yAxisExt[0].id) + ) + } else { + return i.fieldId === chart.yAxis[0].id && i.field?.name === ref[seriesField] + } + }) + if (fields?.length) { + // 样式条件判断 + for (const tc of fields[fields.length - 1].conditions) { + if ( + (tc.term === 'between' && currentValue >= tc.min && currentValue <= tc.max) || + (tc.term === 'lt' && currentValue < tc.value) || + (tc.term === 'le' && currentValue <= tc.value) || + (tc.term === 'gt' && currentValue > tc.value) || + (tc.term === 'ge' && currentValue >= tc.value) + ) { + if (basicStyle.gradient) { + const tmp = hexToRgba(tc.color, basicStyle.alpha) + // 对称条形图需要根据系列字段的值来设置渐变角度 + if (chartType.isBidirectionalBar) { + const mastAxisSeries = ref['series-field-key'] === 'value' ? 0 : 1 + vhAngle = 180 - mastAxisSeries * 180 + if (basicStyle.layout === 'vertical') { + vhAngle = mastAxisSeries === 0 ? 280 : 90 + } + } + return setGradientColor(tmp, true, vhAngle) + } + return tc.color + } + } + } + } + + if (chartType.isWaterfall) + return ref[yField] > 0 + ? seriesFieldColorMap.get(tI18n('chart.increase')) + : seriesFieldColorMap.get(tI18n('chart.decrease')) + if (chartType.isProgressBar) return colors[0] + if (chartType.isBidirectionalBar) return seriesFieldColorMap.get(ref['series-field-key']) + return ref[seriesField] ? seriesFieldColorMap.get(ref[seriesField]) : '' +} diff --git a/core/core-frontend/src/views/chart/components/js/panel/types/impl/g2plot.ts b/core/core-frontend/src/views/chart/components/js/panel/types/impl/g2plot.ts index 964f96dbcd..1db947f6cf 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/types/impl/g2plot.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/types/impl/g2plot.ts @@ -11,7 +11,8 @@ import { getTooltip, getXAxis, getYAxis, - getConditions + getConditions, + handelConditionsStyle } from '@/views/chart/components/js/panel/common/common_antv' import { AntVAbstractChartView, @@ -180,6 +181,10 @@ export abstract class G2PlotChartView< } } + protected configBarConditions(chart: Chart, options: O) { + return handelConditionsStyle(chart, options) + } + /** * 流式配置公共参数,处理常用的配置,后续如果有其他通用配置也可以放进来,需要单独配置的属性在各个图表自行实现。 * @param chart 数据库图表对象。