无木
2021-06-08 8e4f486fcf835f0b6f2a95676dba268ffdd0566e
提交 | 用户 | age
9c2f3f 1 import type { BasicTableProps, FetchParams, SorterResult } from '../types/table';
a1ffb6 2 import type { PaginationProps } from '../types/pagination';
V 3
601368 4 import {
V 5   ref,
6   unref,
7   ComputedRef,
8   computed,
9   onMounted,
10   watch,
11   reactive,
12   Ref,
13   watchEffect,
14 } from 'vue';
a1ffb6 15
b49950 16 import { useTimeoutFn } from '/@/hooks/core/useTimeout';
a1ffb6 17
faf3f4 18 import { buildUUID } from '/@/utils/uuid';
19 import { isFunction, isBoolean } from '/@/utils/is';
31ff05 20 import { get, cloneDeep } from 'lodash-es';
a1ffb6 21
354904 22 import { FETCH_SETTING, ROW_KEY, PAGE_SIZE } from '../const';
faf3f4 23
24 interface ActionType {
354904 25   getPaginationInfo: ComputedRef<boolean | PaginationProps>;
faf3f4 26   setPagination: (info: Partial<PaginationProps>) => void;
354904 27   setLoading: (loading: boolean) => void;
V 28   getFieldsValue: () => Recordable;
9c2f3f 29   clearSelectedRowKeys: () => void;
601368 30   tableData: Ref<Recordable[]>;
9c2f3f 31 }
V 32
33 interface SearchState {
34   sortInfo: Recordable;
35   filterInfo: Record<string, string[]>;
faf3f4 36 }
37 export function useDataSource(
354904 38   propsRef: ComputedRef<BasicTableProps>,
9c2f3f 39   {
V 40     getPaginationInfo,
41     setPagination,
42     setLoading,
43     getFieldsValue,
44     clearSelectedRowKeys,
601368 45     tableData,
9c2f3f 46   }: ActionType,
faf3f4 47   emit: EmitType
48 ) {
9c2f3f 49   const searchState = reactive<SearchState>({
V 50     sortInfo: {},
51     filterInfo: {},
52   });
354904 53   const dataSourceRef = ref<Recordable[]>([]);
faf3f4 54
601368 55   watchEffect(() => {
V 56     tableData.value = unref(dataSourceRef);
57   });
58
da76f3 59   watch(
V 60     () => unref(propsRef).dataSource,
61     () => {
62       const { dataSource, api } = unref(propsRef);
63       !api && dataSource && (dataSourceRef.value = dataSource);
64     },
65     {
66       immediate: true,
67     }
68   );
9c2f3f 69
V 70   function handleTableChange(
71     pagination: PaginationProps,
72     filters: Partial<Recordable<string[]>>,
73     sorter: SorterResult
74   ) {
75     const { clearSelectOnPageChange, sortFn, filterFn } = unref(propsRef);
76     if (clearSelectOnPageChange) {
77       clearSelectedRowKeys();
78     }
79     setPagination(pagination);
80
81     const params: Recordable = {};
82     if (sorter && isFunction(sortFn)) {
83       const sortInfo = sortFn(sorter);
84       searchState.sortInfo = sortInfo;
85       params.sortInfo = sortInfo;
86     }
87
88     if (filters && isFunction(filterFn)) {
89       const filterInfo = filterFn(filters);
90       searchState.filterInfo = filterInfo;
91       params.filterInfo = filterInfo;
92     }
93     fetch(params);
94   }
faf3f4 95
96   function setTableKey(items: any[]) {
354904 97     if (!items || !Array.isArray(items)) return;
faf3f4 98     items.forEach((item) => {
99       if (!item[ROW_KEY]) {
100         item[ROW_KEY] = buildUUID();
101       }
102       if (item.children && item.children.length) {
103         setTableKey(item.children);
104       }
105     });
106   }
354904 107
faf3f4 108   const getAutoCreateKey = computed(() => {
109     return unref(propsRef).autoCreateKey && !unref(propsRef).rowKey;
354904 110   });
V 111
112   const getRowKey = computed(() => {
113     const { rowKey } = unref(propsRef);
114     return unref(getAutoCreateKey) ? ROW_KEY : rowKey;
faf3f4 115   });
116
117   const getDataSourceRef = computed(() => {
118     const dataSource = unref(dataSourceRef);
119     if (!dataSource || dataSource.length === 0) {
120       return [];
121     }
122     if (unref(getAutoCreateKey)) {
123       const firstItem = dataSource[0];
124       const lastItem = dataSource[dataSource.length - 1];
125
126       if (firstItem && lastItem) {
127         if (!firstItem[ROW_KEY] || !lastItem[ROW_KEY]) {
31ff05 128           const data = cloneDeep(unref(dataSourceRef));
V 129           data.forEach((item) => {
faf3f4 130             if (!item[ROW_KEY]) {
131               item[ROW_KEY] = buildUUID();
132             }
133             if (item.children && item.children.length) {
134               setTableKey(item.children);
135             }
136           });
31ff05 137           dataSourceRef.value = data;
faf3f4 138         }
139       }
140     }
141     return unref(dataSourceRef);
142   });
143
9c2f3f 144   async function updateTableData(index: number, key: string, value: any) {
V 145     const record = dataSourceRef.value[index];
146     if (record) {
147       dataSourceRef.value[index][key] = value;
148     }
149     return dataSourceRef.value[index];
150   }
151
8e4f48 152   function updateTableDataRecord(
153     rowKey: string | number,
154     record: Recordable
155   ): Recordable | undefined {
156     if (!dataSourceRef.value || dataSourceRef.value.length == 0) return;
157     const rowKeyName = unref(getRowKey);
158     if (typeof rowKeyName !== 'string') {
159       return;
160     }
161     const row = dataSourceRef.value.find(
162       (r) => Reflect.has(r, rowKeyName as string) && r[rowKeyName as string] === rowKey
163     );
164     if (row) {
165       for (const field in row) {
166         if (Reflect.has(record, field)) row[field] = record[field];
167       }
168       return row;
169     }
170   }
171
faf3f4 172   async function fetch(opt?: FetchParams) {
3ef508 173     const { api, searchInfo, fetchSetting, beforeFetch, afterFetch, useSearchForm, pagination } =
Z 174       unref(propsRef);
661db0 175     if (!api || !isFunction(api)) return;
faf3f4 176     try {
354904 177       setLoading(true);
faf3f4 178       const { pageField, sizeField, listField, totalField } = fetchSetting || FETCH_SETTING;
354904 179       let pageParams: Recordable = {};
V 180
181       const { current = 1, pageSize = PAGE_SIZE } = unref(getPaginationInfo) as PaginationProps;
182
745fcf 183       if ((isBoolean(pagination) && !pagination) || isBoolean(getPaginationInfo)) {
faf3f4 184         pageParams = {};
185       } else {
e034d1 186         pageParams[pageField] = (opt && opt.page) || current;
faf3f4 187         pageParams[sizeField] = pageSize;
188       }
189
9c2f3f 190       const { sortInfo = {}, filterInfo } = searchState;
V 191
354904 192       let params: Recordable = {
faf3f4 193         ...pageParams,
194         ...(useSearchForm ? getFieldsValue() : {}),
195         ...searchInfo,
8d7d08 196         ...(opt?.searchInfo ?? {}),
9c2f3f 197         ...sortInfo,
V 198         ...filterInfo,
8d7d08 199         ...(opt?.sortInfo ?? {}),
V 200         ...(opt?.filterInfo ?? {}),
faf3f4 201       };
202       if (beforeFetch && isFunction(beforeFetch)) {
203         params = beforeFetch(params) || params;
204       }
205
206       const res = await api(params);
354904 207
V 208       const isArrayResult = Array.isArray(res);
209
210       let resultItems: Recordable[] = isArrayResult ? res : get(res, listField);
211       const resultTotal: number = isArrayResult ? 0 : get(res, totalField);
212
877311 213       // 假如数据变少,导致总页数变少并小于当前选中页码,通过getPaginationRef获取到的页码是不正确的,需获取正确的页码再次执行
0aeec5 214       if (resultTotal) {
V 215         const currentTotalPage = Math.ceil(resultTotal / pageSize);
216         if (current > currentTotalPage) {
217           setPagination({
218             current: currentTotalPage,
219           });
220           fetch(opt);
221         }
877311 222       }
354904 223
faf3f4 224       if (afterFetch && isFunction(afterFetch)) {
225         resultItems = afterFetch(resultItems) || resultItems;
226       }
227       dataSourceRef.value = resultItems;
228       setPagination({
229         total: resultTotal || 0,
230       });
231       if (opt && opt.page) {
232         setPagination({
233           current: opt.page || 1,
234         });
235       }
236       emit('fetch-success', {
237         items: unref(resultItems),
238         total: resultTotal,
239       });
240     } catch (error) {
241       emit('fetch-error', error);
242       dataSourceRef.value = [];
243       setPagination({
244         total: 0,
245       });
246     } finally {
354904 247       setLoading(false);
faf3f4 248     }
249   }
250
354904 251   function setTableData<T = Recordable>(values: T[]) {
faf3f4 252     dataSourceRef.value = values;
253   }
354904 254
V 255   function getDataSource<T = Recordable>() {
256     return getDataSourceRef.value as T[];
257   }
258
259   async function reload(opt?: FetchParams) {
260     await fetch(opt);
261   }
262
faf3f4 263   onMounted(() => {
d9b196 264     useTimeoutFn(() => {
faf3f4 265       unref(propsRef).immediate && fetch();
97180e 266     }, 16);
faf3f4 267   });
268
354904 269   return {
V 270     getDataSourceRef,
271     getDataSource,
272     getRowKey,
273     setTableData,
274     getAutoCreateKey,
275     fetch,
276     reload,
9c2f3f 277     updateTableData,
8e4f48 278     updateTableDataRecord,
9c2f3f 279     handleTableChange,
354904 280   };
faf3f4 281 }