import { ref, onMounted, onUnmounted } from 'vue' import { onResize } from '@dcloudio/uni-app' export type PageLayout = { pageStyle: () => string, contentStyle: (offset: number, minimum: boolean) => string, statusStyle: (offset: number) => string, bottomStyle: (padding: number) => string } // 原生渲染不支持 vh/calc,统一以窗口尺寸计算,并随旋转更新。 export function usePageLayout(): PageLayout { const windowInfo = ref(uni.getWindowInfo()) const refresh = () => { windowInfo.value = uni.getWindowInfo() } onMounted(() => refresh()) // #ifdef APP onResize((_options) => { refresh() }) // #endif // #ifndef APP const handleResize = (_options: OnWindowResizeCallbackResult) => { refresh() } uni.onWindowResize(handleResize) onUnmounted(() => { uni.offWindowResize(handleResize) }) // #endif const rpx = (value: number): number => value * windowInfo.value.windowWidth / 750 const status = (): number => windowInfo.value.statusBarHeight ?? 0 const pageStyle = (): string => 'min-height:' + windowInfo.value.windowHeight + 'px;' const contentStyle = (offset: number, minimum: boolean): string => { // #ifdef WEB return (minimum ? 'min-height:' : 'height:') + 'calc(100vh - ' + status() + 'px - ' + offset + 'rpx);' // #endif // #ifndef WEB const height = Math.max(0, windowInfo.value.windowHeight - status() - rpx(offset)) return (minimum ? 'min-height:' : 'height:') + height + 'px;' // #endif } const statusStyle = (offset: number): string => 'height:' + (status() + rpx(offset)) + 'px;' const bottomStyle = (padding: number): string => 'padding-bottom:' + (rpx(padding) + (windowInfo.value.safeAreaInsets?.bottom ?? 0)) + 'px;' return { pageStyle, contentStyle, statusStyle, bottomStyle } }