refactor(20241225-role): 角色权限分配优化
1、优化角色权限分配逻辑 2、采用实时保存,提高速度
This commit is contained in:
@@ -404,7 +404,7 @@ PLUGINS_URL_PATTERNS = []
|
|||||||
# ********** 一键导入插件配置开始 **********
|
# ********** 一键导入插件配置开始 **********
|
||||||
# 例如:
|
# 例如:
|
||||||
# from dvadmin_upgrade_center.settings import * # 升级中心
|
# from dvadmin_upgrade_center.settings import * # 升级中心
|
||||||
from dvadmin3_celery.settings import * # celery 异步任务
|
# from dvadmin3_celery.settings import * # celery 异步任务
|
||||||
# from dvadmin_third.settings import * # 第三方用户管理
|
# from dvadmin_third.settings import * # 第三方用户管理
|
||||||
# from dvadmin_ak_sk.settings import * # 秘钥管理管理
|
# from dvadmin_ak_sk.settings import * # 秘钥管理管理
|
||||||
# from dvadmin_tenants.settings import * # 租户管理
|
# from dvadmin_tenants.settings import * # 租户管理
|
||||||
|
|||||||
@@ -6,24 +6,20 @@
|
|||||||
@Created on: 2021/6/3 003 0:30
|
@Created on: 2021/6/3 003 0:30
|
||||||
@Remark: 菜单按钮管理
|
@Remark: 菜单按钮管理
|
||||||
"""
|
"""
|
||||||
from django.db.models import F, Subquery, OuterRef, Exists, BooleanField, Q, Case, Value, When
|
|
||||||
from django.db.models.functions import Coalesce
|
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
from rest_framework.fields import ListField
|
|
||||||
from rest_framework.permissions import IsAuthenticated
|
from rest_framework.permissions import IsAuthenticated
|
||||||
|
|
||||||
from dvadmin.system.models import RoleMenuButtonPermission, Menu, MenuButton, Dept, RoleMenuPermission, FieldPermission, \
|
from dvadmin.system.models import RoleMenuButtonPermission, Menu, Dept, MenuButton, RoleMenuPermission, \
|
||||||
MenuField
|
MenuField, FieldPermission
|
||||||
from dvadmin.system.views.menu import MenuSerializer
|
from dvadmin.utils.json_response import DetailResponse
|
||||||
from dvadmin.utils.json_response import DetailResponse, ErrorResponse
|
|
||||||
from dvadmin.utils.serializers import CustomModelSerializer
|
from dvadmin.utils.serializers import CustomModelSerializer
|
||||||
from dvadmin.utils.viewset import CustomModelViewSet
|
from dvadmin.utils.viewset import CustomModelViewSet
|
||||||
|
|
||||||
|
|
||||||
class RoleMenuButtonPermissionSerializer(CustomModelSerializer):
|
class RoleMenuButtonPermissionSerializer(CustomModelSerializer):
|
||||||
"""
|
"""
|
||||||
菜单按钮-序列化器
|
角色-菜单-按钮-权限 查询序列化
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@@ -34,7 +30,7 @@ class RoleMenuButtonPermissionSerializer(CustomModelSerializer):
|
|||||||
|
|
||||||
class RoleMenuButtonPermissionCreateUpdateSerializer(CustomModelSerializer):
|
class RoleMenuButtonPermissionCreateUpdateSerializer(CustomModelSerializer):
|
||||||
"""
|
"""
|
||||||
初始化菜单按钮-序列化器
|
角色-菜单-按钮-权限 创建/修改序列化
|
||||||
"""
|
"""
|
||||||
menu_button__name = serializers.CharField(source='menu_button.name', read_only=True)
|
menu_button__name = serializers.CharField(source='menu_button.name', read_only=True)
|
||||||
menu_button__value = serializers.CharField(source='menu_button.value', read_only=True)
|
menu_button__value = serializers.CharField(source='menu_button.value', read_only=True)
|
||||||
@@ -45,63 +41,99 @@ class RoleMenuButtonPermissionCreateUpdateSerializer(CustomModelSerializer):
|
|||||||
read_only_fields = ["id"]
|
read_only_fields = ["id"]
|
||||||
|
|
||||||
|
|
||||||
class RoleButtonPermissionSerializer(CustomModelSerializer):
|
class RoleMenuSerializer(CustomModelSerializer):
|
||||||
"""
|
"""
|
||||||
角色按钮权限
|
角色-菜单 序列化
|
||||||
"""
|
"""
|
||||||
isCheck = serializers.SerializerMethodField()
|
isCheck = serializers.SerializerMethodField()
|
||||||
data_range = serializers.SerializerMethodField()
|
|
||||||
|
|
||||||
def get_isCheck(self, instance):
|
def get_isCheck(self, instance):
|
||||||
params = self.request.query_params
|
params = self.request.query_params
|
||||||
|
data = self.request.data
|
||||||
|
return RoleMenuPermission.objects.filter(
|
||||||
|
menu_id=instance.id,
|
||||||
|
role_id=params.get('roleId', data.get('roleId')),
|
||||||
|
).exists()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Menu
|
||||||
|
fields = ["id", "name", "parent", "is_catalog", "isCheck"]
|
||||||
|
|
||||||
|
|
||||||
|
class RoleMenuButtonSerializer(CustomModelSerializer):
|
||||||
|
"""
|
||||||
|
角色-菜单-按钮 序列化
|
||||||
|
"""
|
||||||
|
isCheck = serializers.SerializerMethodField()
|
||||||
|
data_range = serializers.SerializerMethodField()
|
||||||
|
role_menu_btn_perm_id = serializers.SerializerMethodField()
|
||||||
|
dept = serializers.SerializerMethodField()
|
||||||
|
|
||||||
|
def get_isCheck(self, instance):
|
||||||
|
params = self.request.query_params
|
||||||
|
data = self.request.data
|
||||||
return RoleMenuButtonPermission.objects.filter(
|
return RoleMenuButtonPermission.objects.filter(
|
||||||
menu_button__id=instance['id'],
|
menu_button_id=instance.id,
|
||||||
role__id=params.get('role'),
|
role_id=params.get('roleId', data.get('roleId')),
|
||||||
).exists()
|
).exists()
|
||||||
|
|
||||||
def get_data_range(self, instance):
|
def get_data_range(self, instance):
|
||||||
params = self.request.query_params
|
obj = self.get_role_menu_btn_prem(instance)
|
||||||
obj = RoleMenuButtonPermission.objects.filter(
|
|
||||||
menu_button__id=instance['id'],
|
|
||||||
role__id=params.get('role'),
|
|
||||||
).first()
|
|
||||||
if obj is None:
|
if obj is None:
|
||||||
return None
|
return None
|
||||||
return obj.data_range
|
return obj.data_range
|
||||||
|
|
||||||
|
def get_role_menu_btn_perm_id(self, instance):
|
||||||
|
obj = self.get_role_menu_btn_prem(instance)
|
||||||
|
if obj is None:
|
||||||
|
return None
|
||||||
|
return obj.id
|
||||||
|
|
||||||
|
def get_dept(self, instance):
|
||||||
|
obj = self.get_role_menu_btn_prem(instance)
|
||||||
|
if obj is None:
|
||||||
|
return None
|
||||||
|
return obj.dept.all().values_list('id', flat=True)
|
||||||
|
|
||||||
|
def get_role_menu_btn_prem(self, instance):
|
||||||
|
params = self.request.query_params
|
||||||
|
data = self.request.data
|
||||||
|
obj = RoleMenuButtonPermission.objects.filter(
|
||||||
|
menu_button_id=instance.id,
|
||||||
|
role_id=params.get('roleId', data.get('roleId')),
|
||||||
|
).first()
|
||||||
|
return obj
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = MenuButton
|
model = MenuButton
|
||||||
fields = ['id', 'name', 'value', 'isCheck', 'data_range']
|
fields = ['id', 'menu', 'name', 'isCheck', 'data_range', 'role_menu_btn_perm_id', 'dept']
|
||||||
|
|
||||||
|
|
||||||
class RoleFieldPermissionSerializer(CustomModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = FieldPermission
|
|
||||||
fields = "__all__"
|
|
||||||
|
|
||||||
|
|
||||||
class RoleMenuFieldSerializer(CustomModelSerializer):
|
class RoleMenuFieldSerializer(CustomModelSerializer):
|
||||||
|
"""
|
||||||
|
角色-菜单-字段 序列化
|
||||||
|
"""
|
||||||
is_query = serializers.SerializerMethodField()
|
is_query = serializers.SerializerMethodField()
|
||||||
is_create = serializers.SerializerMethodField()
|
is_create = serializers.SerializerMethodField()
|
||||||
is_update = serializers.SerializerMethodField()
|
is_update = serializers.SerializerMethodField()
|
||||||
|
|
||||||
def get_is_query(self, instance):
|
def get_is_query(self, instance):
|
||||||
params = self.request.query_params
|
params = self.request.query_params
|
||||||
queryset = instance.menu_field.filter(role=params.get('role')).first()
|
queryset = instance.menu_field.filter(role=params.get('roleId')).first()
|
||||||
if queryset:
|
if queryset:
|
||||||
return queryset.is_query
|
return queryset.is_query
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_is_create(self, instance):
|
def get_is_create(self, instance):
|
||||||
params = self.request.query_params
|
params = self.request.query_params
|
||||||
queryset = instance.menu_field.filter(role=params.get('role')).first()
|
queryset = instance.menu_field.filter(role=params.get('roleId')).first()
|
||||||
if queryset:
|
if queryset:
|
||||||
return queryset.is_create
|
return queryset.is_create
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_is_update(self, instance):
|
def get_is_update(self, instance):
|
||||||
params = self.request.query_params
|
params = self.request.query_params
|
||||||
queryset = instance.menu_field.filter(role=params.get('role')).first()
|
queryset = instance.menu_field.filter(role=params.get('roleId')).first()
|
||||||
if queryset:
|
if queryset:
|
||||||
return queryset.is_update
|
return queryset.is_update
|
||||||
return False
|
return False
|
||||||
@@ -111,54 +143,6 @@ class RoleMenuFieldSerializer(CustomModelSerializer):
|
|||||||
fields = ['id', 'field_name', 'title', 'is_query', 'is_create', 'is_update']
|
fields = ['id', 'field_name', 'title', 'is_query', 'is_create', 'is_update']
|
||||||
|
|
||||||
|
|
||||||
class RoleMenuSerializer(CustomModelSerializer):
|
|
||||||
menus = serializers.SerializerMethodField()
|
|
||||||
|
|
||||||
def get_menus(self, instance):
|
|
||||||
menu_list = Menu.objects.filter(parent=instance['id']).values('id', 'name')
|
|
||||||
serializer = RoleMenuPermissionSerializer(menu_list, many=True, request=self.request)
|
|
||||||
return serializer.data
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = Menu
|
|
||||||
fields = ['id', 'name', 'menus']
|
|
||||||
|
|
||||||
|
|
||||||
class RoleMenuPermissionSerializer(CustomModelSerializer):
|
|
||||||
"""
|
|
||||||
菜单和按钮权限
|
|
||||||
"""
|
|
||||||
# name = serializers.SerializerMethodField()
|
|
||||||
isCheck = serializers.SerializerMethodField()
|
|
||||||
btns = serializers.SerializerMethodField()
|
|
||||||
columns = serializers.SerializerMethodField()
|
|
||||||
|
|
||||||
# def get_name(self, instance):
|
|
||||||
# parent_list = Menu.get_all_parent(instance['id'])
|
|
||||||
# names = [d["name"] for d in parent_list]
|
|
||||||
# return "/".join(names)
|
|
||||||
def get_isCheck(self, instance):
|
|
||||||
params = self.request.query_params
|
|
||||||
return RoleMenuPermission.objects.filter(
|
|
||||||
menu__id=instance['id'],
|
|
||||||
role__id=params.get('role'),
|
|
||||||
).exists()
|
|
||||||
|
|
||||||
def get_btns(self, instance):
|
|
||||||
btn_list = MenuButton.objects.filter(menu__id=instance['id']).values('id', 'name', 'value')
|
|
||||||
serializer = RoleButtonPermissionSerializer(btn_list, many=True, request=self.request)
|
|
||||||
return serializer.data
|
|
||||||
|
|
||||||
def get_columns(self, instance):
|
|
||||||
col_list = MenuField.objects.filter(menu=instance['id'])
|
|
||||||
serializer = RoleMenuFieldSerializer(col_list, many=True, request=self.request)
|
|
||||||
return serializer.data
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = Menu
|
|
||||||
fields = ['id', 'name', 'isCheck', 'btns', 'columns']
|
|
||||||
|
|
||||||
|
|
||||||
class RoleMenuButtonPermissionViewSet(CustomModelViewSet):
|
class RoleMenuButtonPermissionViewSet(CustomModelViewSet):
|
||||||
"""
|
"""
|
||||||
菜单按钮接口
|
菜单按钮接口
|
||||||
@@ -174,202 +158,103 @@ class RoleMenuButtonPermissionViewSet(CustomModelViewSet):
|
|||||||
update_serializer_class = RoleMenuButtonPermissionCreateUpdateSerializer
|
update_serializer_class = RoleMenuButtonPermissionCreateUpdateSerializer
|
||||||
extra_filter_class = []
|
extra_filter_class = []
|
||||||
|
|
||||||
# @action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
|
@action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
|
||||||
# def get_role_premission(self, request):
|
def get_role_menu(self, request):
|
||||||
# """
|
"""
|
||||||
# 角色授权获取:
|
获取 角色-菜单
|
||||||
# :param request: role
|
:param request:
|
||||||
# :return: menu,btns,columns
|
:return:
|
||||||
# """
|
"""
|
||||||
# params = request.query_params
|
menu_queryset = Menu.objects.all()
|
||||||
# is_superuser = request.user.is_superuser
|
serializer = RoleMenuSerializer(menu_queryset, many=True, request=request)
|
||||||
# if is_superuser:
|
return DetailResponse(data=serializer.data)
|
||||||
# queryset = Menu.objects.filter(status=1, is_catalog=True).values('name', 'id').all()
|
|
||||||
# else:
|
@action(methods=['PUT'], detail=False, permission_classes=[IsAuthenticated])
|
||||||
# role_id = request.user.role.values_list('id', flat=True)
|
def set_role_menu(self, request):
|
||||||
# menu_list = RoleMenuPermission.objects.filter(role__in=role_id).values_list('menu__id', flat=True)
|
"""
|
||||||
# queryset = Menu.objects.filter(status=1, is_catalog=True, id__in=menu_list).values('name', 'id').all()
|
设置 角色-菜单
|
||||||
# serializer = RoleMenuSerializer(queryset, many=True, request=request)
|
:param request:
|
||||||
# data = serializer.data
|
:return:
|
||||||
# return DetailResponse(data=data)
|
"""
|
||||||
|
data = request.data
|
||||||
|
roleId = data.get('roleId')
|
||||||
|
menuId = data.get('menuId')
|
||||||
|
isCheck = data.get('isCheck')
|
||||||
|
if isCheck:
|
||||||
|
# 添加权限:创建关联记录
|
||||||
|
instance = RoleMenuPermission.objects.create(role_id=roleId, menu_id=menuId)
|
||||||
|
else:
|
||||||
|
# 删除权限:移除关联记录
|
||||||
|
RoleMenuPermission.objects.filter(role_id=roleId, menu_id=menuId).delete()
|
||||||
|
menu_instance = Menu.objects.get(id=menuId)
|
||||||
|
serializer = RoleMenuSerializer(menu_instance, request=request)
|
||||||
|
return DetailResponse(data=serializer.data, msg="更新成功")
|
||||||
|
|
||||||
@action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
|
@action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
|
||||||
def get_role_permission(self, request):
|
def get_role_menu_btn_field(self, request):
|
||||||
|
"""
|
||||||
|
获取 角色-菜单-按钮-列字段
|
||||||
|
:param request:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
params = request.query_params
|
params = request.query_params
|
||||||
# 需要授权的角色信息
|
menuId = params.get('menuId', None)
|
||||||
current_role = params.get('role', None)
|
menu_btn_queryset = MenuButton.objects.filter(menu_id=menuId)
|
||||||
# 当前登录用户的角色
|
menu_btn_serializer = RoleMenuButtonSerializer(menu_btn_queryset, many=True, request=request)
|
||||||
role_list = request.user.role.values_list('id', flat=True)
|
menu_field_queryset = MenuField.objects.filter(menu_id=menuId)
|
||||||
if current_role is None:
|
menu_field_serializer = RoleMenuFieldSerializer(menu_field_queryset, many=True, request=request)
|
||||||
return ErrorResponse(msg='参数错误')
|
return DetailResponse(data={'menu_btn': menu_btn_serializer.data, 'menu_field': menu_field_serializer.data})
|
||||||
is_superuser = request.user.is_superuser
|
|
||||||
if is_superuser:
|
|
||||||
menu_queryset = Menu.objects.prefetch_related('menuPermission').prefetch_related(
|
|
||||||
'menufield_set')
|
|
||||||
else:
|
|
||||||
role_id_list = request.user.role.values_list('id', flat=True)
|
|
||||||
menu_list = RoleMenuPermission.objects.filter(role__in=role_id_list).values_list('menu__id', flat=True)
|
|
||||||
|
|
||||||
# 当前角色已授权的菜单
|
|
||||||
menu_queryset = Menu.objects.filter(id__in=menu_list).prefetch_related('menuPermission').prefetch_related(
|
|
||||||
'menufield_set')
|
|
||||||
result = []
|
|
||||||
for menu_item in menu_queryset:
|
|
||||||
isCheck = RoleMenuPermission.objects.filter(
|
|
||||||
menu_id=menu_item.id,
|
|
||||||
role_id=current_role
|
|
||||||
).exists()
|
|
||||||
dicts = {
|
|
||||||
'name': menu_item.name,
|
|
||||||
'id': menu_item.id,
|
|
||||||
'parent': menu_item.parent.id if menu_item.parent else None,
|
|
||||||
'isCheck': isCheck,
|
|
||||||
'btns': [],
|
|
||||||
'columns': []
|
|
||||||
}
|
|
||||||
for mb_item in menu_item.menuPermission.all():
|
|
||||||
rolemenubuttonpermission_queryset = RoleMenuButtonPermission.objects.filter(
|
|
||||||
menu_button_id=mb_item.id,
|
|
||||||
role_id=current_role
|
|
||||||
).first()
|
|
||||||
dicts['btns'].append(
|
|
||||||
{
|
|
||||||
'id': mb_item.id,
|
|
||||||
'name': mb_item.name,
|
|
||||||
'value': mb_item.value,
|
|
||||||
'data_range': rolemenubuttonpermission_queryset.data_range
|
|
||||||
if rolemenubuttonpermission_queryset
|
|
||||||
else None,
|
|
||||||
'isCheck': bool(rolemenubuttonpermission_queryset),
|
|
||||||
'dept': rolemenubuttonpermission_queryset.dept.all().values_list('id', flat=True)
|
|
||||||
if rolemenubuttonpermission_queryset
|
|
||||||
else [],
|
|
||||||
}
|
|
||||||
)
|
|
||||||
for column_item in menu_item.menufield_set.all():
|
|
||||||
# 需要授权角色已拥有的列权限
|
|
||||||
fieldpermission_queryset = column_item.menu_field.filter(role_id=current_role).first()
|
|
||||||
is_query = fieldpermission_queryset.is_query if fieldpermission_queryset else False
|
|
||||||
is_create = fieldpermission_queryset.is_create if fieldpermission_queryset else False
|
|
||||||
is_update = fieldpermission_queryset.is_update if fieldpermission_queryset else False
|
|
||||||
# 当前登录用户角色可分配的列权限
|
|
||||||
fieldpermission_queryset_disabled = column_item.menu_field.filter(role_id__in=role_list).first()
|
|
||||||
disabled_query = fieldpermission_queryset_disabled.is_query if fieldpermission_queryset_disabled else True
|
|
||||||
disabled_create = fieldpermission_queryset_disabled.is_create if fieldpermission_queryset_disabled else True
|
|
||||||
disabled_update = fieldpermission_queryset_disabled.is_update if fieldpermission_queryset_disabled else True
|
|
||||||
|
|
||||||
dicts['columns'].append({
|
|
||||||
'id': column_item.id,
|
|
||||||
'field_name': column_item.field_name,
|
|
||||||
'title': column_item.title,
|
|
||||||
'is_query': is_query,
|
|
||||||
'is_create': is_create,
|
|
||||||
'is_update': is_update,
|
|
||||||
'disabled_query': False if is_superuser else not disabled_query,
|
|
||||||
'disabled_create': False if is_superuser else not disabled_create,
|
|
||||||
'disabled_update': False if is_superuser else not disabled_update,
|
|
||||||
})
|
|
||||||
result.append(dicts)
|
|
||||||
return DetailResponse(data=result)
|
|
||||||
|
|
||||||
@action(methods=['PUT'], detail=True, permission_classes=[IsAuthenticated])
|
@action(methods=['PUT'], detail=True, permission_classes=[IsAuthenticated])
|
||||||
def set_role_premission(self, request, pk):
|
def set_role_menu_field(self, request, pk):
|
||||||
"""
|
"""
|
||||||
对角色的菜单和按钮及按钮范围授权:
|
设置 角色-菜单-列字段
|
||||||
:param request:
|
|
||||||
:param pk: role
|
|
||||||
:return:
|
|
||||||
"""
|
"""
|
||||||
body = request.data
|
data = request.data
|
||||||
RoleMenuPermission.objects.filter(role=pk).delete()
|
for col in data:
|
||||||
RoleMenuButtonPermission.objects.filter(role=pk).delete()
|
FieldPermission.objects.update_or_create(
|
||||||
for item in body:
|
role_id=pk, field_id=col.get('id'),
|
||||||
if item.get('isCheck'):
|
|
||||||
RoleMenuPermission.objects.create(role_id=pk, menu_id=item["id"])
|
|
||||||
for btn in item.get('btns'):
|
|
||||||
if btn.get('isCheck'):
|
|
||||||
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 item.get('columns'):
|
|
||||||
FieldPermission.objects.update_or_create(role_id=pk, field_id=col.get('id'),
|
|
||||||
defaults={
|
defaults={
|
||||||
'is_query': col.get('is_query'),
|
|
||||||
'is_create': col.get('is_create'),
|
'is_create': col.get('is_create'),
|
||||||
'is_update': col.get('is_update')
|
'is_update': col.get('is_update'),
|
||||||
|
'is_query': col.get('is_query'),
|
||||||
})
|
})
|
||||||
return DetailResponse(msg="授权成功")
|
|
||||||
|
|
||||||
@action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
|
return DetailResponse(data=[], msg="更新成功")
|
||||||
def role_menu_get_button(self, request):
|
|
||||||
"""
|
|
||||||
当前用户角色和菜单获取可下拉选项的按钮:角色授权页面使用
|
|
||||||
:param request:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
if params := request.query_params:
|
|
||||||
if menu_id := params.get('menu', None):
|
|
||||||
is_superuser = request.user.is_superuser
|
|
||||||
if is_superuser:
|
|
||||||
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(btn_id=F('menu_button__id'), name=F('menu_button__name'))
|
|
||||||
return DetailResponse(data=queryset)
|
|
||||||
return ErrorResponse(msg="参数错误")
|
|
||||||
|
|
||||||
@action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
|
@action(methods=['PUT'], detail=False, permission_classes=[IsAuthenticated])
|
||||||
def data_scope(self, request):
|
def set_role_menu_btn(self, request):
|
||||||
"""
|
"""
|
||||||
获取数据权限范围:角色授权页面使用
|
设置 角色-菜单-按钮
|
||||||
:param request:
|
|
||||||
:return:
|
|
||||||
"""
|
"""
|
||||||
is_superuser = request.user.is_superuser
|
data = request.data
|
||||||
if is_superuser:
|
isCheck = data.get('isCheck', None)
|
||||||
data = [
|
roleId = data.get('roleId', None)
|
||||||
{"value": 0, "label": '仅本人数据权限'},
|
btnId = data.get('btnId', None)
|
||||||
{"value": 1, "label": '本部门及以下数据权限'},
|
if isCheck:
|
||||||
{"value": 2, "label": '本部门数据权限'},
|
# 添加权限:创建关联记录
|
||||||
{"value": 3, "label": '全部数据权限'},
|
RoleMenuButtonPermission.objects.create(role_id=roleId, menu_button_id=btnId)
|
||||||
{"value": 4, "label": '自定义数据权限'}
|
|
||||||
]
|
|
||||||
return DetailResponse(data=data)
|
|
||||||
else:
|
else:
|
||||||
params = request.query_params
|
# 删除权限:移除关联记录
|
||||||
data = [{"value": 0, "label": '仅本人数据权限'}]
|
RoleMenuButtonPermission.objects.filter(role_id=roleId, menu_button_id=btnId).delete()
|
||||||
role_list = request.user.role.values_list('id', flat=True)
|
menu_btn_instance = MenuButton.objects.get(id=btnId)
|
||||||
# 权限页面进入初始化获取所有的数据权限范围
|
serializer = RoleMenuButtonSerializer(menu_btn_instance, request=request)
|
||||||
role_queryset = RoleMenuButtonPermission.objects.filter(
|
return DetailResponse(data=serializer.data, msg="更新成功")
|
||||||
role__in=role_list
|
|
||||||
).values_list('data_range', flat=True)
|
|
||||||
# 通过按钮小齿轮获取指定按钮的权限
|
|
||||||
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))
|
@action(methods=['PUT'], detail=False, permission_classes=[IsAuthenticated])
|
||||||
for item in data_range_list:
|
def set_role_menu_btn_data_range(self, request):
|
||||||
if item == 0:
|
"""
|
||||||
data = data
|
设置 角色-菜单-按钮-权限
|
||||||
elif item == 1:
|
"""
|
||||||
data.extend([
|
data = request.data
|
||||||
{"value": 1, "label": '本部门及以下数据权限'},
|
instance = RoleMenuButtonPermission.objects.get(id=data.get('role_menu_btn_perm_id'))
|
||||||
{"value": 2, "label": '本部门数据权限'}
|
instance.data_range = data.get('data_range')
|
||||||
])
|
instance.dept.add(*data.get('dept'))
|
||||||
elif item == 2:
|
if not data.get('dept'):
|
||||||
data.extend([{"value": 2, "label": '本部门数据权限'}])
|
instance.dept.clear()
|
||||||
elif item == 3:
|
instance.save()
|
||||||
data.extend([{"value": 3, "label": '全部数据权限'}])
|
serializer = RoleMenuButtonPermissionSerializer(instance, request=request)
|
||||||
elif item == 4:
|
return DetailResponse(data=serializer.data, msg="更新成功")
|
||||||
data.extend([{"value": 4, "label": '自定义数据权限'}])
|
|
||||||
else:
|
|
||||||
data = []
|
|
||||||
return DetailResponse(data=data)
|
|
||||||
|
|
||||||
@action(methods=['get'], detail=False, permission_classes=[IsAuthenticated])
|
@action(methods=['get'], detail=False, permission_classes=[IsAuthenticated])
|
||||||
def role_to_dept_all(self, request):
|
def role_to_dept_all(self, request):
|
||||||
@@ -395,55 +280,3 @@ class RoleMenuButtonPermissionViewSet(CustomModelViewSet):
|
|||||||
dept["disabled"] = False if is_superuser else dept["id"] not in dept_checked_disabled
|
dept["disabled"] = False if is_superuser else dept["id"] not in dept_checked_disabled
|
||||||
data.append(dept)
|
data.append(dept)
|
||||||
return DetailResponse(data=data)
|
return DetailResponse(data=data)
|
||||||
|
|
||||||
@action(methods=['get'], detail=False, permission_classes=[IsAuthenticated])
|
|
||||||
def menu_to_button(self, request):
|
|
||||||
"""
|
|
||||||
根据所选择菜单获取已配置的按钮/接口权限:角色授权页面使用
|
|
||||||
:param request:
|
|
||||||
:return:
|
|
||||||
"""
|
|
||||||
params = request.query_params
|
|
||||||
menu_id = params.get('menu', None)
|
|
||||||
if menu_id is None:
|
|
||||||
return ErrorResponse(msg="未获取到参数")
|
|
||||||
is_superuser = request.user.is_superuser
|
|
||||||
if is_superuser:
|
|
||||||
queryset = RoleMenuButtonPermission.objects.filter(menu_button__menu=menu_id).values(
|
|
||||||
'id',
|
|
||||||
'data_range',
|
|
||||||
'menu_button',
|
|
||||||
'menu_button__name',
|
|
||||||
'menu_button__value'
|
|
||||||
)
|
|
||||||
return DetailResponse(data=queryset)
|
|
||||||
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)
|
|
||||||
|
|||||||
@@ -1,70 +0,0 @@
|
|||||||
import { request } from "/@/utils/service";
|
|
||||||
import XEUtils from "xe-utils";
|
|
||||||
/**
|
|
||||||
* 获取角色的授权列表
|
|
||||||
* @param roleId
|
|
||||||
* @param query
|
|
||||||
*/
|
|
||||||
export function getRolePermission(query:object) {
|
|
||||||
return request({
|
|
||||||
url: '/api/system/role_menu_button_permission/get_role_permission/',
|
|
||||||
method: 'get',
|
|
||||||
params:query
|
|
||||||
}).then((res:any)=>{
|
|
||||||
return XEUtils.toArrayTree(res.data, {key: 'id', parentKey: 'parent',children: 'children',strict: false})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/***
|
|
||||||
* 设置角色的权限
|
|
||||||
* @param roleId
|
|
||||||
* @param data
|
|
||||||
*/
|
|
||||||
export function setRolePremission(roleId:any,data:object) {
|
|
||||||
return request({
|
|
||||||
url: `/api/system/role_menu_button_permission/${roleId}/set_role_premission/`,
|
|
||||||
method: 'put',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getDataPermissionRange(query:object) {
|
|
||||||
return request({
|
|
||||||
url: '/api/system/role_menu_button_permission/data_scope/',
|
|
||||||
method: 'get',
|
|
||||||
params:query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getDataPermissionRangeAll() {
|
|
||||||
return request({
|
|
||||||
url: '/api/system/role_menu_button_permission/data_scope/',
|
|
||||||
method: 'get',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
export function getDataPermissionDept(query:object) {
|
|
||||||
return request({
|
|
||||||
url: '/api/system/role_menu_button_permission/role_to_dept_all/',
|
|
||||||
method: 'get',
|
|
||||||
params:query
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getDataPermissionMenu() {
|
|
||||||
return request({
|
|
||||||
url: '/api/system/role_menu_button_permission/get_role_permissions/',
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置按钮的数据范围
|
|
||||||
*/
|
|
||||||
export function setBtnDatarange(roleId:number,data:object) {
|
|
||||||
return request({
|
|
||||||
url: `/api/system/role_menu_button_permission/${roleId}/set_btn_datarange/`,
|
|
||||||
method: 'put',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,451 +0,0 @@
|
|||||||
<template>
|
|
||||||
<el-drawer
|
|
||||||
v-model="drawerVisibleNew"
|
|
||||||
title="权限配置"
|
|
||||||
direction="rtl"
|
|
||||||
size="60%"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:before-close="handleDrawerClose"
|
|
||||||
:destroy-on-close="true"
|
|
||||||
>
|
|
||||||
<template #header>
|
|
||||||
<el-row>
|
|
||||||
<el-col :span="4">
|
|
||||||
<div>
|
|
||||||
当前授权角色:
|
|
||||||
<el-tag>{{ props.roleName }}</el-tag>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="6">
|
|
||||||
<div>
|
|
||||||
<el-button size="small" type="primary" class="pc-save-btn" @click="handleSavePermission">保存菜单授权 </el-button>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</template>
|
|
||||||
<div class="permission-com">
|
|
||||||
<el-row class="menu-el-row" :gutter="20">
|
|
||||||
<el-col :span="6">
|
|
||||||
<div class="menu-box menu-left-box">
|
|
||||||
<el-tree
|
|
||||||
ref="treeRef"
|
|
||||||
:data="menuData"
|
|
||||||
:props="defaultTreeProps"
|
|
||||||
:default-checked-keys="menuDefaultCheckedKeys"
|
|
||||||
@check="handleMenuCheck"
|
|
||||||
@node-click="handleMenuClick"
|
|
||||||
node-key="id"
|
|
||||||
check-strictly
|
|
||||||
highlight-current
|
|
||||||
show-checkbox
|
|
||||||
default-expand-all
|
|
||||||
>
|
|
||||||
</el-tree>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
|
|
||||||
<el-col :span="18">
|
|
||||||
<div class="pc-collapse-main" v-if="menuCurrent.btns && menuCurrent.btns.length > 0">
|
|
||||||
<div class="pccm-item">
|
|
||||||
<div class="menu-form-alert">配置操作功能接口权限,配置数据权限点击小齿轮</div>
|
|
||||||
<el-checkbox v-for="(btn, bIndex) in menuCurrent.btns" :key="bIndex" v-model="btn.isCheck" :label="btn.value">
|
|
||||||
<div class="btn-item">
|
|
||||||
{{ btn.data_range !== null ? `${btn.name}(${formatDataRange(btn.data_range)})` : btn.name }}
|
|
||||||
<span v-show="btn.isCheck" @click.stop.prevent="handleSettingClick(menuCurrent, btn)">
|
|
||||||
<el-icon>
|
|
||||||
<Setting />
|
|
||||||
</el-icon>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</el-checkbox>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="pccm-item" v-if="menuCurrent.columns && menuCurrent.columns.length > 0">
|
|
||||||
<div class="menu-form-alert">配置数据列字段权限</div>
|
|
||||||
<ul class="columns-list">
|
|
||||||
<li class="columns-head">
|
|
||||||
<div class="width-txt">
|
|
||||||
<span>字段</span>
|
|
||||||
</div>
|
|
||||||
<div v-for="(head, hIndex) in column.header" :key="hIndex" class="width-check">
|
|
||||||
<el-checkbox :label="head.value" @change="handleColumnChange($event, menuCurrent, head.value, head.disabled)">
|
|
||||||
<span>{{ head.label }}</span>
|
|
||||||
</el-checkbox>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li v-for="(c_item, c_index) in menuCurrent.columns" :key="c_index" class="columns-item">
|
|
||||||
<div class="width-txt">{{ c_item.title }}</div>
|
|
||||||
<div v-for="(col, cIndex) in column.header" :key="cIndex" class="width-check">
|
|
||||||
<el-checkbox v-model="c_item[col.value]" class="ci-checkout" :disabled="c_item[col.disabled]"></el-checkbox>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
|
|
||||||
<el-dialog v-model="dialogVisible" title="数据权限配置" width="400px" :close-on-click-modal="false" :before-close="handleDialogClose">
|
|
||||||
<div class="pc-dialog">
|
|
||||||
<el-select v-model="dataPermission" @change="handlePermissionRangeChange" class="dialog-select" placeholder="请选择">
|
|
||||||
<el-option v-for="item in dataPermissionRange" :key="item.value" :label="item.label" :value="item.value" />
|
|
||||||
</el-select>
|
|
||||||
<el-tree-select
|
|
||||||
v-show="dataPermission === 4"
|
|
||||||
node-key="id"
|
|
||||||
v-model="customDataPermission"
|
|
||||||
:props="defaultTreeProps"
|
|
||||||
:data="deptData"
|
|
||||||
multiple
|
|
||||||
check-strictly
|
|
||||||
:render-after-expand="false"
|
|
||||||
show-checkbox
|
|
||||||
class="dialog-tree"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<template #footer>
|
|
||||||
<div>
|
|
||||||
<el-button type="primary" @click="handleDialogConfirm"> 确定</el-button>
|
|
||||||
<el-button @click="handleDialogClose"> 取消</el-button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</el-drawer>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref, onMounted, defineProps, watch, computed, reactive } from 'vue';
|
|
||||||
import XEUtils from 'xe-utils';
|
|
||||||
import { errorNotification } from '/@/utils/message';
|
|
||||||
import { getDataPermissionRange, getDataPermissionDept, getRolePermission, setRolePremission, setBtnDatarange } from './api';
|
|
||||||
import { MenuDataType, DataPermissionRangeType, CustomDataPermissionDeptType } from './types';
|
|
||||||
import { ElMessage, ElTree } from 'element-plus';
|
|
||||||
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
roleId: {
|
|
||||||
type: Number,
|
|
||||||
default: -1,
|
|
||||||
},
|
|
||||||
roleName: {
|
|
||||||
type: String,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
drawerVisible: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const emit = defineEmits(['update:drawerVisible']);
|
|
||||||
|
|
||||||
const drawerVisibleNew = ref(false);
|
|
||||||
watch(
|
|
||||||
() => props.drawerVisible,
|
|
||||||
(val) => {
|
|
||||||
drawerVisibleNew .value = val;
|
|
||||||
getMenuBtnPermission();
|
|
||||||
getDataPermissionRangeLable();
|
|
||||||
menuCurrent.value = {};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const handleDrawerClose = () => {
|
|
||||||
emit('update:drawerVisible', false);
|
|
||||||
};
|
|
||||||
|
|
||||||
const defaultTreeProps = {
|
|
||||||
children: 'children',
|
|
||||||
label: 'name',
|
|
||||||
value: 'id',
|
|
||||||
};
|
|
||||||
|
|
||||||
let menuData = ref<MenuDataType[]>([]); // 菜单列表数据
|
|
||||||
let menuDefaultCheckedKeys = ref<number[]>([]); // 默认选中的菜单列表
|
|
||||||
let menuCurrent = ref<Partial<MenuDataType>>({}); // 当前选中的菜单
|
|
||||||
|
|
||||||
let menuBtnCurrent = ref<number>(-1);
|
|
||||||
let dialogVisible = ref(false);
|
|
||||||
let dataPermissionRange = ref<DataPermissionRangeType[]>([]);
|
|
||||||
let dataPermissionRangeLabel = ref<DataPermissionRangeType[]>([]);
|
|
||||||
|
|
||||||
const formatDataRange = computed(() => {
|
|
||||||
return function (datarange: number) {
|
|
||||||
const findItem = dataPermissionRangeLabel.value.find((i) => i.value === datarange);
|
|
||||||
return findItem?.label || '';
|
|
||||||
};
|
|
||||||
});
|
|
||||||
let deptData = ref<CustomDataPermissionDeptType[]>([]);
|
|
||||||
let dataPermission = ref();
|
|
||||||
let customDataPermission = ref([]);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 菜单复选框选中
|
|
||||||
* @param node
|
|
||||||
* @param data
|
|
||||||
*/
|
|
||||||
const handleMenuCheck = (node: any, data: any) => {
|
|
||||||
XEUtils.eachTree(menuData.value, (item) => {
|
|
||||||
item.isCheck = data.checkedKeys.includes(item.id);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
* 菜单点击
|
|
||||||
* @param node
|
|
||||||
* @param data
|
|
||||||
*/
|
|
||||||
const handleMenuClick = (selectNode: MenuDataType) => {
|
|
||||||
menuCurrent.value = selectNode;
|
|
||||||
};
|
|
||||||
//获取菜单,按钮,权限
|
|
||||||
const getMenuBtnPermission = async () => {
|
|
||||||
const resMenu = await getRolePermission({ role: props.roleId });
|
|
||||||
menuData.value = resMenu;
|
|
||||||
menuDefaultCheckedKeys.value = XEUtils.toTreeArray(resMenu)
|
|
||||||
.filter((i) => i.isCheck)
|
|
||||||
.map((i) => i.id);
|
|
||||||
};
|
|
||||||
// 获取按钮的数据权限下拉选项
|
|
||||||
const getDataPermissionRangeLable = async () => {
|
|
||||||
const resRange = await getDataPermissionRange({ role: props.roleId });
|
|
||||||
dataPermissionRangeLabel.value = resRange.data;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取按钮数据权限下拉选项
|
|
||||||
* @param btnId 按钮id
|
|
||||||
*/
|
|
||||||
const fetchData = async (btnId: number) => {
|
|
||||||
try {
|
|
||||||
const resRange = await getDataPermissionRange({ menu_button: btnId });
|
|
||||||
if (resRange?.code === 2000) {
|
|
||||||
dataPermissionRange.value = resRange.data;
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置按钮数据权限
|
|
||||||
* @param record 当前菜单
|
|
||||||
* @param btnType 按钮类型
|
|
||||||
*/
|
|
||||||
const handleSettingClick = (record: any, btn: MenuDataType['btns'][number]) => {
|
|
||||||
menuCurrent.value = record;
|
|
||||||
menuBtnCurrent.value = btn.id;
|
|
||||||
dialogVisible.value = true;
|
|
||||||
dataPermission.value = btn.data_range;
|
|
||||||
handlePermissionRangeChange(btn.data_range);
|
|
||||||
fetchData(btn.id);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置列权限
|
|
||||||
* @param val 是否选中
|
|
||||||
* @param record 当前菜单
|
|
||||||
* @param btnType 按钮类型
|
|
||||||
* @param disabledType 禁用类型
|
|
||||||
*/
|
|
||||||
const handleColumnChange = (val: boolean, record: any, btnType: string, disabledType: string) => {
|
|
||||||
for (const iterator of record.columns) {
|
|
||||||
iterator[btnType] = iterator[disabledType] ? iterator[btnType] : val;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 数据权限设置
|
|
||||||
*/
|
|
||||||
const handlePermissionRangeChange = async (val: number) => {
|
|
||||||
if (val === 4) {
|
|
||||||
const res = await getDataPermissionDept({ role: props.roleId, menu_button: menuBtnCurrent.value });
|
|
||||||
const depts = XEUtils.toArrayTree(res.data, { parentKey: 'parent', strict: false });
|
|
||||||
deptData.value = depts;
|
|
||||||
const btnObj = XEUtils.find(menuCurrent.value.btns, (item) => item.id === menuBtnCurrent.value);
|
|
||||||
customDataPermission.value = btnObj.dept;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 数据权限设置确认
|
|
||||||
*/
|
|
||||||
const handleDialogConfirm = () => {
|
|
||||||
if (dataPermission.value !== 0 && !dataPermission.value) {
|
|
||||||
errorNotification('请选择');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (const btn of menuCurrent.value?.btns || []) {
|
|
||||||
if (btn.id === menuBtnCurrent.value) {
|
|
||||||
const findItem = dataPermissionRange.value.find((i) => i.value === dataPermission.value);
|
|
||||||
btn.data_range = findItem?.value || 0;
|
|
||||||
if (btn.data_range === 4) {
|
|
||||||
btn.dept = customDataPermission.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
handleDialogClose();
|
|
||||||
};
|
|
||||||
const handleDialogClose = () => {
|
|
||||||
dialogVisible.value = false;
|
|
||||||
customDataPermission.value = [];
|
|
||||||
dataPermission.value = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
//保存菜单授权
|
|
||||||
const handleSavePermission = () => {
|
|
||||||
setRolePremission(props.roleId, XEUtils.toTreeArray(menuData.value)).then((res: any) => {
|
|
||||||
ElMessage({
|
|
||||||
message: res.msg,
|
|
||||||
type: 'success',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const column = reactive({
|
|
||||||
header: [
|
|
||||||
{ value: 'is_create', label: '新增可见', disabled: 'disabled_create' },
|
|
||||||
{ value: 'is_update', label: '编辑可见', disabled: 'disabled_update' },
|
|
||||||
{ value: 'is_query', label: '列表可见', disabled: 'disabled_query' },
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
onMounted(() => {});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.permission-com {
|
|
||||||
margin: 15px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
|
|
||||||
.pc-save-btn {
|
|
||||||
margin-bottom: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pc-collapse-title {
|
|
||||||
line-height: 32px;
|
|
||||||
text-align: left;
|
|
||||||
|
|
||||||
span {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.pc-collapse-main {
|
|
||||||
box-sizing: border-box;
|
|
||||||
|
|
||||||
.pccm-item {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
|
|
||||||
.menu-form-alert {
|
|
||||||
color: #fff;
|
|
||||||
line-height: 24px;
|
|
||||||
padding: 8px 16px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
border-radius: 4px;
|
|
||||||
background-color: var(--el-color-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
span {
|
|
||||||
margin-left: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.columns-list {
|
|
||||||
.width-txt {
|
|
||||||
width: 200px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.width-check {
|
|
||||||
width: 100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.width-icon {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.columns-head {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 6px 0;
|
|
||||||
border-bottom: 1px solid #ebeef5;
|
|
||||||
box-sizing: border-box;
|
|
||||||
|
|
||||||
span {
|
|
||||||
font-weight: 900;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.columns-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 6px 0;
|
|
||||||
box-sizing: border-box;
|
|
||||||
|
|
||||||
.ci-checkout {
|
|
||||||
height: auto !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.pc-dialog {
|
|
||||||
.dialog-select {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dialog-tree {
|
|
||||||
width: 100%;
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.permission-com {
|
|
||||||
.el-collapse {
|
|
||||||
border-top: none;
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-collapse-item {
|
|
||||||
margin-bottom: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-collapse-item__header {
|
|
||||||
height: auto;
|
|
||||||
padding: 15px;
|
|
||||||
border-radius: 8px;
|
|
||||||
border-top: 1px solid #ebeef5;
|
|
||||||
border-left: 1px solid #ebeef5;
|
|
||||||
border-right: 1px solid #ebeef5;
|
|
||||||
box-sizing: border-box;
|
|
||||||
background-color: #fafafa;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-collapse-item__header.is-active {
|
|
||||||
border-radius: 8px 8px 0 0;
|
|
||||||
background-color: #fafafa;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-collapse-item__wrap {
|
|
||||||
padding: 15px;
|
|
||||||
border-left: 1px solid #ebeef5;
|
|
||||||
border-right: 1px solid #ebeef5;
|
|
||||||
border-top: 1px solid #ebeef5;
|
|
||||||
border-radius: 0 0 8px 8px;
|
|
||||||
background-color: #fafafa;
|
|
||||||
box-sizing: border-box;
|
|
||||||
|
|
||||||
.el-collapse-item__content {
|
|
||||||
padding-bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,29 +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[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface MenuDataType {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
isCheck: boolean;
|
|
||||||
btns: { id: number; name: string; value: string; isCheck: boolean; data_range: number; dept: object }[];
|
|
||||||
columns: { [key: string]: boolean | string; }[];
|
|
||||||
children: MenuDataType[];
|
|
||||||
}
|
|
||||||
@@ -1,25 +1,16 @@
|
|||||||
import {CrudOptions, AddReq, DelReq, EditReq, dict, CrudExpose, compute} from '@fast-crud/fast-crud';
|
import { CreateCrudOptionsProps, CreateCrudOptionsRet, AddReq, DelReq, EditReq, dict, compute } from '@fast-crud/fast-crud';
|
||||||
import * as api from './api';
|
import * as api from './api';
|
||||||
import { dictionary } from '/@/utils/dictionary';
|
import { dictionary } from '/@/utils/dictionary';
|
||||||
import {columnPermission} from '../../../utils/columnPermission';
|
|
||||||
import { successMessage } from '../../../utils/message';
|
import { successMessage } from '../../../utils/message';
|
||||||
import {auth} from '/@/utils/authFunction'
|
import { auth } from '/@/utils/authFunction';
|
||||||
|
|
||||||
interface CreateCrudOptionsTypes {
|
/**
|
||||||
output: any;
|
*
|
||||||
crudOptions: CrudOptions;
|
* @param crudExpose:index传递过来的示例
|
||||||
}
|
* @param context:index传递过来的自定义参数
|
||||||
|
* @returns
|
||||||
//此处为crudOptions配置
|
*/
|
||||||
export const createCrudOptions = function ({
|
export const createCrudOptions = function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||||
crudExpose,
|
|
||||||
rolePermission,
|
|
||||||
handleDrawerOpen,
|
|
||||||
}: {
|
|
||||||
crudExpose: CrudExpose;
|
|
||||||
rolePermission: any;
|
|
||||||
handleDrawerOpen: Function;
|
|
||||||
}): CreateCrudOptionsTypes {
|
|
||||||
const pageRequest = async (query: any) => {
|
const pageRequest = async (query: any) => {
|
||||||
return await api.GetList(query);
|
return await api.GetList(query);
|
||||||
};
|
};
|
||||||
@@ -34,10 +25,6 @@ export const createCrudOptions = function ({
|
|||||||
return await api.AddObj(form);
|
return await api.AddObj(form);
|
||||||
};
|
};
|
||||||
|
|
||||||
//权限判定
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
// @ts-ignore
|
|
||||||
return {
|
return {
|
||||||
crudOptions: {
|
crudOptions: {
|
||||||
request: {
|
request: {
|
||||||
@@ -47,14 +34,14 @@ export const createCrudOptions = function ({
|
|||||||
delRequest,
|
delRequest,
|
||||||
},
|
},
|
||||||
pagination: {
|
pagination: {
|
||||||
show: true
|
show: true,
|
||||||
},
|
},
|
||||||
actionbar: {
|
actionbar: {
|
||||||
buttons: {
|
buttons: {
|
||||||
add: {
|
add: {
|
||||||
show: auth('role:Create')
|
show: auth('role:Create'),
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
rowHandle: {
|
rowHandle: {
|
||||||
//固定右侧
|
//固定右侧
|
||||||
@@ -74,13 +61,11 @@ export const createCrudOptions = function ({
|
|||||||
type: 'primary',
|
type: 'primary',
|
||||||
text: '权限配置',
|
text: '权限配置',
|
||||||
show: auth('role:Permission'),
|
show: auth('role:Permission'),
|
||||||
tooltip: {
|
click: (clickContext: any): void => {
|
||||||
placement: 'top',
|
const { row } = clickContext;
|
||||||
content: '权限配置',
|
context.RoleDrawer.handleDrawerOpen(row);
|
||||||
},
|
context.RoleMenuBtn.setState([]);
|
||||||
click: (context: any): void => {
|
context.RoleMenuField.setState([]);
|
||||||
const {row} = context;
|
|
||||||
handleDrawerOpen(row);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -106,14 +91,12 @@ export const createCrudOptions = function ({
|
|||||||
},
|
},
|
||||||
id: {
|
id: {
|
||||||
title: 'ID',
|
title: 'ID',
|
||||||
type: 'text',
|
|
||||||
column: { show: false },
|
column: { show: false },
|
||||||
search: { show: false },
|
search: { show: false },
|
||||||
form: { show: false },
|
form: { show: false },
|
||||||
},
|
},
|
||||||
name: {
|
name: {
|
||||||
title: '角色名称',
|
title: '角色名称',
|
||||||
type: 'text',
|
|
||||||
search: { show: true },
|
search: { show: true },
|
||||||
column: {
|
column: {
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
@@ -128,7 +111,6 @@ export const createCrudOptions = function ({
|
|||||||
},
|
},
|
||||||
key: {
|
key: {
|
||||||
title: '权限标识',
|
title: '权限标识',
|
||||||
type: 'text',
|
|
||||||
search: { show: false },
|
search: { show: false },
|
||||||
column: {
|
column: {
|
||||||
minWidth: 120,
|
minWidth: 120,
|
||||||
@@ -142,9 +124,9 @@ export const createCrudOptions = function ({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
valueBuilder(context) {
|
valueBuilder(context) {
|
||||||
const {row, key} = context
|
const { row, key } = context;
|
||||||
return row[key]
|
return row[key];
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
sort: {
|
sort: {
|
||||||
title: '排序',
|
title: '排序',
|
||||||
@@ -180,9 +162,9 @@ export const createCrudOptions = function ({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
dict: dict({
|
dict: dict({
|
||||||
data: dictionary('button_status_bool'),
|
value: dictionary('button_status_bool'),
|
||||||
}),
|
}),
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,69 +1,31 @@
|
|||||||
<template>
|
<template>
|
||||||
<fs-page>
|
<fs-page>
|
||||||
<fs-crud ref="crudRef" v-bind="crudBinding">
|
<fs-crud ref="crudRef" v-bind="crudBinding"> </fs-crud>
|
||||||
<template #cell_url="scope">
|
<PermissionDrawerCom ref="PermissionDrawerCom" />
|
||||||
<el-tag size="small">{{ scope.row.url }}</el-tag>
|
|
||||||
</template>
|
|
||||||
</fs-crud>
|
|
||||||
|
|
||||||
<permission ref="rolePermission"></permission>
|
|
||||||
|
|
||||||
<PermissionComNew v-model:drawerVisible="drawerVisible" :roleId="roleId" :roleName="roleName" @drawerClose="handleDrawerClose" />
|
|
||||||
</fs-page>
|
</fs-page>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup name="role">
|
<script lang="ts" setup name="role">
|
||||||
import {ref, onMounted, inject, onBeforeUpdate} from 'vue';
|
import { defineAsyncComponent, onMounted } from 'vue';
|
||||||
|
import { useFs } from '@fast-crud/fast-crud';
|
||||||
import { GetPermission } from './api';
|
|
||||||
import { useExpose, useCrud } from '@fast-crud/fast-crud';
|
|
||||||
import { createCrudOptions } from './crud';
|
import { createCrudOptions } from './crud';
|
||||||
import PermissionComNew from './components/PermissionComNew/index.vue';
|
import { RoleDrawerStores } from './stores/RoleDrawerStores';
|
||||||
import _ from "lodash-es";
|
import { RoleMenuBtnStores } from './stores/RoleMenuBtnStores';
|
||||||
import {handleColumnPermission} from "/@/utils/columnPermission";
|
import { RoleMenuFieldStores } from './stores/RoleMenuFieldStores';
|
||||||
let drawerVisible = ref(false);
|
|
||||||
let roleId = ref(null);
|
|
||||||
let roleName = ref(null);
|
|
||||||
|
|
||||||
const rolePermission = ref();
|
const PermissionDrawerCom = defineAsyncComponent(() => import('./components/RoleDrawer.vue'));
|
||||||
// crud组件的ref
|
|
||||||
const crudRef = ref();
|
|
||||||
// crud 配置的ref
|
|
||||||
const crudBinding = ref();
|
|
||||||
|
|
||||||
|
const RoleDrawer = RoleDrawerStores(); // 权限配置抽屉参数
|
||||||
const handleDrawerOpen = (row: any) => {
|
const RoleMenuBtn = RoleMenuBtnStores(); // 角色-菜单
|
||||||
roleId.value = row.id;
|
const RoleMenuField = RoleMenuFieldStores();
|
||||||
roleName.value = row.name;
|
const { crudBinding, crudRef, crudExpose } = useFs({
|
||||||
drawerVisible.value = true;
|
createCrudOptions,
|
||||||
};
|
context: { RoleDrawer, RoleMenuBtn,RoleMenuField },
|
||||||
|
|
||||||
const handleDrawerClose = () => {
|
|
||||||
drawerVisible.value = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
const { crudExpose } = useExpose({ crudRef, crudBinding });
|
|
||||||
|
|
||||||
// 你的crud配置
|
|
||||||
const { crudOptions } = createCrudOptions({ crudExpose, rolePermission, handleDrawerOpen });
|
|
||||||
|
|
||||||
// 初始化crud配置
|
|
||||||
const { resetCrudOptions } = useCrud({
|
|
||||||
crudExpose,
|
|
||||||
crudOptions,
|
|
||||||
context: {},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 页面打开后获取列表数据
|
// 页面打开后获取列表数据
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
|
// 刷新
|
||||||
const newOptions = await handleColumnPermission(GetPermission,crudOptions)
|
|
||||||
|
|
||||||
|
|
||||||
//重置crudBinding
|
|
||||||
//resetCrudOptions(newOptions);
|
|
||||||
crudExpose.doRefresh();
|
crudExpose.doRefresh();
|
||||||
});
|
});
|
||||||
|
|
||||||
defineExpose(rolePermission);
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,14 +1,4 @@
|
|||||||
import { CrudOptions, CrudExpose } from '@fast-crud/fast-crud';
|
/**角色列表数据类型 */
|
||||||
|
|
||||||
export interface CreateCrudReturnTypes {
|
|
||||||
crudOptions: CrudOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface CreateCrudOptionsTypes {
|
|
||||||
crudExpose: CrudExpose;
|
|
||||||
configPermission: Function;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RoleItemType {
|
export interface RoleItemType {
|
||||||
id: string | number;
|
id: string | number;
|
||||||
modifier_name: string;
|
modifier_name: string;
|
||||||
@@ -25,3 +15,74 @@ export interface RoleItemType {
|
|||||||
admin: boolean;
|
admin: boolean;
|
||||||
creator: string;
|
creator: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 权限配置 抽屉组件参数数据类型
|
||||||
|
*/
|
||||||
|
export interface RoleDrawerType {
|
||||||
|
/** 是否显示抽屉*/
|
||||||
|
drawerVisible: boolean;
|
||||||
|
/** 角色id*/
|
||||||
|
roleId: string | number | undefined;
|
||||||
|
/** 角色名称*/
|
||||||
|
roleName: string | undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 菜单数据类型
|
||||||
|
*/
|
||||||
|
export interface RoleMenuTreeType {
|
||||||
|
id: number | string | undefined;
|
||||||
|
/** 父级id */
|
||||||
|
parent: number | string | undefined;
|
||||||
|
name: string;
|
||||||
|
/** 是否选中 */
|
||||||
|
isCheck: boolean;
|
||||||
|
/** 是否是目录 */
|
||||||
|
is_catalog: boolean;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 菜单-按钮数据类型
|
||||||
|
*/
|
||||||
|
export interface RoleMenuBtnType {
|
||||||
|
id: string | number;
|
||||||
|
menu_btn_pre_id: string | number;
|
||||||
|
/** 是否选中 */
|
||||||
|
isCheck: boolean;
|
||||||
|
/** 按钮名称 */
|
||||||
|
name: string;
|
||||||
|
/** 数据权限范围 */
|
||||||
|
data_range: number | null;
|
||||||
|
/** 自定义部门 */
|
||||||
|
dept: number[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 菜单-列字段数据类型
|
||||||
|
*/
|
||||||
|
export interface RoleMenuFieldType {
|
||||||
|
id: string | number | boolean;
|
||||||
|
/** 模型表字段名 */
|
||||||
|
field_name: string;
|
||||||
|
/** 字段显示名 */
|
||||||
|
title: string;
|
||||||
|
/** 是否可查询 */
|
||||||
|
is_query: boolean;
|
||||||
|
/** 是否可创建 */
|
||||||
|
is_create: boolean;
|
||||||
|
/** 是否可更新 */
|
||||||
|
is_update: boolean;
|
||||||
|
[key: string]: string | number | boolean;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 菜单-列字段-标题数据类型
|
||||||
|
*/
|
||||||
|
export interface RoleMenuFieldHeaderType {
|
||||||
|
value: string;
|
||||||
|
/** 模型表字段名 */
|
||||||
|
label: string;
|
||||||
|
/** 字段显示名 */
|
||||||
|
disabled: string ;
|
||||||
|
/** 是否可查询 */
|
||||||
|
checked: boolean;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user