这是基于vue-vben-admin 模板适用于abp Vnext的前端管理项目
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

473 lines
12 KiB

<template>
<el-dialog
v-el-draggable-dialog
width="800px"
:visible="showDialog"
:title="$t('AbpPermissionManagement.Permissions') + '-' + entityDisplayName"
custom-class="modal-form"
:close-on-click-modal="false"
:close-on-press-escape="false"
:show-close="false"
@close="onFormClosed"
>
<el-form>
<el-checkbox
:disabled="readonly"
:value="grantAllCheckBoxCheckAll"
:indeterminate="grantAllCheckBoxForward"
@change="onGrantAllClicked"
>
{{ $t('AbpPermissionManagement.SelectAllInAllTabs') }}
</el-checkbox>
<el-divider />
<el-tabs
v-model="activeTabPane"
tab-position="left"
type="card"
>
<el-tab-pane
v-for="group in permissionGroups"
:key="group.name"
:label="group.displayName + ' (' + grantedCount(group) + ')'"
:name="group.name"
>
<el-card shadow="never">
<div
slot="header"
class="clearfix"
>
<h3>{{ group.displayName }}</h3>
</div>
<el-checkbox
:disabled="readonly"
:value="scopeCheckBoxCheckAll(group)"
:indeterminate="scopeCheckBoxForward(group)"
@change="(checked) => onCheckScopeAllClicked(checked, group, 'permissionTree-' + group.name)"
>
{{ $t('AbpPermissionManagement.SelectAllInThisTab') }}
</el-checkbox>
<el-divider />
<el-tree
:ref="'permissionTree-' + group.name"
show-checkbox
:check-strictly="true"
node-key="id"
:data="group.permissions"
:default-checked-keys="grantedPermissionKeys(group)"
@check-change="(permission, checked) => onPermissionTreeNodeCheckChanged(permission, checked, group, 'permissionTree-' + group.name)"
/>
</el-card>
</el-tab-pane>
</el-tabs>
<el-divider />
<el-form-item>
<el-button
class="cancel"
type="info"
style="width:100px"
@click="onFormClosed"
>
{{ $t('AbpPermissionManagement.Cancel') }}
</el-button>
<el-button
:disabled="readonly"
class="confirm"
type="primary"
style="width:100px"
icon="el-icon-check"
:loading="confirmButtonBusy"
@click="onSave"
>
{{ confirmButtonTitle }}
</el-button>
</el-form-item>
</el-form>
</el-dialog>
</template>
<script lang="ts">
import { Component, Vue, Prop, Watch } from 'vue-property-decorator'
import PermissionApiService, { Permission, UpdatePermissionsDto } from '@/api/permission'
import { Tree } from 'element-ui'
/** element权限树 */
export class PermissionItem {
/** 权限标识 */
id = ''
/** 显示名称 */
label = ''
/** 是否授权 */
isGrant = false
/** 是否禁用 */
disabled = false
/** 子节点 */
children = new Array<PermissionItem>()
/** 父节点 */
parent?: PermissionItem
constructor(
id: string,
label: string,
isGrant: boolean
) {
this.id = id
this.label = label
this.isGrant = isGrant
}
public createChildren(permission: PermissionItem) {
permission.parent = this
this.children.push(permission)
}
public setGrant(grant: boolean) {
this.isGrant = grant
if (this.parent) {
this.parent.setGrant(grant)
}
}
public static setPermissionGrant(grant: boolean, permission: PermissionItem) {
permission.setGrant(grant)
if (!grant) {
permission.children.map(p => {
PermissionItem.setPermissionGrant(false, p)
})
}
}
public static setAllPermissionGrant(grant: boolean, permission: PermissionItem) {
permission.setGrant(grant)
permission.children.map(p => {
PermissionItem.setAllPermissionGrant(grant, p)
})
}
}
export class PermissionGroup {
name = ''
displayName = ''
permissions = new Array<PermissionItem>()
constructor(
name: string,
displayName: string
) {
this.name = name
this.displayName = displayName
}
public permissionCount() {
let count = 0
count += this.deepPermissionCount(this.permissions)
return count
}
public addPermission(permission: PermissionItem) {
this.permissions.push(permission)
}
public setAllGrant(grant: boolean) {
this.permissions.map(p => {
PermissionItem.setAllPermissionGrant(grant, p)
})
}
public grantedPermissionKeys() {
const keys = new Array<string>()
this.deepGrantedPermissionKeys(keys, this.permissions)
return keys
}
public grantedCount() {
let count = 0
count += this.deepGrantedCount(this.permissions)
return count
}
private deepGrantedCount(permissions: PermissionItem[]) {
let count = 0
count += permissions.filter(p => p.isGrant).length
permissions.forEach(p => {
count += this.deepGrantedCount(p.children)
})
return count
}
private deepGrantedPermissionKeys(keys: string[], permissions: PermissionItem[]) {
permissions.forEach(p => {
if (p.isGrant) {
keys.push(p.id)
}
this.deepGrantedPermissionKeys(keys, p.children)
})
}
private deepPermissionCount(permissions: PermissionItem[]) {
let count = 0
count += permissions.length
permissions.forEach(p => {
count += this.deepPermissionCount(p.children)
})
return count
}
}
/**
* 权限编辑组件
* 大量的计算属性与事件响应,还能再优化
*/
@Component({
name: 'PermissionForm'
})
export default class PermissionForm extends Vue {
/** 权限提供者名称 */
@Prop({ default: '' })
private providerName!: string
/** 权限提供者标识 */
@Prop({ default: '' })
private providerKey!: string
/** 是否展示权限编辑组件 */
@Prop({ default: false })
private showDialog!: boolean
/** 权限节点是否只读 */
@Prop({ default: false })
private readonly!: boolean
/** 激活tab页 */
private activeTabPane = ''
/** 确认按钮忙碌状态 */
private confirmButtonBusy = false
/** 当前编辑权限实体名称 */
private entityDisplayName = ''
/** 得到的权限组集合 */
private permissionGroups = new Array<PermissionGroup>()
/** 某个权限组已授权数量
* 用于显示已授权数量
*/
get grantedCount() {
return (group: PermissionGroup) => {
return group.grantedCount()
}
}
/**
* 所有已授权数量
*/
get grantAllCount() {
let count = 0
this.permissionGroups.forEach(group => {
count += group.grantedCount()
})
return count
}
/** 某个权限组已授权节点
* 用于勾选TreeNode
*/
get grantedPermissionKeys() {
return (group: PermissionGroup) => {
return group.grantedPermissionKeys()
}
}
/**
* 某个权限组权限数量
* 用于设定单个Tree的全选CheckBox状态
*/
get permissionCount() {
return (group: PermissionGroup) => {
return group.permissionCount()
}
}
/**
* 所有权限数量
*/
get permissionAllCount() {
let count = 0
this.permissionGroups.forEach(group => {
count += group.permissionCount()
})
return count
}
/**
* 单个Tree的全选CheckBox是否为选中状态
*/
get scopeCheckBoxCheckAll() {
return (group: PermissionGroup) => {
const grantCount = group.grantedCount()
return grantCount === group.permissionCount()
}
}
/**
* 单个Tree的全选CheckBox状态是否为预选状态
*/
get scopeCheckBoxForward() {
return (group: PermissionGroup) => {
const grantCount = group.grantedCount()
return grantCount > 0 && grantCount < group.permissionCount()
}
}
/**
* 授权所有CheckBox是否为选中状态
*/
get grantAllCheckBoxCheckAll() {
return this.grantAllCount === this.permissionAllCount
}
/**
* 授权所有CheckBox状态是否为预选状态
*/
get grantAllCheckBoxForward() {
const grantCount = this.grantAllCount
return grantCount > 0 && grantCount < this.permissionAllCount
}
/**
* 确认按钮标题
*/
get confirmButtonTitle() {
if (this.confirmButtonBusy) {
return this.$t('AbpPermissionManagement.SavingWithThreeDot')
}
return this.$t('AbpPermissionManagement.Save')
}
/**
* 响应组件可视事件
*/
@Watch('showDialog', { immediate: true })
private onShowDialogChanged() {
this.handleGetPermissions()
}
/**
* 获取权限集合
*/
private handleGetPermissions() {
this.activeTabPane = ''
this.permissionGroups.length = 0
if (this.showDialog && this.providerName) {
PermissionApiService.getPermissionsByKey(this.providerName, this.providerKey).then(res => {
this.entityDisplayName = res.entityDisplayName
res.groups.map(g => {
const group = new PermissionGroup(g.name, g.displayName)
const parents = g.permissions.filter(p => p.parentName === null)
parents.forEach(parent => {
const permission = new PermissionItem(parent.name, parent.displayName, parent.isGranted)
permission.disabled = this.readonly
const subPermissions = g.permissions.filter(p => p.parentName?.startsWith(parent.name))
this.generatePermission(permission, subPermissions)
group.addPermission(permission)
})
this.permissionGroups.push(group)
})
if (this.permissionGroups.length > 0) {
this.activeTabPane = this.permissionGroups[0].name
}
})
}
}
/** 递归生成子节点
* @param permissionTree 二级权限树
* @param permissions 权限列表
*/
private generatePermission(permission: PermissionItem, permissions: Permission[]) {
const subPermissions = permissions.filter(p => p.parentName !== permission.id)
permissions = permissions.filter(p => p.parentName === permission.id)
permissions.forEach(p => {
const children = new PermissionItem(p.name, p.displayName, p.isGranted)
children.disabled = this.readonly
const itemSubPermissions = subPermissions.filter(sp => sp.parentName === p.name)
if (itemSubPermissions.length > 0) {
this.generatePermission(children, itemSubPermissions)
}
permission.createChildren(children)
})
}
/**
* 保存权限
*/
private onSave() {
const updatePermission = new UpdatePermissionsDto()
this.permissionGroups.forEach(group => {
this.updatePermissionByInput(updatePermission, group.permissions)
})
this.confirmButtonBusy = true
PermissionApiService
.setPermissionsByKey(this.providerName, this.providerKey, updatePermission)
.then(() => {
this.$message.success(this.$t('global.successful').toString())
})
.finally(() => {
this.confirmButtonBusy = false
})
}
private updatePermissionByInput(permissions: UpdatePermissionsDto, items: PermissionItem[]) {
items.forEach(p => {
permissions.addPermission(p.id, p.isGrant)
this.updatePermissionByInput(permissions, p.children)
})
}
/**
* 窗口关闭事件
*/
private onFormClosed() {
this.$emit('closed')
}
/**
* 授予所有权限 按钮事件
*/
private onGrantAllClicked(checked: boolean) {
this.permissionGroups.forEach(group => {
group.setAllGrant(checked)
const trees = this.$refs['permissionTree-' + group.name] as Tree[]
trees[0].setCheckedKeys(this.grantedPermissionKeys(group))
})
}
/**
* Permission Tree 全选按钮事件
*/
private onCheckScopeAllClicked(checked: boolean, group: PermissionGroup, treeRef: any) {
group.setAllGrant(checked)
const trees = this.$refs[treeRef] as Tree[]
trees[0].setCheckedKeys(this.grantedPermissionKeys(group))
}
/**
* Permission TreeNode 变更事件
*/
private onPermissionTreeNodeCheckChanged(permission: PermissionItem, checked: boolean, group: PermissionGroup, treeRef: any) {
PermissionItem.setPermissionGrant(checked, permission)
if (permission.children.length > 0) {
const trees = this.$refs[treeRef] as Tree[]
trees[0].setCheckedKeys(this.grantedPermissionKeys(group))
}
}
}
</script>
<style lang="scss" scoped>
.confirm {
position: absolute;
right: 10px;
}
.cancel {
position: absolute;
right: 120px;
}
</style>