From f7b94e496c00c1c13cd5173a8c779427cb31e11f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8C=BF=E5=B0=8F=E5=A4=A9?= <1638245306@qq.com> Date: Mon, 5 Jun 2023 22:21:19 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E2=99=BB=EF=B8=8F=20=E6=8E=88?= =?UTF-8?q?=E6=9D=83=E9=A1=B5=E9=9D=A2=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 重构授权页面 --- backend/dvadmin/system/models.py | 2 +- backend/dvadmin/system/views/menu.py | 11 +- backend/dvadmin/system/views/role_menu.py | 9 +- .../views/role_menu_button_permission.py | 114 ++++-- web/src/plugin/permission/func.permission.ts | 2 +- web/src/utils/service.ts | 12 +- web/src/views/system/role/components/api.ts | 117 ++++++ .../system/role/components/permission.vue | 377 ++++++++++++++++++ web/src/views/system/role/crud.tsx | 2 + web/src/views/system/role/index.vue | 4 +- web/src/views/system/rolePermission/index.vue | 6 +- 11 files changed, 600 insertions(+), 56 deletions(-) create mode 100644 web/src/views/system/role/components/api.ts create mode 100644 web/src/views/system/role/components/permission.vue diff --git a/backend/dvadmin/system/models.py b/backend/dvadmin/system/models.py index 392a08e..146ba0e 100644 --- a/backend/dvadmin/system/models.py +++ b/backend/dvadmin/system/models.py @@ -236,7 +236,7 @@ class RoleMenuPermission(CoreModel): db_table = table_prefix + "role_menu_permission" verbose_name = "角色菜单权限表" verbose_name_plural = verbose_name - ordering = ("-create_datetime",) + # ordering = ("-create_datetime",) class RoleMenuButtonPermission(CoreModel): diff --git a/backend/dvadmin/system/views/menu.py b/backend/dvadmin/system/views/menu.py index 028ed40..d29bb59 100644 --- a/backend/dvadmin/system/views/menu.py +++ b/backend/dvadmin/system/views/menu.py @@ -90,11 +90,16 @@ class MenuViewSet(CustomModelViewSet): def web_router(self, request): """用于前端获取当前角色的路由""" user = request.user - queryset = self.queryset.filter(status=1) - if not user.is_superuser: + is_admin = user.role.values_list('admin', flat=True) + if user.is_superuser or True in is_admin: + queryset = self.queryset.filter(status=1) + else: role_list = user.role.values_list('id', flat=True) - menu_list = RoleMenuPermission.objects.filter(role__in=role_list).values_list('menu_id') + menu_list = RoleMenuPermission.objects.filter(role__in=role_list).values_list('menu_id',flat=True) + print("role_list", role_list) + print("menu_list",menu_list) queryset = Menu.objects.filter(id__in=menu_list) + print(queryset) serializer = WebRouterSerializer(queryset, many=True, request=request) data = serializer.data return SuccessResponse(data=data, total=len(data), msg="获取成功") diff --git a/backend/dvadmin/system/views/role_menu.py b/backend/dvadmin/system/views/role_menu.py index b1e606b..4a3cc95 100644 --- a/backend/dvadmin/system/views/role_menu.py +++ b/backend/dvadmin/system/views/role_menu.py @@ -72,7 +72,14 @@ class RoleMenuPermissionViewSet(CustomModelViewSet): menu_list = body.get('menu',None) if menu_list is None: return ErrorResponse(msg="未获取到菜单参数") - data = [{"role":role_id,"menu":item} for item in menu_list] + obj_list = RoleMenuPermission.objects.filter(role__id=role_id).values_list('menu__id',flat=True) + old_set = set(obj_list) + new_set = set(menu_list) + #need_update = old_set.intersection(new_set) # 需要更新的 + need_del = old_set.difference(new_set) # 需要删除的 + need_add = new_set.difference(old_set) # 需要新增的 + RoleMenuPermission.objects.filter(role__id=role_id,menu__in=list(need_del)).delete() + data = [{"role": role_id, "menu": item} for item in list(need_add)] serializer = RoleMenuPermissionSerializer(data=data,many=True,request=request) if serializer.is_valid(raise_exception=True): serializer.save() diff --git a/backend/dvadmin/system/views/role_menu_button_permission.py b/backend/dvadmin/system/views/role_menu_button_permission.py index 224abda..c680018 100644 --- a/backend/dvadmin/system/views/role_menu_button_permission.py +++ b/backend/dvadmin/system/views/role_menu_button_permission.py @@ -6,11 +6,11 @@ @Created on: 2021/6/3 003 0:30 @Remark: 菜单按钮管理 """ -from django.db.models import F +from django.db.models import F, Subquery, OuterRef, Exists from rest_framework.decorators import action from rest_framework.permissions import IsAuthenticated -from dvadmin.system.models import RoleMenuButtonPermission, Menu, MenuButton, Dept +from dvadmin.system.models import RoleMenuButtonPermission, Menu, MenuButton, Dept, RoleMenuPermission from dvadmin.utils.json_response import DetailResponse, ErrorResponse from dvadmin.utils.serializers import CustomModelSerializer from dvadmin.utils.viewset import CustomModelViewSet @@ -66,14 +66,23 @@ class RoleMenuButtonPermissionViewSet(CustomModelViewSet): @action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated]) def role_get_menu(self, request): """根据当前用户的角色返回角色拥有的菜单""" + data = [] is_superuser = request.user.is_superuser is_admin = request.user.role.values_list('admin', flat=True) if is_superuser or True in is_admin: - queryset = Menu.objects.filter(status=1).values('id','name','parent','is_catalog') + queryset = Menu.objects.filter(status=1).values('name','parent','is_catalog',menu_id=F('id')) + for item in queryset: + btn_name = MenuButton.objects.filter(menu=item['menu_id']).values_list( + 'name', flat=True) + data.append({'menu_id': item['menu_id'], 'name': item['name'], 'parent': item['parent'], + 'permission': ','.join(btn_name), 'is_catalog': item['is_catalog']}) else: role_id = request.user.role.values_list('id',flat=True) - queryset = RoleMenuButtonPermission.objects.filter(role__in=role_id).values(id=F('menu__id'),name=F('menu__name'),parent=F('menu__parent'),is_catalog=F('menu__is_catalog')) - return DetailResponse(data=queryset) + queryset = RoleMenuPermission.objects.filter(role__in=role_id).values('menu_id',name=F('menu__name'),parent=F('menu__parent'),is_catalog=F('menu__is_catalog')).distinct() + for item in queryset: + btn_name = RoleMenuButtonPermission.objects.filter(menu_button__menu=item['menu_id']).values_list('menu_button__name',flat=True) + data.append({'menu_id':item['menu_id'], 'name':item['name'], 'parent':item['parent'],'permission':','.join(btn_name),'is_catalog':item['is_catalog']}) + return DetailResponse(data=data) @action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated]) def role_menu_get_button(self,request): @@ -82,18 +91,16 @@ class RoleMenuButtonPermissionViewSet(CustomModelViewSet): :param request: :return: """ - params = request.query_params - if params: - menu_id = params.get('menu',None) - if menu_id: + if params := request.query_params: + if menu_id := params.get('menu', None): is_superuser = request.user.is_superuser is_admin = request.user.role.values_list('admin', flat=True) if is_superuser or True in is_admin: queryset = MenuButton.objects.filter(menu=menu_id).values('id', 'name') else: role_list = request.user.role.values_list('id',flat=True) - queryset = RoleMenuButtonPermission.objects.filter(role_in=role_list,menu_button__menu=menu_id).values( - id=F('menu_button__id'), + queryset = RoleMenuButtonPermission.objects.filter(role__in=role_list,menu_button__menu=menu_id).values( + btn_id=F('menu_button__id'), name=F('menu_button__name') ) return DetailResponse(data=queryset) @@ -133,12 +140,10 @@ class RoleMenuButtonPermissionViewSet(CustomModelViewSet): return DetailResponse(data=data) else: data = [] - role_id = request.user.role.id - params = request.query_params - if params: - menu_button_id = params.get('menu_button', None) - if menu_button_id: - role_queryset = RoleMenuButtonPermission.objects.filter(role=role_id,menu_button=menu_button_id).values_list('data_range',flat=True) + role_list = request.user.role.values_list('id',flat=True) + if params := request.query_params: + if menu_button_id := params.get('menu_button', None): + role_queryset = RoleMenuButtonPermission.objects.filter(role__in=role_list,menu_button__id=menu_button_id).values_list('data_range',flat=True) data_range_list = list(set(role_queryset)) for item in data_range_list: if item == 0: @@ -202,21 +207,19 @@ class RoleMenuButtonPermissionViewSet(CustomModelViewSet): is_admin = request.user.role.values_list('admin', flat=True) if is_superuser or True in is_admin: queryset = Dept.objects.values('id','name','parent') - return DetailResponse(data=queryset) else: - if params: - menu_button = params.get('menu_button') - if menu_button is None: - return ErrorResponse(msg="参数错误") - role_list = request.user.role.values_list('id', flat=True) - queryset = RoleMenuButtonPermission.objects.filter(role_in=role_list,menu_button=None).values( - id=F('dept__id'), - name=F('dept__name'), - parent=F('dept__parent') - ) - return DetailResponse(data=queryset) - else: + if not params: return ErrorResponse(msg="参数错误") + menu_button = params.get('menu_button') + if menu_button is None: + return ErrorResponse(msg="参数错误") + role_list = request.user.role.values_list('id', flat=True) + queryset = RoleMenuButtonPermission.objects.filter(role__in=role_list,menu_button=None).values( + dept_id=F('dept__id'), + name=F('dept__name'), + parent=F('dept__parent') + ) + return DetailResponse(data=queryset) @@ -228,17 +231,48 @@ class RoleMenuButtonPermissionViewSet(CustomModelViewSet): :return: """ params = request.query_params - if params: - menu_id = params.get('menu',None) - if menu_id is None: - return ErrorResponse(msg="未获取到参数") - role_id = params.get('role', None) - if role_id is None: - return ErrorResponse(msg="未获取到参数") - queryset = RoleMenuButtonPermission.objects.filter(role=role_id,menu_button__menu=menu_id).values( + menu_id = params.get('menu', None) + if menu_id is None: + return ErrorResponse(msg="未获取到参数") + is_superuser = request.user.is_superuser + is_admin = request.user.role.values_list('admin', flat=True) + if is_superuser or True in is_admin: + queryset = RoleMenuButtonPermission.objects.filter(menu_button__menu=menu_id).values( 'id', 'data_range', - 'menu_button' + 'menu_button', + 'menu_button__name', + 'menu_button__value' ) return DetailResponse(data=queryset) - return ErrorResponse(msg="未获取到参数") \ No newline at end of file + else: + if params: + + role_id = params.get('role', None) + if role_id is None: + return ErrorResponse(msg="未获取到参数") + queryset = RoleMenuButtonPermission.objects.filter(role=role_id,menu_button__menu=menu_id).values( + 'id', + 'data_range', + 'menu_button', + 'menu_button__name', + 'menu_button__value' + ) + return DetailResponse(data=queryset) + return ErrorResponse(msg="未获取到参数") + + @action(methods=['get'], detail=False, permission_classes=[IsAuthenticated]) + def role_to_menu(self, request): + """ + 获取角色对应的按钮权限 + :param request: + :return: + """ + params = request.query_params + role_id = params.get('role', None) + if role_id is None: + return ErrorResponse(msg="未获取到参数") + queryset = RoleMenuPermission.objects.filter(role_id=role_id).values_list('menu_id',flat=True).distinct() + + return DetailResponse(data=queryset) + diff --git a/web/src/plugin/permission/func.permission.ts b/web/src/plugin/permission/func.permission.ts index 77911fa..d0a77bc 100644 --- a/web/src/plugin/permission/func.permission.ts +++ b/web/src/plugin/permission/func.permission.ts @@ -9,7 +9,7 @@ export default { return XEUtils.includeArrays(BtnPermission, value) }else if(typeof value === 'string'){ const index = XEUtils.arrayIndexOf(BtnPermission, value) - return index>0?true:false + return index>-1?true:false } } return true diff --git a/web/src/utils/service.ts b/web/src/utils/service.ts index 5694dbc..b791810 100644 --- a/web/src/utils/service.ts +++ b/web/src/utils/service.ts @@ -24,12 +24,12 @@ function createService() { serialize(params) { return qs.stringify(params, { indices: false, - encoder: (val: string) => { - if (typeof val === 'boolean') { - return val ? 1 : 0; - } - return val; - }, + // encoder: (val: string) => { + // if (typeof val === 'boolean') { + // return val ? 1 : 0; + // } + // return val; + // }, }); }, }, diff --git a/web/src/views/system/role/components/api.ts b/web/src/views/system/role/components/api.ts new file mode 100644 index 0000000..8e9abaa --- /dev/null +++ b/web/src/views/system/role/components/api.ts @@ -0,0 +1,117 @@ +import { request } from "/@/utils/service"; + +/** + * 获取角色所拥有的菜单 + * @param params + */ +export function GetMenu(params:any) { + return request({ + url: '/api/system/role_menu_button_permission/role_get_menu/', + method: 'get', + params:params + }); +} + +/*** + * 新增权限 + * @param data + * @constructor + */ +export function SaveMenuPermission(data:any) { + return request({ + url: '/api/system/role_menu_permission/save_auth/', + method: 'post', + data:data + }); +} + + +/** + * 获取菜单下的按钮 + * @param params + * @constructor + */ +export function GetMenuButton(params:any) { + return request({ + url: '/api/system/role_menu_button_permission/role_menu_get_button/', + method: 'get', + params:params + }); +} + + +/*** + * 根据角色获取已授权的菜单 + * @param params + * @constructor + */ +export function role_to_menu (params:any={}) { + return request({ + url: '/api/system/role_menu_button_permission/role_to_menu/', + method: 'get', + params: params + }) +} + +/*** + * 根据角色获取数据权限范围 + * @constructor + */ +export function GetDataScope (params:any={}) { + return request({ + url: '/api/system/role_menu_button_permission/data_scope/', + method: 'get', + params: params + }) +} + +/*** + * 获取权限部门 + * @constructor + */ +export function GetDataScopeDept (params:any) { + return request({ + url: '/api/system/role_menu_button_permission/role_to_dept_all/', + method: 'get', + params: params + }) +} + +/*** + * 新增权限 + * @param data + * @constructor + */ +export function CreatePermission(data:any) { + return request({ + url: '/api/system/role_menu_button_permission/', + method: 'post', + data:data + }); +} + +/*** + * 根据菜单获取菜单下按钮 + * @param params + */ +export function getObj(params:any) { + return request({ + url: '/api/system/role_menu_button_permission/menu_to_button/', + method: 'get', + params:params + }); +} + +/** + * 删除按钮权限 + * @param data + * @constructor + */ +export function DeletePermission(data:any) { + return request({ + url: `/api/system/role_menu_button_permission/${data.id}/`, + method: 'delete', + data:{} + }); +} + diff --git a/web/src/views/system/role/components/permission.vue b/web/src/views/system/role/components/permission.vue new file mode 100644 index 0000000..7ebc9de --- /dev/null +++ b/web/src/views/system/role/components/permission.vue @@ -0,0 +1,377 @@ + + + + + 当前角色:{{ editedRoleInfo.name }} + + + + + 保存菜单授权 + + + + + + + + 新增 + + + + + {{ scope.row.menu_button__name }} + + + + + + + {{ formatDataRange(scope.row.data_range) }} + + + + + + 删除 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 取消 + + 确定 + + + + + + + + + + + diff --git a/web/src/views/system/role/crud.tsx b/web/src/views/system/role/crud.tsx index ae1148f..896ccc6 100644 --- a/web/src/views/system/role/crud.tsx +++ b/web/src/views/system/role/crud.tsx @@ -27,6 +27,8 @@ export const createCrudOptions = function ({ crudExpose, rolePermission }: { cru //权限判定 const hasPermissions = inject("$hasPermissions") + // @ts-ignore + // @ts-ignore return { crudOptions: { request: { diff --git a/web/src/views/system/role/index.vue b/web/src/views/system/role/index.vue index fafdb61..576f725 100644 --- a/web/src/views/system/role/index.vue +++ b/web/src/views/system/role/index.vue @@ -5,7 +5,8 @@ {{ scope.row.url }} - + + @@ -14,6 +15,7 @@ import { ref, onMounted } from 'vue'; import { useExpose, useCrud, dict } from '@fast-crud/fast-crud'; import { createCrudOptions } from './crud'; import RolePermission from '/@/views/system/rolePermission/index.vue'; +import permission from './components/permission.vue' import * as api from './api'; import _ from 'lodash-es'; const rolePermission = ref(); diff --git a/web/src/views/system/rolePermission/index.vue b/web/src/views/system/rolePermission/index.vue index a46d241..bf8896f 100644 --- a/web/src/views/system/rolePermission/index.vue +++ b/web/src/views/system/rolePermission/index.vue @@ -198,7 +198,7 @@ let menuData = ref() const getMenuData = () => { api.GetMenu({}).then((res: any) => { const {data} = res - const list = XEUtils.toArrayTree(data, {parentKey: "parent", strict: true}) + const list = XEUtils.toArrayTree(data, {parentKey: "parent", key:'menu_id',strict: true}) menuData.value = list }) } @@ -212,11 +212,11 @@ const menuNodeClick = (node: any, obj: any) => { if (!node.is_catalog) { buttonOptions.value = [] editedMenuInfo.value = node - api.GetMenuButton({menu: node.id}).then((res: any) => { + api.GetMenuButton({menu: node.menu_id}).then((res: any) => { const {data} = res buttonOptions.value = data }) - api.getObj({menu: node.id, role: editedRoleInfo.value.id}).then((res: any) => { + api.getObj({menu: node.menu_id, role: editedRoleInfo.value.id}).then((res: any) => { const {data} = res buttonPermissionData.value = data })