美文网首页
前端的权限控制

前端的权限控制

作者: 简单tao的简单 | 来源:发表于2024-02-26 17:13 被阅读0次

    一 路由文件里定义两类路由

    1. 没有权限要求的路由页面 constantRoutes
    //router/index.js
    export const constantRoutes = [
      {
        path: '/login',
        component: () => import('@/views/login/index'),
        hidden: true
      },
      {
        path: '/404',
        component: () => import('@/views/404'),
        hidden: true
      }
    ]
    
    1. 用于权限动态生成的路由页面 asyncRoutes
    //router/index.js
    /**
     * constantRoutes
     * 用于权限动态生成的页面都在这里定义
     */
    export const asyncRoutes = [
      {
        path: '/',
        component: Layout,
        redirect: '/dashboard',
        children: [
          {
            path: 'dashboard',
            name: 'Dashboard',
            component: () => import('@/views/dashboard/index'),
            meta: {
              title: 'Dashboard',
              icon: 'dashboard',
              affix: true,
              noCache: true
            }
          }
        ]
      },
      {
        path: '/chatbot', //法务咨询AI助手
        component: Layout,
        redirect: '/chatbot/index',
        children: [
          {
            path: 'index',
            name: 'ChatBot',
            component: () => import('@/views/chatbot/index'),
            meta: {
              title: 'LegalChatbot'
            }
          }
        ]
      },
      {
        path: '/translation', //法务文档翻译
        component: Layout,
        redirect: '/translation/index',
        children: [
          {
            path: 'index',
            name: 'Translation',
            component: () => import('@/views/translation/index'),
            meta: {
              title: 'Translation'
            }
          }
        ]
      },
      {
        path: '/interpretation', // 法务文档解读
        component: Layout,
        redirect: '/interpretation/index',
        children: [
          {
            path: 'index',
            name: 'Interpretation',
            component: () => import('@/views/interpretation/index'),
            meta: {
              title: 'Interpretation'
            }
          }
        ]
      },
      {
        path: '/document', //合同 AI
        component: Layout,
        redirect: '/document/index',
        meta: {
          title: 'ContractAI'
        },
        children: [
          {
            path: 'index',
            name: 'ContractReview',
            component: () => import('@/views/document/index'),
            meta: {
              title: 'ContractReview'
            }
          },
          {
            path: 'ai-analysis',
            name: 'AiAnalysis',
            component: () => import('@/views/document/ai-analysis'),
            meta: {
              title: 'AiAnalysis'
            },
            hidden: true
          },
          {
            path: 'version-comparison',
            name: 'VersionComparison',
            component: () => import('@/views/document/version-comparison'),
            meta: {
              title: 'VersionComparison'
            }
          },
          {
            path: 'draft-contract',
            name: 'DraftContract',
            component: () => import('@/views/document/draft-contract'),
            meta: {
              title: 'DraftContract'
            }
          },
          {
            path: 'legal-letter',
            name: 'LegalLetter',
            component: () => import('@/views/document/legal-letter'),
            meta: {
              title: 'LegalLetter'
            }
          },
          {
            path: 'ai-analysis-onlyoffice',
            name: 'AiAnalysisOnlyoffice',
            component: () => import('@/views/document/ai-analysis-onlyoffice'),
            meta: {
              title: 'AiAnalysisOnlyoffice'
            }
          },
        ]
      },
      {
        path: '/tradeCompliance',
        component: Layout,
        redirect: '/tradeCompliance/index',
        children: [
          {
            path: 'index',
            name: 'TradeCompliance',
            component: () => import('@/views/tradeCompliance/index'),
            meta: {
              title: 'TradeCompliance'
            }
          }
        ]
      },
      {
        path: '/esg',
        component: Layout,
        redirect: '/esg/index',
        children: [
          {
            path: 'index',
            name: 'ESG',
            component: () => import('@/views/esg/index'),
            meta: {
              title: 'ESG AI'
            }
          }
        ]
      },
      {
        path: '/dataSecurity',
        component: Layout,
        redirect: '/dataSecurity/index',
        children: [
          {
            path: 'index',
            name: 'DataSecurity',
            component: () => import('@/views/dataSecurity/index'),
            meta: {
              title: 'DataSecurity'
            }
          }
        ]
      },
      {
        path: '/litigation',
        component: Layout,
        redirect: '/litigation/doc-drafting',
        name: 'LitigationAI',
        meta: {
          title: 'LitigationAI'
        },
        children: [
          {
            path: 'case-analysis',
            name: 'CaseAnalysis',
            component: () => import('@/views/litigation/case-analysis'),
            meta: {
              title: 'CaseAnalysis'
            }
          },
          {
            path: 'doc-drafting',
            name: 'DocDrafting',
            component: () => import('@/views/litigation/doc-drafting'),
            meta: {
              title: 'DocDrafting'
            }
          },
          {
            path: 'trial-report-summary',
            name: 'TrialReportSummary',
            component: () => import('@/views/litigation/trial-report-summary'),
            meta: {
              title: 'TrialReportSummary'
            }
          },
          {
            path: 'business-execution-strategy',
            name: 'BusinessExecutionStrategy',
            component: () =>
              import('@/views/litigation/business-execution-strategy'),
            meta: {
              title: 'BusinessExecutionStrategy'
            }
          },
          {
            path: 'similar-litigation-prevention',
            name: 'SimilarLitigationPrevention',
            component: () =>
              import('@/views/litigation/similar-litigation-prevention'),
            meta: {
              title: 'SimilarLitigationPrevention'
            }
          },
          {
            path: 'dispute-alternatives',
            name: 'DisputeAlternatives',
            component: () => import('@/views/litigation/dispute-alternatives'),
            meta: {
              title: 'DisputeAlternatives'
            }
          },
          {
            path: 'foreign-lawyer-expert-matching',
            name: 'ForeignLawyerExpertMatching',
            component: () =>
              import('@/views/litigation/foreign-lawyer-expert-matching'),
            meta: {
              title: 'ForeignLawyerExpertMatching'
            }
          }
        ]
      },
      {
        path: '/knowledge',
        component: Layout,
        redirect: '/knowledge/check-rules',
        name: 'Knowledge',
        meta: {
          title: 'AIConfig'
        },
        children: [
          {
            path: 'check-rules',
            name: 'CheckRules',
            component: () => import('@/views/knowledge/check-rules'),
            meta: {
              title: 'ReviewRules'
            }
          },
          {
            path: 'professional-knowledge',
            name: 'ProfessionalKnowledge',
            component: () => import('@/views/knowledge/professional-knowledge'),
            meta: {
              title: 'Knowledge'
            }
          },
          {
            path: 'professional-knowledge2',
            name: 'ProfessionalKnowledge2',
            component: () => import('@/views/knowledge/professional-knowledge'),
            meta: {
              title: 'Knowledge2'
            }
          }
        ]
      },
      {
        path: '/systemsetting',
        component: Layout,
        redirect: '/systemsetting/role-management',
        name: 'SystemSetting',
        meta: {
          title: 'SystemSetting'
        },
        children: [
          {
            path: 'role-management',
            name: 'RoleManagement',
            component: () => import('@/views/systemsetting/role-management'),
            meta: {
              title: 'RoleManagement'
            }
          },
          {
            path: 'log-management',
            name: 'LogManagement',
            component: () => import('@/views/systemsetting/log-management'),
            meta: {
              title: 'LogManagement'
            }
          }
        ]
      },
      // 404 page must be placed at the end !!!
      {
        path: '*',
        redirect: '/404',
        hidden: true
      }
    ]
    

    二 在全局前置守卫通过接口user/getMenus获取用户有权限的路由页面 userRouterList

    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 searchParams = new URLSearchParams(window.location.href)
      // const urlToken = searchParams.get('token')
      // urlToken && setToken(urlToken)
      // searchParams.delete('token')
      const hasToken = getToken()
      if (hasToken) {
        if (to.path === '/login') {
          // if is logged in, redirect to the home page
          next({ path: '/' })
          NProgress.done()
        } else {
          const hasGetUserInfo = store.getters.name
          if (hasGetUserInfo) {
            next()
          } else {
            try {
              // get user info
              await store.dispatch('user/getInfo')
              // 获取权限列表
              store.dispatch('user/getMenus').then(roles => {
                // 根据拿到的权限列表,获取动态路由
                store.dispatch('permission/recursiveRouter', roles).then(res => {
                  // 解决下方第七步中的报错 需要在上方引入该方法 import { resetRouter } from '@/router'
                  resetRouter()
                  // 解决路由name重复警告,如果报Router undefined需要在上面引入import Router from 'vue-router'
                  router.matcher = new Router().matcher
                  // 添加路由
                  router.addRoutes(res)
                })
              })
              next()
            } 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=${window.location.href}`)
              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.
          // await store.dispatch('user/loginByAdfs')
          next(`/login?redirect=${window.location.href}`)
          NProgress.done()
        }
      }
    })
    

    三 通过循环递归 asyncRoutes 和 userRouterList 出符合用户权限的路由表

    const actions = {
      /**
       * 根据用户路由权限递归路由表
       * @param commit
       * @param userRouterList 用户路由权限表
       * @returns {Promise}
       */
      recursiveRouter ({ commit }, userRouterList) {
        return new Promise(resolve => {
          let accessedRoutes = recursiveAsyncRoutes(asyncRoutes, userRouterList)
          commit('SET_ROUTES', accessedRoutes)
          commit('SET_ROUTER_STATE', true)
          resolve(accessedRoutes)
        })
      },
    }
    
    /**
     * 通过循环递归出符合用户权限的路由表
     * @param asyncRouterList
     * @param userRouterList
     * @returns {*[]}
     */
    export function recursiveAsyncRoutes (asyncRouterList, userRouterList) {
      let res = []
      asyncRouterList.forEach(route => {
        const tmp = { ...route }
        if (tmp.path === '*' && !tmp.hasOwnProperty('children')) {
          res.push(tmp)
        } else {
          userRouterList.forEach(uRoute => {
            if (uRoute.menuType != 2) {
              if (hasPath(tmp, uRoute)) {
                if (tmp.children && uRoute.subMenus) {
                  tmp.children = recursiveAsyncRoutes(tmp.children, uRoute.subMenus)
                }
                res.push(tmp)
              }
            }
          })
        }
      })
      return res
    }
    

    四 通过router.addRoutes(res) 把符合用户权限的页面添加到路由中

    五 把最终生成的路由页面(包括 constantRoutes 和第三部中循环遍历出来的符合用户权限的页面)数组保存在store中

    const mutations = {
      /**
       * 设置路由表
       * @param state 数据
       * @param routes 路由
       * @constructor
       */
      SET_ROUTES: (state, routes) => {
        state.addRoutes = routes
        state.routes = constantRoutes.concat(routes)
      }
    }
    

    六 通过store中的路由信息生成导航栏

    <template>
          <el-menu
            :default-active="activeMenu"
            :collapse="isCollapse"
            :background-color="variables.menuBg"
            :text-color="variables.menuText"
            :unique-opened="false"
            :active-text-color="variables.menuActiveText"
            :collapse-transition="false"
            mode="vertical"
            v-if="isShow"
          >
            <sidebar-item
              v-for="route in routes"
              :key="route.path"
              :item="route"
              :base-path="route.path"
            />
          </el-menu>
    </template>
    
    <script>
    export default {
      computed: {
        routes () {
          return this.$store.state.permission.routes
        }
      }
    }
    </script>
    

    参考文献

    相关文章

      网友评论

          本文标题:前端的权限控制

          本文链接:https://www.haomeiwen.com/subject/romzadtx.html