From 94ad6b1bae9ad4e27054d13d75dece2d6f01a39a 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, 20 Nov 2023 17:02:37 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E6=9D=83?= =?UTF-8?q?=E9=99=90=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1.更新字段管理 --- backend/application/settings.py | 2 +- backend/dvadmin/system/models.py | 21 +- backend/dvadmin/system/views/column.py | 40 +- backend/dvadmin/system/views/menu.py | 3 +- backend/dvadmin/system/views/menu_button.py | 3 +- .../views/role_menu_button_permission.py | 46 ++- backend/dvadmin/utils/field_permission.py | 14 +- backend/dvadmin/utils/filters.py | 5 +- backend/dvadmin/utils/models.py | 3 +- backend/dvadmin/utils/pagination.py | 3 +- backend/dvadmin/utils/viewset.py | 13 +- web/.env.development | 2 +- .../menu/components/MenuButtonCom/crud.tsx | 2 +- .../menu/components/MenuButtonCom/index.vue | 2 +- web/src/views/system/menu/index.vue | 20 +- .../role/components/PermissionCom/api.ts | 117 ------ .../role/components/PermissionCom/index.vue | 350 ------------------ .../role/components/PermissionComCopy/api.ts | 21 -- .../components/PermissionComCopy/index.vue | 235 ------------ .../components/PermissionComCopy/types.ts | 20 - .../components/PermissionComNew/index.vue | 4 +- web/src/views/system/role/crud.tsx | 34 -- web/src/views/system/role/index.vue | 1 - 23 files changed, 116 insertions(+), 845 deletions(-) delete mode 100644 web/src/views/system/role/components/PermissionCom/api.ts delete mode 100644 web/src/views/system/role/components/PermissionCom/index.vue delete mode 100644 web/src/views/system/role/components/PermissionComCopy/api.ts delete mode 100644 web/src/views/system/role/components/PermissionComCopy/index.vue delete mode 100644 web/src/views/system/role/components/PermissionComCopy/types.ts diff --git a/backend/application/settings.py b/backend/application/settings.py index 39ca001..699b77a 100644 --- a/backend/application/settings.py +++ b/backend/application/settings.py @@ -46,7 +46,7 @@ ALLOWED_HOSTS = locals().get("ALLOWED_HOSTS", ["*"]) # Application definition CUSTOM_APPS = [ "dvadmin.system", -] + CUSTOM_APPS +] INSTALLED_APPS = [ "django.contrib.auth", diff --git a/backend/dvadmin/system/models.py b/backend/dvadmin/system/models.py index ed728ea..79eb236 100644 --- a/backend/dvadmin/system/models.py +++ b/backend/dvadmin/system/models.py @@ -13,7 +13,6 @@ class Role(CoreModel): key = models.CharField(max_length=64, unique=True, verbose_name="权限字符", help_text="权限字符") sort = models.IntegerField(default=1, verbose_name="角色顺序", help_text="角色顺序") status = models.BooleanField(default=True, verbose_name="角色状态", help_text="角色状态") - admin = models.BooleanField(default=False, verbose_name="是否为admin", help_text="是否为admin") class Meta: db_table = table_prefix + "system_role" @@ -179,21 +178,27 @@ class Menu(CoreModel): verbose_name_plural = verbose_name ordering = ("sort",) - -class Columns(CoreModel): - role = models.ForeignKey(to='Role', on_delete=models.CASCADE, verbose_name='角色', db_constraint=False) - app = models.CharField(max_length=64, verbose_name='应用名') - model = models.CharField(max_length=64, verbose_name='表名') +class MenuField(CoreModel): + model = models.CharField(max_length=64, verbose_name='表名',null=True,blank=True) menu = models.ForeignKey(to='Menu', on_delete=models.CASCADE, verbose_name='菜单', db_constraint=False) field_name = models.CharField(max_length=64, verbose_name='模型表字段名') title = models.CharField(max_length=64, verbose_name='字段显示名') + class Meta: + db_table = table_prefix + "system_menu_field" + verbose_name = "菜单字段表" + verbose_name_plural = verbose_name + ordering = ("id",) + +class FieldPermission(CoreModel): + role = models.ForeignKey(to='Role', on_delete=models.CASCADE, verbose_name='角色', db_constraint=False) + field = models.ForeignKey(to='MenuField', on_delete=models.CASCADE,related_name='menu_field', verbose_name='字段', db_constraint=False) is_query = models.BooleanField(default=1, verbose_name='是否可查询') is_create = models.BooleanField(default=1, verbose_name='是否可创建') is_update = models.BooleanField(default=1, verbose_name='是否可更新') class Meta: - db_table = table_prefix + "system_columns" - verbose_name = "列权限表" + db_table = table_prefix + "system_field_permission" + verbose_name = "字段权限表" verbose_name_plural = verbose_name ordering = ("id",) diff --git a/backend/dvadmin/system/views/column.py b/backend/dvadmin/system/views/column.py index a23d27c..993be52 100644 --- a/backend/dvadmin/system/views/column.py +++ b/backend/dvadmin/system/views/column.py @@ -1,9 +1,10 @@ # -*- coding: utf-8 -*- +from django.apps import apps from rest_framework import serializers from rest_framework.decorators import action from rest_framework.permissions import IsAuthenticated -from dvadmin.system.models import Columns, Role +from dvadmin.system.models import Role, MenuField from dvadmin.utils.models import get_custom_app_models from dvadmin.utils.viewset import CustomModelViewSet from dvadmin.utils.serializers import CustomModelSerializer @@ -16,7 +17,7 @@ class ColumnSerializer(CustomModelSerializer): """ class Meta: - model = Columns + model = MenuField fields = '__all__' read_only_fields = ['id'] @@ -25,33 +26,34 @@ class ColumnViewSet(CustomModelViewSet): """ 列权限视图集 """ - queryset = Columns.objects.all() + queryset = MenuField.objects.all() serializer_class = ColumnSerializer def list(self, request, *args, **kwargs): - role_id = request.query_params.get('role') app_name = request.query_params.get('app') model_name = request.query_params.get('model') menu = request.query_params.get('menu') - if not role_id or not model_name or not app_name or not menu: + if not menu: return SuccessResponse([]) - queryset = self.filter_queryset(self.get_queryset().filter(role_id=role_id, model=model_name, app=app_name,menu_id=menu)) - page = self.paginate_queryset(queryset) - if page is not None: - serializer = self.get_serializer(page, many=True, request=request) - return self.get_paginated_response(serializer.data) + queryset = self.filter_queryset(self.get_queryset().filter(menu=menu)) + # page = self.paginate_queryset(queryset) + # if page is not None: + # serializer = self.get_serializer(page, many=True, request=request) + # return self.get_paginated_response(serializer.data) serializer = self.get_serializer(queryset, many=True, request=request) return SuccessResponse(data=serializer.data, msg="获取成功") def create(self, request, *args, **kwargs): payload = request.data - for model in get_custom_app_models(payload.get('app')): - if payload.get('model') == model['model']: + print(11,get_custom_app_models()) + for model in apps.get_models(): + print(model.__name__) + if payload.get('model') == model.__name__: break else: return ErrorResponse(msg='模型表不存在') - if Columns.objects.filter(app=model['app'], model=model['model'], field_name=payload.get('field_name')).exists(): + if MenuField.objects.filter(menu=payload.get('menu'),model=model.__name__, field_name=payload.get('field_name')).exists(): return ErrorResponse(msg='‘%s’ 字段权限已有,不可重复创建' % payload.get('title')) return super().create(request, *args, **kwargs) @@ -72,21 +74,21 @@ class ColumnViewSet(CustomModelViewSet): @action(methods=['POST'], detail=False, permission_classes=[IsAuthenticated]) def auto_match_fields(self, request): """自动匹配已有的字段""" - role_id = request.data.get('role') + menu_id = request.data.get('menu') app_name = request.data.get('app') model_name = request.data.get('model') - if not role_id or not model_name or not app_name: - return DetailResponse([], msg='无操作') + if not menu_id or not model_name or not app_name: + return ErrorResponse( msg='参数错误') for model in get_custom_app_models(app_name): if model['model'] != model_name: continue for field in model['fields']: - if Columns.objects.filter( - role_id=role_id, app=app_name, model=model_name, field_name=field['name'] + if MenuField.objects.filter( + menu_id=menu_id, app=app_name, model=model_name, field_name=field['name'] ).exists(): continue data = { - 'role': role_id, + 'menu': menu_id, 'app': app_name, 'model': model_name, 'field_name': field['name'], diff --git a/backend/dvadmin/system/views/menu.py b/backend/dvadmin/system/views/menu.py index 6899646..7ac3c40 100644 --- a/backend/dvadmin/system/views/menu.py +++ b/backend/dvadmin/system/views/menu.py @@ -119,8 +119,7 @@ class MenuViewSet(CustomModelViewSet): def web_router(self, request): """用于前端获取当前角色的路由""" user = request.user - is_admin = user.role.values_list('admin', flat=True) - if user.is_superuser or True in is_admin: + if user.is_superuser: queryset = self.queryset.filter(status=1) else: role_list = user.role.values_list('id', flat=True) diff --git a/backend/dvadmin/system/views/menu_button.py b/backend/dvadmin/system/views/menu_button.py index 94a65ef..245b347 100644 --- a/backend/dvadmin/system/views/menu_button.py +++ b/backend/dvadmin/system/views/menu_button.py @@ -63,8 +63,7 @@ class MenuButtonViewSet(CustomModelViewSet): :return: """ is_superuser = request.user.is_superuser - is_admin = request.user.role.values_list('admin', flat=True) - if is_superuser or True in is_admin: + if is_superuser: queryset = MenuButton.objects.values_list('value',flat=True) else: role_id = request.user.role.values_list('id', flat=True) diff --git a/backend/dvadmin/system/views/role_menu_button_permission.py b/backend/dvadmin/system/views/role_menu_button_permission.py index 109b27b..a8865ca 100644 --- a/backend/dvadmin/system/views/role_menu_button_permission.py +++ b/backend/dvadmin/system/views/role_menu_button_permission.py @@ -11,7 +11,8 @@ from rest_framework import serializers from rest_framework.decorators import action from rest_framework.permissions import IsAuthenticated -from dvadmin.system.models import RoleMenuButtonPermission, Menu, MenuButton, Dept, RoleMenuPermission, Columns +from dvadmin.system.models import RoleMenuButtonPermission, Menu, MenuButton, Dept, RoleMenuPermission, FieldPermission, \ + MenuField from dvadmin.system.views.menu import MenuSerializer from dvadmin.utils.json_response import DetailResponse, ErrorResponse from dvadmin.utils.serializers import CustomModelSerializer @@ -71,12 +72,41 @@ class RoleButtonPermissionSerializer(CustomModelSerializer): model = MenuButton fields = ['id','name','value','isCheck','data_range'] -class RoleColumnsSerializer(CustomModelSerializer): +class RoleFieldPermissionSerializer(CustomModelSerializer): class Meta: - model = Columns + model = FieldPermission fields = "__all__" +class RoleMenuFieldSerializer(CustomModelSerializer): + is_query = serializers.SerializerMethodField() + is_create = serializers.SerializerMethodField() + is_update = serializers.SerializerMethodField() + + def get_is_query(self, instance): + params = self.request.query_params + queryset = instance.menu_field.filter(role=params.get('role')).first() + if queryset: + return queryset.is_query + return False + + def get_is_create(self, instance): + params = self.request.query_params + queryset = instance.menu_field.filter(role=params.get('role')).first() + if queryset: + return queryset.is_create + return False + + def get_is_update(self, instance): + params = self.request.query_params + queryset = instance.menu_field.filter(role=params.get('role')).first() + if queryset: + return queryset.is_update + return False + class Meta: + model = MenuField + fields = ['id','field_name','title','is_query','is_create','is_update'] + class RoleMenuPermissionSerializer(CustomModelSerializer): """ @@ -99,9 +129,8 @@ class RoleMenuPermissionSerializer(CustomModelSerializer): return serializer.data def get_columns(self, instance): - params = self.request.query_params - col_list = Columns.objects.filter(role__id=params.get('role'),menu__id=instance['id']) - serializer = RoleColumnsSerializer(col_list,many=True,request=self.request) + col_list = MenuField.objects.filter(menu=instance['id']) + serializer = RoleMenuFieldSerializer(col_list,many=True,request=self.request) return serializer.data @@ -165,10 +194,11 @@ class RoleMenuButtonPermissionViewSet(CustomModelViewSet): RoleMenuPermission.objects.create(role_id=pk, menu_id=menu.get('id')) for btn in menu.get('btns'): if btn.get('isCheck'): - instance = RoleMenuButtonPermission.objects.create(role_id=pk, menu_button_id=btn.get('id'),data_range=btn.get('data_range')) + data_range = btn.get('data_range',0) or 0 + instance = RoleMenuButtonPermission.objects.create(role_id=pk, menu_button_id=btn.get('id'),data_range=data_range) instance.dept.set(btn.get('dept',[])) for col in menu.get('columns'): - Columns.objects.filter(id=col.get('id')).update(is_query=col.get('is_query'),is_create=col.get('is_create'),is_update=col.get('is_update')) + FieldPermission.objects.update_or_create(role_id=pk,field_id=col.get('id'),is_query=col.get('is_query'),is_create=col.get('is_create'),is_update=col.get('is_update')) return DetailResponse(msg="授权成功") diff --git a/backend/dvadmin/utils/field_permission.py b/backend/dvadmin/utils/field_permission.py index 939381b..1c969a0 100644 --- a/backend/dvadmin/utils/field_permission.py +++ b/backend/dvadmin/utils/field_permission.py @@ -1,8 +1,9 @@ # -*- coding: utf-8 -*- +from django.db.models import F from rest_framework.decorators import action from rest_framework.permissions import IsAuthenticated -from dvadmin.system.models import Columns +from dvadmin.system.models import FieldPermission, MenuField from dvadmin.utils.json_response import DetailResponse from dvadmin.utils.models import get_custom_app_models @@ -23,16 +24,17 @@ class FieldPermissionMixin: break if finded is False: return [] - roles = request.user.role.values_list('id', flat=True) + print(266666,model) user = request.user if user.is_superuser==1: - data = Columns.objects.filter(app=model['app'], model=model['model']).values('field_name', 'is_create', 'is_query', 'is_update') + data = MenuField.objects.filter( model=model['model']).values('field_name') for item in data: item['is_create'] = True item['is_query'] = True item['is_update'] = True else: - data= Columns.objects.filter( - app=model['app'], model=model['model'],role__in=roles - ).values('field_name', 'is_create', 'is_query', 'is_update') + roles = request.user.role.values_list('id', flat=True) + data= FieldPermission.objects.filter( + field__model=model['model'],role__in=roles + ).values( 'is_create', 'is_query', 'is_update',field_name=F('field__field_name')) return DetailResponse(data=data) \ No newline at end of file diff --git a/backend/dvadmin/utils/filters.py b/backend/dvadmin/utils/filters.py index dbd921f..06dba2e 100644 --- a/backend/dvadmin/utils/filters.py +++ b/backend/dvadmin/utils/filters.py @@ -121,13 +121,12 @@ class DataLevelPermissionsFilter(BaseFilterBackend): role__status=1, menu_button__api=re_api, menu_button__method=method).values( - 'data_range', - role_admin=F('role__admin') + 'data_range' ) dataScope_list = [] # 权限范围列表 for ele in role_permission_list: # 判断用户是否为超级管理员角色/如果拥有[全部数据权限]则返回所有数据 - if ele.get("data_range") == 3 or ele.get("role_admin") == True: + if ele.get("data_range") == 3: return queryset dataScope_list.append(ele.get("data_range")) dataScope_list = list(set(dataScope_list)) diff --git a/backend/dvadmin/utils/models.py b/backend/dvadmin/utils/models.py index 4ec619d..8ea8007 100644 --- a/backend/dvadmin/utils/models.py +++ b/backend/dvadmin/utils/models.py @@ -136,10 +136,11 @@ def get_model_from_app(app_name): def get_custom_app_models(app_name=None): - """获取所有项目写的app里的models""" + """获取所有项目下的app里的models""" if app_name: return get_model_from_app(app_name) res = [] for app in settings.CUSTOM_APPS: + # print(222,get_model_from_app(app)) res.append(get_model_from_app(app)) return res diff --git a/backend/dvadmin/utils/pagination.py b/backend/dvadmin/utils/pagination.py index 52bf143..5e80e57 100644 --- a/backend/dvadmin/utils/pagination.py +++ b/backend/dvadmin/utils/pagination.py @@ -79,6 +79,5 @@ class CustomPagination(PageNumberPagination): ('total', total), ('is_next', is_next), ('is_previous', is_previous), - ('data', data), - ('permission', self.request.permission_fields) + ('data', data) ])) diff --git a/backend/dvadmin/utils/viewset.py b/backend/dvadmin/utils/viewset.py index a462003..6b47457 100644 --- a/backend/dvadmin/utils/viewset.py +++ b/backend/dvadmin/utils/viewset.py @@ -17,7 +17,7 @@ from dvadmin.utils.import_export_mixin import ExportSerializerMixin, ImportSeria from dvadmin.utils.json_response import SuccessResponse, ErrorResponse, DetailResponse from dvadmin.utils.permission import CustomPermission from dvadmin.utils.models import get_custom_app_models -from dvadmin.system.models import Columns +from dvadmin.system.models import FieldPermission, MenuField from django_restql.mixins import QueryArgumentsMixin @@ -64,7 +64,7 @@ class CustomModelViewSet(ModelViewSet, ImportSerializerMixin, ExportSerializerMi serializer_class = self.get_serializer_class() kwargs.setdefault('context', self.get_serializer_context()) # 全部以可见字段为准 - can_see = self.get_column_permission(serializer_class) + can_see = self.get_menu_field(serializer_class) # 排除掉序列化器级的字段 # sub_set = set(serializer_class._declared_fields.keys()) - set(can_see) # for field in sub_set: @@ -79,8 +79,8 @@ class CustomModelViewSet(ModelViewSet, ImportSerializerMixin, ExportSerializerMi else: return serializer_class(*args, **kwargs) - def get_column_permission(self, serializer_class): - """获取列权限""" + def get_menu_field(self, serializer_class): + """获取字段权限""" finded = False for app in get_custom_app_models(): for model in app: @@ -91,9 +91,8 @@ class CustomModelViewSet(ModelViewSet, ImportSerializerMixin, ExportSerializerMi break if finded is False: return [] - return Columns.objects.filter( - app=model['app'], model=model['model'] - ).values('field_name', 'is_create', 'is_query', 'is_update') + return MenuField.objects.filter(model=model['model'] + ).values('field_name', 'title') def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data, request=request) diff --git a/web/.env.development b/web/.env.development index 1c3ca5d..dc36b29 100644 --- a/web/.env.development +++ b/web/.env.development @@ -2,7 +2,7 @@ ENV = 'development' # 本地环境接口地址 -VITE_API_URL = 'http://127.0.0.1:8000' +VITE_API_URL = 'http://127.0.0.1:8001' # 是否启用按钮权限 VITE_PM_ENABLED = true diff --git a/web/src/views/system/menu/components/MenuButtonCom/crud.tsx b/web/src/views/system/menu/components/MenuButtonCom/crud.tsx index fe34d05..0270ad5 100644 --- a/web/src/views/system/menu/components/MenuButtonCom/crud.tsx +++ b/web/src/views/system/menu/components/MenuButtonCom/crud.tsx @@ -124,7 +124,7 @@ export const createCrudOptions = function ({ crudExpose, context }: CreateCrudOp type: 'text', search: { show: false }, column: { - width: 120, + width: 200, sortable: true, }, form: { diff --git a/web/src/views/system/menu/components/MenuButtonCom/index.vue b/web/src/views/system/menu/components/MenuButtonCom/index.vue index af2bddd..9dddaf9 100644 --- a/web/src/views/system/menu/components/MenuButtonCom/index.vue +++ b/web/src/views/system/menu/components/MenuButtonCom/index.vue @@ -1,5 +1,5 @@ - - diff --git a/web/src/views/system/role/components/PermissionComCopy/api.ts b/web/src/views/system/role/components/PermissionComCopy/api.ts deleted file mode 100644 index 9d4c590..0000000 --- a/web/src/views/system/role/components/PermissionComCopy/api.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { request } from "/@/utils/service"; - -export function getDataPermissionRange() { - return request({ - url: '/api/system/role_menu_button_permission/data_scope/', - method: 'get', - }) -} -export function getDataPermissionDept() { - return request({ - url: '/api/system/role_menu_button_permission/role_to_dept_all/', - method: 'get' - }) -} - -export function getDataPermissionMenu() { - return request({ - url: '/api/system/role_menu_button_permission/get_role_permissions/', - method: 'get' - }) -} \ No newline at end of file diff --git a/web/src/views/system/role/components/PermissionComCopy/index.vue b/web/src/views/system/role/components/PermissionComCopy/index.vue deleted file mode 100644 index 1d08e99..0000000 --- a/web/src/views/system/role/components/PermissionComCopy/index.vue +++ /dev/null @@ -1,235 +0,0 @@ - - - - - - - diff --git a/web/src/views/system/role/components/PermissionComCopy/types.ts b/web/src/views/system/role/components/PermissionComCopy/types.ts deleted file mode 100644 index 6abb63d..0000000 --- a/web/src/views/system/role/components/PermissionComCopy/types.ts +++ /dev/null @@ -1,20 +0,0 @@ -export interface DataPermissionRangeType { - label: string; - value: number; -} - -export interface CustomDataPermissionDeptType { - id: number; - name: string; - patent: number; - children: CustomDataPermissionDeptType[] -} - -export interface CustomDataPermissionMenuType { - id: number; - name: string; - is_catalog: boolean; - menuPermission: { id: number; name: string; value: string }[] | null; - columns: { id: number; name: string; title: string }[] | null; - children: CustomDataPermissionMenuType[] -} \ No newline at end of file diff --git a/web/src/views/system/role/components/PermissionComNew/index.vue b/web/src/views/system/role/components/PermissionComNew/index.vue index 0e5d159..db6f332 100644 --- a/web/src/views/system/role/components/PermissionComNew/index.vue +++ b/web/src/views/system/role/components/PermissionComNew/index.vue @@ -1,6 +1,8 @@