@gx-design-vue/pro-table 0.2.0-alpha.7 → 0.2.0-alpha.9

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 (133) hide show
  1. package/dist/ProTable.d.ts +14 -492
  2. package/dist/ProTable.js +818 -518
  3. package/dist/components/ScrollBar/Bar.d.ts +81 -0
  4. package/dist/components/ScrollBar/Bar.js +84 -0
  5. package/dist/components/ScrollBar/Thumb.d.ts +52 -0
  6. package/dist/components/ScrollBar/{Thumb/index.js → Thumb.js} +67 -55
  7. package/dist/components/ScrollBar/context.d.ts +3 -4
  8. package/dist/components/ScrollBar/context.js +3 -3
  9. package/dist/components/ScrollBar/util.d.ts +6 -5
  10. package/dist/components/ScrollBar/util.js +1 -12
  11. package/dist/components/SearchForm/CollapseToggle.d.ts +55 -0
  12. package/dist/components/SearchForm/CollapseToggle.js +47 -0
  13. package/dist/components/SearchForm/FormItemContainer.d.ts +75 -0
  14. package/dist/components/SearchForm/FormItemContainer.js +225 -0
  15. package/dist/components/SearchForm/FormItemWrapper.d.ts +82 -0
  16. package/dist/components/SearchForm/FormItemWrapper.js +62 -0
  17. package/dist/components/SearchForm/SearchForm.d.ts +130 -0
  18. package/dist/components/SearchForm/SearchForm.js +319 -0
  19. package/dist/components/SearchForm/index.d.ts +2 -0
  20. package/dist/components/SearchForm/index.js +2 -0
  21. package/dist/components/Toolbar/FullscreenIcon.d.ts +26 -0
  22. package/dist/components/Toolbar/FullscreenIcon.js +22 -0
  23. package/dist/components/Toolbar/ListToolBar.d.ts +111 -0
  24. package/dist/components/Toolbar/ListToolBar.js +101 -0
  25. package/dist/components/Toolbar/index.d.ts +103 -0
  26. package/dist/components/Toolbar/index.js +101 -0
  27. package/dist/components/Toolbar/style.d.ts +8 -0
  28. package/dist/components/{ListToolBar → Toolbar}/style.js +32 -27
  29. package/dist/context/TableContext.d.ts +15 -27
  30. package/dist/context/TableContext.js +3 -3
  31. package/dist/hooks/index.d.ts +16 -0
  32. package/dist/hooks/index.js +16 -0
  33. package/dist/hooks/useBreakpoints.d.ts +13 -0
  34. package/dist/hooks/useBreakpoints.js +57 -0
  35. package/dist/hooks/useCellRender.d.ts +13 -0
  36. package/dist/hooks/useCellRender.js +28 -0
  37. package/dist/hooks/useColumnResize.d.ts +30 -0
  38. package/dist/hooks/useColumnResize.js +110 -0
  39. package/dist/hooks/useColumns.d.ts +35 -24
  40. package/dist/hooks/useColumns.js +89 -56
  41. package/dist/hooks/useFetchData.d.ts +40 -65
  42. package/dist/hooks/useFetchData.js +157 -172
  43. package/dist/hooks/useFitPage.d.ts +19 -0
  44. package/dist/hooks/useFitPage.js +90 -0
  45. package/dist/hooks/useKeepAliveReload.d.ts +21 -0
  46. package/dist/hooks/useKeepAliveReload.js +24 -0
  47. package/dist/hooks/useLoading.d.ts +18 -7
  48. package/dist/hooks/useLoading.js +26 -8
  49. package/dist/hooks/usePagination.d.ts +10 -7
  50. package/dist/hooks/usePagination.js +37 -26
  51. package/dist/hooks/useRequestOptions.d.ts +18 -0
  52. package/dist/hooks/useRequestOptions.js +39 -0
  53. package/dist/hooks/useRowSelection.d.ts +27 -15
  54. package/dist/hooks/useRowSelection.js +92 -77
  55. package/dist/hooks/useTable.d.ts +19 -77
  56. package/dist/hooks/useTable.js +66 -54
  57. package/dist/hooks/useTableForm.d.ts +15 -83
  58. package/dist/hooks/useTableForm.js +93 -56
  59. package/dist/hooks/useTableScroll.d.ts +33 -31
  60. package/dist/hooks/useTableScroll.js +71 -26
  61. package/dist/hooks/useTableSize.d.ts +17 -7
  62. package/dist/hooks/useTableSize.js +20 -6
  63. package/dist/index.d.ts +10 -7
  64. package/dist/index.js +9 -3
  65. package/dist/interface.d.ts +492 -0
  66. package/dist/pro-table.esm.js +3483 -3913
  67. package/dist/pro-table.js +1 -1
  68. package/dist/style/fit-page.d.ts +4 -2
  69. package/dist/style/fit-page.js +9 -3
  70. package/dist/style/index.d.ts +4 -6
  71. package/dist/style/index.js +24 -74
  72. package/dist/style/list.d.ts +4 -2
  73. package/dist/style/list.js +1 -10
  74. package/dist/style/resizable.d.ts +8 -0
  75. package/dist/style/resizable.js +18 -0
  76. package/dist/style/scroll.d.ts +4 -2
  77. package/dist/style/scroll.js +8 -6
  78. package/dist/style/search.d.ts +8 -0
  79. package/dist/{components/Form/style.js → style/search.js} +22 -8
  80. package/dist/theme/augment.d.ts +8 -0
  81. package/dist/theme/interface/components.d.ts +8 -0
  82. package/dist/utils/dateFormat.d.ts +9 -0
  83. package/dist/utils/dateFormat.js +29 -0
  84. package/dist/utils/formConstants.d.ts +9 -0
  85. package/dist/utils/formConstants.js +29 -0
  86. package/dist/utils/valueFormat.d.ts +9 -0
  87. package/dist/utils/valueFormat.js +27 -0
  88. package/package.json +10 -9
  89. package/dist/components/Form/components/RequestSelect.d.ts +0 -50
  90. package/dist/components/Form/components/RequestSelect.js +0 -56
  91. package/dist/components/Form/hooks/useForm.d.ts +0 -11
  92. package/dist/components/Form/hooks/useForm.js +0 -30
  93. package/dist/components/Form/index.d.ts +0 -32
  94. package/dist/components/Form/index.js +0 -476
  95. package/dist/components/Form/style.d.ts +0 -6
  96. package/dist/components/Form/utils/config.d.ts +0 -9
  97. package/dist/components/Form/utils/config.js +0 -29
  98. package/dist/components/Form/utils/dateFormat.d.ts +0 -22
  99. package/dist/components/Form/utils/dateFormat.js +0 -43
  100. package/dist/components/ListToolBar/index.d.ts +0 -59
  101. package/dist/components/ListToolBar/index.js +0 -123
  102. package/dist/components/ListToolBar/style.d.ts +0 -6
  103. package/dist/components/ScrollBar/Bar/index.d.ts +0 -49
  104. package/dist/components/ScrollBar/Bar/index.js +0 -68
  105. package/dist/components/ScrollBar/Bar/props.d.ts +0 -25
  106. package/dist/components/ScrollBar/Bar/props.js +0 -17
  107. package/dist/components/ScrollBar/Thumb/index.d.ts +0 -40
  108. package/dist/components/ScrollBar/Thumb/props.d.ts +0 -20
  109. package/dist/components/ScrollBar/Thumb/props.js +0 -17
  110. package/dist/components/TableCell/index.d.ts +0 -37
  111. package/dist/components/TableCell/index.js +0 -69
  112. package/dist/components/ToolBar/FullscreenIcon.d.ts +0 -7
  113. package/dist/components/ToolBar/FullscreenIcon.js +0 -11
  114. package/dist/components/ToolBar/index.d.ts +0 -34
  115. package/dist/components/ToolBar/index.js +0 -97
  116. package/dist/hooks/tryOnActivated.d.ts +0 -6
  117. package/dist/hooks/tryOnActivated.js +0 -12
  118. package/dist/hooks/useDebounceFn.d.ts +0 -8
  119. package/dist/hooks/useDebounceFn.js +0 -31
  120. package/dist/hooks/useScrollArea.d.ts +0 -24
  121. package/dist/hooks/useScrollArea.js +0 -102
  122. package/dist/props.d.ts +0 -340
  123. package/dist/props.js +0 -247
  124. package/dist/types/ColumnTypings.d.ts +0 -130
  125. package/dist/types/SlotsTypings.d.ts +0 -63
  126. package/dist/types/SlotsTypings.js +0 -12
  127. package/dist/types/TableTypings.d.ts +0 -359
  128. package/dist/types/index.d.ts +0 -9
  129. package/dist/utils/utils.d.ts +0 -10
  130. package/dist/utils/utils.js +0 -89
  131. /package/dist/{types/ColumnTypings.js → interface.js} +0 -0
  132. /package/dist/{types/TableTypings.js → theme/augment.js} +0 -0
  133. /package/dist/{types/index.js → theme/interface/components.js} +0 -0
