Browse Source

新增代理平台菜单角色权限接口

zhuo 1 tuần trước cách đây
mục cha
commit
6618c64e2e
2 tập tin đã thay đổi với 675 bổ sung0 xóa
  1. 349 0
      AdminController/AgentMenuController.py
  2. 326 0
      AdminController/AgentRoleController.py

+ 349 - 0
AdminController/AgentMenuController.py

@@ -0,0 +1,349 @@
+"""
+@AUTHOR: zhuo
+@NAME: zhuojiaxuan
+@software: PyCharm
+@DATE: 2025/08/05 11:17
+"""
+from django.db import transaction
+from django.views.generic.base import View
+from AgentModel.models import AgentMenu, AgentRoleMenu, AgentUserRole, AgentRole
+from Ansjer.cn_config.test_settings import LOGGING
+from Object.ResponseObject import ResponseObject
+from Object.TokenObject import TokenObject
+from Service.CommonService import CommonService
+import time
+import json
+
+
+class AgentMenuView(View):
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        operation = kwargs.get('operation')
+        return self.validation(request.GET, request, operation)
+
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        operation = kwargs.get('operation')
+        return self.validation(request.POST, request, operation)
+
+    def validation(self, request_dict, request, operation):
+        language = request_dict.get('language', 'en')
+        response = ResponseObject(language, 'pc')
+
+        tko = TokenObject(request.META.get('HTTP_AUTHORIZATION'), returntpye='pc')
+        if tko.code != 0:
+            return response.json(tko.code)
+
+        response.lang = tko.lang
+        userID = tko.userID
+
+        if operation == 'getList':
+            return self.getList(userID, request_dict, response)
+        elif operation == 'doAdd':
+            return self.doAdd(userID, request_dict, response)
+        elif operation == 'doEdit':
+            return self.doEdit(userID, request_dict, response)
+        elif operation == 'doDelete':
+            return self.doDelete(userID, request_dict, response)
+        elif operation == 'getUserMenus':
+            return self.getUserMenus(userID, request_dict, response)
+        elif operation == 'getParentMenus':
+            return self.getParentMenus(userID, request_dict, response)
+        elif operation == 'getMenuDetail':
+            return self.getMenuDetail(userID, request_dict, response)
+        else:
+            return response.json(404)
+
+    #获取菜单列表
+    def getList(self, userID, request_dict, response):
+        menu_name = request_dict.get('menu_name', '')
+        pageNo = request_dict.get('pageNo', None)
+        pageSize = request_dict.get('pageSize', None)
+
+        # 如果不传分页参数,返回树形结构
+        if not pageNo or not pageSize:
+            return self.getMenuTree(userID, request_dict, response)
+
+        # 分页查询
+        page = int(pageNo)
+        line = int(pageSize)
+
+        if menu_name:
+            menu_qs = AgentMenu.objects.filter(title__contains=menu_name).order_by('sort', 'id')
+        else:
+            menu_qs = AgentMenu.objects.all().order_by('sort', 'id')
+
+        count = menu_qs.count()
+        menu_qs = menu_qs[(page - 1) * line:page * line]
+
+        list_data = []
+        for menu in menu_qs:
+            parent_name = ''
+            if menu.parentId > 0:
+                try:
+                    parent_menu = AgentMenu.objects.get(id=menu.parentId)
+                    parent_name = parent_menu.title
+                except AgentMenu.DoesNotExist:
+                    parent_name = '未知父菜单'
+
+            list_data.append({
+                'id': menu.id,
+                'parentId': menu.parentId,
+                'parentName': parent_name,
+                'path': menu.path,
+                'name': menu.name,
+                'component': menu.component,
+                'menutype': menu.menutype,
+                'menu_code': menu.menu_code,
+                'title': menu.title,
+                'icon': menu.icon,
+                'sort': menu.sort,
+                'hidden': menu.hidden,
+                'status': 1,  # 默认启用
+            })
+
+        return response.json(0, {'list': list_data, 'total': count})
+
+    # 获取可作为父菜单的菜单列表
+    def getParentMenus(self, userID, request_dict, response):
+        menus = AgentMenu.objects.filter(menutype=1).order_by('sort')  # 只有菜单类型可以作为父菜单
+        list_data = []
+        for menu in menus:
+            list_data.append({
+                'id': menu.id,
+                'title': menu.title,
+                'parentId': menu.parentId
+            })
+        return response.json(0, {'list': list_data})
+
+    # 获取菜单详情
+    def getMenuDetail(self, userID, request_dict, response):
+        menu_id = request_dict.get('id', '')
+        if not menu_id:
+            return response.json(444,  "缺少菜单ID")
+
+        try:
+            menu = AgentMenu.objects.get(id=menu_id)
+            data = {
+                'id': menu.id,
+                'parentId': menu.parentId,
+                'path': menu.path,
+                'name': menu.name,
+                'component': menu.component,
+                'menutype': menu.menutype,
+                'menu_code': menu.menu_code,
+                'title': menu.title,
+                'icon': menu.icon,
+                'sort': menu.sort,
+                'hidden': menu.hidden
+            }
+            return response.json(0, data)
+        except AgentMenu.DoesNotExist:
+            return response.json(404,  "菜单不存在")
+
+    def doAdd(self, userID, request_dict, response):
+        print(f"开始处理菜单添加 - userID: {userID}")
+
+        data_dict = CommonService.request_dict_to_dict(request_dict)
+
+        # 获取菜单类型
+        menutype = int(data_dict.get('menutype', 1))
+
+        # 根据菜单类型决定必填字段
+        required_fields = ['title', 'name', 'menutype']
+        # 仅当菜单类型为1(菜单)时,path和component为必填
+        if menutype == 1:  # 菜单类型
+            required_fields.extend(['path'])
+
+        for field in required_fields:
+            if not data_dict.get(field):
+                return response.json(444, f"缺少必填字段: {field}")
+
+        # 按钮类型(menutype=2),确保有父级菜单
+        if menutype == 2 and int(data_dict.get('parentId', 0)) == 0:
+            return response.json(500, "按钮类型必须指定父级菜单")
+
+        path = data_dict.get('path')
+        # 只有当提供了path且不为空时才检查唯一性
+        if path and AgentMenu.objects.filter(path=path).exists():
+            return response.json(500, "路径已存在,请修改后重试")
+
+        name = data_dict.get('name')
+        if AgentMenu.objects.filter(name=name).exists():
+            return response.json(500, "路由名称已存在,请修改后重试")
+
+        parent_id = int(data_dict.get('parentId', 0))
+        if parent_id > 0 and not AgentMenu.objects.filter(id=parent_id).exists():
+            return response.json(500, "父菜单不存在")
+
+        # 设置默认值
+        data_dict.setdefault('parentId', 0)
+        data_dict.setdefault('component', '')
+        data_dict.setdefault('path', '')
+        data_dict.setdefault('hidden', False)
+        data_dict.setdefault('icon', '')
+        data_dict.setdefault('sort', 0)
+        data_dict.setdefault('menu_code', '')
+
+        try:
+            with transaction.atomic():
+                menu = AgentMenu.objects.create(**data_dict)
+                print(f"菜单创建成功 - ID: {menu.id}")
+
+                # 自动给管理员角色分配新菜单权限
+                try:
+                    admin_roles = AgentRole.objects.filter(role_name__in=['admin', '管理员'])
+                    for admin_role in admin_roles:
+                        AgentRoleMenu.objects.get_or_create(
+                            role=admin_role,
+                            menu=menu
+                        )
+                    print(f"权限分配完成")
+                except Exception as e:
+                    print(f"自动分配权限失败: {str(e)}")
+
+                success_response = response.json(0, {
+                    'id': menu.id,
+                    'message': "菜单创建成功"
+                })
+                print(f"返回成功响应: {success_response}")
+                return success_response
+
+        except Exception as e:
+            print(f"菜单创建异常: {str(e)}")
+            return response.json(500, f"菜单创建失败: {str(e)}")
+
+    def doEdit(self, userID, request_dict, response):
+        print(f"开始处理菜单编辑 - userID: {userID}")
+
+        data_dict = CommonService.request_dict_to_dict(request_dict)
+
+        menu_id = data_dict.get('id')
+        if not menu_id:
+            return response.json(444, "缺少菜单ID")
+
+        if not AgentMenu.objects.filter(id=menu_id).exists():
+            return response.json(404, "菜单不存在")
+
+        # 移除id字段,避免更新主键
+        data_dict.pop('id', None)
+
+        # 获取菜单类型
+        menutype = int(data_dict.get('menutype', 1))
+
+        # 如果是按钮类型(menutype=2),确保有父级菜单
+        if menutype == 2 and int(data_dict.get('parentId', 0)) == 0:
+            return response.json(500, "按钮类型必须指定父级菜单")
+
+        path = data_dict.get('path')
+        # 只有当提供了path且不为空时才检查唯一性
+        if path and AgentMenu.objects.exclude(id=menu_id).filter(path=path).exists():
+            return response.json(500, "路径已存在,请修改后重试")
+
+        name = data_dict.get('name')
+        if name and AgentMenu.objects.exclude(id=menu_id).filter(name=name).exists():
+            return response.json(500, "路由名称已存在,请修改后重试")
+
+        parent_id = data_dict.get('parentId')
+        if parent_id and int(parent_id) == int(menu_id):
+            return response.json(500, "不能设置自己为父菜单")
+
+        # 明确处理字段类型
+        if 'parentId' in data_dict and data_dict['parentId'] is not None:
+            data_dict['parentId'] = int(data_dict['parentId'])
+
+        if 'sort' in data_dict and data_dict['sort'] is not None:
+            data_dict['sort'] = int(data_dict['sort'])
+
+        # 明确处理布尔类型字段
+        if 'hidden' in data_dict:
+            if isinstance(data_dict['hidden'], str):
+                data_dict['hidden'] = data_dict['hidden'].lower() == 'true'
+
+        # 处理菜单类型
+        if 'menutype' in data_dict and data_dict['menutype'] is not None:
+            data_dict['menutype'] = int(data_dict['menutype'])
+
+        try:
+            # 直接通过ID更新记录
+            rows_updated = AgentMenu.objects.filter(id=menu_id).update(**data_dict)
+            print(f"更新结果: {rows_updated} 行被更新")
+
+            if rows_updated:
+                return response.json(0, "菜单更新成功")
+            return response.json(500, "菜单更新失败:未找到匹配记录")
+        except Exception as e:
+            print(f"菜单更新失败: {str(e)}")
+            return response.json(500, f"菜单更新失败: {str(e)}")
+
+    def doDelete(self, userID, request_dict, response):
+        menu_id = request_dict.get('id', '')
+        if not menu_id:
+            return response.json(444, "缺少菜单ID")
+
+        try:
+            menu = AgentMenu.objects.get(id=menu_id)
+        except AgentMenu.DoesNotExist:
+            return response.json(404, "菜单不存在")
+
+        # 若有子菜单,需先删除子菜单
+        if AgentMenu.objects.filter(parentId=menu_id).exists():
+            return response.json(500, "该菜单下存在子菜单,请先删除子菜单")
+
+        try:
+            menu.delete()
+            return response.json(0, "菜单删除成功")
+        except Exception as e:
+            return response.json(500, f"菜单删除失败: {str(e)}")
+
+    def getUserMenus(self, userID, request_dict, response):
+        """获取用户菜单 """
+        try:
+            print(f"获取用户菜单 - userID: {userID}")
+
+            # 根据用户ID获取用户的角色
+            user_roles = AgentUserRole.objects.filter(user_id=userID).values_list('role_id', flat=True)
+            print(f"用户角色IDs: {list(user_roles)}")
+
+            if not user_roles:
+                print("用户没有分配角色,返回空菜单")
+                return response.json(0, {'list': []})
+
+            # 根据用户角色获取所有可访问的菜单ID
+            menu_ids = AgentRoleMenu.objects.filter(
+                role_id__in=user_roles
+            ).values_list('menu_id', flat=True).distinct()
+            print(f"用户可访问的菜单IDs: {list(menu_ids)}")
+
+            if not menu_ids:
+                print("用户角色没有分配菜单权限")
+                return response.json(0, {'list': []})
+
+            # 获取菜单数据(返回平铺结构,让前端构建树)
+            menus = AgentMenu.objects.filter(
+                id__in=menu_ids
+            ).order_by('sort', 'id')
+
+            list_data = []
+            for menu in menus:
+                list_data.append({
+                    'id': menu.id,
+                    'parentId': menu.parentId,
+                    'path': menu.path,
+                    'name': menu.name,
+                    'component': menu.component,
+                    'menutype': menu.menutype,
+                    'menu_code': menu.menu_code,
+                    'title': menu.title,
+                    'icon': menu.icon,
+                    'sort': menu.sort,
+                    'hidden': menu.hidden,
+                    'status': 1,
+                })
+            print("实际返回菜单数据:", list_data)
+            print(f"返回菜单数据: {len(list_data)} 条")
+            return response.json(0, {'list': list_data})
+
+        except Exception as e:
+            print(f"获取用户菜单失败: {str(e)}")
+            return response.json(500, f"获取用户菜单失败: {str(e)}")

