mirror of
https://github.com/dataease/dataease.git
synced 2026-05-21 04:08:10 +08:00
feat: 增加权限设置
This commit is contained in:
29
frontend/src/directive/Permission/index.js
Normal file
29
frontend/src/directive/Permission/index.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import store from '@/store'
|
||||
|
||||
function checkPermission(el, binding) {
|
||||
const { value } = binding
|
||||
// 我们是基于资源授鉴权 不用角色 因为后期可能有对部门授权 对 人员授权
|
||||
const permissions = store.getters && store.getters.permissions
|
||||
if (value && value instanceof Array) {
|
||||
const needPermissions = value
|
||||
// 满足指令中的每个权限才可放行 而不是 满足任意一个即可
|
||||
const hasPermission = needPermissions.every(needP => {
|
||||
const result = permissions.includes(needP)
|
||||
return result
|
||||
})
|
||||
if (!hasPermission) {
|
||||
el.parentNode && el.parentNode.removeChild(el)
|
||||
}
|
||||
} else {
|
||||
throw new Error(`使用方式: v-permission="['user:read']"`)
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
inserted(el, binding) {
|
||||
checkPermission(el, binding)
|
||||
},
|
||||
update(el, binding) {
|
||||
checkPermission(el, binding)
|
||||
}
|
||||
}
|
||||
8
frontend/src/directive/index.js
Normal file
8
frontend/src/directive/index.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import permission from '@/directive/Permission'
|
||||
|
||||
export default {
|
||||
install(Vue) {
|
||||
Vue.directive('permission', permission)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,11 +14,12 @@ import router from './router'
|
||||
|
||||
import '@/icons' // icon
|
||||
import '@/permission' // permission control
|
||||
|
||||
import api from '@/api/index.js'
|
||||
import filter from '@/filter/filter'
|
||||
import message from '@/metersphere/common/js/message'
|
||||
import { left2RightDrag, bottom2TopDrag, right2LeftDrag } from '@/metersphere/common/js/directive'
|
||||
import directives from './directive'
|
||||
|
||||
Vue.prototype.$api = api
|
||||
|
||||
import * as echarts from 'echarts'
|
||||
@@ -50,11 +51,13 @@ Vue.use(Fit2CloudUI, {
|
||||
})
|
||||
Vue.use(filter)
|
||||
Vue.use(message)
|
||||
Vue.use(directives)
|
||||
Vue.config.productionTip = false
|
||||
// 支持左右拖拽
|
||||
Vue.directive('left-to-right-drag', left2RightDrag)
|
||||
Vue.directive('right-to-left-drag', right2LeftDrag)
|
||||
Vue.directive('bottom-to-top-drag', bottom2TopDrag)
|
||||
|
||||
new Vue({
|
||||
el: '#app',
|
||||
router,
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
<span class="operate-button">
|
||||
<ms-table-button
|
||||
v-if="showCreate"
|
||||
v-permission="permission.add"
|
||||
:is-tester-permission="isTesterPermission"
|
||||
icon="el-icon-circle-plus-outline"
|
||||
:content="createTip"
|
||||
@@ -67,7 +68,8 @@ export default {
|
||||
default: false
|
||||
},
|
||||
condition: {
|
||||
type: Object
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
createTip: {
|
||||
type: String,
|
||||
@@ -76,7 +78,8 @@ export default {
|
||||
}
|
||||
},
|
||||
runTip: {
|
||||
type: String
|
||||
type: String,
|
||||
default: null
|
||||
|
||||
},
|
||||
|
||||
@@ -85,10 +88,18 @@ export default {
|
||||
default: false
|
||||
},
|
||||
tip: {
|
||||
String,
|
||||
type: String,
|
||||
default() {
|
||||
return this.$t('commons.search_by_name')
|
||||
}
|
||||
},
|
||||
permission: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {
|
||||
add: []
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<span>
|
||||
<slot name="front" />
|
||||
<ms-table-operator-button :is-tester-permission="isTesterPermission" :tip="tip1" icon="el-icon-edit" @exec="editClick" @click.stop="editClickStop" />
|
||||
<ms-table-operator-button v-permission="permission.edit" :is-tester-permission="isTesterPermission" :tip="tip1" icon="el-icon-edit" @exec="editClick" @click.stop="editClickStop" />
|
||||
<slot name="middle" />
|
||||
<ms-table-operator-button :is-tester-permission="isTesterPermission" :tip="tip2" icon="el-icon-delete" type="danger" @exec="deleteClick" @click.stop="deleteClickStop" />
|
||||
<ms-table-operator-button v-permission="permission.del" :is-tester-permission="isTesterPermission" :tip="tip2" icon="el-icon-delete" type="danger" @exec="deleteClick" @click.stop="deleteClickStop" />
|
||||
<slot name="behind" />
|
||||
</span>
|
||||
|
||||
@@ -30,6 +30,16 @@ export default {
|
||||
isTesterPermission: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
permission: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {
|
||||
|
||||
edit: [],
|
||||
del: []
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
@@ -66,7 +66,8 @@ router.beforeEach(async(to, from, next) => {
|
||||
})
|
||||
export const loadMenus = (next, to) => {
|
||||
buildMenus().then(res => {
|
||||
const asyncRouter = filterAsyncRouter(res.data)
|
||||
const filterDatas = filterRouter(res.data)
|
||||
const asyncRouter = filterAsyncRouter(filterDatas)
|
||||
asyncRouter.push({ path: '*', redirect: '/404', hidden: true })
|
||||
store.dispatch('permission/GenerateRoutes', asyncRouter).then(() => { // 存储路由
|
||||
router.addRoutes(asyncRouter)
|
||||
@@ -74,6 +75,30 @@ export const loadMenus = (next, to) => {
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 根据权限过滤菜单
|
||||
const filterRouter = routers => {
|
||||
const user_permissions = store.getters.permissions
|
||||
if (!user_permissions || user_permissions.length === 0) {
|
||||
return routers
|
||||
}
|
||||
const tempResults = routers.filter(router => hasPermission(router, user_permissions))
|
||||
// 如果是一级菜单(目录) 没有字菜单 那就移除
|
||||
return tempResults.filter(item => item.children && item.children.length)
|
||||
}
|
||||
const hasPermission = (router, user_permissions) => {
|
||||
// 菜单要求权限 但是当前用户权限没有包含菜单权限
|
||||
if (router.permission && !user_permissions.includes(router.permission)) {
|
||||
return false
|
||||
}
|
||||
// 如果有字菜单 则 判断是否满足 ‘任意一个子菜单有权限’
|
||||
if (router.children && router.children.length) {
|
||||
const permissionChilds = router.children.filter(item => hasPermission(item, user_permissions))
|
||||
router.children = permissionChilds
|
||||
return router.children.length > 0
|
||||
}
|
||||
return true
|
||||
}
|
||||
router.afterEach(() => {
|
||||
// finish progress bar
|
||||
NProgress.done()
|
||||
|
||||
@@ -16,6 +16,7 @@ const getters = {
|
||||
sceneData: state => state.dataset.sceneData,
|
||||
table: state => state.dataset.table,
|
||||
loadingMap: state => state.request.loadingMap,
|
||||
currentPath: state => state.permission.currentPath
|
||||
currentPath: state => state.permission.currentPath,
|
||||
permissions: state => state.user.permissions
|
||||
}
|
||||
export default getters
|
||||
|
||||
@@ -47,7 +47,7 @@ export const filterAsyncRouter = (routers) => { // 遍历后台传来的路由
|
||||
}).map(router => {
|
||||
router.hasOwnProperty('id') && delete router.id
|
||||
router.hasOwnProperty('pid') && delete router.pid
|
||||
router.hasOwnProperty('children') && !router['children'] && delete router.children
|
||||
router.hasOwnProperty('children') && (!router['children'] || !router['children'].length) && delete router.children
|
||||
router.hasOwnProperty('redirect') && !router['redirect'] && delete router.redirect
|
||||
return router
|
||||
})
|
||||
|
||||
@@ -10,7 +10,9 @@ const getDefaultState = () => {
|
||||
roles: [],
|
||||
avatar: '',
|
||||
// 第一次加载菜单时用到
|
||||
loadMenus: false
|
||||
loadMenus: false,
|
||||
// 当前用户拥有哪些资源权限
|
||||
permissions: []
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +39,9 @@ const mutations = {
|
||||
},
|
||||
SET_LOAD_MENUS: (state, loadMenus) => {
|
||||
state.loadMenus = loadMenus
|
||||
},
|
||||
SET_PERMISSIONS: (state, permissions) => {
|
||||
state.permissions = permissions
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,12 +73,13 @@ const actions = {
|
||||
const currentUser = data
|
||||
commit('SET_USER', currentUser)
|
||||
|
||||
const roles = data.roles
|
||||
const { roles, nickName, permissions } = data
|
||||
commit('SET_ROLES', roles)
|
||||
|
||||
const { nickName } = data
|
||||
commit('SET_NAME', nickName)
|
||||
// commit('SET_AVATAR', avatar)
|
||||
|
||||
commit('SET_PERMISSIONS', permissions)
|
||||
resolve(data)
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
|
||||
@@ -15,6 +15,6 @@ export function isExternal(path) {
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
export function validUsername(str) {
|
||||
const valid_map = ['admin', 'editor']
|
||||
const valid_map = ['admin', 'cyw']
|
||||
return valid_map.indexOf(str.trim()) >= 0
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<el-card class="table-card">
|
||||
<template v-slot:header>
|
||||
<ms-table-header
|
||||
:permission="permission"
|
||||
:condition.sync="condition"
|
||||
:create-tip="$t('organization.create')"
|
||||
:title="$t('commons.organization')"
|
||||
@@ -45,7 +46,7 @@
|
||||
|
||||
<el-table-column :label="$t('commons.operating')">
|
||||
<template v-slot:default="scope">
|
||||
<ms-table-operator @editClick="edit(scope.row)" @deleteClick="handleDelete(scope.row)" />
|
||||
<ms-table-operator :permission="permission" @editClick="edit(scope.row)" @deleteClick="handleDelete(scope.row)" />
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
</el-table>
|
||||
@@ -167,6 +168,11 @@ export default {
|
||||
description: [
|
||||
{ max: 50, message: this.$t('commons.input_limit', [0, 50]), trigger: 'blur' }
|
||||
]
|
||||
},
|
||||
permission: {
|
||||
add: ['dept:add'],
|
||||
edit: ['dept:edit'],
|
||||
del: ['dept:del']
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<el-card class="table-card">
|
||||
<template v-slot:header>
|
||||
<ms-table-header
|
||||
:permission="permission"
|
||||
:condition.sync="condition"
|
||||
:create-tip="$t('menu.create')"
|
||||
:title="$t('commons.menu')"
|
||||
@@ -58,9 +59,9 @@
|
||||
|
||||
<el-table-column :label="$t('commons.operating')">
|
||||
<template v-slot:default="scope">
|
||||
<ms-table-operator @editClick="edit(scope.row)" @deleteClick="handleDelete(scope.row)" />
|
||||
<ms-table-operator :permission="permission" @editClick="edit(scope.row)" @deleteClick="handleDelete(scope.row)" />
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
</el-card>
|
||||
@@ -210,6 +211,11 @@ export default {
|
||||
description: [
|
||||
{ max: 50, message: this.$t('commons.input_limit', [0, 50]), trigger: 'blur' }
|
||||
]
|
||||
},
|
||||
permission: {
|
||||
add: ['menu:add'],
|
||||
edit: ['menu:edit'],
|
||||
del: ['menu:del']
|
||||
}
|
||||
|
||||
}
|
||||
@@ -220,6 +226,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
create() {
|
||||
this.form = Object.assign({}, this.defaultForm)
|
||||
this.dialogVisible = true
|
||||
this.formType = 'add'
|
||||
listenGoBack(this.closeFunc)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<el-aside width="70%" style="border: 1px solid #eee">
|
||||
<el-card class="table-card">
|
||||
<template v-slot:header>
|
||||
<ms-table-header :condition.sync="condition" :create-tip="$t('role.add')" :title="$t('commons.role')" @search="search" @create="create" />
|
||||
<ms-table-header :permission="permission" :condition.sync="condition" :create-tip="$t('role.add')" :title="$t('commons.role')" @search="search" @create="create" />
|
||||
</template>
|
||||
<el-table border highlight-current-row class="adjust-table" :data="tableData" style="width: 100%;" @row-click="rowClick">
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('commons.operating')">
|
||||
<template v-slot:default="scope">
|
||||
<ms-table-operator @editClick="edit(scope.row)" @deleteClick="handleDelete(scope.row)" />
|
||||
<ms-table-operator :permission="permission" @editClick="edit(scope.row)" @deleteClick="handleDelete(scope.row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -121,7 +121,12 @@ export default {
|
||||
{ required: true, message: '请输入名称', trigger: 'blur' }
|
||||
]
|
||||
},
|
||||
currentRow: null
|
||||
currentRow: null,
|
||||
permission: {
|
||||
add: ['role:add'],
|
||||
edit: ['role:edit'],
|
||||
del: ['role:del']
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<el-card class="table-card">
|
||||
<template v-slot:header>
|
||||
<ms-table-header
|
||||
:permission="permission"
|
||||
:condition.sync="condition"
|
||||
:create-tip="$t('user.create')"
|
||||
:title="$t('commons.user')"
|
||||
@@ -38,7 +39,7 @@
|
||||
<!-- <el-table-column prop="source" :label="$t('user.source')"/> -->
|
||||
<el-table-column :label="$t('commons.operating')" min-width="120px">
|
||||
<template v-slot:default="scope">
|
||||
<ms-table-operator @editClick="edit(scope.row)" @deleteClick="del(scope.row)">
|
||||
<ms-table-operator :permission="permission" @editClick="edit(scope.row)" @deleteClick="del(scope.row)">
|
||||
<template v-slot:behind>
|
||||
<ms-table-operator-button
|
||||
v-if="scope.row.isLocalUser"
|
||||
@@ -274,7 +275,12 @@ export default {
|
||||
roles: [],
|
||||
roleDatas: [],
|
||||
userRoles: [],
|
||||
formType: 'add'
|
||||
formType: 'add',
|
||||
permission: {
|
||||
add: ['user:add'],
|
||||
edit: ['user:edit'],
|
||||
del: ['user:del']
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
{{ scope.row.title }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="Author" width="110" align="center">
|
||||
<el-table-column v-permission="['menu:del']" label="Author" width="110" align="center">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ scope.row.author }}</span>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user