@hzab/edit-table 0.1.11 → 0.1.13-alpha.0

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.tsx CHANGED
@@ -1,4 +1,12 @@
1
- import { forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
1
+ import {
2
+ forwardRef,
3
+ useCallback,
4
+ useEffect,
5
+ useImperativeHandle,
6
+ useMemo,
7
+ useRef,
8
+ useState,
9
+ } from "react";
2
10
  import { Checkbox, Empty, Spin } from "antd";
3
11
  import { ReactGrid } from "@silevis/reactgrid";
4
12
  import TextTemplate from "./Template/TextCellTemplate";
@@ -66,9 +74,82 @@ function CellEditTable(props: CellEditTableProps, ref: any) {
66
74
  const [headerCustomTemplate, setHeaderCustomTemplate] = useState<any>([]);
67
75
  const [highlights, setHighlights] = useState([]);
68
76
  const highlightsRowIdRef = useRef();
69
-
77
+ /** 附件等动态行高:rowId -> { [columnId]: height },同行多附件列时取最大值 */
78
+ const [rowHeights, setRowHeights] = useState<any>({});
79
+ /** 高度上报按帧合并缓冲,一帧内多次上报只触发一次 state 更新 */
80
+ const pendingHeightsRef = useRef<any>({});
81
+ const flushHeightsRafRef = useRef<any>();
70
82
  const gridRef = useRef<any>();
71
83
  const currentCell = useRef<any>();
84
+ const flushPendingHeights = useCallback(() => {
85
+ flushHeightsRafRef.current = undefined;
86
+ const pending = pendingHeightsRef.current;
87
+ if (Object.keys(pending).length === 0) return;
88
+ pendingHeightsRef.current = {};
89
+ setRowHeights((prev: any) => {
90
+ let next = prev;
91
+ for (const rowId in pending) {
92
+ const cols = { ...(next[rowId] || {}) };
93
+ let rowChanged = false;
94
+ for (const colId in pending[rowId]) {
95
+ const h = pending[rowId][colId];
96
+ if (cols[colId] !== h) {
97
+ cols[colId] = h;
98
+ rowChanged = true;
99
+ }
100
+ }
101
+ if (rowChanged) {
102
+ if (next === prev) next = { ...prev };
103
+ next[rowId] = cols;
104
+ }
105
+ }
106
+ return next === prev ? prev : next;
107
+ });
108
+ }, []);
109
+
110
+ /** 供单元格(如 Upload 附件)回传内容高度,撑开/恢复所在行高 */
111
+ const handleRowHeightChange = useCallback(
112
+ (rowId: any, height?: number, columnId?: string) => {
113
+ const h = Math.max(Number(height) || 0, rowHeight);
114
+ const rId = String(rowId);
115
+ const cId = columnId || "_";
116
+ const row = (pendingHeightsRef.current[rId] = pendingHeightsRef.current[rId] || {});
117
+ if (row[cId] === h) return;
118
+ row[cId] = h;
119
+ if (!flushHeightsRafRef.current) {
120
+ flushHeightsRafRef.current = requestAnimationFrame(flushPendingHeights);
121
+ }
122
+ },
123
+ [rowHeight, flushPendingHeights],
124
+ );
125
+
126
+ /** 组件卸载时取消未执行的合帧刷新 */
127
+ useEffect(() => {
128
+ return () => {
129
+ if (flushHeightsRafRef.current) cancelAnimationFrame(flushHeightsRafRef.current);
130
+ };
131
+ }, []);
132
+
133
+ /** 行高变化时仅补丁式更新受影响行的 height,避免整表重建 */
134
+ useEffect(() => {
135
+ setRows((prev: any) => {
136
+ if (!Array.isArray(prev) || prev.length === 0) return prev;
137
+ let changed = false;
138
+ const next = prev.map((row) => {
139
+ // 表头行高度固定,不参与动态行高
140
+ if (typeof row?.rowId === "string" && row.rowId.indexOf("header-") === 0) return row;
141
+ const heightMap = rowHeights[row.rowId];
142
+ const h =
143
+ heightMap && Object.keys(heightMap).length > 0
144
+ ? Math.max(rowHeight, ...Object.values(heightMap).map(Number))
145
+ : rowHeight;
146
+ if (row.height === h) return row;
147
+ changed = true;
148
+ return { ...row, height: h };
149
+ });
150
+ return changed ? next : prev;
151
+ });
152
+ }, [rowHeights, rowHeight]);
72
153
 
73
154
  useImperativeHandle(ref, () => {
74
155
  return {
@@ -182,9 +263,14 @@ function CellEditTable(props: CellEditTableProps, ref: any) {
182
263
  const columnsIds = tableColumns?.map((el) => el?.columnId);
183
264
 
184
265
  const tempDataSource = newDataSource?.map((item, index) => {
266
+ const heightMap = rowHeights[item[rowKey]];
267
+ const dynamicRowHeight =
268
+ heightMap && Object.keys(heightMap).length > 0
269
+ ? Math.max(rowHeight, ...Object.values(heightMap).map(Number))
270
+ : rowHeight;
185
271
  return {
186
272
  rowId: item[rowKey],
187
- height: rowHeight,
273
+ height: dynamicRowHeight,
188
274
  cells: columnsIds?.map((el, ind) => {
189
275
  let newCell = {};
190
276
  const columnsItem = tableColumns[ind];
@@ -211,7 +297,7 @@ function CellEditTable(props: CellEditTableProps, ref: any) {
211
297
  record: item,
212
298
  rowId: item[rowKey] || columnsItem?.type,
213
299
  type: type,
214
- nonEditable: columnsItem?.nonEditable,
300
+ nonEditable: columnsItem?.pattern == "readPretty" ? true : columnsItem?.nonEditable,
215
301
  text: String(cellItem || ""),
216
302
  value: cellItem,
217
303
  selectedValue: cellItem || "",
@@ -227,6 +313,7 @@ function CellEditTable(props: CellEditTableProps, ref: any) {
227
313
  rowKey,
228
314
  expandKeys,
229
315
  Slots,
316
+ onRowHeightChange: handleRowHeightChange,
230
317
  ...newCell,
231
318
  };
232
319
  }),
@@ -234,6 +321,7 @@ function CellEditTable(props: CellEditTableProps, ref: any) {
234
321
  });
235
322
  const mergerList = [...headerList, ...tempDataSource];
236
323
  setRows(mergerList);
324
+ // 注:此处读取的 rowHeights 为本次渲染时的快照;行高的后续增量变化由下方补丁 effect 处理,避免全量重建
237
325
  }, [newDataSource, tableColumns, headerList]);
238
326
  useEffect(() => {
239
327
  if (loading) {