common_services.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. from functools import lru_cache
  2. from typing import Optional, List
  3. from sqlalchemy import select, or_
  4. from sqlalchemy.ext.asyncio import AsyncSession
  5. from core.enums import StatusTypeEnum, DeleteTypeEnum, MasterTypeEnum
  6. from core.exceptions import ServiceWarning
  7. from domain.dtos import SysLoginLogDto, SysOperLogDto, SysDictDataDto
  8. from domain.models import (
  9. SysUserModel,
  10. SysDeptModel,
  11. SysRoleModel,
  12. SysUserRoleModel,
  13. SysPostModel,
  14. SysUserPostModel,
  15. SysMenuModel,
  16. SysLoginLogModel,
  17. SysOperLogModel,
  18. SysRoleDeptModel,
  19. SysPermissionModel,
  20. SysDictDataModel,
  21. )
  22. from utils import DBUtil, logger
  23. class CommonService:
  24. def __init__(self, db_name: Optional[str] = None):
  25. self._db_name = db_name
  26. pass
  27. async def _get_async_db(self) -> AsyncSession:
  28. """根据db_name获取异步数据库连接"""
  29. try:
  30. # 使用DBUtil获取异步连接
  31. async with DBUtil()(db_name=self._db_name) as conn:
  32. return conn
  33. except Exception as e:
  34. logger.error(f"数据库连接失败: {str(e)}")
  35. raise
  36. async def get_user_detail_by_id(self, id: int):
  37. """
  38. 查询用户详细信息
  39. :param id:
  40. :return:
  41. """
  42. try:
  43. async with await self._get_async_db() as db:
  44. user = (
  45. (
  46. await db.execute(
  47. select(SysUserModel)
  48. .where(
  49. SysUserModel.status == StatusTypeEnum.NORMAL.key,
  50. SysUserModel.is_del == DeleteTypeEnum.NORMAL.key,
  51. SysUserModel.id == id,
  52. )
  53. .distinct()
  54. )
  55. )
  56. .scalars()
  57. .first()
  58. )
  59. if not user:
  60. return None
  61. user_id_str = str(user.id)
  62. dept = (
  63. (
  64. await db.execute(
  65. select(SysDeptModel)
  66. .where(
  67. SysDeptModel.status == StatusTypeEnum.NORMAL.key,
  68. SysDeptModel.is_del == DeleteTypeEnum.NORMAL.key,
  69. SysDeptModel.id == user.dept_id,
  70. )
  71. .distinct()
  72. )
  73. )
  74. .scalars()
  75. .first()
  76. )
  77. roles = (
  78. (
  79. await db.execute(
  80. select(SysRoleModel)
  81. .join(
  82. SysUserRoleModel,
  83. SysUserRoleModel.role_id == SysRoleModel.id,
  84. )
  85. .where(
  86. SysUserRoleModel.user_id == user.id,
  87. SysRoleModel.status == StatusTypeEnum.NORMAL.key,
  88. SysRoleModel.is_del == DeleteTypeEnum.NORMAL.key,
  89. )
  90. .distinct()
  91. )
  92. )
  93. .scalars()
  94. .all()
  95. )
  96. posts = (
  97. (
  98. await db.execute(
  99. select(SysPostModel)
  100. .join(
  101. SysUserPostModel,
  102. SysUserPostModel.post_id == SysPostModel.id,
  103. )
  104. .where(
  105. SysUserPostModel.user_id == user.id,
  106. SysPostModel.status == StatusTypeEnum.NORMAL.key,
  107. )
  108. .distinct()
  109. )
  110. )
  111. .scalars()
  112. .all()
  113. )
  114. role_id_list = [str(item.id) for item in roles]
  115. if "1" in role_id_list:
  116. menus = (
  117. (
  118. await db.execute(
  119. select(SysMenuModel)
  120. .where(SysMenuModel.status == StatusTypeEnum.NORMAL.key)
  121. .distinct()
  122. )
  123. )
  124. .scalars()
  125. .all()
  126. )
  127. else:
  128. menus = (
  129. (
  130. await db.execute(
  131. select(SysMenuModel)
  132. .join(
  133. SysPermissionModel,
  134. SysPermissionModel.name == SysMenuModel.perms,
  135. )
  136. .where(
  137. SysRoleModel.id.in_(role_id_list),
  138. or_(
  139. (
  140. SysPermissionModel.master
  141. == MasterTypeEnum.ROLE.key,
  142. SysPermissionModel.master_value.in_(
  143. role_id_list
  144. ),
  145. ),
  146. (
  147. SysPermissionModel.master
  148. == MasterTypeEnum.USER.key,
  149. SysPermissionModel.master_value
  150. == user_id_str,
  151. ),
  152. ),
  153. SysMenuModel.status == StatusTypeEnum.NORMAL.key,
  154. )
  155. .distinct()
  156. )
  157. )
  158. .scalars()
  159. .all()
  160. )
  161. return {
  162. "user": user,
  163. "dept": dept,
  164. "roles": roles,
  165. "posts": posts,
  166. "menus": menus,
  167. }
  168. except Exception as e:
  169. logger.error(f"查询用户详细信息失败: {str(e)}")
  170. raise ServiceWarning(message=f"查询用户详细信息失败: {str(e)}")
  171. async def get_user_role_dept_ids(self, user_id: int) -> list[int]:
  172. """
  173. 获取用户角色部门id
  174. :param user_id:
  175. :return:
  176. """
  177. try:
  178. async with self._get_async_db() as db:
  179. dept_ids = (
  180. (
  181. await db.execute(
  182. select(SysRoleDeptModel.dept_id)
  183. .join(
  184. SysRoleModel,
  185. SysRoleDeptModel.role_id == SysRoleModel.id,
  186. )
  187. .join(
  188. SysUserRoleModel,
  189. SysRoleDeptModel.role_id == SysUserRoleModel.role_id,
  190. )
  191. .where(
  192. SysUserRoleModel.user_id == user_id,
  193. SysRoleModel.status == StatusTypeEnum.NORMAL.key,
  194. )
  195. .distinct()
  196. )
  197. )
  198. .scalars()
  199. .all()
  200. )
  201. return dept_ids
  202. except Exception as e:
  203. raise ServiceWarning(f"查询用户角色部门id失败:{str(e)}")
  204. async def get_dept_all_children_ids(self, dept_id: int):
  205. """
  206. 获取部门所有子部门id
  207. :param dept_id:
  208. :return:
  209. """
  210. try:
  211. async with self._get_async_db() as db:
  212. # 创建递归CTE查询
  213. cte = (
  214. select(SysDeptModel.id)
  215. .where(
  216. SysDeptModel.id == dept_id,
  217. SysDeptModel.is_del == DeleteTypeEnum.NORMAL.value,
  218. )
  219. .cte(recursive=True)
  220. )
  221. # 递归部分:查找所有子部门
  222. cte = cte.union_all(
  223. select(SysDeptModel.id)
  224. .join(cte, SysDeptModel.parent_id == cte.c.id)
  225. .where(SysDeptModel.is_del == DeleteTypeEnum.NORMAL.value)
  226. )
  227. ids = (await db.execute(select(cte).distinct())).scalars().all()
  228. return ids
  229. except Exception as e:
  230. raise ServiceWarning(f"查询部门所有子部门id失败:{str(e)}")
  231. @lru_cache()
  232. async def get_all_dict_data(self) -> List[SysDictDataDto]:
  233. """根据字典类型查询字典数据"""
  234. try:
  235. async with await self._get_async_db() as db:
  236. query = select(SysDictDataModel).where(
  237. SysDictDataModel.status == StatusTypeEnum.NORMAL.key,
  238. )
  239. result = await db.execute(query)
  240. models = result.scalars().all()
  241. return [SysDictDataDto.from_model(model) for model in models]
  242. except Exception as e:
  243. raise ServiceWarning(f"查询字典数据失败: {str(e)}")
  244. async def create_login_log(self, dto: SysLoginLogDto):
  245. """
  246. 创建登录日志
  247. :param dto:
  248. :return:
  249. """
  250. try:
  251. async with await self._get_async_db() as db:
  252. db_obj = SysLoginLogModel.from_dict(dto.to_dict())
  253. db.add(db_obj)
  254. await db.commit()
  255. await db.refresh(db_obj)
  256. return db_obj
  257. except Exception as e:
  258. raise ServiceWarning(f"创建登录日志失败:{str(e)}")
  259. async def create_oper_log(self, dto: SysOperLogDto):
  260. """
  261. 创建操作日志
  262. :param dto:
  263. :return:
  264. """
  265. try:
  266. async with await self._get_async_db() as db:
  267. db_obj = SysOperLogModel.from_dict(dto.to_dict())
  268. db.add(db_obj)
  269. await db.commit()
  270. await db.refresh(db_obj)
  271. return db_obj
  272. except Exception as e:
  273. raise ServiceWarning(f"创建操作日志失败:{str(e)}")