@zat-design/sisyphus-react 4.4.1-beta.2 → 4.4.1-beta.3
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/dist/index.esm.css +1 -1
- package/dist/less.esm.css +1 -1
- package/es/ProConfigProvider/index.d.ts +1 -1
- package/es/ProConfigProvider/index.js +6 -7
- package/es/ProConfigProvider/propsType.d.ts +22 -0
- package/es/ProEditTable/components/RcTable/DraggableTable.js +18 -32
- package/es/ProEditTable/index.js +7 -1
- package/es/ProEditTable/style/index.less +0 -5
- package/es/ProEditTable/utils/config.js +2 -0
- package/es/ProEditTable/utils/index.d.ts +15 -1
- package/es/ProEditTable/utils/index.js +27 -15
- package/es/ProForm/components/combination/Group/utils/index.d.ts +9 -9
- package/es/ProForm/utils/useWatch.d.ts +14 -4
- package/es/ProForm/utils/useWatch.js +48 -18
- package/es/ProTable/components/EditableCell/index.js +55 -22
- package/es/ProTable/components/EditableCell/propsType.d.ts +14 -0
- package/es/ProTable/components/FormatColumn/index.d.ts +4 -2
- package/es/ProTable/components/FormatColumn/index.js +13 -46
- package/es/ProTable/components/RcTable/components/BaseTable/index.d.ts +1 -8
- package/es/ProTable/components/RcTable/components/BaseTable/index.js +5 -4
- package/es/ProTable/components/RcTable/components/DraggableTable/components/DndWrapper/index.d.ts +1 -1
- package/es/ProTable/components/RcTable/components/DraggableTable/components/DndWrapper/index.js +19 -32
- package/es/ProTable/components/RcTable/components/DraggableTable/index.d.ts +1 -8
- package/es/ProTable/components/RcTable/components/DraggableTable/index.js +5 -4
- package/es/ProTable/components/RenderColumn/index.js +1 -17
- package/es/ProTable/index.d.ts +9 -8
- package/es/ProTable/index.js +151 -111
- package/es/ProTable/propsType.d.ts +21 -6
- package/es/ProTable/utils/columnStorage.d.ts +35 -0
- package/es/ProTable/utils/columnStorage.js +171 -0
- package/es/ProTable/utils/index.d.ts +16 -2
- package/es/ProTable/utils/index.js +34 -21
- package/es/hooks/useDraggableRow.d.ts +34 -0
- package/es/hooks/useDraggableRow.js +70 -0
- package/package.json +1 -3
- package/es/ProForm/components/base/DatePicker/useDateLimit.d.ts +0 -3
- package/es/ProForm/components/base/DatePicker/useDateLimit.js +0 -7
- package/es/ProForm/components/combination/FormList/components/BlockTitle.d.ts +0 -13
- package/es/ProForm/components/combination/FormList/components/BlockTitle.js +0 -31
package/es/ProTable/index.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import _isBoolean from "lodash/isBoolean";
|
|
2
|
-
import _isFunction from "lodash/isFunction";
|
|
3
1
|
import _isObject from "lodash/isObject";
|
|
4
2
|
import _assign from "lodash/assign";
|
|
5
3
|
import _keyBy from "lodash/keyBy";
|
|
6
|
-
import { useEffect, useMemo, useState, createContext } from 'react';
|
|
4
|
+
import React, { useEffect, useMemo, useState, createContext, useRef, forwardRef } from 'react';
|
|
7
5
|
import { useDebounceEffect, useDeepCompareEffect, useSetState } from 'ahooks';
|
|
8
6
|
import classnames from 'classnames';
|
|
7
|
+
import { Form } from 'antd';
|
|
9
8
|
import { useProConfig } from "../index";
|
|
10
9
|
import { RenderTableHeader, RenderFooter, RenderTabs } from "./components";
|
|
11
10
|
import useAntdTable, { SELECTION_ALL, CURRENT_PAGE, UNCHECK_ALL } from "./hooks/useAntdTable";
|
|
@@ -14,7 +13,8 @@ import { formatColumn } from "./components/FormatColumn";
|
|
|
14
13
|
import empty from "../assets/empty.png";
|
|
15
14
|
import resetSvg from "../assets/reset.svg";
|
|
16
15
|
import customColumnSvg from "../assets/customColumn.svg";
|
|
17
|
-
import { getColumnDataIndex, getRowKey } from "./utils";
|
|
16
|
+
import { filterVisibleColumns, getColumnDataIndex, getRowKey } from "./utils";
|
|
17
|
+
import { baseStorage, getColumnCache, getColumnCacheSync, removeColumnCache, setColumnCache } from "./utils/columnStorage";
|
|
18
18
|
import locale from "../locale";
|
|
19
19
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
20
20
|
const defaultCacheTime = 1; // columns 配置保存时间为一天
|
|
@@ -25,7 +25,7 @@ export const defaultPage = {
|
|
|
25
25
|
pageNum: 1,
|
|
26
26
|
pageSize: 10
|
|
27
27
|
};
|
|
28
|
-
const ProTable = props => {
|
|
28
|
+
const ProTable = /*#__PURE__*/forwardRef((props, tableRef) => {
|
|
29
29
|
const {
|
|
30
30
|
storage: configStorage
|
|
31
31
|
} = useProConfig('globalConfig') || {}; // 获取全局缓存位置配置
|
|
@@ -53,8 +53,13 @@ const ProTable = props => {
|
|
|
53
53
|
onDragStart: onDragStartGuard,
|
|
54
54
|
onDragEnd: onDragEndGuard,
|
|
55
55
|
tabs,
|
|
56
|
+
editMode = 'per-cell-form',
|
|
56
57
|
...restProps
|
|
57
58
|
} = props;
|
|
59
|
+
|
|
60
|
+
// shared-form 模式下顶层创建一份 Form 实例,所有 EditableCell 复用;
|
|
61
|
+
// per-cell-form 默认模式下不消费此实例(antd 的 useForm 必须无条件调用以满足 hooks rule)
|
|
62
|
+
const [sharedForm] = Form.useForm();
|
|
58
63
|
const {
|
|
59
64
|
scrollFollowParent = true
|
|
60
65
|
} = props;
|
|
@@ -125,17 +130,33 @@ const ProTable = props => {
|
|
|
125
130
|
} = window.location;
|
|
126
131
|
// 以pathname + tableId作为缓存配置key
|
|
127
132
|
const pathKey = `${pathname}/${tableId || ''}`;
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
const
|
|
131
|
-
|
|
133
|
+
|
|
134
|
+
// 默认 storage 为 'indexedDB'(baseStorage),与 ProEnum 一致
|
|
135
|
+
const effectiveStorage = storage ?? baseStorage;
|
|
136
|
+
|
|
137
|
+
// 同步首读:localStorage / sessionStorage 命中即返回;indexedDB 未命中内存时返回 undefined(异步兜底)
|
|
138
|
+
const [columnEntry, setColumnEntry] = useState(() => getColumnCacheSync(effectiveStorage, pathKey));
|
|
139
|
+
|
|
140
|
+
// indexedDB 模式:异步加载 + setState 平滑替换(不闪烁)
|
|
141
|
+
useEffect(() => {
|
|
142
|
+
if (effectiveStorage !== 'indexedDB') return;
|
|
143
|
+
let cancelled = false;
|
|
144
|
+
Promise.resolve(getColumnCache(effectiveStorage, pathKey)).then(entry => {
|
|
145
|
+
if (cancelled) return;
|
|
146
|
+
if (entry) setColumnEntry(entry);
|
|
147
|
+
});
|
|
148
|
+
return () => {
|
|
149
|
+
cancelled = true;
|
|
150
|
+
};
|
|
151
|
+
}, [effectiveStorage, pathKey]);
|
|
152
|
+
const startTime = columnEntry?.startTime;
|
|
132
153
|
const [curColumns, setCurColumns] = useState(propsColumns);
|
|
133
154
|
useDeepCompareEffect(() => {
|
|
134
155
|
let localColumns;
|
|
135
156
|
const duration = (typeof cacheTime === 'number' ? cacheTime : defaultCacheTime) * 86400000;
|
|
136
157
|
// 开启缓存配置功能且缓存存在时,从缓存中获取缓存配置
|
|
137
158
|
if (cacheTime && startTime && new Date().getTime() - startTime < duration) {
|
|
138
|
-
localColumns =
|
|
159
|
+
localColumns = columnEntry?.columns?.map(item => ({
|
|
139
160
|
...propsColumnObj[getColumnDataIndex(item.dataIndex)],
|
|
140
161
|
dataIndex: item.dataIndex,
|
|
141
162
|
width: resizeColumn ? item?.width : propsColumnObj[getColumnDataIndex(item.dataIndex)]?.width
|
|
@@ -145,16 +166,13 @@ const ProTable = props => {
|
|
|
145
166
|
} else {
|
|
146
167
|
setCurColumns(propsColumns);
|
|
147
168
|
}
|
|
148
|
-
}, [pathKey, cacheTime, propsColumns]);
|
|
169
|
+
}, [pathKey, cacheTime, propsColumns, columnEntry]);
|
|
149
170
|
useEffect(() => {
|
|
150
|
-
if (!cacheTime &&
|
|
151
|
-
// 关闭缓存时,清理对应table缓存
|
|
152
|
-
|
|
153
|
-
...curTableConfig,
|
|
154
|
-
[pathKey]: undefined
|
|
155
|
-
}));
|
|
171
|
+
if (!cacheTime && columnEntry) {
|
|
172
|
+
// 关闭缓存时,清理对应 table 缓存
|
|
173
|
+
removeColumnCache(effectiveStorage, pathKey);
|
|
156
174
|
}
|
|
157
|
-
}, [cacheTime,
|
|
175
|
+
}, [cacheTime, columnEntry, effectiveStorage, pathKey]);
|
|
158
176
|
|
|
159
177
|
// 重置列宽,恢复至props的columns列宽
|
|
160
178
|
const resetColumnWidth = () => {
|
|
@@ -190,7 +208,7 @@ const ProTable = props => {
|
|
|
190
208
|
}
|
|
191
209
|
};
|
|
192
210
|
const formatColumns = nextColumns => {
|
|
193
|
-
nextColumns?.forEach(
|
|
211
|
+
nextColumns?.forEach(item => {
|
|
194
212
|
formatColumn({
|
|
195
213
|
column: item,
|
|
196
214
|
originalObj,
|
|
@@ -198,10 +216,9 @@ const ProTable = props => {
|
|
|
198
216
|
diffConfig,
|
|
199
217
|
wrapToolTipProps,
|
|
200
218
|
scroll: _scroll,
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
isInNewRow: _isInNewRow
|
|
219
|
+
isInNewRow: _isInNewRow,
|
|
220
|
+
editMode,
|
|
221
|
+
sharedForm: editMode === 'shared-form' ? sharedForm : undefined
|
|
205
222
|
});
|
|
206
223
|
if (item.children && Array.isArray(item.children)) {
|
|
207
224
|
formatColumns(item.children);
|
|
@@ -228,19 +245,30 @@ const ProTable = props => {
|
|
|
228
245
|
const nextColumns = formatColumns(newColumns);
|
|
229
246
|
return nextColumns;
|
|
230
247
|
}, [curColumns, handleResize, _scroll, originalDataSource, originalObj, _isInNewRow]);
|
|
231
|
-
|
|
248
|
+
|
|
249
|
+
// 仅在 dev 环境针对 column.show 提示一次(按实例去重)
|
|
250
|
+
const showDeprecationWarnedRef = useRef(false);
|
|
251
|
+
const _columns = useMemo(() => {
|
|
232
252
|
const {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
253
|
+
columns: filtered,
|
|
254
|
+
usedShow
|
|
255
|
+
} = filterVisibleColumns(columns || []);
|
|
256
|
+
if (usedShow && process.env.NODE_ENV !== 'production' && !showDeprecationWarnedRef.current) {
|
|
257
|
+
showDeprecationWarnedRef.current = true;
|
|
258
|
+
// eslint-disable-next-line no-console
|
|
259
|
+
console.warn('[ProTable] column.show is deprecated, please use column.hidden (antd 5.13+ native) instead. column.show 已废弃,请改用 column.hidden(antd 5.13+ 原生支持)。');
|
|
240
260
|
}
|
|
241
|
-
return
|
|
242
|
-
}
|
|
261
|
+
return filtered;
|
|
262
|
+
}, [columns]);
|
|
243
263
|
const isExistPercentWidth = !!_columns?.find(item => item?.width && typeof item?.width === 'string' && item?.width?.endsWith('%'));
|
|
264
|
+
|
|
265
|
+
// shared-form 模式下,仅当存在 editConfig 列时才需要包共享 Form Provider;
|
|
266
|
+
// 否则不挂载 Form,避免给纯展示型表格注入无意义的 Form Context
|
|
267
|
+
const hasEditConfigColumn = useMemo(() => {
|
|
268
|
+
const walk = (cols = []) => cols.some(c => Boolean(c?.editConfig) || Array.isArray(c?.children) && walk(c.children));
|
|
269
|
+
return walk(propsColumns);
|
|
270
|
+
}, [propsColumns]);
|
|
271
|
+
const shouldWrapSharedForm = editMode === 'shared-form' && hasEditConfigColumn;
|
|
244
272
|
if (isExistPercentWidth) {
|
|
245
273
|
_scroll = props?.scroll;
|
|
246
274
|
}
|
|
@@ -268,19 +296,16 @@ const ProTable = props => {
|
|
|
268
296
|
};
|
|
269
297
|
useDebounceEffect(() => {
|
|
270
298
|
if (cacheTime) {
|
|
271
|
-
const
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
width: typeof item.width === 'number' ? Math.round(Number(item.width)) : item.width
|
|
278
|
-
}))
|
|
279
|
-
}
|
|
299
|
+
const newEntry = {
|
|
300
|
+
startTime: new Date().getTime(),
|
|
301
|
+
columns: curColumns?.map(item => ({
|
|
302
|
+
dataIndex: item.dataIndex,
|
|
303
|
+
width: typeof item.width === 'number' ? Math.round(Number(item.width)) : item.width
|
|
304
|
+
}))
|
|
280
305
|
};
|
|
281
|
-
|
|
306
|
+
setColumnCache(effectiveStorage, pathKey, newEntry);
|
|
282
307
|
}
|
|
283
|
-
}, [cacheTime,
|
|
308
|
+
}, [cacheTime, effectiveStorage, pathKey, curColumns], {
|
|
284
309
|
wait: 100
|
|
285
310
|
});
|
|
286
311
|
const customColumns = useMemo(() => propsColumns.map(item => ({
|
|
@@ -346,80 +371,95 @@ const ProTable = props => {
|
|
|
346
371
|
'--zaui-contract-bg': changeTipColor,
|
|
347
372
|
'--zaui-contract-bg-add': addTipColor
|
|
348
373
|
};
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
},
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
374
|
+
const tableContent = /*#__PURE__*/_jsxs("div", {
|
|
375
|
+
className: cls,
|
|
376
|
+
children: [tabs && /*#__PURE__*/_jsx(RenderTabs, {
|
|
377
|
+
...tabs,
|
|
378
|
+
formTableProps: restProps?.formTableProps
|
|
379
|
+
}), /*#__PURE__*/_jsx(RenderTableHeader, {
|
|
380
|
+
dataSource: {
|
|
381
|
+
headerRender,
|
|
382
|
+
columnConfig,
|
|
383
|
+
resizeColumn,
|
|
384
|
+
resetSvg,
|
|
385
|
+
resetColumnWidth,
|
|
386
|
+
locale,
|
|
387
|
+
customColumns,
|
|
388
|
+
checkColumns,
|
|
389
|
+
handleColumnConfig,
|
|
390
|
+
customColumnSvg
|
|
391
|
+
}
|
|
392
|
+
}), /*#__PURE__*/_jsxs("div", {
|
|
393
|
+
className: "pro-table-container",
|
|
394
|
+
style: tagStyle,
|
|
395
|
+
children: [/*#__PURE__*/_jsx(TableComponent, {
|
|
396
|
+
ref: tableRef,
|
|
397
|
+
...restProps,
|
|
398
|
+
draggableProps: {
|
|
399
|
+
onChange: onDataSourceChange,
|
|
400
|
+
draggable,
|
|
401
|
+
rowKey,
|
|
402
|
+
onDragStartGuard,
|
|
403
|
+
onDragEndGuard
|
|
404
|
+
},
|
|
405
|
+
tableProps: {
|
|
406
|
+
value: _dataSource,
|
|
362
407
|
headerRender,
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
408
|
+
columns: _columns,
|
|
409
|
+
renderRowSelection,
|
|
410
|
+
rowClassName: _rowClassName,
|
|
411
|
+
disabled,
|
|
412
|
+
resizeColumn
|
|
413
|
+
},
|
|
414
|
+
emptyTextProps: {
|
|
415
|
+
empty,
|
|
367
416
|
locale,
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
draggable,
|
|
381
|
-
rowKey,
|
|
382
|
-
onDragStartGuard,
|
|
383
|
-
onDragEndGuard
|
|
384
|
-
},
|
|
385
|
-
tableProps: {
|
|
386
|
-
value: _dataSource,
|
|
387
|
-
headerRender,
|
|
388
|
-
columns: _columns,
|
|
389
|
-
renderRowSelection,
|
|
390
|
-
rowClassName: _rowClassName,
|
|
391
|
-
disabled,
|
|
392
|
-
resizeColumn
|
|
393
|
-
},
|
|
394
|
-
emptyTextProps: {
|
|
395
|
-
empty,
|
|
396
|
-
locale,
|
|
397
|
-
emptyText
|
|
398
|
-
},
|
|
399
|
-
summaryProps: {
|
|
400
|
-
summary,
|
|
401
|
-
dataSource: _dataSource
|
|
402
|
-
},
|
|
403
|
-
dataSource: _dataSource,
|
|
404
|
-
scroll: _scroll
|
|
405
|
-
}), /*#__PURE__*/_jsx("span", {
|
|
406
|
-
className: "pro-table-resizable-line",
|
|
407
|
-
style: {
|
|
408
|
-
display: 'none'
|
|
409
|
-
}
|
|
410
|
-
})]
|
|
411
|
-
}), /*#__PURE__*/_jsx(RenderFooter, {
|
|
412
|
-
dataSource: {
|
|
413
|
-
footerRender,
|
|
414
|
-
pagination,
|
|
415
|
-
_dataSource
|
|
417
|
+
emptyText
|
|
418
|
+
},
|
|
419
|
+
summaryProps: {
|
|
420
|
+
summary,
|
|
421
|
+
dataSource: _dataSource
|
|
422
|
+
},
|
|
423
|
+
dataSource: _dataSource,
|
|
424
|
+
scroll: _scroll
|
|
425
|
+
}), /*#__PURE__*/_jsx("span", {
|
|
426
|
+
className: "pro-table-resizable-line",
|
|
427
|
+
style: {
|
|
428
|
+
display: 'none'
|
|
416
429
|
}
|
|
417
430
|
})]
|
|
418
|
-
})
|
|
431
|
+
}), /*#__PURE__*/_jsx(RenderFooter, {
|
|
432
|
+
dataSource: {
|
|
433
|
+
footerRender,
|
|
434
|
+
pagination,
|
|
435
|
+
_dataSource
|
|
436
|
+
}
|
|
437
|
+
})]
|
|
419
438
|
});
|
|
420
|
-
|
|
439
|
+
|
|
440
|
+
// 向后兼容:旧 Context 字段映射到新 columnStorage 语义
|
|
441
|
+
// - tableConfig 之前是 { [pathKey]: entry } 的 JSON map;现仍按此结构包一层
|
|
442
|
+
// - Storage 之前是 Storage 实例;indexedDB 模式下不可同步访问,返回 null
|
|
443
|
+
const legacyTableConfig = columnEntry ? {
|
|
444
|
+
[pathKey]: columnEntry
|
|
445
|
+
} : {};
|
|
446
|
+
const legacyStorage = effectiveStorage === 'localStorage' ? window.localStorage : effectiveStorage === 'sessionStorage' ? window.sessionStorage : null;
|
|
447
|
+
return /*#__PURE__*/_jsx(TableContext.Provider, {
|
|
448
|
+
value: {
|
|
449
|
+
pathKey,
|
|
450
|
+
tableConfig: legacyTableConfig,
|
|
451
|
+
Storage: legacyStorage
|
|
452
|
+
},
|
|
453
|
+
children: shouldWrapSharedForm ? /*#__PURE__*/_jsx(Form, {
|
|
454
|
+
form: sharedForm,
|
|
455
|
+
component: false,
|
|
456
|
+
children: tableContent
|
|
457
|
+
}) : tableContent
|
|
458
|
+
});
|
|
459
|
+
});
|
|
421
460
|
ProTable.useAntdTable = useAntdTable;
|
|
422
461
|
ProTable.SELECTION_ALL = SELECTION_ALL;
|
|
423
462
|
ProTable.CURRENT_PAGE = CURRENT_PAGE;
|
|
424
463
|
ProTable.UNCHECK_ALL = UNCHECK_ALL;
|
|
464
|
+
export { getColumnCache, setColumnCache, removeColumnCache } from "./utils/columnStorage";
|
|
425
465
|
export default ProTable;
|
|
@@ -117,9 +117,9 @@ export interface ProTableColumnType extends Omit<ColumnType<any>, 'dataIndex'> {
|
|
|
117
117
|
*/
|
|
118
118
|
width?: number | string;
|
|
119
119
|
/**
|
|
120
|
-
*
|
|
121
|
-
* @description
|
|
122
|
-
* @default
|
|
120
|
+
* 列最小宽度
|
|
121
|
+
* @description 透传至 antd Table column.minWidth(antd 5.21+),用于 tableLayout='auto' 下计算最小列宽;同时作为列宽拖拽下限
|
|
122
|
+
* @default undefined
|
|
123
123
|
*/
|
|
124
124
|
minWidth?: number;
|
|
125
125
|
/**
|
|
@@ -194,9 +194,16 @@ export interface ProTableColumnType extends Omit<ColumnType<any>, 'dataIndex'> {
|
|
|
194
194
|
* @default undefined
|
|
195
195
|
*/
|
|
196
196
|
transform?: (value: any, record?: any) => string[];
|
|
197
|
+
/**
|
|
198
|
+
* 列隐藏(antd 5.13+ 原生支持)
|
|
199
|
+
* @description 控制列是否隐藏;优先级高于 show
|
|
200
|
+
* @default undefined
|
|
201
|
+
*/
|
|
202
|
+
hidden?: boolean;
|
|
197
203
|
/**
|
|
198
204
|
* 列头显示控制
|
|
199
|
-
* @
|
|
205
|
+
* @deprecated 请改用 column.hidden(antd 5.13+ 原生支持)。show 将在后续版本移除。
|
|
206
|
+
* @description 控制列是否显示;当 hidden 缺省时回退此字段
|
|
200
207
|
* @default true
|
|
201
208
|
*/
|
|
202
209
|
show?: boolean | (() => boolean);
|
|
@@ -462,10 +469,10 @@ export interface ProTableType<T = any> extends Omit<TableProps<any>, 'summary' |
|
|
|
462
469
|
sortColumnText?: string;
|
|
463
470
|
/**
|
|
464
471
|
* 浏览器缓存位置
|
|
465
|
-
* @description
|
|
472
|
+
* @description 用于设置表格列配置的存储位置;'indexedDB' 走异步存储,容量大且不阻塞主线程;其他两种走同步 Web Storage。
|
|
466
473
|
* @default 'localStorage'
|
|
467
474
|
*/
|
|
468
|
-
storage?: 'localStorage' | 'sessionStorage';
|
|
475
|
+
storage?: 'localStorage' | 'sessionStorage' | 'indexedDB';
|
|
469
476
|
/**
|
|
470
477
|
* 自定义 table footer 左侧渲染
|
|
471
478
|
* @description 可以是 ReactNode 或返回 ReactNode 的函数
|
|
@@ -544,6 +551,14 @@ export interface ProTableType<T = any> extends Omit<TableProps<any>, 'summary' |
|
|
|
544
551
|
* @default true
|
|
545
552
|
*/
|
|
546
553
|
scrollFollowParent?: boolean;
|
|
554
|
+
/**
|
|
555
|
+
* 行内编辑 Form 模式
|
|
556
|
+
* @description
|
|
557
|
+
* - 'per-cell-form'(默认):每个 cell 独立 Form 实例,行为与重构前一致
|
|
558
|
+
* - 'shared-form':ProTable 顶层创建共享 Form,所有 cell 复用,并自动注入 column.shouldCellUpdate 实现单 cell 精确更新
|
|
559
|
+
* @default 'per-cell-form'
|
|
560
|
+
*/
|
|
561
|
+
editMode?: 'per-cell-form' | 'shared-form';
|
|
547
562
|
[key: string]: any;
|
|
548
563
|
}
|
|
549
564
|
/**
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export type StorageType = 'localStorage' | 'sessionStorage' | 'indexedDB';
|
|
2
|
+
/** v4 默认列缓存存储类型 */
|
|
3
|
+
export declare const baseStorage: StorageType;
|
|
4
|
+
/** 单条列缓存条目结构 */
|
|
5
|
+
export interface ColumnCacheEntry {
|
|
6
|
+
startTime?: number;
|
|
7
|
+
columns?: any[];
|
|
8
|
+
[key: string]: any;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* 同步读取列缓存
|
|
12
|
+
* - localStorage / sessionStorage:直接同步读
|
|
13
|
+
* - indexedDB:仅命中内存缓存时同步返回,否则 undefined(业务侧需异步兜底)
|
|
14
|
+
*/
|
|
15
|
+
export declare function getColumnCacheSync(storage: StorageType, pathKey: string): ColumnCacheEntry | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* 读取列缓存
|
|
18
|
+
* - localStorage / sessionStorage:同步返回
|
|
19
|
+
* - indexedDB:返回 Promise;命中内存缓存时同样走 Promise(保持调用侧一致)
|
|
20
|
+
*/
|
|
21
|
+
export declare function getColumnCache(storage: StorageType, pathKey: string): ColumnCacheEntry | undefined | Promise<ColumnCacheEntry | undefined>;
|
|
22
|
+
/**
|
|
23
|
+
* 写入列缓存
|
|
24
|
+
* - localStorage / sessionStorage:同步写
|
|
25
|
+
* - indexedDB:同步预热内存缓存 + 异步持久化(返回 Promise)
|
|
26
|
+
*/
|
|
27
|
+
export declare function setColumnCache(storage: StorageType, pathKey: string, value: ColumnCacheEntry): void | Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* 删除列缓存
|
|
30
|
+
*/
|
|
31
|
+
export declare function removeColumnCache(storage: StorageType, pathKey: string): void | Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* 仅供测试:重置内存缓存与 IndexedDB 可用性探测结果
|
|
34
|
+
*/
|
|
35
|
+
export declare function __resetColumnCacheForTest(): void;
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { get as idbGet, set as idbSet, del as idbDel } from 'idb-keyval';
|
|
2
|
+
/** v4 默认列缓存存储类型 */
|
|
3
|
+
export const baseStorage = 'localStorage';
|
|
4
|
+
|
|
5
|
+
/** 顶层共享 key(向后兼容现有 localStorage / sessionStorage 中已存在的 'tableConfig' 数据) */
|
|
6
|
+
const TOP_KEY = 'tableConfig';
|
|
7
|
+
|
|
8
|
+
/** 单条列缓存条目结构 */
|
|
9
|
+
|
|
10
|
+
/** 模块级内存缓存:pathKey → ColumnCacheEntry */
|
|
11
|
+
const memoryCache = new Map();
|
|
12
|
+
|
|
13
|
+
/** IndexedDB 可用性探测结果(首次 set/del 试探后缓存) */
|
|
14
|
+
let indexedDBAvailable = null;
|
|
15
|
+
const isSSR = () => typeof window === 'undefined';
|
|
16
|
+
const getWebStorage = storage => {
|
|
17
|
+
if (isSSR()) return null;
|
|
18
|
+
return storage === 'sessionStorage' ? window.sessionStorage : window.localStorage;
|
|
19
|
+
};
|
|
20
|
+
const readTopMap = storage => {
|
|
21
|
+
const ws = getWebStorage(storage);
|
|
22
|
+
if (!ws) return {};
|
|
23
|
+
try {
|
|
24
|
+
const raw = ws.getItem(TOP_KEY);
|
|
25
|
+
if (!raw) return {};
|
|
26
|
+
const parsed = JSON.parse(raw);
|
|
27
|
+
return parsed && typeof parsed === 'object' ? parsed : {};
|
|
28
|
+
} catch {
|
|
29
|
+
return {};
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
const writeTopMap = (storage, next) => {
|
|
33
|
+
const ws = getWebStorage(storage);
|
|
34
|
+
if (!ws) return;
|
|
35
|
+
ws.setItem(TOP_KEY, JSON.stringify(next));
|
|
36
|
+
};
|
|
37
|
+
async function checkIndexedDBSupport() {
|
|
38
|
+
if (indexedDBAvailable !== null) return indexedDBAvailable;
|
|
39
|
+
try {
|
|
40
|
+
await idbSet('__pro_table_idb_test__', 1);
|
|
41
|
+
await idbDel('__pro_table_idb_test__');
|
|
42
|
+
indexedDBAvailable = true;
|
|
43
|
+
return true;
|
|
44
|
+
} catch (error) {
|
|
45
|
+
// eslint-disable-next-line no-console
|
|
46
|
+
console.warn('ProTable: IndexedDB is not available, falling back to localStorage. 列缓存默认存储 IndexedDB 不可用,已自动降级到 localStorage。', error);
|
|
47
|
+
indexedDBAvailable = false;
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* 同步读取列缓存
|
|
54
|
+
* - localStorage / sessionStorage:直接同步读
|
|
55
|
+
* - indexedDB:仅命中内存缓存时同步返回,否则 undefined(业务侧需异步兜底)
|
|
56
|
+
*/
|
|
57
|
+
export function getColumnCacheSync(storage, pathKey) {
|
|
58
|
+
if (memoryCache.has(pathKey)) return memoryCache.get(pathKey);
|
|
59
|
+
if (storage === 'localStorage' || storage === 'sessionStorage') {
|
|
60
|
+
const map = readTopMap(storage);
|
|
61
|
+
const entry = map[pathKey];
|
|
62
|
+
memoryCache.set(pathKey, entry);
|
|
63
|
+
return entry;
|
|
64
|
+
}
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* 读取列缓存
|
|
70
|
+
* - localStorage / sessionStorage:同步返回
|
|
71
|
+
* - indexedDB:返回 Promise;命中内存缓存时同样走 Promise(保持调用侧一致)
|
|
72
|
+
*/
|
|
73
|
+
export function getColumnCache(storage, pathKey) {
|
|
74
|
+
if (storage === 'localStorage' || storage === 'sessionStorage') {
|
|
75
|
+
return getColumnCacheSync(storage, pathKey);
|
|
76
|
+
}
|
|
77
|
+
// indexedDB
|
|
78
|
+
if (memoryCache.has(pathKey)) {
|
|
79
|
+
return Promise.resolve(memoryCache.get(pathKey));
|
|
80
|
+
}
|
|
81
|
+
if (isSSR()) {
|
|
82
|
+
return Promise.resolve(undefined);
|
|
83
|
+
}
|
|
84
|
+
return checkIndexedDBSupport().then(async ok => {
|
|
85
|
+
if (!ok) {
|
|
86
|
+
// 降级路径:尝试从 localStorage 读取
|
|
87
|
+
const map = readTopMap('localStorage');
|
|
88
|
+
const entry = map[pathKey];
|
|
89
|
+
memoryCache.set(pathKey, entry);
|
|
90
|
+
return entry;
|
|
91
|
+
}
|
|
92
|
+
try {
|
|
93
|
+
const value = await idbGet(pathKey);
|
|
94
|
+
memoryCache.set(pathKey, value);
|
|
95
|
+
return value;
|
|
96
|
+
} catch (error) {
|
|
97
|
+
// eslint-disable-next-line no-console
|
|
98
|
+
console.warn('ProTable: IndexedDB read failed:', error);
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* 写入列缓存
|
|
106
|
+
* - localStorage / sessionStorage:同步写
|
|
107
|
+
* - indexedDB:同步预热内存缓存 + 异步持久化(返回 Promise)
|
|
108
|
+
*/
|
|
109
|
+
export function setColumnCache(storage, pathKey, value) {
|
|
110
|
+
memoryCache.set(pathKey, value);
|
|
111
|
+
if (isSSR()) return;
|
|
112
|
+
if (storage === 'localStorage' || storage === 'sessionStorage') {
|
|
113
|
+
const map = readTopMap(storage);
|
|
114
|
+
map[pathKey] = value;
|
|
115
|
+
writeTopMap(storage, map);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
// indexedDB
|
|
119
|
+
return checkIndexedDBSupport().then(async ok => {
|
|
120
|
+
if (!ok) {
|
|
121
|
+
// 降级到 localStorage
|
|
122
|
+
const map = readTopMap('localStorage');
|
|
123
|
+
map[pathKey] = value;
|
|
124
|
+
writeTopMap('localStorage', map);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
try {
|
|
128
|
+
await idbSet(pathKey, value);
|
|
129
|
+
} catch (error) {
|
|
130
|
+
// eslint-disable-next-line no-console
|
|
131
|
+
console.warn('ProTable: IndexedDB write failed:', error);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* 删除列缓存
|
|
138
|
+
*/
|
|
139
|
+
export function removeColumnCache(storage, pathKey) {
|
|
140
|
+
memoryCache.delete(pathKey);
|
|
141
|
+
if (isSSR()) return;
|
|
142
|
+
if (storage === 'localStorage' || storage === 'sessionStorage') {
|
|
143
|
+
const map = readTopMap(storage);
|
|
144
|
+
delete map[pathKey];
|
|
145
|
+
writeTopMap(storage, map);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
// indexedDB
|
|
149
|
+
return checkIndexedDBSupport().then(async ok => {
|
|
150
|
+
if (!ok) {
|
|
151
|
+
const map = readTopMap('localStorage');
|
|
152
|
+
delete map[pathKey];
|
|
153
|
+
writeTopMap('localStorage', map);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
try {
|
|
157
|
+
await idbDel(pathKey);
|
|
158
|
+
} catch (error) {
|
|
159
|
+
// eslint-disable-next-line no-console
|
|
160
|
+
console.warn('ProTable: IndexedDB delete failed:', error);
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* 仅供测试:重置内存缓存与 IndexedDB 可用性探测结果
|
|
167
|
+
*/
|
|
168
|
+
export function __resetColumnCacheForTest() {
|
|
169
|
+
memoryCache.clear();
|
|
170
|
+
indexedDBAvailable = null;
|
|
171
|
+
}
|
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 列可见性过滤:hidden 优先(antd 5.13+ 原生),show 兼容(已废弃)
|
|
3
|
+
* - hidden 为布尔值 → 直接按 hidden 决定
|
|
4
|
+
* - hidden 缺省、show 为布尔值 → 按 show 决定
|
|
5
|
+
* - hidden 缺省、show 为函数 → 调用 show() 决定
|
|
6
|
+
* - 都缺省 → 显示
|
|
7
|
+
*
|
|
8
|
+
* 返回过滤后的列与 deprecated show 使用情况,由调用方决定告警时机/去重。
|
|
9
|
+
*/
|
|
10
|
+
export declare const filterVisibleColumns: <T extends {
|
|
11
|
+
hidden?: boolean;
|
|
12
|
+
show?: boolean | (() => boolean);
|
|
13
|
+
}>(columns?: T[]) => {
|
|
14
|
+
columns: T[];
|
|
15
|
+
usedShow: boolean;
|
|
16
|
+
};
|
|
1
17
|
/**
|
|
2
18
|
* 获取小数点后的位数
|
|
3
19
|
* @param num 数字
|
|
@@ -34,5 +50,3 @@ export declare const removeEmptyKeys: (obj?: Record<string, any>) => {
|
|
|
34
50
|
};
|
|
35
51
|
/** 判断是有值的对象 */
|
|
36
52
|
export declare const isNonEmptyObject: (obj: any) => obj is Record<string, any>;
|
|
37
|
-
/** 解析宽度值 */
|
|
38
|
-
export declare const parseWidth: (widthValue: number | string | undefined, trWidth: number) => number;
|