# 登录

# 技术点

vuex 的使用 登录信息存入 vuex addRoutes 的使用

# 介绍

输入账号密码登陆成功后,接口会返回 token,携带该 token 调用获取管理员信息接口,该接口会返回管理员信息和分配的菜单权限,分别存入 vuex 中。用户菜单会通过 router.addRoutes 动态添加到路由表中。

# 目录结构

└─ src
   └─ pages
      └─ login                        # 账号相关
         └─ index.vue                 # 账号登录

# 登陆

methods: {
    // 登陆方法
    login() {
        this.$refs.form.validate(async (valid) => {
            if (valid) {
                this.loading = true;
                    // 调用登录方法
                const loginRes = await this.$store.dispatch("user/login", this.form);

                if (loginRes.code !== 200) {
                    this.loading = false;
                    return;
                }
                
                // 获取管理员信息与菜单权限
                const adminRes = await this.$store.dispatch("user/getInfo");
                this.loading = false;

                if (adminRes.code === 200) {
                    // 处理路由
                    let routes = adminRes.data.roles;

                    let asyncRoutes = this.filterAsyncRouter(routes); //过滤路由

                    let isAdd = false; // 防止动态路由重复添加
                    if (!isAdd) {
                        router.addRoutes(asyncRoutes); //动态添加路由
                    }
                    isAdd = true;

                    this.$router.replace(
                    this.$route.query.redirect
                        ? this.$route.query.redirect
                        : asyncRoutes[0].path
                    );
                }
            } else {
                return false;
            }
        });
    },

    // 遍历后台传来的路由字符串,转换为组件对象
    filterAsyncRouter(asyncRoutes) {
        let accessedRouters = asyncRoutes.filter((route) => {
            if (route.component) {
                //Layout组件特殊处理
                if (route.component === "Layout") {
                    route.component = Layout;
                } else {
                    try {
                        // 引入组件
                        route.component = _import(route.component);
                    } catch (e) {
                        console.info(
                            "%c 当前路由 " +
                            route.component +
                            ".vue 不存在,因此无法导入组件,请检查接口数据和组件是否匹配,并重新登录,清空缓存!",
                            "color:red"
                        );
                    }
                }
            }

            // 存在子路由时递归遍历子路由
            if (route.children && route.children.length) {
                route.children = this.filterAsyncRouter(route.children);
            }
            return true;
        });

        return accessedRouters;
    },
},

# 处理用户刷新

登录后用户路由菜单会写入 vuexstorage 中,但用户如果刷新页面,addRouter 中的路由会丢失,所以在路由 router 文件中,需要再次执行 addRouter 操作,并在 main.js 中引入。

const _import = require('./_import_' + process.env.NODE_ENV) // 引入组件方式

import router from "@/router/index"
import Layout from '@/pages/Layout'
import store from '@/store/index'

// 如果存在路由菜单,则执行以下代码
if (store.state.user.menus && Array.isArray(store.state.user.menus)) {
  const routes = store.state.user.menus
  let asyncRoutes = filterAsyncRouter(routes) //过滤路由
  let isAdd = false;    // 
  if (!isAdd) {
    router.addRoutes(asyncRoutes)   //动态添加路由
  };

  isAdd = true
}


function filterAsyncRouter(asyncRoutes) {   //遍历后台传来的路由字符串,转换为组件对象
  const accessedRouters = asyncRoutes.filter(route => {
    if (route.component) {
      if (route.component === 'Layout') {   //Layout组件特殊处理
        route.component = Layout
      } else {
        route.component = _import(route.component)
      }
    }
    if (route.children && route.children.length) {
      route.children = filterAsyncRouter(route.children)
    }
    return true
  })

  return accessedRouters
}

main.js 中引入,以便用户每次刷新页面时,执行该路由方法。

import './router/promission'
上次更新: 6/23/2022, 6:29:21 PM