import { computed, type CSSProperties, ref } from 'vue' import { onUnload } from '@dcloudio/uni-app' type KeyboardHeightChangeResult = { height?: number } type KeyboardHeightChangeCallback = (result: KeyboardHeightChangeResult) => void type MiniProgramKeyboardApi = { onKeyboardHeightChange?: (callback: KeyboardHeightChangeCallback) => void offKeyboardHeightChange?: (callback: KeyboardHeightChangeCallback) => void } type MiniProgramWindowInfo = UniApp.GetWindowInfoResult & { safeAreaInsets?: { bottom?: number } safeArea?: { bottom?: number } } const FOOTER_TOP_PADDING_RPX = 20 const FOOTER_BOTTOM_PADDING_RPX = 20 const FOOTER_BUTTON_HEIGHT_RPX = 88 const CONTENT_EXTRA_BOTTOM_RPX = 24 export const useTaskFormSafeArea = () => { const keyboardApi = uni as unknown as MiniProgramKeyboardApi const windowWidth = ref(375) const safeAreaBottom = ref(0) const keyboardHeight = ref(0) let keyboardListenerRegistered = false const rpxToPx = (rpx: number) => { return (windowWidth.value / 750) * rpx } const activeSafeAreaBottom = computed(() => { return keyboardHeight.value > 0 ? 0 : safeAreaBottom.value }) const keyboardVisible = computed(() => keyboardHeight.value > 0) const footerHeightPx = computed(() => { return ( rpxToPx(FOOTER_TOP_PADDING_RPX + FOOTER_BUTTON_HEIGHT_RPX + FOOTER_BOTTOM_PADDING_RPX) + activeSafeAreaBottom.value ) }) const contentStyle = computed(() => { const paddingBottom = footerHeightPx.value + keyboardHeight.value + rpxToPx(CONTENT_EXTRA_BOTTOM_RPX) return { paddingBottom: `${paddingBottom}px`, } }) const footerStyle = computed(() => { return { bottom: `${keyboardHeight.value}px`, paddingBottom: `${rpxToPx(FOOTER_BOTTOM_PADDING_RPX) + activeSafeAreaBottom.value}px`, } }) const initSystemLayout = () => { const windowInfo = uni.getWindowInfo() as MiniProgramWindowInfo windowWidth.value = windowInfo.windowWidth || 375 if (typeof windowInfo.safeAreaInsets?.bottom === 'number') { safeAreaBottom.value = windowInfo.safeAreaInsets.bottom return } if ( typeof windowInfo.safeArea?.bottom === 'number' && typeof windowInfo.screenHeight === 'number' ) { safeAreaBottom.value = Math.max(windowInfo.screenHeight - windowInfo.safeArea.bottom, 0) return } safeAreaBottom.value = 0 } const handleKeyboardHeightChange: KeyboardHeightChangeCallback = (result) => { const height = Number(result.height ?? 0) keyboardHeight.value = Number.isFinite(height) && height > 0 ? height : 0 } const initSafeArea = () => { initSystemLayout() if ( keyboardListenerRegistered || !keyboardApi.onKeyboardHeightChange || !keyboardApi.offKeyboardHeightChange ) { return } keyboardApi.onKeyboardHeightChange(handleKeyboardHeightChange) keyboardListenerRegistered = true } const disposeSafeArea = () => { if (!keyboardListenerRegistered) { return } keyboardApi.offKeyboardHeightChange?.(handleKeyboardHeightChange) keyboardListenerRegistered = false keyboardHeight.value = 0 } onUnload(disposeSafeArea) return { contentStyle, footerStyle, keyboardVisible, initSafeArea, } }