hookehuyr

feat(wx): 启用微信分享API并优化OAuth流程

修复微信JSSDK签名URL包含hash导致的重复刷新问题
在OAuth流程中保留原始hash路由位置
重构路由守卫代码格式
1 <!-- 1 <!--
2 * @Date: 2025-03-20 19:53:12 2 * @Date: 2025-03-20 19:53:12
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-10-15 10:11:57 4 + * @LastEditTime: 2025-12-09 16:43:21
5 * @FilePath: /mlaj/src/App.vue 5 * @FilePath: /mlaj/src/App.vue
6 * @Description: 入口文件 6 * @Description: 入口文件
7 --> 7 -->
...@@ -27,21 +27,28 @@ import 'vant/es/toast/style' ...@@ -27,21 +27,28 @@ import 'vant/es/toast/style'
27 provideAuth(); // 提供全局认证状态 27 provideAuth(); // 提供全局认证状态
28 provideCart('single'); // 提供全局购物车状态,单一商品模式 28 provideCart('single'); // 提供全局购物车状态,单一商品模式
29 29
30 -// 初始化微信配置 30 +/**
31 + * @function initWxConfig
32 + * @description 初始化微信 JSSDK 配置;签名 URL 必须使用不包含 hash 的完整地址,避免进入详情页在微信环境出现重复刷新。
33 + * @returns {void}
34 + */
31 const initWxConfig = async () => { 35 const initWxConfig = async () => {
32 - const raw_url = encodeURIComponent(location.pathname + location.hash); 36 + // 使用不带 hash 的完整 URL 参与签名,规避重复刷新问题
37 + const sign_url = encodeURIComponent(window.location.href.split('#')[0]);
33 try { 38 try {
34 - const wxJs = await wxJsAPI({ url: raw_url }) 39 + const wxJs = await wxJsAPI({ url: sign_url });
35 - wxJs.data.jsApiList = apiList 40 + wxJs.data.jsApiList = apiList;
36 - wx.config(wxJs.data) 41 + wx.config(wxJs.data);
37 wx.ready(() => { 42 wx.ready(() => {
38 - wx.showAllNonBaseMenuItem() 43 + // 微信 JSSDK 初始化完成,展示所有非基础菜单项
39 - }) 44 + wx.showAllNonBaseMenuItem();
45 + });
40 wx.error((err) => { 46 wx.error((err) => {
41 - console.warn('微信配置初始化失败:', err) 47 + // 微信 JSSDK 初始化失败日志
42 - }) 48 + console.warn('微信配置初始化失败:', err);
49 + });
43 } catch (error) { 50 } catch (error) {
44 - console.error('初始化微信配置失败:', error) 51 + console.error('初始化微信配置失败:', error);
45 } 52 }
46 } 53 }
47 54
......
...@@ -6,8 +6,8 @@ ...@@ -6,8 +6,8 @@
6 * @Description: 文件描述 6 * @Description: 文件描述
7 */ 7 */
8 export const apiList = [ 8 export const apiList = [
9 - // "updateAppMessageShareData", 9 + "updateAppMessageShareData",
10 - // "updateTimelineShareData", 10 + "updateTimelineShareData",
11 "onMenuShareTimeline", 11 "onMenuShareTimeline",
12 "onMenuShareAppMessage", 12 "onMenuShareAppMessage",
13 "onMenuShareQQ", 13 "onMenuShareQQ",
......
...@@ -38,5 +38,25 @@ app.config.warnHandler = () => null; ...@@ -38,5 +38,25 @@ app.config.warnHandler = () => null;
38 38
39 app.config.globalProperties.$http = axios; // 关键语句 39 app.config.globalProperties.$http = axios; // 关键语句
40 app.component('font-awesome-icon', FontAwesomeIcon) 40 app.component('font-awesome-icon', FontAwesomeIcon)
41 +/**
42 + * @function restoreHashAfterOAuth
43 + * @description 前端复原 OAuth 回跳的 hash 路由位置:当 URL 中存在 ret_hash 参数且当前无 hash 时,将其拼回地址栏。
44 + * @returns {void}
45 + */
46 +function restoreHashAfterOAuth() {
47 + const url = new URL(window.location.href);
48 + const ret_hash = url.searchParams.get('ret_hash');
49 + if (ret_hash && !window.location.hash) {
50 + // 删除 ret_hash,保留其他查询参数
51 + url.searchParams.delete('ret_hash');
52 + const base = url.toString().split('#')[0];
53 + const new_url = base + ret_hash;
54 + // 使用 replaceState 避免再次刷新与历史记录污染
55 + window.history.replaceState(null, '', new_url);
56 + }
57 +}
58 +
59 +// 在安装路由前进行一次 hash 复原,确保初始路由正确
60 +restoreHashAfterOAuth()
41 app.use(router) 61 app.use(router)
42 app.mount('#app') 62 app.mount('#app')
......
1 /* 1 /*
2 * @Date: 2025-03-20 20:36:36 2 * @Date: 2025-03-20 20:36:36
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-12-04 11:08:58 4 + * @LastEditTime: 2025-12-09 16:47:55
5 * @FilePath: /mlaj/src/router/guards.js 5 * @FilePath: /mlaj/src/router/guards.js
6 * @Description: 路由守卫逻辑 6 * @Description: 路由守卫逻辑
7 */ 7 */
...@@ -54,6 +54,11 @@ export const checkWxAuth = async () => { ...@@ -54,6 +54,11 @@ export const checkWxAuth = async () => {
54 * @description 手动发起微信授权登录(仅在用户点击微信图标时触发) 54 * @description 手动发起微信授权登录(仅在用户点击微信图标时触发)
55 * @returns {void} 55 * @returns {void}
56 */ 56 */
57 +/**
58 + * @function startWxAuth
59 + * @description 手动发起微信授权登录;使用不含 hash 的完整 URL 作为回跳参数,避免微信浏览器对 hash 的处理差异导致回跳异常。
60 + * @returns {void}
61 + */
57 export const startWxAuth = async () => { 62 export const startWxAuth = async () => {
58 // 开发环境不触发微信授权 63 // 开发环境不触发微信授权
59 if (import.meta.env.DEV) { 64 if (import.meta.env.DEV) {
...@@ -77,9 +82,10 @@ export const startWxAuth = async () => { ...@@ -77,9 +82,10 @@ export const startWxAuth = async () => {
77 // 探测失败不影响授权流程,继续跳转 82 // 探测失败不影响授权流程,继续跳转
78 } 83 }
79 84
80 - // 跳转到微信授权地址 85 + // 跳转到微信授权地址(签名与回跳使用不含 hash 的完整 URL),并通过 ret_hash 参数保留授权前页面位置
81 - const raw_url = encodeURIComponent(location.href); 86 + const base_url = encodeURIComponent(window.location.href.split('#')[0]);
82 - const short_url = `/srv/?f=behalo&a=openid&res=${raw_url}`; 87 + const ret_hash = encodeURIComponent(window.location.hash || '');
88 + const short_url = `/srv/?f=behalo&a=openid&res=${base_url}&ret_hash=${ret_hash}`;
83 location.href = short_url; 89 location.href = short_url;
84 } 90 }
85 91
......