@@ -1,10 +1,9 @@
1
- import { reactive, ref, unref, watch } from "vue";
2
- import { cloneDeep, deepMerge, forInObject, isFunction, isNumber } from "@gx-design-vue/pro-utils";
3
- //#region src/hooks/usePagination.tsx
1
+ import { computed, reactive, ref, watch } from "vue";
2
+ import { isNumber, merge } from "@gx-design-vue/pro-utils";
3
+ //#region src/hooks/usePagination.ts
4
4
  const defaultPagination = {
5
5
  current: 1,
6
6
  pageSize: 10,
7
- size: "default",
8
7
  showQuickJumper: true,
9
8
  showSizeChanger: true,
10
9
  pageSizeOptions: [
@@ -14,44 +13,56 @@ const defaultPagination = {
14
13
  "100"
15
14
  ]
16
15
  };
17
- function usePagination({ pagination, pageItemRender }) {
16
+ /**
17
+ * 分页状态管理。
18
+ * 合并用户分页配置与默认值,分离 UI 分页展示与请求分页参数。
19
+ * setPagination 只同步 current/pageSize/total 到 requestPagination,避免 UI 字段污染请求参数。
20
+ */
21
+ function usePagination({ pagination }) {
18
22
  const paginationInfo = ref({ ...defaultPagination });
19
23
  const requestPagination = reactive({
20
- current: defaultPagination.current || 1,
21
- pageSize: defaultPagination.pageSize || 10,
24
+ current: defaultPagination.current,
25
+ pageSize: defaultPagination.pageSize,
22
26
  total: 0
23
27
  });
24
- watch(() => pagination.value, () => {
25
- if (pagination.value === false) {
28
+ watch(() => pagination.value, (paginationValue) => {
29
+ if (paginationValue === false) {
26
30
  paginationInfo.value = false;
27
31
  return;
28
32
  }
29
- const itemRenderProps = isFunction(pageItemRender) ? { itemRender: ({ page, type, originalElement }) => pageItemRender ? pageItemRender({
30
- page,
31
- type,
32
- originalElement
33
- }) : null } : null;
34
- const pageInfo = {
33
+ const merged = {
35
34
  ...defaultPagination,
36
- ...pagination.value || {},
37
- ...itemRenderProps || {}
35
+ ...paginationValue || {}
38
36
  };
39
- if (!pagination.value?.showTotal) pageInfo.showTotal = (total) => `共${total < pageInfo.pageSize ? 1 : Math.ceil(total / (pageInfo.pageSize || 10))}页 ${total}条记录`;
40
- paginationInfo.value = cloneDeep(pageInfo);
41
- forInObject(requestPagination, (key) => {
42
- if (isNumber(pageInfo[key])) requestPagination[key] = pageInfo[key];
43
- });
37
+ paginationInfo.value = merged;
38
+ syncRequestPagination(merged);
44
39
  }, {
45
- deep: 1,
40
+ deep: true,
46
41
  immediate: true
47
42
  });
48
- function setPagination(state) {
43
+ function syncRequestPagination(info) {
44
+ if (isNumber(info.current)) requestPagination.current = info.current;
45
+ if (isNumber(info.pageSize)) requestPagination.pageSize = info.pageSize;
46
+ if (isNumber(info.total)) requestPagination.total = info.total;
47
+ }
48
+ function setPagination(info) {
49
49
  if (paginationInfo.value === false) return;
50
- paginationInfo.value = deepMerge(unref(paginationInfo), state);
51
- for (const key in requestPagination) if (state[key] && isNumber(state[key])) requestPagination[key] = state[key];
50
+ paginationInfo.value = merge({}, paginationInfo.value, info);
51
+ syncRequestPagination(info);
52
52
  }
53
53
  return {
54
54
  paginationInfo,
55
+ paginationAlign: computed(() => {
56
+ const paginationConfig = paginationInfo.value;
57
+ if (!paginationConfig) return "end";
58
+ const placementList = paginationConfig.placement;
59
+ if (!Array.isArray(placementList)) return "end";
60
+ const matchedPlacement = placementList.find((item) => item.includes("bottom") || item.includes("top"));
61
+ if (!matchedPlacement) return "end";
62
+ if (matchedPlacement.includes("Start")) return "start";
63
+ if (matchedPlacement.includes("Center")) return "center";
64
+ return "end";
65
+ }),
55
66
  requestPagination,
56
67
  setPagination
57
68
  };
@@ -0,0 +1,18 @@
1
+ import { ProSchemaValueEnumType } from "../interface.js";
2
+ import { Ref } from "vue";
3
+
4
+ //#region src/hooks/useRequestOptions.d.ts
5
+ interface UseRequestOptionsParams {
6
+ fetch?: () => Promise<ProSchemaValueEnumType[]>;
7
+ manual?: boolean;
8
+ debounceTime?: number;
9
+ }
10
+ interface UseRequestOptionsReturn {
11
+ optionList: Ref<ProSchemaValueEnumType[]>;
12
+ loading: Ref<boolean>;
13
+ status: Ref<'idle' | 'loading' | 'success' | 'error'>;
14
+ fetchOptions: () => Promise<ProSchemaValueEnumType[] | undefined>;
15
+ }
16
+ declare function useRequestOptions(params: UseRequestOptionsParams): UseRequestOptionsReturn;
17
+ //#endregion
18
+ export { UseRequestOptionsParams, UseRequestOptionsReturn, useRequestOptions };
@@ -0,0 +1,39 @@
1
+ import { onUnmounted, ref } from "vue";
2
+ import { useDebounceFn } from "@vueuse/core";
3
+ //#region src/hooks/useRequestOptions.ts
4
+ function useRequestOptions(params) {
5
+ const optionList = ref([]);
6
+ const loading = ref(false);
7
+ const status = ref("idle");
8
+ const debouncedFetch = useDebounceFn(async () => {
9
+ if (!params.fetch) return;
10
+ loading.value = true;
11
+ status.value = "loading";
12
+ try {
13
+ const result = await params.fetch();
14
+ optionList.value = result ?? [];
15
+ status.value = "success";
16
+ return result;
17
+ } catch (error) {
18
+ console.error("[useRequestOptions] fetch error:", error);
19
+ status.value = "error";
20
+ optionList.value = [];
21
+ return;
22
+ } finally {
23
+ loading.value = false;
24
+ }
25
+ }, params.debounceTime ?? 10);
26
+ if (params.fetch && !params.manual) debouncedFetch();
27
+ onUnmounted(() => {
28
+ optionList.value = [];
29
+ loading.value = false;
30
+ });
31
+ return {
32
+ optionList,
33
+ loading,
34
+ status,
35
+ fetchOptions: debouncedFetch
36
+ };
37
+ }
38
+ //#endregion
39
+ export { useRequestOptions };
@@ -1,19 +1,31 @@
1
- import { ProTableRowSelection } from "../types/TableTypings.js";
2
- import { Ref } from "vue";
1
+ import { ComputedRef } from "vue";
3
2
  import { RecordType } from "@gx-design-vue/pro-utils";
4
- import { SelectionSelectFn } from "ant-design-vue/es/table/interface";
5
- import { Key } from "ant-design-vue/es/vc-table/interface";
3
+ import { Key, TableRowSelection } from "antdv-next/dist/table/interface";
6
4
 
7
5
  //#region src/hooks/useRowSelection.d.ts
8
- declare function useRowSelection(rowKey: Ref<string>, rowSelection: Ref<ProTableRowSelection | undefined>): {
9
- selectedKeys: Ref<Key[], Key[]>;
10
- selectedItems: Ref<RecordType[], RecordType[]>;
11
- selectRowKey: SelectionSelectFn<RecordType>;
12
- selectAllRowKey: (selected: boolean, selectedRows: RecordType[], changeRows: RecordType[]) => void;
13
- removeRowKeys: (keys: (string | number)[]) => void;
14
- changeRowKey: () => void;
15
- syncSelectedRows: (dataList: RecordType[]) => void;
16
- clearAllRowKeys: () => void;
17
- };
6
+ interface UseRowSelectionOptions<T = RecordType> {
7
+ rowKey: ComputedRef<string>;
8
+ rowSelection: ComputedRef<TableRowSelection<T> | undefined>;
9
+ dataSource: ComputedRef<T[]>;
10
+ }
11
+ interface UseRowSelectionReturn<T = RecordType> {
12
+ selectedRowKeys: ComputedRef<Key[]>;
13
+ selectedItems: ComputedRef<T[]>;
14
+ mergedRowSelection: ComputedRef<TableRowSelection<T> | undefined>;
15
+ select: (record: T, selected: boolean) => void;
16
+ selectAll: (records: T[], selected: boolean) => void;
17
+ remove: (keys: Key[]) => void;
18
+ clear: () => void;
19
+ sync: () => void;
20
+ }
21
+ /**
22
+ * 行选择状态管理。内部使用 reactive Map 作为唯一数据源,
23
+ * selectedRowKeys / selectedItems 均从 Map 派生,保证 keys 与 items 永远同步。
24
+ *
25
+ * antdv-next 已废弃 onSelectAll / onSelectInvert / onSelectNone,
26
+ * 所有选中变化统一通过 onChange 回调,因此 mergedRowSelection 只拦截 onChange,
27
+ * 不拦截 onSelect / onSelectAll。
28
+ */
29
+ declare function useRowSelection<T = RecordType>(options: UseRowSelectionOptions<T>): UseRowSelectionReturn<T>;
18
30
  //#endregion
19
- export { useRowSelection };
31
+ export { UseRowSelectionOptions, UseRowSelectionReturn, useRowSelection };
@@ -1,86 +1,101 @@
1
- import { ref, watch } from "vue";
2
- import { arrayUnique, cloneDeep } from "@gx-design-vue/pro-utils";
1
+ import { computed, onScopeDispose, reactive, watch } from "vue";
3
2
  //#region src/hooks/useRowSelection.ts
4
- function useRowSelection(rowKey, rowSelection) {
5
- const selectedKeys = ref([]);
6
- const selectedItems = ref([]);
7
- watch(() => rowSelection.value?.selectedRows, (keys) => {
8
- selectedItems.value = cloneDeep(keys || []);
9
- }, {
10
- deep: true,
11
- immediate: true
12
- });
13
- watch(() => rowSelection.value?.selectedRowKeys, (keys) => {
14
- selectedKeys.value = arrayUnique([...keys || []]);
15
- }, {
16
- deep: true,
17
- immediate: true
18
- });
19
- const selectRowKey = (record, selected) => {
20
- const type = rowSelection.value?.type || "checkbox";
21
- if (rowKey.value) if (selected) if (record?.[rowKey.value] && type === "checkbox") {
22
- selectedKeys.value.push(record[rowKey.value]);
23
- selectedItems.value.push(record);
24
- } else {
25
- selectedKeys.value = [record[rowKey.value]];
26
- selectedItems.value = [record];
3
+ function getKey(record, rowKey) {
4
+ return record[rowKey];
5
+ }
6
+ /**
7
+ * 行选择状态管理。内部使用 reactive Map 作为唯一数据源,
8
+ * selectedRowKeys / selectedItems 均从 Map 派生,保证 keys 与 items 永远同步。
9
+ *
10
+ * antdv-next 已废弃 onSelectAll / onSelectInvert / onSelectNone,
11
+ * 所有选中变化统一通过 onChange 回调,因此 mergedRowSelection 只拦截 onChange,
12
+ * 不拦截 onSelect / onSelectAll。
13
+ */
14
+ function useRowSelection(options) {
15
+ const selectedMap = reactive(/* @__PURE__ */ new Map());
16
+ const stopWatch = watch(() => options.rowSelection.value?.selectedRowKeys, (keys) => {
17
+ if (!keys) return;
18
+ const newMap = /* @__PURE__ */ new Map();
19
+ const currentDataSource = options.dataSource.value;
20
+ for (const key of keys) {
21
+ const existing = selectedMap.get(key);
22
+ const matched = currentDataSource.find((record) => getKey(record, options.rowKey.value) === key);
23
+ newMap.set(key, matched ?? existing);
27
24
  }
28
- else {
29
- selectedKeys.value = selectedKeys.value.filter((item) => item !== record[rowKey.value]);
30
- selectedItems.value = selectedItems.value.filter((item) => item[rowKey.value] !== record[rowKey.value]);
25
+ selectedMap.clear();
26
+ for (const [key, item] of newMap) selectedMap.set(key, item);
27
+ }, { immediate: true });
28
+ onScopeDispose(() => stopWatch());
29
+ const selectedRowKeys = computed(() => Array.from(selectedMap.keys()));
30
+ const selectedItems = computed(() => Array.from(selectedMap.values()).filter((item) => item != null));
31
+ function emitChange(type) {
32
+ options.rowSelection.value?.onChange?.(selectedRowKeys.value, selectedItems.value, { type });
33
+ }
34
+ function select(record, selected) {
35
+ const key = getKey(record, options.rowKey.value);
36
+ const selectionType = options.rowSelection.value?.type ?? "checkbox";
37
+ if (selected) if (selectionType === "radio") {
38
+ selectedMap.clear();
39
+ selectedMap.set(key, record);
40
+ } else selectedMap.set(key, record);
41
+ else selectedMap.delete(key);
42
+ emitChange(selected ? selectionType === "radio" ? "single" : "multiple" : "none");
43
+ }
44
+ function selectAll(records, selected) {
45
+ if (selected) for (const record of records) selectedMap.set(getKey(record, options.rowKey.value), record);
46
+ else for (const record of records) selectedMap.delete(getKey(record, options.rowKey.value));
47
+ emitChange(selected ? "all" : "none");
48
+ }
49
+ function remove(keys) {
50
+ for (const key of keys) selectedMap.delete(key);
51
+ emitChange("none");
52
+ }
53
+ function clear() {
54
+ selectedMap.clear();
55
+ emitChange("none");
56
+ }
57
+ /** 从当前 dataSource 补全 Map 中 value 为空的条目(分页切换后调用) */
58
+ function sync() {
59
+ const currentDataSource = options.dataSource.value;
60
+ const rowKeyField = options.rowKey.value;
61
+ for (const [key, item] of selectedMap) if (item == null) {
62
+ const matched = currentDataSource.find((record) => getKey(record, rowKeyField) === key);
63
+ if (matched) selectedMap.set(key, matched);
31
64
  }
32
- };
33
- const changeRowKey = () => {
34
- if (rowSelection.value) rowSelection.value?.onChange?.(selectedKeys.value, selectedItems.value);
35
- };
36
- const selectAllRowKey = (selected, selectedRows, changeRows) => {
37
- if (rowKey.value) if (selected) selectedRows.map((item) => {
38
- if (selectedKeys.value.every((el) => el !== item?.[rowKey.value])) {
39
- if (item?.[rowKey.value]) {
40
- selectedKeys.value.push(item[rowKey.value]);
41
- selectedItems.value.push(item);
42
- }
43
- }
44
- return item;
45
- });
46
- else changeRows.map((item) => {
47
- if (selectedKeys.value.includes(item?.[rowKey.value])) {
48
- selectedKeys.value = selectedKeys.value.filter((el) => el !== item[rowKey.value]);
49
- selectedItems.value = selectedItems.value.filter((el) => el[rowKey.value] !== item[rowKey.value]);
50
- }
51
- return item;
52
- });
53
- };
54
- const removeRowKeys = (keys) => {
55
- selectedKeys.value = selectedKeys.value.filter((el) => !keys.includes(el));
56
- selectedItems.value = selectedItems.value.filter((el) => !keys.includes(el?.[rowKey.value || ""]));
57
- changeRowKey();
58
- };
59
- const syncSelectedRows = (dataList) => {
60
- if (rowKey.value) {
61
- if (selectedKeys.value.length !== selectedItems.value.length) {
62
- const itemsKeys = selectedItems.value.map((item) => item[rowKey.value]);
63
- const notIncludes = selectedKeys.value.filter((item) => !itemsKeys.includes(item));
64
- dataList.forEach((item) => {
65
- if (notIncludes.includes(item[rowKey.value])) selectedItems.value.push(cloneDeep(item));
66
- });
67
- }
65
+ }
66
+ /**
67
+ * 处理 antdv Table 的 onChange 回调。
68
+ * antd 传入的 rows 只包含当前页数据,需与已有 Map 合并以保留跨页选中项。
69
+ */
70
+ function handleAntdChange(keys, rows, info) {
71
+ const rowKeyField = options.rowKey.value;
72
+ const newMap = /* @__PURE__ */ new Map();
73
+ for (const key of keys) {
74
+ const fromRows = rows.find((record) => getKey(record, rowKeyField) === key);
75
+ const existing = selectedMap.get(key);
76
+ newMap.set(key, fromRows ?? existing);
68
77
  }
69
- };
70
- const clearAllRowKeys = () => {
71
- selectedKeys.value = [];
72
- selectedItems.value = [];
73
- changeRowKey();
74
- };
78
+ selectedMap.clear();
79
+ for (const [key, item] of newMap) selectedMap.set(key, item);
80
+ options.rowSelection.value?.onChange?.(selectedRowKeys.value, selectedItems.value, info);
81
+ }
75
82
  return {
76
- selectedKeys,
83
+ selectedRowKeys,
77
84
  selectedItems,
78
- selectRowKey,
79
- selectAllRowKey,
80
- removeRowKeys,
81
- changeRowKey,
82
- syncSelectedRows,
83
- clearAllRowKeys
85
+ mergedRowSelection: computed(() => {
86
+ const rowSelectionConfig = options.rowSelection.value;
87
+ if (!rowSelectionConfig) return void 0;
88
+ return {
89
+ ...rowSelectionConfig,
90
+ selectedRowKeys: selectedRowKeys.value,
91
+ onChange: handleAntdChange
92
+ };
93
+ }),
94
+ select,
95
+ selectAll,
96
+ remove,
97
+ clear,
98
+ sync
84
99
  };
85
100
  }
86
101
  //#endregion
@@ -1,90 +1,32 @@
1
- import { ProColumnType, ProColumnsType, ProSearchMap } from "../types/ColumnTypings.js";
2
- import { ProCoreActionType, ProCoreFormType, ProTableProps, ProTableRef, ProTableRowSelection, RequestConfig, RequestFunction } from "../types/TableTypings.js";
3
- import { BaseTableProps } from "../props.js";
1
+ import { PageState, ProCoreActionType, ProTablePaginationConfig, ProTableProps, ProTableRef, RequestFunction, RowSelectionActions } from "../interface.js";
4
2
  import { ComputedRef, MaybeRef, Reactive, Ref } from "vue";
5
- import { RecordType } from "@gx-design-vue/pro-utils";
3
+ import { FilterValue, SorterResult, TableCurrentDataSource } from "antdv-next/dist/table/interface";
6
4
 
7
5
  //#region src/hooks/useTable.d.ts
8
- type ProTableState<T extends object = RecordType, R extends object = RecordType> = Omit<BaseTableProps, 'columns' | 'params' | 'dataSource' | 'rowSelection' | 'searchMap' | 'rowKey' | 'postData' | 'onReset' | 'onReload' | 'onSubmit' | 'onExpand' | 'title' | 'footer' | 'rowExpandable' | 'transformCellText' | 'expandIcon' | 'rowClassName' | 'customRow' | 'customHeaderRow' | 'expandedRowRender' | 'onBeforeSearchSubmit'> & {
9
- params: R;
10
- columns: ProColumnsType<T, R>;
11
- dataSource: T[];
12
- rowSelection: ProTableRowSelection<T>;
13
- searchMap: ProSearchMap<undefined, keyof R | keyof T>[];
14
- rowKey?: keyof T;
15
- title?: (data: T[]) => any;
16
- footer?: (data: T[]) => any;
17
- postData?: (data: T[]) => any;
18
- rowExpandable?: (record: T) => boolean;
19
- transformCellText?: (opt: {
20
- text: any;
21
- column: ProColumnType<T, R>;
22
- record: any;
23
- index: number;
24
- }) => any;
25
- expandIcon?: (props: {
26
- prefixCls: string;
27
- expanded: boolean;
28
- record: T;
29
- expandable: boolean;
30
- onExpand: (record: T, event: MouseEvent) => void;
31
- }) => any;
32
- customRow?: (data: T, index?: number, column?: ProColumnType<T, R>) => any;
33
- customHeaderRow?: (data: T, index?: number, column?: ProColumnType<T, R>) => any;
34
- expandedRowRender: (opt: {
35
- record: T;
36
- index: number;
37
- indent: number;
38
- expanded: boolean;
39
- }) => any;
40
- rowClassName?: string | ((record: T, index: number, indent: number) => string);
41
- onReset?: (params?: Partial<R>) => void;
42
- onReload?: (params?: Partial<R>) => void;
43
- onSubmit?: (params?: Partial<R>) => void;
44
- onExpand?: (expanded: boolean, record: T) => void;
45
- onResizeColumn?: (w: number, col: ProColumnType<T, R>) => void;
46
- onBeforeSearchSubmit?: RequestFunction<T, R>;
47
- };
48
- type BaseTableState<T extends object = RecordType, R extends object = RecordType> = Omit<ProTableProps<T, R>, 'request'>;
49
- interface UseTableReturn<T extends object = RecordType, R extends object = RecordType> {
50
- /** @name loading 状态,可以直接进行修改 */
6
+ interface UseTableOptions<T = any, R = any> {
7
+ state?: MaybeRef<Partial<ProTableProps<T, R>>> | Reactive<Partial<ProTableProps<T, R>>>;
8
+ request?: RequestFunction<T, R>;
9
+ }
10
+ interface UseTableReturn<T = any, R = any> {
51
11
  loading: Ref<boolean>;
52
- /** @name 只读表格数据,不能修改 */
53
12
  dataSource: ComputedRef<T[]>;
54
- /** @name 表格列选择keys,只读 */
55
- selectedKeys: ProCoreActionType<T, R>['selectedKeys'];
56
- /** @name 表格列选择rows,只读 */
57
- selectedItems: ProCoreActionType<T, R>['selectedItems'];
58
- /** @name 表格列选项操作 */
59
- rowsSelection: ProCoreActionType<T, R>['rowsSelection'];
60
- /** @name 表格请求参数 */
61
- requestSearch: ComputedRef<RequestConfig<R>['params']>;
62
- /** @name 主动刷新,按照当前的参数在当前页重新请求下 */
13
+ requestSearch: ComputedRef<Partial<R> & Partial<PageState>>;
14
+ selectedKeys: ComputedRef<(string | number)[]>;
15
+ selectedItems: ComputedRef<T[]>;
16
+ rowsSelection: RowSelectionActions<T>;
63
17
  reload: ProCoreActionType<T, R>['reload'];
64
- /** @name 更新表格数据,直接替换,谨慎操作 */
65
18
  setTableDataList: ProCoreActionType<T, R>['setTableDataList'];
66
- /** @name 更新TableData属性值 */
67
19
  operateTableDataRow: ProCoreActionType<T, R>['operateTableDataRow'];
68
- /** @name 设置翻页、排序、筛选、并且刷新(reload) */
69
- setPageInfo: ProCoreActionType<T, R>['setPageInfo'];
70
- /** @name 设置翻页 */
20
+ setPageInfo: (pagination: ProTablePaginationConfig, filters?: Record<string, FilterValue | null>, sorter?: SorterResult | SorterResult[], extra?: TableCurrentDataSource) => void;
71
21
  setPagination: ProCoreActionType<T, R>['setPagination'];
72
- /** @name 刷新并清空表单,重置为第一页 */
73
22
  reloadAndReset: ProCoreActionType<T, R>['reloadAndReset'];
74
- /** @name 改变loading状态 */
75
23
  setLoading: ProCoreActionType<T, R>['setLoading'];
76
- /** @name action表格实例 */
77
- actionRef: ComputedRef<ProCoreActionType<T, R>>;
78
- /** @name form查询表单实例 */
79
- formRef: ComputedRef<ProCoreFormType<R>>;
80
- /** @name 表格参数,用于传递给ProTable组件使用,可以对其进行修改 */
81
- tableState: Reactive<ProTableState<T, R>>;
82
- /** @name 更新表格参数 SearchMap,key为SearchMap唯一字段,value是更新的参数,会merge */
83
- updateSearchMap: (key: keyof R | keyof T, value: Partial<ProSearchMap<any>>) => void;
24
+ tableState: Reactive<Partial<ProTableProps<T, R>>>;
84
25
  }
85
- declare function useTable<T extends object = RecordType, R extends object = RecordType>(tableRef: Ref<ProTableRef<T> | undefined>, options?: {
86
- state?: MaybeRef<BaseTableState<T, R>> | Reactive<BaseTableState<T, R>> | ComputedRef<BaseTableState<T, R>>;
87
- request?: RequestFunction<T, R>;
88
- }): UseTableReturn<T, R>;
26
+ /**
27
+ * 外部命令式 hook,通过 template ref 访问 ProTable 暴露的 actionRef。
28
+ * loading 单向同步(actionRef → 外部 state),避免双向 watch 循环。
29
+ */
30
+ declare function useTable<T = any, R = any>(tableRef: Ref<ProTableRef<T, R> | undefined>, options?: UseTableOptions<T, R>): UseTableReturn<T, R>;
89
31
  //#endregion
90
- export { BaseTableState, ProTableState, UseTableReturn, useTable };
32
+ export { UseTableOptions, UseTableReturn, useTable };
@@ -1,70 +1,82 @@
1
- import { computed, isRef, reactive, ref, watch } from "vue";
2
- import { cloneDeep, deepMerge, isObject, useDeepMerge } from "@gx-design-vue/pro-utils";
1
+ import { computed, reactive, ref, toValue, watch } from "vue";
2
+ import { merge } from "@gx-design-vue/pro-utils";
3
3
  //#region src/hooks/useTable.ts
4
+ const EMPTY_ARRAY = [];
5
+ /**
6
+ * 外部命令式 hook,通过 template ref 访问 ProTable 暴露的 actionRef。
7
+ * loading 单向同步(actionRef → 外部 state),避免双向 watch 循环。
8
+ */
4
9
  function useTable(tableRef, options) {
5
- function getTableState() {
6
- const defaultState = {
7
- params: {},
8
- searchMap: []
9
- };
10
- if (options?.state) {
11
- if (isRef(options.state) && isObject(options.state.value)) return deepMerge(defaultState, cloneDeep(options.state.value));
12
- else if (isObject(options.state) && !isRef(options.state)) return deepMerge(defaultState, cloneDeep(options.state));
10
+ const tableState = reactive({});
11
+ const syncedStateKeys = /* @__PURE__ */ new Set();
12
+ function syncTableState(state = {}) {
13
+ const nextState = merge({}, state);
14
+ for (const key of syncedStateKeys) if (!(key in nextState)) {
15
+ delete tableState[key];
16
+ syncedStateKeys.delete(key);
13
17
  }
14
- return defaultState;
18
+ Object.assign(tableState, nextState);
19
+ for (const key of Object.keys(nextState)) syncedStateKeys.add(key);
20
+ if (options?.request) tableState.request = options.request;
15
21
  }
16
- const tableState = reactive(deepMerge(getTableState(), { request: options?.request }));
17
- if (options?.state) watch(() => options.state && isRef(options.state) ? options.state.value : options.state, () => {
18
- updateTableState();
19
- }, { deep: true });
20
- const actionRef = computed(() => {
21
- if (tableRef.value) return tableRef.value.actionRef();
22
- return {};
23
- });
24
- const formRef = computed(() => {
25
- if (tableRef.value?.formRef) return tableRef.value.formRef();
26
- return {};
22
+ watch(() => toValue(options?.state), (newState) => {
23
+ syncTableState(newState ?? {});
24
+ }, {
25
+ deep: true,
26
+ immediate: true
27
27
  });
28
- const requestSearch = computed(() => {
29
- return {
30
- ...actionRef.value?.pageInfo || {},
31
- ...formRef.value?.getFormSearch?.() || {}
32
- };
28
+ const actionRef = computed(() => {
29
+ return tableRef.value?.actionRef?.() ?? {};
33
30
  });
34
- const loading = ref(!!actionRef.value?.loading?.value);
31
+ const requestSearch = computed(() => ({ ...actionRef.value?.pageInfo || {} }));
32
+ const loading = ref(false);
35
33
  watch(() => actionRef.value?.loading?.value, (val) => {
36
34
  loading.value = !!val;
37
35
  });
38
- watch(loading, (val) => {
39
- actionRef.value?.setLoading?.(!!val);
40
- });
41
- function updateTableState() {
42
- useDeepMerge(tableState, getTableState());
36
+ function reload(info) {
37
+ actionRef.value?.reload?.(info);
38
+ }
39
+ function setTableDataList(data) {
40
+ actionRef.value?.setTableDataList?.(data);
41
+ }
42
+ function operateTableDataRow(props) {
43
+ actionRef.value?.operateTableDataRow?.(props);
43
44
  }
44
- function updateSearchMap(key, value) {
45
- if (tableState.searchMap) tableState.searchMap = cloneDeep(tableState.searchMap).map((item) => {
46
- if (item.name === key) return deepMerge(item, value);
47
- return item;
48
- });
45
+ function setPageInfo(pagination, filters, sorter, extra) {
46
+ actionRef.value?.setPageInfo?.(pagination, filters, sorter, extra);
49
47
  }
48
+ function setPagination(pagination) {
49
+ actionRef.value?.setPagination?.(pagination);
50
+ }
51
+ function reloadAndReset(options) {
52
+ actionRef.value?.reloadAndReset?.(options);
53
+ }
54
+ function setLoading(value) {
55
+ loading.value = value;
56
+ }
57
+ const selectedKeys = computed(() => actionRef.value?.selectedKeys?.value ?? []);
58
+ const selectedItems = computed(() => actionRef.value?.selectedItems?.value ?? []);
50
59
  return {
51
- formRef,
52
- actionRef,
53
- tableState,
54
- requestSearch,
55
60
  loading,
56
- dataSource: computed(() => actionRef?.value?.dataSource?.value || []),
57
- selectedKeys: computed(() => actionRef?.value?.selectedKeys?.value || []),
58
- selectedItems: computed(() => actionRef?.value?.selectedItems?.value || []),
59
- rowsSelection: actionRef?.value?.rowsSelection,
60
- setTableDataList: (data) => actionRef.value?.setTableDataList?.(data),
61
- reloadAndReset: (options) => actionRef.value?.reloadAndReset?.(options),
62
- setPageInfo: (pagination, filters, sorter, extra) => actionRef.value?.setPageInfo?.(pagination, filters, sorter, extra),
63
- setPagination: (pageInfo) => actionRef.value?.setPagination?.(pageInfo),
64
- setLoading: (value) => loading.value = value,
65
- operateTableDataRow: (params) => actionRef.value?.operateTableDataRow?.(params),
66
- reload: (info) => actionRef.value?.reload?.(info),
67
- updateSearchMap
61
+ dataSource: computed(() => actionRef.value?.dataSource?.value ?? EMPTY_ARRAY),
62
+ requestSearch,
63
+ selectedKeys,
64
+ selectedItems,
65
+ rowsSelection: {
66
+ clear: () => actionRef.value?.rowsSelection?.clear?.(),
67
+ select: (record, selected) => actionRef.value?.rowsSelection?.select?.(record, selected),
68
+ selectAll: (records, selected) => actionRef.value?.rowsSelection?.selectAll?.(records, selected),
69
+ remove: (keys) => actionRef.value?.rowsSelection?.remove?.(keys),
70
+ sync: () => actionRef.value?.rowsSelection?.sync?.()
71
+ },
72
+ reload,
73
+ setTableDataList,
74
+ operateTableDataRow,
75
+ setPageInfo,
76
+ setPagination,
77
+ reloadAndReset,
78
+ setLoading,
79
+ tableState
68
80
  };
69
81
  }
70
82
  //#endregion