Skip to content

Commit 0651ffb

Browse files
authored
Merge pull request #4649 from Violet2314/feat/table-within-table2
feat: auto headerExpandLevel hierarchyState adaptation and updateFrozenColumnShadowHeight
2 parents 3751373 + 0269cf7 commit 0651ffb

2 files changed

Lines changed: 130 additions & 47 deletions

File tree

packages/vtable-plugins/src/master-detail-plugin/config.ts

Lines changed: 103 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -151,63 +151,120 @@ export class ConfigManager {
151151
});
152152
};
153153
processRecords(records);
154-
// 处理完 hierarchyState 后,遍历所有 body 行并执行对应操作
155154
this.performInitialExpansion();
156155
}
157156

158157
/**
159158
* 遍历所有记录,根据 hierarchyState 状态执行初始展开
159+
* 与VTable的异步CellGroup创建过程同步,在每个CellGroup创建后检查是否需要展开
160160
*/
161161
private performInitialExpansion(): void {
162-
// 延迟执行,确保表格已经完成渲染
163-
setTimeout(() => {
164-
const dataSource = this.table.dataSource as unknown as {
165-
source?: unknown[];
166-
_source?: unknown[];
167-
records: unknown[];
168-
};
169-
const allRecords = dataSource.source || dataSource._source || this.table.dataSource.records;
170-
const HierarchyState = VTable.TYPES.HierarchyState;
171-
// 获取插件内部属性来访问 expandedRecordIndices
172-
const tableWithInternalProps = this.table as unknown as {
173-
internalProps: { expandedRecordIndices: number[] };
174-
};
175-
if (!tableWithInternalProps.internalProps.expandedRecordIndices) {
176-
tableWithInternalProps.internalProps.expandedRecordIndices = [];
177-
}
178-
const expandedRecordIndices = tableWithInternalProps.internalProps.expandedRecordIndices;
179-
// 遍历所有记录
180-
for (let recordIndex = 0; recordIndex < allRecords.length; recordIndex++) {
181-
const record = allRecords[recordIndex];
182-
if (record && typeof record === 'object') {
183-
const recordObj = record as Record<string, unknown>;
184-
// 检查是否需要展开
185-
if (
186-
(this.hasChildren(record) || recordObj.children === true) &&
187-
recordObj.hierarchyState === HierarchyState.expand
188-
) {
189-
// 将记录索引添加到 expandedRecordIndices 中
190-
if (!expandedRecordIndices.includes(recordIndex)) {
191-
expandedRecordIndices.push(recordIndex);
192-
}
193-
// 如果记录在当前页面中,执行实际的展开操作
194-
try {
195-
const bodyRowIndex = this.table.getBodyRowIndexByRecordIndex(recordIndex);
196-
if (bodyRowIndex >= 0) {
197-
// 计算实际行索引(body行索引 + 表头行数)
198-
const actualRowIndex = bodyRowIndex + this.table.columnHeaderLevelCount;
199-
// 调用展开行方法
200-
if (this.expandRowCallback) {
201-
this.expandRowCallback(actualRowIndex);
202-
}
203-
}
204-
} catch (error) {
205-
//
162+
// 获取需要展开的记录索引列表
163+
const expandableRecords = this.getExpandableRecords();
164+
if (expandableRecords.length === 0) {
165+
return;
166+
}
167+
168+
// 开始异步展开过程,与VTable的渲染频率同步
169+
this.startAsyncExpansion(expandableRecords);
170+
}
171+
172+
/**
173+
* 获取所有需要展开的记录信息
174+
*/
175+
private getExpandableRecords(): Array<{ recordIndex: number; actualRowIndex: number; record: unknown }> {
176+
const dataSource = this.table.dataSource as unknown as {
177+
source?: unknown[];
178+
_source?: unknown[];
179+
records: unknown[];
180+
};
181+
const allRecords = dataSource.source || dataSource._source || this.table.dataSource.records;
182+
const HierarchyState = VTable.TYPES.HierarchyState;
183+
const expandableRecords: Array<{ recordIndex: number; actualRowIndex: number; record: unknown }> = [];
184+
185+
// 获取插件内部属性来访问 expandedRecordIndices
186+
const tableWithInternalProps = this.table as unknown as {
187+
internalProps: { expandedRecordIndices: number[] };
188+
};
189+
if (!tableWithInternalProps.internalProps.expandedRecordIndices) {
190+
tableWithInternalProps.internalProps.expandedRecordIndices = [];
191+
}
192+
const expandedRecordIndices = tableWithInternalProps.internalProps.expandedRecordIndices;
193+
194+
// 遍历所有记录,收集需要展开的行
195+
for (let recordIndex = 0; recordIndex < allRecords.length; recordIndex++) {
196+
const record = allRecords[recordIndex];
197+
if (record && typeof record === 'object') {
198+
const recordObj = record as Record<string, unknown>;
199+
// 检查是否需要展开
200+
if (
201+
(this.hasChildren(record) || recordObj.children === true) &&
202+
recordObj.hierarchyState === HierarchyState.expand
203+
) {
204+
// 将记录索引添加到 expandedRecordIndices 中
205+
if (!expandedRecordIndices.includes(recordIndex)) {
206+
expandedRecordIndices.push(recordIndex);
207+
}
208+
// 尝试获取行索引
209+
try {
210+
const bodyRowIndex = this.table.getBodyRowIndexByRecordIndex(recordIndex);
211+
if (bodyRowIndex >= 0) {
212+
const actualRowIndex = bodyRowIndex + this.table.columnHeaderLevelCount;
213+
expandableRecords.push({ recordIndex, actualRowIndex, record });
206214
}
215+
} catch (error) {
216+
// 记录可能不在当前页面中,跳过
207217
}
208218
}
209219
}
210-
}, 0);
220+
}
221+
222+
return expandableRecords;
223+
}
224+
225+
/**
226+
* 开始异步展开过程,与VTable的异步渲染同步
227+
*/
228+
private startAsyncExpansion(
229+
expandableRecords: Array<{ recordIndex: number; actualRowIndex: number; record: unknown }>
230+
): void {
231+
let currentIndex = 0;
232+
233+
const processNextExpansion = (): void => {
234+
if (currentIndex >= expandableRecords.length) {
235+
return; // 所有展开操作完成
236+
}
237+
238+
const { actualRowIndex } = expandableRecords[currentIndex];
239+
// 检查该行的CellGroup是否已经创建
240+
if (this.isCellGroupCreated(actualRowIndex)) {
241+
// CellGroup已创建,立即执行展开
242+
if (this.expandRowCallback) {
243+
this.expandRowCallback(actualRowIndex);
244+
}
245+
currentIndex++;
246+
// 立即处理下一个,避免不必要的延迟
247+
setTimeout(processNextExpansion, 0);
248+
} else {
249+
// CellGroup尚未创建,等待16ms后再检查(与VTable的异步渲染频率同步)
250+
setTimeout(processNextExpansion, 16);
251+
}
252+
};
253+
// 启动异步展开过程
254+
setTimeout(processNextExpansion, 0);
255+
}
256+
257+
/**
258+
* 检查指定行的CellGroup是否已经创建
259+
*/
260+
private isCellGroupCreated(rowIndex: number): boolean {
261+
try {
262+
// 检查第一列的CellGroup是否存在且有效
263+
const cellGroup = this.table.scenegraph.getCell(0, rowIndex);
264+
return cellGroup && cellGroup.role === 'cell';
265+
} catch (error) {
266+
return false;
267+
}
211268
}
212269

213270
/**

packages/vtable-plugins/src/master-detail-plugin/core.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ export class MasterDetailPlugin implements VTable.plugins.IVTablePlugin {
6464
this.eventManager.handleAfterUpdateSelectBorderHeight(eventArgs as any);
6565
}
6666
}
67-
6867
/**
6968
* 初始化管理器
7069
*/
@@ -248,6 +247,8 @@ export class MasterDetailPlugin implements VTable.plugins.IVTablePlugin {
248247

249248
const originalHeight = this.table.getRowHeight(rowIndex);
250249
if (internalProps.originalRowHeights) {
250+
const oldCellGroup = this.table.scenegraph.getCell(colIndex, rowIndex);
251+
// console.log(bodyRowIndex,oldCellGroup)
251252
internalProps.originalRowHeights.set(bodyRowIndex, originalHeight);
252253
}
253254
const record = getRecordByRowIndex(this.table, bodyRowIndex);
@@ -262,6 +263,9 @@ export class MasterDetailPlugin implements VTable.plugins.IVTablePlugin {
262263
this.updateRowHeightForExpand(rowIndex, deltaHeight);
263264
this.table.scenegraph.updateContainerHeight(rowIndex, deltaHeight);
264265
internalProps._heightResizedRowMap.add(rowIndex);
266+
if(rowIndex === 96){
267+
console.log("wokk");
268+
}
265269
this.subTableManager.renderSubTable(bodyRowIndex, childrenData, (record, bodyRowIndex) =>
266270
this.configManager.getDetailConfigForRecord(record, bodyRowIndex)
267271
);
@@ -273,6 +277,8 @@ export class MasterDetailPlugin implements VTable.plugins.IVTablePlugin {
273277
if (this.table.heightMode === 'adaptive') {
274278
this.table.scenegraph.dealHeightMode();
275279
}
280+
// 更新冻结线高度
281+
this.updateFrozenColumnShadowHeight();
276282
}
277283

278284
/**
@@ -341,6 +347,8 @@ export class MasterDetailPlugin implements VTable.plugins.IVTablePlugin {
341347
if (this.table.heightMode === 'adaptive') {
342348
this.table.scenegraph.dealHeightMode();
343349
}
350+
// 更新冻结线高度
351+
this.updateFrozenColumnShadowHeight();
344352
}
345353

346354
/**
@@ -372,6 +380,8 @@ export class MasterDetailPlugin implements VTable.plugins.IVTablePlugin {
372380
if (this.table.heightMode === 'adaptive') {
373381
this.table.scenegraph.dealHeightMode();
374382
}
383+
// 更新冻结线高度
384+
this.updateFrozenColumnShadowHeight();
375385
}
376386

377387
/**
@@ -723,6 +733,22 @@ export class MasterDetailPlugin implements VTable.plugins.IVTablePlugin {
723733
return result;
724734
}
725735

736+
/**
737+
* 更新冻结列阴影高度
738+
* 当行展开/收起导致表格总高度变化时,需要更新冻结列的阴影高度
739+
*/
740+
private updateFrozenColumnShadowHeight(): void {
741+
try {
742+
// 获取当前冻结列数量
743+
const frozenColCount = this.table.frozenColCount;
744+
if (frozenColCount > 0) {
745+
this.table.scenegraph.component.setFrozenColumnShadow(frozenColCount - 1);
746+
}
747+
} catch (error) {
748+
console.warn('更新冻结列阴影高度失败:', error);
749+
}
750+
}
751+
726752
/**
727753
* 清理主从表功能
728754
*/

0 commit comments

Comments
 (0)