From 83454f910599d5fc4100168d28d1aecff1378f06 Mon Sep 17 00:00:00 2001 From: wisonic-s Date: Sun, 28 Sep 2025 23:00:42 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E5=9B=BE=E8=A1=A8):=20=E6=B1=87=E6=80=BB?= =?UTF-8?q?=E8=A1=A8=E6=94=AF=E6=8C=81=E8=A1=A8=E5=A4=B4=E5=88=86=E7=BB=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../table/TableHeaderGroupConfig.vue | 14 +++- .../components/table/TableHeaderSelector.vue | 15 ++-- .../js/panel/charts/table/table-info.ts | 28 +++---- .../js/panel/charts/table/table-normal.ts | 79 ++++++++++++++++--- .../js/panel/common/common_table.ts | 17 ++++ 5 files changed, 116 insertions(+), 37 deletions(-) diff --git a/core/core-frontend/src/views/chart/components/editor/editor-style/components/table/TableHeaderGroupConfig.vue b/core/core-frontend/src/views/chart/components/editor/editor-style/components/table/TableHeaderGroupConfig.vue index f00326950c..c4e1a93bf3 100644 --- a/core/core-frontend/src/views/chart/components/editor/editor-style/components/table/TableHeaderGroupConfig.vue +++ b/core/core-frontend/src/views/chart/components/editor/editor-style/components/table/TableHeaderGroupConfig.vue @@ -60,6 +60,13 @@ const onCancelConfig = () => { emits('onCancelConfig') } +const allAxis = computed(() => { + const axis = [...props.chart.xAxis] + if (props.chart.type === 'table-normal') { + axis.push(...props.chart.yAxis) + } + return axis +}) const onConfigChange = () => { const { fields } = s2.dataCfg emits('onConfigChange', { columns: fields.columns, meta: [] }) @@ -67,10 +74,9 @@ const onConfigChange = () => { const init = () => { const chart = cloneDeep(props.chart) - const xAxis = chart.xAxis const { headerGroupConfig } = chart.customAttr.tableHeader const showColumns = [] - xAxis?.forEach(axis => { + allAxis.value?.forEach(axis => { axis.hide !== true && showColumns.push({ field: axis.dataeaseName, title: axis.chartShowName ?? axis.name }) }) @@ -93,11 +99,11 @@ const init = () => { } setupColumnTitle(headerGroupConfig.columns, nameFieldMap) } - const allAxis = showColumns.map(item => item.field) + const allKeys = showColumns.map(item => item.field) const leafNodes = getLeafNodes(headerGroupConfig.columns) const leafKeys = leafNodes.map(item => item.field) const { columns } = headerGroupConfig - if (!isEqual(allAxis, leafKeys)) { + if (!isEqual(allKeys, leafKeys)) { columns.splice(0, columns.length, ...showColumns) } else { const nameMap = showColumns.reduce((pre, cur) => { diff --git a/core/core-frontend/src/views/chart/components/editor/editor-style/components/table/TableHeaderSelector.vue b/core/core-frontend/src/views/chart/components/editor/editor-style/components/table/TableHeaderSelector.vue index 1a4c463dd5..a9c39745c0 100644 --- a/core/core-frontend/src/views/chart/components/editor/editor-style/components/table/TableHeaderSelector.vue +++ b/core/core-frontend/src/views/chart/components/editor/editor-style/components/table/TableHeaderSelector.vue @@ -96,18 +96,21 @@ const groupConfigValid = computed(() => { if (noGroup) { return false } - const xAxis = props.chart.xAxis + const allAxis = [...props.chart?.xAxis] + if (props.chart.type === 'table-normal') { + allAxis.push(...props.chart?.yAxis) + } const showColumns = [] - xAxis?.forEach(axis => { - axis.hide !== true && showColumns.push({ key: axis.dataeaseName }) + allAxis?.forEach(axis => { + axis.hide !== true && showColumns.push({ field: axis.dataeaseName }) }) if (!showColumns.length) { return false } - const allAxis = showColumns.map(item => item.key) + const allKeys = showColumns.map(item => item.field) const leafNodes = getLeafNodes(columns as Array) - const leafKeys = leafNodes.map(item => item.key) - return isEqual(allAxis, leafKeys) + const leafKeys = leafNodes.map(item => item.field) + return isEqual(allKeys, leafKeys) }) const init = () => { const tableHeader = props.chart?.customAttr?.tableHeader diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/table/table-info.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/table/table-info.ts index 3a1e1fabbd..ac16093a43 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/table/table-info.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/table/table-info.ts @@ -28,7 +28,9 @@ import { getSummaryRow, SummaryCell, mapKeyToField, - setupColumnTitle + setupColumnTitle, + calcTreeWidth, + getStartPosition } from '@/views/chart/components/js/panel/common/common_table' const { t } = useI18n() @@ -153,15 +155,21 @@ export class TableInfo extends S2ChartView { }) } setupColumnTitle(headerGroupConfig.columns as unknown as ColumnNode[], nameMap) - const allKeys = columns.map(c => drillFieldMap[c] || c.field) + const allKeys = columns.map(c => drillFieldMap[c.field] || c.field) const leafNodes = getLeafNodes(headerGroupConfig.columns as ColumnNode[]) const leafKeys = leafNodes.map(c => c.field) if (isEqual(leafKeys, allKeys)) { if (Object.keys(drillFieldMap).length) { + const drillNameMap = + chart.drillFields?.reduce((pre, cur) => { + pre[cur.dataeaseName] = cur.chartShowName || cur.name + return pre + }, {}) || {} const originField = Object.values(drillFieldMap)[0] const drillField = Object.keys(drillFieldMap)[0] const [drillCol] = getColumns([originField], headerGroupConfig.columns as ColumnNode[]) drillCol.field = drillField + drillCol.title = drillNameMap[drillField] ?? drillCol.title } columns.splice(0, columns.length, ...headerGroupConfig.columns) } @@ -516,19 +524,3 @@ export class TableInfo extends S2ChartView { super('table-info', []) } } - -function calcTreeWidth(node) { - if (!node.children?.length) { - return node.width - } - return node.children.reduce((pre, cur) => { - return pre + calcTreeWidth(cur) - }, 0) -} - -function getStartPosition(node) { - if (!node.children?.length) { - return node.x - } - return getStartPosition(node.children[0]) -} diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/table/table-normal.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/table/table-normal.ts index bbe7fd2a8b..c5a3e6dcf7 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/table/table-normal.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/table/table-normal.ts @@ -6,7 +6,13 @@ import { getSummaryRow, SortTooltip, SummaryCell, - summaryRowStyle + summaryRowStyle, + getLeafNodes, + getColumns, + calcTreeWidth, + getStartPosition, + mapKeyToField, + setupColumnTitle } from '@/views/chart/components/js/panel/common/common_table' import { S2ChartView, S2DrawOptions } from '@/views/chart/components/js/panel/types/impl/s2' import { parseJson } from '@/views/chart/components/js/util' @@ -20,7 +26,7 @@ import { TableSheet, ViewMeta } from '@antv/s2' -import { isNumber } from 'lodash-es' +import { isEqual, isNumber } from 'lodash-es' import { TABLE_EDITOR_PROPERTY, TABLE_EDITOR_PROPERTY_INNER } from './common' const { t } = useI18n() @@ -34,7 +40,8 @@ export class TableNormal extends S2ChartView { 'table-header-selector': [ ...TABLE_EDITOR_PROPERTY_INNER['table-header-selector'], 'tableHeaderSort', - 'showTableHeader' + 'showTableHeader', + 'headerGroup' ], 'basic-style-selector': [ ...TABLE_EDITOR_PROPERTY_INNER['basic-style-selector'], @@ -76,6 +83,7 @@ export class TableNormal extends S2ChartView { const columns = [] const meta = [] + const drillFieldMap = {} if (chart.drill) { // 下钻过滤字段 const filterFields = chart.drillFilters.map(i => i.fieldId) @@ -84,13 +92,14 @@ export class TableNormal extends S2ChartView { const drillFieldIndex = chart.xAxis.findIndex(ele => ele.id === drillFieldId) // 当前下钻字段 const curDrillFieldId = chart.drillFields[filterFields.length].id - const curDrillField = fields.filter(ele => ele.id === curDrillFieldId) + const curDrillField = fields.find(ele => ele.id === curDrillFieldId) filterFields.push(curDrillFieldId) // 移除下钻字段,把当前下钻字段插入到下钻入口位置 fields = fields.filter(ele => { return !filterFields.includes(ele.id) }) - fields.splice(drillFieldIndex, 0, ...curDrillField) + drillFieldMap[curDrillField.dataeaseName] = chart.drillFields[0].dataeaseName + fields.splice(drillFieldIndex, 0, curDrillField) } const axisMap = [...chart.xAxis, ...chart.yAxis].reduce((pre, cur) => { pre[cur.dataeaseName] = cur @@ -102,10 +111,9 @@ export class TableNormal extends S2ChartView { if (f?.hide === true) { return } - columns.push(ele.dataeaseName) + columns.push({ field: ele.dataeaseName, title: ele.chartShowName ?? ele.name }) meta.push({ field: ele.dataeaseName, - name: ele.chartShowName ?? ele.name, formatter: function (value) { if (!f) { return value @@ -124,7 +132,47 @@ export class TableNormal extends S2ChartView { } }) }) - + const { basicStyle, tableCell, tableHeader, tooltip } = parseJson(chart.customAttr) + // 表头分组 + const { headerGroup, showTableHeader } = tableHeader + if (headerGroup && showTableHeader !== false) { + const { headerGroupConfig } = tableHeader + if (headerGroupConfig?.columns?.length) { + // 存量配置转换 + if (headerGroupConfig.columns[0].key) { + mapKeyToField(headerGroupConfig.columns as unknown as ColumnNode[]) + } + const nameMap = + [...chart.xAxis, ...chart.yAxis].reduce((pre, cur) => { + pre[cur.dataeaseName] = cur.name + return pre + }, {}) || {} + if (headerGroupConfig.meta?.length) { + headerGroupConfig.meta.forEach(m => { + nameMap[m.field] = m.name + }) + } + setupColumnTitle(headerGroupConfig.columns as unknown as ColumnNode[], nameMap) + const allKeys = columns.map(c => drillFieldMap[c.field] || c.field) + const leafNodes = getLeafNodes(headerGroupConfig.columns as ColumnNode[]) + const leafKeys = leafNodes.map(c => c.field) + if (isEqual(leafKeys, allKeys)) { + if (Object.keys(drillFieldMap).length) { + const drillNameMap = + chart.drillFields?.reduce((pre, cur) => { + pre[cur.dataeaseName] = cur.chartShowName || cur.name + return pre + }, {}) || {} + const originField = Object.values(drillFieldMap)[0] + const drillField = Object.keys(drillFieldMap)[0] + const [drillCol] = getColumns([originField], headerGroupConfig.columns as ColumnNode[]) + drillCol.field = drillField + drillCol.title = drillNameMap[drillField] ?? drillCol.title + } + columns.splice(0, columns.length, ...headerGroupConfig.columns) + } + } + } // 空值处理 const newData = this.configEmptyDataStrategy(chart) // data config @@ -136,7 +184,6 @@ export class TableNormal extends S2ChartView { data: newData } - const { basicStyle, tableCell, tableHeader, tooltip } = parseJson(chart.customAttr) // options const s2Options: S2Options = { width: containerDom.offsetWidth, @@ -221,6 +268,13 @@ export class TableNormal extends S2ChartView { n.x = p return p + n.width }, 0) + // 处理分组的单元格,宽度为所有叶子节点之和 + ev.colNodes.forEach(n => { + if (n.colIndex === -1) { + n.width = calcTreeWidth(n) + n.x = getStartPosition(n) + } + }) ev.colsHierarchy.width = totalWidth newChart.store.set('lastLayoutResult', undefined) return @@ -241,6 +295,13 @@ export class TableNormal extends S2ChartView { n.x = p return p + n.width }, 0) + // 处理分组的单元格,宽度为所有叶子节点之和 + ev.colNodes.forEach(n => { + if (n.colIndex === -1) { + n.width = calcTreeWidth(n) + n.x = getStartPosition(n) + } + }) // 从最后一列减掉 const lastNode = ev.colLeafNodes[ev.colLeafNodes.length - 1] if (totalWidth > containerWidth) { diff --git a/core/core-frontend/src/views/chart/components/js/panel/common/common_table.ts b/core/core-frontend/src/views/chart/components/js/panel/common/common_table.ts index 57e96e0a0e..4f9dcc776a 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/common/common_table.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/common/common_table.ts @@ -2066,6 +2066,23 @@ export const summaryRowStyle = (newChart, newData, tableCell, tableHeader, showS }) } + +export function calcTreeWidth(node) { + if (!node.children?.length) { + return node.width + } + return node.children.reduce((pre, cur) => { + return pre + calcTreeWidth(cur) + }, 0) +} + +export function getStartPosition(node) { + if (!node.children?.length) { + return node.x + } + return getStartPosition(node.children[0]) +} + export class SummaryCell extends CustomDataCell { getTextStyle() { const textStyle = cloneDeep(this.theme.colCell.bolderText)