Commit dd158a17fe1c512a333fe19f0665d35bf5bac93e

Authored by lzdjack
Committed by GitHub
1 parent c8d59a0b

feat: 添加table继承父元素高度的功能 (#1523)

在保证了原有的高度计算上,额外新增继承父级高度, 只需设置isCanResizeParent:true
src/components/Table/src/BasicTable.vue
1 1 <template>
2 2 <div ref="wrapRef" :class="getWrapperClass">
3 3 <BasicForm
  4 + ref="formRef"
4 5 submitOnReset
5 6 v-bind="getFormProps"
6 7 v-if="getBindValues.useSearchForm"
... ... @@ -25,7 +26,7 @@
25 26 <slot :name="item" v-bind="data || {}"></slot>
26 27 </template>
27 28  
28   - <template #[`header-${column.dataIndex}`] v-for="column in columns" :key="column.dataIndex">
  29 + <template #[`header-${column.dataIndex}`] v-for="(column, index) in columns" :key="index">
29 30 <HeaderCell :column="column" />
30 31 </template>
31 32 </Table>
... ... @@ -97,6 +98,7 @@
97 98 const tableData = ref<Recordable[]>([]);
98 99  
99 100 const wrapRef = ref(null);
  101 + const formRef = ref(null);
100 102 const innerPropsRef = ref<Partial<BasicTableProps>>();
101 103  
102 104 const { prefixCls } = useDesign('basic-table');
... ... @@ -185,6 +187,8 @@
185 187 getColumnsRef,
186 188 getRowSelectionRef,
187 189 getDataSourceRef,
  190 + wrapRef,
  191 + formRef,
188 192 );
189 193  
190 194 const { scrollTo } = useTableScrollTo(tableElRef, getDataSourceRef);
... ... @@ -318,6 +322,7 @@
318 322 emit('register', tableAction, formActions);
319 323  
320 324 return {
  325 + formRef,
321 326 tableElRef,
322 327 getBindValues,
323 328 getLoading,
... ... @@ -352,6 +357,7 @@
352 357  
353 358 .@{prefix-cls} {
354 359 max-width: 100%;
  360 + height: 100%;
355 361  
356 362 &-row__striped {
357 363 td {
... ...
src/components/Table/src/hooks/useTableScroll.ts
1 1 import type { BasicTableProps, TableRowSelection, BasicColumn } from '../types/table';
2   -import type { Ref, ComputedRef } from 'vue';
  2 +import { Ref, ComputedRef, ref } from 'vue';
3 3 import { computed, unref, nextTick, watch } from 'vue';
4 4 import { getViewportOffset } from '/@/utils/domUtils';
5 5 import { isBoolean } from '/@/utils/is';
... ... @@ -14,7 +14,10 @@ export function useTableScroll(
14 14 columnsRef: ComputedRef<BasicColumn[]>,
15 15 rowSelectionRef: ComputedRef<TableRowSelection | null>,
16 16 getDataSourceRef: ComputedRef<Recordable[]>,
  17 + wrapRef: Ref<HTMLElement | null>,
  18 + formRef: Ref<ComponentRef>,
17 19 ) {
  20 + const tableHeightRef: Ref<Nullable<number | string>> = ref(167);
18 21 const modalFn = useModalContext();
19 22  
20 23 // Greater than animation time 280
... ... @@ -41,7 +44,8 @@ export function useTableScroll(
41 44 });
42 45 }
43 46  
44   - function setHeight() {
  47 + function setHeight(height: number) {
  48 + tableHeightRef.value = height;
45 49 // Solve the problem of modal adaptive height calculation when the form is placed in the modal
46 50 modalFn?.redoModalHeight?.();
47 51 }
... ... @@ -52,7 +56,8 @@ export function useTableScroll(
52 56 let bodyEl: HTMLElement | null;
53 57  
54 58 async function calcTableHeight() {
55   - const { resizeHeightOffset, pagination, maxHeight } = unref(propsRef);
  59 + const { resizeHeightOffset, pagination, maxHeight, isCanResizeParent, useSearchForm } =
  60 + unref(propsRef);
56 61 const tableData = unref(getDataSourceRef);
57 62  
58 63 const table = unref(tableElRef);
... ... @@ -94,11 +99,8 @@ export function useTableScroll(
94 99  
95 100 if (!headEl) return;
96 101  
97   - // Table height from bottom
98   - const { bottomIncludeBody } = getViewportOffset(headEl);
99 102 // Table height from bottom height-custom offset
100   -
101   - const paddingHeight = 32;
  103 + let paddingHeight = 32;
102 104 // Pager height
103 105 let paginationHeight = 2;
104 106 if (!isBoolean(pagination)) {
... ... @@ -129,6 +131,35 @@ export function useTableScroll(
129 131 headerHeight = (headEl as HTMLElement).offsetHeight;
130 132 }
131 133  
  134 + let bottomIncludeBody = 0;
  135 + if (unref(wrapRef) && isCanResizeParent) {
  136 + const tablePadding = 12;
  137 + const formMargin = 16;
  138 + let paginationMargin = 10;
  139 + const wrapHeight = unref(wrapRef)?.offsetHeight ?? 0;
  140 +
  141 + let formHeight = unref(formRef)?.$el.offsetHeight ?? 0;
  142 + if (formHeight) {
  143 + formHeight += formMargin;
  144 + }
  145 + if (isBoolean(pagination) && !pagination) {
  146 + paginationMargin = 0;
  147 + }
  148 + if (isBoolean(useSearchForm) && !useSearchForm) {
  149 + paddingHeight = 0;
  150 + }
  151 +
  152 + const headerCellHeight =
  153 + (tableEl.querySelector('.ant-table-title') as HTMLElement)?.offsetHeight ?? 0;
  154 +
  155 + console.log(wrapHeight - formHeight - headerCellHeight - tablePadding - paginationMargin);
  156 + bottomIncludeBody =
  157 + wrapHeight - formHeight - headerCellHeight - tablePadding - paginationMargin;
  158 + } else {
  159 + // Table height from bottom
  160 + bottomIncludeBody = getViewportOffset(headEl).bottomIncludeBody;
  161 + }
  162 +
132 163 let height =
133 164 bottomIncludeBody -
134 165 (resizeHeightOffset || 0) -
... ... @@ -136,9 +167,8 @@ export function useTableScroll(
136 167 paginationHeight -
137 168 footerHeight -
138 169 headerHeight;
139   -
140 170 height = (height > maxHeight! ? (maxHeight as number) : height) ?? height;
141   - setHeight();
  171 + setHeight(height);
142 172  
143 173 bodyEl!.style.height = `${height}px`;
144 174 }
... ... @@ -176,10 +206,11 @@ export function useTableScroll(
176 206 });
177 207  
178 208 const getScrollRef = computed(() => {
  209 + const tableHeight = unref(tableHeightRef);
179 210 const { canResize, scroll } = unref(propsRef);
180 211 return {
181 212 x: unref(getScrollX),
182   - y: canResize ? '100%' : null,
  213 + y: canResize ? tableHeight : null,
183 214 scrollToFirstRowOnChange: false,
184 215 ...scroll,
185 216 };
... ...
src/components/Table/src/props.ts
... ... @@ -97,6 +97,7 @@ export const basicProps = {
97 97 default: null,
98 98 },
99 99 ellipsis: { type: Boolean, default: true },
  100 + isCanResizeParent: { type: Boolean, default: false },
100 101 canResize: { type: Boolean, default: true },
101 102 clearSelectOnPageChange: propTypes.bool,
102 103 resizeHeightOffset: propTypes.number.def(0),
... ...
src/components/Table/src/types/table.ts
... ... @@ -191,6 +191,8 @@ export interface BasicTableProps&lt;T = any&gt; {
191 191 actionColumn?: BasicColumn;
192 192 // 文本超过宽度是否显示。。。
193 193 ellipsis?: boolean;
  194 + // 是否继承父级高度(父级高度-表单高度-padding高度)
  195 + isCanResizeParent?: boolean;
194 196 // 是否可以自适应高度
195 197 canResize?: boolean;
196 198 // 自适应高度偏移, 计算结果-偏移量
... ...
src/locales/lang/en/routes/demo.ts
... ... @@ -195,5 +195,6 @@ export default {
195 195 editCellTable: 'Editable cell',
196 196 editRowTable: 'Editable row',
197 197 authColumn: 'Auth column',
  198 + resizeParentHeightTable: 'resizeParentHeightTable',
198 199 },
199 200 };
... ...
src/locales/lang/zh-CN/routes/demo.ts
... ... @@ -186,5 +186,6 @@ export default {
186 186 editCellTable: '可编辑单元格',
187 187 editRowTable: '可编辑行',
188 188 authColumn: '权限列',
  189 + resizeParentHeightTable: '继承父元素高度',
189 190 },
190 191 };
... ...
src/router/routes/modules/demo/comp.ts
... ... @@ -239,6 +239,14 @@ const comp: AppRouteModule = {
239 239 title: t('routes.demo.table.authColumn'),
240 240 },
241 241 },
  242 + {
  243 + path: 'resizeParentHeightTable',
  244 + name: 'ResizeParentHeightTable',
  245 + component: () => import('/@/views/demo/table/ResizeParentHeightTable.vue'),
  246 + meta: {
  247 + title: t('routes.demo.table.resizeParentHeightTable'),
  248 + },
  249 + },
242 250 ],
243 251 },
244 252 {
... ...
src/views/demo/table/ResizeParentHeightTable.vue 0 → 100644
  1 +<template>
  2 + <div class="h-full flex p-4">
  3 + <div class="flex flex-col pr-4 w-1/2">
  4 + <div class="flex-1">
  5 + <BasicTable @register="registerTable" />
  6 + </div>
  7 + <div class="h-4"></div>
  8 + <div class="flex-1">
  9 + <BasicTable @register="registerTable" />
  10 + </div>
  11 + </div>
  12 + <div class="flex-1 flex flex-col w-1/2 h-full">
  13 + <div class="h-1/3 mb-4">
  14 + <BasicTable @register="registerTable" />
  15 + </div>
  16 + <div class="h-1/3 mb-4">
  17 + <BasicTable @register="registerTable2" />
  18 + </div>
  19 + <div class="h-1/3">
  20 + <BasicTable @register="registerTable1" />
  21 + </div>
  22 + </div>
  23 + </div>
  24 +</template>
  25 +<script lang="ts">
  26 + import { defineComponent } from 'vue';
  27 + import { BasicTable, useTable } from '/@/components/Table';
  28 + import { getBasicColumns, getFormConfig } from './tableData';
  29 +
  30 + import { demoListApi } from '/@/api/demo/table';
  31 +
  32 + export default defineComponent({
  33 + components: { BasicTable },
  34 + setup(_) {
  35 + const [registerTable] = useTable({
  36 + api: demoListApi,
  37 + columns: getBasicColumns(),
  38 + useSearchForm: false,
  39 + formConfig: getFormConfig(),
  40 + showTableSetting: false,
  41 + tableSetting: { fullScreen: true },
  42 + showIndexColumn: false,
  43 + isCanResizeParent: true,
  44 + rowKey: 'id',
  45 + });
  46 +
  47 + const [registerTable1] = useTable({
  48 + api: demoListApi,
  49 + columns: getBasicColumns(),
  50 + formConfig: getFormConfig(),
  51 + showTableSetting: false,
  52 + tableSetting: { fullScreen: true },
  53 + showIndexColumn: false,
  54 + isCanResizeParent: true,
  55 + useSearchForm: false,
  56 + rowKey: 'id',
  57 + });
  58 +
  59 + const [registerTable2] = useTable({
  60 + api: demoListApi,
  61 + columns: getBasicColumns(),
  62 + formConfig: getFormConfig(),
  63 + showTableSetting: false,
  64 + tableSetting: { fullScreen: true },
  65 + showIndexColumn: false,
  66 + isCanResizeParent: true,
  67 + useSearchForm: false,
  68 + pagination: false,
  69 + rowKey: 'id',
  70 + });
  71 +
  72 + return {
  73 + registerTable,
  74 + registerTable1,
  75 + registerTable2,
  76 + };
  77 + },
  78 + });
  79 +</script>
... ...