ant design pro of Vue版本登陆权限

这是原始篇也是最好理解并且根据各自接口需求改方法,总结就是登陆的时候把角色权限id传到permission.js做匹配,然后vuex进行拦截匹配对应菜单结结尾附带路由文件代码。

1.第一步配置接口

注释main.js里mock.js

antdesign pro 权限 ant design vue pro权限_vue.js

devServer: {
    // development server port 8000
    port: 8000,
    // If you want to turn on the proxy, please remove the mockjs /src/main.jsL11
    proxy: {
      '/api': {
        target: '接口地址',
        changeOrigin: true,
        pathRewrite: { '^/api': '' }
      }
    }
  },

配置登陆接口api

antdesign pro 权限 ant design vue pro权限_vue.js_02


接着去登陆页导入接口

antdesign pro 权限 ant design vue pro权限_node.js_03

antdesign pro 权限 ant design vue pro权限_antdesign pro 权限_04


代码已贴出可参考

<template>
  <div class="main">
    <a-form
      id="formLogin"
      class="user-layout-login"
      ref="formLogin"
      :form="form"
      @submit="handleSubmit"
    >
      <a-tabs
        :activeKey="customActiveKey"
        :tabBarStyle="{ textAlign: 'center', borderBottom: 'unset' }"
        @change="handleTabClick"
      >
        <a-tab-pane key="tab1" tab="账号密码登录">
          <!--<a-alert v-if="isLoginError" type="error" showIcon style="margin-bottom: 24px;" message="账户或密码错误(admin/ant.design )" />-->
          <a-form-item>
            <a-input
              size="large"
              type="text"
              placeholder="账户: admin"
              v-decorator="[
                'username',
                {rules: [{ required: true, message: '请输入帐户名或邮箱地址' }, { validator: handleUsernameOrEmail }], validateTrigger: 'change'}
              ]"
            >
              <a-icon slot="prefix" type="user" :style="{ color: 'rgba(0,0,0,.25)' }"/>
            </a-input>
          </a-form-item>

          <a-form-item>
            <a-input
              size="large"
              type="password"
              autocomplete="false"
              placeholder="密码: admin or ant.design"
              v-decorator="[
                'password',
                {rules: [{ required: true, message: '请输入密码' }], validateTrigger: 'blur'}
              ]"
            >
              <a-icon slot="prefix" type="lock" :style="{ color: 'rgba(0,0,0,.25)' }"/>
            </a-input>
          </a-form-item>
        </a-tab-pane>
        <a-tab-pane key="tab2" tab="手机号登录">
          <a-form-item>
            <a-input size="large" type="text" placeholder="手机号" v-decorator="['mobile', {rules: [{ required: true, pattern: /^1[34578]\d{9}$/, message: '请输入正确的手机号' }], validateTrigger: 'change'}]">
              <a-icon slot="prefix" type="mobile" :style="{ color: 'rgba(0,0,0,.25)' }"/>
            </a-input>
          </a-form-item>

          <a-row :gutter="16">
            <a-col class="gutter-row" :span="16">
              <a-form-item>
                <a-input size="large" type="text" placeholder="验证码" v-decorator="['captcha', {rules: [{ required: true, message: '请输入验证码' }], validateTrigger: 'blur'}]">
                  <a-icon slot="prefix" type="mail" :style="{ color: 'rgba(0,0,0,.25)' }"/>
                </a-input>
              </a-form-item>
            </a-col>
            <a-col class="gutter-row" :span="8">
              <a-button
                class="getCaptcha"
                tabindex="-1"
                :disabled="state.smsSendBtn"
                @click.stop.prevent="getCaptcha"
                v-text="!state.smsSendBtn && '获取验证码' || (state.time+' s')"
              ></a-button>
            </a-col>
          </a-row>
        </a-tab-pane>
      </a-tabs>

      <!--<a-form-item>-->
        <!--<a-checkbox v-decorator="['rememberMe']">自动登录</a-checkbox>-->
        <!--<router-link-->
          <!--:to="{ name: 'recover', params: { user: 'aaa'} }"-->
          <!--class="forge-password"-->
          <!--style="float: right;"-->
        <!-->忘记密码</router-link>-->
      <!--</a-form-item>-->

      <a-form-item style="margin-top:24px">
        <a-button
          size="large"
          type="primary"
          htmlType="submit"
          class="login-button"
          :loading="state.loginBtn"
          :disabled="state.loginBtn"
        >确定</a-button>
      </a-form-item>

      <!--<div class="user-login-other">-->
        <!--<span>其他登录方式</span>-->
        <!--<a>-->
          <!--<a-icon class="item-icon" type="alipay-circle"></a-icon>-->
        <!--</a>-->
        <!--<a>-->
          <!--<a-icon class="item-icon" type="taobao-circle"></a-icon>-->
        <!--</a>-->
        <!--<a>-->
          <!--<a-icon class="item-icon" type="weibo-circle"></a-icon>-->
        <!--</a>-->
        <!--<router-link class="register" :to="{ name: 'register' }">注册账户</router-link>-->
      <!--</div>-->
    </a-form>

    <two-step-captcha
      v-if="requiredTwoStepCaptcha"
      :visible="stepCaptchaVisible"
      @success="stepCaptchaSuccess"
      @cancel="stepCaptchaCancel"
    ></two-step-captcha>
  </div>
