diff --git a/README-zh.md b/README-zh.md
index 03c7735..77766d1 100644
--- a/README-zh.md
+++ b/README-zh.md
@@ -1,5 +1,4 @@
-如果你想要根据用户角色来动态生成侧边栏和 router,你可以使用该分支[permission-control](https://github.com/PanJiaChen/vue-admin-template/tree/permission-control)
## 相关项目
@@ -23,6 +22,7 @@
```bash
+
# 进入项目目录
cd gulu-admin
@@ -64,3 +64,10 @@ npm run lint
npm run lint -- --fix
```
+更多信息请参考 [使用文档](https://panjiachen.github.io/vue-element-admin-site/zh/)
+
+## Demo
+
+![demo](https://github.com/PanJiaChen/PanJiaChen.github.io/blob/master/images/demo.gif)
+
+
diff --git a/README.md b/README.md
index 1e20c74..d5b508e 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,8 @@
+
+## Build Setup
+
+
```bash
# enter the project directory
@@ -61,6 +65,4 @@ For `typescript` version, you can use [vue-typescript-admin-template](https://gi
- [awesome-project](https://github.com/PanJiaChen/vue-element-admin/issues/2312)
-## Browsers support
-Modern browsers and Internet Explorer 10+.
diff --git a/src/layout/components/Sidebar/index.vue b/src/layout/components/Sidebar/index.vue
index da39034..fb014a2 100644
--- a/src/layout/components/Sidebar/index.vue
+++ b/src/layout/components/Sidebar/index.vue
@@ -12,7 +12,7 @@
:collapse-transition="false"
mode="vertical"
>
-
+
@@ -28,11 +28,9 @@ export default {
components: { SidebarItem, Logo },
computed: {
...mapGetters([
+ 'permission_routes',
'sidebar'
]),
- routes() {
- return this.$router.options.routes
- },
activeMenu() {
const route = this.$route
const { meta, path } = route
diff --git a/src/permission.js b/src/permission.js
index fa1ea19..3d08d6b 100644
--- a/src/permission.js
+++ b/src/permission.js
@@ -26,15 +26,25 @@ router.beforeEach(async(to, from, next) => {
next({ path: '/' })
NProgress.done()
} else {
- const hasGetUserInfo = store.getters.name
- if (hasGetUserInfo) {
+ // 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
- await store.dispatch('user/getInfo')
+ // note: roles must be a object array! such as: ['admin'] or ,['developer','editor']
+ const { roles } = await store.dispatch('user/getInfo')
- next()
+ // generate accessible routes map based on roles
+ const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
+
+ // 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')
diff --git a/src/router/index.js b/src/router/index.js
index f091f0f..b572aac 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -88,8 +88,14 @@ export const constantRoutes = [
meta: { title: 'Form', icon: 'form' }
}
]
- },
+ }
+]
+/**
+ * asyncRoutes
+ * the routes that need to be dynamically loaded based on user roles
+ */
+export const asyncRoutes = [
{
path: '/nested',
component: Layout,
diff --git a/src/store/getters.js b/src/store/getters.js
index 5ab7b4c..a108508 100644
--- a/src/store/getters.js
+++ b/src/store/getters.js
@@ -3,6 +3,8 @@ const getters = {
device: state => state.app.device,
token: state => state.user.token,
avatar: state => state.user.avatar,
- name: state => state.user.name
+ name: state => state.user.name,
+ roles: state => state.user.roles,
+ permission_routes: state => state.permission.routes
}
export default getters
diff --git a/src/store/index.js b/src/store/index.js
index 6be466a..6ae5dad 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -2,6 +2,7 @@ import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
import app from './modules/app'
+import permission from './modules/permission'
import settings from './modules/settings'
import user from './modules/user'
@@ -10,6 +11,7 @@ Vue.use(Vuex)
const store = new Vuex.Store({
modules: {
app,
+ permission,
settings,
user
},
diff --git a/src/store/modules/permission.js b/src/store/modules/permission.js
new file mode 100644
index 0000000..aeb5ee5
--- /dev/null
+++ b/src/store/modules/permission.js
@@ -0,0 +1,69 @@
+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) {
+ 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
+}
diff --git a/src/store/modules/user.js b/src/store/modules/user.js
index 8d86b68..3c2a6de 100644
--- a/src/store/modules/user.js
+++ b/src/store/modules/user.js
@@ -6,7 +6,8 @@ const getDefaultState = () => {
return {
token: getToken(),
name: '',
- avatar: ''
+ avatar: '',
+ roles: []
}
}
@@ -24,6 +25,9 @@ const mutations = {
},
SET_AVATAR: (state, avatar) => {
state.avatar = avatar
+ },
+ SET_ROLES: (state, roles) => {
+ state.roles = roles
}
}
@@ -53,8 +57,14 @@ const actions = {
reject('Verification failed, please Login again.')
}
- const { name, avatar } = data
+ const { roles, name, avatar } = data
+
+ // roles must be a non-empty array
+ if (!roles || roles.length <= 0) {
+ reject('getInfo: roles must be a non-null array!')
+ }
+ commit('SET_ROLES', roles)
commit('SET_NAME', name)
commit('SET_AVATAR', avatar)
resolve(data)
diff --git a/src/views/dashboard/index.vue b/src/views/dashboard/index.vue
index 33e5ab6..77ae59a 100644
--- a/src/views/dashboard/index.vue
+++ b/src/views/dashboard/index.vue
@@ -1,6 +1,7 @@
name: {{ name }}
+
roles: {{ role }}
@@ -11,7 +12,8 @@ export default {
name: 'Dashboard',
computed: {
...mapGetters([
- 'name'
+ 'name',
+ 'roles'
])
}
}