1- import { ComputedRef , nextTick , Ref , ref , unref , watch } from 'vue' ;
1+ import { ComputedRef , isRef , nextTick , Ref , ref , unref , watch } from 'vue' ;
22import { onMountedOrActivated } from '/@/hooks/core/onMountedOrActivated' ;
33import { useWindowSizeFn } from '/@/hooks/event/useWindowSizeFn' ;
44import { useLayoutHeight } from '/@/layouts/default/content/useContentViewHeight' ;
55import { getViewportOffset } from '/@/utils/domUtils' ;
6+ import { isNumber , isString } from '/@/utils/is' ;
67
78export interface CompensationHeight {
89 // 使用 layout Footer 高度作为判断补偿高度的条件
@@ -11,6 +12,8 @@ export interface CompensationHeight {
1112 elements ?: Ref [ ] ;
1213}
1314
15+ type Upward = number | string | null | undefined ;
16+
1417/**
1518 * 动态计算内容高度,根据锚点dom最下坐标到屏幕最下坐标,根据传入dom的高度、padding、margin等值进行动态计算
1619 * 最终获取合适的内容高度
@@ -20,13 +23,15 @@ export interface CompensationHeight {
2023 * @param subtractHeightRefs 待减去高度的组件列表 Ref<ElRef | ComponentRef>
2124 * @param substractSpaceRefs 待减去空闲空间(margins/paddings)的组件列表 Ref<ElRef | ComponentRef>
2225 * @param offsetHeightRef 计算偏移的响应式高度,计算高度时将直接减去此值
26+ * @param upwardSpace 向上递归减去空闲空间的 层级 或 直到指定class为止 数值为2代表向上递归两次|数值为ant-layout表示向上递归直到碰见.ant-layout为止
2327 * @returns 响应式高度
2428 */
2529export function useContentHeight (
2630 flag : ComputedRef < Boolean > ,
2731 anchorRef : Ref ,
2832 subtractHeightRefs : Ref [ ] ,
2933 substractSpaceRefs : Ref [ ] ,
34+ upwardSpace : Ref < Upward > | ComputedRef < Upward > | Upward = 0 ,
3035 offsetHeightRef : Ref < number > = ref ( 0 ) ,
3136) {
3237 const contentHeight : Ref < Nullable < number > > = ref ( null ) ;
@@ -45,23 +50,33 @@ export function useContentHeight(
4550 } ) ;
4651 }
4752
48- function calcSubtractSpace ( element : HTMLDivElement | null | undefined ) : number {
53+ function calcSubtractSpace (
54+ element : Element | null | undefined ,
55+ direction : 'all' | 'top' | 'bottom' = 'all' ,
56+ ) : number {
57+ function numberPx ( px : string ) {
58+ return Number ( px . replace ( / [ ^ \d ] / g, '' ) ) ;
59+ }
4960 let subtractHeight = 0 ;
5061 const ZERO_PX = '0px' ;
51- let marginBottom = ZERO_PX ;
52- let marginTop = ZERO_PX ;
5362 if ( element ) {
5463 const cssStyle = getComputedStyle ( element ) ;
55- marginBottom = cssStyle ?. marginBottom ?? ZERO_PX ;
56- marginTop = cssStyle ?. marginTop ?? ZERO_PX ;
57- }
58- if ( marginBottom ) {
59- const contentMarginBottom = Number ( marginBottom . replace ( / [ ^ \d ] / g, '' ) ) ;
60- subtractHeight += contentMarginBottom ;
61- }
62- if ( marginTop ) {
63- const contentMarginTop = Number ( marginTop . replace ( / [ ^ \d ] / g, '' ) ) ;
64- subtractHeight += contentMarginTop ;
64+ const marginTop = numberPx ( cssStyle ?. marginTop ?? ZERO_PX ) ;
65+ const marginBottom = numberPx ( cssStyle ?. marginBottom ?? ZERO_PX ) ;
66+ const paddingTop = numberPx ( cssStyle ?. paddingTop ?? ZERO_PX ) ;
67+ const paddingBottom = numberPx ( cssStyle ?. paddingBottom ?? ZERO_PX ) ;
68+ if ( direction === 'all' ) {
69+ subtractHeight += marginTop ;
70+ subtractHeight += marginBottom ;
71+ subtractHeight += paddingTop ;
72+ subtractHeight += paddingBottom ;
73+ } else if ( direction === 'top' ) {
74+ subtractHeight += marginTop ;
75+ subtractHeight += paddingTop ;
76+ } else {
77+ subtractHeight += marginBottom ;
78+ subtractHeight += paddingBottom ;
79+ }
6580 }
6681 return subtractHeight ;
6782 }
@@ -80,11 +95,11 @@ export function useContentHeight(
8095 // Add a delay to get the correct height
8196 await nextTick ( ) ;
8297
83- const wrapperEl = getEl ( unref ( anchorRef ) ) ;
84- if ( ! wrapperEl ) {
98+ const anchorEl = getEl ( unref ( anchorRef ) ) ;
99+ if ( ! anchorEl ) {
85100 return ;
86101 }
87- const { bottomIncludeBody } = getViewportOffset ( wrapperEl ) ;
102+ const { bottomIncludeBody } = getViewportOffset ( anchorEl ) ;
88103
89104 // substract elements height
90105 let substractHeight = 0 ;
@@ -93,17 +108,46 @@ export function useContentHeight(
93108 } ) ;
94109
95110 // subtract margins / paddings
96- let substractSpaceHeight = 0 ;
111+ let substractSpaceHeight = calcSubtractSpace ( anchorEl ) ?? 0 ;
97112 substractSpaceRefs . forEach ( ( item ) => {
98113 substractSpaceHeight += calcSubtractSpace ( getEl ( unref ( item ) ) ) ;
99114 } ) ;
100115
116+ // upwardSpace
117+ let upwardSpaceHeight = 0 ;
118+ function upward ( element : Element | null , upwardLvlOrClass : number | string | null | undefined ) {
119+ if ( element && upwardLvlOrClass ) {
120+ const parent = element . parentElement ;
121+ if ( parent ) {
122+ if ( isString ( upwardLvlOrClass ) ) {
123+ if ( ! parent . classList . contains ( upwardLvlOrClass ) ) {
124+ upwardSpaceHeight += calcSubtractSpace ( parent , 'bottom' ) ;
125+ upward ( parent , upwardLvlOrClass ) ;
126+ } else {
127+ upwardSpaceHeight += calcSubtractSpace ( parent , 'bottom' ) ;
128+ }
129+ } else if ( isNumber ( upwardLvlOrClass ) ) {
130+ if ( upwardLvlOrClass > 0 ) {
131+ upwardSpaceHeight += calcSubtractSpace ( parent , 'bottom' ) ;
132+ upward ( parent , -- upwardLvlOrClass ) ;
133+ }
134+ }
135+ }
136+ }
137+ }
138+ if ( isRef ( upwardSpace ) ) {
139+ upward ( anchorEl , unref ( upwardSpace ) ) ;
140+ } else {
141+ upward ( anchorEl , upwardSpace ) ;
142+ }
143+
101144 let height =
102145 bottomIncludeBody -
103146 unref ( layoutFooterHeightRef ) -
104147 unref ( offsetHeightRef ) -
105148 substractHeight -
106- substractSpaceHeight ;
149+ substractSpaceHeight -
150+ upwardSpaceHeight ;
107151
108152 // compensation height
109153 const calcCompensationHeight = ( ) => {
0 commit comments