</template>

<script>
import md5 from 'md5'
import TwoStepCaptcha from '@/components/tools/TwoStepCaptcha'
import { mapActions } from 'vuex'
import { timeFix } from '@/utils/util'
import { rolePrivilege } from '@/api/privilege'
import {   login, } from '@/api/login'

export default {
  components: {
    TwoStepCaptcha
  },
  data () {
    return {
      customActiveKey: 'tab1',
      loginBtn: false,
      // login type: 0 email, 1 username, 2 telephone
      loginType: 0,
      isLoginError: false,
      requiredTwoStepCaptcha: false,
      stepCaptchaVisible: false,
      form: this.$form.createForm(this),
      state: {
        time: 60,
        loginBtn: false,
        // login type: 0 email, 1 username, 2 telephone
        loginType: 0,
        smsSendBtn: false
      }
    }
  },
  created () {
    // get2step({ })
    //   .then(res => {
    //     this.requiredTwoStepCaptcha = res.result.stepCode
    //   })
    //   .catch(() => {
    //     this.requiredTwoStepCaptcha = false
    //   })
    // this.requiredTwoStepCaptcha = true
  },
  methods: {
    ...mapActions(['Login', 'Logout']),
    // handler
    handleUsernameOrEmail (rule, value, callback) {
      const { state } = this
      const regex = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((\.[a-zA-Z0-9_-]{2,3}){1,2})$/
      if (regex.test(value)) {
        state.loginType = 0
      } else {
        state.loginType = 1
      }
      callback()
    },
    handleTabClick (key) {
      this.customActiveKey = key
      // this.form.resetFields()
    },
    handleSubmit (e) {
      e.preventDefault()
      const {
        form: { validateFields },
        state,
        customActiveKey,
        Login
      } = this

      state.loginBtn = true

      const validateFieldsKey = customActiveKey === 'tab1' ? ['username', 'password'] : ['mobile', 'captcha']

      validateFields(validateFieldsKey, { force: true }, (err, values) => {
        if (!err) {
          console.log('login form', values)
          const loginParams = { ...values }
          delete loginParams.username
          loginParams[!state.loginType ? 'email' : 'username'] = values.username
          loginParams.password = md5(values.password)
          login(values)
            .then((res) => this.loginSuccess(res))
            .catch(err => this.requestFailed(err))
            .finally(() => {
              state.loginBtn = false
            })
        } else {
          setTimeout(() => {
            state.loginBtn = false
          }, 600)
        }
      })
    },
    getCaptcha (e) {
      e.preventDefault()
      const { form: { validateFields }, state } = this

      validateFields(['mobile'], { force: true }, (err, values) => {
        if (!err) {
          state.smsSendBtn = true

          const interval = window.setInterval(() => {
            if (state.time-- <= 0) {
              state.time = 60
              state.smsSendBtn = false
              window.clearInterval(interval)
            }
          }, 1000)

          const hide = this.$message.loading('验证码发送中..', 0)
          getSmsCaptcha({ mobile: values.mobile }).then(res => {
            setTimeout(hide, 2500)
            this.$notification['success']({
              message: '提示',
              description: '验证码获取成功,您的验证码为:' + res.result.captcha,
              duration: 8
            })
          }).catch(err => {
            setTimeout(hide, 1)
            clearInterval(interval)
            state.time = 60
            state.smsSendBtn = false
            this.requestFailed(err)
          })
        }
      })
    },
    stepCaptchaSuccess () {
      this.loginSuccess()
    },
    stepCaptchaCancel () {
      this.logout().then(() => {
        this.loginBtn = false
        this.stepCaptchaVisible = false
      })
    },
    
    loginSuccess (res) {
      console.log(res ,'asd')
      // check res.homePage define, set $router.push name res.homePage
      // Why not enter onComplete
      /*
      this.$router.push({ name: 'analysis' }, () => {
        console.log('onComplete')
        this.$notification.success({
          message: '欢迎',
          description: `${timeFix()},欢迎回来`
        })
      })
      */
     //这一部分是关键部分
        if (res.code===0) {//登陆成功后把信息存到sessionStorage
          sessionStorage.setItem('user',JSON.stringify(res.data))
          var data={
            roleId: res.data.roleId
          }
          if (res.data.roleId===null) {
    //因为我登陆 后超级管理员携带了角色id是null所有做了这个if判断
           var role =[
              'from',
              'table',
              'dashboard',
            ]

            sessionStorage.setItem('rolePrivilege', JSON.stringify(role))
          }else {
            rolePrivilege(data).then(role =>{
          //这个是权限树查询接口,登陆后获取到了角色id拿到对应值存到sessionStorage
          //然后在permission.js需要role对应权限路由的   
          //  meta: { title: '查询表格', keepAlive: true, permission: [ 'table' ] }
              console.log('role',role)
              sessionStorage.setItem('rolePrivilege', JSON.stringify(role.data))
            })
          }
        }
      this.$router.push({ path: '/' })
      // 延迟 1 秒显示欢迎信息
      setTimeout(() => {
        this.$notification.success({
          message: '欢迎',
          description: `${timeFix()},欢迎回来`
        })
      }, 1000)
      this.isLoginError = false
    },
    requestFailed (err) {
      this.isLoginError = true
      this.$notification['error']({
        message: '错误',
        description: ((err.response || {}).data || {}).message || '请求出现错误,请稍后再试',
        duration: 4
      })
    }
  }
}
</script>

