From fc14051073ebaf0035fc1971e915af08df735c9f Mon Sep 17 00:00:00 2001 From: Peanut Date: Sun, 24 May 2026 18:39:28 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=B0=8F=E7=A8=8B=E5=BA=8F=E8=8F=9C?= =?UTF-8?q?=E5=8D=95=E6=8C=89=E9=92=AE=E5=AE=89=E5=85=A8=E5=8C=BA=E5=9F=9F?= =?UTF-8?q?=E9=80=82=E9=85=8D=E5=B7=A5=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.7 --- .../src/composables/useMenuButtonSafeArea.js | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 mini-program/src/composables/useMenuButtonSafeArea.js diff --git a/mini-program/src/composables/useMenuButtonSafeArea.js b/mini-program/src/composables/useMenuButtonSafeArea.js new file mode 100644 index 0000000..8f89afd --- /dev/null +++ b/mini-program/src/composables/useMenuButtonSafeArea.js @@ -0,0 +1,62 @@ +import { computed, ref } from 'vue' + +export const useMenuButtonSafeArea = ({ extraRightRpx = 20, extraTopPx = 8 } = {}) => { + const windowWidth = ref(uni.getStorageSync('windowWidth') || 375) + const safeAreaTop = ref(uni.getStorageSync('safeAreaTop') || 20) + const menuButton = ref(uni.getStorageSync('menuButtonRect') || null) + + const readSafeArea = () => { + try { + const windowInfo = uni.getWindowInfo ? uni.getWindowInfo() : uni.getSystemInfoSync() + windowWidth.value = windowInfo.windowWidth || windowWidth.value + safeAreaTop.value = windowInfo.safeAreaInsets?.top || windowInfo.statusBarHeight || safeAreaTop.value + if (uni.getMenuButtonBoundingClientRect) { + menuButton.value = uni.getMenuButtonBoundingClientRect() + } + } catch (error) { + menuButton.value = uni.getStorageSync('menuButtonRect') || menuButton.value + } + } + + readSafeArea() + + const pxToRpx = (px) => Math.ceil((Number(px) || 0) * 750 / (windowWidth.value || 375)) + + const capsuleRightReserveRpx = computed(() => { + const rect = menuButton.value + if (!rect?.left) return 32 + return pxToRpx((windowWidth.value - rect.left) + extraTopPx) + extraRightRpx + }) + + const capsuleTopReservePx = computed(() => { + const rect = menuButton.value + if (!rect?.bottom) return safeAreaTop.value + extraTopPx + return Math.max(safeAreaTop.value + extraTopPx, rect.bottom + extraTopPx) + }) + + const navStyle = computed(() => ({ + paddingTop: `${capsuleTopReservePx.value}px`, + paddingRight: `${capsuleRightReserveRpx.value}rpx` + })) + + const topbarStyle = computed(() => ({ + paddingRight: `${capsuleRightReserveRpx.value}rpx` + })) + + const floatingTopStyle = computed(() => ({ + paddingTop: `${capsuleTopReservePx.value}px`, + paddingRight: `${capsuleRightReserveRpx.value}rpx` + })) + + return { + safeAreaTop, + capsuleRightReserveRpx, + capsuleTopReservePx, + navStyle, + topbarStyle, + floatingTopStyle, + readSafeArea + } +} + +export default useMenuButtonSafeArea