官网参考:https://router.vuejs.org/zh/guide/advanced/dynamic-routing.html
router/index.ts 配置代码,导出的router在main.ts中use即可。SystemDataStore.menus是用户登录后从后端获得的菜单数据。
import { defineAsyncComponent } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
import { type route_data, type route_meta } from '@/common/interfaces'
import pinia from '@/stores/store'
import { useSystemDataStore } from '@/stores/index'
import { getCookie } from '@/common/cookie'

// SystemDataStore 可以在本文件中随意使用
const SystemDataStore = useSystemDataStore(pinia);
//创建路由
const router = createRouter({
  history: createWebHistory(),
  routes: [
    {
      path: '/',
      name: 'home',
      // 重定向到login 重定向和别名:https://router.vuejs.org/zh/guide/essentials/redirect-and-alias.html
      redirect: { name: 'login' },
    },
    {
      path: '/login',
      name: 'login',
      component: () => import('../views/Login.vue'),
    },
    // 嵌套路由:https://router.vuejs.org/zh/guide/essentials/nested-routes.html
    {
      path: '/main',
      name: 'main',
      component: () => import('../views/Main.vue'),
    },

    //注释掉原路由配置,改为动态路由。
    // {
    //   path: '/SysSetting',
    //   name: 'SysSetting',
    //   meta: { title: "系统设置" },
    //   children: [
    //     {
    //       path: '/SysSetting/UserMgr',
    //       name: 'UserMgr',
    //       meta: { title: "用户管理" },
    //       children: [
    //         {
    //           path: '/SysSetting/UserMgr/UserAccountMgr',
    //           name: 'UserAccountMgr',
    //           component: () => import('../views/SysSetting/UserMgr/UserAccountMgr.vue'),
    //           meta: { title: "用户账户管理" },
    //         },
    //         {
    //           path: '/SysSetting/UserMgr/UserAddressMgr',
    //           name: 'UserAddressMgr',
    //           component: () => import('../views/SysSetting/UserMgr/UserAddressMgr.vue'),
    //           meta: { title: "用户地址管理" },
    //         },
    //       ],
    //     },
    //     {
    //       path: '/SysSetting/RoleMgr',
    //       name: 'RoleMgr',
    //       component: () => import('../views/SysSetting/RoleMgr.vue'),
    //       meta: { title: "角色管理" },
    //     },
    //     {
    //       path: '/SysSetting/MenuMgr',
    //       name: 'MenuMgr',
    //       component: () => import('../views/SysSetting/MenuMgr.vue'),
    //       meta: { title: "菜单管理" },
    //     },
    //     {
    //       path: '/SysSetting/ProductionMgr',
    //       name: 'ProductionMgr',
    //       component: () => import('../views/SysSetting/ProductionMgr.vue'),
    //       meta: { title: "商品管理" },
    //     },
    //   ]
    // },

    //注释掉,动态路由在刷新的时候尚未添加到routes中,会造成404.
    // 将匹配所有内容并将其放在 `$route.params.pathMatch` 下。
    // { path: '/:pathMatch(.*)*', name: 'NotFound', component: () => import('../views/NotFound.vue') },
  ]
})

//导航守卫
router.beforeEach(async (to, from, next) => {
  //用户登录后的token
  let token = getCookie('XSRF-TOKEN');
  //标记是否已经添加过动态路由true/false
  let isLoadRouters = SystemDataStore.isLoadRouters;
  if (inWhiteList(to.path)) {
    next()
  } else {
    //用户已登录,加载用户信息、菜单信息、权限信息。
    SystemDataStore.initData();
    if (token && JSON.stringify(SystemDataStore.menus) !== '[]') {
      if (isLoadRouters) {
        // console.log('路由已添加,直接跳转到目标页面', router.getRoutes());
        next()
      } else {
        //解决刷新页面空白
        //console.log('重新加载路由,并跳转到目标页');
        SystemDataStore.setIsLoadRouters(true)
        //添加动态路由
        await generateRoutes();
        // console.log('路由添加完毕,从新进入路由。', router.getRoutes());
        next({ ...to, replace: true })
      }
    } else {
      // console.log('无登录信息,跳转到登录页');
      SystemDataStore.setIsLoadRouters(false)
      next(`/login`)
    }
  }
})

//动态添加路由
const generateRoutes = () => {
  SystemDataStore.initData();
  let _asyncRoutes = SystemDataStore.menus;
  if (_asyncRoutes == null) {
    return;
  }
  _asyncRoutes.forEach((menu1: any) => {
    if (menu1.children.length > 0) {
      menu1.children.forEach((menu2: any) => {
        if (menu2.children.length > 0) {
          menu2.children.forEach((menu3: any) => {
            let _asyncRoute3: any = menuToRoute(menu3);
            if (_asyncRoute3) {
              router.addRoute(_asyncRoute3)
            }
          });
        } else {
          //二级
          let _asyncRoute2: any = menuToRoute(menu2);
          if (_asyncRoute2) {
            router.addRoute(_asyncRoute2)
          }
        }
      })
    } else {
      //一级
      let _asyncRoute1: any = menuToRoute(menu1);
      if (_asyncRoute1) {
        router.addRoute(_asyncRoute1)
      }
    }
  })
}

//将菜单转换成router可以识别的路由
const menuToRoute = (menu: any) => {
  if (!menu.url) {
    return null;
  } else {
    let routeCur: route_data = {
      name: menu.name,
      path: menu.url,
      meta: {
        title: menu.meta.title, idx: menu.meta.idx
      },
      children: [],
      component: null
    }
    //方式1 动态组件 /* @vite-ignore */ 忽略vite警告
    //vite语法不识别动态导入,报错:The above dynamic import cannot be analyzed by Vite.
    routeCur.component = () => import(/* @vite-ignore */'../views' + menu.url + '.vue');
    //方式2 动态组件
    // routeCur.component = defineAsyncComponent(() => import(/* @vite-ignore */'../views' + menu.url + '.vue'))
    return routeCur;
  }
}

// 检查是否存在于免登陆白名单
const inWhiteList = (toPath: any) => {
  const whiteList = ['/login']
  let str = toPath.toLowerCase();
  if (whiteList.indexOf(str) > -1) {
    return true;
  }
  return false;
}
export default router

 

posted on 2024-06-25 11:19  邢帅杰  阅读(5)  评论(0编辑  收藏  举报