From 00bf4bcfd62db8602cbd8ffa3f779ede4a64edd6 Mon Sep 17 00:00:00 2001 From: ZF sun <34314687@qq.com> Date: Wed, 15 Jul 2026 09:05:50 +0800 Subject: [PATCH] feat(mp-share): add disabled share page list and hide share menu for specific pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增了禁用分享的页面配置列表,针对指定页面主动隐藏转发按钮,同时优化了分享逻辑的兜底和性能。 具体包括: 1. 增加_DISABLED_PAGES集合管理禁分享页面路由 2. 添加页面禁用检查和隐藏分享菜单工具方法 3. 在created和onLoad阶段自动隐藏对应页面的转发按钮 4. 优化onShow和分享钩子的禁用逻辑,避免无效请求和调用 --- common/js/mp-share-default.js | 120 +++++++++++++++++++++++++++++----- 1 file changed, 105 insertions(+), 15 deletions(-) diff --git a/common/js/mp-share-default.js b/common/js/mp-share-default.js index 77379e6..e2d8e28 100644 --- a/common/js/mp-share-default.js +++ b/common/js/mp-share-default.js @@ -30,6 +30,68 @@ const _safeGetCurrentPage = () => { } }; +/** + * 关闭分享能力的页面 route 列表(不带前导斜杠,与 mp-weixin page.route 保持一致) + * + * 为什么需要: + * mp-share-default.js 通过 Vue.mixin 全局注入 onShareAppMessage / onShareTimeline, + * 但有些页面不适合"分享": + * 1) webview 容器页: 转发它等于转发一个 iframe 壳,无意义且会暴露内部 src + * 2) 隐私弹窗 / 登录中转页: 状态不稳定,转出去体验差 + * 3) 任何业务明确要求"不分享"的页面 + * + * 命中后行为: + * - mixin 内部不再拉取分享配置(节省一次 HTTP 请求) + * - mixin 注入的 onShareAppMessage / onShareTimeline / $mpShare_* 工具方法仍然存在, + * 但内部立即调用 wx.hideShareMenu() 把转发按钮从右上角菜单中隐藏 + * - 这两条防线双保险:即使 mixin 钩子被业务侧转发链路误触发,也不会显示分享弹窗 + * + * 备选方案对比(都没选,原因列在下方): + * - 在 created 里 this.onShareAppMessage = undefined: + * Vue mixin 合并策略会把 undefined 视为"未声明",mixin 的钩子仍然生效 → 不可靠 + * - mixin 内 return null / 不 return: + * 微信会回退到默认 title 转发,按钮仍显示 → 不可靠 + * - 使用 wx.hideShareMenu(本方案采用): + * 微信官方 API,会立即把"转发"按钮从当前页右上角菜单中隐藏,行为最稳 + */ +const _DISABLED_PAGES = new Set([ + 'pages_tool/webview/webview', // webview 容器,转发无意义 +]); + +const _isCurrentPageDisabled = () => { + const page = _safeGetCurrentPage(); + if (!page) return false; + const route = (page.route || (page.$page && page.$page.path) || '').replace(/^\//, ''); + return _DISABLED_PAGES.has(route); +}; + +/** + * 主动隐藏当前页的"转发"按钮 + * - 只能在 mp-weixin 环境调用(其它平台 wx 全局不存在) + * - 必须在 onLoad 之后调用(需要 Page 实例已注册完成) + * - 失败时静默吞掉(权限/版本/非微信环境都可能导致失败) + */ +const _hideShareMenu = () => { + try { + // #ifdef MP-WEIXIN + if (typeof wx !== 'undefined' && typeof wx.hideShareMenu === 'function') { + wx.hideShareMenu({ + menus: ['shareAppMessage', 'shareTimeline'] + }); + } + // #endif + } catch (e) { + // 静默:旧基础库可能不支持 menus 参数,降级到无参版本 + try { + // #ifdef MP-WEIXIN + if (typeof wx !== 'undefined' && typeof wx.hideShareMenu === 'function') { + wx.hideShareMenu(); + } + // #endif + } catch (e2) { /* ignore */ } + } +}; + const _getCurrentPath = (withQuery = true) => { const page = _safeGetCurrentPage(); if (!page) return ''; @@ -90,11 +152,30 @@ export default { __mpShareCache: null, // 当前页面的分享配置 }; }, + /** + * 在实例创建阶段检查当前页面是否在 _DISABLED_PAGES 列表中。 + * 命中后调用 wx.hideShareMenu 把当前页的"转发"按钮从右上角菜单中隐藏。 + */ + created() { + try { + if (_isCurrentPageDisabled()) { + // 立即隐藏(此时 wx 还没完全就绪,先尝试一次;失败也无所谓,onLoad 会再调一次) + _hideShareMenu(); + } + } catch (e) {} + }, onLoad() { try { + if (_isCurrentPageDisabled()) { + // 命中关闭列表的页面: + // 1) 再次调 wx.hideShareMenu(此时 Page 已就绪,稳定生效) + // 2) 不再拉取分享配置,避免无谓请求 + _hideShareMenu(); + return; + } const path = _getCurrentPath(true); _getShareConfig(path).then(cfg => { - // 后端未返回配置时,注入站点名作为默认标题 + // 后端未返回配置时,注入站点名作为默认标题 if (cfg && !cfg.title) { const siteName = (this.$store && this.$store.state && this.$store.state.siteInfo && this.$store.state.siteInfo.site_name) || ''; cfg.title = siteName || '小程序分享'; @@ -104,21 +185,27 @@ export default { } catch (e) {} }, onShow() { - // 兜底:进入页面后如果尚未就绪,再异步拉一次 - if (!this.__mpShareCache) { - try { - const path = _getCurrentPath(true); - _getShareConfig(path).then(cfg => { - this.__mpShareCache = cfg; - }); - } catch (e) {} - } + // 兜底:进入页面后如果尚未就绪,再异步拉一次 + if (this.__mpShareCache) return; + if (_isCurrentPageDisabled()) return; // 命中关闭列表,不再拉 + try { + const path = _getCurrentPath(true); + _getShareConfig(path).then(cfg => { + this.__mpShareCache = cfg; + }); + } catch (e) {} }, /** - * 全局默认 onShareAppMessage: - * uni-app 规范:组件自身的钩子优先级 > mixin,因此已显式声明的页面不受影响。 + * 全局默认 onShareAppMessage: + * uni-app 规范:组件自身的钩子优先级 > mixin,因此已显式声明的页面不受影响。 */ onShareAppMessage() { + // 命中禁用列表的页面:即使 wx.hideShareMenu 因某些原因没生效, + // 这里直接 return undefined / 也不主动拼 cfg,让微信回退到默认行为 + // (主防线是 wx.hideShareMenu,这里只是兜底) + if (_isCurrentPageDisabled()) { + return undefined; + } const cfg = this.__mpShareCache; if (cfg && cfg.title) { return { @@ -127,17 +214,20 @@ export default { imageUrl: cfg.imageUrl || '' }; } - // 后端无配置时:使用站点名 + 当前路径 + // 后端无配置时:使用站点名 + 当前路径 return { title: _buildFallback(_getCurrentPath(true)).title, path: _getCurrentPath(true) }; }, /** - * 全局默认 onShareTimeline(朋友圈): - * 朋友圈只支持 query(不能直接传 path),从 cfg.path 中抽取 ? 之后的 query。 + * 全局默认 onShareTimeline(朋友圈): + * 朋友圈只支持 query(不能直接传 path),从 cfg.path 中抽取 ? 之后的 query。 */ onShareTimeline() { + if (_isCurrentPageDisabled()) { + return undefined; + } const cfg = this.__mpShareCache; if (cfg && cfg.title) { const path = cfg.path || _getCurrentPath(true);