101 lines
8.4 KiB
Markdown
101 lines
8.4 KiB
Markdown
# AGENTS.md · mama-box(兜爸心选 H5)
|
||
|
||
> 在本仓库工作前先读。**跨仓库的权威约定在 `box_app/AGENTS.md`**(`/home/jone/workspace/box_app/AGENTS.md`)——
|
||
> 三仓布局、身份契约、接口命名、部署与踩坑总表都在那里;本文件只写本仓库特有的部分。
|
||
|
||
---
|
||
|
||
## 1. 这是什么
|
||
|
||
微信小程序里的**首页 H5**:小程序首页壳(`crmeb/pages/index/index.vue`)用 web-view 硬编码加载
|
||
`https://mp.yizhezhe.com/mama-box/`,用户看到的就是本站。它同时是 **H5 应用宫格**入口(30+ 第三方应用的门面)。
|
||
|
||
- 纯静态站点:**无框架、无构建、无测试**,`index.html` 一个页面用 `.screen` 切换多个屏。
|
||
- 仓库 `jone/mama-box`;本地 `/home/jone/workspace/mama-box`;生产 `/opt/app/mama-box`(nginx alias 托管,非 box_app 挂载)。
|
||
- 原型参考(只读,别当改动目标):`/home/jone/workspace/dailiang-app-03`。
|
||
|
||
## 2. 文件地图
|
||
|
||
| 文件 | 作用 |
|
||
| --- | --- |
|
||
| `index.html` | 单页多屏的全部结构 + 样式引用/脚本引用(1550+ 行) |
|
||
| `js/app.js` | **全部业务逻辑**(3000+ 行):屏切换、远程数据、宫格、授权、跳转、last_app |
|
||
| `js/wx-auth.js` | **共享助手,别的 H5 应用也引用它**:环境判定 / 读授权结果 / `requestProfile` / `goMall` / `reportLocation`。改动等于改所有接入方,务必保守 |
|
||
| `mama-box.css` | 样式 |
|
||
| `assets/` | 图片/资源。⚠️ `assets/img/` 下**文件名 = 文件内容 md5 的前 12 位**(`md5sum 新图` 取前 12 位),内容寻址:换图即换 URL,天然不会被上一版图缓存顶住。别起描述性名字 —— 全目录 35 张都按这个规则(2026-09-22 换顾问二维码时实测确认) |
|
||
| `js/core.js` | ⚠️ **本仓库内已无任何引用**(MPA 原型带过来的遗留)。新代码不要基于它,改前先确认没有隐藏引用 |
|
||
|
||
## 3. 发布
|
||
|
||
```bash
|
||
git push origin main # 完成后在服务器:
|
||
cd /opt/app/mama-box && git fetch && git reset --hard origin/main # 静态站,无需重启
|
||
```
|
||
|
||
nginx:`root /opt/app` + `Cache-Control: no-cache` + `etag on` —— 缓存靠 ETag,所以**改完必须 bump 版本号**。
|
||
|
||
**版本号规则(必做)**:改了 `js/*.js` 或 `mama-box.css` 时,两处同步 bump,且 commit message 带版本:
|
||
- `index.html` 顶部 `<!-- V:YYMMDDNN 缓存版本标记… -->`
|
||
- `js/app.js` 顶部 `var VER = 'YYMMDDNN';`
|
||
|
||
`YYMMDD` = 当天日期,`NN` = 当日两位序号(从 `01` 起)。例:`v26092202`。
|
||
|
||
## 4. 硬约定
|
||
|
||
1. **身份只从 URL 读**:宿主把 `#openid=…&unionid=…` 注入进来,用 `hashParam(name)` 读
|
||
(它同时读 hash 与 query,并会剥掉历史 bug 粘上的 `?t=`)。`openid` 是唯一身份键。
|
||
2. **拿不到 openid 就显示提示条**(`showIdNotice`),**不要造假数据**:宿主拿不到身份时不会加载本页;
|
||
真出现空身份要让人一眼看出来,而不是显示 `--`/演示值。
|
||
3. **跳其它 H5 应用一律走 `jumpApp(url, identifier)`**(或档案页的 `goArchiveH5()`):它负责
|
||
带身份(query)、上报分享地址、上报 last_app,再 `location.href`。**禁止裸 `location.href` 跳应用**。
|
||
4. **不要在本仓库写死应用名单**:能不能出现、叫什么、链接是什么,全部由 box_app 后台 App 表决定
|
||
(`/api/mp/apps?isPublished=1`)。要下架某应用去后台下架,别在前端加过滤(历史教训:`wx-h5-demo` 过滤已按要求移除,别加回来)。
|
||
5. **授权走 `wxAuth.requestProfile()`**:它用 `wx.miniProgram.navigateTo` 跳小程序独立授权页并带 `backUrl`;
|
||
结果由宿主写回 URL 的 **hash**。**不要用 postMessage 做授权请求**(延迟批量投递,点了没反应)。
|
||
6. **分享位置上报 `reportHostLocation()`**:postMessage 非实时(微信攒到后退/销毁/分享才派发),
|
||
所以要在**换页/跳转前**主动上报目标地址,宿主的分享卡片才能在分享那一刻拿到正确地址。
|
||
7. **换应用前上报 last_app**(`reportLastApp()`,`navigator.sendBeacon`):这是「退出小程序再进能回到上次应用」的
|
||
数据来源,新增任何跳应用的入口都要走 `jumpApp()` 以继承这个行为。
|
||
8. **返回首页要清 last_app**(`clearLastAppOnBackHome()` → `DELETE /api/mp/public/last-app`):
|
||
用户已经从 H5 应用退回首页,首页才是他最后待的地方 —— 不清的话下次冷启动又把他送回刚退出的应用。
|
||
⚠️ **只认「返回回到本页」三种情形**(bfcache 的 `pageshow.persisted`、后退重载的
|
||
`navigation.type === 'back_forward'`、从应用页 `location.href` 回来的 `document.referrer`);
|
||
**绝不能改成「每次加载都清」** —— 宿主恢复会把本页当返回落点加载,误清会毁掉刚用上的记录。
|
||
9. **保存资料失败必须提示,不能静默**(2026-09-22「档案以上游为准」):
|
||
`PUT /profile` 改**预产期/昵称/宝宝小名**时,后端会**先推上游用户中心、成功才落库**,推失败返回 `code=400`
|
||
且**不落库**。H5 必须弹提示(`_putProfile` 已按此判断 `res.code`)——静默的话下次加载会被上游值覆盖回去,
|
||
用户以为"改了没生效"。改这个接口的调用方时别再把失败吞掉。
|
||
10. **产后态必须先判 `postpartum`**(2026-09-22):`/pregnancy` 的产后返回体里 `week` 也是 `null`,
|
||
`applyRemoteProfile` 与 `syncPregnancy` 都必须**先判 `state.postpartum` 再判 `empty || week == null`**,
|
||
否则会给**已经生产**的用户弹「完善孕期信息」引导;
|
||
并且 `syncPregnancy()` 之后那条按 `state.week` 重算的链(`syncStaticDates` 等)要一并拦住 ——
|
||
`week=null` 会让它算出「看着正常但全错」的日期,页面上看不出来。文案集中在 `syncPregnancy` 的产后分支。
|
||
11. **首页那 5 张工具卡的数据来自 box_app**(2026-09-22,v26092213 起):`GET /api/mp/public/mama-box/tool-cards`
|
||
(box_app 封装数胎动平台的 `app-cards`;H5 **不直连上游、不持有 token**)。两条纪律:
|
||
① **接口优先、失败回退本地** —— 接口 `ok=false` 或某槽缺失时保留卡上现有值,页面绝不因上游抖动变空;
|
||
两个来源并行返回、先后不定,所以用 `cardsOwned` 旗子定优先级(`#kickTodayHome`、`#calNext` 归接口,
|
||
curve 卡写值后**摘掉 `data-wk`**),**别赌返回顺序**;
|
||
② 卡片的**名称与链接仍以 App 表为准**(`MINI_APP_MAP` + `APP_BY_ID`),接口回的 `appId/path` 只作诊断 ——
|
||
上游 `app_id` 是 URL slug(`taier-guzhong`),与 App 表 `identifier`(`taierguzhong`)**刻意不同**,别互相推导。
|
||
⚠️ 卡是固定高度 bento,只有 kick / weight 有位置放第二行(`.mc-extra`);给 fweight/cal/curve 加第二行前
|
||
先重排那笔高度账(`158+10+64=232`,见 `mama-box.css`)。
|
||
|
||
## 5. 踩坑
|
||
|
||
- **不要给别的应用追加 `#openid`**:部分应用自带 hash 路由(如 `/baobao-yingji`),追加 hash 会被当非法路由 → 页面未找到。身份一律走 query(`withIdentity()` 已封装)。
|
||
- **`bustReload` 重载必须把 hash 拼回去**,否则丢身份、误报「未获取到微信身份」(v26092009 修过)。
|
||
- **首屏渲染与异步数据的竞态**:`init()` 负责渲染,远程档案在 `init()` **末尾**才拉(先拉会被 init 覆盖)。新增远程数据请照这个顺序。
|
||
- **`resumeLastApp()` 是兜底,不是主恢复**:主恢复在小程序首页壳(冷启动自己读 last-app 直接进容器页)。
|
||
本页只在「首页壳取数失败回落加载」或「浏览器直访」时恢复;被宿主加了 `#norestore=1` 时必须**既不跳、也用
|
||
sessionStorage 闸门占住**(否则宿主 `?t=` 重载会把返回落点也换成目标应用,back 回不到首页)。
|
||
- **改 `js/wx-auth.js` 等于改全生态**:它是所有接入 H5 应用共用的授权助手,先看 `docs/h5-auth-standard.md` 的协议再动。
|
||
|
||
## 6. 自测
|
||
|
||
无构建、无自动化测试。改完:
|
||
```bash
|
||
node --check js/app.js # 语法
|
||
```
|
||
真机/微信开发者工具里走一遍:身份注入是否正常、宫格跳应用是否带身份、分享卡片地址、授权回填、
|
||
退出小程序再进是否能回到上次应用。相关接口契约与验证清单见 `box_app/AGENTS.md` §6。
|