😎优化角色管理,拆分菜单授权
This commit is contained in:
parent
5603e52553
commit
1973f6dbe2
@ -34,11 +34,6 @@ public class AddRoleInput : SysRole
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[Required(ErrorMessage = "角色名称不能为空")]
|
[Required(ErrorMessage = "角色名称不能为空")]
|
||||||
public override string Name { get; set; }
|
public override string Name { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 菜单Id集合
|
|
||||||
/// </summary>
|
|
||||||
public List<long> MenuIdList { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class UpdateRoleInput : AddRoleInput
|
public class UpdateRoleInput : AddRoleInput
|
||||||
|
|||||||
@ -18,7 +18,6 @@ public class SysRoleService : IDynamicApiController, ITransient
|
|||||||
private readonly SysRoleMenuService _sysRoleMenuService;
|
private readonly SysRoleMenuService _sysRoleMenuService;
|
||||||
private readonly SysRoleApiService _sysRoleApiService;
|
private readonly SysRoleApiService _sysRoleApiService;
|
||||||
private readonly SysOrgService _sysOrgService;
|
private readonly SysOrgService _sysOrgService;
|
||||||
private readonly SysMenuService _sysMenuService;
|
|
||||||
private readonly SysUserRoleService _sysUserRoleService;
|
private readonly SysUserRoleService _sysUserRoleService;
|
||||||
private readonly SysCacheService _sysCacheService;
|
private readonly SysCacheService _sysCacheService;
|
||||||
private readonly SysCommonService _sysCommonService;
|
private readonly SysCommonService _sysCommonService;
|
||||||
@ -29,7 +28,6 @@ public class SysRoleService : IDynamicApiController, ITransient
|
|||||||
SysRoleMenuService sysRoleMenuService,
|
SysRoleMenuService sysRoleMenuService,
|
||||||
SysRoleApiService sysRoleApiService,
|
SysRoleApiService sysRoleApiService,
|
||||||
SysOrgService sysOrgService,
|
SysOrgService sysOrgService,
|
||||||
SysMenuService sysMenuService,
|
|
||||||
SysUserRoleService sysUserRoleService,
|
SysUserRoleService sysUserRoleService,
|
||||||
SysCacheService sysCacheService,
|
SysCacheService sysCacheService,
|
||||||
SysCommonService sysCommonService)
|
SysCommonService sysCommonService)
|
||||||
@ -40,7 +38,6 @@ public class SysRoleService : IDynamicApiController, ITransient
|
|||||||
_sysRoleMenuService = sysRoleMenuService;
|
_sysRoleMenuService = sysRoleMenuService;
|
||||||
_sysRoleApiService = sysRoleApiService;
|
_sysRoleApiService = sysRoleApiService;
|
||||||
_sysOrgService = sysOrgService;
|
_sysOrgService = sysOrgService;
|
||||||
_sysMenuService = sysMenuService;
|
|
||||||
_sysUserRoleService = sysUserRoleService;
|
_sysUserRoleService = sysUserRoleService;
|
||||||
_sysCacheService = sysCacheService;
|
_sysCacheService = sysCacheService;
|
||||||
_sysCommonService = sysCommonService;
|
_sysCommonService = sysCommonService;
|
||||||
@ -97,31 +94,7 @@ public class SysRoleService : IDynamicApiController, ITransient
|
|||||||
if (await _sysRoleRep.IsAnyAsync(u => u.Name == input.Name && u.Code == input.Code))
|
if (await _sysRoleRep.IsAnyAsync(u => u.Name == input.Name && u.Code == input.Code))
|
||||||
throw Oops.Oh(ErrorCodeEnum.D1006);
|
throw Oops.Oh(ErrorCodeEnum.D1006);
|
||||||
|
|
||||||
var newRole = await _sysRoleRep.AsInsertable(input.Adapt<SysRole>()).ExecuteReturnEntityAsync();
|
await _sysRoleRep.InsertAsync(input.Adapt<SysRole>());
|
||||||
input.Id = newRole.Id;
|
|
||||||
await UpdateRoleMenu(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 更新角色菜单权限
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="input"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
private async Task UpdateRoleMenu(AddRoleInput input)
|
|
||||||
{
|
|
||||||
if (input.MenuIdList == null || input.MenuIdList.Count < 1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// 将父节点为0的菜单排除,防止前端全选异常
|
|
||||||
var pMenuIds = await _sysRoleRep.ChangeRepository<SqlSugarRepository<SysMenu>>().AsQueryable().Where(u => input.MenuIdList.Contains(u.Id) && u.Pid == 0).ToListAsync(u => u.Id);
|
|
||||||
var menuIds = input.MenuIdList.Except(pMenuIds); // 差集
|
|
||||||
await GrantMenu(new RoleMenuInput()
|
|
||||||
{
|
|
||||||
Id = input.Id,
|
|
||||||
MenuIdList = menuIds.ToList()
|
|
||||||
});
|
|
||||||
|
|
||||||
await ClearUserApiCache(input.Id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -138,8 +111,6 @@ public class SysRoleService : IDynamicApiController, ITransient
|
|||||||
|
|
||||||
await _sysRoleRep.AsUpdateable(input.Adapt<SysRole>()).IgnoreColumns(true)
|
await _sysRoleRep.AsUpdateable(input.Adapt<SysRole>()).IgnoreColumns(true)
|
||||||
.IgnoreColumns(u => new { u.DataScope }).ExecuteCommandAsync();
|
.IgnoreColumns(u => new { u.DataScope }).ExecuteCommandAsync();
|
||||||
|
|
||||||
await UpdateRoleMenu(input);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -182,11 +153,24 @@ public class SysRoleService : IDynamicApiController, ITransient
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="input"></param>
|
/// <param name="input"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[UnitOfWork]
|
|
||||||
[DisplayName("授权角色菜单")]
|
[DisplayName("授权角色菜单")]
|
||||||
public async Task GrantMenu(RoleMenuInput input)
|
public async Task GrantMenu(RoleMenuInput input)
|
||||||
{
|
{
|
||||||
|
if (input.MenuIdList == null || input.MenuIdList.Count < 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//// 将父节点为0的菜单排除,防止前端全选异常
|
||||||
|
//var pMenuIds = await _sysRoleRep.ChangeRepository<SqlSugarRepository<SysMenu>>().AsQueryable().Where(u => input.MenuIdList.Contains(u.Id) && u.Pid == 0).ToListAsync(u => u.Id);
|
||||||
|
//var menuIds = input.MenuIdList.Except(pMenuIds); // 差集
|
||||||
|
//await _sysRoleMenuService.GrantRoleMenu(new RoleMenuInput()
|
||||||
|
//{
|
||||||
|
// Id = input.Id,
|
||||||
|
// MenuIdList = menuIds.ToList()
|
||||||
|
//});
|
||||||
|
|
||||||
await _sysRoleMenuService.GrantRoleMenu(input);
|
await _sysRoleMenuService.GrantRoleMenu(input);
|
||||||
|
|
||||||
|
await ClearUserApiCache(input.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -233,25 +217,16 @@ public class SysRoleService : IDynamicApiController, ITransient
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 根据角色Id获取菜单Id集合 🔖
|
/// 授权角色接口 🔖
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="input"></param>
|
/// <param name="input"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[DisplayName("根据角色Id获取菜单Id集合")]
|
[UnitOfWork]
|
||||||
public async Task<List<long>> GetOwnMenuList([FromQuery] RoleInput input)
|
[DisplayName("授权角色接口")]
|
||||||
|
public async Task GrantApi(RoleApiInput input)
|
||||||
{
|
{
|
||||||
return await _sysRoleMenuService.GetRoleMenuIdList(new List<long> { input.Id });
|
await ClearUserApiCache(input.Id);
|
||||||
}
|
await _sysRoleApiService.GrantRoleApi(input);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 根据角色Id获取机构Id集合 🔖
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="input"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
[DisplayName("根据角色Id获取机构Id集合")]
|
|
||||||
public async Task<List<long>> GetOwnOrgList([FromQuery] RoleInput input)
|
|
||||||
{
|
|
||||||
return await _sysRoleOrgService.GetRoleOrgIdList(new List<long> { input.Id });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -272,30 +247,25 @@ public class SysRoleService : IDynamicApiController, ITransient
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 授权角色接口 🔖
|
/// 根据角色Id获取菜单Id集合 🔖
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="input"></param>
|
/// <param name="input"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[UnitOfWork]
|
[DisplayName("根据角色Id获取菜单Id集合")]
|
||||||
[DisplayName("授权角色接口")]
|
public async Task<List<long>> GetOwnMenuList([FromQuery] RoleInput input)
|
||||||
public async Task GrantApi(RoleApiInput input)
|
|
||||||
{
|
{
|
||||||
await ClearUserApiCache(input.Id);
|
return await _sysRoleMenuService.GetRoleMenuIdList(new List<long> { input.Id });
|
||||||
await _sysRoleApiService.GrantRoleApi(input);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 删除与该角色相关的用户接口缓存
|
/// 根据角色Id获取机构Id集合 🔖
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="roleId"></param>
|
/// <param name="input"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private async Task ClearUserApiCache(long roleId)
|
[DisplayName("根据角色Id获取机构Id集合")]
|
||||||
|
public async Task<List<long>> GetOwnOrgList([FromQuery] RoleInput input)
|
||||||
{
|
{
|
||||||
var userIdList = await _sysUserRoleService.GetUserIdList(roleId);
|
return await _sysRoleOrgService.GetRoleOrgIdList(new List<long> { input.Id });
|
||||||
foreach (var userId in userIdList)
|
|
||||||
{
|
|
||||||
_sysCacheService.Remove(CacheConst.KeyUserApi + userId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -397,4 +367,18 @@ public class SysRoleService : IDynamicApiController, ITransient
|
|||||||
.WhereIF(menuIds.Count > 0, u => menuIds.Contains(u.Id))
|
.WhereIF(menuIds.Count > 0, u => menuIds.Contains(u.Id))
|
||||||
.Select(u => u.Permission).ToListAsync();
|
.Select(u => u.Permission).ToListAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 删除与该角色相关的用户接口缓存
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="roleId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private async Task ClearUserApiCache(long roleId)
|
||||||
|
{
|
||||||
|
var userIdList = await _sysUserRoleService.GetUserIdList(roleId);
|
||||||
|
foreach (var userId in userIdList)
|
||||||
|
{
|
||||||
|
_sysCacheService.Remove(CacheConst.KeyUserApi + userId);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -144,12 +144,4 @@ export interface AddRoleInput {
|
|||||||
* @memberof AddRoleInput
|
* @memberof AddRoleInput
|
||||||
*/
|
*/
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* 菜单Id集合
|
|
||||||
*
|
|
||||||
* @type {Array<number>}
|
|
||||||
* @memberof AddRoleInput
|
|
||||||
*/
|
|
||||||
menuIdList?: Array<number> | null;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -144,12 +144,4 @@ export interface UpdateRoleInput {
|
|||||||
* @memberof UpdateRoleInput
|
* @memberof UpdateRoleInput
|
||||||
*/
|
*/
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* 菜单Id集合
|
|
||||||
*
|
|
||||||
* @type {Array<number>}
|
|
||||||
* @memberof UpdateRoleInput
|
|
||||||
*/
|
|
||||||
menuIdList?: Array<number> | null;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="sys-role-container">
|
<div class="sys-role-container">
|
||||||
<el-dialog v-model="state.isShowDialog" draggable :close-on-click-modal="false">
|
<el-dialog v-model="state.isShowDialog" draggable :close-on-click-modal="false" width="700px">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div style="color: #fff">
|
<div style="color: #fff">
|
||||||
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Edit /> </el-icon>
|
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Edit /> </el-icon>
|
||||||
@ -37,21 +37,6 @@
|
|||||||
<el-input v-model="state.ruleForm.remark" placeholder="请输入备注内容" clearable type="textarea" />
|
<el-input v-model="state.ruleForm.remark" placeholder="请输入备注内容" clearable type="textarea" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="mb20">
|
|
||||||
<el-form-item label="菜单权限" v-loading="state.loading">
|
|
||||||
<el-tree
|
|
||||||
ref="treeRef"
|
|
||||||
:data="state.menuData"
|
|
||||||
node-key="id"
|
|
||||||
show-checkbox
|
|
||||||
:props="{ children: 'children', label: 'title', class: treeNodeClass }"
|
|
||||||
icon="ele-Menu"
|
|
||||||
highlight-current
|
|
||||||
default-expand-all
|
|
||||||
style="height: 500px; overflow-y: auto; width: 100%"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
@ -65,46 +50,27 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup name="sysEditRole">
|
<script lang="ts" setup name="sysEditRole">
|
||||||
import { onMounted, reactive, ref } from 'vue';
|
import { reactive, ref } from 'vue';
|
||||||
import type { ElTree } from 'element-plus';
|
|
||||||
|
|
||||||
import { getAPI } from '/@/utils/axios-utils';
|
import { getAPI } from '/@/utils/axios-utils';
|
||||||
import { SysMenuApi, SysRoleApi } from '/@/api-services/api';
|
import { SysRoleApi } from '/@/api-services/api';
|
||||||
import { SysMenu, UpdateRoleInput } from '/@/api-services/models';
|
import { UpdateRoleInput } from '/@/api-services/models';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
title: String,
|
title: String,
|
||||||
});
|
});
|
||||||
const emits = defineEmits(['handleQuery']);
|
const emits = defineEmits(['handleQuery']);
|
||||||
const ruleFormRef = ref();
|
const ruleFormRef = ref();
|
||||||
const treeRef = ref<InstanceType<typeof ElTree>>();
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
loading: false,
|
|
||||||
isShowDialog: false,
|
isShowDialog: false,
|
||||||
ruleForm: {} as UpdateRoleInput,
|
ruleForm: {} as UpdateRoleInput,
|
||||||
menuData: [] as Array<SysMenu>, // 菜单数据
|
|
||||||
});
|
|
||||||
|
|
||||||
// 页面初始化
|
|
||||||
onMounted(async () => {
|
|
||||||
state.loading = true;
|
|
||||||
var res = await getAPI(SysMenuApi).apiSysMenuListGet();
|
|
||||||
state.menuData = res.data.result ?? [];
|
|
||||||
state.loading = false;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 打开弹窗
|
// 打开弹窗
|
||||||
const openDialog = async (row: any) => {
|
const openDialog = async (row: any) => {
|
||||||
ruleFormRef.value?.resetFields();
|
|
||||||
treeRef.value?.setCheckedKeys([]); // 清空选中值
|
|
||||||
state.ruleForm = JSON.parse(JSON.stringify(row));
|
state.ruleForm = JSON.parse(JSON.stringify(row));
|
||||||
if (row.id != undefined) {
|
|
||||||
var res = await getAPI(SysRoleApi).apiSysRoleOwnMenuListGet(row.id);
|
|
||||||
setTimeout(() => {
|
|
||||||
treeRef.value?.setCheckedKeys(res.data.result ?? []);
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
state.isShowDialog = true;
|
state.isShowDialog = true;
|
||||||
|
ruleFormRef.value?.resetFields();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 关闭弹窗
|
// 关闭弹窗
|
||||||
@ -119,10 +85,9 @@ const cancel = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 提交
|
// 提交
|
||||||
const submit = () => {
|
const submit = async () => {
|
||||||
ruleFormRef.value.validate(async (valid: boolean) => {
|
ruleFormRef.value.validate(async (valid: boolean) => {
|
||||||
if (!valid) return;
|
if (!valid) return;
|
||||||
state.ruleForm.menuIdList = treeRef.value?.getCheckedKeys() as Array<number>; //.concat(treeRef.value?.getHalfCheckedKeys());
|
|
||||||
if (state.ruleForm.id != undefined && state.ruleForm.id > 0) {
|
if (state.ruleForm.id != undefined && state.ruleForm.id > 0) {
|
||||||
await getAPI(SysRoleApi).apiSysRoleUpdatePost(state.ruleForm);
|
await getAPI(SysRoleApi).apiSysRoleUpdatePost(state.ruleForm);
|
||||||
} else {
|
} else {
|
||||||
@ -132,49 +97,6 @@ const submit = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 叶子节点同行显示样式
|
|
||||||
const treeNodeClass = (node: SysMenu) => {
|
|
||||||
let addClass = true; // 添加叶子节点同行显示样式
|
|
||||||
for (var key in node.children) {
|
|
||||||
// 如果存在子节点非叶子节点,不添加样式
|
|
||||||
if (node.children[key].children?.length ?? 0 > 0) {
|
|
||||||
addClass = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return addClass ? 'penultimate-node' : '';
|
|
||||||
};
|
|
||||||
|
|
||||||
// 导出对象
|
// 导出对象
|
||||||
defineExpose({ openDialog });
|
defineExpose({ openDialog });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.menu-data-tree {
|
|
||||||
width: 100%;
|
|
||||||
border: 1px solid var(--el-border-color);
|
|
||||||
border-radius: var(--el-input-border-radius, var(--el-border-radius-base));
|
|
||||||
padding: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
:deep(.penultimate-node) {
|
|
||||||
.el-tree-node__children {
|
|
||||||
padding-left: 40px;
|
|
||||||
white-space: pre-wrap;
|
|
||||||
line-height: 100%;
|
|
||||||
|
|
||||||
.el-tree-node {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-tree-node__content {
|
|
||||||
padding-left: 5px !important;
|
|
||||||
padding-right: 5px;
|
|
||||||
|
|
||||||
// .el-tree-node__expand-icon {
|
|
||||||
// display: none;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@ -95,9 +95,7 @@ const initTreeData = async () => {
|
|||||||
state.loading = true;
|
state.loading = true;
|
||||||
var res = await getAPI(SysCommonApi).apiSysCommonApiListGet();
|
var res = await getAPI(SysCommonApi).apiSysCommonApiListGet();
|
||||||
var tData = res.data.result ?? [];
|
var tData = res.data.result ?? [];
|
||||||
|
|
||||||
treeRef.value?.setCheckedKeys([]); // 清空选中值
|
treeRef.value?.setCheckedKeys([]); // 清空选中值
|
||||||
|
|
||||||
state.allApiData = tData;
|
state.allApiData = tData;
|
||||||
state.loading = false;
|
state.loading = false;
|
||||||
};
|
};
|
||||||
@ -106,10 +104,9 @@ const initTreeData = async () => {
|
|||||||
const openDrawer = async (row: any) => {
|
const openDrawer = async (row: any) => {
|
||||||
state.selectedTabName = 0;
|
state.selectedTabName = 0;
|
||||||
state.roleId = row.id;
|
state.roleId = row.id;
|
||||||
state.drawerTitle = '授权角色接口资源【' + row.name + '】';
|
state.drawerTitle = '设置角色接口黑名单【' + row.name + '】';
|
||||||
state.isVisible = true;
|
|
||||||
state.loading = false;
|
|
||||||
|
|
||||||
|
state.loading = true;
|
||||||
// 获取已有接口资源
|
// 获取已有接口资源
|
||||||
var res1 = await getAPI(SysRoleApi).apiSysRoleRoleApiListGet(state.roleId);
|
var res1 = await getAPI(SysRoleApi).apiSysRoleRoleApiListGet(state.roleId);
|
||||||
state.ownApiList = res1.data.result ?? [];
|
state.ownApiList = res1.data.result ?? [];
|
||||||
@ -119,6 +116,7 @@ const openDrawer = async (row: any) => {
|
|||||||
}, 200);
|
}, 200);
|
||||||
|
|
||||||
state.loading = false;
|
state.loading = false;
|
||||||
|
state.isVisible = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 节点过滤
|
// 节点过滤
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
<template #header>
|
<template #header>
|
||||||
<div style="color: #fff">
|
<div style="color: #fff">
|
||||||
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Edit /> </el-icon>
|
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Edit /> </el-icon>
|
||||||
<span> 授权数据范围 </span>
|
<span> {{ state.title }} </span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<el-form :model="state.ruleForm" label-position="top">
|
<el-form :model="state.ruleForm" label-position="top">
|
||||||
@ -47,6 +47,7 @@ const emits = defineEmits(['handleQuery']);
|
|||||||
const orgTreeRef = ref();
|
const orgTreeRef = ref();
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
isShowDialog: false,
|
isShowDialog: false,
|
||||||
|
title: '',
|
||||||
ruleForm: {} as RoleOrgInput,
|
ruleForm: {} as RoleOrgInput,
|
||||||
dataScopeType: [
|
dataScopeType: [
|
||||||
{ value: 1, label: '全部数据' },
|
{ value: 1, label: '全部数据' },
|
||||||
@ -59,6 +60,8 @@ const state = reactive({
|
|||||||
|
|
||||||
// 打开弹窗
|
// 打开弹窗
|
||||||
const openDialog = async (row: any) => {
|
const openDialog = async (row: any) => {
|
||||||
|
state.title = '授权角色数据范围【' + row.name + '】';
|
||||||
|
|
||||||
state.ruleForm = JSON.parse(JSON.stringify(row));
|
state.ruleForm = JSON.parse(JSON.stringify(row));
|
||||||
var res = await getAPI(SysRoleApi).apiSysRoleOwnOrgListGet(row.id);
|
var res = await getAPI(SysRoleApi).apiSysRoleOwnOrgListGet(row.id);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|||||||
141
Web/src/views/system/role/component/grantMenu.vue
Normal file
141
Web/src/views/system/role/component/grantMenu.vue
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
<template>
|
||||||
|
<div class="sys-grantMenu-container">
|
||||||
|
<el-drawer v-model="state.isVisible" size="55%">
|
||||||
|
<template #header>
|
||||||
|
<div style="color: #fff">
|
||||||
|
<el-icon size="16" style="margin-right: 3px; display: inline; vertical-align: middle"> <ele-Menu /> </el-icon>
|
||||||
|
<span>{{ state.drawerTitle }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<div>
|
||||||
|
<NoticeBar leftIcon="iconfont icon-tongzhi2" text="非超管角色禁止授权系统核心模块菜单资源!!!" :scrollable="true" style="margin: 5px" />
|
||||||
|
</div>
|
||||||
|
<div v-loading="state.loading">
|
||||||
|
<el-tree
|
||||||
|
ref="treeRef"
|
||||||
|
:data="state.menuData"
|
||||||
|
node-key="id"
|
||||||
|
show-checkbox
|
||||||
|
:props="{ children: 'children', label: 'title', class: treeNodeClass }"
|
||||||
|
icon="ele-Menu"
|
||||||
|
highlight-current
|
||||||
|
default-expand-all
|
||||||
|
style="margin: 10px"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<template #footer>
|
||||||
|
<div style="margin-bottom: 20px; margin-right: 20px">
|
||||||
|
<el-button @click="cancel">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="submit">确 定</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-drawer>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { reactive, onMounted, ref } from 'vue';
|
||||||
|
import type { ElTree } from 'element-plus';
|
||||||
|
import NoticeBar from '/@/components/noticeBar/index.vue';
|
||||||
|
|
||||||
|
import { getAPI } from '/@/utils/axios-utils';
|
||||||
|
import { SysMenuApi, SysRoleApi } from '/@/api-services/api';
|
||||||
|
import { SysMenu, UpdateRoleInput } from '/@/api-services/models';
|
||||||
|
|
||||||
|
const ruleFormRef = ref();
|
||||||
|
const treeRef = ref<InstanceType<typeof ElTree>>();
|
||||||
|
const state = reactive({
|
||||||
|
loading: false,
|
||||||
|
isVisible: false,
|
||||||
|
drawerTitle: '',
|
||||||
|
menuIdList: [] as any,
|
||||||
|
roleId: 0,
|
||||||
|
ruleForm: {} as UpdateRoleInput,
|
||||||
|
menuData: [] as Array<SysMenu>, // 菜单数据
|
||||||
|
});
|
||||||
|
|
||||||
|
// 页面初始化
|
||||||
|
onMounted(async () => {
|
||||||
|
state.loading = true;
|
||||||
|
var res = await getAPI(SysMenuApi).apiSysMenuListGet();
|
||||||
|
state.menuData = res.data.result ?? [];
|
||||||
|
state.loading = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 打开页面
|
||||||
|
const openDrawer = async (row: any) => {
|
||||||
|
state.roleId = row.id;
|
||||||
|
state.drawerTitle = '授权角色菜单【' + row.name + '】';
|
||||||
|
|
||||||
|
state.loading = true;
|
||||||
|
ruleFormRef.value?.resetFields();
|
||||||
|
treeRef.value?.setCheckedKeys([]); // 清空选中值
|
||||||
|
state.ruleForm = JSON.parse(JSON.stringify(row));
|
||||||
|
if (row.id != undefined) {
|
||||||
|
var res = await getAPI(SysRoleApi).apiSysRoleOwnMenuListGet(row.id);
|
||||||
|
setTimeout(() => {
|
||||||
|
treeRef.value?.setCheckedKeys(res.data.result ?? []);
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
state.loading = false;
|
||||||
|
state.isVisible = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 取消
|
||||||
|
const cancel = () => {
|
||||||
|
state.isVisible = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 提交
|
||||||
|
const submit = async () => {
|
||||||
|
state.menuIdList = treeRef.value?.getCheckedKeys() as Array<number>; //.concat(treeRef.value?.getHalfCheckedKeys());
|
||||||
|
await getAPI(SysRoleApi).apiSysRoleGrantMenuPost({ id: state.roleId, menuIdList: state.menuIdList });
|
||||||
|
cancel();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 叶子节点同行显示样式
|
||||||
|
const treeNodeClass = (node: SysMenu) => {
|
||||||
|
let addClass = true; // 添加叶子节点同行显示样式
|
||||||
|
for (var key in node.children) {
|
||||||
|
// 如果存在子节点非叶子节点,不添加样式
|
||||||
|
if (node.children[key].children?.length ?? 0 > 0) {
|
||||||
|
addClass = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return addClass ? 'penultimate-node' : '';
|
||||||
|
};
|
||||||
|
|
||||||
|
// 导出对象
|
||||||
|
defineExpose({ openDrawer });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
// .menu-data-tree {
|
||||||
|
// width: 100%;
|
||||||
|
// border: 1px solid var(--el-border-color);
|
||||||
|
// border-radius: var(--el-input-border-radius, var(--el-border-radius-base));
|
||||||
|
// padding: 5px;
|
||||||
|
// }
|
||||||
|
|
||||||
|
:deep(.penultimate-node) {
|
||||||
|
.el-tree-node__children {
|
||||||
|
padding-left: 35px;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
line-height: 100%;
|
||||||
|
|
||||||
|
.el-tree-node {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-tree-node__content {
|
||||||
|
padding-left: 5px !important;
|
||||||
|
padding-right: 5px;
|
||||||
|
|
||||||
|
// .el-tree-node__expand-icon {
|
||||||
|
// display: none;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -58,16 +58,17 @@
|
|||||||
<el-tooltip content="删除" placement="top">
|
<el-tooltip content="删除" placement="top">
|
||||||
<el-button icon="ele-Delete" size="small" text type="danger" @click="handleDelete(row)" v-auth="'sysRole/delete'"></el-button>
|
<el-button icon="ele-Delete" size="small" text type="danger" @click="handleDelete(row)" v-auth="'sysRole/delete'"></el-button>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<el-button icon="ele-OfficeBuilding" size="small" text type="primary" @click="openGrantData(row)" v-auth="'sysRole/grantDataScope'">数据范围</el-button>
|
<el-button icon="ele-Menu" size="small" text type="primary" @click="openGrantMenu(row)" v-auth="'sysRole/grantMenu'">授权菜单</el-button>
|
||||||
|
<el-button icon="ele-OfficeBuilding" size="small" text type="primary" @click="openGrantData(row)" v-auth="'sysRole/grantDataScope'">授权数据</el-button>
|
||||||
<el-button icon="ele-Link" size="small" text type="primary" @click="openGrantApi(row)" v-auth="'sysRole/grantApi'"> 接口黑名单 </el-button>
|
<el-button icon="ele-Link" size="small" text type="primary" @click="openGrantApi(row)" v-auth="'sysRole/grantApi'"> 接口黑名单 </el-button>
|
||||||
</template>
|
</template>
|
||||||
</vxe-grid>
|
</vxe-grid>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
<EditRole ref="editRoleRef" :title="state.title" @handleQuery="handleQuery" />
|
<EditRole ref="editRoleRef" :title="state.title" @handleQuery="handleQuery" />
|
||||||
|
<GrantMenu ref="grantMenuRef" />
|
||||||
<GrantData ref="grantDataRef" @handleQuery="handleQuery" />
|
<GrantData ref="grantDataRef" @handleQuery="handleQuery" />
|
||||||
<GrantApi ref="grantApiRef" @handleQuery="handleQuery" />
|
<GrantApi ref="grantApiRef" />
|
||||||
<BaseApi ref="baseApiRef" />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -79,6 +80,7 @@ import { useVxeTable } from '/@/hooks/useVxeTableOptionsHook';
|
|||||||
import { Local } from '/@/utils/storage';
|
import { Local } from '/@/utils/storage';
|
||||||
|
|
||||||
import EditRole from '/@/views/system/role/component/editRole.vue';
|
import EditRole from '/@/views/system/role/component/editRole.vue';
|
||||||
|
import GrantMenu from '/@/views/system/role/component/grantMenu.vue';
|
||||||
import GrantData from '/@/views/system/role/component/grantData.vue';
|
import GrantData from '/@/views/system/role/component/grantData.vue';
|
||||||
import GrantApi from '/@/views/system/role/component/grantApi.vue';
|
import GrantApi from '/@/views/system/role/component/grantApi.vue';
|
||||||
import ModifyRecord from '/@/components/table/modifyRecord.vue';
|
import ModifyRecord from '/@/components/table/modifyRecord.vue';
|
||||||
@ -89,6 +91,7 @@ import { PageRoleInput, PageRoleOutput } from '/@/api-services/models';
|
|||||||
|
|
||||||
const xGrid = ref<VxeGridInstance>();
|
const xGrid = ref<VxeGridInstance>();
|
||||||
const editRoleRef = ref<InstanceType<typeof EditRole>>();
|
const editRoleRef = ref<InstanceType<typeof EditRole>>();
|
||||||
|
const grantMenuRef = ref<InstanceType<typeof GrantMenu>>();
|
||||||
const grantDataRef = ref<InstanceType<typeof GrantData>>();
|
const grantDataRef = ref<InstanceType<typeof GrantData>>();
|
||||||
const grantApiRef = ref<InstanceType<typeof GrantApi>>();
|
const grantApiRef = ref<InstanceType<typeof GrantApi>>();
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
@ -121,7 +124,7 @@ const options = useVxeTable<PageRoleOutput>(
|
|||||||
{ field: 'orderNo', title: '排序', width: 80, showOverflow: 'tooltip' },
|
{ field: 'orderNo', title: '排序', width: 80, showOverflow: 'tooltip' },
|
||||||
{ field: 'status', title: '状态', width: 80, showOverflow: 'tooltip', slots: { default: 'row_status' } },
|
{ field: 'status', title: '状态', width: 80, showOverflow: 'tooltip', slots: { default: 'row_status' } },
|
||||||
{ field: '', title: '修改记录', width: 100, showOverflow: 'tooltip', slots: { default: 'row_record' } },
|
{ field: '', title: '修改记录', width: 100, showOverflow: 'tooltip', slots: { default: 'row_record' } },
|
||||||
{ title: '操作', fixed: 'right', width: 280, showOverflow: true, slots: { default: 'row_buttons' } },
|
{ title: '操作', fixed: 'right', width: 360, showOverflow: true, slots: { default: 'row_buttons' } },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
// vxeGrid配置参数(此处可覆写任何参数),参考vxe-table官方文档
|
// vxeGrid配置参数(此处可覆写任何参数),参考vxe-table官方文档
|
||||||
@ -203,6 +206,11 @@ const gridEvents: VxeGridListeners<PageRoleOutput> = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 打开授权菜单页面
|
||||||
|
const openGrantMenu = (row: any) => {
|
||||||
|
grantMenuRef.value?.openDrawer(row);
|
||||||
|
};
|
||||||
|
|
||||||
// 打开授权数据范围页面
|
// 打开授权数据范围页面
|
||||||
const openGrantData = (row: any) => {
|
const openGrantData = (row: any) => {
|
||||||
grantDataRef.value?.openDialog(row);
|
grantDataRef.value?.openDialog(row);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user