import { View, Text } from '@tarojs/components'; import Taro from '@tarojs/taro'; import { useState, useEffect } from 'react'; let cached = null; /** 顶部安全区(沉浸式自定义导航用):状态栏 + 胶囊高度。 */ export function getTopInset() { if (!cached) { try { const win = Taro.getWindowInfo ? Taro.getWindowInfo() : Taro.getSystemInfoSync(); const statusBar = win.statusBarHeight || 44; const windowWidth = win.windowWidth || 375; let navH = statusBar + 44; try { const menu = Taro.getMenuButtonBoundingClientRect ? Taro.getMenuButtonBoundingClientRect() : null; if (menu && menu.height) navH = statusBar + (menu.top - statusBar) * 2 + menu.height; } catch { /* 无胶囊环境用默认 */ } cached = { statusBar, navH, windowWidth }; } catch { cached = { statusBar: 44, navH: 88, windowWidth: 375 }; } } return cached; } /** 统一固定标题区(fixed 不随滚动):像素字 kicker + 彩虹渐变标题 + 像素字注脚。 * back:传入函数=自定义返回;true=自动返回(无上一页则回首页 Tab)。 * shift:内容整体上移量(rpx),默认 65;底部占位高度不受影响。 * 占位高度由 createSelectorQuery 实测 navbar 真实高度,绝无空白/覆盖/重复。 */ export function PageHeader({ no, title, en, sub, back, shift = 65 }) { const { navH, windowWidth } = getTopInset(); // 标题区整体上移 shift rpx:从状态栏让位空间中扣除(不是容器偏移,占位实测自动跟随,无空白) const SHIFT_PX = Math.round((shift * (windowWidth || 375)) / 750); const topPad = Math.max(navH - SHIFT_PX, 24); // 下限:至少给状态栏留 24px // 默认占位高度 = 状态栏+导航区+标题内容,避免异步测量前内容被遮挡 const defaultH = navH + 80; const [h, setH] = useState(defaultH); useEffect(() => { Taro.nextTick(() => { Taro.createSelectorQuery() .select('.page-navbar') .boundingClientRect((r) => { if (r && r.height) setH(r.height); }) .exec(); }); }, [no, title, en, sub, back]); const goBack = () => { if (typeof back === 'function') { back(); return; } const pages = Taro.getCurrentPages ? Taro.getCurrentPages() : []; if (pages.length > 1) Taro.navigateBack({ delta: 1 }); else Taro.switchTab({ url: '/pages/index/index' }); }; return ( <> {no || back ? ( {back ? ( ) : null} {no ? {no} : null} ) : null} {title} {sub ? {sub} : null} {en ? {en} : null} ); } /** 沉浸式顶部占位:配合页面 navigationStyle=custom 使用。 */ export default function TopInset() { const { navH } = getTopInset(); return ; }