hookehuyr

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

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