From 5b8056f24ac608a9092db7f8b03e2fb2e99101c8 Mon Sep 17 00:00:00 2001
From: fangsmile <892739385@qq.com>
Date: Tue, 28 Jul 2026 21:07:40 +0800
Subject: [PATCH 1/8] fix(vtable): fill auto height zero rows
---
.../debug/issue-5115-auto-height-zero-row.ts | 65 +++++++++++++++++++
packages/vtable/examples/menu.ts | 4 ++
.../progress/create-group-for-first-screen.ts | 16 +++++
3 files changed, 85 insertions(+)
create mode 100644 packages/vtable/examples/debug/issue-5115-auto-height-zero-row.ts
diff --git a/packages/vtable/examples/debug/issue-5115-auto-height-zero-row.ts b/packages/vtable/examples/debug/issue-5115-auto-height-zero-row.ts
new file mode 100644
index 0000000000..3f69b13d0f
--- /dev/null
+++ b/packages/vtable/examples/debug/issue-5115-auto-height-zero-row.ts
@@ -0,0 +1,65 @@
+import * as VTable from '../../src';
+
+const CONTAINER_ID = 'vTable';
+
+const records = Array.from({ length: 120 }, (_, index) => ({
+ id: index + 1,
+ status: index % 2 === 0 ? 'hidden-height-0' : 'visible',
+ text: `row ${index + 1} visible content`
+}));
+
+export function createTable() {
+ const container = document.getElementById(CONTAINER_ID)!;
+ document.getElementById('issue5115Toolbar')?.remove();
+ container.style.width = '720px';
+ container.style.height = '420px';
+
+ const toolbar = document.createElement('div');
+ toolbar.id = 'issue5115Toolbar';
+ toolbar.style.cssText = 'height: 48px; font-size: 12px; display: flex; gap: 12px; align-items: center;';
+ toolbar.innerHTML = `
+
+
+ `;
+ container.before(toolbar);
+
+ const tableInstance = new VTable.ListTable({
+ container,
+ records,
+ columns: [
+ { field: 'id', title: 'ID', width: 80 },
+ { field: 'status', title: 'Status', width: 160 },
+ { field: 'text', title: 'Text', width: 260 }
+ ],
+ widthMode: 'standard',
+ heightMode: 'autoHeight',
+ defaultRowHeight: 40,
+ customComputeRowHeight: ({ row }) => {
+ if (row > 0 && (row - 1) % 2 === 0) {
+ return 0;
+ }
+ return 'auto';
+ }
+ });
+
+ const check = () => {
+ const proxy = tableInstance.scenegraph.proxy;
+ const bodyStart = tableInstance.frozenRowCount;
+ const bodyHeight = tableInstance.tableNoFrameHeight - tableInstance.getFrozenRowsHeight();
+ const renderedHeight = tableInstance.getRowsHeight(bodyStart, proxy.rowEnd);
+ const zeroHeight = tableInstance.getRowHeight(tableInstance.columnHeaderLevelCount) === 0;
+ const pass = zeroHeight && renderedHeight >= bodyHeight;
+ const state = document.getElementById('issue5115State')!;
+ state.textContent =
+ `${pass ? 'PASS' : 'FAIL'} | zeroHeight=${zeroHeight} renderedHeight=${renderedHeight} ` +
+ `bodyHeight=${bodyHeight} rowEnd=${proxy.rowEnd}`;
+ return { pass, zeroHeight, renderedHeight, bodyHeight, rowEnd: proxy.rowEnd };
+ };
+
+ document.getElementById('issue5115Check')!.addEventListener('click', check);
+
+ window.tableInstance = tableInstance;
+ (window as any).issue5115Check = check;
+
+ setTimeout(check, 0);
+}
diff --git a/packages/vtable/examples/menu.ts b/packages/vtable/examples/menu.ts
index 13b2c16107..f435bad181 100644
--- a/packages/vtable/examples/menu.ts
+++ b/packages/vtable/examples/menu.ts
@@ -34,6 +34,10 @@ export const menus = [
path: 'debug',
name: 'issue-5114'
},
+ {
+ path: 'debug',
+ name: 'issue-5115-auto-height-zero-row'
+ },
{
path: 'debug',
name: 'issue-5146'
diff --git a/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts b/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts
index 4fcf6d1baa..8927530a19 100644
--- a/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts
+++ b/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts
@@ -6,6 +6,21 @@ import { computeRowsHeight } from '../../layout/compute-row-height';
import { createColGroup } from '../column';
import type { SceneProxy } from './proxy';
+function fillVisibleBodyRows(proxy: SceneProxy, distRow: number): number {
+ const { table } = proxy;
+ const bodyBottomRow = table.rowCount - 1 - table.bottomFrozenRowCount;
+ const visibleBodyHeight = table.tableNoFrameHeight - table.getFrozenRowsHeight() - table.getBottomFrozenRowsHeight();
+ let targetRow = distRow;
+
+ while (targetRow < bodyBottomRow && table.getRowsHeight(table.frozenRowCount, targetRow) < visibleBodyHeight) {
+ const nextRow = targetRow + 1;
+ computeRowsHeight(table, targetRow + 1, nextRow);
+ targetRow = nextRow;
+ }
+
+ return targetRow;
+}
+
export function createGroupForFirstScreen(
cornerHeaderGroup: Group,
colHeaderGroup: Group,
@@ -64,6 +79,7 @@ export function createGroupForFirstScreen(
? table.rowCount - 1
: distRowForCompute ?? distRow
); //如果配置了 canvasHeight为 'auto', 则一次性将所有行高都计算出来才能满足后续赋值表格高度的使用
+ distRow = fillVisibleBodyRows(proxy, distRow);
}
if (distCol < table.colCount - table.rightFrozenColCount) {
From 06cc55372be522928b2929afde28b407be2eb917 Mon Sep 17 00:00:00 2001
From: fangsmile <892739385@qq.com>
Date: Wed, 29 Jul 2026 10:57:37 +0800
Subject: [PATCH 2/8] fix(vtable): limit zero-row fill to auto height
---
.../group-creater/progress/create-group-for-first-screen.ts | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts b/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts
index 8927530a19..ea0af67515 100644
--- a/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts
+++ b/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts
@@ -79,7 +79,9 @@ export function createGroupForFirstScreen(
? table.rowCount - 1
: distRowForCompute ?? distRow
); //如果配置了 canvasHeight为 'auto', 则一次性将所有行高都计算出来才能满足后续赋值表格高度的使用
- distRow = fillVisibleBodyRows(proxy, distRow);
+ if (table.heightMode === 'autoHeight') {
+ distRow = fillVisibleBodyRows(proxy, distRow);
+ }
}
if (distCol < table.colCount - table.rightFrozenColCount) {
From 17c163cae36d270b6ba2f6f15c6b235caeb69194 Mon Sep 17 00:00:00 2001
From: fangsmile <892739385@qq.com>
Date: Wed, 29 Jul 2026 11:10:44 +0800
Subject: [PATCH 3/8] fix(vtable): keep row height cache during zero fill
---
.../group-creater/progress/create-group-for-first-screen.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts b/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts
index ea0af67515..f552cee718 100644
--- a/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts
+++ b/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts
@@ -14,7 +14,7 @@ function fillVisibleBodyRows(proxy: SceneProxy, distRow: number): number {
while (targetRow < bodyBottomRow && table.getRowsHeight(table.frozenRowCount, targetRow) < visibleBodyHeight) {
const nextRow = targetRow + 1;
- computeRowsHeight(table, targetRow + 1, nextRow);
+ computeRowsHeight(table, nextRow, nextRow, false);
targetRow = nextRow;
}
From eac5791fec86ad7b287b55a8bcf2f97f9bdee3d5 Mon Sep 17 00:00:00 2001
From: fangsmile <892739385@qq.com>
Date: Wed, 29 Jul 2026 12:48:04 +0800
Subject: [PATCH 4/8] fix(vtable): align first screen body row range
---
.../debug/issue-5115-auto-height-zero-row.ts | 4 +++-
.../progress/create-group-for-first-screen.ts | 15 ++++++++-------
2 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/packages/vtable/examples/debug/issue-5115-auto-height-zero-row.ts b/packages/vtable/examples/debug/issue-5115-auto-height-zero-row.ts
index 3f69b13d0f..92e1bfb0b6 100644
--- a/packages/vtable/examples/debug/issue-5115-auto-height-zero-row.ts
+++ b/packages/vtable/examples/debug/issue-5115-auto-height-zero-row.ts
@@ -34,6 +34,7 @@ export function createTable() {
widthMode: 'standard',
heightMode: 'autoHeight',
defaultRowHeight: 40,
+ bottomFrozenRowCount: 2,
customComputeRowHeight: ({ row }) => {
if (row > 0 && (row - 1) % 2 === 0) {
return 0;
@@ -45,7 +46,8 @@ export function createTable() {
const check = () => {
const proxy = tableInstance.scenegraph.proxy;
const bodyStart = tableInstance.frozenRowCount;
- const bodyHeight = tableInstance.tableNoFrameHeight - tableInstance.getFrozenRowsHeight();
+ const bodyHeight =
+ tableInstance.tableNoFrameHeight - tableInstance.getFrozenRowsHeight() - tableInstance.getBottomFrozenRowsHeight();
const renderedHeight = tableInstance.getRowsHeight(bodyStart, proxy.rowEnd);
const zeroHeight = tableInstance.getRowHeight(tableInstance.columnHeaderLevelCount) === 0;
const pass = zeroHeight && renderedHeight >= bodyHeight;
diff --git a/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts b/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts
index f552cee718..0bf78f4ba5 100644
--- a/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts
+++ b/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts
@@ -65,6 +65,7 @@ export function createGroupForFirstScreen(
} else {
distRow = Math.min(proxy.firstScreenRowLimit - 1, table.rowCount - 1);
}
+ let bodyDistRow = Math.min(proxy.bodyBottomRow, distRow - table.bottomFrozenRowCount);
if (table.internalProps._widthResizedColMap.size === 0) {
// compute colums width in first screen
computeColsWidth(table, 0, distColForCompute ?? distCol);
@@ -80,7 +81,7 @@ export function createGroupForFirstScreen(
: distRowForCompute ?? distRow
); //如果配置了 canvasHeight为 'auto', 则一次性将所有行高都计算出来才能满足后续赋值表格高度的使用
if (table.heightMode === 'autoHeight') {
- distRow = fillVisibleBodyRows(proxy, distRow);
+ bodyDistRow = fillVisibleBodyRows(proxy, bodyDistRow);
}
}
@@ -90,7 +91,7 @@ export function createGroupForFirstScreen(
computeColsWidth(table, table.colCount - table.rightFrozenColCount, table.colCount - 1);
}
}
- if (distRow < table.rowCount - table.bottomFrozenRowCount) {
+ if (bodyDistRow < table.rowCount - table.bottomFrozenRowCount) {
// compute bottom frozen row height
if (table.rowCount - table.bottomFrozenRowCount <= table.rowCount - 1) {
computeRowsHeight(table, table.rowCount - table.bottomFrozenRowCount, table.rowCount - 1);
@@ -146,7 +147,7 @@ export function createGroupForFirstScreen(
table.leftRowSeriesNumberCount - 1, // colEnd
table.frozenRowCount, // rowStart
// Math.min(proxy.firstScreenRowLimit, table.rowCount - 1 - table.bottomFrozenRowCount), // rowEnd
- distRow - table.bottomFrozenRowCount,
+ bodyDistRow,
'rowHeader', // isHeader
table
);
@@ -160,7 +161,7 @@ export function createGroupForFirstScreen(
Math.min(table.frozenColCount - 1, table.rowHeaderLevelCount + table.leftRowSeriesNumberCount - 1), // colEnd
table.frozenRowCount, // rowStart
// Math.min(proxy.firstScreenRowLimit, table.rowCount - 1 - table.bottomFrozenRowCount), // rowEnd
- distRow - table.bottomFrozenRowCount,
+ bodyDistRow,
'rowHeader', // isHeader
table
);
@@ -174,7 +175,7 @@ export function createGroupForFirstScreen(
table.frozenColCount - 1, // colEnd
table.frozenRowCount, // rowStart
// Math.min(proxy.firstScreenRowLimit, table.rowCount - 1 - table.bottomFrozenRowCount), // rowEnd
- distRow - table.bottomFrozenRowCount,
+ bodyDistRow,
'body',
table
);
@@ -293,7 +294,7 @@ export function createGroupForFirstScreen(
table.colCount - 1, // colEnd
table.frozenRowCount, // rowStart
// Math.min(proxy.firstScreenRowLimit, table.rowCount - 1 - table.bottomFrozenRowCount), // rowEnd
- distRow - table.bottomFrozenRowCount,
+ bodyDistRow,
table.isPivotChart() ? 'rowHeader' : 'body', // isHeader
table
);
@@ -325,7 +326,7 @@ export function createGroupForFirstScreen(
distCol - table.rightFrozenColCount,
table.frozenRowCount, // rowStart
// Math.min(proxy.firstScreenRowLimit, table.rowCount - 1 - table.bottomFrozenRowCount), // rowEnd
- distRow - table.bottomFrozenRowCount,
+ bodyDistRow,
'body', // isHeader
table
);
From 7ce351ef94743b839874099176ac7d2c3509ee30 Mon Sep 17 00:00:00 2001
From: fangsmile <892739385@qq.com>
Date: Wed, 29 Jul 2026 15:49:27 +0800
Subject: [PATCH 5/8] fix(vtable): fill auto height rows after tree toggle
---
.../debug/issue-5115-auto-height-zero-row.ts | 87 ++++++++++++++-----
.../src/scenegraph/layout/update-row.ts | 40 +++++++++
2 files changed, 107 insertions(+), 20 deletions(-)
diff --git a/packages/vtable/examples/debug/issue-5115-auto-height-zero-row.ts b/packages/vtable/examples/debug/issue-5115-auto-height-zero-row.ts
index 92e1bfb0b6..ea5d5efcfd 100644
--- a/packages/vtable/examples/debug/issue-5115-auto-height-zero-row.ts
+++ b/packages/vtable/examples/debug/issue-5115-auto-height-zero-row.ts
@@ -2,11 +2,36 @@ import * as VTable from '../../src';
const CONTAINER_ID = 'vTable';
-const records = Array.from({ length: 120 }, (_, index) => ({
- id: index + 1,
- status: index % 2 === 0 ? 'hidden-height-0' : 'visible',
- text: `row ${index + 1} visible content`
+const filteredChildren = Array.from({ length: 300 }, (_, index) => ({
+ name: `filtered child ${index + 1}`,
+ status: 'visible before filter',
+ desc: 'This row is hidden after filter interaction',
+ _show: true
}));
+const visibleChildren = Array.from({ length: 40 }, (_, index) => ({
+ name: `visible child ${index + 1}`,
+ status: 'visible after filter',
+ desc: `Visible tree row ${index + 1} should fill the viewport after filtered zero-height rows`,
+ _show: true
+}));
+const records = [
+ {
+ name: 'expanded group filtered by interaction',
+ status: 'group',
+ desc: 'Children below become _show=false after simulated filter interaction',
+ _show: true,
+ hierarchyState: 'expand',
+ children: filteredChildren
+ },
+ {
+ name: 'expanded group with visible children',
+ status: 'group',
+ desc: 'These rows should be pulled into first screen after zero-height rows',
+ _show: true,
+ hierarchyState: 'expand',
+ children: visibleChildren
+ }
+];
export function createTable() {
const container = document.getElementById(CONTAINER_ID)!;
@@ -19,29 +44,30 @@ export function createTable() {
toolbar.style.cssText = 'height: 48px; font-size: 12px; display: flex; gap: 12px; align-items: center;';
toolbar.innerHTML = `
+
`;
container.before(toolbar);
- const tableInstance = new VTable.ListTable({
+ const option: VTable.ListTableConstructorOptions = {
container,
records,
columns: [
- { field: 'id', title: 'ID', width: 80 },
- { field: 'status', title: 'Status', width: 160 },
- { field: 'text', title: 'Text', width: 260 }
+ { field: 'name', title: 'Name', tree: true, width: 260 },
+ { field: 'status', title: 'Status', width: 180 },
+ { field: 'desc', title: 'Description', width: 260 }
],
widthMode: 'standard',
heightMode: 'autoHeight',
defaultRowHeight: 40,
- bottomFrozenRowCount: 2,
- customComputeRowHeight: ({ row }) => {
- if (row > 0 && (row - 1) % 2 === 0) {
- return 0;
- }
- return 'auto';
+ hierarchyIndent: 20,
+ hierarchyExpandLevel: 2,
+ customComputeRowHeight: ({ row, table }) => {
+ const record = table.getCellOriginRecord(0, row);
+ return record && record._show === false ? 0 : 'auto';
}
- });
+ };
+ const tableInstance = new VTable.ListTable(option);
const check = () => {
const proxy = tableInstance.scenegraph.proxy;
@@ -49,19 +75,40 @@ export function createTable() {
const bodyHeight =
tableInstance.tableNoFrameHeight - tableInstance.getFrozenRowsHeight() - tableInstance.getBottomFrozenRowsHeight();
const renderedHeight = tableInstance.getRowsHeight(bodyStart, proxy.rowEnd);
- const zeroHeight = tableInstance.getRowHeight(tableInstance.columnHeaderLevelCount) === 0;
- const pass = zeroHeight && renderedHeight >= bodyHeight;
+ const firstFilteredRowHeight = tableInstance.getRowHeight(tableInstance.columnHeaderLevelCount + 1);
+ const pass = firstFilteredRowHeight === 0 && renderedHeight >= bodyHeight;
const state = document.getElementById('issue5115State')!;
state.textContent =
- `${pass ? 'PASS' : 'FAIL'} | zeroHeight=${zeroHeight} renderedHeight=${renderedHeight} ` +
+ `${pass ? 'PASS' : 'FAIL'} | firstFilteredRowHeight=${firstFilteredRowHeight} renderedHeight=${renderedHeight} ` +
`bodyHeight=${bodyHeight} rowEnd=${proxy.rowEnd}`;
- return { pass, zeroHeight, renderedHeight, bodyHeight, rowEnd: proxy.rowEnd };
+ return { pass, firstFilteredRowHeight, renderedHeight, bodyHeight, rowEnd: proxy.rowEnd };
+ };
+
+ const filterRows = () => {
+ filteredChildren.forEach(record => {
+ record._show = false;
+ record.status = 'hidden by _show=false';
+ });
+ tableInstance.updateOption(option, { clearRowHeightCache: true, clearColWidthCache: false });
+ };
+
+ const toggleCheck = async () => {
+ tableInstance.toggleHierarchyState(0, 1, false);
+ await new Promise(resolve => setTimeout(resolve, 60));
+ tableInstance.toggleHierarchyState(0, 1, false);
+ await new Promise(resolve => setTimeout(resolve, 120));
+ return check();
};
document.getElementById('issue5115Check')!.addEventListener('click', check);
+ document.getElementById('issue5115ToggleCheck')!.addEventListener('click', toggleCheck);
window.tableInstance = tableInstance;
(window as any).issue5115Check = check;
+ (window as any).issue5115ToggleCheck = toggleCheck;
- setTimeout(check, 0);
+ setTimeout(() => {
+ filterRows();
+ setTimeout(check, 0);
+ }, 0);
}
diff --git a/packages/vtable/src/scenegraph/layout/update-row.ts b/packages/vtable/src/scenegraph/layout/update-row.ts
index a2175ff157..610bbcefa5 100644
--- a/packages/vtable/src/scenegraph/layout/update-row.ts
+++ b/packages/vtable/src/scenegraph/layout/update-row.ts
@@ -7,6 +7,7 @@ import type { Scenegraph } from '../scenegraph';
import { getCellMergeInfo } from '../utils/get-cell-merge';
import { deduplication } from '../../tools/util';
import { checkHaveTextStick, resetTextStick } from '../stick-text';
+import { computeRowsHeight } from './compute-row-height';
/**
* add and remove rows in scenegraph
@@ -78,6 +79,11 @@ export function updateRow(
updateAfter = updateAfter ?? needUpdateAfter;
rowHeightsMap.insert(row);
});
+ const filledVisibleRowStart = fillVisibleBodyRows(scene);
+ if (isNumber(filledVisibleRowStart)) {
+ updateAfter = updateAfter ?? filledVisibleRowStart;
+ rowUpdatePos = isValid(rowUpdatePos) ? Math.min(rowUpdatePos, filledVisibleRowStart) : filledVisibleRowStart;
+ }
// reset attribute y and row number in CellGroup
// const newTotalHeight = resetRowNumberAndY(scene);
@@ -277,6 +283,40 @@ function addRow(row: number, scene: Scenegraph, skipUpdateProxy?: boolean) {
// scene.proxy.rowEnd++;
// scene.proxy.currentRow++;
}
+
+function fillVisibleBodyRows(scene: Scenegraph): number | undefined {
+ const { table, proxy } = scene;
+ if (table.heightMode !== 'autoHeight') {
+ return undefined;
+ }
+ const bodyBottomRow = table.rowCount - 1 - table.bottomFrozenRowCount;
+ const visibleBodyHeight = table.tableNoFrameHeight - table.getFrozenRowsHeight() - table.getBottomFrozenRowsHeight();
+ let targetRow = Math.min(proxy.rowEnd, bodyBottomRow);
+
+ computeRowsHeight(table, proxy.rowStart, targetRow, false);
+ while (targetRow < bodyBottomRow && table.getRowsHeight(table.frozenRowCount, targetRow) < visibleBodyHeight) {
+ const nextRow = targetRow + 1;
+ computeRowsHeight(table, nextRow, nextRow, false);
+ targetRow = nextRow;
+ }
+
+ if (targetRow <= proxy.rowEnd) {
+ return undefined;
+ }
+
+ const startRow = proxy.rowEnd + 1;
+ for (let row = startRow; row <= targetRow; row++) {
+ addRowCellGroup(row, scene);
+ }
+ proxy.rowEnd = targetRow;
+ proxy.currentRow = Math.max(proxy.currentRow, targetRow);
+ proxy.totalRow = Math.max(proxy.totalRow, targetRow);
+ proxy.totalActualBodyRowCount = Math.max(proxy.totalActualBodyRowCount, targetRow - proxy.rowStart + 1);
+ proxy.rowUpdatePos = Math.min(proxy.rowUpdatePos, startRow);
+
+ return startRow;
+}
+
function resetRowNumber(scene: Scenegraph) {
scene.bodyGroup.forEachChildren((colGroup: Group) => {
let rowIndex = scene.bodyRowStart;
From deeffba5fefe6a40991cf232319f72bbb046990d Mon Sep 17 00:00:00 2001
From: fangsmile <892739385@qq.com>
Date: Wed, 29 Jul 2026 16:20:18 +0800
Subject: [PATCH 6/8] fix(vtable): sync record index checkbox cascade state
---
.../vtable/src/state/checkbox/checkbox.ts | 20 ++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/packages/vtable/src/state/checkbox/checkbox.ts b/packages/vtable/src/state/checkbox/checkbox.ts
index 92a183134f..5b4da0ea5e 100644
--- a/packages/vtable/src/state/checkbox/checkbox.ts
+++ b/packages/vtable/src/state/checkbox/checkbox.ts
@@ -6,6 +6,9 @@ import type { BaseTableAPI } from '../../ts-types/base-table';
import type { CachedDataSource } from '../../data';
import type { CheckBox } from '@src/vrender';
+type CheckboxStateValue = boolean | 'indeterminate';
+type CheckboxRecordValue = CheckboxStateValue | { checked?: CheckboxStateValue };
+
export function setCheckedState(
col: number,
row: number,
@@ -590,9 +593,12 @@ function updateParentCheckboxStateByRecordIndex(recordIndex: number | number[],
continue;
}
- const childStates = parentRecord.children.map((child: any, childIndex: number) =>
- getRecordCheckboxState(parentIndex.concat(childIndex), child, field, table)
- );
+ const childStates: CheckboxStateValue[] = parentRecord.children.map((child: any, childIndex: number) => {
+ const childRecordIndex = parentIndex.concat(childIndex);
+ const childState = getRecordCheckboxState(childRecordIndex, child, field, table);
+ setRecordCheckboxState(childRecordIndex, field, childState, table.stateManager.checkedState);
+ return childState;
+ });
const allChecked = childStates.every(state => state === true);
const allUnchecked = childStates.every(state => state !== true && state !== 'indeterminate');
const parentState = allChecked ? true : allUnchecked ? false : 'indeterminate';
@@ -606,7 +612,7 @@ function getRecordCheckboxState(
record: any,
field: FieldDef,
table: BaseTableAPI
-): boolean | 'indeterminate' {
+): CheckboxStateValue {
const fieldKey = field as string | number;
const dataIndex = normalizeRecordIndex(recordIndex).toString();
const cachedState = table.stateManager.checkedState.get(dataIndex)?.[fieldKey];
@@ -614,9 +620,9 @@ function getRecordCheckboxState(
return cachedState;
}
- const value = record?.[fieldKey];
- if (isObject(value) && isValid(value.checked)) {
- return value.checked;
+ const value = record?.[fieldKey] as CheckboxRecordValue | undefined;
+ if (isObject(value) && isValid((value as { checked?: CheckboxStateValue }).checked)) {
+ return (value as { checked?: CheckboxStateValue }).checked;
}
if (typeof value === 'boolean') {
return value;
From 8ad8e8923901ade52211e896f33353156681e0cf Mon Sep 17 00:00:00 2001
From: fangsmile <892739385@qq.com>
Date: Wed, 29 Jul 2026 16:54:11 +0800
Subject: [PATCH 7/8] fix(vtable): sync auto height first screen rows
---
.../debug/issue-5115-auto-height-zero-row.ts | 17 ++++++++++++++---
.../progress/create-group-for-first-screen.ts | 10 ++++++++++
2 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/packages/vtable/examples/debug/issue-5115-auto-height-zero-row.ts b/packages/vtable/examples/debug/issue-5115-auto-height-zero-row.ts
index ea5d5efcfd..88b1877e06 100644
--- a/packages/vtable/examples/debug/issue-5115-auto-height-zero-row.ts
+++ b/packages/vtable/examples/debug/issue-5115-auto-height-zero-row.ts
@@ -76,12 +76,23 @@ export function createTable() {
tableInstance.tableNoFrameHeight - tableInstance.getFrozenRowsHeight() - tableInstance.getBottomFrozenRowsHeight();
const renderedHeight = tableInstance.getRowsHeight(bodyStart, proxy.rowEnd);
const firstFilteredRowHeight = tableInstance.getRowHeight(tableInstance.columnHeaderLevelCount + 1);
- const pass = firstFilteredRowHeight === 0 && renderedHeight >= bodyHeight;
+ const proxyRowsSynced =
+ proxy.totalRow >= proxy.rowEnd && proxy.totalActualBodyRowCount >= proxy.rowEnd - proxy.rowStart + 1;
+ const pass = firstFilteredRowHeight === 0 && renderedHeight >= bodyHeight && proxyRowsSynced;
const state = document.getElementById('issue5115State')!;
state.textContent =
`${pass ? 'PASS' : 'FAIL'} | firstFilteredRowHeight=${firstFilteredRowHeight} renderedHeight=${renderedHeight} ` +
- `bodyHeight=${bodyHeight} rowEnd=${proxy.rowEnd}`;
- return { pass, firstFilteredRowHeight, renderedHeight, bodyHeight, rowEnd: proxy.rowEnd };
+ `bodyHeight=${bodyHeight} rowEnd=${proxy.rowEnd} totalRow=${proxy.totalRow}`;
+ return {
+ pass,
+ firstFilteredRowHeight,
+ renderedHeight,
+ bodyHeight,
+ rowEnd: proxy.rowEnd,
+ totalRow: proxy.totalRow,
+ totalActualBodyRowCount: proxy.totalActualBodyRowCount,
+ proxyRowsSynced
+ };
};
const filterRows = () => {
diff --git a/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts b/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts
index 0bf78f4ba5..651072cbf3 100644
--- a/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts
+++ b/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts
@@ -21,6 +21,15 @@ function fillVisibleBodyRows(proxy: SceneProxy, distRow: number): number {
return targetRow;
}
+function syncVisibleBodyRows(proxy: SceneProxy, targetRow: number) {
+ if (targetRow <= proxy.totalRow) {
+ return;
+ }
+
+ proxy.totalRow = targetRow;
+ proxy.totalActualBodyRowCount = Math.max(proxy.totalActualBodyRowCount, targetRow - proxy.bodyTopRow + 1);
+}
+
export function createGroupForFirstScreen(
cornerHeaderGroup: Group,
colHeaderGroup: Group,
@@ -82,6 +91,7 @@ export function createGroupForFirstScreen(
); //如果配置了 canvasHeight为 'auto', 则一次性将所有行高都计算出来才能满足后续赋值表格高度的使用
if (table.heightMode === 'autoHeight') {
bodyDistRow = fillVisibleBodyRows(proxy, bodyDistRow);
+ syncVisibleBodyRows(proxy, bodyDistRow);
}
}
From 87ebd12c09b0431d828ec5577016079731cdeae3 Mon Sep 17 00:00:00 2001
From: fangsmile <892739385@qq.com>
Date: Wed, 29 Jul 2026 17:45:39 +0800
Subject: [PATCH 8/8] fix(vtable): preserve bottom frozen height timing
---
.../group-creater/progress/create-group-for-first-screen.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts b/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts
index 651072cbf3..01b31ddeb1 100644
--- a/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts
+++ b/packages/vtable/src/scenegraph/group-creater/progress/create-group-for-first-screen.ts
@@ -101,7 +101,7 @@ export function createGroupForFirstScreen(
computeColsWidth(table, table.colCount - table.rightFrozenColCount, table.colCount - 1);
}
}
- if (bodyDistRow < table.rowCount - table.bottomFrozenRowCount) {
+ if (distRow < table.rowCount - table.bottomFrozenRowCount) {
// compute bottom frozen row height
if (table.rowCount - table.bottomFrozenRowCount <= table.rowCount - 1) {
computeRowsHeight(table, table.rowCount - table.bottomFrozenRowCount, table.rowCount - 1);