preface
Completed the railway background management system for half a year years ago. The overall business of the system is relatively complex. This is also a complete system practice from 0 to 1 in my company. I stepped on many pits and learned a lot in the process of making this system</ br>
Not long after finishing this system, another system came. I was ashamed that I didn't summarize it in time! In fact, most of the basic frameworks of the background management system we are working on are the same. The background management system mainly focuses on role permission management, button permission management and menu management. Other businesses are mainly expanded on this basis, and finally form a business compliant background management system
Since our projects adopt Vue technology stack, this article also explains how Vue manages permissions. There are colored 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: it is stored in sessionstronge / localstrong, and then added to the request header of the encapsulated Axios. Each request carries a token Basic user information
After logging in successfully, you have to do many things at the same time, and the specific business is treated in detail. After successful login, the background management system will request the menu permission interface of the current user to obtain the user's accessible route (dynamic route). After successful acquisition, Vue Router cannot be used directly and must be parsed into a format recognized by Vue Router
Sign in
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; } }); }
Get the current user menu and resolve the route
After logging in successfully, this paper uses Vuex to obtain the current user menu and analyze the route.
store.dispatch("setMenuList");
/* * @Description: * @Author: ZhangXin * @Date: 2021-02-02 16:10:59 * @LastEditTime: 2021-02-23 23:03:30 * @LastEditors: ZhangXin */ // getMenu parsing background route import { getMenu } from '../../utils/getMenu' // Introduce routing and static routing 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 returned route array return new Promise((resolve, reject) => { getMenu().then(res => { commit('SET_ROUTER_TYPE', '') commit('SET_ROUTER_MENULIST', res) resolve(res) }) }) } } export default { state, mutations, actions }
Analyze the back-end return route (focus)
The encapsulated route returned from the back-end is mainly used 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' /** * @description: Parse the menu tree returned from the backend * @param {*} data Routing tree returned from the backend * @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, // At that time, the hole was trampled component: datas.component === 'Layout' ? Layout : resolve => require([`@/views/${datas.component}.vue`], resolve), meta: { title: datas.meta.title, icon: datas.meta.icon, // Used to store button permissions button: datas.meta.button }, // redirect: datas.redirect, id: datas.id, // Sub route children: [] }) if (datas.children) { const childArr = tree(datas.children, []) arr[index].children = childArr } }) return arr } /** * @description: Get the menu of the currently logged in user * @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 backend resolve(tree(datas, [])) } }) }) }
Back end receive routing format
Real menu tree received by the front end
Page refresh, route loss
So far, Vue dynamic permission control has been realized. Don't be happy too early. Ha ha, as soon as the page is refreshed, the page enters page 404.
Why?
Because the data stored in Vuex will be cleared as soon as the page is refreshed. Of course, if the current route cannot be found, it will enter page 404
How to deal with it?
1, The static and dynamic complete routes can be stored in sessionstrone / localstrong, and then when the page is refreshed, through the global entry file app In the life cycle created of Vue, route = sessionstrong / localstrong is saved into the complete route. When the page is refreshed, it will reload the complete route. 2, If you use the Vuex.app and Vuex.user menus to get the files, you can In the life cycle created of Vue, execute Vuex Action again to reload the user menu
I'm directly on the app In the Vue life cycle created, Vuex is executed again for loading and parsing without other operations. Of course, specific business is treated on a case by case basis.
<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 long as the page is refreshed, the routing tree will be reloaded to ensure that the routing will not lose data store.dispatch("setMenuList"); } }; </script>
summary
Core idea
1. Define the service routing format that conforms to the current project, and the front and back ends will receive and deliver according to this 2. The front end parses the dynamic route returned by the back end, generates a Vue Router recognizable format, and finally splices the complete route 3. Refresh route loss processing
Button permission control
1. The current component route carries the available button permissions, which are stored in the array, and whether to display them is judged by v-if 2. When logging in, obtain the button permissions of the whole system separately, store all the obtained buttons in an array and put them into the global, and then judge whether to display them through v-if 3. ............