Skip to content

Commit b44335f

Browse files
committed
feature[Permission]: add role permission management page (#1605)
1 parent f175427 commit b44335f

File tree

14 files changed

+467
-46
lines changed

14 files changed

+467
-46
lines changed

mock/mocks.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ import login from './login'
22
import article from './article'
33
import search from './remoteSearch'
44
import transaction from './transaction'
5+
import role from './role'
56

67
export default {
78
...login,
89
...article,
910
...search,
10-
...transaction
11+
...transaction,
12+
...role
1113
}
1214

mock/role/index.js

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import Mock from 'mockjs'
2+
// import { deepClone } from '@/utils'
3+
// import { filterAsyncRoutes } from '@/store/modules/permission'
4+
// import { asyncRoutes, constantRoutes } from '@/router'
5+
6+
// const routes = deepClone([...constantRoutes, ...asyncRoutes])
7+
8+
const roles = [
9+
{
10+
key: 'admin',
11+
name: 'admin',
12+
description: 'Super Administrator. Have access to view all pages.',
13+
routes: []
14+
},
15+
{
16+
key: 'editor',
17+
name: 'editor',
18+
description: 'Normal Editor. Can see all pages except permission page',
19+
routes: []
20+
},
21+
{
22+
key: 'visitor',
23+
name: 'visitor',
24+
description: 'Just a visitor. Can only see the home page and the document page',
25+
routes: [{
26+
path: '',
27+
redirect: 'dashboard',
28+
children: [
29+
{
30+
path: 'dashboard',
31+
name: 'Dashboard',
32+
meta: { title: 'dashboard', icon: 'dashboard' }
33+
}
34+
]
35+
}]
36+
}
37+
]
38+
39+
export default {
40+
'/routes': () => {
41+
return []
42+
},
43+
'/roles': () => {
44+
return roles
45+
},
46+
'/roles/add': () => {
47+
return Mock.mock('@integer(300, 5000)')
48+
},
49+
'/roles/update/\/[A-Za-z0-9]': () => {
50+
const res = {
51+
data: 'success'
52+
}
53+
return res
54+
},
55+
'/roles/delete/\/[A-Za-z0-9]'() {
56+
const res = {
57+
data: 'success'
58+
}
59+
return res
60+
}
61+
}

src/api/role.js

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import request from '@/utils/request'
2+
3+
export function getRoutes() {
4+
return request({
5+
url: '/routes',
6+
method: 'get'
7+
})
8+
}
9+
10+
export function getRoles() {
11+
return request({
12+
url: '/roles',
13+
method: 'get'
14+
})
15+
}
16+
17+
export function addRole(data) {
18+
return request({
19+
url: '/roles/add',
20+
method: 'post',
21+
data
22+
})
23+
}
24+
25+
export function updateRole(id, data) {
26+
return request({
27+
url: `/roles/update/${id}`,
28+
method: 'put',
29+
data
30+
})
31+
}
32+
33+
export function deleteRole(id) {
34+
return request({
35+
url: `/roles/delete/${id}`,
36+
method: 'delete'
37+
})
38+
}

src/components/HeaderSearch/index.vue

+12-12
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,19 @@ export default {
3636
}
3737
},
3838
computed: {
39-
routers() {
40-
return this.$store.getters.permission_routers
39+
routes() {
40+
return this.$store.getters.permission_routes
4141
},
4242
lang() {
4343
return this.$store.getters.language
4444
}
4545
},
4646
watch: {
4747
lang() {
48-
this.searchPool = this.generateRouters(this.routers)
48+
this.searchPool = this.generateRoutes(this.routes)
4949
},
50-
routers() {
51-
this.searchPool = this.generateRouters(this.routers)
50+
routes() {
51+
this.searchPool = this.generateRoutes(this.routes)
5252
},
5353
searchPool(list) {
5454
this.initFuse(list)
@@ -62,7 +62,7 @@ export default {
6262
}
6363
},
6464
mounted() {
65-
this.searchPool = this.generateRouters(this.routers)
65+
this.searchPool = this.generateRoutes(this.routes)
6666
},
6767
methods: {
6868
click() {
@@ -103,10 +103,10 @@ export default {
103103
},
104104
// Filter out the routes that can be displayed in the sidebar
105105
// And generate the internationalized title
106-
generateRouters(routers, basePath = '/', prefixTitle = []) {
106+
generateRoutes(routes, basePath = '/', prefixTitle = []) {
107107
let res = []
108108
109-
for (const router of routers) {
109+
for (const router of routes) {
110110
// skip hidden router
111111
if (router.hidden) { continue }
112112
@@ -128,11 +128,11 @@ export default {
128128
}
129129
}
130130
131-
// recursive child routers
131+
// recursive child routes
132132
if (router.children) {
133-
const tempRouters = this.generateRouters(router.children, data.path, data.title)
134-
if (tempRouters.length >= 1) {
135-
res = [...res, ...tempRouters]
133+
const tempRoutes = this.generateRoutes(router.children, data.path, data.title)
134+
if (tempRoutes.length >= 1) {
135+
res = [...res, ...tempRoutes]
136136
}
137137
}
138138
}

src/lang/en.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export default {
66
guide: 'Guide',
77
permission: 'Permission',
88
pagePermission: 'Page Permission',
9+
rolePermission: 'Role Permission',
910
directivePermission: 'Directive Permission',
1011
icons: 'Icons',
1112
components: 'Components',
@@ -86,9 +87,14 @@ export default {
8687
github: 'Github Repository'
8788
},
8889
permission: {
90+
addRole: 'New Role',
91+
editPermission: 'Edit Permission',
8992
roles: 'Your roles',
9093
switchRoles: 'Switch roles',
91-
tips: 'In some cases it is not suitable to use v-permission, such as element Tab component or el-table-column and other asynchronous rendering dom cases which can only be achieved by manually setting the v-if.'
94+
tips: 'In some cases it is not suitable to use v-permission, such as element Tab component or el-table-column and other asynchronous rendering dom cases which can only be achieved by manually setting the v-if.',
95+
delete: 'Delete',
96+
confirm: 'Confirm',
97+
cancel: 'Cancel'
9298
},
9399
guide: {
94100
description: 'The guide page is useful for some people who entered the project for the first time. You can briefly introduce the features of the project. Demo is based on ',

src/lang/es.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export default {
55
documentation: 'Documentación',
66
guide: 'Guía',
77
permission: 'Permisos',
8+
rolePermission: 'Permisos de rol',
89
pagePermission: 'Permisos de la página',
910
directivePermission: 'Permisos de la directiva',
1011
icons: 'Iconos',
@@ -86,9 +87,14 @@ export default {
8687
github: 'Repositorio Github'
8788
},
8889
permission: {
90+
addRole: 'Nuevo rol',
91+
editPermission: 'Permiso de edición',
8992
roles: 'Tus permisos',
9093
switchRoles: 'Cambiar permisos',
91-
tips: 'In some cases it is not suitable to use v-permission, such as element Tab component or el-table-column and other asynchronous rendering dom cases which can only be achieved by manually setting the v-if.'
94+
tips: 'In some cases it is not suitable to use v-permission, such as element Tab component or el-table-column and other asynchronous rendering dom cases which can only be achieved by manually setting the v-if.',
95+
delete: 'Borrar',
96+
confirm: 'Confirmar',
97+
cancel: 'Cancelar'
9298
},
9399
guide: {
94100
description: 'The guide page is useful for some people who entered the project for the first time. You can briefly introduce the features of the project. Demo is based on ',

src/lang/zh.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export default {
55
documentation: '文档',
66
guide: '引导页',
77
permission: '权限测试页',
8+
rolePermission: '角色权限',
89
pagePermission: '页面权限',
910
directivePermission: '指令权限',
1011
icons: '图标',
@@ -86,9 +87,14 @@ export default {
8687
github: 'Github 地址'
8788
},
8889
permission: {
90+
addRole: '新增角色',
91+
editPermission: '编辑权限',
8992
roles: '你的权限',
9093
switchRoles: '切换权限',
91-
tips: '在某些情况下,不适合使用 v-permission。例如:Element-UI 的 Tab 组件或 el-table-column 以及其它动态渲染 dom 的场景。你只能通过手动设置 v-if 来实现。'
94+
tips: '在某些情况下,不适合使用 v-permission。例如:Element-UI 的 Tab 组件或 el-table-column 以及其它动态渲染 dom 的场景。你只能通过手动设置 v-if 来实现。',
95+
delete: '删除',
96+
confirm: '确定',
97+
cancel: '取消'
9298
},
9399
guide: {
94100
description: '引导页对于一些第一次进入项目的人很有用,你可以简单介绍下项目的功能。本 Demo 是基于',

src/layout/components/Sidebar/index.vue

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
:collapse-transition="false"
1010
mode="vertical"
1111
>
12-
<sidebar-item v-for="route in permission_routers" :key="route.path" :item="route" :base-path="route.path" />
12+
<sidebar-item v-for="route in permission_routes" :key="route.path" :item="route" :base-path="route.path" />
1313
</el-menu>
1414
</el-scrollbar>
1515
</template>
@@ -23,7 +23,7 @@ export default {
2323
components: { SidebarItem },
2424
computed: {
2525
...mapGetters([
26-
'permission_routers',
26+
'permission_routes',
2727
'sidebar'
2828
]),
2929
variables() {

src/layout/components/TagsView/index.vue

+3-3
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ export default {
5454
visitedViews() {
5555
return this.$store.state.tagsView.visitedViews
5656
},
57-
routers() {
58-
return this.$store.state.permission.routers
57+
routes() {
58+
return this.$store.state.permission.routes
5959
}
6060
},
6161
watch: {
@@ -102,7 +102,7 @@ export default {
102102
return tags
103103
},
104104
initTags() {
105-
const affixTags = this.affixTags = this.filterAffixTags(this.routers)
105+
const affixTags = this.affixTags = this.filterAffixTags(this.routes)
106106
for (const tag of affixTags) {
107107
// Must have tag name
108108
if (tag.name) {

src/permission.js

+27-18
Original file line numberDiff line numberDiff line change
@@ -2,41 +2,49 @@ import router from './router'
22
import store from './store'
33
import { Message } from 'element-ui'
44
import NProgress from 'nprogress' // progress bar
5-
import 'nprogress/nprogress.css'// progress bar style
6-
import { getToken } from '@/utils/auth' // getToken from cookie
5+
import 'nprogress/nprogress.css' // progress bar style
6+
import { getToken } from '@/utils/auth' // get token from cookie
77

8-
NProgress.configure({ showSpinner: false })// NProgress Configuration
8+
NProgress.configure({ showSpinner: false }) // NProgress Configuration
99

1010
// permission judge function
1111
function hasPermission(roles, permissionRoles) {
12-
if (roles.indexOf('admin') >= 0) return true // admin permission passed directly
12+
if (roles.includes('admin')) return true // admin permission passed directly
1313
if (!permissionRoles) return true
1414
return roles.some(role => permissionRoles.indexOf(role) >= 0)
1515
}
1616

17-
const whiteList = ['/login', '/auth-redirect']// no redirect whitelist
17+
const whiteList = ['/login', '/auth-redirect'] // no redirect whitelist
1818

1919
router.beforeEach((to, from, next) => {
2020
NProgress.start() // start progress bar
21-
if (getToken()) { // determine if there has token
21+
if (getToken()) {
22+
// determine if there has token
23+
2224
/* has token*/
2325
if (to.path === '/login') {
2426
next({ path: '/' })
2527
NProgress.done() // if current page is dashboard will not trigger afterEach hook, so manually handle it
2628
} else {
27-
if (store.getters.roles.length === 0) { // 判断当前用户是否已拉取完user_info信息
28-
store.dispatch('GetUserInfo').then(res => { // 拉取user_info
29-
const roles = res.data.roles // note: roles must be a array! such as: ['editor','develop']
30-
store.dispatch('GenerateRoutes', { roles }).then(() => { // 根据roles权限生成可访问的路由表
31-
router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表
32-
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
29+
if (store.getters.roles.length === 0) {
30+
// 判断当前用户是否已拉取完user_info信息
31+
store
32+
.dispatch('GetUserInfo')
33+
.then(res => {
34+
// 拉取user_info
35+
const roles = res.data.roles // note: roles must be a object array! such as: [{id: '1', name: 'editor'}, {id: '2', name: 'developer'}]
36+
store.dispatch('GenerateRoutes', { roles }).then(accessRoutes => {
37+
// 根据roles权限生成可访问的路由表
38+
router.addRoutes(accessRoutes) // 动态添加可访问路由表
39+
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
40+
})
3341
})
34-
}).catch((err) => {
35-
store.dispatch('FedLogOut').then(() => {
36-
Message.error(err)
37-
next({ path: '/' })
42+
.catch(err => {
43+
store.dispatch('FedLogOut').then(() => {
44+
Message.error(err)
45+
next({ path: '/' })
46+
})
3847
})
39-
})
4048
} else {
4149
// 没有动态改变权限的需求可直接next() 删除下方权限判断 ↓
4250
if (hasPermission(store.getters.roles, to.meta.roles)) {
@@ -49,7 +57,8 @@ router.beforeEach((to, from, next) => {
4957
}
5058
} else {
5159
/* has no token*/
52-
if (whiteList.indexOf(to.path) !== -1) { // 在免登录白名单,直接进入
60+
if (whiteList.indexOf(to.path) !== -1) {
61+
// 在免登录白名单,直接进入
5362
next()
5463
} else {
5564
next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页

0 commit comments

Comments
 (0)