• vue-element-admin 权限管理看完这个帖子就够了


    说明下 小编是19年1月开始接触vue-element-admin的,一直没时间整理笔记 就随意整理一下吧 

    其实也没什么说的 太简单了 就说说动态路由鉴权的

    原理是 两个接口 

    流程其实是这样的

    1.登录页面按钮点击
    2.vuex 里面的 login 方法被调用
    3.vuex 里面的 login 方法被调用 完毕
    4.监听路由改变 然后获取当前登录的用户角色
    5.获取当前用户信息 获取角色组 并保存登录状态,返回当前角色信息
    6.通过 角色 和 所有路由 匹配出对应角色拥有的路由权限 返回路由组
    7将上面获取到的 路由权限 挂载到真实的路由上面去

    然后说下参与路由权限 牵扯的文件吧

    /src/view/login/index.vue 登录页面的入口文件

    /src/store/modules/user.js vuex 的文件 全局方法

    /src/permission.js 监听路由改变后的js

    /src/store/mudules/permission.js 通过 角色返回 登录角色的对应路由列表的方法

    srcviewspermissioncomponents/SwitchRoles.vue 切换角色的文件 这个登录不走 切换角色才会走

    不说了直接上代码

    ///src/view/login/index.vue
    ///src/view/login/index.vue
    <template> <div class="login-container"> <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" autocomplete="on" label-position="left"> <div class="title-container"> <h3 class="title">Login Form</h3> </div> <el-form-item prop="username"> <span class="svg-container"> <svg-icon icon-class="user" /> </span> <el-input ref="username" v-model="loginForm.username" placeholder="Username" name="username" type="text" tabindex="1" autocomplete="on" /> </el-form-item> <el-tooltip v-model="capsTooltip" content="Caps lock is On" placement="right" manual> <el-form-item prop="password"> <span class="svg-container"> <svg-icon icon-class="password" /> </span> <el-input :key="passwordType" ref="password" v-model="loginForm.password" :type="passwordType" placeholder="Password" name="password" tabindex="2" autocomplete="on" @keyup.native="checkCapslock" @blur="capsTooltip = false" @keyup.enter.native="handleLogin" /> <span class="show-pwd" @click="showPwd"> <svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" /> </span> </el-form-item> </el-tooltip> <el-button :loading="loading" type="primary" style="100%;margin-bottom:30px;" @click.native.prevent="handleLogin">Login</el-button> <div style="position:relative"> <div class="tips"> <span>Username : admin</span> <span>Password : any</span> </div> <div class="tips"> <span style="margin-right:18px;">Username : editor</span> <span>Password : any</span> </div> <el-button class="thirdparty-button" type="primary" @click="showDialog=true"> Or connect with </el-button> </div> </el-form> <el-dialog title="Or connect with" :visible.sync="showDialog"> Can not be simulated on local, so please combine you own business simulation! ! ! <br> <br> <br> <social-sign /> </el-dialog> </div> </template> <script> import { validUsername } from '@/utils/validate' import SocialSign from './components/SocialSignin' export default { name: 'Login', components: { SocialSign }, data() { const validateUsername = (rule, value, callback) => { if (!validUsername(value)) { callback(new Error('Please enter the correct user name')) } else { callback() } } const validatePassword = (rule, value, callback) => { if (value.length < 6) { callback(new Error('The password can not be less than 6 digits')) } else { callback() } } return { loginForm: { username: 'admin', password: '111111' }, loginRules: { username: [{ required: true, trigger: 'blur', validator: validateUsername }], password: [{ required: true, trigger: 'blur', validator: validatePassword }] }, passwordType: 'password', capsTooltip: false, loading: false, showDialog: false, redirect: undefined, otherQuery: {} } }, watch: { $route: { handler: function(route) { const query = route.query if (query) { this.redirect = query.redirect this.otherQuery = this.getOtherQuery(query) } }, immediate: true } }, created() { // window.addEventListener('storage', this.afterQRScan) }, mounted() { if (this.loginForm.username === '') { this.$refs.username.focus() } else if (this.loginForm.password === '') { this.$refs.password.focus() } }, destroyed() { // window.removeEventListener('storage', this.afterQRScan) }, methods: { checkCapslock(e) { const { key } = e this.capsTooltip = key && key.length === 1 && (key >= 'A' && key <= 'Z') }, showPwd() { if (this.passwordType === 'password') { this.passwordType = '' } else { this.passwordType = 'password' } this.$nextTick(() => { this.$refs.password.focus() }) }, handleLogin() { console.info("1.登录页面按钮点击"); this.$refs.loginForm.validate(valid => { if (valid) { this.loading = true this.$store.dispatch('user/login', this.loginForm) .then(() => { console.info("3.vuex 里面的 login 方法被调用 完毕"); this.$router.push({ path: this.redirect || '/', query: this.otherQuery });//进入路由 this.loading = false }) .catch(() => { this.loading = false }) } else { console.log('error submit!!') return false } }) }, getOtherQuery(query) { return Object.keys(query).reduce((acc, cur) => { if (cur !== 'redirect') { acc[cur] = query[cur] } return acc }, {}) } // afterQRScan() { // if (e.key === 'x-admin-oauth-code') { // const code = getQueryObject(e.newValue) // const codeMap = { // wechat: 'code', // tencent: 'code' // } // const type = codeMap[this.auth_type] // const codeName = code[type] // if (codeName) { // this.$store.dispatch('LoginByThirdparty', codeName).then(() => { // this.$router.push({ path: this.redirect || '/' }) // }) // } else { // alert('第三方登录失败') // } // } // } } } </script> <style lang="scss"> /* 修复input 背景不协调 和光标变色 */ /* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */ $bg:#283443; $light_gray:#fff; $cursor: #fff; @supports (-webkit-mask: none) and (not (cater-color: $cursor)) { .login-container .el-input input { color: $cursor; } } /* reset element-ui css */ .login-container { .el-input { display: inline-block; height: 47px; 85%; input { background: transparent; border: 0px; -webkit-appearance: none; border-radius: 0px; padding: 12px 5px 12px 15px; color: $light_gray; height: 47px; caret-color: $cursor; &:-webkit-autofill { box-shadow: 0 0 0px 1000px $bg inset !important; -webkit-text-fill-color: $cursor !important; } } } .el-form-item { border: 1px solid rgba(255, 255, 255, 0.1); background: rgba(0, 0, 0, 0.1); border-radius: 5px; color: #454545; } } </style> <style lang="scss" scoped> $bg:#2d3a4b; $dark_gray:#889aa4; $light_gray:#eee; .login-container { min-height: 100%; 100%; background-color: $bg; overflow: hidden; .login-form { position: relative; 520px; max- 100%; padding: 160px 35px 0; margin: 0 auto; overflow: hidden; } .tips { font-size: 14px; color: #fff; margin-bottom: 10px; span { &:first-of-type { margin-right: 16px; } } } .svg-container { padding: 6px 5px 6px 15px; color: $dark_gray; vertical-align: middle; 30px; display: inline-block; } .title-container { position: relative; .title { font-size: 26px; color: $light_gray; margin: 0px auto 40px auto; text-align: center; font-weight: bold; } } .show-pwd { position: absolute; right: 10px; top: 7px; font-size: 16px; color: $dark_gray; cursor: pointer; user-select: none; } .thirdparty-button { position: absolute; right: 0; bottom: 6px; } @media only screen and (max- 470px) { .thirdparty-button { display: none; } } } </style>

    /src/store/modules/user.js

    import { login, logout, getInfo } from '@/api/user'
    import { getToken, setToken, removeToken } from '@/utils/auth'
    import router, { resetRouter } from '@/router'
    
    //状态列表
    const state = {
      token: getToken(),
      name: '',
      avatar: '',
      introduction: '',
      roles: []
    }
    
    //修改vuex 的入口
    const mutations = {
      SET_TOKEN: (state, token) => {
        state.token = token
      },
      SET_INTRODUCTION: (state, introduction) => {
        state.introduction = introduction
      },
      SET_NAME: (state, name) => {
        state.name = name
      },
      SET_AVATAR: (state, avatar) => {
        state.avatar = avatar
      },
      SET_ROLES: (state, roles) => {
        state.roles = roles
      }
    }
    
    //全局方法
    const actions = {
      // user login 登录方法
      login({ commit }, userInfo) {
        console.info("2.vuex 里面的 login 方法被调用");
        const { username, password } = userInfo
        return new Promise((resolve, reject) => {
          login({ username: username.trim(), password: password }).then(response => {
            //登录成功后 保存 token
            const { data } = response
            commit('SET_TOKEN', data.token)
            setToken(data.token)
            resolve();//返回成功
          }).catch(error => {
            reject(error)
          })
        })
      },
    
      // get user info 获取用户信息
      getInfo({ commit, state }) {
        return new Promise((resolve, reject) => {
          console.info("5.获取当前用户信息 获取角色组 并保存登录状态,返回当前角色信息");
          getInfo(state.token).then(response => {
            const { data } = response
    
            if (!data) {
              reject('Verification failed, please Login again.')
            }
    
            const { roles, name, avatar, introduction } = data
    
            // roles must be a non-empty array
            if (!roles || roles.length <= 0) {
              reject('getInfo: roles must be a non-null array!')
            }
            
            //修改用户登录的信息 调用 commit方法
            commit('SET_ROLES', roles)
            commit('SET_NAME', name)
            commit('SET_AVATAR', avatar)
            commit('SET_INTRODUCTION', introduction);
    
            
    
            resolve(data)
          }).catch(error => {
            reject(error)
          })
        })
      },
    
      // user logout 退出登录
      logout({ commit, state, dispatch }) {
        return new Promise((resolve, reject) => {
          logout(state.token).then(() => {
            commit('SET_TOKEN', '')
            commit('SET_ROLES', [])
            removeToken()
            resetRouter()
    
            // reset visited views and cached views
            // to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2485
            dispatch('tagsView/delAllViews', null, { root: true })
    
            resolve()
          }).catch(error => {
            reject(error)
          })
        })
      },
    
      // remove token 清除登录信息 token什么的
      resetToken({ commit }) {
        return new Promise(resolve => {
          commit('SET_TOKEN', '')
          commit('SET_ROLES', [])
          removeToken()
          resolve()
        })
      },
    
      // dynamically modify permissions 更改角色 这个方法登录的时候应该不调用 是在登录成功后切换角色使用的
      changeRoles({ commit, dispatch }, role) {
        //console.info("4.调用vuex changeRoles 方法 进入");
        return new Promise(async resolve => {
          const token = role + '-token'
    
          commit('SET_TOKEN', token)
          setToken(token)
    
          const { roles } = await dispatch('getInfo');//调用这个文件里面的 getInfo方法
    
          resetRouter()
    
          // generate accessible routes map based on roles
          const accessRoutes = await dispatch('permission/generateRoutes', roles, { root: true })
    
          // dynamically add accessible routes
          router.addRoutes(accessRoutes)
    
          // reset visited views and cached views
          dispatch('tagsView/delAllViews', null, { root: true })
    
          resolve()
        })
      }
    }
    
    export default {
      namespaced: true,
      state,
      mutations,
      actions
    }

     /src/permission.js

    import router from './router'
    import store from './store'
    import { Message } from 'element-ui'
    import NProgress from 'nprogress' // progress bar
    import 'nprogress/nprogress.css' // progress bar style
    import { getToken } from '@/utils/auth' // get token from cookie
    import getPageTitle from '@/utils/get-page-title'
    
    NProgress.configure({ showSpinner: false }) // NProgress Configuration
    
    const whiteList = ['/login', '/auth-redirect'] // no redirect whitelist
    
    router.beforeEach(async(to, from, next) => {
      // start progress bar
      NProgress.start()
    
      // set page title
      document.title = getPageTitle(to.meta.title)
    
      // determine whether the user has logged in
      const hasToken = getToken()
    
      if (hasToken) {
        if (to.path === '/login') {
          // if is logged in, redirect to the home page
          next({ path: '/' })
          NProgress.done()
        } else {
          // determine whether the user has obtained his permission roles through getInfo
          const hasRoles = store.getters.roles && store.getters.roles.length > 0
          if (hasRoles) {
            next()
          } else {
            try {
              // get user info
              // note: roles must be a object array! such as: ['admin'] or ,['developer','editor']
    
              //监听路由改变的时候 调用 获取当前登录用户身份信息
    
              console.info("4.监听路由改变 然后获取当前登录的用户角色");
              const { roles } = await store.dispatch('user/getInfo');//拿到当前的用户信息 角色
    
              // generate accessible routes map based on roles
              const accessRoutes = await store.dispatch('permission/generateRoutes', roles);
    
              
              //将上面获取到的 路由权限 挂载到真实的路由上面去
              console.info("7.将上面获取到的 路由权限 挂载到真实的路由上面去");
              // dynamically add accessible routes
              router.addRoutes(accessRoutes)
    
              // hack method to ensure that addRoutes is complete
              // set the replace: true, so the navigation will not leave a history record
              next({ ...to, replace: true })
            } catch (error) {
              // remove token and go to login page to re-login
              await store.dispatch('user/resetToken')
              Message.error(error || 'Has Error')
              next(`/login?redirect=${to.path}`)
              NProgress.done()
            }
          }
        }
      } else {
        /* has no token*/
    
        if (whiteList.indexOf(to.path) !== -1) {
          // in the free login whitelist, go directly
          next()
        } else {
          // other pages that do not have permission to access are redirected to the login page.
          next(`/login?redirect=${to.path}`)
          NProgress.done()
        }
      }
    })
    
    router.afterEach(() => {
      // finish progress bar
      NProgress.done()
    })

    /src/store/mudules/permission.js

    import { asyncRoutes, constantRoutes } from '@/router'
    
    /**
     * Use meta.role to determine if the current user has permission
     * @param roles
     * @param route
     */
    function hasPermission(roles, route) {
      if (route.meta && route.meta.roles) {
        return roles.some(role => route.meta.roles.includes(role))
      } else {
        return true
      }
    }
    
    /**
     * Filter asynchronous routing tables by recursion
     * @param routes asyncRoutes
     * @param roles
     */
    export function filterAsyncRoutes(routes, roles) {
      const res = []
    
      routes.forEach(route => {
        const tmp = { ...route }
        if (hasPermission(roles, tmp)) {
          if (tmp.children) {
            tmp.children = filterAsyncRoutes(tmp.children, roles)
          }
          res.push(tmp)
        }
      })
    
      return res
    }
    
    const state = {
      routes: [],
      addRoutes: []
    }
    
    const mutations = {
      SET_ROUTES: (state, routes) => {
        state.addRoutes = routes
        state.routes = constantRoutes.concat(routes)
      }
    }
    
    const actions = {
      //通过 角色 和 所有路由 匹配出对应角色拥有的路由权限
      generateRoutes({ commit }, roles) {
        console.info("6.通过 角色 和 所有路由 匹配出对应角色拥有的路由权限 返回路由组");
        return new Promise(resolve => {
          let accessedRoutes
          if (roles.includes('admin')) {
            accessedRoutes = asyncRoutes || []
          } else {
            accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
          }
          commit('SET_ROUTES', accessedRoutes)
          resolve(accessedRoutes)
        })
      }
    }
    
    export default {
      namespaced: true,
      state,
      mutations,
      actions
    }

    最后讲下怎么动态切换身份加路由吧 权限开关

    srcviewspermissioncomponents/SwitchRoles.vue

    srcviewspermissionpage.vue

    <template>
      <div>
        <div style="margin-bottom:15px;">
          Your roles: {{ roles }}
        </div>
        Switch roles:
        <el-radio-group v-model="switchRoles">
          <el-radio-button label="editor" />
          <el-radio-button label="admin" />
        </el-radio-group>
      </div>
    </template>
    
    <script>
    export default {
      computed: {
        roles() {
          return this.$store.getters.roles
        },
        switchRoles: {
          get() {
            return this.roles[0]
          },
          //设置权限  传权限名称
          set(val) {
            this.$store.dispatch('user/changeRoles', val).then(() => {
              this.$emit('change')
            })
          }
        }
      }
    }
    </script>

    页面里面 通过指令来区分身份 内置自带的自定义指令

    /src/views/permission/directive.vue

    <template>
      <div class="app-container">
        <switch-roles @change="handleRolesChange" />
        <div :key="key" style="margin-top:30px;">
          <div>
            <span v-permission="['admin']" class="permission-alert">
              Only
              <el-tag class="permission-tag" size="small">admin</el-tag> can see this
            </span>
            <el-tag v-permission="['admin']" class="permission-sourceCode" type="info">
              v-permission="['admin']"
            </el-tag>
          </div>
    
          <div>
            <span v-permission="['editor']" class="permission-alert">
              Only
              <el-tag class="permission-tag" size="small">editor</el-tag> can see this
            </span>
            <el-tag v-permission="['editor']" class="permission-sourceCode" type="info">
              v-permission="['editor']"
            </el-tag>
          </div>
    
          <div>
            <span v-permission="['admin','editor']" class="permission-alert">
              Both
              <el-tag class="permission-tag" size="small">admin</el-tag> and
              <el-tag class="permission-tag" size="small">editor</el-tag> can see this
            </span>
            <el-tag v-permission="['admin','editor']" class="permission-sourceCode" type="info">
              v-permission="['admin','editor']"
            </el-tag>
          </div>
        </div>
    
        <div :key="'checkPermission'+key" style="margin-top:60px;">
          <aside>
            In some cases, using v-permission will have no effect. For example: Element-UI's Tab component or el-table-column and other scenes that dynamically render dom. You can only do this with v-if.
            <br> e.g.
          </aside>
    
          <el-tabs type="border-card" style="550px;">
            <el-tab-pane v-if="checkPermission(['admin'])" label="Admin">
              Admin can see this
              <el-tag class="permission-sourceCode" type="info">
                v-if="checkPermission(['admin'])"
              </el-tag>
            </el-tab-pane>
    
            <el-tab-pane v-if="checkPermission(['editor'])" label="Editor">
              Editor can see this
              <el-tag class="permission-sourceCode" type="info">
                v-if="checkPermission(['editor'])"
              </el-tag>
            </el-tab-pane>
    
            <el-tab-pane v-if="checkPermission(['admin','editor'])" label="Admin-OR-Editor">
              Both admin or editor can see this
              <el-tag class="permission-sourceCode" type="info">
                v-if="checkPermission(['admin','editor'])"
              </el-tag>
            </el-tab-pane>
          </el-tabs>
        </div>
      </div>
    </template>
    
    <script>
    import permission from '@/directive/permission/index.js' // 权限判断指令
    import checkPermission from '@/utils/permission' // 权限判断函数
    import SwitchRoles from './components/SwitchRoles'
    
    export default {
      name: 'DirectivePermission',
      components: { SwitchRoles },
      directives: { permission },
      data() {
        return {
          key: 1 // 为了能每次切换权限的时候重新初始化指令
        }
      },
      methods: {
        checkPermission,
        handleRolesChange() {
          this.key++
        }
      }
    }
    </script>
    
    <style lang="scss" scoped>
    .app-container {
      /deep/ .permission-alert {
         320px;
        margin-top: 15px;
        background-color: #f0f9eb;
        color: #67c23a;
        padding: 8px 16px;
        border-radius: 4px;
        display: inline-block;
      }
      /deep/ .permission-sourceCode {
        margin-left: 15px;
      }
      /deep/ .permission-tag {
        background-color: #ecf5ff;
      }
    }
    </style>

    好了 重头戏来了 动态修改角色的权限 这个可是一个好东西 直接上代码吧

    <template>
      <div class="app-container">
        <el-button type="primary" @click="handleAddRole">New Role</el-button>

        <el-table :data="rolesList" style=" 100%;margin-top:30px;" border>
          <el-table-column align="center" label="Role Key" width="220">
            <template slot-scope="scope">
              {{ scope.row.key }}
            </template>
          </el-table-column>
          <el-table-column align="center" label="Role Name" width="220">
            <template slot-scope="scope">
              {{ scope.row.name }}
            </template>
          </el-table-column>
          <el-table-column align="header-center" label="Description">
            <template slot-scope="scope">
              {{ scope.row.description }}
            </template>
          </el-table-column>
          <el-table-column align="center" label="Operations">
            <template slot-scope="scope">
              <el-button type="primary" size="small" @click="handleEdit(scope)">Edit</el-button>
              <el-button type="danger" size="small" @click="handleDelete(scope)">Delete</el-button>
            </template>
          </el-table-column>
        </el-table>

        <el-dialog :visible.sync="dialogVisible" :title="dialogType==='edit'?'Edit Role':'New Role'">
          <el-form :model="role" label-width="80px" label-position="left">
            <el-form-item label="Name">
              <el-input v-model="role.name" placeholder="Role Name" />
            </el-form-item>
            <el-form-item label="Desc">
              <el-input
                v-model="role.description"
                :autosize="{ minRows: 2, maxRows: 4}"
                type="textarea"
                placeholder="Role Description"
              />
            </el-form-item>
            <el-form-item label="Menus">
              <el-tree
                ref="tree"
                :check-strictly="checkStrictly"
                :data="routesData"
                :props="defaultProps"
                show-checkbox
                node-key="path"
                class="permission-tree"
              />
            </el-form-item>
          </el-form>
          <div style="text-align:right;">
            <el-button type="danger" @click="dialogVisible=false">Cancel</el-button>
            <el-button type="primary" @click="confirmRole">Confirm</el-button>
          </div>
        </el-dialog>
      </div>
    </template>

    <script>
    import path from 'path'
    import { deepClone } from '@/utils';//这个是什么方法
    import { getRoutes, getRoles, addRole, deleteRole, updateRole } from '@/api/role'

    //默认路由权限列表
    const defaultRole = {
      key: '',
      name: '',
      description: '',
      routes: []
    }

    export default {
      data() {
        return {
          role: Object.assign({}, defaultRole),
          routes: [],//这个是路由的列表 
          rolesList: [],//这个是角色列表 身份列表 里面的 routes是他对应的权限 可拥有的权限
          dialogVisible: false,
          dialogType: 'new',
          checkStrictly: false,
          defaultProps: {
            children: 'children',
            label: 'title'
          }
        }
      },
      computed: {
        routesData() {
          return this.routes
        }
      },
      created() {
        // Mock: get all routes and roles list from server
        this.getRoutes();//获取全部的路由列表

        this.getRoles();//获取全部的角色加里面的权限路由
      },
      methods: {
        async getRoutes() {
          const res = await getRoutes()
          this.serviceRoutes = res.data
          this.routes = this.generateRoutes(res.data)
        },
        async getRoles() {
          const res = await getRoles()
          this.rolesList = res.data
        },

        // Reshape the routes structure so that it looks the same as the sidebar
        generateRoutes(routes, basePath = '/') {
          const res = []

          for (let route of routes) {
            // skip some route
            if (route.hidden) { continue }

            const onlyOneShowingChild = this.onlyOneShowingChild(route.children, route)

            if (route.children && onlyOneShowingChild && !route.alwaysShow) {
              route = onlyOneShowingChild
            }

            const data = {
              path: path.resolve(basePath, route.path),
              title: route.meta && route.meta.title

            }

            // recursive child routes
            if (route.children) {
              data.children = this.generateRoutes(route.children, data.path)
            }
            res.push(data)
          }
          return res
        },
        generateArr(routes) {
          let data = []
          routes.forEach(route => {
            data.push(route)
            if (route.children) {
              const temp = this.generateArr(route.children)
              if (temp.length > 0) {
                data = [...data, ...temp]
              }
            }
          })
          return data
        },
        //添加路由
        handleAddRole() {
          this.role = Object.assign({}, defaultRole)
          if (this.$refs.tree) {
            this.$refs.tree.setCheckedNodes([])
          }
          this.dialogType = 'new'
          this.dialogVisible = true
        },
        //修改路由的权限列表 路由权限
        handleEdit(scope) {
          this.dialogType = 'edit'
          this.dialogVisible = true
          this.checkStrictly = true
          this.role = deepClone(scope.row);
          this.$nextTick(() => {
            const routes = this.generateRoutes(this.role.routes)
            this.$refs.tree.setCheckedNodes(this.generateArr(routes))
            // set checked state of a node not affects its father and child nodes
            this.checkStrictly = false
          })
        },
        handleDelete({ $index, row }) {
          this.$confirm('Confirm to remove the role?', 'Warning', {
            confirmButtonText: 'Confirm',
            cancelButtonText: 'Cancel',
            type: 'warning'
          })
            .then(async() => {
              await deleteRole(row.key)
              this.rolesList.splice($index, 1)
              this.$message({
                type: 'success',
                message: 'Delete succed!'
              })
            })
            .catch(err => { console.error(err) })
        },
        generateTree(routes, basePath = '/', checkedKeys) {
          const res = []

          for (const route of routes) {
            const routePath = path.resolve(basePath, route.path)

            // recursive child routes
            if (route.children) {
              route.children = this.generateTree(route.children, routePath, checkedKeys)
            }

            if (checkedKeys.includes(routePath) || (route.children && route.children.length >= 1)) {
              res.push(route)
            }
          }
          return res
        },
        //提交修改
        async confirmRole() {
          const isEdit = this.dialogType === 'edit'

          const checkedKeys = this.$refs.tree.getCheckedKeys()
          this.role.routes = this.generateTree(deepClone(this.serviceRoutes), '/', checkedKeys)

          if (isEdit) {
            //修改
            await updateRole(this.role.key, this.role)
            for (let index = 0; index < this.rolesList.length; index++) {
              if (this.rolesList[index].key === this.role.key) {
                this.rolesList.splice(index, 1, Object.assign({}, this.role))
                break
              }
            }
          } else {
            //添加
            const { data } = await addRole(this.role)
            this.role.key = data.key
            this.rolesList.push(this.role)
          }

          const { description, key, name } = this.role
          this.dialogVisible = false
          this.$notify({
            title: 'Success',
            dangerouslyUseHTMLString: true,
            message: `
                <div>Role Key: ${key}</div>
                <div>Role Name: ${name}</div>
                <div>Description: ${description}</div>
              `,
            type: 'success'
          })
        },
        // reference: src/view/layout/components/Sidebar/SidebarItem.vue
        onlyOneShowingChild(children = [], parent) {
          let onlyOneChild = null
          const showingChildren = children.filter(item => !item.hidden)

          // When there is only one child route, the child route is displayed by default
          if (showingChildren.length === 1) {
            onlyOneChild = showingChildren[0]
            onlyOneChild.path = path.resolve(parent.path, onlyOneChild.path)
            return onlyOneChild
          }

          // Show parent if there are no child route to display
          if (showingChildren.length === 0) {
            onlyOneChild = { ... parent, path: '', noShowingChildren: true }
            return onlyOneChild
          }

          return false
        }
      }
    }
    </script>

    <style lang="scss" scoped>
    .app-container {
      .roles-table {
        margin-top: 30px;
      }
      .permission-tree {
        margin-bottom: 30px;
      }
    }
    </style>
  • 相关阅读:
    牛人读书 列表
    设计模式 简介
    java 并发编程 list
    Spring Boot 概念知识
    JS原生Date类型方法的一些冷知识
    JavaScript 操作 Cookie
    nodeJS(express4.x)+vue(vue-cli)构建前后端分离详细教程(带跨域)
    Vue学习笔记(一)
    windows下常查看端口占用方法总结
    webstorm添加*.vue文件代码提醒支持webstorm支持es6vue里支持es6写法
  • 原文地址:https://www.cnblogs.com/shaozhu520/p/12792592.html
Copyright © 2020-2023  润新知