Files
wx-h5-demo/index.html
Karlcarlo 0399fd00ff wx-h5-demo: 顶部新增「返回首页」6 个按钮 —— 演示身份怎么带过去 (demo v26092201)
按接入规范(box_app/docs/h5-auth-standard.md 第三节第 6 条同源身份缓存、
第五节第 6 条回首页不要裸跳)把这条路径做成可点的验证工具:

  ① goHome()                —— 规范推荐,库自己带身份
  ② 手拼 URL 带 openid/unionid —— 规范做法,身份放 query
  ③ 裸跳 /mama-box/(反例)      —— URL 无身份;靠同源缓存兜底通常仍认得
  ④ switchTab 回小程序首页壳    —— 宿主重新注入,最稳(仅 web-view 内)
  ⑤ 清同源缓存 + 裸跳           —— **复现线上 bug**:首页「身份不完整」且重试救不回
  ⑥ 清同源缓存 + goHome()       —— 证明 goHome 主动带身份、不依赖缓存

实现要点:
- 卡片放在页面顶部(.env 那行之后);新增一行只读展示 identity() 的 from/openid/unionid。
- ②③⑤ 用**同源相对地址**(location.origin + '/mama-box/'):同源缓存本来就只在本 origin
  有效,这样写与生产等价且可被其它挂载点复用;①⑥ 仍走库的 goHome()(绝对地址)——那正是要演示的 API。
- clearIdCache() 清完**不再**调 identity() 刷新展示:本页 URL 上还带着身份,"URL 优先"会立刻
  写回缓存,等于白清(本地实测踩过,⑤ 因此复现不出来)。
- dbg() 已镜像 console.log:这些按钮点下去就跳走,页内面板看不到日志。

本地同源验证(/wx-h5-demo + /mama-box 同一 origin、桩后端):②③⑥ 落地无「身份不完整」;
⑤ 落地**提示条 flex**(bug 复现);① 走库的 goHome() 带 ?openid= 落地正常。页面无 JS 异常。
2026-09-22 21:52:16 +08:00

