/** * 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', {}); }, }, });