hookehuyr

feat(登录): 调整微信授权为手动触发方式

将微信授权逻辑从自动检查改为用户点击触发
- 移除路由守卫中的自动微信授权检查
- 新增手动触发授权方法 startWxAuth
- 登录页微信图标添加点击事件绑定
- 优化授权回跳后的登录态处理流程
......@@ -19,3 +19,8 @@ https://oa-dev.onwall.cn/f/mlaj
- 学习详情页标签指示条修复:`/src/views/profile/StudyCoursePage.vue`
- 现象:首次进入且存在“打卡互动”时,底部绿色指示条定位错误。
- 修复:新增标签容器 `ref``ResizeObserver`,按栏目数量对容器进行等分,指示条宽度与位移按分段和索引计算,异步加载第三个栏目时不再错位。
- 登录逻辑调整:仅在登录页微信图标点击时触发授权
- 变更文件:`/src/views/auth/LoginPage.vue``/src/router/guards.js``/src/router/index.js`
- 路由守卫:移除自动微信授权检查,新增 `startWxAuth` 供手动触发。
- 登录页:微信图标绑定点击事件,非微信环境提示“请在微信内打开”。
- 使用方式:进入登录页,点击微信图标进行授权登录。
......
/*
* @Date: 2025-03-20 20:36:36
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-11-19 20:37:35
* @LastEditTime: 2025-12-04 11:08:58
* @FilePath: /mlaj/src/router/guards.js
* @Description: 路由守卫逻辑
*/
......@@ -32,30 +32,65 @@ export const authRequiredRoutes = [
},
]
// TAG: 微信授权检查
/**
* @description 兼容旧逻辑的微信授权检查(不再自动跳转)
* @returns {boolean} 始终返回true,不在路由守卫内自动触发授权
*/
export const checkWxAuth = async () => {
if (!import.meta.env.DEV && wxInfo().isWeiXin) {
// 说明:根据新业务需求,微信授权不应在路由守卫中自动触发
// 此函数保留以兼容旧代码调用,但不再进行重定向
try {
const { code, data } = await getAuthInfoAPI();
if (code && !data.openid_has) {
// 直接在这里处理授权跳转
let raw_url = encodeURIComponent(location.href); // 未授权的地址
const short_url = `/srv/?f=behalo&a=openid&res=${raw_url}`;
location.href = short_url;
return false;
if (!import.meta.env.DEV && wxInfo().isWeiXin) {
// 仅做一次授权状态探测,避免无意义请求
await getAuthInfoAPI();
}
} catch (error) {
console.error('微信授权检查失败:', error)
// 忽略授权探测错误,不影响后续流程
}
return true;
}
/**
* @description 手动发起微信授权登录(仅在用户点击微信图标时触发)
* @returns {void}
*/
export const startWxAuth = async () => {
// 开发环境不触发微信授权
if (import.meta.env.DEV) {
// 开发环境下不触发微信授权登录
return;
}
return true
const info = wxInfo();
// 非微信环境不进行授权跳转
if (!info.isWeiXin) {
return;
}
// 如果已授权则不跳转;否则进入授权页
try {
const { code, data } = await getAuthInfoAPI();
if (code && data.openid_has) {
return;
}
} catch (e) {
// 探测失败不影响授权流程,继续跳转
}
// 跳转到微信授权地址
const raw_url = encodeURIComponent(location.href);
const short_url = `/srv/?f=behalo&a=openid&res=${raw_url}`;
location.href = short_url;
}
// 检查用户是否已登录
// 登录权限检查
/**
* @description 登录权限检查,未登录时重定向到登录页
* @param {*} to 目标路由对象
* @returns {true|Object} 允许通过或返回重定向对象
*/
export const checkAuth = (to) => {
const currentUser = JSON.parse(localStorage.getItem('currentUser'))
......@@ -80,7 +115,6 @@ export const checkAuth = (to) => {
if (needAuth && !currentUser) {
// 未登录时重定向到登录页面
return { path: '/login', query: { redirect: to.fullPath } }
// return { path: '/login' }
}
return true
......
/*
* @Date: 2025-03-20 20:36:36
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-08-26 09:43:50
* @LastEditTime: 2025-12-04 11:25:22
* @FilePath: /mlaj/src/router/index.js
* @Description: 路由实例创建和导出
*/
import { createRouter, createWebHashHistory } from 'vue-router'
import { routes } from './routes'
import { checkWxAuth, checkAuth } from './guards'
import { checkAuth } from './guards'
import { getUserIsLoginAPI } from '@/api/auth'
import { getUserInfoAPI } from '@/api/users'
const router = createRouter({
history: createWebHashHistory(import.meta.env.VITE_BASE || '/'),
......@@ -20,29 +22,52 @@ const router = createRouter({
// 导航守卫
router.beforeEach(async (to, from, next) => {
// 微信授权检查
const wxAuthResult = await checkWxAuth()
if (wxAuthResult !== true) {
next(wxAuthResult)
return
}
// 检查用户是否已登录
const currentUser = JSON.parse(localStorage.getItem('currentUser') || 'null')
const redirectRaw = to.query && to.query.redirect
// 登录权限检查
// 登录权限检查(不再自动触发微信授权)
const authResult = checkAuth(to)
if (authResult !== true) {
next(authResult)
return
}
// 如果用户已经在登录页面,但已经登录了,重定向到首页
if (to.path === '/login' && currentUser) {
next('/')
// 登录页统一处理授权回跳与默认重定向
if (to.path === '/login') {
/**
* 情况1:本地已有登录态
* - 有 redirect:跳回来源页
* - 无 redirect:默认跳首页
*/
if (currentUser) {
const redirect = redirectRaw ? decodeURIComponent(redirectRaw) : '/'
next(redirect)
return
}
/**
* 情况2:授权回跳但本地未写入登录态
* - 统一在路由层探测登录
* - 登录为真:写入用户信息,并按 redirect 或首页跳转
*/
try {
const { code, data } = await getUserIsLoginAPI()
if (code && data && data.is_login) {
const { code: uiCode, data: uiData } = await getUserInfoAPI()
if (uiCode) {
const mergedUser = { ...uiData.user, ...uiData.checkin }
localStorage.setItem('currentUser', JSON.stringify(mergedUser))
}
const redirect = redirectRaw ? decodeURIComponent(redirectRaw) : '/'
next(redirect)
return
}
} catch (e) {
// 静默失败,进入登录页
}
}
next()
})
......
......@@ -3,7 +3,7 @@
class="min-h-screen flex flex-col bg-gradient-to-br from-green-50 via-teal-50 to-blue-50 py-8 px-4 sm:px-6 lg:px-8"
>
<div class="sm:mx-auto sm:w-full sm:max-w-md text-center">
<van-icon name="https://cdn.ipadbiz.cn/mlaj/icon/behalo-logo-1.png" size="10rem" style="margin-bottom: 0.5rem;" />
<van-icon name="https://cdn.ipadbiz.cn/mlaj/icon/behalo-logo-1.png?imageMogr2/thumbnail/200x/strip/quality/70" size="10rem" style="margin-bottom: 0.5rem;" />
<h1 class="text-center text-3xl font-bold text-gray-800 mb-2">美乐爱觉教育</h1>
<!-- <h2 class="text-center text-xl font-medium text-gray-600">欢迎回来</h2> -->
</div>
......@@ -173,7 +173,7 @@
<div class="mt-6 flex justify-center items-center gap-4" style="flex-direction: column;">
<div class="text-sm font-medium text-gray-600">其他登录方式</div>
<div>
<img :src="weixinLogo" alt="微信登录" style="width: 40px; height: 40px; border-radius: 8px;">
<img :src="weixinLogo" alt="微信登录" style="width: 40px; height: 40px; border-radius: 8px;" @click="handleWxLoginClick">
</div>
</div>
</FrostedGlass>
......@@ -193,6 +193,8 @@ import { showToast } from "vant";
import UserAgreement from "@/components/ui/UserAgreement.vue";
import { setAuthHeaders } from "@/utils/axios";
import weixinLogo from '@/assets/images/weixin_logo_lg.jpeg'
import { startWxAuth } from '@/router/guards'
import { wxInfo } from '@/utils/tools'
const userAgreementRef = ref(null);
......@@ -248,6 +250,26 @@ const startCountdown = () => {
}, 1000);
};
/**
* @description 点击微信图标触发微信授权登录
* @returns {void}
*/
const handleWxLoginClick = async () => {
// 非微信环境提示并不触发授权
if (!import.meta.env.DEV && !wxInfo().isWeiXin) {
showToast('请在微信内打开以完成微信授权登录');
return;
}
try {
// 手动发起微信授权流程(guards.js中实现)
await startWxAuth();
} catch (e) {
console.error('微信授权触发失败:', e);
showToast('微信授权失败,请稍后重试');
}
};
const sendVerificationCode = async () => {
if (!isPhoneValid.value) {
return;
......@@ -321,4 +343,6 @@ const handleSubmit = async () => {
loading.value = false;
}
};
// 说明:授权回跳的重定向处理已移动到路由层
</script>
......