修复登录及验证码功能
This commit is contained in:
@@ -317,10 +317,14 @@ a {
|
||||
|
||||
// 验证码图片
|
||||
.captcha-img {
|
||||
width: 120px;
|
||||
height: 40px;
|
||||
flex-shrink: 0;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
border: 1px solid @border-color;
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
}
|
||||
|
||||
// ============ H5 响应式 ============
|
||||
|
||||
+57
-16
@@ -1,11 +1,11 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import { useAuth } from '../composables/useAuth'
|
||||
|
||||
// 静态路由(不需要登录的页面)
|
||||
// 静态路由(不需要登录的公开页面)
|
||||
// 注意:千万不要在 staticRoutes 中定义没有目标组件的通配重定向(如 redirect: '/'),否则在动态路由未挂载时会引发递归死循环
|
||||
const staticRoutes = [
|
||||
{ path: '/login', name: 'Login', component: () => import('../views/auth/login/index.vue'), meta: { public: true } },
|
||||
{ path: '/forgot-password', name: 'ForgotPassword', component: () => import('../views/auth/forgot/index.vue'), meta: { public: true } },
|
||||
{ path: '/:pathMatch(.*)*', redirect: '/' }
|
||||
{ path: '/forgot-password', name: 'ForgotPassword', component: () => import('../views/auth/forgot/index.vue'), meta: { public: true } }
|
||||
]
|
||||
|
||||
const router = createRouter({
|
||||
@@ -21,20 +21,18 @@ const componentMap = import.meta.glob('../views/**/index.vue')
|
||||
|
||||
// 根据菜单数据动态注册路由
|
||||
export function loadDynamicRoutes(menus) {
|
||||
// 先移除旧的动态路由
|
||||
if (dynamicRoutesLoaded) {
|
||||
router.getRoutes().forEach(r => {
|
||||
if (!staticRoutes.find(s => s.name === r.name)) {
|
||||
router.removeRoute(r.name)
|
||||
}
|
||||
})
|
||||
}
|
||||
// 先重置旧的动态路由
|
||||
resetDynamicRoutes()
|
||||
|
||||
function registerMenu(menu) {
|
||||
if (menu.component && menu.component !== '') {
|
||||
const compPath = `../views/${menu.component}.vue`
|
||||
if (menu.component && menu.component.trim() !== '') {
|
||||
const cleanComp = menu.component.replace(/\.vue$/, '').trim()
|
||||
const compPath = `../views/${cleanComp}.vue`
|
||||
const component = componentMap[compPath]
|
||||
if (component) {
|
||||
if (router.hasRoute(menu.name)) {
|
||||
router.removeRoute(menu.name)
|
||||
}
|
||||
router.addRoute({
|
||||
path: menu.path,
|
||||
name: menu.name,
|
||||
@@ -48,6 +46,21 @@ export function loadDynamicRoutes(menus) {
|
||||
}
|
||||
})
|
||||
}
|
||||
} else if (menu.redirect && menu.redirect.trim() !== '') {
|
||||
if (router.hasRoute(menu.name)) {
|
||||
router.removeRoute(menu.name)
|
||||
}
|
||||
router.addRoute({
|
||||
path: menu.path,
|
||||
name: menu.name,
|
||||
redirect: menu.redirect,
|
||||
meta: {
|
||||
title: menu.title,
|
||||
icon: menu.icon,
|
||||
requireAuth: menu.require_auth,
|
||||
requireAdmin: menu.require_admin
|
||||
}
|
||||
})
|
||||
}
|
||||
if (menu.children && menu.children.length > 0) {
|
||||
menu.children.forEach(registerMenu)
|
||||
@@ -55,14 +68,26 @@ export function loadDynamicRoutes(menus) {
|
||||
}
|
||||
|
||||
menus.forEach(registerMenu)
|
||||
|
||||
// 动态路由挂载完毕后,在末尾注册通配重定向到首页
|
||||
if (router.hasRoute('NotFound')) {
|
||||
router.removeRoute('NotFound')
|
||||
}
|
||||
router.addRoute({
|
||||
path: '/:pathMatch(.*)*',
|
||||
name: 'NotFound',
|
||||
redirect: '/'
|
||||
})
|
||||
|
||||
dynamicRoutesLoaded = true
|
||||
}
|
||||
|
||||
// 重置动态路由(登出时调用)
|
||||
export function resetDynamicRoutes() {
|
||||
dynamicRoutesLoaded = false
|
||||
const staticNames = staticRoutes.map(s => s.name)
|
||||
router.getRoutes().forEach(r => {
|
||||
if (!staticRoutes.find(s => s.name === r.name)) {
|
||||
if (r.name && !staticNames.includes(r.name)) {
|
||||
router.removeRoute(r.name)
|
||||
}
|
||||
})
|
||||
@@ -76,7 +101,23 @@ router.beforeEach(async (to, from, next) => {
|
||||
if (isLogin.value && expireAt && Date.now() > parseInt(expireAt)) {
|
||||
logout()
|
||||
resetDynamicRoutes()
|
||||
next({ path: '/login', query: { redirect: to.fullPath } })
|
||||
next({ path: '/login', query: to.path !== '/' ? { redirect: to.fullPath } : undefined })
|
||||
return
|
||||
}
|
||||
|
||||
// 已登录状态下访问登录页,直接跳转首页
|
||||
if (to.path === '/login' && isLogin.value) {
|
||||
if (!dynamicRoutesLoaded) {
|
||||
try {
|
||||
await loadMenus()
|
||||
} catch (e) {
|
||||
logout()
|
||||
resetDynamicRoutes()
|
||||
next()
|
||||
return
|
||||
}
|
||||
}
|
||||
next('/')
|
||||
return
|
||||
}
|
||||
|
||||
@@ -88,7 +129,7 @@ router.beforeEach(async (to, from, next) => {
|
||||
|
||||
// 未登录跳登录
|
||||
if (!isLogin.value) {
|
||||
next({ path: '/login', query: { redirect: to.fullPath } })
|
||||
next({ path: '/login', query: to.path !== '/' ? { redirect: to.fullPath } : undefined })
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<el-input v-model="loginForm.password" type="password" placeholder="密码" size="large" show-password :prefix-icon="LockIcon" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="captcha_code">
|
||||
<div style="display:flex;gap:10px;width:100%">
|
||||
<div style="display:flex;gap:10px;width:100%;align-items:center">
|
||||
<el-input v-model="loginForm.captcha_code" placeholder="验证码" size="large" :prefix-icon="KeyIcon" style="flex:1" />
|
||||
<img :src="captchaImg" class="captcha-img" @click="refreshCaptcha" title="点击刷新" />
|
||||
</div>
|
||||
@@ -42,7 +42,7 @@
|
||||
<el-input v-model="regForm.email" placeholder="邮箱(用于找回密码)" size="large" :prefix-icon="MailIcon" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="captcha_code">
|
||||
<div style="display:flex;gap:10px;width:100%">
|
||||
<div style="display:flex;gap:10px;width:100%;align-items:center">
|
||||
<el-input v-model="regForm.captcha_code" placeholder="验证码" size="large" :prefix-icon="KeyIcon" style="flex:1" />
|
||||
<img :src="captchaImg" class="captcha-img" @click="refreshCaptcha" title="点击刷新" />
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user