update 角色管理菜单权限-数据权限放到一起

This commit is contained in:
lau
2026-04-14 21:08:43 +08:00
parent d38329befb
commit cedf975ed3
2 changed files with 144 additions and 103 deletions
+5 -5
View File
@@ -45,23 +45,23 @@ export const addRole = (data: any) => {
}; };
/** /**
* 修改角色 * 修改角色基础信息
* @param data * @param data
*/ */
export const updateRole = (data: any) => { export const updateRole = (data: any) => {
return request({ return request({
url: '/system/role', url: '/system/role/baseInfo',
method: 'put', method: 'put',
data: data data: data
}); });
}; };
/** /**
* 角色数据权限 * 修改角色权限(菜单权限 + 数据权限
*/ */
export const dataScope = (data: any) => { export const updateRolePermission = (data: any) => {
return request({ return request({
url: '/system/role/dataScope', url: '/system/role/permission',
method: 'put', method: 'put',
data: data data: data
}); });
+139 -98
View File
@@ -136,7 +136,7 @@
@click="handleDelete(scope.row)" @click="handleDelete(scope.row)"
></el-button> ></el-button>
</el-tooltip> </el-tooltip>
<el-tooltip v-if="scope.row.roleId !== 1761300000000000001" content="数据权限" placement="top"> <el-tooltip v-if="scope.row.roleId !== 1761300000000000001" content="分配权限" placement="top">
<el-button <el-button
v-hasPermi="['system:role:edit']" v-hasPermi="['system:role:edit']"
link link
@@ -167,54 +167,47 @@
/> />
</el-card> </el-card>
<el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body> <el-dialog v-model="dialog.visible" :title="dialog.title" width="720px" append-to-body>
<el-form ref="roleFormRef" :model="form" :rules="rules" label-width="100px"> <el-form ref="roleFormRef" :model="form" :rules="rules" label-width="100px" class="dialog-grid-form">
<el-form-item label="角色名称" prop="roleName"> <el-row :gutter="16">
<el-input v-model="form.roleName" placeholder="请输入角色名称" /> <el-col :span="12">
</el-form-item> <el-form-item label="角色名称" prop="roleName">
<el-form-item prop="roleKey"> <el-input v-model="form.roleName" placeholder="请输入角色名称" />
<template #label> </el-form-item>
<span> </el-col>
<el-tooltip content="控制器中定义的权限字符,如:@SaCheckRole('admin')" placement="top"> <el-col :span="12">
<el-icon><question-filled /></el-icon> <el-form-item prop="roleKey">
</el-tooltip> <template #label>
权限字符 <span>
</span> <el-tooltip content="控制器中定义的权限字符,如:@SaCheckRole('admin')" placement="top">
</template> <el-icon><question-filled /></el-icon>
<el-input v-model="form.roleKey" placeholder="请输入权限字符" /> </el-tooltip>
</el-form-item> 权限字符
<el-form-item label="角色顺序" prop="roleSort"> </span>
<el-input-number v-model="form.roleSort" controls-position="right" :min="0" /> </template>
</el-form-item> <el-input v-model="form.roleKey" placeholder="请输入权限字符" />
<el-form-item label="状态"> </el-form-item>
<el-radio-group v-model="form.status"> </el-col>
<el-radio v-for="dict in sys_normal_disable" :key="dict.value" :value="dict.value"> <el-col :span="12">
{{ dict.label }} <el-form-item label="角色顺序" prop="roleSort">
</el-radio> <el-input-number v-model="form.roleSort" controls-position="right" :min="0" class="w-full" />
</el-radio-group> </el-form-item>
</el-form-item> </el-col>
<el-form-item label="菜单权限"> <el-col :span="12">
<el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event, 'menu')">展开/折叠</el-checkbox> <el-form-item label="状态">
<el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event, 'menu')"> <el-radio-group v-model="form.status">
全选/全不选 <el-radio v-for="dict in sys_normal_disable" :key="dict.value" :value="dict.value">
</el-checkbox> {{ dict.label }}
<el-checkbox v-model="form.menuCheckStrictly" @change="handleCheckedTreeConnect($event, 'menu')"> </el-radio>
父子联动 </el-radio-group>
</el-checkbox> </el-form-item>
<el-tree </el-col>
ref="menuRef" <el-col :span="24">
class="tree-border" <el-form-item label="备注">
:data="menuOptions" <el-input v-model="form.remark" type="textarea" :rows="3" placeholder="请输入内容"></el-input>
show-checkbox </el-form-item>
node-key="id" </el-col>
:check-strictly="!form.menuCheckStrictly" </el-row>
empty-text="加载中请稍候"
:props="{ label: 'label', children: 'children' } as any"
></el-tree>
</el-form-item>
<el-form-item label="备注">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
</el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
<div class="dialog-footer"> <div class="dialog-footer">
@@ -224,45 +217,62 @@
</template> </template>
</el-dialog> </el-dialog>
<!-- 分配角色数据权限对话框 --> <!-- 分配角色权限对话框 -->
<el-dialog v-model="openDataScope" :title="dialog.title" width="500px" append-to-body> <el-dialog v-model="openDataScope" :title="dialog.title" width="760px" append-to-body>
<el-form ref="dataScopeRef" :model="form" label-width="80px"> <el-form ref="dataScopeRef" :model="form" label-width="90px" class="dialog-grid-form permission-dialog-form">
<el-form-item label="角色名称"> <el-tabs v-model="permissionTab">
<el-input v-model="form.roleName" :disabled="true" /> <el-tab-pane label="数据权限" name="data">
</el-form-item> <el-form-item label="权限范围">
<el-form-item label="权限字符"> <el-select v-model="form.dataScope" @change="dataScopeSelectChange">
<el-input v-model="form.roleKey" :disabled="true" /> <el-option
</el-form-item> v-for="item in dataScopeOptions"
<el-form-item label="权限范围"> :key="item.value"
<el-select v-model="form.dataScope" @change="dataScopeSelectChange"> :label="item.label"
<el-option :value="item.value"
v-for="item in dataScopeOptions" ></el-option>
:key="item.value" </el-select>
:label="item.label" </el-form-item>
:value="item.value" <el-form-item v-show="form.dataScope === '2'" label="数据权限">
></el-option> <el-checkbox v-model="deptExpand" @change="handleCheckedTreeExpand($event, 'dept')">展开/折叠</el-checkbox>
</el-select> <el-checkbox v-model="deptNodeAll" @change="handleCheckedTreeNodeAll($event, 'dept')">
</el-form-item> 全选/全不选
<el-form-item v-show="form.dataScope === '2'" label="数据权限"> </el-checkbox>
<el-checkbox v-model="deptExpand" @change="handleCheckedTreeExpand($event, 'dept')">展开/折叠</el-checkbox> <el-checkbox v-model="form.deptCheckStrictly" @change="handleCheckedTreeConnect($event, 'dept')">
<el-checkbox v-model="deptNodeAll" @change="handleCheckedTreeNodeAll($event, 'dept')"> 父子联动
全选/全不选 </el-checkbox>
</el-checkbox> <el-tree
<el-checkbox v-model="form.deptCheckStrictly" @change="handleCheckedTreeConnect($event, 'dept')"> ref="deptRef"
父子联动 class="tree-border"
</el-checkbox> :data="deptOptions"
<el-tree show-checkbox
ref="deptRef" default-expand-all
class="tree-border" node-key="id"
:data="deptOptions" :check-strictly="!form.deptCheckStrictly"
show-checkbox empty-text="加载中请稍候"
default-expand-all :props="{ label: 'label', children: 'children' } as any"
node-key="id" ></el-tree>
:check-strictly="!form.deptCheckStrictly" </el-form-item>
empty-text="加载中请稍候" </el-tab-pane>
:props="{ label: 'label', children: 'children' } as any" <el-tab-pane label="菜单权限" name="menu">
></el-tree> <el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event, 'menu')">展开/折叠</el-checkbox>
</el-form-item> <el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event, 'menu')">
全选/全不选
</el-checkbox>
<el-checkbox v-model="form.menuCheckStrictly" @change="handleCheckedTreeConnect($event, 'menu')">
父子联动
</el-checkbox>
<el-tree
ref="menuRef"
class="tree-border"
:data="menuOptions"
show-checkbox
node-key="id"
:check-strictly="!form.menuCheckStrictly"
empty-text="加载中请稍候"
:props="{ label: 'label', children: 'children' } as any"
></el-tree>
</el-tab-pane>
</el-tabs>
</el-form> </el-form>
<template #footer> <template #footer>
<div class="dialog-footer"> <div class="dialog-footer">
@@ -281,10 +291,10 @@ import { MenuTreeOption, RoleMenuTree } from '@/api/system/menu/types';
import { import {
addRole, addRole,
changeRoleStatus, changeRoleStatus,
dataScope,
delRole, delRole,
getRole, getRole,
listRole, listRole,
updateRolePermission,
updateRole, updateRole,
deptTreeSelect deptTreeSelect
} from '@/api/system/role'; } from '@/api/system/role';
@@ -312,6 +322,11 @@ const deptExpand = ref(true);
const deptNodeAll = ref(false); const deptNodeAll = ref(false);
const deptOptions = ref<DeptTreeOption[]>([]); const deptOptions = ref<DeptTreeOption[]>([]);
const openDataScope = ref(false); const openDataScope = ref(false);
/**
* 权限分配弹窗 Tab
* data=数据权限,menu=菜单权限
*/
const permissionTab = ref<'data' | 'menu'>('data');
/** 数据范围选项*/ /** 数据范围选项*/
const dataScopeOptions = ref([ const dataScopeOptions = ref([
@@ -464,7 +479,6 @@ const reset = () => {
/** 添加角色 */ /** 添加角色 */
const handleAdd = () => { const handleAdd = () => {
reset(); reset();
getMenuTreeselect();
dialog.visible = true; dialog.visible = true;
dialog.title = '添加角色'; dialog.title = '添加角色';
}; };
@@ -475,14 +489,11 @@ const handleUpdate = async (row?: RoleVO) => {
const { data } = await getRole(roleId); const { data } = await getRole(roleId);
Object.assign(form.value, data); Object.assign(form.value, data);
form.value.roleSort = Number(form.value.roleSort); form.value.roleSort = Number(form.value.roleSort);
const res = await getRoleMenuTreeselect(roleId); // 菜单分配已迁移到“分配权限”弹窗,这里预置已有菜单,避免基础信息保存时误清空菜单权限。
const { checkedKeys } = await getRoleMenuTreeselect(roleId);
form.value.menuIds = checkedKeys;
dialog.title = '修改角色'; dialog.title = '修改角色';
dialog.visible = true; dialog.visible = true;
res.checkedKeys.forEach(v => {
nextTick(() => {
menuRef.value?.setChecked(v, true, false);
});
});
}; };
/** 根据角色ID查询菜单树结构 */ /** 根据角色ID查询菜单树结构 */
const getRoleMenuTreeselect = (roleId: string | number) => { const getRoleMenuTreeselect = (roleId: string | number) => {
@@ -568,20 +579,25 @@ const dataScopeSelectChange = (value: string) => {
}; };
/** 分配数据权限操作 */ /** 分配数据权限操作 */
const handleDataScope = async (row: RoleVO) => { const handleDataScope = async (row: RoleVO) => {
permissionTab.value = 'data';
const response = await getRole(row.roleId); const response = await getRole(row.roleId);
Object.assign(form.value, response.data); Object.assign(form.value, response.data);
const menuRes = await getRoleMenuTreeselect(row.roleId);
const res = await getRoleDeptTreeSelect(row.roleId); const res = await getRoleDeptTreeSelect(row.roleId);
openDataScope.value = true; openDataScope.value = true;
dialog.title = '分配数据权限'; dialog.title = '分配权限';
await nextTick(() => { await nextTick(() => {
menuRef.value?.setCheckedKeys(menuRes.checkedKeys);
deptRef.value?.setCheckedKeys(res.checkedKeys); deptRef.value?.setCheckedKeys(res.checkedKeys);
}); });
}; };
/** 提交按钮(数据权限) */ /** 提交按钮(数据权限) */
const submitDataScope = async () => { const submitDataScope = async () => {
if (form.value.roleId) { if (form.value.roleId) {
// 权限信息统一提交:菜单权限 + 数据权限。
form.value.menuIds = getMenuAllCheckedKeys();
form.value.deptIds = getDeptAllCheckedKeys(); form.value.deptIds = getDeptAllCheckedKeys();
await dataScope(form.value); await updateRolePermission(form.value);
modal.msgSuccess('修改成功'); modal.msgSuccess('修改成功');
openDataScope.value = false; openDataScope.value = false;
getList(); getList();
@@ -591,6 +607,8 @@ const submitDataScope = async () => {
const cancelDataScope = () => { const cancelDataScope = () => {
dataScopeRef.value?.resetFields(); dataScopeRef.value?.resetFields();
form.value = { ...initForm }; form.value = { ...initForm };
permissionTab.value = 'data';
menuRef.value?.setCheckedKeys([]);
openDataScope.value = false; openDataScope.value = false;
}; };
@@ -603,4 +621,27 @@ onMounted(() => {
@use '@/assets/styles/components/page-shell' as pageShell; @use '@/assets/styles/components/page-shell' as pageShell;
@include pageShell.table-crud-page; @include pageShell.table-crud-page;
.dialog-grid-form {
:deep(.el-form-item) {
margin-bottom: 16px;
}
:deep(.el-input-number.w-full) {
width: 100%;
}
}
.permission-dialog-form {
:deep(.el-tabs__header) {
margin-bottom: 16px;
}
:deep(.tree-border) {
max-height: 320px;
padding: 8px;
border-radius: 6px;
overflow: auto;
}
}
</style> </style>