vben
2020-10-22 1c075a7a32dd05454bc45d4eb686e2234c3c6175
提交 | 用户 | age
faf3f4 1 <template>
2   <div
8b3a4d 3     ref="wrapRef"
faf3f4 4     class="basic-table"
5     :class="{
6       'table-form-container': getBindValues.useSearchForm,
7     }"
8   >
9     <BasicForm
10       v-bind="getFormProps"
11       v-if="getBindValues.useSearchForm"
12       :submitButtonOptions="{ loading }"
13       @register="registerForm"
14       @submit="handleSearchInfoChange"
15       @advanced-change="redoHeight"
16     >
17       <template #[item]="data" v-for="item in Object.keys($slots)">
18         <slot :name="`form-${item}`" v-bind="data" />
19       </template>
20     </BasicForm>
21     <Table
22       ref="tableElRef"
23       v-bind="getBindValues"
24       :rowClassName="getRowClassName"
25       :class="{
26         hidden: !getEmptyDataIsShowTable,
27       }"
28       @change="handleTableChange"
29     >
30       <template #[item]="data" v-for="item in Object.keys($slots)">
31         <slot :name="item" v-bind="data" />
32       </template>
33     </Table>
34   </div>
35 </template>
36 <script lang="ts">
8b3a4d 37   import { defineComponent, ref, computed, unref, watch, nextTick, toRaw } from 'vue';
faf3f4 38   import { Table } from 'ant-design-vue';
39   import { basicProps } from './props';
40   import type {
41     BasicTableProps,
42     FetchParams,
43     GetColumnsParams,
44     TableActionType,
8b3a4d 45     SizeType,
faf3f4 46   } from './types/table';
8b3a4d 47
faf3f4 48   import { isFunction, isString } from '/@/utils/is';
49
50   import renderTitle from './components/renderTitle';
51   import renderFooter from './components/renderFooter';
52   import renderExpandIcon from './components/renderExpandIcon';
53
54   import { usePagination } from './hooks/usePagination';
55   import { useColumns } from './hooks/useColumns';
56   import { useDataSource } from './hooks/useDataSource';
57   import { useLoading } from './hooks/useLoading';
58   import { useRowSelection } from './hooks/useRowSelection';
59   import { useTableScroll } from './hooks/useTableScroll';
60   import { provideTable } from './hooks/useProvinceTable';
61   import { BasicForm, FormProps, useForm } from '/@/components/Form/index';
62   import { omit } from 'lodash-es';
63   import { ROW_KEY } from './const';
64   import { PaginationProps } from './types/pagination';
65   import { deepMerge } from '/@/utils';
66   import { TableCustomRecord } from 'ant-design-vue/types/table/table';
67   import { useEvent } from '/@/hooks/event/useEvent';
8b3a4d 68
V 69   import './style/index.less';
faf3f4 70   export default defineComponent({
71     props: basicProps,
72     components: { Table, BasicForm },
73     emits: ['fetch-success', 'fetch-error', 'selection-change', 'register'],
74     setup(props, { attrs, emit, slots }) {
75       const tableElRef = ref<any>(null);
8b3a4d 76       const wrapRef = ref<Nullable<HTMLDivElement>>(null);
faf3f4 77       const innerPropsRef = ref<Partial<BasicTableProps>>();
78       const [registerForm, { getFieldsValue }] = useForm();
79
80       const getMergeProps = computed(
81         (): BasicTableProps => {
82           return {
83             ...props,
84             ...unref(innerPropsRef),
85           } as BasicTableProps;
86         }
87       );
88       const { loadingRef } = useLoading(getMergeProps);
89       const { getPaginationRef, setPagination } = usePagination(getMergeProps);
90       const { getColumnsRef, setColumns } = useColumns(getMergeProps, getPaginationRef);
91       const { getDataSourceRef, setTableData, fetch, getAutoCreateKey } = useDataSource(
92         getMergeProps,
93         {
94           getPaginationRef,
95           loadingRef,
96           setPagination,
97           getFieldsValue,
98         },
99         emit
100       );
8b3a4d 101
faf3f4 102       const { getScrollRef, redoHeight } = useTableScroll(getMergeProps, tableElRef);
103       const {
104         getRowSelectionRef,
105         getSelectRows,
106         clearSelectedRowKeys,
107         getSelectRowKeys,
108         deleteSelectRowByKey,
109         setSelectedRowKeys,
110       } = useRowSelection(getMergeProps, emit);
111
112       const getRowKey = computed(() => {
113         const { rowKey } = unref(getMergeProps);
114
115         return unref(getAutoCreateKey) ? ROW_KEY : rowKey;
116       });
8b3a4d 117
faf3f4 118       const getBindValues = computed(() => {
8b3a4d 119         const { title, titleHelpMessage, showSummary, showTableSetting, tableSetting } = unref(
V 120           getMergeProps
121         );
122         const hideTitle = !slots.tableTitle && !title && !slots.toolbar && !showTableSetting;
faf3f4 123         const titleData: any =
8b3a4d 124           hideTitle && !isString(title)
faf3f4 125             ? {}
126             : {
8b3a4d 127                 title: hideTitle
V 128                   ? null
129                   : renderTitle.bind(
130                       null,
131                       title,
132                       titleHelpMessage,
133                       slots,
134                       showTableSetting,
135                       tableSetting
136                     ),
faf3f4 137               };
138         const pagination = unref(getPaginationRef);
139         const rowSelection = unref(getRowSelectionRef);
140         const scroll = unref(getScrollRef);
141         const loading = unref(loadingRef);
142         const rowKey = unref(getRowKey);
143         const columns = unref(getColumnsRef);
144         const dataSource = unref(getDataSourceRef);
145         let propsData = {
146           size: 'middle',
147           ...(slots.expandedRowRender ? { expandIcon: renderExpandIcon() } : {}),
148           ...attrs,
149           ...unref(getMergeProps),
150           ...titleData,
151           scroll,
152           loading,
153           tableLayout: 'fixed',
154           rowSelection,
155           rowKey,
156           columns,
157           pagination,
158           dataSource,
159         };
160         if (slots.expandedRowRender) {
161           propsData = omit(propsData, 'scroll');
162         }
163         if (showSummary) {
164           propsData.footer = renderFooter.bind(null, {
710158 165             scroll: scroll as any,
faf3f4 166             columnsRef: getColumnsRef,
167             summaryFunc: unref(getMergeProps).summaryFunc,
168             dataSourceRef: getDataSourceRef,
169             rowSelectionRef: getRowSelectionRef,
170           });
171         }
172         return propsData;
173       });
8b3a4d 174
faf3f4 175       const getFormProps = computed(() => {
176         const { formConfig } = unref(getBindValues);
177         const formProps: FormProps = {
178           showAdvancedButton: true,
179           ...(formConfig as FormProps),
180           compact: true,
181         };
182         return formProps;
183       });
184
185       const getEmptyDataIsShowTable = computed(() => {
186         const { emptyDataIsShowTable, useSearchForm } = unref(getMergeProps);
187         if (emptyDataIsShowTable || !useSearchForm) {
188           return true;
189         }
190         return !!unref(getDataSourceRef).length;
191       });
192
193       function getRowClassName(record: TableCustomRecord<any>, index: number) {
194         const { striped, rowClassName } = unref(getMergeProps);
195         if (!striped) return;
196         if (rowClassName && isFunction(rowClassName)) {
197           return rowClassName(record);
198         }
199         return (index || 0) % 2 === 1 ? 'basic-table-row__striped' : '';
200       }
201
202       function handleSearchInfoChange(info: any) {
203         const { handleSearchInfoFn } = unref(getMergeProps);
204         if (handleSearchInfoFn && isFunction(handleSearchInfoFn)) {
205           info = handleSearchInfoFn(info) || info;
206         }
207         fetch({ searchInfo: info, page: 1 });
208       }
209
210       function handleTableChange(pagination: PaginationProps) {
211         const { clearSelectOnPageChange } = unref(getMergeProps);
212         if (clearSelectOnPageChange) {
213           clearSelectedRowKeys();
214         }
215         setPagination(pagination);
216         fetch();
217       }
8b3a4d 218
1c075a 219       function handleSummary() {
V 220         if (unref(getMergeProps).showSummary) {
221           nextTick(() => {
222             const tableEl = unref(tableElRef);
223             if (!tableEl) {
224               return;
225             }
226             const bodyDomList = tableEl.$el.querySelectorAll('.ant-table-body') as HTMLDivElement[];
227             const bodyDom = bodyDomList[0];
228             useEvent({
229               el: bodyDom,
230               name: 'scroll',
231               listener: () => {
232                 const footerBodyDom = tableEl.$el.querySelector(
233                   '.ant-table-footer .ant-table-body'
234                 ) as HTMLDivElement;
235                 if (!footerBodyDom || !bodyDom) return;
236                 footerBodyDom.scrollLeft = bodyDom.scrollLeft;
237               },
238               wait: 0,
239               options: true,
240             });
241           });
242         }
243       }
244
faf3f4 245       watch(
246         () => unref(getDataSourceRef),
247         () => {
1c075a 248           handleSummary();
faf3f4 249         },
250         { immediate: true }
251       );
252
8b3a4d 253       function setProps(props: Partial<BasicTableProps>) {
V 254         innerPropsRef.value = deepMerge(unref(innerPropsRef) || {}, props);
255       }
256
faf3f4 257       const tableAction: TableActionType = {
258         reload: async (opt?: FetchParams) => {
259           await fetch(opt);
260         },
261         getSelectRows,
262         clearSelectedRowKeys,
263         getSelectRowKeys,
264         deleteSelectRowByKey,
265         setPagination,
266         setTableData,
267         redoHeight,
268         setSelectedRowKeys,
269         setColumns,
270         getPaginationRef: () => {
271           return unref(getPaginationRef);
272         },
273         getColumns: (opt?: GetColumnsParams) => {
8b3a4d 274           const { ignoreIndex, ignoreAction } = opt || {};
V 275           let columns = toRaw(unref(getColumnsRef));
faf3f4 276           if (ignoreIndex) {
277             columns = columns.filter((item) => item.flag !== 'INDEX');
8b3a4d 278           }
V 279           if (ignoreAction) {
280             columns = columns.filter((item) => item.flag !== 'ACTION');
faf3f4 281           }
282           return columns;
283         },
284         getDataSource: () => {
285           return unref(getDataSourceRef);
286         },
287         setLoading: (loading: boolean) => {
288           loadingRef.value = loading;
289         },
8b3a4d 290         setProps,
V 291         getSize: (): SizeType => {
292           return unref(getBindValues).size;
faf3f4 293         },
294       };
295
8b3a4d 296       provideTable({
V 297         ...tableAction,
298         wrapRef,
299       });
faf3f4 300
301       emit('register', tableAction);
302       return {
303         tableElRef,
304         getBindValues,
305         loading: loadingRef,
306         registerForm,
307         handleSearchInfoChange,
308         getFormProps,
309         getEmptyDataIsShowTable,
310         handleTableChange,
311         getRowClassName,
8b3a4d 312         wrapRef,
faf3f4 313         ...tableAction,
314       };
315     },
316   });
317 </script>