Login and Routing Permissions (Promoted)

Let’s post the flow chart I’ve been drawing for almost an hour. It’s a little ugly, but it’s still good to see

Let’s talk about it in detail

The login. The vue web page

// Click the login button
<el-button @click.prevent="handleLogin">Login</el-button>

let loginReq = () = > {
  store
     // See store/modules/user.js below for details
    .dispatch('user/login', formInline)
    .then(() = > {
      State. redirect-> Record the last redirect to the login page path * state.otherQuery-> Record the last redirect to the login page parameter. Redirect and otherQuery are empty * */
      proxy.$router.push({ path: state.redirect || '/'.query: state.otherQuery })
    })
    .catch((res) = > {
      // An error message is displayed
      tipMessage.value = res.msg
    })
}

Copy the code

store/modules/user.js

//dispatch('user/login', formInline)
// Use localStorage to store tokens
import { setToken, removeToken } from '@/utils/auth login({ commit }, data) { return new Promise((resolve, Reject) => {// Send the login request loginReq(data). Then ((res) => {if (res.code === 20000) {// Store the token in localStorage setToken(res.data? .jwtToken) resolve() } else { reject(res) } }) .catch((error) => { reject(error) }) }) },Copy the code

permission.js

// Page whitelist
const whiteList = ['/login']
router.beforeEach(async (to, from, next) => {
  // Start page animation
  if (settings.isNeedNprogress) NProgress.start()
  // Set the page tital
  document.title = getPageTitle(to.meta.title)
  // Whether login is required: Yes -> obtain the token, no -> set a temporary token
  let hasToken = settings.isNeedLogin ? getToken() : 'temp_token'
  if (hasToken) {
    if (to.path === '/login') {
      // If you go to the login page with a token, set the login home page
      next({ path: '/'})}else {
      // Whether user information has been obtained
      let isGetUserInfo = store.state.permission.isGetUserInfo
      if (isGetUserInfo) {
        // If the user information is obtained, the dynamic route is displayed. After the user information is set, the page is directly allowed
        next()
      } else {
        // No user information has been obtained. User information setting and dynamic route filtering process
        try {
          let accessRoutes = []
            /* Whether to log in: Yes: the user information is set, and dynamic route filtering is performed. No: dynamic routes are not filtered. * */
          if (settings.isNeedLogin) {
            // Request user information
            const { roles } = await store.dispatch('user/getInfo')
            / / filter dynamic routing, permission/generateRoutes process in detail below
            accessRoutes = await store.dispatch('permission/generateRoutes', roles)
            // Static routes and filtered dynamic routes are set to vuex and displayed in the sideBar
            store.commit('permission/M_routes', accessRoutes)
          } else {
            accessRoutes = asyncRoutes
            store.commit('permission/M_routes', accessRoutes)
          }
          // Set accessRoutes to vue-router
          accessRoutes.forEach((route) = > {
            router.addRoute(route)
          })
          Set isGetUserInfo to true
          store.commit('permission/M_isGetUserInfo'.true)
          // replace: true, clear the browser historynext({ ... to,replace: true})}catch (err) {
          // If an error occurs, reset the state and redirect to the login page
          await store.dispatch('user/resetToken')
          next(`/login? redirect=${to.path}`)
          if (settings.isNeedNprogress) NProgress.done()
        }
      }
    }
  } else {
    // The whitelist page is directly allowed. Otherwise, you are redirected to the login page
    if(whiteList.indexOf(to.path) ! = = -1) {
      next()
    } else {
      next(`/login? redirect=${to.path}`)
      if (settings.isNeedNprogress) NProgress.done()
    }
  }
})
Copy the code

store/modules/permission.js

//store.dispatch('permission/generateRoutes', roles)
generateRoutes({ commit }, roles) {
    return new Promise(async (resolve) => {
      let accessedRoutes
      // Determine how to filter dynamic routes, roles or codeArr
      if (settings.permissionMode === 'roles') {
        if (roles.includes('admin')) {
           // If the role is admin, the highest permission is not filtered
          accessedRoutes = asyncRoutes || []
        } else {
          // call filterAsyncRoutes to filterAsyncRoutes based on roles
          accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
        }
      } else {
        // Get codeArr data, if not set to [1]
        let codeArr = localStorage.getItem('codeArr')
        if (codeArr) {
          codeArr = JSON.parse(codeArr)
        } else {
          localStorage.setItem('codeArr'.JSON.stringify([1]))
          codeArr = localStorage.getItem('codeArr')}// Execute filterRouterByCodeArr to filter asyncRoutes based on codeArr
        accessedRoutes = await filterRouterByCodeArr(codeArr, asyncRoutes)
      }
      // Dynamic route filtering is complete and configured to vuEX for subsequent use
      commit('M_routes', accessedRoutes)
      // Returns the filtered dynamic route to permission.js
      resolve(accessedRoutes)
    })
  }

/** * Filter dynamic routes by role *@param Routes Dynamic routes *@param Roles Array of roles passed in */
export function filterAsyncRoutes(routes, roles) {
  const res = []
  routes.forEach((route) = > {
    consttmp = { ... route }if (hasPermission(roles, tmp)) {
      if (tmp.children) {
        // Recursively call the current method to filter children
        tmp.children = filterAsyncRoutes(tmp.children, roles)
      }
      res.push(tmp)
    }
  })
  return res
}
Roles is included in route.meta. Roles, true if so
function hasPermission(roles, route) {
  if (route.meta && route.meta.roles) {
    return roles.some((role) = > route.meta.roles.includes(role))
  } else {
    return true}}/** * Filter dynamic routes through codeArr@param codeArr
 * @param asyncRoutes* /
function filterRouterByCodeArr(codeArr, asyncRoutes) {
  return new Promise((resolve) = > {
    let filterRouter = []
    asyncRoutes.forEach(async (routeItem) => {
      if (hasCodePermission(codeArr, routeItem)) {
        if (routeItem.children) {
          routeItem.children = await filterRouterByCodeArr(codeArr, routeItem.children)
        }
        filterRouter.push(routeItem)
      }
    })
    resolve(filterRouter)
  })
}
function hasCodePermission(codeArr, routeItem) {
  if (routeItem.meta && routeItem.meta.code) {
    // If hidden is true, this route is not filtered
    return codeArr.includes(routeItem.meta.code) || routeItem.hidden
  } else {
    return true}}Copy the code

In general, dynamic filtering dynamic routing asyncRoutes by role or codeArr. After obtaining the dynamic route, call vue-router

Router. addRoute(route) Sets a route and mounts it to a real router