__init__.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. from fastapi import APIRouter, Request, Depends, Query, HTTPException, status
  4. from pydantic import BaseModel
  5. from database import get_db
  6. from sqlalchemy.orm import Session
  7. from typing import List
  8. from models import *
  9. import json
  10. from sqlalchemy.sql import func
  11. router = APIRouter()
  12. # 定义 Meta 和 Child 模型用于嵌套结构
  13. class Meta(BaseModel):
  14. title: str
  15. icon: str
  16. noCache: bool
  17. link: str = None
  18. class Child(BaseModel):
  19. name: str
  20. path: str
  21. hidden: bool
  22. component: str
  23. meta: Meta
  24. children: List['Child'] = []
  25. class Router(BaseModel):
  26. name: str
  27. path: str
  28. hidden: bool
  29. redirect: str = 'noRedirect'
  30. component: str
  31. alwaysShow: bool = True
  32. meta: Meta
  33. children: List[Child] = []
  34. class Router_frame(BaseModel):
  35. component:str
  36. hidden: bool
  37. meta:Meta
  38. name: str
  39. path: str
  40. redirect: str = 'noRedirect'
  41. children: List[Child] = []
  42. alwaysShow: bool = True
  43. @router.get('/getRouters')
  44. async def getRouters(request: Request, db: Session = Depends(get_db)):
  45. try:
  46. # 查询数据库中的所有菜单项,根据 parent_id 排序以构建树形结构
  47. query = db.query(SysMenu)
  48. query = query.filter_by(parent_id=0)
  49. query = query.filter(SysMenu.del_flag != '2')
  50. menus =query.all() # 顶级菜单
  51. # 递归函数用于构建树形结构
  52. def build_menu_tree(menus, parent_menu):
  53. menu_tree = [] # 初始化一个列表来存储菜单树结构
  54. for menu in menus:
  55. if menu.is_frame==0:
  56. menu_data = Router_frame(
  57. component=menu.component or 'Layout',
  58. hidden=menu.visible == '1',
  59. name=menu.path,
  60. path='/'+menu.path,
  61. meta = Meta(
  62. title=menu.menu_name,
  63. icon=menu.icon,
  64. noCache=menu.is_cache == '1',
  65. link = menu.path
  66. ),
  67. children=[]
  68. )
  69. else:
  70. menu_data = Router(
  71. name=menu.path,#menu.menu_name,
  72. path='/'+menu.path,
  73. hidden=menu.visible == '1',
  74. component=menu.component or 'Layout',
  75. meta=Meta(
  76. title=menu.menu_name,
  77. icon=menu.icon,
  78. noCache=menu.is_cache == '1'
  79. ),
  80. children=[] # 初始化 children 列表,即使没有子菜单
  81. )
  82. # 如果菜单有子菜单,则递归构建子菜单
  83. if menu.menu_type == 'M': # 假设 'M' 表示目录类型
  84. query = db.query(SysMenu)
  85. query = query.filter_by(parent_id=menu.menu_id)
  86. query = query.filter(SysMenu.del_flag != '2')
  87. # children_menus = db.query(SysMenu).filter_by(parent_id=menu.menu_id).all()
  88. children_menus = query.all()
  89. menu_data.children = build_menu_tree(children_menus, menu)
  90. else:
  91. del menu_data.children #没有子菜单,删除children 列表
  92. del menu_data.redirect
  93. del menu_data.alwaysShow
  94. menu_data.path = menu_data.path[1:]
  95. menu_tree.append(menu_data) # 将当前菜单数据添加到菜单树列表
  96. return menu_tree
  97. # 构建顶级菜单的树形结构
  98. routers = build_menu_tree(menus, None)
  99. # routers_dict = [router.dict() for router in routers]
  100. routers_dict = []
  101. for router in routers:
  102. router_info = router.dict()
  103. if len(router_info['children'])==0:
  104. del router_info['children']
  105. del router_info['redirect']
  106. del router_info['alwaysShow']
  107. router_info['path'] = router_info['path'][1:]
  108. routers_dict.append(router_info)
  109. # 返回构建好的路由数据
  110. return {
  111. "code": 200,
  112. "msg": "操作成功",
  113. "data": routers_dict #[router.dict() for router in routers] # 如果没有顶级菜单,返回空列表
  114. }
  115. except Exception as e:
  116. # 处理异常,返回错误信息
  117. raise HTTPException(status_code=500, detail=str(e))
  118. @router.get('/list')
  119. async def get_list(
  120. # request: Request,
  121. menuName: str = Query(None, max_length=100),
  122. status: str = Query(None, max_length=100),
  123. db: Session = Depends(get_db)
  124. ):
  125. query = db.query(SysMenu)
  126. query = query.filter(SysMenu.del_flag != '2')
  127. if menuName:
  128. query = query.filter(SysMenu.menu_name.like(f'%{menuName}%'))
  129. if status:
  130. query = query.filter(SysMenu.status.like(f'%{status}%'))
  131. # 应用查询
  132. # menu_list = db.query(SysMenu).filter(
  133. # (SysMenu.menu_name.like(f'%{menu_name}%')) ,
  134. # (SysMenu.status.like(f'%{status}%'))
  135. # ).all()
  136. menu_list = query.all()
  137. # 将模型实例转换为字典
  138. menu_list_dict = [{
  139. "menuId": menu.menu_id,
  140. "menuName": menu.menu_name,
  141. "parentId": menu.parent_id,
  142. "orderNum": menu.order_num,
  143. "path": menu.path,
  144. "component": menu.component,
  145. "queryParam": menu.query_param,
  146. "isFrame": str(menu.is_frame),
  147. "isCache": str(menu.is_cache),
  148. "menuType": menu.menu_type,
  149. "visible": menu.visible,
  150. "status": menu.status,
  151. "perms": menu.perms,
  152. "icon": menu.icon,
  153. "createDept": menu.create_dept,
  154. "remark": menu.remark,
  155. "createTime": menu.create_time.strftime('%Y-%m-%d %H:%M:%S') if menu.create_time else '',
  156. "children": [] # 递归调用以获取子菜单
  157. } for menu in menu_list]
  158. # 构建分页响应
  159. # pagination_info = {
  160. # "total": total_count,
  161. # "page_num": page_num,
  162. # "page_size": page_size,
  163. # "total_pages": (total_count + page_size - 1) // page_size # 计算总页数
  164. # }
  165. return {
  166. "code": 200,
  167. "data": menu_list_dict,
  168. # 'pages': page_num, # 总页数
  169. # 'currentPage': page_num, # 当前页数
  170. # # 'current':current,
  171. # # 'total' : total,
  172. # 'total': total_count, # 总数据量
  173. # # 'size':size,
  174. # 'pageSize': page_size, # 页码
  175. # {
  176. # "items": menu_list_dict,
  177. # "pagination": pagination_info
  178. # },
  179. "msg": "操作成功"
  180. }
  181. class SysMuneCreateForm(BaseModel):
  182. component:str = None
  183. icon : str
  184. isCache: str
  185. isFrame:str
  186. menuName: str
  187. menuType:str
  188. orderNum:int
  189. parentId:int
  190. path:str
  191. perms:str=None
  192. queryParam:str=None
  193. status:str
  194. visible:str
  195. @router.post('/create')
  196. async def create(
  197. form_data: SysMuneCreateForm,
  198. db: Session = Depends(get_db)
  199. ):
  200. try:
  201. new_menu = SysMenu(
  202. menu_name = form_data.menuName,
  203. parent_id = form_data.parentId,
  204. order_num = form_data.orderNum,
  205. path = form_data.path,
  206. is_frame = int(form_data.isFrame),
  207. is_cache = int(form_data.isCache),
  208. menu_type = form_data.menuType,
  209. visible = form_data.visible,
  210. status = form_data.status,
  211. icon = form_data.icon,
  212. component= form_data.component,
  213. perms=form_data.perms,
  214. query_param=form_data.queryParam
  215. )
  216. db.add(new_menu)
  217. db.commit()
  218. db.refresh(new_menu)
  219. return {
  220. "code": 200,
  221. "data": None,
  222. "msg": "操作成功"
  223. }
  224. except Exception as e:
  225. db.rollback()
  226. raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e))
  227. class SysMuneUpdateForm(BaseModel):
  228. menuId : str
  229. component:str = None
  230. icon : str = None
  231. isCache: str = None
  232. isFrame:str = None
  233. menuName: str = None
  234. menuType:str = None
  235. orderNum:int = None
  236. parentId:int = None
  237. path:str = None
  238. perms:str=None
  239. queryParam:str=None
  240. status:str = None
  241. visible:str = None
  242. @router.put('/update')
  243. async def update(
  244. request: Request,
  245. form_data: SysMuneUpdateForm,
  246. db: Session = Depends(get_db)
  247. ):
  248. try:
  249. query = db.query(SysMenu)
  250. query = query.filter(SysMenu.menu_id == form_data.menuId)
  251. query = query.filter(SysMenu.del_flag != '2')
  252. menu = query.first()
  253. if not menu:
  254. detail = "菜单不存在"
  255. raise HTTPException(status_code=404, detail="菜单不存在")
  256. # 更新字段,排除主键和不可更新的字段
  257. if form_data.component:
  258. menu.component=form_data.component
  259. if form_data.icon:
  260. menu.icon=form_data.icon
  261. if form_data.isCache:
  262. menu.is_cache=form_data.isCache
  263. if form_data.isFrame:
  264. menu.is_frame=form_data.isFrame
  265. if form_data.menuName:
  266. menu.menu_name=form_data.menuName
  267. if form_data.menuType:
  268. menu.menu_type=form_data.menuType
  269. if form_data.orderNum:
  270. menu.order_num=form_data.orderNum
  271. if form_data.parentId:
  272. menu.parent_id=form_data.parentId
  273. if form_data.path:
  274. menu.path=form_data.path
  275. if form_data.perms:
  276. menu.perms=form_data.perms
  277. if form_data.queryParam:
  278. menu.query_param=form_data.queryParam
  279. if form_data.status:
  280. menu.status=form_data.status
  281. if form_data.visible:
  282. menu.visible=form_data.visible
  283. # for field, value in menu_data.items():
  284. # if field != 'menu_id' and field in menu_to_update.__dict__:
  285. # setattr(menu_to_update, field, value)
  286. #
  287. # db.add(menu_to_update)
  288. db.commit()
  289. return {
  290. "code": 200,
  291. "msg": "菜单更新成功"
  292. }
  293. except Exception as e:
  294. # db.rollback()
  295. if str(e)=='':
  296. e = detail
  297. raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e))
  298. @router.delete('/delete/{menu_id}')
  299. async def delete(
  300. menu_id: int,
  301. db: Session = Depends(get_db)
  302. ):
  303. try:
  304. query = db.query(SysMenu)
  305. query = query.filter(SysMenu.menu_id == menu_id)
  306. query = query.filter(SysMenu.del_flag != '2')
  307. menu_to_delete =query.first()
  308. if not menu_to_delete:
  309. detail = "菜单不存在"
  310. raise HTTPException(status_code=404, detail="菜单不存在")
  311. menu_to_delete.del_flag='2'
  312. # db.delete(menu_to_delete)
  313. db.commit()
  314. return {
  315. "code": 200,
  316. "msg": "菜单删除成功"
  317. }
  318. except Exception as e:
  319. db.rollback()
  320. if str(e)=='':
  321. e = detail
  322. raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e))