Commit dd158a17fe1c512a333fe19f0665d35bf5bac93e
Committed by
GitHub
1 parent
c8d59a0b
feat: 添加table继承父元素高度的功能 (#1523)
在保证了原有的高度计算上,额外新增继承父级高度, 只需设置isCanResizeParent:true
Showing
8 changed files
with
140 additions
and
11 deletions
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<T = any> { |
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
src/locales/lang/zh-CN/routes/demo.ts
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> | ... | ... |