2 12.根据菜单动态添加路由
const store = createStore({
state() {
return {
...略
//
menus: [],
ruleNames: []
}
},
mutations: {
...略
// 菜单相关
SET_MENUS(state, menus){
state.menus = menus
},
SET_RULENAMES(state, ruleNames){
state.ruleNames = ruleNames
},
},
actions: {
...略
// 获取当前登录用户信息
getinfo({ commit }){
return new Promise((resolve, reject) => {
getinfo().then(res=>{
// console.log(res)
commit('SET_USERINFO', res)
commit('SET_MENUS', res.menus)
commit('SET_RULENAMES', res.ruleNames)
resolve(res)
}).catch(err=>reject(err))
})
},
}
})
src/router/index.js
import {
createRouter,
createWebHashHistory
} from 'vue-router'
import Admin from '~/layouts/admin.vue'
import Index from '~/pages/index.vue'
import GoodList from '~/pages/goods/list.vue'
import CateGoryList from '~/pages/category/list.vue'
import NotFound from '~/pages/404.vue'
import Login from '~/pages/login.vue'
// 默认路由,所有用户共享
const routes = [
{ path: "/", name: "admin",component: Admin },
{ path: "/login", component: Login, meta: {'title': '登录'}},
{ path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound, meta: {'title': '404'} },
]
// 动态路由,用户匹配菜单动态添加路由
const asyncRoutes = [
{ path:"/", name: "/",component: Index, meta:{ title:"后台首页" }},
{ path:"/goods/list",name:"/goods/list", component: GoodList, meta:{ title:"商品列表" }},
{ path:"/category/list", name:"/category/list",component: CateGoryList, meta:{ title:"分类列表" }}
]
// 3.创建路由实例并传递 `routes` 配置
export const router = createRouter({
history: createWebHashHistory(),
routes
})
// 动态添加路由的方法,根据路径配置
export function addRoutes(menus) {
let hasNewRoutes = false
const findAndAddRoutesByMenus = (arr) => {
arr.forEach(e=>{
let item = asyncRoutes.find(o=>o.path == e.frontpath)
if (item && !router.hasRoute(item.path)){
router.addRoute('admin',item)
hasNewRoutes = true
}
if(e.child && e.child.length > 0) {
findAndAddRoutesByMenus(e.child)
}
});
}
findAndAddRoutesByMenus(menus)
// console.log(router.getRoutes())
return hasNewRoutes
}
src/permission.js
import { router, addRoutes } from './router'
import { getToken } from '~/composables/auth'
import { toast,showFullLoading,hideFullLoading } from '~/composables/util'
import store from '~/store'
// 全局前置守卫
router.beforeEach(async (to, from, next) => {
showFullLoading()
const token = getToken()
// 没有登录,强制跳转到登录页面
if(!token && to.path != '/login') {
toast('请先登录', 'error')
return next({ path: "/login"})
}
// 防止重复登录
if(token && to.path == '/login'){
return next({ path: from.path ? from.path: '/'})
}
// 如果用户登录了,自动获取用户信息,并存储再 vuex 当中
let hasNewRoutes = false
if(token){
let { menus } = await store.dispatch("getinfo")
hasNewRoutes = addRoutes(menus)
}
// 设置页面标题
let title = (to.meta.title ? to.meta.title : "") + "~牛皮编程后台"
document.title = title
hasNewRoutes ? next(to.fullPath) : next()
})
router.afterEach((to,from)=> hideFullLoading())
Last updated