fix(身份): 宿主未注入 openid 时给出可见提示 + jumpApp 带 __no_identity 标记 (v26092008)
背景(2026-09-20 线上排查):小程序首页壳拿不到 openid 时会**匿名加载**本页,
页面照常渲染但全是占位(孕周 `--`、档案查不到),而跳应用时 jumpApp 因为没有身份
就跳**裸 URL** —— 从商城返回首页加载本页时很容易被误判成「数据丢了」。
根因在小程序侧(App.vue 丢掉无 token 分支的 openid;首页壳没有像 web_view 那样的
silenceAuthNoLogin 兜底),H5 这侧先做**可见 + 可观测**两件缓解:
· 新增顶部提示条(#idNotice):仅在没有 openid 时显示,文案「未获取到微信身份,
页面数据可能不完整」;带「重试」按钮(location.replace 换 URL 重载,重试过一次后
文案升级为「请退出小程序后重新进入」,状态落 sessionStorage,活过那次跳转)。
有身份加载时(applyRemoteProfile 拿到 openid)自动隐藏。
⚠️ 刻意不做自动轮询/自动 reload:宿主只在它自己重设 web-view src 或 onShow 时注入身份,
页面自己刷同一 URL 并不会让身份出现,反而可能循环。
· jumpApp():一个身份都没有时显式带 `__no_identity=1` —— 目标应用能区分「宿主没注入身份」
与「参数被平台丢了」,nginx/后端日志里也能一眼查到(排查 openid 为空的关键指纹)。
验证(本地代理 + 浏览器):访客态提示可见且默认文案正确;有 openid 时隐藏;
点重试后 URL 变 `?t=…`、提示仍在且文案升级;点宫格:无身份 → `…/?__no_identity=1`,
有身份 → `?openid=…&unionid=…`(无标记);卡片/红点/资源库 8 份/弹窗/我的页/tab 顺序
全部回归正常,errors 与 console 为空。
This commit is contained in:
58
js/app.js
58
js/app.js
@@ -3,7 +3,7 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
/* 页面版本号(YYMMDD+序号):显示在「关于兜爸心选」页底部;bump 时同步 head 注释与 ?v= */
|
||||
var VER = '26092007';
|
||||
var VER = '26092008';
|
||||
const $ = (s, c) => (c || document).querySelector(s);
|
||||
const $$ = (s, c) => Array.from((c || document).querySelectorAll(s));
|
||||
|
||||
@@ -192,6 +192,12 @@
|
||||
const q = [];
|
||||
if (oid) q.push('openid=' + encodeURIComponent(oid));
|
||||
if (uid) q.push('unionid=' + encodeURIComponent(uid));
|
||||
/* ⚠️ 2026-09-20:一个身份都没有时**显式标记**,别让目标应用/日志去猜
|
||||
「是宿主没注入身份」还是「参数在路上被平台丢了」。
|
||||
· 被跳的 H5 可以据此显示自己的身份提示(或走自己的兜底);
|
||||
· nginx/后端日志里 __no_identity=1 一眼可查(排查 openid 为空时很快)。
|
||||
排查背景见 docs/mama-box-change-list-20260919.md 与 showIdNotice() 的注释。 */
|
||||
if (!oid && !uid) q.push('__no_identity=1');
|
||||
if (q.length) url += (url.indexOf('?') >= 0 ? '&' : '?') + q.join('&');
|
||||
reportHostLocation(url);
|
||||
location.href = url;
|
||||
@@ -2470,6 +2476,51 @@
|
||||
return m ? decodeURIComponent(m[1]).split('?')[0] : '';
|
||||
} catch (e) { return ''; }
|
||||
}
|
||||
/* ---------- 身份未就绪提示(2026-09-20) ----------
|
||||
宿主(小程序首页壳)拿不到 openid 时会**匿名加载**本页 —— 页面照常渲染,
|
||||
但全是占位数据(孕周 `--`、档案空、跳应用不带身份)。以前这种情况完全静默,
|
||||
排查时只能靠服务端日志反推;现在给一条可见提示。
|
||||
⚠️ 只在「确实没有 openid」时显示;一旦宿主把身份注入回来(onShow 重载),
|
||||
applyRemoteProfile 会再跑一次,这里要 hide。
|
||||
⚠️ 不做自动轮询/自动 reload:宿主只在它自己重设 web-view src 或 onShow 时注入身份,
|
||||
页面自己 reload 同一 URL 并不会让身份出现(反而可能循环),所以只留手动重试。 */
|
||||
function showIdNotice(reason) {
|
||||
const el = $('#idNotice'), txt = $('#idNoticeTxt');
|
||||
if (!el) return;
|
||||
if (txt) {
|
||||
/* ⚠️ 重试过一次之后(sessionStorage 计数)文案要保留「请退出小程序重进」,
|
||||
否则重载回来又变回温和版,用户以为重试没发生过(重试是 location.replace,
|
||||
文案状态活不过那一次跳转,只能落到 sessionStorage)。 */
|
||||
let tried = reason === 'retried';
|
||||
if (!tried) {
|
||||
try { tried = (parseInt(sessionStorage.getItem('mmbox.idretry') || '0', 10) || 0) > 0; } catch (e) {}
|
||||
}
|
||||
txt.textContent = tried
|
||||
? '仍未获取到微信身份,请退出小程序后重新进入'
|
||||
: '未获取到微信身份,页面数据可能不完整';
|
||||
}
|
||||
el.classList.remove('hide');
|
||||
}
|
||||
function hideIdNotice() {
|
||||
const el = $('#idNotice');
|
||||
if (el) el.classList.add('hide');
|
||||
}
|
||||
/* 重试:只做一次「换 URL 重载」——带上 ?t= 让宿主/缓存放行。
|
||||
宿主 onShow 也会重新注入身份(切到别的 tab 再回来即可),提示文案里已说明。 */
|
||||
function retryIdentity() {
|
||||
let n = 0;
|
||||
try { n = parseInt(sessionStorage.getItem('mmbox.idretry') || '0', 10) || 0; } catch (e) {}
|
||||
try { sessionStorage.setItem('mmbox.idretry', String(n + 1)); } catch (e) {}
|
||||
showIdNotice('retried');
|
||||
setTimeout(() => {
|
||||
try {
|
||||
const u = location.href.split('#')[0].split('?')[0] + '?t=' + Date.now();
|
||||
location.replace(u);
|
||||
} catch (e) { location.reload(); }
|
||||
}, 500);
|
||||
}
|
||||
$('#idNoticeRetry').addEventListener('click', retryIdentity);
|
||||
|
||||
let _profileApplied = false;
|
||||
function applyRemoteProfile() {
|
||||
if (_profileApplied) return; // init 只跑一次,防重复 fetch
|
||||
@@ -2479,6 +2530,9 @@
|
||||
⚠️ 绝不能停在内置演示默认值上(小汤圆 / 孕27周 都是前端现算的假数据)——
|
||||
全部切占位/引导;宿主拿到身份后会带 openid 重载本页,届时自动切真实数据。 */
|
||||
if (!openid) {
|
||||
/* ⚠️ 可见提示(2026-09-20):宿主没注入身份时别静默装正常。
|
||||
排查路径见 showIdNotice() 上方那段注释。 */
|
||||
showIdNotice();
|
||||
state.pregEmpty = true;
|
||||
state.due = null; state.week = null; state.day = null;
|
||||
state.babyName = ''; state.userName = '';
|
||||
@@ -2492,6 +2546,8 @@
|
||||
- profile:babyName/userName/babySex/dueDate(身份 + 建档字段)
|
||||
- pregnancy:week/day/due 以服务端权威派生为准(避免客户端重复算、口径统一)
|
||||
拉不到(无 openid / 未返回 200 / 断网)就静默保持内置默认值,页面照常可用。 */
|
||||
/* 走到这里说明这次加载是带身份的(openid 非空)→ 把上一次的提示收掉 */
|
||||
hideIdNotice();
|
||||
Promise.all([
|
||||
fetch(base + 'profile?openid=' + encodeURIComponent(openid)).then(r => (r.ok ? r.json() : null)),
|
||||
fetch(base + 'pregnancy?openid=' + encodeURIComponent(openid)).then(r => (r.ok ? r.json() : null))
|
||||
|
||||
Reference in New Issue
Block a user