+ 326 - 0
AdminController/AgentRoleController.py

@@ -0,0 +1,326 @@
+"""
+@AUTHOR: zhuo
+@NAME: zhuojiaxuan
+@software: PyCharm
+@DATE: 2025/08/05 11:17
+"""
+from django.db import transaction
+from django.db.models import Max
+from django.views.generic.base import View
+
+from AgentModel.models import AgentRole, AgentRoleMenu, AgentMenu, AgentUserRole
+from Object.ResponseObject import ResponseObject
+from Object.TokenObject import TokenObject
+from Service.CommonService import CommonService
+import time
+
+
+class AgentRoleView(View):
+    def get(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        operation = kwargs.get('operation')
+        return self.validation(request.GET, request, operation)
+
+    def post(self, request, *args, **kwargs):
+        request.encoding = 'utf-8'
+        operation = kwargs.get('operation')
+        return self.validation(request.POST, request, operation)
+
+    def validation(self, request_dict, request, operation):
+        language = request_dict.get('language', 'en')
+        response = ResponseObject(language, 'pc')
+
+        if operation == '??':
+            return response.json(0)
+        else:
+            tko = TokenObject(request.META.get('HTTP_AUTHORIZATION'), returntpye='pc')
+            if tko.code != 0:
+                return response.json(tko.code)
+            response.lang = tko.lang
+            userID = tko.userID
+
+            if operation == 'getList':
+                return self.getList(userID, request_dict, response)
+            elif operation == 'doAdd':
+                return self.doAdd(userID, request_dict, response)
+            elif operation == 'doEdit':
+                return self.doEdit(userID, request_dict, response)
+            elif operation == 'doDelete':
+                return self.doDelete(userID, request_dict, response)
+            elif operation == 'getRoleDetail':
+                return self.getRoleDetail(userID, request_dict, response)
+            elif operation == 'setPerms':
+                return self.setPerms(userID, request_dict, response)
+            elif operation == 'getMenusIds':
+                return self.getMenusIds(userID, request_dict, response)
+            elif operation == 'getAllMenusTree':
+                return self.getAllMenusTree(userID, request_dict, response)
+            elif operation == 'getUserInfo':
+                return self.getUserInfo(userID, request_dict, response)
+            else:
+                return response.json(404)
+
+    def getList(self, userID, request_dict, response):
+        """获取角色列表"""
+        isSelect = request_dict.get('isSelect', None)  # 获取全部数据作为角色选项
+        if isSelect:
+            role_qs = AgentRole.objects.all().values('rid', 'role_name', 'description')
+            return response.json(0, {'list': CommonService.qs_to_list(role_qs)})
+
+        roleName = request_dict.get('role_name', '')
+        pageNo = request_dict.get('pageNo', None)
+        pageSize = request_dict.get('pageSize', None)
+
+        if not all([pageNo, pageSize]):
+            return response.json(444,  "缺少分页参数")
+
+        page = int(pageNo)
+        line = int(pageSize)
+
+        if roleName:
+            role_qs = AgentRole.objects.filter(role_name__contains=roleName)
+        else:
+            role_qs = AgentRole.objects.all()
+
+        count = role_qs.count()
+        role_qs = role_qs.order_by('-rid')[(page - 1) * line:page * line]
+
+        list_data = []
+        for role in role_qs:
+            # 统计该角色关联的用户数和菜单数
+            user_count = AgentUserRole.objects.filter(role=role).count()
+            menu_count = AgentRoleMenu.objects.filter(role=role).count()
+
+            list_data.append({
+                'rid': role.rid,
+                'role_name': role.role_name,
+                'description': role.description,
+                'data_scope': role.data_scope,
+                'agent_type': role.agent_type,
+                'user_count': user_count,
+                'menu_count': menu_count,
+                'status': 1,  # 默认启用状态
+                'created_time': getattr(role, 'created_time', int(time.time())),
+                'updated_time': getattr(role, 'updated_time', int(time.time()))
+            })
+
+        return response.json(0, {'list': list_data, 'total': count})
+
+    def getRoleDetail(self, userID, request_dict, response):
+        """获取角色详情"""
+        rid = request_dict.get('rid', '')
+        if not rid:
+            return response.json(444,  "缺少角色ID")
+
+        try:
+            role = AgentRole.objects.get(rid=rid)
+            data = {
+                'rid': role.rid,
+                'role_name': role.role_name,
+                'description': role.description,
+                'data_scope': role.data_scope,
+                'agent_type': role.agent_type
+            }
+            return response.json(0, data)
+        except AgentRole.DoesNotExist:
+            return response.json(404,  "角色不存在")
+
+    def doAdd(self, userID, request_dict, response):
+        """新增角色"""
+        data_dict = CommonService.request_dict_to_dict(request_dict)
+
+        # 必填字段验证
+        role_name = data_dict.get('role_name', '').strip()
+        if not role_name:
+            return response.json(444,  "角色名称不能为空")
+
+        # 检查角色名是否已存在
+        if AgentRole.objects.filter(role_name=role_name).exists():
+            return response.json(500,  "角色名称已存在")
+
+        # 自动生成角色ID
+        max_rid = AgentRole.objects.aggregate(Max('rid'))['rid__max']
+        new_rid = (max_rid or 0) + 1
+
+        # 设置默认值
+        data_dict['rid'] = new_rid
+        data_dict.setdefault('description', '')
+        data_dict.setdefault('data_scope', 1)
+        data_dict.setdefault('agent_type', 1)
+
+        try:
+            role = AgentRole.objects.create(**data_dict)
+            return response.json(0, {'rid': role.rid},  "角色创建成功")
+        except Exception as e:
+            return response.json(500,  f"角色创建失败: {str(e)}")
+
+    def doEdit(self, userID, request_dict, response):
+        """编辑角色"""
+        data_dict = CommonService.request_dict_to_dict(request_dict)
+
+        rid = data_dict.get('rid')
+        if not rid:
+            return response.json(444,  "缺少角色ID")
+
+        try:
+            role = AgentRole.objects.get(rid=rid)
+        except AgentRole.DoesNotExist:
+            return response.json(404,  "角色不存在")
+
+        # 检查角色名是否已存在(排除自身)
+        role_name = data_dict.get('role_name', '').strip()
+        if role_name and AgentRole.objects.exclude(rid=rid).filter(role_name=role_name).exists():
+            return response.json(500,  "角色名称已存在")
+
+        # 移除不需要更新的字段
+        data_dict.pop('rid', None)
+
+        try:
+            AgentRole.objects.filter(rid=rid).update(**data_dict)
+            return response.json(0,  "角色更新成功")
+        except Exception as e:
+            return response.json(500,  f"角色更新失败: {str(e)}")
+
+    def doDelete(self, userID, request_dict, response):
+        """删除角色"""
+        rid = request_dict.get('rid', '')
+        if not rid:
+            return response.json(444,  "缺少角色ID")
+
+        try:
+            role = AgentRole.objects.get(rid=rid)
+        except AgentRole.DoesNotExist:
+            return response.json(404,  "角色不存在")
+
+        # 若已关联用户,需提示
+        if AgentUserRole.objects.filter(role_id=rid).exists():
+            return response.json(500,  "该角色已关联用户,不可删除")
+
+        try:
+            # 先删除角色菜单关联
+            AgentRoleMenu.objects.filter(role_id=rid).delete()
+            # 再删除角色
+            role.delete()
+            return response.json(0,  "角色删除成功")
+        except Exception as e:
+            return response.json(500,  f"角色删除失败: {str(e)}")
+
+    def getAllMenusTree(self, userID, request_dict, response):
+        """获取所有菜单的树形结构(用于权限分配)"""
+        try:
+            # 获取所有根菜单
+            root_menus = AgentMenu.objects.filter(parentId=0).order_by('sort')
+            menu_tree = []
+
+            for root_menu in root_menus:
+                menu_data = self._build_menu_tree(root_menu)
+                menu_tree.append(menu_data)
+
+            return response.json(0, {'list': menu_tree})
+        except Exception as e:
+            return response.json(500,  f"获取菜单树失败: {str(e)}")
+
+    def _build_menu_tree(self, menu):
+        """递归构建菜单树"""
+        menu_data = {
+            'id': menu.id,
+            'title': menu.title,
+            'parentId': menu.parentId,
+            'menutype': menu.menutype,
+            'sort': menu.sort
+        }
+
+        # 获取子菜单
+        children = AgentMenu.objects.filter(parentId=menu.id).order_by('sort')
+        if children.exists():
+            menu_data['children'] = []
+            for child in children:
+                child_data = self._build_menu_tree(child)
+                menu_data['children'].append(child_data)
+
+        return menu_data
+
+    def setPerms(self, userID, request_dict, response):
+        """设置角色权限"""
+        rid = request_dict.get('rid', '')
+        menu_ids = request_dict.get('menu_ids', '')
+
+        if not rid:
+            return response.json(444,  "缺少角色ID")
+
+        try:
+            role = AgentRole.objects.get(rid=rid)
+
+            with transaction.atomic():
+                # 先清空角色的所有菜单权限
+                AgentRoleMenu.objects.filter(role_id=rid).delete()
+
+                # 添加新的菜单权限
+                if menu_ids:
+                    if isinstance(menu_ids, str):
+                        menu_ids = menu_ids.split(',') if menu_ids else []
+
+                    if menu_ids:
+                        menu_objects = AgentMenu.objects.filter(id__in=menu_ids)
+
+                        role_menus = []
+                        for menu in menu_objects:
+                            role_menus.append(AgentRoleMenu(role=role, menu=menu))
+
+                        if role_menus:
+                            AgentRoleMenu.objects.bulk_create(role_menus)
+
+            return response.json(0,  "权限分配成功")
+        except AgentRole.DoesNotExist:
+            return response.json(404,  "角色不存在")
+        except Exception as e:
+            return response.json(500,  f"权限分配失败:{str(e)}")
+
+    def getMenusIds(self, userID, request_dict, response):
+        """获取角色关联的菜单ID列表"""
+        rid = request_dict.get('rid', '')
+        if not rid:
+            return response.json(444,  "缺少角色ID")
+
+        try:
+            role = AgentRole.objects.get(rid=rid)
+            # 获取角色关联的菜单ID列表
+            menu_ids = AgentRoleMenu.objects.filter(role=role).values_list('menu_id', flat=True)
+            return response.json(0, {'menu_ids': list(menu_ids)})
+        except AgentRole.DoesNotExist:
+            return response.json(404,  "角色不存在")
+        except Exception as e:
+            return response.json(500,  f"获取角色菜单失败: {str(e)}")
+
+    def getUserInfo(self, userID, request_dict, response):
+        """获取用户基本信息和角色 """
+        try:
+            print(f"获取用户信息 - userID: {userID}")
+
+            # 获取用户角色关联信息
+            user_roles = AgentUserRole.objects.filter(user_id=userID).select_related('role')
+            print(f"找到的用户角色关联: {user_roles.count()} 条")
+
+            roles = []
+            role_ids = []
+            for user_role in user_roles:
+                roles.append(user_role.role.role_name)
+                role_ids.append(user_role.role.rid)
+                print(f"角色: {user_role.role.role_name} (ID: {user_role.role.rid})")
+
+            # 如果没有找到角色,设置默认角色
+            if not roles:
+                print("用户没有分配角色,设置为默认用户")
+                roles = ["user"]
+
+            data = {
+                'user_id': userID,
+                'username': userID,
+                'roles': roles,
+                'role_ids': role_ids
+            }
+            print(f"返回用户信息: {data}")
+            return response.json(0, data)
+        except Exception as e:
+            print(f"获取用户信息失败: {str(e)}")
+            return response.json(500, f"获取用户信息失败: {str(e)}")