Files
admin_core/demo-project/_doc/登录跳转首页修复说明.md
张成 b27c047930 1
2025-10-08 20:01:26 +08:00

9.0 KiB
Raw Blame History

登录跳转首页修复说明

🎯 需求

  1. 登录成功后自动跳转到首页
  2. 访问 / 时自动重定向到 /home

📋 问题分析

原来的问题

登录流程

用户登录
  ↓
调用 handleLogin
  ↓
保存 token 和 authorityMenus
  ↓
显示"登录成功!"
  ↓
window.location.reload()  ← ❌ 刷新当前页面(/login
  ↓
停留在登录页面 ❌

问题

  • 登录成功后刷新了登录页面
  • 虽然路由守卫会检测到 token 并重定向到首页
  • 但是刷新操作会导致页面停留在 /login

路由守卫逻辑

src/router/index.js 中的路由守卫:

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 中的主路由配置:

let mainRoute = {
  path: '/',
  name: '主视图',
  redirect: '/home',  // ← 访问 / 时重定向到 /home
  component: Main,
  children: []
}

说明

  • 访问 / 时会自动重定向到 /home
  • 前提是 /home 路由存在(从后端权限菜单生成)

解决方案

修改登录成功后的跳转逻辑

修改文件src/views/login/login.vue

修改前

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) {
    // 错误处理
  }
}

修改后

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

setTimeout(() => {
  window.location.href = window.location.origin + window.location.pathname + '#/'
}, 500)

原因

  • 让"登录成功!"提示信息有时间显示
  • 给用户更好的体验
  • 确保 localStorage 写入完成

3. URL 构造说明

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 配置

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

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

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. 登录后的跳转

推荐

// 使用 location.href 触发完整页面加载
window.location.href = window.location.origin + window.location.pathname + '#/'

不推荐

// 只刷新当前页面,不跳转
window.location.reload()

// 客户端路由跳转,不重新加载
this.$router.push({ path: '/' })

2. 路由守卫

推荐

  • 在路由守卫中统一处理登录状态检查
  • 已登录访问登录页时自动重定向到首页
  • 未登录访问受保护页面时自动重定向到登录页

3. 主路由配置

推荐

  • 设置 redirect: '/home' 确保访问 / 时重定向到首页
  • 从后端权限菜单生成路由
  • 提供默认菜单配置作为降级方案

📝 总结

修改内容

  • 修改了登录成功后的跳转逻辑
  • 使用 window.location.href 跳转到首页
  • 触发完整页面加载
  • 确保路由和菜单正确初始化

效果

  • 登录成功后自动跳转到首页
  • 访问 / 自动重定向到 /home
  • 已登录访问登录页自动重定向到首页
  • 用户体验更流畅

登录跳转首页功能已完成! 🎉

现在登录成功后会自动跳转到首页,访问 / 也会正确重定向到 /home