<style lang="less" scoped>
.user-layout-login {
  label {
    font-size: 14px;
  }

  .getCaptcha {
    display: block;
    width: 100%;
    height: 40px;
  }

  .forge-password {
    font-size: 14px;
  }

  button.login-button {
    padding: 0 15px;
    font-size: 16px;
    height: 40px;
    width: 100%;
  }

  .user-login-other {
    text-align: left;
    margin-top: 24px;
    line-height: 22px;

    .item-icon {
      font-size: 24px;
      color: rgba(0, 0, 0, 0.2);
      margin-left: 16px;
      vertical-align: middle;
      cursor: pointer;
      transition: color 0.3s;

      &:hover {
        color: #1890ff;
      }
    }

    .register {
      float: right;
    }
  }
}
</style>

完成登陆页操作后我们需要去permission.js 。更改一些代码

antdesign pro 权限 ant design vue pro权限_antdesign pro 权限_05


antdesign pro 权限 ant design vue pro权限_node.js_06

import Vue from 'vue'
import router from './router'
import store from './store'

import NProgress from 'nprogress' // progress bar
import '@/components/NProgress/nprogress.less' // progress bar custom style
import notification from 'ant-design-vue/es/notification'
import { setDocumentTitle, domTitle } from '@/utils/domUtil'
import { ACCESS_TOKEN } from '@/store/mutation-types'
import { rolePrivilege } from '@/api/privilege'
NProgress.configure({ showSpinner: false }) // NProgress Configuration

