工作:路由是前台配,还是后台配的问题?
个人建议,前端配置,这样才能达到前后端分离的工作;
1、后台配置路由,前端人不在的情况;没办法页面跳转;
2、新的需求,前端把路由配好了,后台的人不在,没办法找到路由;
首先定义不需要权限的默认路由,
routre/index.js
**
* 默认路由
*/
export const defaultRouterMap = [
{
path: "/",
redirect: "login",
hidden: true,
meta: {
name: "主页"
}
},
{
path: "/login",
name: "Login",
hidden: true,
meta: {
name: "登录"
},
component: () => import("../views/Login/index.vue")
},
{
path: "/console",
name: "Console",
redirect: "index",
meta: {
name: "控制台",
icon: 'console'
},
component: Layout,
children: [
{
path: "/index",
name: "Index",
meta: {
keepAlive: true,
name: "首页"
},
component: resolve=>(require(["@/views/Console/index.vue"],resolve))
}
]
},
export default new Router({
mode: 'hash',
scrollBehavior: () => ({ y: 0 }),
routes: defaultRouterMap
});
定义动态路由
routre/index.js
/**
* 动态路由
* 角色:sale, technician, manager
*/
export const asnycRouterMap = [
{
path: "/info",
name: "Info",
meta: {
role: ['sale', 'manager'],
system: 'infoSystem',
name: "信息管理",
icon: 'info'
},
component: Layout,
children: [
{
path: "/infoIndex",
name: "InfoIndex",
meta: {
keepAlive: true,
role: ['sale', 'manager'],
name: "信息列表"
},
component: () => import("../views/Info/index.vue")
},
{
path: "/infoCategory",
name: "InfoCategory",
meta: {
keepAlive: true,
role: ['sale'],
name: "信息分类"
},
component: () => import("../views/Info/category.vue")
},
{
path: "/infoDetailed",
name: "InfoDetailed",
hidden: true,
meta: {
keepAlive: true,
role: ['sale'],
name: "信息详情"
},
component: () => import("../views/Info/detailed.vue")
}
]
},
接下来在vuex进行操作,在store新建一个js文件如permission.js,创建动态路由
store/permission.js
//获取权限接口方法
import { getUserRole } from "@/api/login";
//引入动态路由,静态路由
import { defaultRouterMap, asnycRouterMap } from "@/router"
function hasPremission(roles, router){
if(router.meta && router.meta.role) {
return roles.some(item => router.meta.role.indexOf(item) >= 0)
}
}
const state = {
allRouters: defaultRouterMap,
addRouters: [],
}
const getters = {
allRouters: state => state.allRouters, // 所有的
addRouters: state => state.addRouters, // 匹配的
}
const mutations = { // 必须的 同步 没有回调处理事情
SET_ROUTER(state, router) {
state.addRouters = router
state.allRouters = defaultRouterMap.concat(router)
}
}
创建动态路由
store/permission.js
const actions = { // 可以回调处理事情
/**
* 获取用户角色
* @param {*} param0
* @param {*} repuestData
*/
getRoles({ commit }, repuestData) {
return new Promise((resolve, reject) => {
getUserRole().then(response => {
let data = response.data.data;
resolve(data);
})
})
},
/**
* 创建动态路由
*/
createRouter({ commit }, data){
return new Promise((resolve, reject) => {
//对应router路由里meta标签里system的值,如果相同则有权限访问
// ["infoSystem", "userSystem"]
let role = data;
// 超管的状态
let addRouters = []
if(role.includes('admin')) {
addRouters = asnycRouterMap
}else{ // 普通管理员
addRouters = asnycRouterMap.filter(item => {
if(hasPremission(role, item)) {
// 优先判断
if(item.children && item.children.length > 0) {
item.children = item.children.filter(child => {
if(hasPremission(role, child)){
return child;
}
})
return item;
}
return item;
}
})
addRouters.push(asnycRouterMap[asnycRouterMap.length - 1]);
}
// 更新路由
commit('SET_ROUTER', addRouters);
resolve()
})
}
}
export default {
namespaced: true,
state,
getters,
mutations,
actions
};
这个时候我们已经拿到权限数据,并将数据存放到了vuex中,面我们需要利用返回数据匹配之前写的异步路由表,将匹配结果和静态路由表结合,开成最终的实际路由表。
为了代码简洁明白,我们在router文件夹下新建一个js文件
store/premit.js
import router from "./index";
import store from "../store/index";
import { getToKen, removeToKen, removeUserName } from "@/utils/app";
const whiteRouter = ['/login']; // indexOf方法,判断数组中是否存在指定的某个对象,如果不存在,则返回-1
// 路由守卫
router.beforeEach((to, from, next) => {
if(getToKen()){
if(to.path === '/login'){
removeToKen();
removeUserName();
store.commit("app/SET_TOKEN", '');
store.commit("app/SET_USERNAME", '');
next();
}else{
// 获取用户的色
// 动态分配路由权限
/**
* 1、什么时候处理动态路由
* 2、以什么条件处理
* roles[]
*/
if(store.getters['app/roles'].length === 0) {
store.dispatch('permission/getRoles').then(response => {
let role = response.role;
let button = response.button; // 这是上学时说的内容
let btnPerm = response.btnPerm;
store.commit("app/SET_ROLES", role);
store.commit("app/SET_BUTTON", btnPerm);
// 存储角色
store.dispatch('permission/createRouter', role).then(response => {
let addRouters = store.getters['permission/addRouters'];
let allRouters = store.getters['permission/allRouters'];
// 路由更新
router.options.routes = allRouters;
// 添加动态路由
router.addRoutes(addRouters)
next({ ...to, replace: true});
// es6扩展运算符,防止内容发生变化的情况
// 不被记录历史记录
})
});
}else{
next();
}
}
/**
* 1、to = /console
* 2、to = /index
*/
// 路由动态添加,分配菜单,每个角色分配不同的菜单
}else{
if(whiteRouter.indexOf(to.path) !== -1) { // 存在
next(); // to
}else{
next('/login') // 路由指向
}
/**
* 1、直接进入index的时候,参数to被改变成了 "/index",触发路由指向,就会跑beforeEach
* 2、再一次 next 指向了login,再次发生路由指向,再跑beforeEach,参数的to被改变成了"/login"
* 3、白名单判断存在,则直接执行next(),因为没有参数,所以不会再次beforeEach。
*/
}
})
至此为止,由前端配置权限控制流程就差不多是这样,如果大家有疑问,或者博主有什么错误的,欢迎大家评论区留言。
如果对大家有所帮助,希望大家点赞并关注博主。谢谢大家。