docs: add miniprogram header capsule safe-area design (scheme B).
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
b3640741ef
commit
2866fef5bf
1 file changed
+119
@@ -0,0 +1,119 @@
|
||||
# 小程序自定义顶部栏 · 微信胶囊安全区适配(方案 B)
|
||||
|
||||
> 日期:2026-09-12
|
||||
> 范围:`miniprogram` 中 `navigationStyle: custom` 的页面
|
||||
> 状态:待用户审阅后进入实现计划
|
||||
|
||||
## 1. 背景与问题
|
||||
|
||||
体验版中,从工作台进入地磅「仪表盘」等自定义导航页时,业务顶部栏(返回、标题、右侧用户名/操作)与微信小程序原生顶栏(状态栏 + 右上角胶囊「··· / 关闭」)重叠,尤其右侧关闭按钮区域会挡住业务内容。
|
||||
|
||||
根因:
|
||||
|
||||
1. 多数业务顶栏仅用固定 `padding`(如 `.db-header { padding: 12px 16px }`),未计入 `statusBarHeight`。
|
||||
2. 仓库已有 `utils/safeArea.js`、`components/app-safe-header.vue` 与 CSS 变量约定(`--sq-safe-top` 等),但:
|
||||
- `applySafeAreaCssVars` 仅写入 H5 的 `document.documentElement`,**微信小程序端不生效**;
|
||||
- `app-safe-header` **未被任何页面引用**;
|
||||
- 地磅 `.db-header`、报销 `.topbar`、壳层 `.mp-header` 未统一消费同一套量纲。
|
||||
|
||||
用户确认采用 **方案 B**:顶部加高并对齐胶囊垂直中心,**右侧永久预留胶囊宽度**,业务可点按钮不得放入胶囊区。
|
||||
|
||||
## 2. 目标
|
||||
|
||||
- 所有自定义导航页的顶栏内容(标题、返回、次要文案)落在胶囊下方/左侧安全区内,不被遮挡。
|
||||
- 量纲由运行时 API 计算,适配不同机型(刘海、胶囊位置差异)。
|
||||
- 视觉风格不变:白底列表顶栏与绿色渐变大头仍分别沿用现有 Token;只调整几何与占位。
|
||||
- 最小改动:复用已有 `safeArea` 基建,统一样式入口,避免每页手写高度。
|
||||
|
||||
## 3. 非目标
|
||||
|
||||
- 不改系统默认导航栏页面(如协议/隐私等非 custom 页)。
|
||||
- 不调整底部 TabBar / `safe-area-inset-bottom`(除非顺带发现明显缺陷且与本次无关则不做)。
|
||||
- 不做顶栏视觉重设计(颜色、圆角、字号大改)。
|
||||
- 不在右侧胶囊区放置业务「关闭」「更多」按钮。
|
||||
|
||||
## 4. 量纲与 CSS 变量
|
||||
|
||||
沿用并落实 `miniprogram/utils/safeArea.js` 的计算(`uni.getSystemInfoSync` + `uni.getMenuButtonBoundingClientRect`):
|
||||
|
||||
| 变量 | 含义 | 典型算法 |
|
||||
|------|------|----------|
|
||||
| `--sq-safe-top` | 状态栏高度 | `statusBarHeight` |
|
||||
| `--sq-nav-height` | 导航内容行高(与胶囊垂直居中) | `(capsule.top - statusBarHeight) * 2 + capsule.height`,下限 44 |
|
||||
| `--sq-header-height` | 顶栏总高 | `safe-top + nav-height` |
|
||||
| `--sq-capsule-right-safe` | 右侧预留宽 | `capsule.width + (windowWidth - capsule.right) + 水平余量`,无胶囊时为 `0` |
|
||||
|
||||
启动时 `App.onLaunch` 已调用 `initGlobalSafeArea()`;实现时须保证指标写入 **小程序可消费的样式**(见 §5),不能仅依赖 H5 `document`。
|
||||
|
||||
## 5. 布局规则(方案 B)
|
||||
|
||||
### 5.1 白底顶栏(地磅 / 报销)
|
||||
|
||||
结构:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ 状态栏占位 (--sq-safe-top) │
|
||||
├──────────┬──────────────────┬───────────────┤
|
||||
│ 返回+标题 │ 次要信息(可选) │ 胶囊右侧空白 │
|
||||
│ │ │ (不可放按钮) │
|
||||
└──────────┴──────────────────┴───────────────┘
|
||||
←────────── --sq-nav-height ───────────────→
|
||||
```
|
||||
|
||||
约束:
|
||||
|
||||
1. 总高度 = `--sq-header-height`;内容行垂直居中对齐胶囊。
|
||||
2. 网格或等价布局:`auto | minmax(0,1fr) | var(--sq-capsule-right-safe)`。
|
||||
3. 标题省略号截断;右侧列为空占位。
|
||||
|
||||
### 5.2 渐变大头(工作台 / 首页 / 待办等 `.mp-header`)
|
||||
|
||||
- `padding-top`: `calc(var(--sq-safe-top) + 内容上边距)`(替换仅 `env(safe-area-inset-top)` 或写死像素)。
|
||||
- `padding-right`: `calc(水平内边距 + var(--sq-capsule-right-safe))`,保证副文案/用户信息不进入胶囊区。
|
||||
- 若该页在头部右侧放置「退出」等按钮:须落在胶囊左侧列,不得占用 `--sq-capsule-right-safe` 区域(工作台现有右侧用户栈需按此收紧)。
|
||||
|
||||
### 5.3 变量下发(微信端)— 既定路径
|
||||
|
||||
采用 **「SCSS 统一吃变量 + 顶栏根节点内联注入」**,不强制先改完所有页面 DOM:
|
||||
|
||||
1. 新增或复用 composable / 工具函数:基于 `getGlobalSafeArea()` 返回四变量的 style 对象(px 字符串)。
|
||||
2. `.db-header` / `.bx-page .topbar` / `.mp-header`(及必要变体)在 SCSS 中改用 `--sq-*`;各页顶栏根节点绑定 `:style="safeAreaStyle"`(或等价)。
|
||||
3. `app-safe-header`:补齐样式与插槽后,**新页优先使用**;存量地磅/报销可先改 SCSS + 内联变量,不必一次性替换 DOM。
|
||||
4. `applySafeAreaCssVars`:保留 H5 写入 `document`;微信端以顶栏内联为准(不依赖 page 全局 CSS 变量穿透)。
|
||||
|
||||
禁止:仅增大固定 `padding-top`、不预留右侧(已否决的方案 C)。
|
||||
|
||||
## 6. 影响面
|
||||
|
||||
| 样式/组件 | 路径 | 动作 |
|
||||
|-----------|------|------|
|
||||
| safeArea 工具 | `miniprogram/utils/safeArea.js` | 确保微信端可消费;必要时补小程序注入 |
|
||||
| 公共顶栏 | `miniprogram/components/app-safe-header.vue` | 完善后供白底页复用,或抽出等效 SCSS |
|
||||
| 地磅顶栏 | `miniprogram/styles/db-theme.scss` + 各地磅页 | `.db-header` 改为方案 B 几何 |
|
||||
| 报销顶栏 | `miniprogram/styles/bx-theme.scss` | `.topbar` 对齐同一变量(替换仅 `env(safe-area-inset-top)` + 写死 58px) |
|
||||
| 壳层大头 | `miniprogram/styles/mp-shell.scss`(及 `mp-biz` 变体) | `.mp-header*` 使用 safe-top + capsule-right |
|
||||
| 既有大背景头 | `miniprogram/styles/index.scss` `.sq-hero-header` | 核对已引用变量是否在微信端生效;无效则一并修通 |
|
||||
| UI 规范 | `docs/miniprogram-ui-spec-sanqiang.md` §3.2 | 补充「自定义 Header 须适配胶囊」SHALL |
|
||||
|
||||
页面枚举以 `pages.json` 中 `navigationStyle: custom` 为准,至少覆盖:工作台、首页、待办、地磅全链路、报销全链路、占位页。
|
||||
|
||||
## 7. 验收标准
|
||||
|
||||
1. iPhone(刘海)与 Android 体验版:仪表盘返回/标题/用户名均不被胶囊遮挡。
|
||||
2. 地磅列表/详情、报销列表/表单顶栏同样不被遮挡。
|
||||
3. 工作台渐变头标题与右侧用户/退出不与胶囊重叠。
|
||||
4. H5 预览不出现异常巨大右侧空白或顶栏塌陷(无胶囊时 `--sq-capsule-right-safe = 0`)。
|
||||
5. 不引入新的业务按钮挤进胶囊区。
|
||||
|
||||
## 8. 风险与注意
|
||||
|
||||
- `getMenuButtonBoundingClientRect` 在部分端或过早调用可能为空:已有默认值(safe-top≈20、nav=44、右侧 0/96);实现时保持兜底。
|
||||
- 工作台当前 `mp-header--workbench` 含额外 `40px` 偏移,改造时应用变量替换魔法数,避免双重叠加导致头部过高。
|
||||
- 规范文档与 Demo HTML 可后置同步,但代码合入前至少更新 `miniprogram-ui-spec-sanqiang.md` 中 Header 一小节。
|
||||
|
||||
## 9. 决策记录
|
||||
|
||||
- **方案 B**(加高 + 右侧预留)— 用户确认 2026-09-12。
|
||||
- **否决方案 C**(只加高不预留右侧)。
|
||||
- 视觉 Token 不换色;几何统一到 `--sq-*` 变量。
|
||||
Reference in new issue
Block a user