This commit is contained in:
张成
2025-10-08 19:30:09 +08:00
parent 7e888970d3
commit 99f73eff84
6 changed files with 1339 additions and 3 deletions

View File

@@ -0,0 +1,412 @@
# 登录跳转首页修复说明
## 🎯 需求
1. 登录成功后自动跳转到首页
2. 访问 `/` 时自动重定向到 `/home`
## 📋 问题分析
### 原来的问题
**登录流程**
```
用户登录
调用 handleLogin
保存 token 和 authorityMenus
显示"登录成功!"
window.location.reload() ← ❌ 刷新当前页面(/login
停留在登录页面 ❌
```
**问题**
- 登录成功后刷新了登录页面
- 虽然路由守卫会检测到 token 并重定向到首页
- 但是刷新操作会导致页面停留在 `/login`
### 路由守卫逻辑
`src/router/index.js` 中的路由守卫:
```javascript
router.beforeEach((to, from, next) => {
const token = getToken()
if (!token && to.name !== 'login') {
// 未登录且访问非登录页 → 跳转到登录页
next({ name: 'login' })
} else if (!token && to.name === 'login') {
// 未登录且访问登录页 → 允许访问
next()
} else if (token && to.name === 'login') {
// 已登录且访问登录页 → 重定向到首页
next({ name: homeName }) // homeName = 'home'
} else {
// 其他情况 → 允许访问
next()
}
})
```
**说明**
- 如果已登录(有 token且访问登录页会重定向到首页
- 但是 `window.location.reload()` 会刷新当前页面,不会触发路由跳转
### 主路由重定向配置
`src/utils/uiTool.js` 中的主路由配置:
```javascript
let mainRoute = {
path: '/',
name: '主视图',
redirect: '/home', // ← 访问 / 时重定向到 /home
component: Main,
children: []
}
```
**说明**
- 访问 `/` 时会自动重定向到 `/home`
- 前提是 `/home` 路由存在(从后端权限菜单生成)
## ✅ 解决方案
### 修改登录成功后的跳转逻辑
**修改文件**`src/views/login/login.vue`
**修改前**
```javascript
async handleSubmit({ userName, password }) {
try {
let userFrom = { name: userName, password: password }
await this.handleLogin({
userFrom,
Main,
ParentView,
Page404
})
this.$Message.success('登录成功!')
window.location.reload() // ❌ 刷新当前页面(/login
} catch (error) {
// 错误处理
}
}
```
**修改后**
```javascript
async handleSubmit({ userName, password }) {
try {
let userFrom = { name: userName, password: password }
await this.handleLogin({
userFrom,
Main,
ParentView,
Page404
})
this.$Message.success('登录成功!')
// ✅ 跳转到首页(使用 location.href 触发完整页面加载)
setTimeout(() => {
window.location.href = window.location.origin + window.location.pathname + '#/'
}, 500)
} catch (error) {
// 错误处理
}
}
```
**改进点**
- ✅ 使用 `window.location.href` 跳转到 `#/`
- ✅ 触发完整的页面加载
- ✅ 路由会重定向到 `/home`
- ✅ 延迟 500ms 确保提示信息显示
## 📊 新的登录流程
### 完整流程
```
用户输入用户名密码
点击登录
调用 handleLogin action
调用登录接口
保存 token 到 localStorage
保存用户信息到 Vuex
调用 setAuthorityMenus
├─ 尝试获取权限菜单
├─ 如果失败,使用默认菜单
└─ 保存到 localStorage.authorityMenus
显示"登录成功!"提示
延迟 500ms
跳转到 #/ (window.location.href)
触发完整页面加载
框架初始化
从 localStorage 读取 authorityMenus
生成路由(包括首页)
访问 / 路由
重定向到 /home ✅
显示首页 ✅
```
### 路由重定向流程
```
访问 #/
匹配主路由 { path: '/', redirect: '/home' }
重定向到 /home
匹配首页路由 { path: '/home', component: HomePage }
显示首页组件 ✅
```
### 已登录用户访问登录页
```
已登录用户访问 #/login
路由守卫检测到 token
检测到访问登录页
重定向到首页 next({ name: 'home' })
显示首页 ✅
```
## 🎯 关键点说明
### 1. 为什么使用 `window.location.href` 而不是 `this.$router.push`
**`this.$router.push({ path: '/' })`**
- 只是客户端路由跳转
- 不会重新加载页面
- 不会重新初始化框架
- 不会重新从 localStorage 读取 authorityMenus
**`window.location.href = '#/'`**
- 触发完整的页面加载
- 重新初始化框架
- 重新从 localStorage 读取 authorityMenus
- 重新生成路由
- 确保路由和菜单正确加载
### 2. 为什么延迟 500ms
```javascript
setTimeout(() => {
window.location.href = window.location.origin + window.location.pathname + '#/'
}, 500)
```
**原因**
- 让"登录成功!"提示信息有时间显示
- 给用户更好的体验
- 确保 localStorage 写入完成
### 3. URL 构造说明
```javascript
window.location.origin + window.location.pathname + '#/'
```
**示例**
- `window.location.origin` = `http://localhost:8080`
- `window.location.pathname` = `/``/demo-project/`
- 最终 URL = `http://localhost:8080/#/``http://localhost:8080/demo-project/#/`
**为什么这样构造**
- 兼容不同的部署路径
- 确保 hash 路由正确
- 避免硬编码 URL
### 4. 主路由的 redirect 配置
```javascript
let mainRoute = {
path: '/',
redirect: '/home',
component: Main,
children: [
{ path: '/home', name: 'home', component: HomePage },
// ... 其他路由
]
}
```
**工作原理**
- 访问 `/` 时,自动重定向到 `/home`
- `/home` 路由由后端权限菜单生成
- 如果后端没有返回首页配置,会使用默认菜单配置
## ✅ 验证清单
### 登录流程验证
- ✅ 访问登录页面
- ✅ 输入用户名密码
- ✅ 点击登录
- ✅ 显示"登录成功!"提示
- ✅ 自动跳转到首页
- ✅ 首页正确显示
- ✅ 菜单正确显示
### 路由重定向验证
- ✅ 登录后访问 `#/` 自动重定向到 `#/home`
- ✅ 已登录状态访问 `#/login` 自动重定向到 `#/home`
- ✅ 未登录状态访问 `#/home` 自动重定向到 `#/login`
### 刷新页面验证
- ✅ 登录后刷新页面,停留在当前页面
- ✅ 菜单和路由保持正确
- ✅ 用户信息保持正确
## 🔧 相关配置
### 路由守卫配置
**文件**`src/router/index.js`
```javascript
export const setupRouterGuards = (router, ViewUI, homeName = 'home') => {
router.beforeEach((to, from, next) => {
const token = getToken()
ViewUI.LoadingBar.start()
if (!token && to.name !== 'login') {
// 未登录 → 跳转到登录页
next({ name: 'login' })
} else if (!token && to.name === 'login') {
// 未登录访问登录页 → 允许
next()
} else if (token && to.name === 'login') {
// 已登录访问登录页 → 重定向到首页
next({ name: homeName })
} else {
// 其他情况 → 允许
next()
}
})
router.afterEach(to => {
ViewUI.LoadingBar.finish()
window.scrollTo(0, 0)
})
return router
}
```
### 主路由配置
**文件**`src/utils/uiTool.js`
```javascript
static getRoutes(Main, ParentView, Page404) {
let mainRoute = {
path: '/',
name: '主视图',
redirect: '/home',
component: Main,
meta: { title: '首页', notCache: true },
children: []
}
// 从 localStorage 读取权限菜单
if (localStorage.authorityMenus && localStorage.authorityMenus !== 'undefined') {
let authorityMenus = JSON.parse(localStorage.authorityMenus) || []
if (authorityMenus && authorityMenus.length > 0) {
let menus = uiTool.transformTree(authorityMenus)
let curRoutes = uiTool.menuToRoute(menus, ParentView, Page404)
// 使用后端返回的路由(包括首页)
mainRoute.children = curRoutes
}
}
return mainRoute
}
```
## 💡 最佳实践
### 1. 登录后的跳转
**推荐**
```javascript
// 使用 location.href 触发完整页面加载
window.location.href = window.location.origin + window.location.pathname + '#/'
```
**不推荐**
```javascript
// 只刷新当前页面,不跳转
window.location.reload()
// 客户端路由跳转,不重新加载
this.$router.push({ path: '/' })
```
### 2. 路由守卫
**推荐**
- 在路由守卫中统一处理登录状态检查
- 已登录访问登录页时自动重定向到首页
- 未登录访问受保护页面时自动重定向到登录页
### 3. 主路由配置
**推荐**
- 设置 `redirect: '/home'` 确保访问 `/` 时重定向到首页
- 从后端权限菜单生成路由
- 提供默认菜单配置作为降级方案
## 📝 总结
### 修改内容
- ✅ 修改了登录成功后的跳转逻辑
- ✅ 使用 `window.location.href` 跳转到首页
- ✅ 触发完整页面加载
- ✅ 确保路由和菜单正确初始化
### 效果
- ✅ 登录成功后自动跳转到首页
- ✅ 访问 `/` 自动重定向到 `/home`
- ✅ 已登录访问登录页自动重定向到首页
- ✅ 用户体验更流畅
---
**登录跳转首页功能已完成!** 🎉
现在登录成功后会自动跳转到首页,访问 `/` 也会正确重定向到 `/home`