diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/table/table-pivot.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/table/table-pivot.ts index 60eeda5f53..41c36e075a 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/table/table-pivot.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/table/table-pivot.ts @@ -13,7 +13,8 @@ import { TotalStatus, Aggregation, S2DataConfig, - MergedCell + MergedCell, + LayoutResult } from '@antv/s2' import { formatterItem, valueFormatter } from '../../../formatter' import { hexColorToRGBA, isAlphaColor, parseJson } from '../../../util' @@ -327,6 +328,128 @@ export class TablePivot extends S2ChartView { this.configTooltip(chart, s2Options) // 开始渲染 const s2 = new PivotSheet(containerDom, s2DataConfig, s2Options as unknown as S2Options) + // 自适应铺满 + if (basicStyle.tableColumnMode === 'adapt') { + s2.on(S2Event.LAYOUT_RESIZE_COL_WIDTH, () => { + s2.store.set('lastLayoutResult', s2.facet.layoutResult) + }) + // 平铺模式行头resize + s2.on(S2Event.LAYOUT_RESIZE_ROW_WIDTH, () => { + s2.store.set('lastLayoutResult', s2.facet.layoutResult) + }) + // 树形模式行头resize + s2.on(S2Event.LAYOUT_RESIZE_TREE_WIDTH, () => { + s2.store.set('lastLayoutResult', s2.facet.layoutResult) + }) + s2.on(S2Event.LAYOUT_AFTER_HEADER_LAYOUT, (ev: LayoutResult) => { + const lastLayoutResult = s2.store.get('lastLayoutResult') as LayoutResult + if (lastLayoutResult) { + // 拖动 col 表头 resize + const colWidthByFieldValue = s2.options.style?.colCfg?.widthByFieldValue + // 平铺模式拖动 row 表头 resize + const rowWidthByField = s2.options.style?.rowCfg?.widthByField + // 树形模式拖动 row 表头 resize + const treeRowWidth = + s2.options.style?.treeRowsWidth || lastLayoutResult.rowsHierarchy.width + const colWidthMap = + lastLayoutResult.colLeafNodes.reduce((p, n) => { + p[n.id] = colWidthByFieldValue?.[n.value] ?? n.width + return p + }, {}) || {} + const totalColWidth = ev.colLeafNodes.reduce((p, n) => { + n.width = colWidthMap[n.id] || n.width + n.x = p + return p + n.width + }, 0) + ev.colNodes.forEach(n => { + if (n.isLeaf) { + return + } + n.width = this.getColWidth(n) + n.x = this.getLeftChild(n).x + }) + if (basicStyle.tableLayoutMode === 'tree') { + ev.rowNodes.forEach(n => { + n.width = treeRowWidth + }) + ev.rowsHierarchy.width = treeRowWidth + ev.colsHierarchy.width = totalColWidth + } else { + const rowWidthMap = + lastLayoutResult.rowNodes.reduce((p, n) => { + p[n.id] = rowWidthByField?.[n.field] ?? n.width + return p + }, {}) || {} + ev.rowNodes.forEach(n => { + n.x = 0 + n.width = rowWidthMap[n.id] || n.width + let tmp = n + while (tmp.parent.id !== 'root') { + n.x += tmp.parent.width + tmp = tmp.parent + } + }) + const totlaRowWidth = ev.rowsHierarchy.sampleNodesForAllLevels.reduce((p, n) => { + return p + n.width + }, 0) + const maxRowLevel = ev.rowsHierarchy.maxLevel + ev.rowNodes.forEach(n => { + // 总计和中间层级的小计需要重新计算宽度 + if (n.isTotalRoot || (n.isSubTotals && n.level < maxRowLevel)) { + let width = 0 + for (let i = n.level; i <= maxRowLevel; i++) { + width += ev.rowsHierarchy.sampleNodesForAllLevels[i].width + } + n.width = width + } + }) + ev.rowsHierarchy.width = totlaRowWidth + ev.colsHierarchy.width = totalColWidth + } + s2.store.set('lastLayoutResult', undefined) + return + } + const containerWidth = containerDom.getBoundingClientRect().width + const scale = containerWidth / (ev.colsHierarchy.width + ev.rowsHierarchy.width) + if (scale <= 1) { + return + } + const totalRowWidth = Math.round(ev.rowsHierarchy.width * scale) + ev.rowNodes.forEach(n => { + n.width = Math.round(n.width * scale) + }) + if (basicStyle.tableLayoutMode !== 'tree') { + ev.rowNodes.forEach(n => { + n.x = 0 + let tmp = n + while (tmp.parent.id !== 'root') { + n.x += tmp.parent.width + tmp = tmp.parent + } + }) + } + let totalColWidth = ev.colLeafNodes.reduce((p, n) => { + n.width = Math.round(n.width * scale) + n.x = p + return p + n.width + }, 0) + ev.colNodes.forEach(n => { + if (n.isLeaf) { + return + } + n.width = this.getColWidth(n) + n.x = this.getLeftChild(n).x + }) + const totalWidth = totalColWidth + totalRowWidth + if (totalWidth > containerWidth) { + // 从最后一列减掉 + ev.colLeafNodes[ev.colLeafNodes.length - 1].width -= totalWidth - containerWidth + totalColWidth = totalColWidth - (totalWidth - containerWidth) + } + ev.colsHierarchy.width = totalColWidth + ev.rowsHierarchy.width = totalRowWidth + }) + } // tooltip const { show } = tooltip if (show) { @@ -350,6 +473,23 @@ export class TablePivot extends S2ChartView { return s2 } + private getColWidth(node) { + let width = 0 + if (node.children?.length) { + node.children.forEach(child => { + width += this.getColWidth(child) + }) + } else { + width = node.width + } + return width + } + private getLeftChild(node) { + if (!node.children?.length) { + return node + } + return this.getLeftChild(node.children[0]) + } private dataCellClickAction(chart: Chart, ev, s2Instance: PivotSheet, callback) { const cell = s2Instance.getCell(ev.target) const meta = cell.getMeta()