- 两个宿主页 / mixin / App.vue / 授权页 / 引导页 的职责地图,发布方式(HBuilderX→微信审核) - 硬约定:宿主页共用 mixin、身份走 query 授权结果走 hash、fail-closed、分享深链脱敏、 分享图按 webViewUrl 当场解析、tabBar 全局状态、恢复/落地走容器页、只有 options.url 算显式落地 - 踩坑:热启动(点胶囊关闭后再进)不触发 onLoad —— 恢复逻辑不能只写在 onLoad; onShow 无条件重载会把用户踢回首页(用 App.onShow 时间戳区分热启动与切 tab) - 提醒:mixins/shareCard.js 未被 git 跟踪,提交时别漏
5.9 KiB
5.9 KiB
AGENTS.md · CRMEB 小程序(web-view 宿主)
在本仓库工作前先读。跨仓库的权威约定在
box_app/AGENTS.md(WSL:/home/jone/workspace/box_app/AGENTS.md)—— 三仓布局、身份契约、接口命名、部署流程都在那里。本文件只写小程序侧特有的部分。
1. 这是什么
CRMEB 商城小程序(uniapp,manifest name=DoubaShop),同时是整个 H5 生态的 web-view 宿主:
- 首页壳
pages/index/index.vue—— tabBar 首页,硬编码加载https://mp.yizhezhe.com/mama-box/; H5 应用宫格在 mama-box 内用location.href换应用,本页不会重新 onLoad。 - 容器页
pages/annex/web_view/index.vue—— 太阳码 / 分享落地 / 商城宫格 / JumpPath 的通用宿主。 - H5 应用(30+)只在 box_app 后台登记,本仓库没有它们的源码。
| 项 | 值 |
|---|---|
| 本地路径 | /mnt/c/Users/Jone/Documents/HBuilderProjects/crmeb(Windows:C:\Users\Jone\Documents\HBuilderProjects\crmeb) |
| 发布 | HBuilderX 发行 → 微信小程序上传 → 微信审核 → 发布(没有 git remote,本仓库是纯本地库) |
| 版本 | manifest.json 的 versionName / versionCode |
2. 关键文件
| 文件 | 作用 |
|---|---|
pages/index/index.vue |
首页壳:身份 fail-closed、加载 mama-box、冷启动恢复 last_app、分享卡片、tabBar 显隐 |
pages/annex/web_view/index.vue |
容器页:太阳码 scene 解析、身份注入(query)、_reportLastApp 上报 |
mixins/webviewHost.js |
宿主公共能力:postMessage 分发(location/share/copyLink/setTitle/requestProfile)、原生授权面板、授权回传、静默登录复用 |
mixins/shareCard.js |
分享图:按当前 H5 URL 反查 box_app App 表;朋友圈本地图转换 |
App.vue |
冷启动静默登录、globalData(spid / appShowAt)、onShow(前台化时间戳) |
pages/annex/auth/index.vue |
独立授权页(navigateTo 进入,成功写 __AUTH_RESULT__ 后 navigateBack) |
pages/guide/index.vue |
pages.json 第一个页面(冷启动入口,无广告时 switchTab 到首页壳) |
3. 硬约定
- 两个宿主页必须共用 mixin:
mixins/webviewHost.js+mixins/shareCard.js。历史上两页各写一份导致能力分叉(首页壳缺 copyLink / 授权回传 / unionid),别再分叉。 - 身份注入走 query、授权结果走 hash:容器页
_applyIdentity()负责按当前 openid 重写 URL(含_v=缓存击穿);授权回传只走 hash(#openid=&phone=&nickname=&avatar=)——微信 web-view 首次加载丢 query、不丢 hash。 - 拿不到 openid 就不加载 H5(fail-closed):重试 → 兜底屏 → 手动重试;不要匿名加载(H5 会进访客态,反而更难排查)。
- 分享深链必须
stripAuthParams():别把发送者的openid/unionid/t泄露给接收者;接收者由容器页按自己身份重新注入。 - 分享图/标题按
onShareAppMessage(options).webViewUrl当场解析:postMessage 是延迟投递,首页壳又不随 H5 换应用 onLoad,沿用上次结果会「B 应用带 A 应用的图」。 - tabBar 是全局状态:首页壳必须
uni.hideTabBar()(web-view 盖不住原生条,H5 自带底栏会双条);严禁在商城页主动showTabBar配对 —— 会与 DIY 底栏同显成双 tabBar。 - 恢复/落地统一
navigateTo容器页,并保留首页壳作为返回落点;不要直接把首页壳的 web-view src 指向第三方应用(首页壳的buildWebUrl是 hash 注入,会破坏自带 hash 路由的应用)。 - 只用
options.url当显式落地判据:options.scene每次冷启动都有值(1001 最近使用 / 1007 分享 / 1011 扫码…),拿它判落地会导致恢复永远不执行。
4. 踩坑:热启动 vs 冷启动(2026-09-22,付过线上代价)
- 用户点右上角胶囊圆点「关闭」不是销毁,只是切后台。马上再进是热启动:页面栈与 web-view 都在,
只触发
onShow,不触发onLoad;被回收后才是冷启动。 - 所以「退出小程序再进要回到上次的 H5 应用」这类需求,只写在
onLoad里会失败 —— 用户测的正是「关闭后马上再进」。 - 反过来,
onShow里无条件重载 web-view 会把用户从 H5 应用踢回首页。首页壳曾有一段「切回首页 tab 就重载」的老逻辑, 热启动也走它,于是把恢复好的应用冲掉(shareHref因 postMessage 延迟还停在 mama-box)。 - 判据:切 tab 不触发
App.onShow,热启动会。做法:App.vue onShow记globalData.appShowAt, 页面onShow里Date.now() - appShowAt < 2000视为热启动恢复 → 跳过重载。 - 改任何
onShow逻辑前,先想清楚触发来源(App 前后台切换 / 页内跳转 / 切 tab)。
5. 本仓库状态提醒
- ⚠️
mixins/shareCard.js未被 git 跟踪(untracked),但两个宿主页都 import 它 —— 提交时别漏,否则一旦丢工作区这份文件就没了。 pages/index/index.vue.origin-bak(及若干.bak_*)是原装修首页/历史备份,别当改动目标,也别删(回退时要用)。- 仓库里有多次会话遗留的未提交改动(
manifest.json/pages.json/pages/index/mall.vue等),动手前先git status分清哪些是本次的。
6. 自测
微信开发者工具(HBuilderX 运行到小程序):
- 冷启动:点「编译」→ 有 last_app 记录时应直接进上次的 H5 应用(不经过首页)。
- 热启动:点工具栏「切后台」再「切前台」→ 应停在原 H5,不应重载回首页。
- 无记录 / 断网冷启动 → 最多约 1.5s 后照常进首页。
- 授权页返回、分享卡片、商城宫格进应用各走一遍。
接口契约与后端验证清单见
box_app/AGENTS.md§5、§6。