/**
* NavBar 自定义导航栏(规范 §17)
*
* 用于非 tabBar 页面:返回按钮 + 标题 + 右侧操作 slot。
*
* 顶部几何(2026-09-23 修正):
* 此前 statusBarHeight / navBarHeight 由调用方各自用 wx.getSystemInfoSync 估算
* (`platform === 'android' ? 48 : 44`),**从未读取右上角胶囊按钮的真实位置**。
* 后果:导航行与胶囊不在同一水平带;右侧 slot 内容(如 chat 页的「⋯」)直接压在
* 胶囊下面点不到。现改为组件自己调 utils/nav-metrics 实测胶囊矩形:
* - 导航行高度与胶囊垂直居中对齐;
* - 标题居中且用 max-width 让开胶囊(左右对称,仍精确居中于屏幕);
* - 右侧 slot 内缩 --nav-right,整体落在胶囊左侧。
* 调用方传入的 statusBarHeight / navBarHeight 仅作为「拿不到胶囊信息」时的兜底,
* 不再作为唯一事实源(旧页面无需改动)。
*
* 用法:
*
* ⋯
*/
const { getNavMetrics } = require('../../utils/nav-metrics');
Component({
options: { addGlobalClass: true, multipleSlots: true },
properties: {
title: { type: String, value: '' },
showBack: { type: Boolean, value: true },
statusBarHeight: { type: Number, value: 0 },
navBarHeight: { type: Number, value: 0 },
bg: { type: String, value: 'card' }, // card | transparent
},
data: {
containerStyle: '',
navVars: '',
},
lifetimes: {
attached() {
this.applyNavMetrics();
},
},
observers: {
// 调用方 setData 后重算(旧页面习惯在 onLoad 里注入,可能晚于组件初次渲染)
'statusBarHeight, navBarHeight'() {
this.applyNavMetrics();
},
},
methods: {
applyNavMetrics() {
const metrics = getNavMetrics();
const measured = metrics.source === 'capsule';
// 实测到胶囊时以实测为准;否则回落到调用方传入值,再回落到兜底值
const statusBar = measured
? metrics.statusBarHeight
: (this.properties.statusBarHeight || metrics.statusBarHeight);
const navBar = measured
? metrics.navBarHeight
: (this.properties.navBarHeight || metrics.navBarHeight);
this.setData({
containerStyle: `padding-top: ${statusBar}px; height: ${statusBar + navBar}px;`,
navVars: `--nav-h: ${navBar}px; --nav-right: ${metrics.reserve}px;`,
});
},
onBack() {
this.triggerEvent('back', {});
},
},
});