|
@@ -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)}")
|