const whiteList = ['login', 'register', 'registerResult'] // no redirect whitelist
const defaultRoutePath = '/dashboard/workplace'
var a = 1//结尾记住要有a++不然用户信息获取失败会无限请求
router.beforeEach((to, from, next) => {
  NProgress.start() // start progress bar
  to.meta && (typeof to.meta.title !== 'undefined' && setDocumentTitle(`${to.meta.title} - ${domTitle}`))
 var user= JSON.parse(sessionStorage.getItem('user'))
  var roless = {
    permissionList: JSON.parse(sessionStorage.getItem('rolePrivilege'))
  }
  if (user !== null && user !== undefined) {
    /* has token */
    if (to.path === '/user/login') {
      next({ path: defaultRoutePath })
      NProgress.done()
    } else {
      if (a<=1) {
        console.log(store.getters.roles, 'store.getters.roles')
            store.dispatch('GenerateRoutes',roless ).then(() => {
              console.log(roless, 'rolessadasda')
              // 根据roles权限生成可访问的路由表
              // 动态添加可访问路由表
              router.addRoutes(store.getters.addRouters)
              console.log(store.getters.addRouters, 'aaaastore.getters.roles')
              const redirect = decodeURIComponent(from.query.redirect || to.path)
              if (to.path === redirect) {
                // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
                next({ ...to, replace: true })
              } else {
                // 跳转到目的路由
                next({ path: redirect })
              }
            })

          .catch(() => {
            notification.error({
              message: '错误',
              description: '请求用户信息失败,请重试'
            })
            store.dispatch('Logout').then(() => {
              next({ path: '/user/login', query: { redirect: to.fullPath } })
            })
          })
        a++
      } else {
        next()
      }
    }
  } else {
    if (whiteList.includes(to.name)) {
      // 在免登录白名单,直接进入
      next()
    } else {
      next({ path: '/user/login', query: { redirect: to.fullPath } })
      NProgress.done() // if current page is login will not trigger afterEach hook, so manually handle it
    }
  }
})

router.afterEach(() => {
  NProgress.done() // finish progress bar
})

vueX更换接口

antdesign pro 权限 ant design vue pro权限_antdesign pro 权限_07

antdesign pro 权限 ant design vue pro权限_antdesign pro 权限_08


需要对vuex里的permission.js做一些改动GenerateRoutes

antdesign pro 权限 ant design vue pro权限_node.js_09


antdesign pro 权限 ant design vue pro权限_antdesign pro 权限_10


vuex里permission.js

import { asyncRouterMap, constantRouterMap } from '@/config/router.config'

/**
 * 过滤账户是否拥有某一个权限,并将菜单从加载列表移除
 *
 * @param permission
 * @param route
 * @returns {boolean}
 */
function hasPermission (permission, route) {
  console.log(route, 'route')
  console.log(route.meta, 'route.meta')
  if (route.meta && route.meta.permission) {
    let flag = false
    for (let i = 0, len = permission.length; i < len; i++) {
      flag = route.meta.permission.includes(permission[i])
      if (flag) {
        return true
      }
    }
    return false
  }
  return true
}

/**
 * 单账户多角色时,使用该方法可过滤角色不存在的菜单
 *
 * @param roles
 * @param route
 * @returns {*}
 */
