瀏覽代碼

开发后台侧边栏动态路由

reghao 3 月之前
父節點
當前提交
b7b3ea0518

+ 3 - 2
src/assets/js/mixin.js

@@ -5,6 +5,7 @@ import { getPubkey, getCaptchaCode, getVerifyCode, login, logout, register, forg
 import { setUserToken, removeAll } from '@/utils/auth'
 import { JSEncrypt } from 'jsencrypt'
 import Vue from 'vue'
+import store from '@/store'
 
 export const userMixin = {
   data() {
@@ -182,7 +183,7 @@ export const userMixin = {
           const userToken = respData.accountToken
           // 保存授权信息到本地缓存
           setUserToken(userToken)
-          this.$store.commit('UPDATE_USER_INFO', userInfo)
+          store.commit('SET_USER_INFO', userInfo)
 
           // 刷新当前页面
           // this.$router.go(0)
@@ -300,7 +301,7 @@ export const userMixin = {
         logout().then(resp => {
           if (resp.code === 0) {
             Vue.$cookies.remove('token')
-            this.$store.commit('USER_LOGOUT')
+            store.commit('USER_LOGOUT')
             removeAll()
           } else {
             this.$notify.error({

+ 16 - 1
src/permission.js

@@ -1,14 +1,29 @@
 import router from './router'
 import { getAccessToken, removeAll } from '@/utils/auth'
+import store from '@/store'
 
 router.beforeEach((to, from, next) => {
+  // document.title = to.meta.title
   const needAuth = to.meta.needAuth
   const token = getAccessToken()
   if (token != null) {
     if (to.path === '/login' || to.path === '/register') {
       next({ path: '/' })
     } else {
-      next()
+      const hasRoles = store.getters.roles.length > 0
+      if (hasRoles) {
+        next()
+      } else {
+        const roles = store.dispatch('getUserRoles')
+        const accessRoutes = store.dispatch('generateRoutes', roles)
+        accessRoutes.then(allRoutes => {
+          console.log(allRoutes)
+          router.addRoutes(allRoutes)
+        })
+        /* getRoutes(router).then(r => {
+          next({ ...to, replace: true })
+        })*/
+      }
     }
   } else {
     removeAll()

+ 18 - 24
src/router/background_devops.js

@@ -34,37 +34,31 @@ export default {
   path: '/bg',
   name: 'Background',
   component: Background,
-  meta: { needAuth: true },
+  meta: { needAuth: true, roles: ['admin'] },
   children: [
-    {
-      path: '',
-      name: 'Dashboard',
-      component: Dashboard,
-      meta: { needAuth: true }
-    },
     {
       path: '/bg/user',
       name: 'UserProfile',
       component: { render: (e) => e('router-view') },
-      meta: { needAuth: true },
+      meta: { needAuth: true, roles: ['user'] },
       children: [
         {
           path: '/bg/user/profile',
           name: 'UserProfile',
           component: UserProfile,
-          meta: { needAuth: true }
+          meta: { needAuth: true, roles: ['user'] }
         },
         {
           path: '/bg/user/record',
           name: 'UserLogin',
           component: UserLogin,
-          meta: { needAuth: true }
+          meta: { needAuth: true, roles: ['user'] }
         },
         {
           path: '/bg/user/message',
           name: 'UserMessage',
           component: UserMessage,
-          meta: { needAuth: true }
+          meta: { needAuth: true, roles: ['user'] }
         }
       ]
     },
@@ -72,7 +66,7 @@ export default {
       path: '/bg/machine',
       name: 'MachineHost',
       component: { render: (e) => e('router-view') },
-      meta: { needAuth: true },
+      meta: { needAuth: true, roles: ['admin'] },
       children: [
         {
           path: '/bg/machine/host',
@@ -92,37 +86,37 @@ export default {
       path: '/bg/build',
       name: 'BuildDir',
       component: { render: (e) => e('router-view') },
-      meta: { needAuth: true },
+      meta: { needAuth: true, roles: ['admin'] },
       children: [
         {
           path: '/bg/build/dir',
           name: 'BuildDir',
           component: BuildDir,
-          meta: { needAuth: true }
+          meta: { needAuth: true, roles: ['admin'] }
         },
         {
           path: '/bg/build/repo_auth',
           name: 'RepoAuth',
           component: RepoAuth,
-          meta: { needAuth: true }
+          meta: { needAuth: true, roles: ['admin'] }
         },
         {
           path: '/bg/build/compiler',
           name: 'Compiler',
           component: Compiler,
-          meta: { needAuth: true }
+          meta: { needAuth: true, roles: ['admin'] }
         },
         {
           path: '/bg/build/docker_registry',
           name: 'DockerRegistry',
           component: DockerRegistry,
-          meta: { needAuth: true }
+          meta: { needAuth: true, roles: ['admin'] }
         },
         {
           path: '/bg/build/packer',
           name: 'Packer',
           component: Packer,
-          meta: { needAuth: true }
+          meta: { needAuth: true, roles: ['admin'] }
         }
       ]
     },
@@ -130,25 +124,25 @@ export default {
       path: '/bg/app',
       name: 'AppConfig',
       component: { render: (e) => e('router-view') },
-      meta: { needAuth: true },
+      meta: { needAuth: true, roles: ['admin'] },
       children: [
         {
           path: '/bg/app/config',
           name: 'AppConfig',
           component: AppConfig,
-          meta: { needAuth: true }
+          meta: { needAuth: true, roles: ['admin'] }
         },
         {
           path: '/bg/app/bd',
           name: 'BuildDeploy',
           component: BuildDeploy,
-          meta: { needAuth: true }
+          meta: { needAuth: true, roles: ['admin'] }
         },
         {
           path: '/bg/app/stat',
           name: 'AppStat',
           component: AppStat,
-          meta: { needAuth: true }
+          meta: { needAuth: true, roles: ['admin'] }
         }
       ]
     },
@@ -156,7 +150,7 @@ export default {
       path: '/bg/sys',
       name: 'SiteConfig',
       component: { render: (e) => e('router-view') },
-      meta: { needAuth: true },
+      meta: { needAuth: true, roles: ['admin'] },
       children: [
         {
           path: '/bg/sys/site',
@@ -194,7 +188,7 @@ export default {
       path: '/bg/rbac',
       name: 'RBAC',
       component: { render: (e) => e('router-view') },
-      meta: { needAuth: true },
+      meta: { needAuth: true, roles: ['admin'] },
       children: [
         {
           path: '/bg/rbac/menu',

+ 14 - 2
src/router/index.js

@@ -24,6 +24,7 @@ const Register = () => import('views/Register')
 const Forgot = () => import('views/Forgot')
 const Index = () => import('views/Index')
 const Background = () => import('views/admin/Background')
+const Dashboard = () => import('views/devops/Dashboard')
 
 // ********************************************************************************************************************
 // 使用安装路由插件
@@ -34,7 +35,6 @@ export const constantRoutes = [
   SearchRouter,
   BlogRouter,
   VodRouter,
-  BackgroundDevopsRouter,
   BackgroundAccountRouter,
   BackgroundMyRouter,
   BackgroundPostRouter,
@@ -54,7 +54,15 @@ export const constantRoutes = [
     path: '/bg',
     name: 'Background',
     component: Background,
-    meta: { needAuth: false }
+    meta: { needAuth: false },
+    children: [
+      {
+        path: '',
+        name: 'Dashboard',
+        component: Dashboard,
+        meta: { needAuth: true, roles: ['admin'] }
+      }
+    ]
   },
   {
     path: '/login',
@@ -82,6 +90,10 @@ export const constantRoutes = [
   }
 ]
 
+export const asyncRoutes = [
+  BackgroundDevopsRouter
+]
+
 // 创建路由对象并导出
 export default new VueRouter({
   mode: 'history',

+ 0 - 8
src/store/getters.js

@@ -1,8 +0,0 @@
-const getters = {
-  // 用户登入状态
-  uid: state => state.user.uid,
-  // websocket 连接状态
-  socketStatus: state => state.socketStatus
-}
-
-export default getters

+ 86 - 96
src/store/index.js

@@ -1,111 +1,101 @@
 import Vuex from 'vuex'
 import Vue from 'vue'
 
-import user from './modules/user'
-import chat from './modules/talk'
-import getters from './getters'
-import state from './state'
-import mutations from './mutations'
+import { asyncRoutes, constantRoutes } from '@/router'
+import { getAuthedUser, setAuthedUser } from '@/utils/auth'
 
 Vue.use(Vuex)
 const store = new Vuex.Store({
-  modules: {
-    user,
-    chat
+  /* modules: {
+    user
+  },*/
+  getters: {
+    // 用户登入状态
+    roles: state => state.roles,
+    // websocket 连接状态
+    socketStatus: state => state.socketStatus
+  },
+  state: {
+    userInfo: null,
+    roles: [],
+    routes: [],
+    addRoutes: [],
+    socketStatus: 'Offline'
+  },
+  mutations: {
+    SET_ROUTES: (state, routes) => {
+      state.addRoutes = routes
+      state.routes = constantRoutes.concat(routes) // 组合路由,将原始路由和权限路由组合生成路由表
+    },
+    // 更新socket 连接状态
+    UPDATE_SOCKET_STATUS(state, status) {
+      state.socketStatus = status
+    },
+    // 更新用户信息
+    SET_USER_INFO(state, userInfo) {
+      // 保存用户信息到缓存
+      setAuthedUser(userInfo)
+      state.userInfo = userInfo
+      // state.roles = userInfo.roles
+    },
+    SET_ROLES(state, roles) {
+      state.roles = roles
+    },
+    // 用户退出登入
+    USER_LOGOUT(state) {
+      state.userInfo = null
+      state.roles = []
+    }
   },
-  getters,
-  state,
-  mutations,
   // 异步操作
   actions: {
-    getPageBean(context) {
-      /* getPageBean(context.state.cid, context.state.activePage, 6).then(res => {
-        context.commit('getPageBean', res)
-      })*/
+    // 这里就是获取 权限路由 参数roles即是用户信息中返回的roles
+    generateRoutes({ commit }, roles) {
+      return new Promise(resolve => {
+        roles.then(roles => {
+          const accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
+          // 更改state
+          commit('SET_ROUTES', accessedRoutes)
+          resolve(accessedRoutes) // 返回 生成的权限路由表
+        })
+      })
     },
-    getPageBeanByValue(context) {
-      const res = {
-        totalCount: 10,
-        list: [
-          {
-            vname: '哈1',
-            coverurl: 'https://picx.zhimg.com/v2-ea15e9203a1d95a465a78da043a9315d_xl.jpg',
-            releasetime: '2023-04-24 16:47:00',
-            visited: 10,
-            keyword: '芒果,草莓,西瓜'
-          },
-          {
-            vname: '哈2',
-            coverurl: 'https://picx.zhimg.com/v2-ea15e9203a1d95a465a78da043a9315d_xl.jpg',
-            releasetime: '2023-04-24 16:47:00',
-            visited: 10,
-            keyword: '芒果,草莓,西瓜'
-          },
-          {
-            vname: '哈3',
-            coverurl: 'https://picx.zhimg.com/v2-ea15e9203a1d95a465a78da043a9315d_xl.jpg',
-            releasetime: '2023-04-24 16:47:00',
-            visited: 10,
-            keyword: '芒果,草莓,西瓜'
-          },
-          {
-            vname: '哈4',
-            coverurl: 'https://picx.zhimg.com/v2-ea15e9203a1d95a465a78da043a9315d_xl.jpg',
-            releasetime: '2023-04-24 16:47:00',
-            visited: 10,
-            keyword: '芒果,草莓,西瓜'
-          },
-          {
-            vname: '哈5',
-            coverurl: 'https://picx.zhimg.com/v2-ea15e9203a1d95a465a78da043a9315d_xl.jpg',
-            releasetime: '2023-04-24 16:47:00',
-            visited: 10,
-            keyword: '芒果,草莓,西瓜'
-          },
-          {
-            vname: '哈1',
-            coverurl: 'https://picx.zhimg.com/v2-ea15e9203a1d95a465a78da043a9315d_xl.jpg',
-            releasetime: '2023-04-24 16:47:00',
-            visited: 10,
-            keyword: '芒果,草莓,西瓜'
-          },
-          {
-            vname: '哈2',
-            coverurl: 'https://picx.zhimg.com/v2-ea15e9203a1d95a465a78da043a9315d_xl.jpg',
-            releasetime: '2023-04-24 16:47:00',
-            visited: 10,
-            keyword: '芒果,草莓,西瓜'
-          },
-          {
-            vname: '哈3',
-            coverurl: 'https://picx.zhimg.com/v2-ea15e9203a1d95a465a78da043a9315d_xl.jpg',
-            releasetime: '2023-04-24 16:47:00',
-            visited: 10,
-            keyword: '芒果,草莓,西瓜'
-          },
-          {
-            vname: '哈4',
-            coverurl: 'https://picx.zhimg.com/v2-ea15e9203a1d95a465a78da043a9315d_xl.jpg',
-            releasetime: '2023-04-24 16:47:00',
-            visited: 10,
-            keyword: '芒果,草莓,西瓜'
-          },
-          {
-            vname: '哈5',
-            coverurl: 'https://picx.zhimg.com/v2-ea15e9203a1d95a465a78da043a9315d_xl.jpg',
-            releasetime: '2023-04-24 16:47:00',
-            visited: 10,
-            keyword: '芒果,草莓,西瓜'
-          }
-        ]
-      }
-      context.commit('getPageBean', res)
-      /* getPageBeanByValue(context.state.value, context.state.activePage, 8).then(res => {
-        console.log(res)
-        context.commit('getPageBean', res)
-      })*/
+    getUserRoles({ commit }) {
+      /* const { roles, userId, avatarUrl, username } = getAuthedUser()
+      commit('SET_ROLES', roles)
+      return roles*/
+      return new Promise((resolve, reject) => {
+        const { roles, userId, avatarUrl, username } = getAuthedUser()
+        commit('SET_ROLES', roles)
+        resolve(roles)
+      })
     }
   }
 })
 
+function hasPermission(roles, route) {
+  if (route.meta && route.meta.roles) {
+    return roles.some(role => route.meta.roles.includes(role))
+  } else {
+    return true
+  }
+}
+
+// 判断在 meta 中定义的 roles 是否包含用户角色返回的 roles
+function filterAsyncRoutes(routes, roles) {
+  const res = []
+  // 循环定义的asyncRoutes权限的路由表
+  for (const route of routes) {
+    const tmp = { ...route }
+    if (hasPermission(roles, tmp)) {
+      if (tmp.children) { // 如果有子项 进行递归过滤
+        tmp.children = filterAsyncRoutes(tmp.children, roles)
+      }
+      // 如果定义的mate中roles包含用户roles中的某一项 则添加到res中
+      res.push(tmp)
+    }
+  }
+  return res
+}
+
 export default store

+ 0 - 86
src/store/modules/talk.js

@@ -1,86 +0,0 @@
-const Talk = {
-  state: {
-    // 会话列表
-    items: []
-  },
-  getters: {
-    talkItems: state => {
-      return state.items
-    },
-    talkNum: state => state.items.length
-  },
-  mutations: {
-    // 新增对话节点
-    PUSH_TALK_ITEM(state, resource) {
-      state.items.push(resource)
-    },
-    // 移除对话节点
-    REMOVE_TALK_ITEM(state) {
-      state.items = []
-    },
-    SET_LOAD_STATUS(state, resource) {
-      state.loadStatus = resource
-    },
-    // 设置对话列表
-    SET_TALK_ITEMS(state, resource) {
-      state.items = resource.items
-    },
-    // 更新对话节点
-    UPDATE_TALK_ITEM(state, resource) {
-      for (const iterator of state.items) {
-        if (iterator.indexName === resource.indexName) {
-          Object.assign(iterator, resource)
-          break
-        }
-      }
-    },
-    // 更新对话消息
-    UPDATE_TALK_MESSAGE(state, resource) {
-      for (const iterator of state.items) {
-        if (iterator.indexName !== resource.indexName) {
-          continue
-        }
-
-        iterator.unreadNum++
-        iterator.msgText = resource.msgText
-        iterator.updatedAt = resource.updatedAt
-        break
-      }
-    },
-
-    SET_TLAK_UNREAD_MESSAGE(state, resource) {
-      state.unreadMessage.num++
-      state.unreadMessage.nickname = resource.nickname
-      state.unreadMessage.content = resource.content
-    },
-
-    // 清除最后一条未读消息
-    CLEAR_TLAK_UNREAD_MESSAGE(state) {
-      state.unreadMessage = {
-        num: 0,
-        nickname: '未知',
-        content: '...'
-      }
-    }
-  },
-  actions: {
-    // 加载会话列表
-    LOAD_TALK_ITEMS(context) {
-      context.commit('SET_LOAD_STATUS', 2)
-      /* ServeGetTalkList().then(({ code, data }) => {
-          if (code !== 0) return
-
-          context.commit('SET_TALK_ITEMS', {
-            items: data.map(item => formateTalkItem(item)),
-          })
-
-          context.commit('SET_LOAD_STATUS', 3)
-        })
-        .catch(() => {
-          context.commit('SET_LOAD_STATUS', 4)
-        })*/
-    }
-  }
-}
-
-export default Talk

+ 0 - 40
src/store/modules/user.js

@@ -1,40 +0,0 @@
-import { setAuthedUser, getAuthedUser, getAccessToken } from '@/utils/auth'
-
-const state = {
-  userId: 0,
-  username: null,
-  avatarUrl: null
-}
-
-// 判断用户是否登入
-if (getAccessToken()) {
-  const userInfo = getAuthedUser()
-  state.userId = userInfo.uid
-  state.username = userInfo.screenName
-  state.avatarUrl = userInfo.avatarUrl ? userInfo.avatarUrl : state.avatarUrl
-}
-
-const User = {
-  state,
-  mutations: {
-    // 更新用户信息
-    UPDATE_USER_INFO(state, userInfo) {
-      // 保存用户信息到缓存
-      setAuthedUser(userInfo)
-    },
-    // 用户退出登入
-    USER_LOGOUT(state) {
-      state.userId = 0
-      state.username = null
-      state.avatarUrl = null
-    }
-  },
-  actions: {
-    // 退出登入处理操作
-    USER_LOGOUT_ACTION({ commit }) {
-      commit('USER_LOGOUT')
-    }
-  }
-}
-
-export default User

+ 0 - 29
src/store/mutations.js

@@ -1,29 +0,0 @@
-// 根级别的 mutation
-const mutations = {
-  // 更新socket 连接状态
-  UPDATE_SOCKET_STATUS(state, status) {
-    state.socketStatus = status
-  },
-  // 获取分页视频
-  getPageBean(state, pageBean) {
-    state.pageBean = pageBean
-  },
-  // 存入cid
-  saveCid(state, cid) {
-    state.cid = cid
-  },
-  // 存入value
-  saveValue(state, value) {
-    state.value = value
-  },
-  // 存入playerVideo
-  savePlayerVideo(state, palyerVideo) {
-    state.playerVideo = palyerVideo
-  },
-  // 改变页数
-  updatePage(state, newPage) {
-    state.activePage = newPage
-  }
-}
-
-export default mutations

+ 0 - 10
src/store/state.js

@@ -1,10 +0,0 @@
-// 根级别的 state
-const state = {
-  socketStatus: 'Offline',
-  pageBean: Object,
-  activePage: 1,
-  cid: 1,
-  value: String // 搜索框的value
-}
-
-export default state

+ 7 - 0
src/views/admin/LeftAside.vue

@@ -31,6 +31,8 @@
 </template>
 
 <script>
+import { mapState } from 'vuex'
+
 export default {
   name: 'LeftAside',
   data() {
@@ -41,6 +43,11 @@ export default {
       devops: true
     }
   },
+  computed: {
+    ...mapState({
+      routers: 'routes'
+    })
+  },
   mounted() {
     this.initSideMenu()
   },

+ 15 - 0
src/views/devops/Dashboard.vue

@@ -104,6 +104,7 @@
 </template>
 
 <script>
+import store from '@/store'
 import { getDashboard } from '@/api/devops'
 
 export default {
@@ -118,8 +119,22 @@ export default {
   created() {
     document.title = 'Dashboard'
     this.getData()
+    // this.getUserInfo()
   },
   methods: {
+    async getUserInfo() {
+      const hasRoles = store.getters.roles.length > 0
+      if (hasRoles) {
+        console.log('get roles')
+      } else {
+        console.log('no roles')
+      }
+
+      const { roles } = await store.dispatch('getUserInfo')
+      const accessRoutes = await store.dispatch('generateRoutes', roles)
+      console.log(roles)
+      console.log(accessRoutes)
+    },
     getData() {
       if (this.devops) {
         this.getDevopsDashboard()