123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- import type { BasicTableProps, TableRowSelection, BasicColumn } from '../types/table';
- import { Ref, ComputedRef, ref } from 'vue';
- import { computed, unref, nextTick, watch } from 'vue';
- import { getViewportOffset } from '/@/utils/domUtils';
- import { isBoolean } from '/@/utils/is';
- import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn';
- import { useModalContext } from '/@/components/Modal';
- import { onMountedOrActivated } from '/@/hooks/core/onMountedOrActivated';
- import { useDebounceFn } from '@vueuse/core';
- export function useTableScroll(
- propsRef: ComputedRef<BasicTableProps>,
- tableElRef: Ref<ComponentRef>,
- columnsRef: ComputedRef<BasicColumn[]>,
- rowSelectionRef: ComputedRef<TableRowSelection | null>,
- getDataSourceRef: ComputedRef<Recordable[]>,
- wrapRef: Ref<HTMLElement | null>,
- formRef: Ref<ComponentRef>,
- ) {
- const tableHeightRef: Ref<Nullable<number | string>> = ref(167);
- const modalFn = useModalContext();
- // Greater than animation time 280
- const debounceRedoHeight = useDebounceFn(redoHeight, 100);
- const getCanResize = computed(() => {
- const { canResize, scroll } = unref(propsRef);
- return canResize && !(scroll || {}).y;
- });
- watch(
- () => [unref(getCanResize), unref(getDataSourceRef)?.length],
- () => {
- debounceRedoHeight();
- },
- {
- flush: 'post',
- },
- );
- function redoHeight() {
- nextTick(() => {
- calcTableHeight();
- });
- }
- function setHeight(height: number) {
- tableHeightRef.value = height;
- // Solve the problem of modal adaptive height calculation when the form is placed in the modal
- modalFn?.redoModalHeight?.();
- }
- // No need to repeat queries
- let paginationEl: HTMLElement | null;
- let footerEl: HTMLElement | null;
- let bodyEl: HTMLElement | null;
- async function calcTableHeight() {
- const { resizeHeightOffset, pagination, maxHeight, isCanResizeParent, useSearchForm } =
- unref(propsRef);
- const tableData = unref(getDataSourceRef);
- const table = unref(tableElRef);
- if (!table) return;
- const tableEl: Element = table.$el;
- if (!tableEl) return;
- if (!bodyEl) {
- bodyEl = tableEl.querySelector('.ant-table-body');
- if (!bodyEl) return;
- }
- const hasScrollBarY = bodyEl.scrollHeight > bodyEl.clientHeight;
- const hasScrollBarX = bodyEl.scrollWidth > bodyEl.clientWidth;
- if (hasScrollBarY) {
- tableEl.classList.contains('hide-scrollbar-y') &&
- tableEl.classList.remove('hide-scrollbar-y');
- } else {
- !tableEl.classList.contains('hide-scrollbar-y') && tableEl.classList.add('hide-scrollbar-y');
- }
- if (hasScrollBarX) {
- tableEl.classList.contains('hide-scrollbar-x') &&
- tableEl.classList.remove('hide-scrollbar-x');
- } else {
- !tableEl.classList.contains('hide-scrollbar-x') && tableEl.classList.add('hide-scrollbar-x');
- }
- bodyEl!.style.height = 'unset';
- if (!unref(getCanResize) || !unref(tableData) || tableData.length === 0) return;
- await nextTick();
- // Add a delay to get the correct bottomIncludeBody paginationHeight footerHeight headerHeight
- const headEl = tableEl.querySelector('.ant-table-thead ');
- if (!headEl) return;
- // Table height from bottom height-custom offset
- let paddingHeight = 32;
- // Pager height
- let paginationHeight = 2;
- if (!isBoolean(pagination)) {
- paginationEl = tableEl.querySelector('.ant-pagination') as HTMLElement;
- if (paginationEl) {
- const offsetHeight = paginationEl.offsetHeight;
- paginationHeight += offsetHeight || 0;
- } else {
- // TODO First fix 24
- paginationHeight += 24;
- }
- } else {
- paginationHeight = -8;
- }
- let footerHeight = 0;
- if (!isBoolean(pagination)) {
- if (!footerEl) {
- footerEl = tableEl.querySelector('.ant-table-footer') as HTMLElement;
- } else {
- const offsetHeight = footerEl.offsetHeight;
- footerHeight += offsetHeight || 0;
- }
- }
- let headerHeight = 0;
- if (headEl) {
- headerHeight = (headEl as HTMLElement).offsetHeight;
- }
- let bottomIncludeBody = 0;
- if (unref(wrapRef) && isCanResizeParent) {
- const tablePadding = 12;
- const formMargin = 16;
- let paginationMargin = 10;
- const wrapHeight = unref(wrapRef)?.offsetHeight ?? 0;
- let formHeight = unref(formRef)?.$el.offsetHeight ?? 0;
- if (formHeight) {
- formHeight += formMargin;
- }
- if (isBoolean(pagination) && !pagination) {
- paginationMargin = 0;
- }
- if (isBoolean(useSearchForm) && !useSearchForm) {
- paddingHeight = 0;
- }
- const headerCellHeight =
- (tableEl.querySelector('.ant-table-title') as HTMLElement)?.offsetHeight ?? 0;
- console.log(wrapHeight - formHeight - headerCellHeight - tablePadding - paginationMargin);
- bottomIncludeBody =
- wrapHeight - formHeight - headerCellHeight - tablePadding - paginationMargin;
- } else {
- // Table height from bottom
- bottomIncludeBody = getViewportOffset(headEl).bottomIncludeBody;
- }
- let height =
- bottomIncludeBody -
- (resizeHeightOffset || 0) -
- paddingHeight -
- paginationHeight -
- footerHeight -
- headerHeight;
- height = (height > maxHeight! ? (maxHeight as number) : height) ?? height;
- setHeight(height);
- bodyEl!.style.height = `${height}px`;
- }
- useWindowSizeFn(calcTableHeight, 280);
- onMountedOrActivated(() => {
- calcTableHeight();
- nextTick(() => {
- debounceRedoHeight();
- });
- });
- const getScrollX = computed(() => {
- let width = 0;
- if (unref(rowSelectionRef)) {
- width += 60;
- }
- // TODO props ?? 0;
- const NORMAL_WIDTH = 150;
- const columns = unref(columnsRef).filter((item) => !item.defaultHidden);
- columns.forEach((item) => {
- width += Number.parseInt(item.width as string) || 0;
- });
- const unsetWidthColumns = columns.filter((item) => !Reflect.has(item, 'width'));
- const len = unsetWidthColumns.length;
- if (len !== 0) {
- width += len * NORMAL_WIDTH;
- }
- const table = unref(tableElRef);
- const tableWidth = table?.$el?.offsetWidth ?? 0;
- return tableWidth > width ? '100%' : width;
- });
- const getScrollRef = computed(() => {
- const tableHeight = unref(tableHeightRef);
- const { canResize, scroll } = unref(propsRef);
- return {
- x: unref(getScrollX),
- y: canResize ? tableHeight : null,
- scrollToFirstRowOnChange: false,
- ...scroll,
- };
- });
- return { getScrollRef, redoHeight };
- }
|