@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/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 = 44,
54
- rowHeight = 44,
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
- // 失败时仍 getList() 回滚恢复
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