From 5cc6c80a5787b998f166237fe2c07c4260fc64b3 Mon Sep 17 00:00:00 2001 From: jianneng-fit2cloud Date: Tue, 15 Apr 2025 22:22:25 +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=E3=80=81=E6=9F=B1=E7=BA=BF=E7=BB=84=E5=90=88=E5=9B=BE?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=A1=B6=E9=83=A8=E5=9C=86=E8=A7=92=E9=80=89?= =?UTF-8?q?=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/core-frontend/src/locales/en.ts | 1 + core/core-frontend/src/locales/tw.ts | 1 + core/core-frontend/src/locales/zh-CN.ts | 1 + .../src/models/chart/chart-attr.d.ts | 4 +- .../components/BasicStyleSelector.vue | 5 ++ .../components/DualBasicStyleSelector.vue | 10 +++ .../components/js/panel/charts/bar/bar.ts | 18 +---- .../js/panel/charts/bar/bidirectional-bar.ts | 21 +++-- .../js/panel/charts/bar/bullet-graph.ts | 35 +++++++-- .../js/panel/charts/bar/horizontal-bar.ts | 24 +++--- .../js/panel/charts/bar/progress-bar.ts | 16 ++-- .../js/panel/charts/bar/range-bar.ts | 26 ++++--- .../js/panel/charts/others/chart-mix.ts | 47 +++++++---- .../components/js/panel/common/common_antv.ts | 78 ++++++++++++++++++- 14 files changed, 202 insertions(+), 85 deletions(-) diff --git a/core/core-frontend/src/locales/en.ts b/core/core-frontend/src/locales/en.ts index fef473620b..2c4ca18f33 100644 --- a/core/core-frontend/src/locales/en.ts +++ b/core/core-frontend/src/locales/en.ts @@ -1943,6 +1943,7 @@ export default { radiusColumnBar: 'Column', rightAngle: 'Right angle', roundAngle: 'Rounded angle', + topRoundAngle: 'Top rounded angle', table_layout_mode: 'Display form', table_layout_grid: 'Tile display', table_layout_tree: 'Tree display', diff --git a/core/core-frontend/src/locales/tw.ts b/core/core-frontend/src/locales/tw.ts index 05498fa53b..66d424e18b 100644 --- a/core/core-frontend/src/locales/tw.ts +++ b/core/core-frontend/src/locales/tw.ts @@ -1892,6 +1892,7 @@ export default { radiusColumnBar: '柱形', rightAngle: '直角', roundAngle: '圓角', + topRoundAngle: '頂部圓角', table_layout_mode: '展示形式', table_layout_grid: '平鋪展示', table_layout_tree: '樹形展示', diff --git a/core/core-frontend/src/locales/zh-CN.ts b/core/core-frontend/src/locales/zh-CN.ts index 1db7d72250..ab4a6d6abf 100644 --- a/core/core-frontend/src/locales/zh-CN.ts +++ b/core/core-frontend/src/locales/zh-CN.ts @@ -1897,6 +1897,7 @@ export default { radiusColumnBar: '柱形', rightAngle: '直角', roundAngle: '圆角', + topRoundAngle: '顶部圆角', table_layout_mode: '展示形式', table_layout_grid: '平铺展示', table_layout_tree: '树形展示', 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 e438ebaf79..3be07452b0 100644 --- a/core/core-frontend/src/models/chart/chart-attr.d.ts +++ b/core/core-frontend/src/models/chart/chart-attr.d.ts @@ -182,9 +182,9 @@ declare interface ChartBasicStyle { */ barWidth: number /** - * 柱子形状:直角|圆角 + * 柱子形状:直角|圆角|顶部圆角 */ - radiusColumnBar?: 'rightAngle' | 'roundAngle' + radiusColumnBar?: 'rightAngle' | 'roundAngle' | 'topRoundAngle' /** * 圆角柱倒角 */ diff --git a/core/core-frontend/src/views/chart/components/editor/editor-style/components/BasicStyleSelector.vue b/core/core-frontend/src/views/chart/components/editor/editor-style/components/BasicStyleSelector.vue index 633f197cf0..8d02d88159 100644 --- a/core/core-frontend/src/views/chart/components/editor/editor-style/components/BasicStyleSelector.vue +++ b/core/core-frontend/src/views/chart/components/editor/editor-style/components/BasicStyleSelector.vue @@ -490,9 +490,11 @@ onMounted(() => { :effect="themes" v-model="state.basicStyleForm.radiusColumnBar" @change="changeBasicStyle('radiusColumnBar')" + class="radius-class" > {{ t('chart.rightAngle') }} {{ t('chart.roundAngle') }} + {{ t('chart.topRoundAngle') }} @@ -1741,4 +1743,7 @@ onMounted(() => { flex-direction: row; align-items: center; } +.radius-class { + flex-wrap: nowrap !important; +} diff --git a/core/core-frontend/src/views/chart/components/editor/editor-style/components/DualBasicStyleSelector.vue b/core/core-frontend/src/views/chart/components/editor/editor-style/components/DualBasicStyleSelector.vue index 0bf612f789..0fe84931bb 100644 --- a/core/core-frontend/src/views/chart/components/editor/editor-style/components/DualBasicStyleSelector.vue +++ b/core/core-frontend/src/views/chart/components/editor/editor-style/components/DualBasicStyleSelector.vue @@ -224,9 +224,13 @@ onMounted(() => { :effect="themes" v-model="state.basicStyleForm.radiusColumnBar" @change="changeBasicStyle('radiusColumnBar')" + class="radius-class" > {{ t('chart.rightAngle') }} {{ t('chart.roundAngle') }} + {{ + t('chart.topRoundAngle') + }}
@@ -552,4 +556,10 @@ onMounted(() => { border-top: none !important; } } +.radius-class { + flex-wrap: nowrap !important; + :deep(.ed-radio) { + margin-right: 30px !important; + } +} 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 7d61906ee7..3c5af6f1c4 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,7 +7,6 @@ import { import { flow, hexColorToRGBA, - hexToRgba, parseJson, setUpGroupSeriesColor, setUpStackSeriesColor @@ -21,6 +20,7 @@ import { } from '@/views/chart/components/js/panel/charts/bar/common' import { configPlotTooltipEvent, + configRadius, getLabel, getPadding, getTooltipContainer, @@ -181,19 +181,9 @@ export class Bar extends G2PlotChartView { color } } - if (basicStyle.radiusColumnBar === 'roundAngle') { - const columnStyle = { - radius: [ - basicStyle.columnBarRightAngleRadius, - basicStyle.columnBarRightAngleRadius, - basicStyle.columnBarRightAngleRadius, - basicStyle.columnBarRightAngleRadius - ] - } - options = { - ...options, - columnStyle - } + options = { + ...options, + ...configRadius(options.data, basicStyle, 'columnStyle', options.xField, options.seriesField) } let columnWidthRatio const _v = basicStyle.columnWidthRatio ?? DEFAULT_BASIC_STYLE.columnWidthRatio 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 0e81f0b2e8..40430b628d 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 @@ -12,8 +12,7 @@ import { getYAxis, getYAxisExt, setGradientColor, - TOOLTIP_TPL, - addConditionsStyleColorToData + TOOLTIP_TPL } from '@/views/chart/components/js/panel/common/common_antv' import type { BidirectionalBar as G2BidirectionalBar, @@ -213,18 +212,16 @@ export class BidirectionalHorizontalBar extends G2PlotChartView< ...options, layout: basicStyle.layout } - if (basicStyle.radiusColumnBar === 'roundAngle') { - const barStyle = { - radius: [ - basicStyle.columnBarRightAngleRadius, - basicStyle.columnBarRightAngleRadius, - basicStyle.columnBarRightAngleRadius, - basicStyle.columnBarRightAngleRadius - ] - } + if (['roundAngle', 'topRoundAngle'].includes(basicStyle.radiusColumnBar)) { + const valueField = basicStyle.layout === 'vertical' ? 'valueExt' : 'value' + const radius = Array(basicStyle.radiusColumnBar === 'roundAngle' ? 4 : 2).fill( + basicStyle.columnBarRightAngleRadius + ) options = { ...options, - barStyle + barStyle: datum => ({ + radius: datum[valueField] && radius.length === 2 ? [0, 0, ...radius] : radius + }) } } return options diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/bar/bullet-graph.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/bar/bullet-graph.ts index 5599a69e76..e9a77fe8fe 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/bar/bullet-graph.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/bar/bullet-graph.ts @@ -140,23 +140,42 @@ export class BulletGraph extends G2PlotChartView { const { radiusColumnBar, columnBarRightAngleRadius, layout } = basicStyle let radiusValue = 0 let rangeLength = 1 - if (radiusColumnBar === 'roundAngle') { + if (radiusColumnBar === 'roundAngle' || radiusColumnBar === 'topRoundAngle') { radiusValue = columnBarRightAngleRadius rangeLength = options.data[0]?.ranges?.length } - const barRadiusStyle = { radius: Array(4).fill(radiusValue) } + const barRadiusStyle = { radius: Array(2).fill(radiusValue) } + const baseRadius = [...barRadiusStyle.radius, ...barRadiusStyle.radius] options = { ...options, bulletStyle: { range: datum => { if (!datum.rKey) return { fill: 'rgba(0, 0, 0, 0)' } - if (rangeLength === 1) return barRadiusStyle - if (rangeLength > 1 && datum.rKey === 'ranges_0') - return { radius: [0, 0, radiusValue, radiusValue] } - if (rangeLength > 1 && datum.rKey === 'ranges_' + (rangeLength - 1)) - return { radius: [radiusValue, radiusValue, 0, 0] } + if (rangeLength === 1) { + return { + radius: + radiusColumnBar === 'topRoundAngle' ? [...barRadiusStyle.radius, 0, 0] : baseRadius + } + } + if (rangeLength > 1 && datum.rKey === 'ranges_0') { + return { + radius: radiusColumnBar === 'topRoundAngle' ? [] : [0, 0, ...barRadiusStyle.radius] + } + } + if (rangeLength > 1 && datum.rKey === 'ranges_' + (rangeLength - 1)) { + return { radius: [...barRadiusStyle.radius, 0, 0] } + } + }, + measure: datum => { + if (datum.measures) { + return { + radius: + radiusColumnBar === 'topRoundAngle' ? [...barRadiusStyle.radius, 0, 0] : baseRadius + } + } else { + return undefined + } }, - measure: datum => (datum.measures ? barRadiusStyle : undefined), target: datum => (datum.tKey === 'target' ? { lineWidth: 2 } : undefined) } } 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 78455b1689..21b52bf3a8 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 @@ -6,6 +6,7 @@ import type { Bar, BarOptions } from '@antv/g2plot/esm/plots/bar' import { configAxisLabelLengthLimit, configPlotTooltipEvent, + configRadius, getPadding, getTooltipContainer, setGradientColor, @@ -171,19 +172,16 @@ export class HorizontalBar extends G2PlotChartView { color } } - if (basicStyle.radiusColumnBar === 'roundAngle') { - const barStyle = { - radius: [ - basicStyle.columnBarRightAngleRadius, - basicStyle.columnBarRightAngleRadius, - basicStyle.columnBarRightAngleRadius, - basicStyle.columnBarRightAngleRadius - ] - } - options = { - ...options, - barStyle - } + options = { + ...options, + ...configRadius( + options.data, + basicStyle, + 'barStyle', + options.yField, + options.seriesField, + true + ) } let barWidthRatio 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 0819082539..8a683189e9 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 @@ -4,7 +4,6 @@ import { configAxisLabelLengthLimit, configPlotTooltipEvent, getTooltipContainer, - getTooltipItemConditionColor, setGradientColor, TOOLTIP_TPL } from '../../common/common_antv' @@ -184,18 +183,13 @@ export class ProgressBar extends G2PlotChartView { } } } - if (basicStyle.radiusColumnBar === 'roundAngle') { - const barStyle = { - radius: [ - basicStyle.columnBarRightAngleRadius, - basicStyle.columnBarRightAngleRadius, - basicStyle.columnBarRightAngleRadius, - basicStyle.columnBarRightAngleRadius - ] - } + if (['roundAngle', 'topRoundAngle'].includes(basicStyle.radiusColumnBar)) { + const radius = Array(basicStyle.radiusColumnBar === 'roundAngle' ? 4 : 2).fill( + basicStyle.columnBarRightAngleRadius + ) options = { ...options, - barStyle + barStyle: { radius } } } 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 784fcd68a8..ef289bb452 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 @@ -321,18 +321,24 @@ export class RangeBar extends G2PlotChartView { } } } - if (basicStyle.radiusColumnBar === 'roundAngle') { - const barStyle = { - radius: [ - basicStyle.columnBarRightAngleRadius, - basicStyle.columnBarRightAngleRadius, - basicStyle.columnBarRightAngleRadius, - basicStyle.columnBarRightAngleRadius - ] - } + if (['roundAngle', 'topRoundAngle'].includes(basicStyle.radiusColumnBar)) { + const radius = Array(2).fill(basicStyle.columnBarRightAngleRadius) options = { ...options, - barStyle + barStyle: datum => { + const isTopRound = basicStyle.radiusColumnBar === 'topRoundAngle' + const baseRadius = [...radius, ...radius] + return { + radius: + datum.values[0] < datum.values[1] + ? isTopRound + ? [...radius, 0, 0] + : baseRadius + : isTopRound + ? [0, 0, ...radius] + : baseRadius + } + } } } let barWidthRatio diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/others/chart-mix.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/others/chart-mix.ts index 9f547a7a7d..f089d22118 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/others/chart-mix.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/others/chart-mix.ts @@ -120,10 +120,27 @@ export class ColumnLineMix extends G2PlotChartView { valueExt: d.value } }) - + // column数据分组 + const groupedByField = data1.reduce((acc, item) => { + const groupField = isGroup ? `${item.field}-${item.category}` : item.field + if (!acc[groupField]) { + acc[groupField] = [] + } + acc[groupField].push(item) + return acc + }, {}) + // 遍历每个分组,添加 isFirst 和 isLast 属性 + Object.values(groupedByField).forEach(group => { + const firstItem = group[0] + const lastItem = group[group.length - 1] + firstItem.isFirst = true + lastItem.isLast = true + }) + // 将分组后的数据重新展开为一个数组 + const result = Object.values(groupedByField).flat() // options const initOptions: DualAxesOptions = { - data: [data1, data2], + data: [result, data2], xField: 'field', yField: ['value', 'valueExt'], //这里不能设置成一样的 appendPadding: getPadding(chart), @@ -134,7 +151,8 @@ export class ColumnLineMix extends G2PlotChartView { color: [], isGroup: isGroup, isStack: isStack, - seriesField: seriesField + seriesField: seriesField, + rawFields: ['isFirst', 'isLast'] }, { geometry: data2Type, @@ -298,17 +316,20 @@ export class ColumnLineMix extends G2PlotChartView { tempOption.geometryOptions[1].point = point tempOption.geometryOptions[1].lineStyle = lineStyle - if (s.radiusColumnBar === 'roundAngle') { - const columnStyle = { - radius: [ - s.columnBarRightAngleRadius, - s.columnBarRightAngleRadius, - s.columnBarRightAngleRadius, - s.columnBarRightAngleRadius - ] + if (['roundAngle', 'topRoundAngle'].includes(s.radiusColumnBar)) { + const radius = Array(2).fill(s.columnBarRightAngleRadius) + const isTopRound = s.radiusColumnBar === 'topRoundAngle' + tempOption.geometryOptions[0].columnStyle = datum => { + if (isTopRound && datum.isFirst && datum.isLast) { + return { radius } + } + if (!isTopRound && datum.isFirst && datum.isLast) { + return { radius: [...radius, ...radius] } + } + if (datum.isFirst || (!isTopRound && datum.isLast)) { + return { radius: datum.isLast ? [0, 0, ...radius] : radius } + } } - tempOption.geometryOptions[0].columnStyle = columnStyle - tempOption.geometryOptions[1].columnStyle = columnStyle } } 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 5a39e80e23..2d21343783 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 @@ -33,7 +33,7 @@ import { PositionType } from '@antv/l7-core' import { centroid } from '@turf/centroid' import type { Plot } from '@antv/g2plot' import type { PickOptions } from '@antv/g2plot/lib/core/plot' -import { defaults, find } from 'lodash-es' +import { defaults, find, groupBy, map, uniq } from 'lodash-es' import { useI18n } from '@/hooks/web/useI18n' import { isMobile } from '@/utils/utils' import { GaodeMap, TMap, TencentMap } from '@antv/l7-maps' @@ -2205,7 +2205,7 @@ const getColorByConditions = (quotaList: [], values: number | number[], chart) = * @param chart * @param options */ -export function handleConditionsStyle(chart: Chart, options: O) { +export function handleConditionsStyle(chart: Chart, options) { const { threshold } = parseJson(chart.senior) if (!threshold.enable) return options const { basicStyle } = parseJson(chart.customAttr) @@ -2394,3 +2394,77 @@ export const numberToChineseUnderHundred = (num: number): string => { // 处理其他两位数 return tens === 1 ? '十' + digits[ones] : digits[tens] + '十' + digits[ones] } + +/** + * 配置柱条图的圆角 + * @param data + * @param basicStyle + * @param styleName + * @param xField + * @param seriesField + * @param isHorizontalBar 条形图 + */ +export const configRadius = ( + data: Record[], + basicStyle: DeepPartial, + styleName: string, + xField: string, + seriesField: string, + isHorizontalBar?: boolean +) => { + if (['roundAngle', 'topRoundAngle'].includes(basicStyle.radiusColumnBar)) { + // 根据维度分组 + const grouped = groupBy(data, xField) + // 分组下的堆叠项 + const result = map(grouped, (items, field) => ({ + field, + seriesFields: uniq(map(items, seriesField)) + })) + const radius = Array(2).fill(basicStyle.columnBarRightAngleRadius) + // 分组下堆叠项索引 + const groupIndex = new Map() + // 配置柱条样式 + const style = datum => { + const group = result.find(item => item.field === datum[xField]) + // 未找到分组直接返回 + if (!group) return { radius } + // 分组下堆叠项索引,每遇到一个索引+1 + if (groupIndex.has(group.field)) { + groupIndex.set(group.field, groupIndex.get(group.field) + 1) + } else { + groupIndex.set(group.field, 0) + } + // 分组下堆叠项长度 + const seriesFieldLength = group.seriesFields.length + // 只有一个柱子时 + if (seriesFieldLength === 1) { + return { + radius: [ + ...radius, + ...(seriesFieldLength === 1 && basicStyle.radiusColumnBar === 'topRoundAngle' + ? [0, 0] + : radius) + ] + } + } + // 获取当前分组的索引 + const groupIdx = groupIndex.get(group.field) + // 判断是否为第一个或最后一个堆叠项 + const isStart = isHorizontalBar ? groupIdx === seriesFieldLength - 1 : groupIdx === 0 + const isEnd = isHorizontalBar ? groupIdx === 0 : groupIdx === seriesFieldLength - 1 + return { + radius: isStart + ? [...radius, 0, 0] + : isEnd + ? basicStyle.radiusColumnBar === 'topRoundAngle' + ? [] + : [0, 0, ...radius] + : [] + } + } + return { + [styleName]: style + } + } + return {} +}