__init__.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. from fastapi import APIRouter, Request, Depends, Query, HTTPException, status
  4. from common.security import valid_access_token
  5. from pydantic import BaseModel
  6. from database import get_db
  7. from sqlalchemy.orm import Session
  8. from typing import List
  9. from models import *
  10. from utils import *
  11. from utils.ry_system_util import *
  12. import json
  13. from sqlalchemy.sql import func
  14. from common.auth_user import *
  15. from common.enc import mpfun, sys_menu_data, sys_menu_layer_data
  16. import traceback
  17. from common.db import db_czrz
  18. from exceptions import HmacException
  19. router = APIRouter()
  20. # 定义 Meta 和 Child 模型用于嵌套结构
  21. class Meta(BaseModel):
  22. title: str
  23. icon: str
  24. noCache: bool
  25. link: str = None
  26. class Child(BaseModel):
  27. name: str
  28. path: str
  29. hidden: bool
  30. component: str
  31. meta: Meta
  32. children: List['Child'] = []
  33. class Router(BaseModel):
  34. name: str
  35. path: str
  36. hidden: bool
  37. redirect: str = 'noRedirect'
  38. component: str
  39. alwaysShow: bool = True
  40. meta: Meta
  41. children: List[Child] = []
  42. class Router_frame(BaseModel):
  43. component:str
  44. hidden: bool
  45. meta:Meta
  46. name: str
  47. path: str
  48. redirect: str = 'noRedirect'
  49. children: List[Child] = []
  50. alwaysShow: bool = True
  51. # checkedKeys roleMenuTreeselect
  52. @router.get('/getRouters')
  53. async def getRouters(request: Request, db: Session = Depends(get_db),
  54. body = Depends(remove_xss_json),
  55. user_id = Depends(valid_access_token)):
  56. try:
  57. # 查询数据库中的所有菜单项,根据 parent_id 排序以构建树形结构
  58. query = db.query(SysMenuLayer)
  59. query = query.filter_by(parent_id=0)
  60. query = query.filter(SysMenuLayer.del_flag != '2')
  61. menus =query.all() # 顶级菜单
  62. # 递归函数用于构建树形结构
  63. def build_menu_tree(menus, parent_menu):
  64. menu_tree = [] # 初始化一个列表来存储菜单树结构
  65. for menu in menus:
  66. if menu.is_frame==0:
  67. menu_data = Router_frame(
  68. component=menu.component or 'Layout',
  69. hidden=menu.layer_visible == '1',
  70. name=menu.path,
  71. path='/'+menu.path,
  72. meta = Meta(
  73. title=menu.menu_name,
  74. icon=menu.icon,
  75. noCache=menu.is_cache == '1',
  76. link = menu.path
  77. ),
  78. children=[]
  79. )
  80. else:
  81. menu_data = Router(
  82. name=menu.path,#menu.menu_name,
  83. path='/'+menu.path,
  84. hidden=menu.layer_visible == '1',
  85. component=menu.component or 'Layout',
  86. meta=Meta(
  87. title=menu.menu_name,
  88. icon=menu.icon,
  89. noCache=menu.is_cache == '1'
  90. ),
  91. children=[] # 初始化 children 列表,即使没有子菜单
  92. )
  93. # 如果菜单有子菜单,则递归构建子菜单
  94. if menu.menu_type == 'D' or menu.menu_type == 'Z': # 假设 'M' 表示目录类型
  95. query = db.query(SysMenuLayer)
  96. query = query.filter_by(parent_id=menu.menu_id)
  97. query = query.filter(SysMenuLayer.del_flag != '2')
  98. # children_menus = db.query(SysMenu).filter_by(parent_id=menu.menu_id).all()
  99. children_menus = query.all()
  100. menu_data.children = build_menu_tree(children_menus, menu)
  101. else:
  102. del menu_data.children #没有子菜单,删除children 列表
  103. del menu_data.redirect
  104. del menu_data.alwaysShow
  105. menu_data.path = menu_data.path[1:]
  106. menu_tree.append(menu_data) # 将当前菜单数据添加到菜单树列表
  107. return menu_tree
  108. # 构建顶级菜单的树形结构
  109. routers = build_menu_tree(menus, None)
  110. # routers_dict = [router.dict() for router in routers]
  111. routers_dict = []
  112. for router in routers:
  113. router_info = router.dict()
  114. print(router_info)
  115. if len(router_info['children'])==0:
  116. del router_info['children']
  117. del router_info['redirect']
  118. del router_info['alwaysShow']
  119. router_info['path'] = router_info['path'][1:]
  120. routers_dict.append(router_info)
  121. # 返回构建好的路由数据
  122. return {
  123. "code": 200,
  124. "msg": "操作成功",
  125. "data": routers_dict #[router.dict() for router in routers] # 如果没有顶级菜单,返回空列表
  126. }
  127. except Exception as e:
  128. # 处理异常,返回错误信息
  129. traceback.print_exc()
  130. raise HTTPException(status_code=500, detail=str(e))
  131. @router.get('/list')
  132. async def get_list(
  133. # request: Request,
  134. menuName: str = Query(None, max_length=100),
  135. status: str = Query(None, max_length=100),
  136. db: Session = Depends(get_db),
  137. body = Depends(remove_xss_json),
  138. user_id = Depends(valid_access_token)
  139. ):
  140. query = db.query(SysMenuLayer)
  141. query = query.filter(SysMenuLayer.del_flag != '2')
  142. if menuName:
  143. query = query.filter(SysMenuLayer.menu_name.like(f'%{menuName}%'))
  144. query = query.filter(SysMenuLayer.menu_type=='T')
  145. if status:
  146. query = query.filter(SysMenuLayer.status==status)
  147. # 应用查询
  148. # menu_list = db.query(SysMenu).filter(
  149. # (SysMenu.menu_name.like(f'%{menu_name}%')) ,
  150. # (SysMenu.status.like(f'%{status}%'))
  151. # ).all()
  152. menu_list = query.all()
  153. # 将模型实例转换为字典
  154. menu_list_dict = [{
  155. "menuId": menu.menu_id,
  156. "menuName": menu.menu_name,
  157. "parentId": menu.parent_id,
  158. "orderNum": menu.order_num,
  159. "path": menu.path,
  160. "component": menu.component,
  161. "queryParam": menu.query_param,
  162. "isFrame": str(menu.is_frame),
  163. "isCache": str(menu.is_cache),
  164. "menuType": menu.menu_type,
  165. "layerVisible": menu.layer_visible,
  166. "status": menu.status,
  167. "perms": menu.perms,
  168. "icon": menu.icon,
  169. "createDept": menu.create_dept,
  170. "remark": menu.remark,
  171. "createTime": menu.create_time.strftime('%Y-%m-%d %H:%M:%S') if menu.create_time else '',
  172. "children": [] # 递归调用以获取子菜单
  173. } for menu in menu_list]
  174. return {
  175. "code": 200,
  176. "data": menu_list_dict,
  177. "msg": "操作成功"
  178. }
  179. @router.get('/info/{menuid}')
  180. async def get_list(
  181. # request: Request,
  182. menuid: str = Query(None, max_length=100),
  183. db: Session = Depends(get_db),
  184. body = Depends(remove_xss_json),
  185. user_id = Depends(valid_access_token)
  186. ):
  187. query = db.query(SysMenuLayer)
  188. query = query.filter(SysMenuLayer.del_flag != '2')
  189. if menuid:
  190. query = query.filter(SysMenuLayer.menu_id==menuid)
  191. menu= query.first()
  192. # 将模型实例转换为字典
  193. menu_list_dict = {
  194. "menuId": menu.menu_id,
  195. "menuName": menu.menu_name,
  196. "parentId": menu.parent_id,
  197. "orderNum": menu.order_num,
  198. "path": menu.path,
  199. "component": menu.component,
  200. "queryParam": menu.query_param,
  201. "isFrame": str(menu.is_frame),
  202. "isCache": str(menu.is_cache),
  203. "menuType": menu.menu_type,
  204. "layerVisible": menu.layer_visible,
  205. "status": menu.status,
  206. "perms": menu.perms,
  207. "icon": menu.icon,
  208. "createDept": menu.create_dept,
  209. "remark": menu.remark,
  210. "createTime": menu.create_time.strftime('%Y-%m-%d %H:%M:%S') if menu.create_time else '',
  211. "children": [], # 递归调用以获取子菜单
  212. "layer_template":menu.layer_template
  213. }
  214. return {
  215. "code": 200,
  216. "data": menu_list_dict,
  217. "msg": "操作成功"
  218. }
  219. @router.post('/create')
  220. async def create(
  221. request: Request,
  222. # form_data: SysMuneCreateForm,
  223. db: Session = Depends(get_db),
  224. body=Depends(remove_xss_json),
  225. auth_user: AuthUser = Depends(find_auth_user),
  226. user_id=Depends(valid_access_token)
  227. ):
  228. try:
  229. # 开始事务
  230. # db.begin()
  231. # 创建新的菜单层,此时还不能使用new_menu.menu_id,因为它还没有被赋值
  232. new_menu_layer = SysMenuLayer(
  233. menu_name=body['menuName'],
  234. parent_id=body['parentId'],
  235. order_num=body['orderNum'],
  236. path=body['path'],
  237. is_frame=int(body['isFrame']),
  238. is_cache=int(body['isCache']),
  239. menu_type=body['menuType'],
  240. layer_visible=body['layerVisible'],
  241. status=body['status'],
  242. icon=body['icon'],
  243. component=body['component'],
  244. perms=body['perms'],
  245. query_param=body['queryParam'],
  246. create_by=user_id,
  247. layer_template=body['layer_template']
  248. )
  249. db.add(new_menu_layer)
  250. # 提交事务
  251. db.commit()
  252. sys_menu_data.sign_table()
  253. sys_menu_layer_data.sign_table()
  254. db_czrz.log(db, auth_user, "系统管理", f"后台管理新建地图菜单【{body['menuName']}】成功", request.client.host)
  255. return {
  256. "code": 200,
  257. "data": None,#new_menu_layer.menu_id, # 返回新创建的SysMenuLayer的ID
  258. "msg": "操作成功"
  259. }
  260. except Exception as e:
  261. traceback.print_exc()
  262. # 如果发生异常,回滚事务
  263. db.rollback()
  264. raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e))
  265. @router.put('/update')
  266. async def update(
  267. request: Request,
  268. auth_user: AuthUser = Depends(find_auth_user),
  269. # form_data: SysMuneUpdateForm,
  270. db: Session = Depends(get_db),
  271. body = Depends(remove_xss_json),
  272. user_id = Depends(valid_access_token)
  273. ):
  274. try:
  275. queryLayer = db.query(SysMenuLayer)
  276. queryLayer = queryLayer.filter(SysMenuLayer.menu_id == body['menuId'])
  277. queryLayer = queryLayer.filter(SysMenuLayer.del_flag != '2')
  278. menu = queryLayer.first()
  279. if not menu:
  280. detail = "菜单不存在"
  281. raise HTTPException(status_code=404, detail="菜单不存在")
  282. # 更新字段,排除主键和不可更新的字段
  283. if 'component' in body:
  284. menu.component = body['component']
  285. if 'icon' in body:
  286. menu.icon = body['icon']
  287. if 'isCache' in body:
  288. menu.is_cache = body['isCache']
  289. if 'isFrame' in body:
  290. menu.is_frame = body['isFrame']
  291. if 'menuName' in body:
  292. menu.menu_name = body['menuName']
  293. if 'menuType' in body:
  294. menu.menu_type = body['menuType']
  295. if 'orderNum' in body:
  296. menu.order_num = body['orderNum']
  297. if 'parentId' in body:
  298. menu.parent_id = body['parentId']
  299. if 'path' in body:
  300. menu.path = body['path']
  301. if 'perms' in body:
  302. menu.perms = body['perms']
  303. if 'queryParam' in body:
  304. menu.query_param = body['queryParam']
  305. if 'status' in body:
  306. menu.status = body['status']
  307. if 'layer_visible' in body:
  308. menu.layer_visible = body['layerVisible']
  309. if 'layer_template' in body:
  310. menu.layer_template = body['layer_template']
  311. menu.update_by = user_id
  312. menu.update_time = datetime.now()
  313. menu.sign = sys_menu_layer_data.get_sign_hmac(menu)
  314. db.commit()
  315. db_czrz.log(db, auth_user, "系统管理", f"后台管理更新地图菜单【{body['menuName']}】成功", request.client.host)
  316. return {
  317. "code": 200,
  318. "msg": "菜单更新成功"
  319. }
  320. except Exception as e:
  321. traceback.print_exc()
  322. # db.rollback()
  323. if str(e)=='':
  324. e = detail
  325. raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e))
  326. @router.delete('/delete/{menu_id}')
  327. async def delete(
  328. request: Request,
  329. menu_id: int,
  330. db: Session = Depends(get_db),
  331. body = Depends(remove_xss_json),
  332. auth_user: AuthUser = Depends(find_auth_user),
  333. user_id = Depends(valid_access_token)
  334. ):
  335. try:
  336. db.begin()
  337. query = db.query(SysMenu)
  338. query = query.filter(SysMenu.menu_id == menu_id)
  339. query = query.filter(SysMenu.del_flag != '2')
  340. menu_to_delete =query.first()
  341. if not menu_to_delete:
  342. detail = "菜单不存在"
  343. raise HTTPException(status_code=404, detail="菜单不存在")
  344. menu_to_delete.create_by = user_id
  345. menu_to_delete.del_flag='2'
  346. # db.delete(menu_to_delete)
  347. # db.commit()
  348. queryLayer = db.query(SysMenuLayer)
  349. queryLayer = queryLayer.filter(SysMenuLayer.menu_id == menu_id)
  350. queryLayer = queryLayer.filter(SysMenuLayer.del_flag != '2')
  351. menu_to_delete = queryLayer.first()
  352. if not menu_to_delete:
  353. detail = "菜单不存在"
  354. raise HTTPException(status_code=404, detail="菜单不存在")
  355. menu_to_delete.update_by = user_id
  356. menu_to_delete.update_time = datetime.now()
  357. menu_to_delete.del_flag = '2'
  358. menu_to_delete.sign = sys_menu_layer_data.get_sign_hmac(menu_to_delete)
  359. db.commit()
  360. db_czrz.log(db, auth_user, "系统管理", f"后台管理删除菜单【{menu_to_delete.menu_name}】成功", request.client.host)
  361. return {
  362. "code": 200,
  363. "msg": "菜单删除成功"
  364. }
  365. except Exception as e:
  366. traceback.print_exc()
  367. db.rollback()
  368. if str(e)=='':
  369. e = detail
  370. raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e))