vben
2021-01-12 cdf0a600e505daf429446b8a7968269e1034de04
提交 | 用户 | age
116a1f 1 import type { BasicTableProps, TableRowSelection } from '../types/table';
354904 2 import type { Ref, ComputedRef } from 'vue';
da76f3 3 import { computed, unref, ref, nextTick, watch } from 'vue';
a1ffb6 4
faf3f4 5 import { getViewportOffset } from '/@/utils/domUtils';
6 import { isBoolean } from '/@/utils/is';
a1ffb6 7
d9b196 8 import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
81baf1 9 import { useModalContext } from '/@/components/Modal';
116a1f 10 import { useDebounce } from '/@/hooks/core/useDebounce';
V 11 import type { BasicColumn } from '/@/components/Table';
faf3f4 12
354904 13 export function useTableScroll(
V 14   propsRef: ComputedRef<BasicTableProps>,
116a1f 15   tableElRef: Ref<ComponentRef>,
V 16   columnsRef: ComputedRef<BasicColumn[]>,
17   rowSelectionRef: ComputedRef<TableRowSelection<any> | null>
354904 18 ) {
V 19   const tableHeightRef: Ref<Nullable<number>> = ref(null);
9abf17 20
81baf1 21   const modalFn = useModalContext();
116a1f 22
V 23   // const [debounceCalcTableHeight] = useDebounce(calcTableHeight, 80);
24   const [debounceRedoHeight] = useDebounce(redoHeight, 250);
faf3f4 25
354904 26   const getCanResize = computed(() => {
V 27     const { canResize, scroll } = unref(propsRef);
28     return canResize && !(scroll || {}).y;
29   });
30
da76f3 31   watch(
V 32     () => unref(getCanResize),
33     () => {
34       debounceRedoHeight();
35     },
36     {
37       immediate: true,
38     }
39   );
9abf17 40
faf3f4 41   function redoHeight() {
354904 42     if (unref(getCanResize)) {
V 43       nextTick(() => {
44         calcTableHeight();
45       });
46     }
116a1f 47   }
V 48
49   function setHeight(heigh: number) {
50     tableHeightRef.value = heigh;
51     //  Solve the problem of modal adaptive height calculation when the form is placed in the modal
52     modalFn?.redoModalHeight?.();
faf3f4 53   }
54
354904 55   // No need to repeat queries
a1ffb6 56   let paginationEl: HTMLElement | null;
V 57   let footerEl: HTMLElement | null;
354904 58
a1ffb6 59   async function calcTableHeight() {
354904 60     const { resizeHeightOffset, pagination, maxHeight } = unref(propsRef);
V 61     if (!unref(getCanResize)) return;
9abf17 62
faf3f4 63     await nextTick();
354904 64     const table = unref(tableElRef);
9abf17 65     if (!table) return;
faf3f4 66
67     const tableEl: Element = table.$el;
9abf17 68     if (!tableEl) return;
354904 69
a1ffb6 70     const headEl = tableEl.querySelector('.ant-table-thead ');
V 71     if (!headEl) return;
9abf17 72
354904 73     // Table height from bottom
a1ffb6 74     const { bottomIncludeBody } = getViewportOffset(headEl);
354904 75     // Table height from bottom height-custom offset
faf3f4 76
77     const paddingHeight = 32;
78     const borderHeight = 2 * 2;
354904 79     // Pager height
a1ffb6 80     let paginationHeight = 2;
V 81     if (!isBoolean(pagination)) {
82       if (!paginationEl) {
83         paginationEl = tableEl.querySelector('.ant-pagination') as HTMLElement;
84       }
85       if (paginationEl) {
86         const offsetHeight = paginationEl.offsetHeight;
87         paginationHeight += offsetHeight || 0;
88       } else {
354904 89         // TODO First fix 24
a1ffb6 90         paginationHeight += 24;
V 91       }
92     }
faf3f4 93
94     let footerHeight = 0;
95     if (!isBoolean(pagination)) {
a1ffb6 96       if (!footerEl) {
V 97         footerEl = tableEl.querySelector('.ant-table-footer') as HTMLElement;
98       } else {
faf3f4 99         const offsetHeight = footerEl.offsetHeight;
100         footerHeight += offsetHeight || 0;
101       }
102     }
354904 103
faf3f4 104     let headerHeight = 0;
a1ffb6 105     if (headEl) {
V 106       headerHeight = (headEl as HTMLElement).offsetHeight;
faf3f4 107     }
354904 108
116a1f 109     let height =
faf3f4 110       bottomIncludeBody -
111       (resizeHeightOffset || 0) -
112       paddingHeight -
113       borderHeight -
114       paginationHeight -
115       footerHeight -
116       headerHeight;
a1ffb6 117
116a1f 118     height = (height > maxHeight! ? (maxHeight as number) : height) ?? height;
V 119     setHeight(height);
faf3f4 120   }
121
116a1f 122   useWindowSizeFn(calcTableHeight, 200);
V 123
124   const getScrollX = computed(() => {
125     let width = 0;
126     if (unref(rowSelectionRef)) {
127       width += 60;
128     }
129
c96002 130     // TODO props ?? 0;
116a1f 131     const NORMAL_WIDTH = 150;
V 132
c96002 133     const columns = unref(columnsRef).filter((item) => !item.defaultHidden);
116a1f 134     columns.forEach((item) => {
V 135       width += Number.parseInt(item.width as string) || 0;
136     });
137     const unsetWidthColumns = columns.filter((item) => !Reflect.has(item, 'width'));
138
139     const len = unsetWidthColumns.length;
140     if (len !== 0) {
141       width += len * NORMAL_WIDTH;
142     }
9c2f3f 143
V 144     const table = unref(tableElRef);
145     const tableWidth = table?.$el?.offsetWidth ?? 0;
cdf0a6 146     return tableWidth > width ? '100%' : width;
116a1f 147   });
faf3f4 148
149   const getScrollRef = computed(() => {
150     const tableHeight = unref(tableHeightRef);
151     const { canResize, scroll } = unref(propsRef);
152     return {
116a1f 153       x: unref(getScrollX),
faf3f4 154       y: canResize ? tableHeight : null,
155       scrollToFirstRowOnChange: false,
156       ...scroll,
157     };
158   });
354904 159
faf3f4 160   return { getScrollRef, redoHeight };
161 }