@hzab/edit-table 0.1.13-alpha.1 → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/dist/common/WidthWrapHoc.d.ts +2 -0
- package/dist/index.cjs +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +189 -155
- package/dist/index.js.map +1 -1
- package/dist/project-manifest.json +6 -5
- package/dist/project.json +4 -3
- package/package.json +5 -5
- package/src/common/WidthWrapHoc.tsx +7 -0
- package/src/index.less +26 -0
- package/src/index.tsx +69 -3
package/src/index.less
CHANGED
|
@@ -70,6 +70,32 @@
|
|
|
70
70
|
background-color: #fff;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
/** 可编辑单元格(非 nonEditable)默认底色,用于区分不可编辑单元格;
|
|
74
|
+
设置在 .rg-cell 层级,内层 .base-hoc 透明透出,避免嵌套 .base-hoc(如 cellRender 返回的“未填写”)盖住底色 */
|
|
75
|
+
.rg-cell:not(.rg-cell-nonEditable) {
|
|
76
|
+
background-color: #f9f9ff;
|
|
77
|
+
}
|
|
78
|
+
.rg-cell.rg-rowSelection-cell{
|
|
79
|
+
background-color: #ffffff;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
/** 整行点击高亮:.rg-cell 背景统一切换为高亮色 #e9f8ff,覆盖包括 #f9f9ff 在内的所有其他背景。
|
|
86
|
+
.custom-highlights-row 由 JS(WidthWrapHoc.getClassName)追加到选中行的 .rg-cell 上 */
|
|
87
|
+
.rg-cell.custom-highlights-row {
|
|
88
|
+
background-color: #e9f8ff;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** 高亮行内编辑态单元格(.base-hoc-edit 默认 #fff)也覆盖为高亮色,保证整行背景一致 */
|
|
92
|
+
.rg-cell.custom-highlights-row .base-hoc-edit {
|
|
93
|
+
background-color: #ffffff;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
|
|
73
99
|
/** 组件回显/编辑内容容器:纯内容高度,不设 min-height(保证高度测量双向真实) */
|
|
74
100
|
.base-hoc-inner {
|
|
75
101
|
width: 100%;
|
package/src/index.tsx
CHANGED
|
@@ -39,9 +39,41 @@ interface CellEditTableProps {
|
|
|
39
39
|
loading?: boolean;
|
|
40
40
|
isExpand?: boolean;
|
|
41
41
|
getList?: () => void;
|
|
42
|
+
setList?: (value: any) => void;
|
|
42
43
|
onRow?: (v: any, ri: number, ci: number) => void;
|
|
43
44
|
}
|
|
44
45
|
|
|
46
|
+
/** 将编辑后的行合并回列表数据源,供 getList 返回前保持单元格新值 */
|
|
47
|
+
function mergeRowsByKey(list: any[], updates: any[], key: string): any[] {
|
|
48
|
+
if (!Array.isArray(list) || !Array.isArray(updates) || updates.length === 0) return list;
|
|
49
|
+
|
|
50
|
+
const updateMap = new Map<string, any>();
|
|
51
|
+
updates.forEach((item) => {
|
|
52
|
+
if (item?.[key] != null) updateMap.set(String(item[key]), item);
|
|
53
|
+
if (item?.id != null) updateMap.set(String(item.id), item);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const walk = (items: any[]): any[] => {
|
|
57
|
+
if (!Array.isArray(items)) return items;
|
|
58
|
+
return items.map((item) => {
|
|
59
|
+
const update = updateMap.get(String(item?.[key] ?? item?.id));
|
|
60
|
+
const originalChildren = item?.children;
|
|
61
|
+
const children = originalChildren ? walk(originalChildren) : originalChildren;
|
|
62
|
+
if (!update) {
|
|
63
|
+
return children === originalChildren ? item : { ...item, children };
|
|
64
|
+
}
|
|
65
|
+
const { children: _children, ...nextItem } = update;
|
|
66
|
+
return {
|
|
67
|
+
...item,
|
|
68
|
+
...nextItem,
|
|
69
|
+
...(originalChildren !== undefined ? { children } : {}),
|
|
70
|
+
};
|
|
71
|
+
});
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
return walk(list);
|
|
75
|
+
}
|
|
76
|
+
|
|
45
77
|
function CellEditTable(props: CellEditTableProps, ref: any) {
|
|
46
78
|
const {
|
|
47
79
|
columns,
|
|
@@ -50,8 +82,8 @@ function CellEditTable(props: CellEditTableProps, ref: any) {
|
|
|
50
82
|
onChange,
|
|
51
83
|
reactGridProps = {},
|
|
52
84
|
onEditSubmit,
|
|
53
|
-
headerRowHeight =
|
|
54
|
-
rowHeight =
|
|
85
|
+
headerRowHeight = 48,
|
|
86
|
+
rowHeight = 48,
|
|
55
87
|
reactGridStyle,
|
|
56
88
|
className,
|
|
57
89
|
Slots,
|
|
@@ -61,6 +93,7 @@ function CellEditTable(props: CellEditTableProps, ref: any) {
|
|
|
61
93
|
loading,
|
|
62
94
|
isExpand = false,
|
|
63
95
|
getList,
|
|
96
|
+
setList,
|
|
64
97
|
onRow,
|
|
65
98
|
} = props;
|
|
66
99
|
|
|
@@ -139,6 +172,8 @@ function CellEditTable(props: CellEditTableProps, ref: any) {
|
|
|
139
172
|
const validRowIds = rows.map((r) => r.rowId);
|
|
140
173
|
if (!validRowIds?.includes(highlightsRowIdRef.current)) {
|
|
141
174
|
setHighlights([]);
|
|
175
|
+
// 同步清理高亮行全局标记,避免 .rg-cell 残留高亮 class
|
|
176
|
+
(window as any).gridHighlightRowId = null;
|
|
142
177
|
}
|
|
143
178
|
}, [rows]);
|
|
144
179
|
|
|
@@ -297,15 +332,24 @@ function CellEditTable(props: CellEditTableProps, ref: any) {
|
|
|
297
332
|
const handleCellsChanged = async (changes) => {
|
|
298
333
|
if (!Array.isArray(changes) || changes.length === 0) return;
|
|
299
334
|
const batchQuery: any = [];
|
|
335
|
+
// 父级数据源快照:保存失败时撤销乐观更新,避免 getList 前再次回显旧值
|
|
336
|
+
const previousDataSource = dataSource;
|
|
300
337
|
|
|
301
338
|
// 基于 rowsRef 当前值在 updater 外纯计算(updater 执行时机不确定且可能执行两次,
|
|
302
339
|
// 不能在 updater 内收集提交数据),一次性生成新数组后同步 rowsRef 再 setRows
|
|
303
340
|
const prevRows = rowsRef.current || [];
|
|
304
341
|
const nextRows = prevRows.map((row) => ({ ...row, cells: [...row.cells] }));
|
|
342
|
+
// 编辑前单元格快照,保存失败时用于单元格级回滚
|
|
343
|
+
const prevCellSnapshot: any[] = [];
|
|
305
344
|
changes.forEach((change) => {
|
|
306
345
|
const changeRowIdx = nextRows.findIndex((el) => el.rowId == change.rowId);
|
|
307
346
|
const changeColumnIdx = tableColumns.findIndex((el) => el.columnId == change.columnId);
|
|
308
347
|
if (changeRowIdx === -1 || changeColumnIdx === -1) return;
|
|
348
|
+
prevCellSnapshot.push({
|
|
349
|
+
rowId: change.rowId,
|
|
350
|
+
columnId: change.columnId,
|
|
351
|
+
previousCell: change.previousCell,
|
|
352
|
+
});
|
|
309
353
|
nextRows[changeRowIdx].cells[changeColumnIdx] = { ...change.newCell };
|
|
310
354
|
currentCell.current = { ...change.newCell };
|
|
311
355
|
batchQuery.push(handleArrayToObj(nextRows[changeRowIdx]));
|
|
@@ -336,14 +380,33 @@ function CellEditTable(props: CellEditTableProps, ref: any) {
|
|
|
336
380
|
armScrollProtect(SCROLL_RESET_GUARD_MS);
|
|
337
381
|
setRows(nextRows);
|
|
338
382
|
restoreScroll();
|
|
383
|
+
// 同步父级 list:保存成功后的 getList 在接口返回前仍使用旧 list,
|
|
384
|
+
// 只更新内部 rows 会被随后触发的数据源重建覆盖成编辑前的值。
|
|
385
|
+
if (setList && batchQuery.length > 0) {
|
|
386
|
+
setList((prevList: any[]) => mergeRowsByKey(prevList, batchQuery, rowKey));
|
|
387
|
+
}
|
|
339
388
|
|
|
340
389
|
// 提交成功后由 list-render 的 onEditSubmit 全量刷新列表;
|
|
341
390
|
// 滚动位置由 rows 重建 effect 中的快照/恢复机制保持;
|
|
342
|
-
//
|
|
391
|
+
// 失败时先把修改过的单元格回滚为编辑前的值,再 getList() 兜底刷新
|
|
343
392
|
if (onEditSubmit) {
|
|
344
393
|
try {
|
|
345
394
|
await onEditSubmit(batchQuery);
|
|
346
395
|
} catch (err) {
|
|
396
|
+
const restoredRows = (rowsRef.current || []).map((row) => ({
|
|
397
|
+
...row,
|
|
398
|
+
cells: [...row.cells],
|
|
399
|
+
}));
|
|
400
|
+
prevCellSnapshot.forEach(({ rowId, columnId, previousCell }) => {
|
|
401
|
+
const rIdx = restoredRows.findIndex((el) => el.rowId == rowId);
|
|
402
|
+
const cIdx = tableColumns.findIndex((el) => el.columnId == columnId);
|
|
403
|
+
if (rIdx === -1 || cIdx === -1 || !previousCell) return;
|
|
404
|
+
restoredRows[rIdx].cells[cIdx] = { ...previousCell };
|
|
405
|
+
});
|
|
406
|
+
rowsRef.current = restoredRows;
|
|
407
|
+
setRows(restoredRows);
|
|
408
|
+
restoreScroll();
|
|
409
|
+
setList?.(previousDataSource);
|
|
347
410
|
getList && getList();
|
|
348
411
|
}
|
|
349
412
|
}
|
|
@@ -480,6 +543,9 @@ function CellEditTable(props: CellEditTableProps, ref: any) {
|
|
|
480
543
|
borderColor: "transparent",
|
|
481
544
|
}));
|
|
482
545
|
highlightsRowIdRef.current = cell?.rowId;
|
|
546
|
+
// 记录高亮行 rowId 到全局,供 WidthWrapHoc.getClassName 给 .rg-cell 追加高亮 class
|
|
547
|
+
(window as any).gridHighlightRowId = cell?.rowId;
|
|
548
|
+
|
|
483
549
|
setHighlights(list);
|
|
484
550
|
};
|
|
485
551
|
|