// eslint-disable-next-line
function hasRole(roles, route) {
  if (route.meta && route.meta.roles) {
    return route.meta.roles.includes(roles.id)
  } else {
    return true
  }
}

function filterAsyncRouter (routerMap, roles) {
  console.log(roles, 'filterAsyncRouterroute')
  console.log(routerMap, 'filterAsyncRouterrouterMap')
  const accessedRouters = routerMap.filter(route => {
    if (hasPermission(roles.permissionList, route)) {
      if (route.children && route.children.length) {
        route.children = filterAsyncRouter(route.children, roles)
      }
      return true
    }
    return false
  })
  return accessedRouters
}

const permission = {
  state: {
    routers: constantRouterMap,
    addRouters: []
  },
  mutations: {
    SET_ROUTERS: (state, routers) => {
      state.addRouters = routers
      state.routers = constantRouterMap.concat(routers)
    }
  },
  actions: {
    GenerateRoutes ({ commit }, data) {
      return new Promise(resolve => {
        //const { roles } = data
        const roles  = data//取消括号不然会拿不到值
        const accessedRouters = filterAsyncRouter(asyncRouterMap, roles)
        commit('SET_ROUTERS', accessedRouters)
        resolve()
      })
    }
  }
}

export default permission

vuex里的user.js

import Vue from 'vue'
import { login, getInfo, logout } from '@/api/login'
import { ACCESS_TOKEN } from '@/store/mutation-types'
import { welcome } from '@/utils/util'
import { rolePrivilege } from '@/api/privilege'
const user = {
  state: {
    token: '',
    name: '',
    welcome: '',
    avatar: '',
    roles: [],
    info: {}
  },

  mutations: {
    SET_TOKEN: (state, token) => {
      state.token = token
    },
    SET_NAME: (state, { name, welcome }) => {
      state.name = name
      state.welcome = welcome
    },
    SET_AVATAR: (state, avatar) => {
      state.avatar = avatar
    },
    SET_ROLES: (state, roles) => {
      state.roles = roles
    },
    SET_INFO: (state, info) => {
      state.info = info
    }
  },

  actions: {
    // 登录
    Login ({ commit }, userInfo) {
      return new Promise((resolve, reject) => {
        login(userInfo).then(response => {
          const result = response.result
          Vue.ls.set(ACCESS_TOKEN, result.token, 7 * 24 * 60 * 60 * 1000)
          commit('SET_TOKEN', result.token)
          resolve()
        }).catch(error => {
          reject(error)
        })
      })
    },


    // // 获取用户信息
    // GetInfo ({ commit }) {
    //   var user = JSON.parse(sessionStorage.getItem('user'))
    //   return new Promise((resolve, reject) => {
    //     if (user.roleId === null) {
    //       console.log(user, 'getinfouser')
    //       var role = {
    //         permissionList: [
    //           'from',
    //           'table',
    //           'dashboard',
    //         ]
    //       }
    //       resolve(role)
    //       reject(new Error('getInfo: roles must be a non-null array !'))
    //     } else {
    //       rolePrivilege(user).then(response => {
    //         const result = response.result
    //
    //         if (result.role && result.role.permissions.length > 0) {
    //           const role = result.role
    //           role.permissions = result.role.permissions
    //           role.permissions.map(per => {
    //             if (per.actionEntitySet != null && per.actionEntitySet.length > 0) {
    //               const action = per.actionEntitySet.map(action => { return action.action })
    //               per.actionList = action
    //             }
    //           })
    //           role.permissionList = role.permissions.map(permission => { return permission.permissionId })
    //           commit('SET_ROLES', result.role)
    //           commit('SET_INFO', result)
    //         } else {
    //           reject(new Error('getInfo: roles must be a non-null array !'))
    //         }
    //
    //         commit('SET_NAME', { name: result.name, welcome: welcome() })
    //         commit('SET_AVATAR', result.avatar)
    //
    //         resolve(response)
    //       }).catch(error => {
    //         reject(error)
    //       })
    //     }
    //     // getInfo().then(response => {
    //     //   console.log(response, 'response')
    //     //         const result = response.result
    //     //
    //     //         if (result.role && result.role.permissions.length > 0) {
    //     //           const role = result.role
    //     //           role.permissions = result.role.permissions
    //     //           role.permissions.map(per => {
    //     //             if (per.actionEntitySet != null && per.actionEntitySet.length > 0) {
    //     //               const action = per.actionEntitySet.map(action => { return action.action })
    //     //               per.actionList = action
    //     //             }
    //     //           })
    //     //           role.permissionList = role.permissions.map(permission => { return permission.permissionId })
    //     //           commit('SET_ROLES', result.role)
    //     //           commit('SET_INFO', result)
    //     //         } else {
    //     //           reject(new Error('getInfo: roles must be a non-null array !'))
    //     //         }
    //     //
    //     //         commit('SET_NAME', { name: result.name, welcome: welcome() })
    //     //         commit('SET_AVATAR', result.avatar)
    //     //
    //     //         resolve(response)
    //     //       }).catch(error => {
    //     //         reject(error)
    //     //       })
    //   })
    // },



    // 登出
    Logout ({ commit, state }) {
      return new Promise((resolve) => {
        logout(state.token).then(() => {
          resolve()
        }).catch(() => {
          resolve()
        }).finally(() => {
          commit('SET_TOKEN', '')
          commit('SET_ROLES', [])
          Vue.ls.remove(ACCESS_TOKEN)
        })
      })
    }

  }
}

