-
-
Notifications
You must be signed in to change notification settings - Fork 590
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
更复杂的分组表头 #1115
Comments
实现复杂分组表头最小侵入方案:
新增 src/utils/convertUtil.tsinterface Column {
[key: string | symbol]: any;
};
interface Options {
children: string;
colSpan: string;
rowSpan: string;
hidden: string;
}
export function convertColumns<Columns extends readonly any[] = Column[]>(
columns: Columns,
options: Partial<Options> = {},
) {
if (!Array.isArray(columns) || columns.length === 0) {
return [] as unknown as Columns;
}
const defaultOptions = {
children: 'children',
colSpan: 'colSpan',
rowSpan: 'rowSpan',
hidden: 'hidden',
};
const {
children: childrenProp,
colSpan: colSpanProp,
rowSpan: rowSpanProp,
hidden: hiddenProp,
} = Object.assign({}, defaultOptions, options);
let specified = false;
let tree = columns.map((item) => ({ ...item } as Column));
let depthCurr = 0;
let depthNext = 0;
const nodePos: {
index: number;
total: number;
} = [{
index: tree.length,
total: tree.length,
}];
const rowSpans: number[] = [];
const columnsMap = new Map<number, Column[]>();
const treeMap = new Map<Column, Column[]>();
const branchLastSet = new Set<Column>();
while (tree.length > 0) {
depthCurr = depthNext;
nodePos.splice(depthCurr + 1);
rowSpans.splice(depthCurr);
nodePos[depthCurr].index--;
if (nodePos[depthCurr].index <= 0) {
depthNext = 0;
for (let i = nodePos.length - 1; i >= 0; i--) {
if (nodePos[i].index > 0) {
depthNext = i;
break;
}
}
}
const node = tree.shift();
if (!node || typeof node !== 'object' || node[hiddenProp]) {
continue;
}
// const pathKey = nodePos.reduce((acc, { index, total }) => {
// return `${acc}-${total - 1 - index}`;
// }, 'key');
const colSpanSpecified = node[colSpanProp];
const rowSpanSpecified = node[rowSpanProp];
const colSpan = node[colSpanProp] ?? 1;
const rowSpan = node[rowSpanProp] ?? 1;
node[colSpanProp] = colSpan;
node[rowSpanProp] = rowSpan;
if (!specified && (colSpan > 1 || rowSpan > 1)) {
specified = true;
}
const parentsRowCount = rowSpans.reduce((acc, num) => acc + num, 0);
if (!columnsMap.has(parentsRowCount)) {
columnsMap.set(parentsRowCount, []);
}
columnsMap.get(parentsRowCount).push(node);
let leaf = node[childrenProp];
delete node[childrenProp];
if (Array.isArray(leaf) && leaf.length > 0) {
depthNext = depthCurr + 1;
nodePos[depthNext] = { index: leaf.length, total: leaf.length };
rowSpans[depthCurr] = rowSpan;
leaf = leaf.map((item) => ({ ...item } as Column));
node.colSpanSpecified = colSpanSpecified;
if (!treeMap.has(node)) {
treeMap.set(node, []);
}
treeMap.get(node).push(...leaf);
tree = [...leaf, ...tree];
} else {
node.rowSpanSpecified = rowSpanSpecified;
node.parentsRowCount = parentsRowCount;
branchLastSet.add(node);
}
}
if (!specified) {
return columns;
}
// correct colSpan of parent column in default state
[...treeMap.keys()].reverse().forEach((column) => {
const { colSpanSpecified } = column;
delete column.colSpanSpecified;
if (column[hiddenProp] || Number.isInteger(colSpanSpecified)) {
return;
}
const children = treeMap.get(column);
column[colSpanProp] = children.reduce((acc, item) => {
return item[hiddenProp] ? acc : acc + item[colSpanProp];
}, 0);
});
let rowCountMax = 0;
branchLastSet.forEach((column) => {
const rowCount = column[rowSpanProp] + column.parentsRowCount;
if (rowCount > rowCountMax) {
rowCountMax = rowCount;
}
});
// correct rowSpan of column in default state
branchLastSet.forEach((column) => {
const { rowSpanSpecified, parentsRowCount } = column;
if (!Number.isInteger(rowSpanSpecified)) {
column[rowSpanProp] = rowCountMax - parentsRowCount;
}
delete column.rowSpanSpecified;
delete column.parentsRowCount;
});
const keys = [...columnsMap.keys()].sort();
for (let i = keys.length - 1; i >= 1; i--) {
const parent = columnsMap.get(keys[i - 1]);
parent[0][childrenProp] = columnsMap.get(keys[i]);
}
return columnsMap.get(0) as unknown as Columns;
} 在 diff --git a/src/Header/Header.tsx b/src/Header/Header.tsx
index f21b817b..07162562 100644
--- a/src/Header/Header.tsx
+++ b/src/Header/Header.tsx
@@ -2,6 +2,7 @@ import { useContext } from '@rc-component/context';
import * as React from 'react';
import TableContext, { responseImmutable } from '../context/TableContext';
import devRenderTimes from '../hooks/useRenderTimes';
+import { convertColumns } from '../utils/convertUtil';
import type {
CellType,
ColumnGroupType,
@@ -67,7 +68,7 @@ function parseHeaderRows<RecordType>(
}
// Generate `rows` cell data
- fillRowCells(rootColumns, 0);
+ fillRowCells(convertColumns<ColumnsType<RecordType>>(rootColumns), 0);
// Handle `rowSpan`
const rowCount = rows.length; |
来个 PR? |
新增复杂分组表头后会造成以下影响
改动的文件可能较多,继续在 #1118 追加完善,还是等待 merge 后再提交新的 PR 呢 |
(匿了 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
更复杂分组表头的渲染
期望渲染结果:
实际渲染结果:
示例复现的代码
不知是否有支持计划,如有可以提交相关 PR
The text was updated successfully, but these errors were encountered: