@gx-design-vue/pro-table 0.2.0-alpha.0 → 0.2.0-alpha.10
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/ProTable.d.ts +14 -493
- package/dist/ProTable.js +818 -512
- package/dist/components/ScrollBar/Bar.d.ts +81 -0
- package/dist/components/ScrollBar/Bar.js +84 -0
- package/dist/components/ScrollBar/Thumb.d.ts +52 -0
- package/dist/components/ScrollBar/{Thumb/index.js → Thumb.js} +67 -58
- package/dist/components/ScrollBar/context.d.ts +3 -4
- package/dist/components/ScrollBar/context.js +3 -5
- package/dist/components/ScrollBar/util.d.ts +6 -5
- package/dist/components/ScrollBar/util.js +1 -14
- package/dist/components/SearchForm/CollapseToggle.d.ts +55 -0
- package/dist/components/SearchForm/CollapseToggle.js +47 -0
- package/dist/components/SearchForm/FormItemContainer.d.ts +75 -0
- package/dist/components/SearchForm/FormItemContainer.js +225 -0
- package/dist/components/SearchForm/FormItemWrapper.d.ts +82 -0
- package/dist/components/SearchForm/FormItemWrapper.js +62 -0
- package/dist/components/SearchForm/SearchForm.d.ts +130 -0
- package/dist/components/SearchForm/SearchForm.js +319 -0
- package/dist/components/SearchForm/index.d.ts +2 -0
- package/dist/components/SearchForm/index.js +2 -0
- package/dist/components/Toolbar/FullscreenIcon.d.ts +26 -0
- package/dist/components/Toolbar/FullscreenIcon.js +22 -0
- package/dist/components/Toolbar/ListToolBar.d.ts +111 -0
- package/dist/components/Toolbar/ListToolBar.js +101 -0
- package/dist/components/Toolbar/index.d.ts +103 -0
- package/dist/components/Toolbar/index.js +101 -0
- package/dist/components/Toolbar/style.d.ts +8 -0
- package/dist/components/{ListToolBar → Toolbar}/style.js +32 -27
- package/dist/context/TableContext.d.ts +15 -27
- package/dist/context/TableContext.js +3 -5
- package/dist/hooks/index.d.ts +16 -0
- package/dist/hooks/index.js +16 -0
- package/dist/hooks/useBreakpoints.d.ts +13 -0
- package/dist/hooks/useBreakpoints.js +57 -0
- package/dist/hooks/useCellRender.d.ts +13 -0
- package/dist/hooks/useCellRender.js +28 -0
- package/dist/hooks/useColumnResize.d.ts +30 -0
- package/dist/hooks/useColumnResize.js +110 -0
- package/dist/hooks/useColumns.d.ts +35 -24
- package/dist/hooks/useColumns.js +89 -58
- package/dist/hooks/useFetchData.d.ts +40 -65
- package/dist/hooks/useFetchData.js +157 -174
- package/dist/hooks/useFitPage.d.ts +19 -0
- package/dist/hooks/useFitPage.js +90 -0
- package/dist/hooks/useKeepAliveReload.d.ts +21 -0
- package/dist/hooks/useKeepAliveReload.js +24 -0
- package/dist/hooks/useLoading.d.ts +18 -7
- package/dist/hooks/useLoading.js +27 -11
- package/dist/hooks/usePagination.d.ts +10 -7
- package/dist/hooks/usePagination.js +38 -29
- package/dist/hooks/useRequestOptions.d.ts +18 -0
- package/dist/hooks/useRequestOptions.js +39 -0
- package/dist/hooks/useRowSelection.d.ts +27 -15
- package/dist/hooks/useRowSelection.js +93 -80
- package/dist/hooks/useTable.d.ts +35 -77
- package/dist/hooks/useTable.js +72 -50
- package/dist/hooks/useTableForm.d.ts +15 -82
- package/dist/hooks/useTableForm.js +93 -55
- package/dist/hooks/useTableScroll.d.ts +33 -31
- package/dist/hooks/useTableScroll.js +71 -28
- package/dist/hooks/useTableSize.d.ts +17 -7
- package/dist/hooks/useTableSize.js +21 -9
- package/dist/index.d.ts +10 -7
- package/dist/index.js +9 -4
- package/dist/interface.d.ts +499 -0
- package/dist/interface.js +1 -0
- package/dist/pro-table.esm.js +3579 -3834
- package/dist/pro-table.js +1 -1
- package/dist/style/fit-page.d.ts +4 -2
- package/dist/style/fit-page.js +10 -5
- package/dist/style/index.d.ts +4 -6
- package/dist/style/index.js +24 -76
- package/dist/style/list.d.ts +4 -2
- package/dist/style/list.js +2 -12
- package/dist/style/resizable.d.ts +8 -0
- package/dist/style/resizable.js +18 -0
- package/dist/style/scroll.d.ts +4 -2
- package/dist/style/scroll.js +9 -9
- package/dist/style/search.d.ts +8 -0
- package/dist/{components/Form/style.js → style/search.js} +22 -9
- package/dist/theme/augment.d.ts +8 -0
- package/dist/theme/augment.js +1 -0
- package/dist/theme/interface/components.d.ts +8 -0
- package/dist/theme/interface/components.js +1 -0
- package/dist/utils/dateFormat.d.ts +9 -0
- package/dist/utils/dateFormat.js +29 -0
- package/dist/utils/formConstants.d.ts +9 -0
- package/dist/utils/formConstants.js +29 -0
- package/dist/utils/valueFormat.d.ts +9 -0
- package/dist/utils/valueFormat.js +27 -0
- package/package.json +11 -10
- package/dist/components/Form/components/RequestSelect.d.ts +0 -50
- package/dist/components/Form/components/RequestSelect.js +0 -58
- package/dist/components/Form/hooks/useForm.d.ts +0 -11
- package/dist/components/Form/hooks/useForm.js +0 -32
- package/dist/components/Form/index.d.ts +0 -33
- package/dist/components/Form/index.js +0 -479
- package/dist/components/Form/style.d.ts +0 -6
- package/dist/components/Form/utils/config.d.ts +0 -9
- package/dist/components/Form/utils/config.js +0 -30
- package/dist/components/Form/utils/dateFormat.d.ts +0 -22
- package/dist/components/Form/utils/dateFormat.js +0 -45
- package/dist/components/ListToolBar/index.d.ts +0 -60
- package/dist/components/ListToolBar/index.js +0 -123
- package/dist/components/ListToolBar/style.d.ts +0 -6
- package/dist/components/ScrollBar/Bar/index.d.ts +0 -49
- package/dist/components/ScrollBar/Bar/index.js +0 -71
- package/dist/components/ScrollBar/Bar/props.d.ts +0 -25
- package/dist/components/ScrollBar/Bar/props.js +0 -18
- package/dist/components/ScrollBar/Thumb/index.d.ts +0 -40
- package/dist/components/ScrollBar/Thumb/props.d.ts +0 -20
- package/dist/components/ScrollBar/Thumb/props.js +0 -18
- package/dist/components/TableCell/index.d.ts +0 -37
- package/dist/components/TableCell/index.js +0 -72
- package/dist/components/ToolBar/FullscreenIcon.d.ts +0 -7
- package/dist/components/ToolBar/FullscreenIcon.js +0 -14
- package/dist/components/ToolBar/index.d.ts +0 -34
- package/dist/components/ToolBar/index.js +0 -100
- package/dist/hooks/tryOnActivated.d.ts +0 -6
- package/dist/hooks/tryOnActivated.js +0 -14
- package/dist/hooks/useDebounceFn.d.ts +0 -8
- package/dist/hooks/useDebounceFn.js +0 -34
- package/dist/hooks/useScrollArea.d.ts +0 -24
- package/dist/hooks/useScrollArea.js +0 -104
- package/dist/props.d.ts +0 -340
- package/dist/props.js +0 -251
- package/dist/types/ColumnTypings.d.ts +0 -127
- package/dist/types/ColumnTypings.js +0 -1
- package/dist/types/SlotsTypings.d.ts +0 -63
- package/dist/types/SlotsTypings.js +0 -13
- package/dist/types/TableTypings.d.ts +0 -359
- package/dist/types/TableTypings.js +0 -1
- package/dist/types/index.d.ts +0 -9
- package/dist/types/index.js +0 -1
- package/dist/utils/utils.d.ts +0 -10
- package/dist/utils/utils.js +0 -91
|
@@ -1,50 +1,78 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { omit } from "es-toolkit";
|
|
5
|
-
|
|
1
|
+
import { computed, onActivated, onDeactivated, onUnmounted, ref, toRaw, watch } from "vue";
|
|
2
|
+
import { getRandomNumber, getSortIndex, handleCurrentPage, isArray, isFunction, isObject, merge } from "@gx-design-vue/pro-utils";
|
|
3
|
+
import { useDebounceFn } from "@vueuse/core";
|
|
6
4
|
//#region src/hooks/useFetchData.ts
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
autoRequest
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
function useFetchData({ rowKey, autoRequest, polling, request, postData, dataSource, waitRequest, debounceTime }, { params, columns, setLoading, setColumns, removeRowKeys, syncSelectedRows, defaultFormSearch, setPagination, pageInfo, paginationInfo, onRequestError, onBeforeSearchSubmit, hasCustomRender }, emit) {
|
|
24
|
-
const updateKey = ref("");
|
|
25
|
-
const umountRef = ref(false);
|
|
26
|
-
const pollingLoading = ref(false);
|
|
5
|
+
const EMPTY_ARRAY = [];
|
|
6
|
+
/**
|
|
7
|
+
* 核心请求引擎。
|
|
8
|
+
* 负责数据请求调度、分页状态、轮询、AbortController 中断、
|
|
9
|
+
* loading 管理、数据转换、行操作、排序/筛选变更。
|
|
10
|
+
*
|
|
11
|
+
* 调度模型:所有请求入口(run/reload/handleTableChange/params 变化等)
|
|
12
|
+
* 统一进入 dispatchFetch → debouncedFetch → fetchList。
|
|
13
|
+
* 通过 requestId + AbortController 双重保证旧响应不回写。
|
|
14
|
+
*/
|
|
15
|
+
function useFetchData(config, action) {
|
|
16
|
+
const { rowKey, polling, pollingTime, request, postData, dataSource, immediate, waitRequest, autoRequest, debounceTime, params, defaultFormSearch, onLoadingChange, onRequestError, onBeforeSearchSubmit } = config;
|
|
17
|
+
const { pageInfo, paginationInfo, setPagination, setLoading, setColumns, removeRowKeys, syncSelectedRows, columns } = action;
|
|
27
18
|
const tableDataList = ref([]);
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
19
|
+
const unmounted = ref(false);
|
|
20
|
+
const pollingTimer = ref(null);
|
|
21
|
+
const abortController = ref(null);
|
|
22
|
+
const requestId = ref("");
|
|
23
|
+
/** 通知外部 loading 状态变化(通过 onLoadingChange 回调) */
|
|
24
|
+
function notifyLoading(loadingState) {
|
|
25
|
+
if (onLoadingChange) onLoadingChange(loadingState);
|
|
26
|
+
}
|
|
27
|
+
function clearPollingTimer() {
|
|
28
|
+
if (pollingTimer.value != null) {
|
|
29
|
+
clearTimeout(pollingTimer.value);
|
|
30
|
+
pollingTimer.value = null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function stopPolling() {
|
|
34
|
+
clearPollingTimer();
|
|
35
|
+
}
|
|
36
|
+
function schedulePolling(fetchParams) {
|
|
37
|
+
if (unmounted.value || !polling.value) return;
|
|
38
|
+
const interval = Math.max(pollingTime.value || 2e3, 2e3);
|
|
39
|
+
clearPollingTimer();
|
|
40
|
+
pollingTimer.value = setTimeout(() => {
|
|
41
|
+
dispatchFetch({
|
|
42
|
+
...fetchParams,
|
|
43
|
+
isPolling: true
|
|
44
|
+
});
|
|
45
|
+
}, interval);
|
|
46
|
+
}
|
|
47
|
+
function abortCurrent() {
|
|
48
|
+
abortController.value?.abort();
|
|
49
|
+
abortController.value = null;
|
|
50
|
+
}
|
|
51
|
+
/** 写入表格数据并同步 sortIndex,无 request 时同步 dataSource total */
|
|
52
|
+
function setTableDataList(list) {
|
|
53
|
+
tableDataList.value = getSortIndex(list, toRaw(pageInfo));
|
|
54
|
+
if (!request || !isFunction(request)) {
|
|
55
|
+
const total = list.length || 0;
|
|
56
|
+
if (total !== pageInfo.total) setPagination({ total });
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** 执行单次请求,处理参数合并、AbortController、轮询调度、错误处理 */
|
|
60
|
+
async function fetchList(fetchParams = {}) {
|
|
61
|
+
const { pagination: fetchPagination = {}, filters = {}, sorter = {}, removeKeys = [], isPolling = false, extra } = fetchParams;
|
|
36
62
|
if (!request || !isFunction(request)) return dataSource.value || [];
|
|
37
|
-
if (!isPolling)
|
|
38
|
-
|
|
39
|
-
|
|
63
|
+
if (!isPolling) {
|
|
64
|
+
setLoading(true);
|
|
65
|
+
notifyLoading(true);
|
|
66
|
+
}
|
|
67
|
+
if (fetchPagination && Object.keys(fetchPagination).length) setPagination(fetchPagination);
|
|
40
68
|
try {
|
|
41
69
|
if (removeKeys.length) removeRowKeys(removeKeys);
|
|
42
|
-
const sorterList = isObject(sorter)
|
|
43
|
-
setColumns(
|
|
44
|
-
const
|
|
70
|
+
const sorterList = isObject(sorter) && Object.keys(sorter).length ? [sorter] : isArray(sorter) ? sorter : [];
|
|
71
|
+
if (setColumns && columns) setColumns(columns.value.map((columnItem) => {
|
|
72
|
+
const matchedSorter = sorterList.find((sorterItem) => (sorterItem?.columnKey || sorterItem?.field) === columnItem.dataIndex);
|
|
45
73
|
return {
|
|
46
|
-
...
|
|
47
|
-
sortOrder:
|
|
74
|
+
...columnItem,
|
|
75
|
+
sortOrder: matchedSorter?.order
|
|
48
76
|
};
|
|
49
77
|
}));
|
|
50
78
|
let actionParams = {
|
|
@@ -52,9 +80,9 @@ function useFetchData({ rowKey, autoRequest, polling, request, postData, dataSou
|
|
|
52
80
|
pageSize: pageInfo.pageSize,
|
|
53
81
|
current: handleCurrentPage(toRaw(pageInfo), removeKeys.length)
|
|
54
82
|
},
|
|
55
|
-
...
|
|
56
|
-
...
|
|
57
|
-
...
|
|
83
|
+
...toRaw(defaultFormSearch.value),
|
|
84
|
+
...toRaw(params.value),
|
|
85
|
+
...fetchParams.params || {}
|
|
58
86
|
};
|
|
59
87
|
if (onBeforeSearchSubmit && isFunction(onBeforeSearchSubmit)) actionParams = await onBeforeSearchSubmit({
|
|
60
88
|
params: actionParams,
|
|
@@ -62,98 +90,66 @@ function useFetchData({ rowKey, autoRequest, polling, request, postData, dataSou
|
|
|
62
90
|
filter: filters,
|
|
63
91
|
extra
|
|
64
92
|
});
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
93
|
+
const currentRequestId = `table_request_${getRandomNumber().uuid(10)}`;
|
|
94
|
+
requestId.value = currentRequestId;
|
|
95
|
+
const controller = new AbortController();
|
|
96
|
+
abortController.value = controller;
|
|
97
|
+
const response = await request({
|
|
98
|
+
params: { ...actionParams },
|
|
70
99
|
sorter: sorterList,
|
|
71
100
|
filter: filters,
|
|
72
|
-
extra
|
|
101
|
+
extra,
|
|
102
|
+
signal: controller.signal
|
|
73
103
|
});
|
|
74
|
-
if (
|
|
104
|
+
if (requestId.value !== currentRequestId || controller.signal.aborted) return [];
|
|
75
105
|
if (response) {
|
|
76
106
|
const { success = true, data = [] } = response;
|
|
77
107
|
if (!success) return [];
|
|
78
|
-
responseData = typeof postData === "function" ?
|
|
79
|
-
|
|
80
|
-
const total = response.total || responseData?.length || 0;
|
|
108
|
+
const responseData = typeof postData === "function" ? postData(data) : data;
|
|
109
|
+
const total = response.total || responseData.length || 0;
|
|
81
110
|
if (total !== pageInfo.total) setPagination({ total });
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
} else return [];
|
|
111
|
+
setTableDataList(responseData);
|
|
112
|
+
syncSelectedRows(responseData);
|
|
113
|
+
schedulePolling(fetchParams);
|
|
114
|
+
return responseData;
|
|
115
|
+
}
|
|
116
|
+
return [];
|
|
89
117
|
} catch (e) {
|
|
90
|
-
if (
|
|
91
|
-
if (
|
|
92
|
-
|
|
118
|
+
if (e.name === "AbortError") return [];
|
|
119
|
+
if (onRequestError) {
|
|
120
|
+
if (tableDataList.value === void 0) setTableDataList([]);
|
|
121
|
+
onRequestError(e);
|
|
122
|
+
return [];
|
|
123
|
+
}
|
|
124
|
+
throw e;
|
|
93
125
|
} finally {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
const fetchListDebounce = useDebounceFn_default(async (props = {}) => {
|
|
99
|
-
if (pollingSetTimeRef.value) clearTimeout(pollingSetTimeRef.value);
|
|
100
|
-
if (!request) return;
|
|
101
|
-
const abort = new AbortController();
|
|
102
|
-
abortRef.value = abort;
|
|
103
|
-
try {
|
|
104
|
-
const msg = await Promise.race([fetchList(props), new Promise((_, reject) => {
|
|
105
|
-
abortRef.value?.signal?.addEventListener?.("abort", () => {
|
|
106
|
-
reject("aborted");
|
|
107
|
-
fetchListDebounce.cancel();
|
|
108
|
-
requestFinally();
|
|
109
|
-
});
|
|
110
|
-
})]);
|
|
111
|
-
if (abort.signal.aborted) return;
|
|
112
|
-
const needPolling = runFunction(polling.value, msg);
|
|
113
|
-
if (needPolling && !umountRef.value) pollingSetTimeRef.value = setTimeout(() => {
|
|
114
|
-
fetchListDebounce.run({
|
|
115
|
-
...props,
|
|
116
|
-
isPolling: needPolling
|
|
117
|
-
});
|
|
118
|
-
}, Math.max(needPolling, 2e3));
|
|
119
|
-
return msg;
|
|
120
|
-
} catch (error) {
|
|
121
|
-
if (error === "aborted") return;
|
|
122
|
-
throw error;
|
|
126
|
+
if (!isPolling) {
|
|
127
|
+
setLoading(false);
|
|
128
|
+
notifyLoading(false);
|
|
129
|
+
}
|
|
123
130
|
}
|
|
124
|
-
}
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
umountRef.value = false;
|
|
132
|
-
});
|
|
131
|
+
}
|
|
132
|
+
const debouncedFetch = useDebounceFn((fetchParams) => fetchList(fetchParams), () => debounceTime.value ?? 10);
|
|
133
|
+
/** 统一请求调度入口:先 abort 上一个请求,再 debounce 执行 */
|
|
134
|
+
function dispatchFetch(fetchParams = {}) {
|
|
135
|
+
abortCurrent();
|
|
136
|
+
debouncedFetch(fetchParams);
|
|
137
|
+
}
|
|
133
138
|
onActivated(() => {
|
|
134
|
-
|
|
139
|
+
unmounted.value = false;
|
|
135
140
|
});
|
|
136
141
|
onUnmounted(() => {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
142
|
+
unmounted.value = true;
|
|
143
|
+
abortCurrent();
|
|
144
|
+
stopPolling();
|
|
140
145
|
});
|
|
141
146
|
onDeactivated(() => {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
147
|
+
unmounted.value = true;
|
|
148
|
+
abortCurrent();
|
|
149
|
+
stopPolling();
|
|
145
150
|
});
|
|
146
|
-
watch(() =>
|
|
147
|
-
if (
|
|
148
|
-
if (!polling.value) clearTimeout(pollingSetTimeRef.value);
|
|
149
|
-
else fetchListDebounce.run({ isPolling: true });
|
|
150
|
-
}, { immediate: true });
|
|
151
|
-
watch(() => waitRequest.value, () => {
|
|
152
|
-
if (waitRequest.value) setLoading(true);
|
|
153
|
-
else fetchListDebounce.run({ isPolling: false });
|
|
154
|
-
}, { immediate: true });
|
|
155
|
-
watch(() => dataSource.value, () => {
|
|
156
|
-
if (dataSource.value) setTableDataList(dataSource.value || []);
|
|
151
|
+
watch(() => dataSource.value, (source) => {
|
|
152
|
+
if (source && !isFunction(request)) setTableDataList(source);
|
|
157
153
|
}, {
|
|
158
154
|
deep: true,
|
|
159
155
|
immediate: true
|
|
@@ -162,59 +158,40 @@ function useFetchData({ rowKey, autoRequest, polling, request, postData, dataSou
|
|
|
162
158
|
if (waitRequest.value) return;
|
|
163
159
|
if (autoRequest.value) {
|
|
164
160
|
setPagination({ current: 1 });
|
|
165
|
-
|
|
161
|
+
dispatchFetch({ isPolling: false });
|
|
166
162
|
}
|
|
167
|
-
}, {
|
|
168
|
-
|
|
169
|
-
immediate: true
|
|
170
|
-
});
|
|
171
|
-
watch(() => defaultFormSearch.value, (val, old) => {
|
|
163
|
+
}, { deep: true });
|
|
164
|
+
watch(() => defaultFormSearch.value, (current, previous) => {
|
|
172
165
|
if (waitRequest.value) return;
|
|
173
|
-
if (
|
|
166
|
+
if (current !== previous) {
|
|
174
167
|
setPagination({ current: 1 });
|
|
175
|
-
|
|
168
|
+
dispatchFetch({ isPolling: false });
|
|
176
169
|
}
|
|
177
|
-
}, {
|
|
178
|
-
|
|
179
|
-
|
|
170
|
+
}, { deep: true });
|
|
171
|
+
watch(() => polling.value, () => {
|
|
172
|
+
if (waitRequest.value) return;
|
|
173
|
+
if (!polling.value) stopPolling();
|
|
174
|
+
else dispatchFetch({ isPolling: true });
|
|
180
175
|
});
|
|
181
|
-
|
|
182
|
-
if (
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
}
|
|
187
|
-
} else setTableDataList(dataSource.value || []);
|
|
188
|
-
}
|
|
189
|
-
const getDataSourceRef = computed(() => {
|
|
190
|
-
if (hasCustomRender.value) return unref(tableDataList);
|
|
191
|
-
const viewColumns = columns.value.filter((column) => column.show || column.show === void 0);
|
|
192
|
-
if (!unref(tableDataList) || !viewColumns || viewColumns.length === 0) return [];
|
|
193
|
-
return unref(tableDataList);
|
|
176
|
+
watch(() => waitRequest.value, (waiting) => {
|
|
177
|
+
if (waiting) {
|
|
178
|
+
setLoading(true);
|
|
179
|
+
notifyLoading(true);
|
|
180
|
+
} else if (immediate.value) dispatchFetch({ isPolling: false });
|
|
194
181
|
});
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
abortFetch();
|
|
201
|
-
fetchListDebounce.run({
|
|
202
|
-
pagination,
|
|
182
|
+
if (!waitRequest.value && immediate.value) dispatchFetch({ isPolling: false });
|
|
183
|
+
const isTreeDataRef = computed(() => tableDataList.value.some((item) => isArray(item.children) && item.children.length > 0));
|
|
184
|
+
function handleTableChange(paginationConfig, filters = {}, sorter = {}, extra) {
|
|
185
|
+
dispatchFetch({
|
|
186
|
+
pagination: paginationConfig,
|
|
203
187
|
filters,
|
|
204
188
|
sorter,
|
|
205
189
|
extra,
|
|
206
190
|
isPolling: false
|
|
207
191
|
});
|
|
208
192
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
tableDataList.value = newData;
|
|
212
|
-
if (!request || !isFunction(request)) {
|
|
213
|
-
const total = newData.length || 0;
|
|
214
|
-
if (total !== pageInfo.total) setPagination({ total });
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
const operateTableDataRow = (props) => {
|
|
193
|
+
/** 对表格数据行执行增删改操作(update/push/unshift/delete) */
|
|
194
|
+
function operateTableDataRow(props) {
|
|
218
195
|
const { key, row, value, type = "update" } = props;
|
|
219
196
|
const dataIndex = key ?? rowKey.value;
|
|
220
197
|
const recordValue = row?.[dataIndex] ?? value;
|
|
@@ -222,7 +199,7 @@ function useFetchData({ rowKey, autoRequest, polling, request, postData, dataSou
|
|
|
222
199
|
switch (type) {
|
|
223
200
|
case "update":
|
|
224
201
|
if (dataIndex && recordValue && row) tableDataList.value = tableDataList.value.map((item) => {
|
|
225
|
-
if (recordValue === item[dataIndex]) return
|
|
202
|
+
if (recordValue === item[dataIndex]) return merge({}, item, row);
|
|
226
203
|
return item;
|
|
227
204
|
});
|
|
228
205
|
break;
|
|
@@ -236,23 +213,29 @@ function useFetchData({ rowKey, autoRequest, polling, request, postData, dataSou
|
|
|
236
213
|
if (dataIndex) tableDataList.value = tableDataList.value.filter((item) => value !== item[dataIndex]);
|
|
237
214
|
break;
|
|
238
215
|
}
|
|
239
|
-
}
|
|
216
|
+
}
|
|
217
|
+
/** 手动触发请求,waitRequest=true 时跳过 */
|
|
218
|
+
function run(info) {
|
|
219
|
+
if (waitRequest.value) return;
|
|
220
|
+
if (request) dispatchFetch({
|
|
221
|
+
...info,
|
|
222
|
+
isPolling: false
|
|
223
|
+
});
|
|
224
|
+
else setTableDataList(dataSource.value || []);
|
|
225
|
+
}
|
|
226
|
+
/** reload 是 run 的别名 */
|
|
227
|
+
function reload(info) {
|
|
228
|
+
run(info);
|
|
229
|
+
}
|
|
240
230
|
return {
|
|
241
|
-
dataSource:
|
|
231
|
+
dataSource: computed(() => tableDataList.value.length ? tableDataList.value : EMPTY_ARRAY),
|
|
242
232
|
isTreeDataRef,
|
|
243
233
|
setTableDataList,
|
|
244
234
|
operateTableDataRow,
|
|
245
235
|
handleTableChange,
|
|
246
|
-
run
|
|
247
|
-
|
|
248
|
-
if (request) await fetchListDebounce.run({
|
|
249
|
-
...info,
|
|
250
|
-
isPolling: false
|
|
251
|
-
});
|
|
252
|
-
else emit("reload");
|
|
253
|
-
}
|
|
236
|
+
run,
|
|
237
|
+
reload
|
|
254
238
|
};
|
|
255
239
|
}
|
|
256
|
-
|
|
257
240
|
//#endregion
|
|
258
|
-
export {
|
|
241
|
+
export { useFetchData };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { BarExpose } from "../components/ScrollBar/Bar.js";
|
|
2
|
+
import { ComputedRef, Ref } from "vue";
|
|
3
|
+
|
|
4
|
+
//#region src/hooks/useFitPage.d.ts
|
|
5
|
+
interface UseFitPageOptions {
|
|
6
|
+
fitPage: ComputedRef<boolean>;
|
|
7
|
+
cardEl: Ref<HTMLElement | undefined>;
|
|
8
|
+
prefixCls: ComputedRef<string>;
|
|
9
|
+
}
|
|
10
|
+
interface UseFitPageReturn {
|
|
11
|
+
scrollY: ComputedRef<number>;
|
|
12
|
+
overflowHidden: ComputedRef<boolean>;
|
|
13
|
+
fullPageClass: ComputedRef<string>;
|
|
14
|
+
scrollEl: Ref<HTMLElement | undefined>;
|
|
15
|
+
barRef: Ref<BarExpose | undefined>;
|
|
16
|
+
}
|
|
17
|
+
declare function useFitPage(options: UseFitPageOptions): UseFitPageReturn;
|
|
18
|
+
//#endregion
|
|
19
|
+
export { UseFitPageOptions, UseFitPageReturn, useFitPage };
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { useProvideScrollBarContext } from "../components/ScrollBar/context.js";
|
|
2
|
+
import { computed, ref, watchEffect } from "vue";
|
|
3
|
+
import { useElementSize, useMutationObserver, useResizeObserver, useScroll } from "@vueuse/core";
|
|
4
|
+
import { onMountedOrActivated } from "@gx-design-vue/pro-hooks";
|
|
5
|
+
//#region src/hooks/useFitPage.ts
|
|
6
|
+
function queryChildElements(card, prefixCls, targets) {
|
|
7
|
+
targets.toolbarEl.value = card.querySelector(`.${prefixCls}-list-toolbar`) ?? void 0;
|
|
8
|
+
targets.headerEl.value = card.querySelector(".ant-table-header") ?? void 0;
|
|
9
|
+
targets.pageEl.value = card.querySelector(".ant-table-pagination") ?? void 0;
|
|
10
|
+
targets.scrollEl.value = card.querySelector(".ant-table-body") ?? void 0;
|
|
11
|
+
targets.bodyInnerEl.value = card.querySelector(".ant-table-body > table") ?? void 0;
|
|
12
|
+
}
|
|
13
|
+
function getElementBlockMargin(el) {
|
|
14
|
+
if (!el) return 0;
|
|
15
|
+
const style = getComputedStyle(el);
|
|
16
|
+
return (Number.parseFloat(style.marginTop) || 0) + (Number.parseFloat(style.marginBottom) || 0);
|
|
17
|
+
}
|
|
18
|
+
function useFitPage(options) {
|
|
19
|
+
const { fitPage, cardEl, prefixCls } = options;
|
|
20
|
+
const barRef = ref();
|
|
21
|
+
const toolbarEl = ref();
|
|
22
|
+
const headerEl = ref();
|
|
23
|
+
const pageEl = ref();
|
|
24
|
+
const scrollEl = ref();
|
|
25
|
+
const bodyInnerEl = ref();
|
|
26
|
+
const childRefs = {
|
|
27
|
+
toolbarEl,
|
|
28
|
+
headerEl,
|
|
29
|
+
pageEl,
|
|
30
|
+
scrollEl,
|
|
31
|
+
bodyInnerEl
|
|
32
|
+
};
|
|
33
|
+
const { height: cardHeight } = useElementSize(cardEl);
|
|
34
|
+
const { height: toolbarHeight } = useElementSize(toolbarEl);
|
|
35
|
+
const { height: headerHeight } = useElementSize(headerEl);
|
|
36
|
+
const { height: pageHeight } = useElementSize(pageEl);
|
|
37
|
+
const { height: bodyContentHeight } = useElementSize(bodyInnerEl);
|
|
38
|
+
useMutationObserver(cardEl, () => {
|
|
39
|
+
if (cardEl.value) queryChildElements(cardEl.value, prefixCls.value, childRefs);
|
|
40
|
+
}, {
|
|
41
|
+
childList: true,
|
|
42
|
+
subtree: true
|
|
43
|
+
});
|
|
44
|
+
onMountedOrActivated(() => {
|
|
45
|
+
if (cardEl.value) queryChildElements(cardEl.value, prefixCls.value, childRefs);
|
|
46
|
+
});
|
|
47
|
+
const toolbarMargin = computed(() => getElementBlockMargin(toolbarEl.value));
|
|
48
|
+
const pageMargin = computed(() => {
|
|
49
|
+
return getElementBlockMargin(pageEl.value);
|
|
50
|
+
});
|
|
51
|
+
const scrollY = computed(() => {
|
|
52
|
+
if (!cardEl.value || !fitPage.value) return 0;
|
|
53
|
+
const tableHeight = cardHeight.value - toolbarHeight.value - toolbarMargin.value - headerHeight.value - pageHeight.value - pageMargin.value;
|
|
54
|
+
return Math.max(0, tableHeight);
|
|
55
|
+
});
|
|
56
|
+
const overflowHidden = computed(() => {
|
|
57
|
+
if (!scrollY.value || !fitPage.value) return false;
|
|
58
|
+
return bodyContentHeight.value <= scrollY.value;
|
|
59
|
+
});
|
|
60
|
+
const fullPageClass = computed(() => {
|
|
61
|
+
return fitPage.value ? `${prefixCls.value}-full-page` : "";
|
|
62
|
+
});
|
|
63
|
+
watchEffect(() => {
|
|
64
|
+
if (!scrollEl.value) return;
|
|
65
|
+
if (fitPage.value && scrollY.value > 0) scrollEl.value.style.height = `${scrollY.value}px`;
|
|
66
|
+
else scrollEl.value.style.height = "";
|
|
67
|
+
});
|
|
68
|
+
useScroll(scrollEl, { onScroll: () => {
|
|
69
|
+
if (scrollEl.value) barRef.value?.handleScroll(scrollEl.value);
|
|
70
|
+
} });
|
|
71
|
+
useResizeObserver(scrollEl, () => {
|
|
72
|
+
barRef.value?.update();
|
|
73
|
+
});
|
|
74
|
+
useProvideScrollBarContext({
|
|
75
|
+
className: `${prefixCls.value}-scroll`,
|
|
76
|
+
tableHeaderHeight: headerHeight,
|
|
77
|
+
tableScrollYHeight: scrollY,
|
|
78
|
+
scrollbarElement: cardEl,
|
|
79
|
+
wrapElement: scrollEl
|
|
80
|
+
});
|
|
81
|
+
return {
|
|
82
|
+
scrollY,
|
|
83
|
+
overflowHidden,
|
|
84
|
+
fullPageClass,
|
|
85
|
+
scrollEl,
|
|
86
|
+
barRef
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
//#endregion
|
|
90
|
+
export { useFitPage };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ComputedRef, Ref } from "vue";
|
|
2
|
+
|
|
3
|
+
//#region src/hooks/useKeepAliveReload.d.ts
|
|
4
|
+
interface UseKeepAliveReloadOptions {
|
|
5
|
+
enabled: ComputedRef<boolean>;
|
|
6
|
+
reload: () => void;
|
|
7
|
+
}
|
|
8
|
+
interface UseKeepAliveReloadReturn {
|
|
9
|
+
hasActivated: Ref<boolean>;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* 安全的 onActivated 包装:无组件实例时直接执行回调。
|
|
13
|
+
*/
|
|
14
|
+
declare function tryOnActivated(callback: () => void): void;
|
|
15
|
+
/**
|
|
16
|
+
* Keep-alive 页面重新进入时触发数据请求。
|
|
17
|
+
* 首次激活仅标记状态,后续激活且 enabled 为 true 时调用 reload。
|
|
18
|
+
*/
|
|
19
|
+
declare function useKeepAliveReload(options: UseKeepAliveReloadOptions): UseKeepAliveReloadReturn;
|
|
20
|
+
//#endregion
|
|
21
|
+
export { UseKeepAliveReloadOptions, UseKeepAliveReloadReturn, tryOnActivated, useKeepAliveReload };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { getCurrentInstance, nextTick, onActivated, ref } from "vue";
|
|
2
|
+
//#region src/hooks/useKeepAliveReload.ts
|
|
3
|
+
/**
|
|
4
|
+
* 安全的 onActivated 包装:无组件实例时直接执行回调。
|
|
5
|
+
*/
|
|
6
|
+
function tryOnActivated(callback) {
|
|
7
|
+
if (getCurrentInstance()) onActivated(callback);
|
|
8
|
+
else nextTick(callback);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Keep-alive 页面重新进入时触发数据请求。
|
|
12
|
+
* 首次激活仅标记状态,后续激活且 enabled 为 true 时调用 reload。
|
|
13
|
+
*/
|
|
14
|
+
function useKeepAliveReload(options) {
|
|
15
|
+
const hasActivated = ref(false);
|
|
16
|
+
tryOnActivated(() => {
|
|
17
|
+
if (hasActivated.value) {
|
|
18
|
+
if (options.enabled.value) options.reload();
|
|
19
|
+
} else hasActivated.value = true;
|
|
20
|
+
});
|
|
21
|
+
return { hasActivated };
|
|
22
|
+
}
|
|
23
|
+
//#endregion
|
|
24
|
+
export { tryOnActivated, useKeepAliveReload };
|
|
@@ -1,10 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Ref } from "vue";
|
|
1
|
+
import { ComputedRef, Ref } from "vue";
|
|
3
2
|
|
|
4
3
|
//#region src/hooks/useLoading.d.ts
|
|
5
|
-
|
|
6
|
-
loading:
|
|
7
|
-
|
|
8
|
-
}
|
|
4
|
+
interface UseLoadingOptions {
|
|
5
|
+
loading: ComputedRef<boolean | {
|
|
6
|
+
spinning?: boolean;
|
|
7
|
+
} | undefined>;
|
|
8
|
+
onChange?: (loading: boolean) => void;
|
|
9
|
+
}
|
|
10
|
+
interface UseLoadingReturn {
|
|
11
|
+
loading: Ref<boolean>;
|
|
12
|
+
setLoading: (value: boolean) => void;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Table loading 状态管理。
|
|
16
|
+
* 支持 boolean 和 SpinProps 对象两种 loading prop 形式,
|
|
17
|
+
* 内部始终维护 boolean 状态,外部 prop 变化时自动同步。
|
|
18
|
+
*/
|
|
19
|
+
declare function useLoading(options: UseLoadingOptions): UseLoadingReturn;
|
|
9
20
|
//#endregion
|
|
10
|
-
export { useLoading };
|
|
21
|
+
export { UseLoadingOptions, UseLoadingReturn, useLoading };
|
package/dist/hooks/useLoading.js
CHANGED
|
@@ -1,20 +1,36 @@
|
|
|
1
1
|
import { ref, watch } from "vue";
|
|
2
2
|
import { isBoolean, isObject } from "@gx-design-vue/pro-utils";
|
|
3
|
-
|
|
4
3
|
//#region src/hooks/useLoading.ts
|
|
4
|
+
/** 从 boolean 或 SpinProps 对象中提取 spinning 状态 */
|
|
5
|
+
function toSpinning(value, fallback = false) {
|
|
6
|
+
if (isBoolean(value)) return value;
|
|
7
|
+
if (isObject(value)) return value.spinning ?? fallback;
|
|
8
|
+
return fallback;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Table loading 状态管理。
|
|
12
|
+
* 支持 boolean 和 SpinProps 对象两种 loading prop 形式,
|
|
13
|
+
* 内部始终维护 boolean 状态,外部 prop 变化时自动同步。
|
|
14
|
+
*/
|
|
5
15
|
function useLoading(options) {
|
|
6
|
-
const loading = ref(
|
|
7
|
-
watch(() => options.loading.value, (
|
|
8
|
-
|
|
16
|
+
const loading = ref(toSpinning(options.loading.value));
|
|
17
|
+
watch(() => options.loading.value, (propValue) => {
|
|
18
|
+
const next = toSpinning(propValue, loading.value);
|
|
19
|
+
if (next !== loading.value) {
|
|
20
|
+
loading.value = next;
|
|
21
|
+
options.onChange?.(next);
|
|
22
|
+
}
|
|
9
23
|
});
|
|
10
|
-
function getStatus(value, defaultValue = false) {
|
|
11
|
-
return isBoolean(value) ? value : isObject(value) ? value?.spinning ?? defaultValue : defaultValue;
|
|
12
|
-
}
|
|
13
24
|
function setLoading(value) {
|
|
14
|
-
loading.value
|
|
25
|
+
if (loading.value !== value) {
|
|
26
|
+
loading.value = value;
|
|
27
|
+
options.onChange?.(value);
|
|
28
|
+
}
|
|
15
29
|
}
|
|
16
|
-
return
|
|
30
|
+
return {
|
|
31
|
+
loading,
|
|
32
|
+
setLoading
|
|
33
|
+
};
|
|
17
34
|
}
|
|
18
|
-
|
|
19
35
|
//#endregion
|
|
20
|
-
export { useLoading };
|
|
36
|
+
export { useLoading };
|
|
@@ -1,18 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { PageState, ProTablePagination, ProTableProps } from "../types/TableTypings.js";
|
|
1
|
+
import { PageState, ProTablePagination, ProTablePaginationConfig } from "../interface.js";
|
|
3
2
|
import { Ref } from "vue";
|
|
4
3
|
|
|
5
4
|
//#region src/hooks/usePagination.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* 分页状态管理。
|
|
7
|
+
* 合并用户分页配置与默认值,分离 UI 分页展示与请求分页参数。
|
|
8
|
+
* setPagination 只同步 current/pageSize/total 到 requestPagination,避免 UI 字段污染请求参数。
|
|
9
|
+
*/
|
|
6
10
|
declare function usePagination({
|
|
7
|
-
pagination
|
|
8
|
-
pageItemRender
|
|
11
|
+
pagination
|
|
9
12
|
}: {
|
|
10
|
-
pagination: Ref<
|
|
11
|
-
pageItemRender: PageItemRender;
|
|
13
|
+
pagination: Ref<ProTablePagination | undefined>;
|
|
12
14
|
}): {
|
|
13
15
|
paginationInfo: Ref<ProTablePagination | false>;
|
|
16
|
+
paginationAlign: Ref<'start' | 'center' | 'end'>;
|
|
14
17
|
requestPagination: PageState;
|
|
15
|
-
setPagination: (info: Partial<
|
|
18
|
+
setPagination: (info: Partial<ProTablePaginationConfig>) => void;
|
|
16
19
|
};
|
|
17
20
|
//#endregion
|
|
18
21
|
export { usePagination };
|