20 changed files with 928 additions and 763 deletions
@ -1,9 +0,0 @@ |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace LINGYUN.Abp.IdentityServer.Clients |
|||
{ |
|||
public class ClientCorsOriginDto : EntityDto |
|||
{ |
|||
public string Origin { get; set; } |
|||
} |
|||
} |
|||
Binary file not shown.
@ -0,0 +1,466 @@ |
|||
<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 |
|||
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 |
|||
|
|||
/** 确认按钮忙碌状态 */ |
|||
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.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) |
|||
}) |
|||
}) |
|||
} |
|||
} |
|||
|
|||
/** 递归生成子节点 |
|||
* @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> |
|||
Loading…
Reference in new issue