b1b86bb80d
- PageHeader 新增 shift 参数(默认 65rpx,其他页面不变) - 大厅传 95rpx:标题文本整体上移,底部占位高度不变
87 lines
3.5 KiB
React
87 lines
3.5 KiB
React
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 (
|
|
<>
|
|
<View className="page-navbar" style={{ paddingTop: `${topPad}px` }}>
|
|
<View className="page-navbar-col">
|
|
{no || back ? (
|
|
<View className="page-navbar-norow">
|
|
{back ? (
|
|
<View className="page-navbar-back-hit" hoverClass="pressed" onClick={goBack}>
|
|
<Text className="page-navbar-back-ic ic ic-arrow-left" aria-hidden />
|
|
</View>
|
|
) : null}
|
|
{no ? <Text className="page-navbar-no">{no}</Text> : null}
|
|
</View>
|
|
) : null}
|
|
<View className="page-navbar-titlerow">
|
|
<Text className="page-navbar-title">{title}</Text>
|
|
{sub ? <Text className="page-navbar-sub">{sub}</Text> : null}
|
|
</View>
|
|
{en ? <Text className="page-navbar-en">{en}</Text> : null}
|
|
</View>
|
|
</View>
|
|
<View style={{ height: `${h}px` }} />
|
|
</>
|
|
);
|
|
}
|
|
|
|
/** 沉浸式顶部占位:配合页面 navigationStyle=custom 使用。 */
|
|
export default function TopInset() {
|
|
const { navH } = getTopInset();
|
|
return <View style={{ height: `${navH}px` }} />;
|
|
}
|