AgentMenuController.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. """
  2. @AUTHOR: zhuo
  3. @NAME: zhuojiaxuan
  4. @software: PyCharm
  5. @DATE: 2025/08/05 11:17
  6. """
  7. from django.db import transaction
  8. from django.views.generic.base import View
  9. from AgentModel.models import AgentMenu, AgentRoleMenu, AgentUserRole, AgentRole
  10. from Ansjer.cn_config.test_settings import LOGGING
  11. from Object.ResponseObject import ResponseObject
  12. from Object.TokenObject import TokenObject
  13. from Service.CommonService import CommonService
  14. import time
  15. import json
  16. class AgentMenuView(View):
  17. def get(self, request, *args, **kwargs):
  18. request.encoding = 'utf-8'
  19. operation = kwargs.get('operation')
  20. return self.validation(request.GET, request, operation)
  21. def post(self, request, *args, **kwargs):
  22. request.encoding = 'utf-8'
  23. operation = kwargs.get('operation')
  24. return self.validation(request.POST, request, operation)
  25. def validation(self, request_dict, request, operation):
  26. language = request_dict.get('language', 'en')
  27. response = ResponseObject(language, 'pc')
  28. tko = TokenObject(request.META.get('HTTP_AUTHORIZATION'), returntpye='pc')
  29. if tko.code != 0:
  30. return response.json(tko.code)
  31. response.lang = tko.lang
  32. userID = tko.userID
  33. if operation == 'getList':
  34. return self.getList(userID, request_dict, response)
  35. elif operation == 'doAdd':
  36. return self.doAdd(userID, request_dict, response)
  37. elif operation == 'doEdit':
  38. return self.doEdit(userID, request_dict, response)
  39. elif operation == 'doDelete':
  40. return self.doDelete(userID, request_dict, response)
  41. elif operation == 'getUserMenus':
  42. return self.getUserMenus(userID, request_dict, response)
  43. elif operation == 'getParentMenus':
  44. return self.getParentMenus(userID, request_dict, response)
  45. elif operation == 'getMenuDetail':
  46. return self.getMenuDetail(userID, request_dict, response)
  47. else:
  48. return response.json(404)
  49. #获取菜单列表
  50. def getList(self, userID, request_dict, response):
  51. menu_name = request_dict.get('menu_name', '')
  52. pageNo = request_dict.get('pageNo', None)
  53. pageSize = request_dict.get('pageSize', None)
  54. # 如果不传分页参数,返回树形结构
  55. if not pageNo or not pageSize:
  56. return self.getMenuTree(userID, request_dict, response)
  57. # 分页查询
  58. page = int(pageNo)
  59. line = int(pageSize)
  60. if menu_name:
  61. menu_qs = AgentMenu.objects.filter(title__contains=menu_name).order_by('sort', 'id')
  62. else:
  63. menu_qs = AgentMenu.objects.all().order_by('sort', 'id')
  64. count = menu_qs.count()
  65. menu_qs = menu_qs[(page - 1) * line:page * line]
  66. list_data = []
  67. for menu in menu_qs:
  68. parent_name = ''
  69. if menu.parentId > 0:
  70. try:
  71. parent_menu = AgentMenu.objects.get(id=menu.parentId)
  72. parent_name = parent_menu.title
  73. except AgentMenu.DoesNotExist:
  74. parent_name = '未知父菜单'
  75. list_data.append({
  76. 'id': menu.id,
  77. 'parentId': menu.parentId,
  78. 'parentName': parent_name,
  79. 'path': menu.path,
  80. 'name': menu.name,
  81. 'component': menu.component,
  82. 'menutype': menu.menutype,
  83. 'menu_code': menu.menu_code,
  84. 'title': menu.title,
  85. 'icon': menu.icon,
  86. 'sort': menu.sort,
  87. 'hidden': menu.hidden,
  88. 'status': 1, # 默认启用
  89. })
  90. return response.json(0, {'list': list_data, 'total': count})
  91. # 获取可作为父菜单的菜单列表
  92. def getParentMenus(self, userID, request_dict, response):
  93. menus = AgentMenu.objects.filter(menutype=1).order_by('sort') # 只有菜单类型可以作为父菜单
  94. list_data = []
  95. for menu in menus:
  96. list_data.append({
  97. 'id': menu.id,
  98. 'title': menu.title,
  99. 'parentId': menu.parentId
  100. })
  101. return response.json(0, {'list': list_data})
  102. # 获取菜单详情
  103. def getMenuDetail(self, userID, request_dict, response):
  104. menu_id = request_dict.get('id', '')
  105. if not menu_id:
  106. return response.json(444, "缺少菜单ID")
  107. try:
  108. menu = AgentMenu.objects.get(id=menu_id)
  109. data = {
  110. 'id': menu.id,
  111. 'parentId': menu.parentId,
  112. 'path': menu.path,
  113. 'name': menu.name,
  114. 'component': menu.component,
  115. 'menutype': menu.menutype,
  116. 'menu_code': menu.menu_code,
  117. 'title': menu.title,
  118. 'icon': menu.icon,
  119. 'sort': menu.sort,
  120. 'hidden': menu.hidden
  121. }
  122. return response.json(0, data)
  123. except AgentMenu.DoesNotExist:
  124. return response.json(404, "菜单不存在")
  125. def doAdd(self, userID, request_dict, response):
  126. print(f"开始处理菜单添加 - userID: {userID}")
  127. data_dict = CommonService.request_dict_to_dict(request_dict)
  128. # 获取菜单类型
  129. menutype = int(data_dict.get('menutype', 1))
  130. # 根据菜单类型决定必填字段
  131. required_fields = ['title', 'name', 'menutype']
  132. # 仅当菜单类型为1(菜单)时,path和component为必填
  133. if menutype == 1: # 菜单类型
  134. required_fields.extend(['path'])
  135. for field in required_fields:
  136. if not data_dict.get(field):
  137. return response.json(444, f"缺少必填字段: {field}")
  138. # 按钮类型(menutype=2),确保有父级菜单
  139. if menutype == 2 and int(data_dict.get('parentId', 0)) == 0:
  140. return response.json(500, "按钮类型必须指定父级菜单")
  141. path = data_dict.get('path')
  142. # 只有当提供了path且不为空时才检查唯一性
  143. if path and AgentMenu.objects.filter(path=path).exists():
  144. return response.json(500, "路径已存在,请修改后重试")
  145. name = data_dict.get('name')
  146. if AgentMenu.objects.filter(name=name).exists():
  147. return response.json(500, "路由名称已存在,请修改后重试")
  148. parent_id = int(data_dict.get('parentId', 0))
  149. if parent_id > 0 and not AgentMenu.objects.filter(id=parent_id).exists():
  150. return response.json(500, "父菜单不存在")
  151. # 设置默认值
  152. data_dict.setdefault('parentId', 0)
  153. data_dict.setdefault('component', '')
  154. data_dict.setdefault('path', '')
  155. data_dict.setdefault('hidden', False)
  156. data_dict.setdefault('icon', '')
  157. data_dict.setdefault('sort', 0)
  158. data_dict.setdefault('menu_code', '')
  159. try:
  160. with transaction.atomic():
  161. menu = AgentMenu.objects.create(**data_dict)
  162. print(f"菜单创建成功 - ID: {menu.id}")
  163. # 自动给管理员角色分配新菜单权限
  164. try:
  165. admin_roles = AgentRole.objects.filter(role_name__in=['admin', '管理员'])
  166. for admin_role in admin_roles:
  167. AgentRoleMenu.objects.get_or_create(
  168. role=admin_role,
  169. menu=menu
  170. )
  171. print(f"权限分配完成")
  172. except Exception as e:
  173. print(f"自动分配权限失败: {str(e)}")
  174. success_response = response.json(0, {
  175. 'id': menu.id,
  176. 'message': "菜单创建成功"
  177. })
  178. print(f"返回成功响应: {success_response}")
  179. return success_response
  180. except Exception as e:
  181. print(f"菜单创建异常: {str(e)}")
  182. return response.json(500, f"菜单创建失败: {str(e)}")
  183. def doEdit(self, userID, request_dict, response):
  184. print(f"开始处理菜单编辑 - userID: {userID}")
  185. data_dict = CommonService.request_dict_to_dict(request_dict)
  186. menu_id = data_dict.get('id')
  187. if not menu_id:
  188. return response.json(444, "缺少菜单ID")
  189. if not AgentMenu.objects.filter(id=menu_id).exists():
  190. return response.json(404, "菜单不存在")
  191. # 移除id字段,避免更新主键
  192. data_dict.pop('id', None)
  193. # 获取菜单类型
  194. menutype = int(data_dict.get('menutype', 1))
  195. # 如果是按钮类型(menutype=2),确保有父级菜单
  196. if menutype == 2 and int(data_dict.get('parentId', 0)) == 0:
  197. return response.json(500, "按钮类型必须指定父级菜单")
  198. path = data_dict.get('path')
  199. # 只有当提供了path且不为空时才检查唯一性
  200. if path and AgentMenu.objects.exclude(id=menu_id).filter(path=path).exists():
  201. return response.json(500, "路径已存在,请修改后重试")
  202. name = data_dict.get('name')
  203. if name and AgentMenu.objects.exclude(id=menu_id).filter(name=name).exists():
  204. return response.json(500, "路由名称已存在,请修改后重试")
  205. parent_id = data_dict.get('parentId')
  206. if parent_id and int(parent_id) == int(menu_id):
  207. return response.json(500, "不能设置自己为父菜单")
  208. # 明确处理字段类型
  209. if 'parentId' in data_dict and data_dict['parentId'] is not None:
  210. data_dict['parentId'] = int(data_dict['parentId'])
  211. if 'sort' in data_dict and data_dict['sort'] is not None:
  212. data_dict['sort'] = int(data_dict['sort'])
  213. # 明确处理布尔类型字段
  214. if 'hidden' in data_dict:
  215. if isinstance(data_dict['hidden'], str):
  216. data_dict['hidden'] = data_dict['hidden'].lower() == 'true'
  217. # 处理菜单类型
  218. if 'menutype' in data_dict and data_dict['menutype'] is not None:
  219. data_dict['menutype'] = int(data_dict['menutype'])
  220. try:
  221. # 直接通过ID更新记录
  222. rows_updated = AgentMenu.objects.filter(id=menu_id).update(**data_dict)
  223. print(f"更新结果: {rows_updated} 行被更新")
  224. if rows_updated:
  225. return response.json(0, "菜单更新成功")
  226. return response.json(500, "菜单更新失败:未找到匹配记录")
  227. except Exception as e:
  228. print(f"菜单更新失败: {str(e)}")
  229. return response.json(500, f"菜单更新失败: {str(e)}")
  230. def doDelete(self, userID, request_dict, response):
  231. menu_id = request_dict.get('id', '')
  232. if not menu_id:
  233. return response.json(444, "缺少菜单ID")
  234. try:
  235. menu = AgentMenu.objects.get(id=menu_id)
  236. except AgentMenu.DoesNotExist:
  237. return response.json(404, "菜单不存在")
  238. # 若有子菜单,需先删除子菜单
  239. if AgentMenu.objects.filter(parentId=menu_id).exists():
  240. return response.json(500, "该菜单下存在子菜单,请先删除子菜单")
  241. try:
  242. menu.delete()
  243. return response.json(0, "菜单删除成功")
  244. except Exception as e:
  245. return response.json(500, f"菜单删除失败: {str(e)}")
  246. def getUserMenus(self, userID, request_dict, response):
  247. """获取用户菜单 """
  248. try:
  249. print(f"获取用户菜单 - userID: {userID}")
  250. # 根据用户ID获取用户的角色
  251. user_roles = AgentUserRole.objects.filter(user_id=userID).values_list('role_id', flat=True)
  252. print(f"用户角色IDs: {list(user_roles)}")
  253. if not user_roles:
  254. print("用户没有分配角色,返回空菜单")
  255. return response.json(0, {'list': []})
  256. # 根据用户角色获取所有可访问的菜单ID
  257. menu_ids = AgentRoleMenu.objects.filter(
  258. role_id__in=user_roles
  259. ).values_list('menu_id', flat=True).distinct()
  260. print(f"用户可访问的菜单IDs: {list(menu_ids)}")
  261. if not menu_ids:
  262. print("用户角色没有分配菜单权限")
  263. return response.json(0, {'list': []})
  264. # 获取菜单数据(返回平铺结构,让前端构建树)
  265. menus = AgentMenu.objects.filter(
  266. id__in=menu_ids
  267. ).order_by('sort', 'id')
  268. list_data = []
  269. for menu in menus:
  270. list_data.append({
  271. 'id': menu.id,
  272. 'parentId': menu.parentId,
  273. 'path': menu.path,
  274. 'name': menu.name,
  275. 'component': menu.component,
  276. 'menutype': menu.menutype,
  277. 'menu_code': menu.menu_code,
  278. 'title': menu.title,
  279. 'icon': menu.icon,
  280. 'sort': menu.sort,
  281. 'hidden': menu.hidden,
  282. 'status': 1,
  283. })
  284. print("实际返回菜单数据:", list_data)
  285. print(f"返回菜单数据: {len(list_data)} 条")
  286. return response.json(0, {'list': list_data})
  287. except Exception as e:
  288. print(f"获取用户菜单失败: {str(e)}")
  289. return response.json(500, f"获取用户菜单失败: {str(e)}")