export default user

可做参考router.config.js动态添加菜单

// eslint-disable-next-linexue
import { UserLayout, BasicLayout, RouteView, BlankLayout, PageView } from '@/layouts'
import { bxAnaalyse } from '@/core/icons'
import { tree } from '@/api/privilege'


const constantRouterComponents = {
  // 基础页面 layout 必须引入
  BasicLayout: BasicLayout,
  BlankLayout: BlankLayout,
  RouteView: RouteView,
  PageView: PageView,
  '403': () => import(/* webpackChunkName: "error" */ '@/views/exception/403'),
  '404': () => import(/* webpackChunkName: "error" */ '@/views/exception/404'),
  '500': () => import(/* webpackChunkName: "error" */ '@/views/exception/500'),

  // 你需要动态引入的页面组件
  '首页': () => import('@/views/home/index'),
  '部门管理': () => import('@/views/Staff/Department'),
  '人员管理': () => import('@/views/Staff/StaffManagement'),
  '数据字典': () => import('@/views/SystemSetup/Dictionary'),
  '设备核对': () => import('@/views/OperationAnalysis/EquipmentCheck'),
  '报警信息': () => import('@/views/OperationAnalysis/DeviceAlarm'),
  '用户管理': () => import('@/views/Privilege/UserManage'),
  '角色管理': () => import('@/views/Privilege/RoleManage'),
  '菜单管理': () => import('@/views/Privilege/MenuManage'),
  '学校管理': () => import('@/views/SchoolManage/schoolManage'),
  '设备登记表': () => import('@/views/SchoolManage/EquipmentRegistration'),
  '通讯参数': () => import('@/views/SchoolManage/CommParameters'),
  '项目管理': () => import('@/views/projectManage')
}

// 根级菜单
const rootRouter = {
  path: '/',
  name: 'home',
  component: BasicLayout,
  meta: { title: '首页' },
  redirect: '/home',
  children: []
}
const notFoundRouter = {
  path: '*', redirect: '/404', hidden: true
}

