v26110903 广场/专题/计算器/测一测在小程序里也开容器页,复制链接直达;容器页返回走 navigateBack
新增 js/host-nav.js(MBHost.open/back/home + 页内同站 <a> 拦截): - 首页进广场、专题问题、百宝箱测一测/计算器 → 容器页;广场点笔记 → 容器页 ?n= - 容器页(_hv=1)里笔记关闭、广场/专题/计算器返回 → navigateBack;广场「返回」tab → switchTab 首页 - 失败或不在小程序照旧本页跳转 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
/* 页面版本号(YYMMDD+序号):显示在「关于兜爸心选」页底部;bump 时同步 head 注释与 ?v= */
|
||||
var VER = '26110901';
|
||||
var VER = '26110903';
|
||||
const $ = (s, c) => (c || document).querySelector(s);
|
||||
const $$ = (s, c) => Array.from((c || document).querySelectorAll(s));
|
||||
|
||||
@@ -181,6 +181,7 @@
|
||||
return u.href;
|
||||
}
|
||||
function openInHost(target) {
|
||||
if (window.MBHost) return window.MBHost.open(target); // js/host-nav.js(加 _hv=1,子页面返回走 navigateBack)
|
||||
const mp = window.wx && window.wx.miniProgram;
|
||||
if (!inMiniProgram() || !mp || typeof mp.navigateTo !== 'function') return false;
|
||||
if (Date.now() - hostNavAt < 1000) return true; // 连点:上一次 navigateTo 还在路上
|
||||
@@ -194,6 +195,7 @@
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* ================= H5 宿主恢复:冷启动回到上次进入的 H5 应用(2026-09-22) =================
|
||||
需求:在小程序里进入某个 H5 应用后退出小程序,再次进入要恢复那个应用。
|
||||
数据源:box_app GET /api/mp/public/last-app?openid=(Redis,per-openid,7 天 TTL)
|
||||
@@ -4466,6 +4468,7 @@
|
||||
haptic();
|
||||
const url = 'guangchang/' + (id ? '?t=' + encodeURIComponent(id) : '') + location.hash;
|
||||
reportHostLocation(new URL(url, location.href).href);
|
||||
if (openInHost(url)) return;
|
||||
location.href = url;
|
||||
}
|
||||
/* 「全部」:只放热门,四块(家庭/婚姻/职场/母婴)轮流排,别一排全是同一块;选了某块:该块热门在前、其余在后 */
|
||||
@@ -4544,6 +4547,7 @@
|
||||
haptic();
|
||||
const url = 'guangchang/?mine=1' + location.hash;
|
||||
reportHostLocation(new URL(url, location.href).href);
|
||||
if (openInHost(url)) return;
|
||||
location.href = url;
|
||||
});
|
||||
$('.gch-who', sec).before(b);
|
||||
@@ -6048,7 +6052,7 @@
|
||||
const a = document.createElement('div'); a.className = 'qa-a';
|
||||
a.textContent = x.a || '';
|
||||
/* 有专题页的条目(首页那 6 个)点了直接进专题页 */
|
||||
h.addEventListener('click', () => { if (x.href) { haptic(); location.href = qaHref(x.href); return; } it.classList.toggle('open'); haptic(); });
|
||||
h.addEventListener('click', () => { if (x.href) { haptic(); const u = qaHref(x.href); if (!openInHost(u)) location.href = u; return; } it.classList.toggle('open'); haptic(); });
|
||||
it.appendChild(h); it.appendChild(a);
|
||||
L.appendChild(it);
|
||||
});
|
||||
@@ -6913,6 +6917,7 @@
|
||||
haptic();
|
||||
const url = 'guangchang/?fav=1' + location.hash;
|
||||
reportHostLocation(new URL(url, location.href).href);
|
||||
if (openInHost(url)) return;
|
||||
location.href = url;
|
||||
});
|
||||
})();
|
||||
|
||||
76
js/host-nav.js
Normal file
76
js/host-nav.js
Normal file
@@ -0,0 +1,76 @@
|
||||
/* ============================================================
|
||||
host-nav.js · 小程序里换页开「容器页」(2026-11-09 用户)
|
||||
------------------------------------------------------------
|
||||
「在任何一个子页面点小程序『复制链接』,打开应该进到那个子页面,现在都进首页」——
|
||||
「复制链接」复制的是**小程序当前页面**的路径和参数。首页壳里 location.href 换页,小程序页面一直是首页壳,
|
||||
复制出来永远是首页。所以在小程序里进子页面 / 应用 / 广场笔记时,navigateTo 通用容器
|
||||
pages/annex/web_view/index?url=<净地址>(分享卡片落地用的同一个页,容器按打开者自己的身份注入),
|
||||
小程序当前页就是那一页。
|
||||
|
||||
MBHost.open(url, fallback) 小程序里开容器页;不在小程序 → false(调用方照旧 location.href);
|
||||
navigateTo 失败(页面栈满 10 层等)→ 调 fallback,没给就 location.href = url
|
||||
MBHost.back(fallback) 本页是 open() 开出来的容器页(地址带 _hv=1)→ navigateBack 回上一页,返回 true;
|
||||
后退失败(复制链接直接打开、没有上一页)→ 调 fallback
|
||||
MBHost.home(fallback) 同上条件 → switchTab 回小程序首页(首页壳是 tabBar 页,原来停的位置还在)
|
||||
⚠️ url 只放净地址:去掉 openid/unionid/__no_identity/return_url 和 hash 里的身份,复制出去不带分享人身份。
|
||||
⚠️ 加 _hv=1 只为让页面知道「我在容器页里」,返回时用 navigateBack,不用在容器里再开一个首页。
|
||||
============================================================ */
|
||||
(function (g) {
|
||||
'use strict';
|
||||
if (g.MBHost) return;
|
||||
var VIEW = '/pages/annex/web_view/index';
|
||||
var at = 0;
|
||||
function mp() { return g.wx && g.wx.miniProgram; }
|
||||
function inMp() { return g.__wxjs_environment === 'miniprogram' || /miniProgram/i.test(navigator.userAgent); }
|
||||
function inView() { return /[?&]_hv=1(&|$)/.test(location.search); }
|
||||
function clean(url) {
|
||||
var u = new URL(url, location.href);
|
||||
['openid', 'unionid', '__no_identity', 'return_url', 'norestore'].forEach(function (k) { u.searchParams.delete(k); });
|
||||
if (/(^|[#&])(openid|unionid|phone|nickname|avatar|norestore)=/.test(u.hash)) u.hash = '';
|
||||
u.searchParams.set('_hv', '1');
|
||||
return u.href;
|
||||
}
|
||||
var H = {
|
||||
inMp: inMp,
|
||||
inView: inView,
|
||||
open: function (url, fallback) {
|
||||
var m = mp();
|
||||
if (!inMp() || !m || typeof m.navigateTo !== 'function') return false;
|
||||
if (Date.now() - at < 1000) return true; // 连点:上一次 navigateTo 还在路上
|
||||
var c;
|
||||
try { c = clean(url); } catch (e) { return false; }
|
||||
at = Date.now();
|
||||
m.navigateTo({
|
||||
url: VIEW + '?url=' + encodeURIComponent(c),
|
||||
fail: function () { at = 0; if (fallback) fallback(); else location.href = url; }
|
||||
});
|
||||
return true;
|
||||
},
|
||||
back: function (fallback) {
|
||||
var m = mp();
|
||||
if (!inView() || !inMp() || !m || typeof m.navigateBack !== 'function') return false;
|
||||
m.navigateBack({ delta: 1, fail: function () { if (fallback) fallback(); } });
|
||||
return true;
|
||||
},
|
||||
home: function (fallback) {
|
||||
var m = mp();
|
||||
if (!inView() || !inMp() || !m || typeof m.switchTab !== 'function') return false;
|
||||
m.switchTab({ url: '/pages/index/index', fail: function () { if (fallback) fallback(); } });
|
||||
return true;
|
||||
}
|
||||
};
|
||||
g.MBHost = H;
|
||||
|
||||
/* 页面里的 <a href> 指向本站别的页面:小程序里也开容器页(别人已经 preventDefault 的不管) */
|
||||
document.addEventListener('click', function (e) {
|
||||
if (e.defaultPrevented || e.button || e.metaKey || e.ctrlKey || !inMp()) return;
|
||||
var a = e.target && e.target.closest && e.target.closest('a[href]');
|
||||
if (!a || a.target || a.hasAttribute('download')) return;
|
||||
var href = a.getAttribute('href') || '';
|
||||
if (!href || href.charAt(0) === '#' || /^(javascript|mailto|tel):/i.test(href)) return;
|
||||
var u;
|
||||
try { u = new URL(href, location.href); } catch (err) { return; }
|
||||
if (u.origin !== location.origin || u.pathname === location.pathname) return;
|
||||
if (H.open(u.href)) e.preventDefault();
|
||||
});
|
||||
})(window);
|
||||
@@ -264,8 +264,9 @@
|
||||
var b = e.target.closest('.kit-e,.kit-mb'); if (!b) return;
|
||||
try { navigator.vibrate && navigator.vibrate(8); } catch (x) {}
|
||||
var k = b.dataset.k;
|
||||
if (k === 'qz') location.href = 'guangchang/' + cleanQ({ c: 'ceshi' });
|
||||
else if (k === 'js') location.href = 'topic/jisuan/' + cleanQ();
|
||||
var go = function (u) { if (!(window.MBHost && MBHost.open(u))) location.href = u; }; /* 11-09 小程序里开容器页,复制链接直达(js/host-nav.js) */
|
||||
if (k === 'qz') go('guangchang/' + cleanQ({ c: 'ceshi' }));
|
||||
else if (k === 'js') go('topic/jisuan/' + cleanQ());
|
||||
else if (window.__mbOpenQA) window.__mbOpenQA('孕期百问');
|
||||
});
|
||||
})();
|
||||
|
||||
@@ -106,6 +106,7 @@
|
||||
if (window.wxAuth && wxAuth.reportLocation) wxAuth.reportLocation({ href: target });
|
||||
} catch (e) {}
|
||||
/* 11-09:小程序里开容器页,「复制链接」才能直达这个应用(同 js/app.js openInHost,url 只放净地址) */
|
||||
if (window.MBHost && MBHost.open(url, function () { location.href = target; })) return;
|
||||
var mp = window.wx && window.wx.miniProgram;
|
||||
if ((window.__wxjs_environment === 'miniprogram' || /miniProgram/i.test(navigator.userAgent)) && mp && typeof mp.navigateTo === 'function') {
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user