Files
mama-box/js/host-nav.js
deploy dc54a29748 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>
2026-11-09 14:10:54 +00:00

77 lines
4.2 KiB
JavaScript
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.
/* ============================================================
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);