export const asyncRouterMap = () => {
  return new Promise(resolve => {
    tree().then(value => {
      // const { result } = value.data
      const menuNav = []
      const routers = generator(value.data)
      rootRouter.children = routers
      menuNav.push(rootRouter)
      menuNav.push(notFoundRouter)
      // var data = [
      //   {
      //     path: '/',
      //     name: 'index',
      //     component: BasicLayout,
      //     meta: { title: '首页' },
      //     children: [
      //       // 人员管理
      //       {
      //         path: '/Staff',
      //         redirect: '/Staff/Department',
      //         name: 'Staff',
      //         component: PageView,
      //         meta: { title: '人员管理', icon: 'form', permission: [ '17' ] },
      //         children: [
      //           {
      //             path: '/Staff/Department',
      //             name: '部门管理',
      //             component: () => import('@/views/Staff/Department'),
      //             meta: { title: '部门管理', permission: [ '18' ] }
      //           },
      //           {
      //             path: '/Staff/StaffManagement',
      //             name: '人员管理',
      //             component: () => import('@/views/Staff/StaffManagement'),
      //             meta: { title: '人员管理', permission: [ '19' ] }
      //           }
      //         ]
      //       },
      //       // 系统设置
      //       {
      //         path: '/SystemSetup',
      //         redirect: '/SystemSetup/Dictionary',
      //         component: PageView,
      //         meta: { title: '系统设置', icon: 'form', permission: [ 'SystemSetup' ] },
      //         children: [
      //           {
      //             path: '/SystemSetup/Dictionary',
      //             name: 'Dictionary',
      //             component: () => import('@/views/SystemSetup/Dictionary'),
      //             meta: { title: '数据字典', permission: [ 'SystemSetup' ] }
      //           }
      //         ]
      //       },
      //       // 运维分析
      //       {
      //         path: '/OperationAnalysis',
      //         redirect: '/OperationAnalysis/EquipmentCheck',
      //         component: PageView,
      //         meta: { title: '运维分析', icon: 'form', permission: [ 'OperationAnalysis' ] },
      //         children: [
      //           {
      //             path: '/OperationAnalysis/EquipmentCheck',
      //             name: 'EquipmentCheck',
      //             component: () => import('@/views/OperationAnalysis/EquipmentCheck'),
      //             meta: { title: '设备核对', permission: [ 'OperationAnalysis' ] }
      //           }
      //         ]
      //       },
      //       // 权限管理
      //       {
      //         path: '/Privilege',
      //         name: 'Privilege',
      //         component: PageView,
      //         meta: { title: '权限管理', icon: 'bank', permission: [ 'Privilege' ] },
      //         children: [
      //           {
      //             path: '/Privilege/UserManage',
      //             name: 'UserManage',
      //             component: () => import('@/views/Privilege/UserManage'),
      //             meta: { title: '用户管理', icon: 'bank', permission: [ 'Privilege' ] }
      //           },
      //           {
      //             path: '/Privilege/RoleManage',
      //             name: 'RoleManage',
      //             component: () => import('@/views/Privilege/RoleManage'),
      //             meta: { title: '角色管理', icon: 'bank', permission: [ 'Privilege' ] }
      //           },
      //           {
      //             path: '/Privilege/MenuManage',
      //             name: 'MenuManage',
      //             component: () => import('@/views/Privilege/MenuManage'),
      //             meta: { title: '菜单管理', icon: 'bank', permission: [ 'Privilege' ] }
      //           }
      //         ]
      //       },
      //       // 学校管理
      //       {
      //         path: '/school',
      //         name: 'school',
      //         component: PageView,
      //         meta: { title: '学校管理', icon: 'bank', permission: [ 'school' ] },
      //         children: [
      //           {
      //             path: '/school/SchoolManage',
      //             name: 'SchoolManage',
      //             component: () => import('@/views/SchoolManage/schoolManage'),
      //             meta: { title: '学校管理', icon: 'bank', permission: [ 'school' ] }
      //           },
      //           {
      //             path: '/school/EquipmentRegistration',
      //             name: 'EquipmentRegistration',
      //             component: () => import('@/views/SchoolManage/EquipmentRegistration'),
      //             meta: { title: '设备登记表', icon: 'exception', permission: [ 'school' ] }
      //           },
      //           {
      //             path: '/school/CommParameters',
      //             name: 'CommParameters',
      //             component: () => import('@/views/SchoolManage/CommParameters'),
      //             meta: { title: '通讯参数', icon: 'global', permission: [ 'school' ] }
      //           }
      //         ]
      //       },
      //       // 项目管理
      //       {
      //         path: '/projectManage',
      //         name: 'projectManage',
      //         component: () => import('@/views/projectManage'),
      //         meta: { title: '项目管理', icon: 'project', permission: [ 'projectManage' ] }
      //       }
      //     ]
      //   },
      //   {
      //     path: '*', redirect: '/404', hidden: true
      //   }
      // ]
      resolve(menuNav)
    })
  })
}