470 lines
27 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
<meta name="theme-color" content="#F4593C">
<title>wx-h5-demo · 共享授权规范示例</title>
<style>
* { margin:0; padding:0; box-sizing:border-box; -webkit-tap-highlight-color:transparent; }
body { font-family:-apple-system,"PingFang SC","Microsoft YaHei",sans-serif; background:#F8F3EF; color:#2B2320; min-height:100vh; display:flex; justify-content:center; }
.wrap { width:100%; max-width:430px; padding:24px 20px 40px; }
.brand { font-size:22px; font-weight:800; color:#F4593C; } .brand small{color:#A79C95;font-size:13px;font-weight:500;margin-left:8px}
.env { margin:14px 0 8px; font-size:13px; color:#6B615B; } .env b{color:#2B2320}
.tag { display:inline-block; padding:2px 8px; border-radius:8px; font-size:12px; }
.tag.ok{background:#E8F2EB;color:#5F8A4A} .tag.no{background:#F6DCD6;color:#C4553A}
.card { background:#fff; border:1px solid #EFE7E1; border-radius:16px; padding:16px; margin-top:14px; }
.card h2{font-size:15px;font-weight:800;margin-bottom:10px}
.row{display:flex;justify-content:space-between;align-items:center;padding:10px 0;border-bottom:1px dashed #EFE7E1;font-size:14px}
.row:last-child{border-bottom:none} .row .k{color:#6B615B} .row .v{font-weight:600} .row .v.placeholder{color:#C9B7AC;font-weight:500}
.avatar{width:44px;height:44px;border-radius:50%;background:#F1E6E0;overflow:hidden;display:flex;align-items:center;justify-content:center;font-size:18px}
.avatar img{width:100%;height:100%;object-fit:cover}
.btn{display:block;width:100%;padding:15px;border:none;border-radius:14px;font-size:15px;font-weight:700;margin-top:14px;cursor:pointer}
.btn.main{background:#F4593C;color:#fff} .btn.ghost{background:#fff;color:#6B615B;border:1px solid #EFE7E1}
.hint{font-size:12px;color:#A79C95;margin-top:12px;line-height:1.6}
.env-hint{font-size:12.5px;color:#C4553A;background:#FBF0EE;border:1px solid #F0D8D2;border-radius:10px;padding:10px 12px;margin-top:12px;line-height:1.6}
#toast{position:fixed;left:50%;top:14%;transform:translateX(-50%);background:rgba(30,22,18,.9);color:#fff;padding:10px 18px;border-radius:10px;font-size:13px;opacity:0;pointer-events:none;transition:opacity .25s;z-index:99}
#toast.show{opacity:1}
/* ==== 调试日志面板 ==== */
#dbgToggle{position:fixed;right:12px;bottom:12px;z-index:200;background:#2B2320;color:#fff;border:none;border-radius:20px;padding:9px 14px;font-size:13px;font-weight:700;box-shadow:0 4px 14px rgba(0,0,0,.25);cursor:pointer;opacity:.92}
#dbgPanel{position:fixed;right:0;bottom:0;left:0;z-index:210;background:#1A1512;color:#E7DAD1;font-family:Menlo,Consolas,monospace;font-size:12px;line-height:1.5;border-top:2px solid #F4593C;transform:translateY(100%);transition:transform .25s;max-height:62vh;display:flex;flex-direction:column}
#dbgPanel.open{transform:translateY(0)}
#dbgHead{display:flex;justify-content:space-between;align-items:center;padding:9px 12px;background:#241D18;border-bottom:1px solid #3A2F28}
#dbgHead b{font-size:13px;color:#F4593C}
#dbgHead span{font-size:11px;color:#A79C95}
#dbgHead button{margin-left:8px;background:none;border:1px solid #4A3D34;color:#E7DAD1;border-radius:6px;padding:3px 10px;font-size:12px;cursor:pointer}
#dbgLog{overflow-y:auto;padding:8px 12px;flex:1;word-break:break-all}
#dbgLog .ln{margin:3px 0;padding:3px 6px;border-left:3px solid #4A3D34;color:#CBBDB2}
#dbgLog .ln.err{border-left-color:#F4593C;color:#FF9E86;background:rgba(244,89,60,.08)}
#dbgLog .ln.ok{border-left-color:#5F8A4A;color:#9BC48A}
#dbgLog .ln.warn{border-left-color:#E0B33E;color:#EED49A}
#dbgLog .ln.muted{color:#8B7E75;border-left-color:#3A2F28}
#dbgLog .ln b{color:#fff;font-weight:700}
</style>
</head>
<body>
<div class="wrap">
<div class="brand">wx-h5-demo <small>共享授权规范示例</small></div>
<div class="env">环境:<b id="envTxt">检测中…</b> <span id="envTag" class="tag no">纯浏览器</span></div>
<!-- 场景4 · 返回首页:身份怎么带过去(规范见 box_app/docs/h5-auth-standard.md
第三节第 6 条「同源身份缓存」与第五节第 6 条「回首页不要裸跳」) -->
<div class="card">
<h2>返回首页 · 身份怎么带过去(点哪个都要看首页认不认得你)</h2>
<div class="row"><span class="k">identity()</span><span class="v" id="idNow" style="word-break:break-all;text-align:right;max-width:64%">—</span></div>
<button class="btn main" id="btnHomeGo">① goHome()(规范推荐:自动带身份)</button>
<button class="btn ghost" id="btnHomeUrl">② 手拼 URL 带 openid/unionid(规范做法)</button>
<button class="btn ghost" id="btnHomeBare" style="color:#C4553A;border-color:#F0D8D2">③ ❌ 裸跳 /mama-box/(反例:宿主不会补身份)</button>
<button class="btn ghost" id="btnHomeSwitch">④ switchTab 回小程序首页壳(宿主重新注入,仅 webview 内)</button>
<button class="btn ghost" id="btnHomeBareClear" style="color:#C4553A;border-color:#F0D8D2">⑤ 清同源缓存 + 裸跳(兜底也会失效)</button>
<button class="btn ghost" id="btnHomeClearGo">⑥ 清同源缓存 + goHome()(证明它不依赖缓存)</button>
<p class="hint">
<b>要看的现象</b>:① ② ⑥ 跳过去后首页应<b>认得你</b>(不出现「身份不完整」提示条、能拉到你的档案);
③ 是<b>反例</b>——它不带身份,但因为有<b>同源缓存兜底</b>(本页与 mama-box 同在 <code>mp.yizhezhe.com</code>,
共享 <code>sessionStorage</code>)通常也能认出你;<b>⑤ 清掉缓存后再裸跳</b>就会露出「身份不完整」,
而且<b>点重试也救不回</b>(重试只是重载同一条没有身份的 URL)—— 这就是线上那个 bug 的完整复现。<br>
⚠️ 缓存只是<b>兜底不是许可</b>:清微信缓存/换会话、或应用挂在外链域名下时就失效,
所以跳转仍要按规范带身份(或调 <code>goHome()</code>)。<br>
⚠️ 「回首页」的目标是 <b>mama-box 这个 H5 首页</b>(H5 方式);④ 是另一条路 —— 回小程序首页壳,
由宿主重新注入身份,最稳但仅在小程序 web-view 内可用。<br>
⚠️ 身份放 <b>query</b>,别放 hash:部分应用自带 <code>location.hash</code> 路由,追加 hash 会被当成非法路由
(规范第三节第 5 条)。
</p>
</div>
<div class="card">
<h2>授权状态</h2>
<p id="authState" style="font-size:13px;color:#6B615B;line-height:1.6">检测中…</p>
<button class="btn main" id="btnAuth" style="display:none">授权登录</button>
<button class="btn ghost" id="btnMall">进商城</button>
<p id="envHint" class="env-hint" style="display:none">⚠️ 当前不是小程序 webview,无法完成授权登录。请在<strong>微信小程序</strong>里打开本页后使用(浏览器/微信内直开仅能查看)。</p>
</div>
<div class="card">
<h2>授权结果(宿主页回传后读取 #phone/nickname/avatar)</h2>
<div class="row"><span class="k">手机号</span><span class="v placeholder" id="rPhone">—</span></div>
<div class="row"><span class="k">昵称</span><span class="v placeholder" id="rNick">—</span></div>
<div class="row"><span class="k">头像</span><span class="v"><span class="avatar" id="rAvatarWrap"><span id="rAvatarText">宝</span></span></span></div>
</div>
<div class="card">
<h2>场景3 · 分享深链验证(web-view 内 H5 分享)</h2>
<div class="row"><span class="k">当前页面</span><span class="v" id="shCur" style="word-break:break-all;text-align:right;max-width:62%">—</span></div>
<div class="row"><span class="k">深链标记</span><span class="v" id="shMark">(未设置)</span></div>
<button class="btn ghost" id="btnShMark">① 生成唯一深链标记(写入 hash 路由)</button>
<button class="btn main" id="btnShOk">② ✅ 正确分享:只 postMessage(本页不跳)</button>
<button class="btn ghost" id="btnShBad" style="color:#C4553A;border-color:#F0D8D2">③ ❌ 复现旧 bug:postMessage + navigateBack</button>
<p class="hint">
<b>判定标准</b>:点 ② 后本页<b>停留不动</b>,再点右上角「···」转发;接收者点开卡片,
打开的应是上面「当前页面」那个地址(含 hash 标记),<b>而不是小程序首页</b>。<br>
点 ③ 会立即退回上一页(旧版 <code>bridge.share()</code> 的 <code>navigateBack</code> 副作用)——
此时再点「···」转发,卡片会由上一页产出,接收者落到上一页:即线上 bug 的复现。<br>
⚠️ 仅在<b>小程序 web-view</b> 内有效(宿主页需按 <code>onShareAppMessage(options).webViewUrl</code> 拼深链,
见 <code>miniapp/scenario3-share-webview.js</code> / CRMEB <code>pages/annex/web_view</code>)。
微信浏览器/纯浏览器只能看 UI。
</p>
</div>
<p class="hint">
本页演示<b>共享授权规范</b>:<code>wx-auth.js</code>(<code>wxAuth.init/requestProfile/goMall/readAuth/isAuthorized</code>)。
授权流程:点「授权登录」→ <code>wx.miniProgram.navigateTo('/pages/annex/auth/index')</code> →
小程序端独立授权页(头像/昵称/手机号,非 web-view 原生组件页)→ <code>POST /api/mp/public/auth/profile</code> 落库共享 UserAuth →
授权返回后宿主页更新 <code>web-view src</code>(hash 带结果)→ 本页重载 → <code>wxAuth.readAuth()</code> 显示。
「进商城」→ <code>wx.miniProgram.switchTab('/pages/goods_cate/goods_cate')</code>。
「返回首页」有 6 个按钮(页面顶部那张卡):正路是 <code>wxAuth.goHome()</code> 或手拼 URL 带身份;
其余是反例与降级演示 —— 用来验证<b>同源身份缓存</b>到底兜住了什么、什么时候会失效。
</p>
<div id="ver" style="text-align:center;color:#B3A69C;font-size:11px;margin-top:22px;padding-bottom:8px">v<span id="verNo"></span></div>
</div>
<div id="toast"></div>
<!-- 调试日志面板 -->
<button id="dbgToggle">🐛 调试日志</button>
<div id="dbgPanel">
<div id="dbgHead">
<b>调试日志</b>
<span id="dbgCount"></span>
<span>
<button id="dbgCopy">复制</button>
<button id="dbgClear">清空</button>
<button id="dbgClose">收起</button>
</span>
</div>
<div id="dbgLog"></div>
</div>
<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
<script src="/mama-box/js/wx-auth.js?v=20260908"></script>
<script>
(function () {
'use strict';
/* ============================================================
① 页面版本号(YYMMDD + 两位序号)—— 用于排查 webview 是否缓存了旧页面
============================================================ */
var VER = 26092201;
var verNoEl = el('verNo');
if (verNoEl) verNoEl.textContent = VER;
/* ============================================================
② 日志面板(真机上 console/alert 看不到,用可视化面板)
============================================================ */
var dbgCount = 0;
function el(id) { return document.getElementById(id); }
function dbg(msg, cls) {
dbgCount++;
var logBox = el('dbgLog');
var ln = document.createElement('div');
ln.className = 'ln' + (cls ? ' ' + cls : '');
var t = new Date().toTimeString().replace(/.*(\d\d:\d\d:\d\d).*/, '$1');
ln.innerHTML = '<b>' + t + '</b> ' + msg;
logBox.appendChild(ln);
logBox.scrollTop = logBox.scrollHeight;
el('dbgCount').textContent = '共 ' + dbgCount + ' 条';
try { console.log('[dbg]', msg); } catch (e) {}
}
function dbgErr(msg) { dbg('❌ ' + msg, 'err'); }
window.__dbg = dbg;
// 全局错误捕获
window.addEventListener('error', function (e) {
dbgErr('window.onerror: ' + (e.message || '未知') + ' @ ' + (e.filename || '') + ':' + (e.lineno || '') + ':' + (e.colno || ''));
});
window.addEventListener('unhandledrejection', function (e) {
var r = e.reason;
dbgErr('unhandledrejection: ' + (r && (r.message || r.stack) ? (r.message || r.stack) : r));
});
// 面板开关
el('dbgToggle').addEventListener('click', function () { el('dbgPanel').classList.toggle('open'); });
el('dbgClose').addEventListener('click', function () { el('dbgPanel').classList.remove('open'); });
el('dbgClear').addEventListener('click', function () { el('dbgLog').innerHTML = ''; dbgCount = 0; el('dbgCount').textContent = ''; });
// 复制日志:隐藏 textarea + execCommand('copy'),微信 webview 通用做法
el('dbgCopy').addEventListener('click', function () {
var text = '';
var lns = el('dbgLog').querySelectorAll('.ln');
for (var i = 0; i < lns.length; i++) {
var t = (lns[i].querySelector('b') ? lns[i].querySelector('b').textContent : '');
text += t + ' ' + lns[i].textContent.replace(t, '').trim() + '\n';
}
text = '[wx-h5-demo 调试日志 v' + VER + ']\n' + text;
function ok() { dbg('已复制 ' + lns.length + ' 条日志到剪贴板', 'ok'); }
try {
var ta = document.createElement('textarea');
ta.value = text;
ta.style.cssText = 'position:fixed;top:0;left:0;opacity:0;height:1px;width:1px;overflow:hidden';
document.body.appendChild(ta);
ta.select();
var did = document.execCommand('copy');
document.body.removeChild(ta);
if (did) ok(); else dbgErr('复制失败(execCommand 返回 false)');
} catch (e) {
dbgErr('复制失败: ' + (e && e.message ? e.message : e));
}
});
function show(tag, title) {
el('envTag').textContent = title; el('envTag').className = 'tag ' + (tag === 'ok' ? 'ok' : 'no');
}
/* ============================================================
② jweixin / wx.miniProgram 环境检测(先记录关键前提)
============================================================ */
dbg('脚本初始化开始');
dbg('jweixin 已加载: window.wx = ' + (typeof window.wx !== 'undefined' ? '✅ 存在' : '❌ 不存在(CDN 加载失败或未进入微信环境)'));
dbg('window.wx.miniProgram = ' + ((window.wx && window.wx.miniProgram) ? '✅ 存在' : '❌ 不存在'), 'muted');
dbg('navigator.userAgent 含 MicroMessenger: ' + (/MicroMessenger/i.test(navigator.userAgent) ? '✅ 是' : '❌ 否'), 'muted');
dbg('location.hash = ' + (location.hash || '(空)') + ' location.search = ' + (location.search || '(空)'), 'muted');
// 给 navigateTo 打补丁:记录每一次跳转调用 + 捕获异常 + 转发 fail/success
// (navigateTo 跳不存在的页面 / 页面栈超 10 层时是静默失败,必须靠 fail 才能看到原因)
if (window.wx && window.wx.miniProgram && window.wx.miniProgram.navigateTo) {
var _nav = window.wx.miniProgram.navigateTo.bind(window.wx.miniProgram);
window.wx.miniProgram.navigateTo = function (o) {
var opt = o || {};
dbg('navigateTo 调用 → ' + opt.url, 'ok');
var _fail = opt.fail, _succ = opt.success;
opt.fail = function (err) {
dbgErr('navigateTo fail: ' + ((err && err.errMsg) || '未知原因'));
if (_fail) { try { _fail(err); } catch (e) {} }
};
opt.success = function (res) {
dbg('navigateTo success', 'ok');
if (_succ) { try { _succ(res); } catch (e) {} }
};
try { _nav(opt); dbg('navigateTo 已调用(结果见 success/fail)', 'ok'); }
catch (ex) { dbgErr('navigateTo 抛异常: ' + (ex && ex.message ? ex.message : ex)); }
};
}
// 给 switchTab 打补丁:记录每一次跳转调用 + 捕获异常 + 转发 fail/success
if (window.wx && window.wx.miniProgram && window.wx.miniProgram.switchTab) {
var _st = window.wx.miniProgram.switchTab.bind(window.wx.miniProgram);
window.wx.miniProgram.switchTab = function (o) {
var opt = o || {};
dbg('switchTab 调用 → ' + opt.url, 'ok');
var _fail = opt.fail, _succ = opt.success;
opt.fail = function (err) {
dbgErr('switchTab fail: ' + ((err && err.errMsg) || '未知原因'));
if (_fail) { try { _fail(err); } catch (e) {} }
};
opt.success = function (res) {
dbg('switchTab success', 'ok');
if (_succ) { try { _succ(res); } catch (e) {} }
};
try { _st(opt); dbg('switchTab 已调用(结果见 success/fail)', 'ok'); }
catch (ex) { dbgErr('switchTab 抛异常: ' + (ex && ex.message ? ex.message : ex)); }
};
}
// 给 navigateBack 打补丁:旧版 bridge.share 用它「触发 postMessage 投递」,
// 副作用是把 web-view 页弹掉、转发被上一页接管(场景3 要复现的 bug)。
if (window.wx && window.wx.miniProgram && window.wx.miniProgram.navigateBack) {
var _back = window.wx.miniProgram.navigateBack.bind(window.wx.miniProgram);
window.wx.miniProgram.navigateBack = function (o) {
var opt = o || {};
dbg('navigateBack 调用 → delta=' + (opt.delta || 1), 'warn');
var _bfail = opt.fail, _bsucc = opt.success;
opt.fail = function (err) {
dbgErr('navigateBack fail: ' + ((err && err.errMsg) || '未知原因'));
if (_bfail) { try { _bfail(err); } catch (e) {} }
};
opt.success = function (res) {
dbg('navigateBack success(已退回上一页)', 'warn');
if (_bsucc) { try { _bsucc(res); } catch (e) {} }
};
try { _back(opt); } catch (ex) { dbgErr('navigateBack 抛异常: ' + (ex && ex.message ? ex.message : ex)); }
};
}
// 给 postMessage 打补丁:记录每一次调用 + 捕获异常
var origPost = (window.wx && window.wx.miniProgram && window.wx.miniProgram.postMessage) ? window.wx.miniProgram.postMessage.bind(window.wx.miniProgram) : null;
if (window.wx && window.wx.miniProgram) {
window.wx.miniProgram.postMessage = function (msg) {
dbg('postMessage 调用 → ' + JSON.stringify(msg), 'ok');
if (!origPost) { dbgErr('postMessage: 无原始方法,无法发送'); return; }
try { origPost(msg); dbg('postMessage 已发送', 'ok'); }
catch (ex) { dbgErr('postMessage 抛异常: ' + (ex && ex.message ? ex.message : ex)); }
};
} else {
dbg('未安装 postMessage 补丁(wx.miniProgram 不存在)', 'warn');
}
/* ============================================================
③ 页面数据渲染
============================================================ */
function render(a) {
var authed = a.isAuthorized();
dbg('render(): isAuthorized=' + authed + ' readAuth=' + JSON.stringify(a.readAuth()), 'muted');
el('authState').textContent = authed ? '✅ 已授权(昵称/头像/手机号)' : '🔓 未授权,点下方「授权登录」';
el('btnAuth').style.display = authed ? 'none' : 'block';
el('rPhone').textContent = a.readAuth().phone || '—';
el('rNick').textContent = a.readAuth().nickname || '—';
if (a.readAuth().avatar) { el('rAvatarWrap').innerHTML = '<img src="' + a.readAuth().avatar + '" alt="头像">'; }
}
/* ============================================================
④-b 场景3:分享深链验证
------------------------------------------------------------
规则:web-view 里的 H5 **不能**自己拉起分享面板,卡片只能由宿主小程序页
的 onShareAppMessage 产出。正确做法是 H5 只发 postMessage(传标题/图),
宿主用 options.webViewUrl(当前 web-view 真实地址,含 hash/SPA 路由)拼深链。
❌ 旧做法:postMessage 后调 navigateBack「触发投递」——会把 web-view 页弹掉,
转发被上一页接管,接收者落到首页(本页可复现)。
============================================================ */
function shRefresh() {
if (!el('shCur')) return;
el('shCur').textContent = location.href;
var m = (location.hash || '').replace(/^#\/?/, '');
el('shMark').textContent = m || '(未设置)';
}
function shMakeMarker() {
var n = Date.now().toString(36);
location.hash = '#/share-probe/' + n; // 模拟 H5 应用的 hash 深链(webview 不丢 hash)
shRefresh();
dbg('已写入深链标记 → #/share-probe/' + n, 'ok');
wxAuth.toast('深链标记:' + n);
}
function shRequest(useNavigateBack) {
var mp = window.wx && window.wx.miniProgram;
if (!mp || !mp.postMessage) {
dbgErr('不在小程序 web-view(无 wx.miniProgram),无法分享');
wxAuth.toast('请在小程序 web-view 中打开本页');
return;
}
mp.postMessage({ data: {
action: 'share',
title: 'wx-h5-demo · 分享深链验证',
href: location.href,
summary: '接收者应打开本页(含 hash 标记),而不是小程序首页',
imageUrl: 'https://mp.yizhezhe.com/mama-box/assets/resources/report.png'
} });
if (useNavigateBack) {
dbg('❌ 复现旧 bug:postMessage 后调用 navigateBack({delta:1}),会退出本 web-view 页', 'warn');
mp.navigateBack({ delta: 1, fail: function (err) { dbgErr('navigateBack fail: ' + ((err && err.errMsg) || '未知原因')); } });
} else {
dbg('✅ 已请求分享(本页未跳)。请点右上角「···」→ 转发;卡片链接应为:' + location.href, 'ok');
wxAuth.toast('请点右上角「···」→ 转发给朋友');
}
}
/* ============================================================
④ 初始化:环境检测 + 读取授权
============================================================ */
function init() {
wxAuth.init(function (a) {
var envTxt = a.inWebview ? '小程序 web-view' : (a.MODE === 'wechat-browser' ? '微信浏览器' : '纯浏览器');
dbg('init 回调: envTxt=' + envTxt + ' MODE=' + a.MODE + ' inWebview=' + a.inWebview, 'ok');
el('envTxt').textContent = envTxt;
show(a.inWebview ? 'ok' : 'no', envTxt); // 修:之前 show() 从未被调用,标签永远停在初始「纯浏览器」
el('envHint').style.display = a.inWebview ? 'none' : 'block';
render(a);
});
}
document.addEventListener('DOMContentLoaded', function () {
init();
// 场景3:分享深链验证
shRefresh();
window.addEventListener('hashchange', shRefresh);
el('btnShMark').addEventListener('click', function () { dbg('🖱️ 点击「生成深链标记」'); shMakeMarker(); });
el('btnShOk').addEventListener('click', function () { dbg('🖱️ 点击「✅ 正确分享」'); shRequest(false); });
el('btnShBad').addEventListener('click', function () { dbg('🖱️ 点击「❌ 复现旧 bug」'); shRequest(true); });
el('btnAuth').addEventListener('click', function () {
dbg('🖱️ 点击「授权登录」按钮');
if (!(window.wx && window.wx.miniProgram)) {
dbgErr('requestProfile 被拒绝:window.wx.miniProgram 不存在(不在微信 web-view 或 jweixin 未加载)');
} else {
dbg('requestProfile: UA 含 MicroMessenger = ' + (/MicroMessenger/i.test(navigator.userAgent) ? '✅ 是' : '❌ 否') + '(否→秒提示;是→getEnv 确认后跳转)', 'ok');
}
wxAuth.requestProfile();
});
el('btnMall').addEventListener('click', function () {
dbg('🖱️ 点击「进商城」按钮');
wxAuth.goMall();
});
/* ============================================================
场景4 · 返回首页:三条正路 + 反例/降级(按钮在页面顶部那张卡)
⚠️ 这些按钮点下去就 location.href 跳走了,**页内日志面板看不到**(它随页面销毁)——
所以关键信息同时进 console(dbg() 已镜像到 console.log('[dbg]', …)),
真机上用 vConsole / 开发者工具看 console 历史。
============================================================ */
function identityTxt() {
if (!(wxAuth && wxAuth.identity)) return '(wx-auth.js 版本过旧,没有 identity() 方法)';
var id = wxAuth.identity();
return (id.openid || '(无)') + ' from=' + id.from + (id.unionid ? ' unionid=' + id.unionid : '');
}
function refreshIdNow() { var n = el('idNow'); if (n) n.textContent = identityTxt(); }
function clearIdCache() {
try {
sessionStorage.removeItem('mmbox.identity');
dbg('🧹 已清 sessionStorage[mmbox.identity]', 'ok');
/* ⚠️ 清完**不要**再调 refreshIdNow()/identity() 去刷新上面那行 ——
本页 URL 上还带着宿主注入的身份,"URL 优先"逻辑会立刻把它写回缓存,
等于白清(本地实测踩过:⑤ 因此复现不出「身份不完整」)。这里只改文案。 */
var n = el('idNow'); if (n) n.textContent = '(缓存已清空 · 跳转后不再有兜底)';
} catch (e) { dbgErr('清缓存失败: ' + e.message); }
}
function jump(url) { try { location.href = url; } catch (e) { dbgErr('跳转失败: ' + e.message); } }
/* ②③⑤ 用**同源相对地址**:同源缓存本来就只在本 origin 内有效,这样写
既和生产等价(本页在 mp.yizhezhe.com/wx-h5-demo/),又能被本地/其它挂载点复用。
①⑥ 仍走库的 goHome()(绝对地址)—— 那正是要演示的 API。 */
var HOME = location.origin + '/mama-box/';
el('btnHomeGo').addEventListener('click', function () {
dbg('🖱️ ① goHome() 跳转前 identity(): ' + identityTxt());
dbg(' 预期:首页认得你(goHome 会自己带上身份)', 'ok');
wxAuth.goHome();
});
el('btnHomeUrl').addEventListener('click', function () {
var id = (wxAuth && wxAuth.identity) ? wxAuth.identity() : { openid: '', unionid: '' };
var q = id.openid
? '?openid=' + encodeURIComponent(id.openid) + (id.unionid ? '&unionid=' + encodeURIComponent(id.unionid) : '')
: '';
var u = HOME + q;
dbg('🖱️ ② 手拼 URL 带参数:' + (q ? u : '(identity() 为空,只能裸跳 → 会露出「身份不完整」)'));
dbg(' 预期:首页认得你', 'ok');
jump(u);
});
el('btnHomeBare').addEventListener('click', function () {
dbg('🖱️ ③ 裸跳(反例):' + HOME);
dbg(' 预期:URL 无身份;若同源缓存里有(本页刚进来时存过)通常仍能认出你 —— 那是兜底生效,不是这条跳法对');
jump(HOME);
});
el('btnHomeSwitch').addEventListener('click', function () {
dbg('🖱️ ④ switchTab → /pages/index/index(小程序首页壳,宿主会重新注入身份)');
if (window.wx && wx.miniProgram && wx.miniProgram.switchTab) {
wx.miniProgram.switchTab({
url: '/pages/index/index',
fail: function (err) { dbgErr('switchTab fail: ' + ((err && err.errMsg) || '未知') + '(不在 web-view / 页面不存在)'); }
});
} else {
dbgErr('不在小程序 web-view 内(window.wx.miniProgram 不存在),switchTab 不可用');
}
});
el('btnHomeBareClear').addEventListener('click', function () {
dbg('🖱️ ⑤ 清同源缓存 + 裸跳(**复现线上 bug 的那条路**)');
clearIdCache();
dbg(' 预期:首页出现「身份不完整」提示条,且点重试也恢复不了');
jump(HOME);
});
el('btnHomeClearGo').addEventListener('click', function () {
dbg('🖱️ ⑥ 清同源缓存 + goHome()');
clearIdCache();
dbg(' 预期:首页仍认得你(goHome 是主动带身份,不依赖缓存)', 'ok');
wxAuth.goHome();
});
refreshIdNow();
window.addEventListener('hashchange', refreshIdNow);
});
})();
</script>
</body>
</html>