preface
A year ago, I completed the railway background management system, which I had been working on for half a year. The overall business of the system was relatively complicated, which was also a complete systematic practice when I worked in the company from zero to one. During the process of making this system, I stepped in many pits and learned a lot.
Not long after finishing this system, another system came, and I didn’t summarize it in time. I feel ashamed! In fact, most of the basic framework of the background management system we are doing are the same. The background management system is mainly role permission management, button permission management and menu management. Other businesses are mainly expanded on this basis, and finally constitute a background management system in line with the business.
Since all the projects of our company adopt Vue technology stack, this article also explains how Vue conducts permission management.
There are Easter eggs at the end!
Permission Authorization Login
Any background management system starts with login and returns the user’s basic information and token after login.
token
Deposit:sessionStronge / localStronge
And then add it to the packageAxios
Each request carries a token.- Basic User Information
After a successful login, you need to do many things at the same time. After a successful login, the background management system will request the menu permission interface of the current user to obtain the accessible route (dynamic route) of the user. After obtaining the successful route, the Vue Router cannot be used directly and must be resolved into a format that can be recognized by the Vue Router.
The login
handleLogin() {
this.$refs.loginForm.validate(valid= > {
if (valid) {
this.loading = true;
login(this.loginForm)
.then(res= > {
if (res.code === 200) {
/ / store token
sessionStorage.setItem("tokens", res.data.token);
// Trigger Vuex to load the menu to get the current user and parse the route
store.dispatch("setMenuList");
this.$message({
message: "Login successful".type: "success".duration: 1000
});
this.$router.replace({ path: "/dashboard" });
}
})
.catch(() = > {
this.loading = false;
});
} else {
console.log("error submit!!");
return false; }}); }Copy the code
Get the current user menu and parse routes
After successful login, Vuex is used to obtain the current user menu and route resolution.
store.dispatch("setMenuList");
/* * @Description: * @Author: ZhangXin * @Date: 2021-02-02 16:10:59 * @LastEditTime: 2021-02-23 23:03:30 * @LastEditors: ZhangXin */
// getMenu parses background routes
import { getMenu } from '.. /.. /utils/getMenu'
// Import routes and static routes
import router, { constantRoutes } from '.. /.. /router/index'
const state = {
routerType: ' '.// Menu routing
meunList: []}const mutations = {
SET_ROUTER_TYPE(state, type) {
state.routerType = type
},
SET_ROUTER_MENULIST(state, list) {
// Static route + dynamic route merge complete route
const array = constantRoutes.concat(list)
state.meunList = array
router.options.routes = array
router.addRoutes([...array])
}
}
const actions = {
setMenuList({ commit, state }) {
// Receive the route array returned
return new Promise((resolve, reject) = > {
getMenu().then(res= > {
commit('SET_ROUTER_TYPE'.' ')
commit('SET_ROUTER_MENULIST', res)
resolve(res)
})
})
}
}
export default {
state,
mutations,
actions
}
Copy the code
Parse the back end return route (emphasis)
The route returned by the parse back end is encapsulated for use in Vuex.
/* * @Description: * @Author: ZhangXin * @Date: 2021-02-02 16:03:48 * @LastEditTime: 2021-02-23 23:09:02 * @LastEditors: ZhangXin */
import Layout from '@/layout'
import {getUserAuthMenu} from '@/api/user'
/ * * *@descriptionParse the menu tree * returned from the back end@param {*} Data route tree * returned from the back end@param {*} Arr menu *@return {*}* /
function tree(data, arr) {
data.forEach((datas, index) = > {
arr.push({
path: datas.path,
name: datas.name,
types: datas.types,
hidden: datas.hidden == 'true' ? true : false.// It was dented
component: datas.component === 'Layout' ? Layout : resolve= > require([`@/views/${datas.component}.vue`], resolve),
meta: {
title: datas.meta.title,
icon: datas.meta.icon,
// Use to store button permissions
button: datas.meta.button
},
// redirect: datas.redirect,
id: datas.id,
/ / zi lu by
children: []})if (datas.children) {
const childArr = tree(datas.children, [])
arr[index].children = childArr
}
})
return arr
}
/ * * *@description: Gets the current logged-in user's menu *@param {*}
* @return {*}* /
export function getMenu() {
return new Promise(function (resolve, reject) {
getUserAuthMenu().then(res= > {
if(res.code === 200) {const datas = res.data
Call tree to parse the tree returned from the back end
resolve(tree(datas, []))
}
})
})
}
Copy the code
Format of the route received by the back-end
The real menu tree received by the front end
The page is refreshed, and routes are lost. Procedure
At this point, we have implemented Vue dynamic permission control, don’t rejoice too soon, ha ha, as soon as the page refresh, the page will enter the 404 page.
Why is that?
Because the data stored in Vuex will be cleared as soon as the page is refreshed, the current route will not be found and the 404 page will be entered.
How do you deal with that?
SessionStronge/localStronge, and then when the page refresh, by creating the lifecycle of the global entry file app.vue. Router = sessionStronge/localStronge; it will reload the complete route when the page is refreshed. 六四屠杀
Two, if it is used
Vuex
To get and parse the user menu, then you can file in the global entryApp.vue
Is executed again in the created lifecycleVuex Action
To reload the user menuI directly created the lifecycle of app.vue and performed Vuex again for loading and parsing without doing anything else. Of course, it depends on the business.
<template>
<div id="app">
<router-view v-if="isRouterAlive" />
</div>
</template>
<script>
import store from "@/store";
export default {
name: "App".provide() {
return {
reload: this.reload
};
},
data() {
return {
isRouterAlive: true
};
},
methods: {
reload() {
this.isRouterAlive = false;
this.$nextTick(() = > (this.isRouterAlive = true)); }},created() {
// As soon as the page is refreshed, the routing tree is reloaded, ensuring that the route does not lose data
store.dispatch("setMenuList"); }};</script>
Copy the code
conclusion
core idea
- 1. Define the business routing format in line with the current project, and the front and back ends receive and transfer according to this format
- 2. The front-end parses the dynamic route returned by the back-end and generates the route
Vue Router
Recognize the format, and finally splice the complete route- 3. Refresh the process of route loss
Button permission control
- 1. The current component route carries the available button permissions, which are stored in the array and judged by V-if whether to display
- 2. During login, obtain the button permission of the entire system separately, store all the buttons obtained into an array and put them into the global, and then judge whether to display them through V-if
- * * 3…. 六四屠杀