export const generator = (routerMap, parent) => {
  return routerMap.map(item => {
    const { title, show, hideChildren, hiddenHeaderContent, target, icon } = item.meta || {}
    const currentRouter = {
      // 如果路由设置了 path,则作为默认 path,否则 路由地址 动态拼接生成如 /dashboard/workplace
      path: item.resourcePath || `${parent && parent.path || ''}/${item.key}`,
      // 路由名称,建议唯一
      name: item.id || item.key || '',
      // 该路由对应页面的 组件 :方案1
      component: item.parentId === null && item.title !== '项目管理' && item.title !== '首页' ? PageView : constantRouterComponents[item.title],

      // 该路由对应页面的 组件 :方案2 (动态加载)
      // component: constantRouterComponents[item.component || item.key] || () => import(`@/views/${item.component}`),

      // meta: 页面标题, 菜单图标, 页面权限(供指令权限用,可去掉)
      meta: { title: item.title, icon: item.icon || undefined, permission: [`${item.id}`] }
    }
    // 是否设置了隐藏菜单
    if (show === false) {
      currentRouter.hidden = true
    }
    // 是否设置了隐藏子菜单
    if (hideChildren) {
      currentRouter.hideChildrenInMenu = true
    }
    // 为了防止出现后端返回结果不规范,处理有可能出现拼接出两个 反斜杠
    if (!currentRouter.path.startsWith('http')) {
      currentRouter.path = currentRouter.path.replace('//', '/')
    }
    // 重定向
    item.redirect && (currentRouter.redirect = item.redirect)
    // 是否有子菜单,并递归处理
    if (item.children && item.children.length > 0) {
      // Recursion
      currentRouter.children = generator(item.children, currentRouter)
    }
    return currentRouter
  })
}

/**
 * 基础路由
 * @type { *[] }
 */
export const constantRouterMap = [
  {
    path: '/user',
    component: UserLayout,
    redirect: '/user/login',
    hidden: true,
    children: [
      {
        path: 'login',
        name: 'login',
        component: () => import(/* webpackChunkName: "user" */ '@/views/user/Login')
      },
      {
        path: 'register',
        name: 'register',
        component: () => import(/* webpackChunkName: "user" */ '@/views/user/Register')
      },
      {
        path: 'register-result',
        name: 'registerResult',
        component: () => import(/* webpackChunkName: "user" */ '@/views/user/RegisterResult')
      },
      {
        path: 'recover',
        name: 'recover',
        component: undefined
      }
    ]
  },

  {
    path: '/test',
    component: BlankLayout,
    redirect: '/test/home',
    children: [
      {
        path: 'home',
        name: 'TestHome',
        component: () => import('@/views/Home')
      }
    ]
  },

  {
    path: '/404',
    component: () => import(/* webpackChunkName: "fail" */ '@/views/exception/404')
  }

]

这是我们做的模仿jeecg-boot的菜单界面

antdesign pro 权限 ant design vue pro权限_验证码_11

成功完成登陆后,可以打印vuex信息

antdesign pro 权限 ant design vue pro权限_node.js_12