@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.
Files changed (39) hide show
  1. package/dist/index.esm.css +1 -1
  2. package/dist/less.esm.css +1 -1
  3. package/es/ProConfigProvider/index.d.ts +1 -1
  4. package/es/ProConfigProvider/index.js +6 -7
  5. package/es/ProConfigProvider/propsType.d.ts +22 -0
  6. package/es/ProEditTable/components/RcTable/DraggableTable.js +18 -32
  7. package/es/ProEditTable/index.js +7 -1
  8. package/es/ProEditTable/style/index.less +0 -5
  9. package/es/ProEditTable/utils/config.js +2 -0
  10. package/es/ProEditTable/utils/index.d.ts +15 -1
  11. package/es/ProEditTable/utils/index.js +27 -15
  12. package/es/ProForm/components/combination/Group/utils/index.d.ts +9 -9
  13. package/es/ProForm/utils/useWatch.d.ts +14 -4
  14. package/es/ProForm/utils/useWatch.js +48 -18
  15. package/es/ProTable/components/EditableCell/index.js +55 -22
  16. package/es/ProTable/components/EditableCell/propsType.d.ts +14 -0
  17. package/es/ProTable/components/FormatColumn/index.d.ts +4 -2
  18. package/es/ProTable/components/FormatColumn/index.js +13 -46
  19. package/es/ProTable/components/RcTable/components/BaseTable/index.d.ts +1 -8
  20. package/es/ProTable/components/RcTable/components/BaseTable/index.js +5 -4
  21. package/es/ProTable/components/RcTable/components/DraggableTable/components/DndWrapper/index.d.ts +1 -1
  22. package/es/ProTable/components/RcTable/components/DraggableTable/components/DndWrapper/index.js +19 -32
  23. package/es/ProTable/components/RcTable/components/DraggableTable/index.d.ts +1 -8
  24. package/es/ProTable/components/RcTable/components/DraggableTable/index.js +5 -4
  25. package/es/ProTable/components/RenderColumn/index.js +1 -17
  26. package/es/ProTable/index.d.ts +9 -8
  27. package/es/ProTable/index.js +151 -111
  28. package/es/ProTable/propsType.d.ts +21 -6
  29. package/es/ProTable/utils/columnStorage.d.ts +35 -0
  30. package/es/ProTable/utils/columnStorage.js +171 -0
  31. package/es/ProTable/utils/index.d.ts +16 -2
  32. package/es/ProTable/utils/index.js +34 -21
  33. package/es/hooks/useDraggableRow.d.ts +34 -0
  34. package/es/hooks/useDraggableRow.js +70 -0
  35. package/package.json +1 -3
  36. package/es/ProForm/components/base/DatePicker/useDateLimit.d.ts +0 -3
  37. package/es/ProForm/components/base/DatePicker/useDateLimit.js +0 -7
  38. package/es/ProForm/components/combination/FormList/components/BlockTitle.d.ts +0 -13
  39. package/es/ProForm/components/combination/FormList/components/BlockTitle.js +0 -31
@@ -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
- const Storage = storage === 'sessionStorage' ? sessionStorage : localStorage;
129
- const tableConfig = Storage.getItem('tableConfig');
130
- const curTableConfig = tableConfig ? JSON.parse(tableConfig) : {};
131
- const startTime = curTableConfig[pathKey]?.startTime;
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 = curTableConfig[pathKey]?.columns?.map(item => ({
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 && JSON.stringify(curTableConfig) !== '{}') {
151
- // 关闭缓存时,清理对应table缓存
152
- Storage.setItem('tableConfig', JSON.stringify({
153
- ...curTableConfig,
154
- [pathKey]: undefined
155
- }));
171
+ if (!cacheTime && columnEntry) {
172
+ // 关闭缓存时,清理对应 table 缓存
173
+ removeColumnCache(effectiveStorage, pathKey);
156
174
  }
157
- }, [cacheTime, curTableConfig, storage]);
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((item, index) => {
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
- onUpdateMinWidth: w => {
202
- curColumns[index].minWidth = w;
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
- const _columns = useMemo(() => columns?.filter((item, index) => {
248
+
249
+ // 仅在 dev 环境针对 column.show 提示一次(按实例去重)
250
+ const showDeprecationWarnedRef = useRef(false);
251
+ const _columns = useMemo(() => {
232
252
  const {
233
- show
234
- } = item;
235
- if (_isBoolean(show)) {
236
- return show;
237
- }
238
- if (_isFunction(show)) {
239
- return show();
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 true;
242
- }), [columns]);
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 newTableConfig = {
272
- ...curTableConfig,
273
- [pathKey]: {
274
- startTime: new Date().getTime(),
275
- columns: curColumns?.map(item => ({
276
- dataIndex: item.dataIndex,
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
- Storage.setItem('tableConfig', JSON.stringify(newTableConfig));
306
+ setColumnCache(effectiveStorage, pathKey, newEntry);
282
307
  }
283
- }, [cacheTime, storage, pathKey, curColumns], {
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
- return /*#__PURE__*/_jsx(TableContext.Provider, {
350
- value: {
351
- pathKey,
352
- tableConfig,
353
- Storage
354
- },
355
- children: /*#__PURE__*/_jsxs("div", {
356
- className: cls,
357
- children: [tabs && /*#__PURE__*/_jsx(RenderTabs, {
358
- ...tabs,
359
- formTableProps: restProps?.formTableProps
360
- }), /*#__PURE__*/_jsx(RenderTableHeader, {
361
- dataSource: {
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
- columnConfig,
364
- resizeColumn,
365
- resetSvg,
366
- resetColumnWidth,
408
+ columns: _columns,
409
+ renderRowSelection,
410
+ rowClassName: _rowClassName,
411
+ disabled,
412
+ resizeColumn
413
+ },
414
+ emptyTextProps: {
415
+ empty,
367
416
  locale,
368
- customColumns,
369
- checkColumns,
370
- handleColumnConfig,
371
- customColumnSvg
372
- }
373
- }), /*#__PURE__*/_jsxs("div", {
374
- className: "pro-table-container",
375
- style: tagStyle,
376
- children: [/*#__PURE__*/_jsx(TableComponent, {
377
- ...restProps,
378
- draggableProps: {
379
- onChange: onDataSourceChange,
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 50
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
- * @description 控制列是否显示
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;