service.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. from typing import Any
  2. from app.api.v1.module_system.auth.schema import AuthSchema
  3. from app.core.base_schema import BatchSetAvailable
  4. from app.core.exceptions import CustomException
  5. from app.utils.excel_util import ExcelUtil
  6. from .crud import RoleCRUD
  7. from .schema import (
  8. RoleCreateSchema,
  9. RoleOutSchema,
  10. RolePermissionSettingSchema,
  11. RoleQueryParam,
  12. RoleUpdateSchema,
  13. )
  14. class RoleService:
  15. """角色模块服务层"""
  16. @classmethod
  17. async def get_role_detail_service(cls, auth: AuthSchema, id: int) -> dict:
  18. """
  19. 获取角色详情
  20. 参数:
  21. - auth (AuthSchema): 认证信息模型
  22. - id (int): 角色ID
  23. 返回:
  24. - dict: 角色详情字典
  25. """
  26. role = await RoleCRUD(auth).get_by_id_crud(id=id)
  27. return RoleOutSchema.model_validate(role).model_dump()
  28. @classmethod
  29. async def get_role_list_service(
  30. cls,
  31. auth: AuthSchema,
  32. search: RoleQueryParam | None = None,
  33. order_by: list[dict[str, str]] | None = None,
  34. ) -> list[dict]:
  35. """
  36. 获取角色列表
  37. 参数:
  38. - auth (AuthSchema): 认证信息模型
  39. - search (RoleQueryParam | None): 查询参数模型
  40. - order_by (list[dict[str, str]] | None): 排序参数列表
  41. 返回:
  42. - list[dict]: 角色详情字典列表
  43. """
  44. role_list = await RoleCRUD(auth).get_list_crud(search=search.__dict__, order_by=order_by)
  45. return [RoleOutSchema.model_validate(role).model_dump() for role in role_list]
  46. @classmethod
  47. async def get_role_page_service(
  48. cls,
  49. auth: AuthSchema,
  50. page_no: int,
  51. page_size: int,
  52. search: RoleQueryParam | None = None,
  53. order_by: list[dict[str, str]] | None = None,
  54. ) -> dict:
  55. """
  56. 分页查询角色(数据库 OFFSET/LIMIT)。
  57. 参数:
  58. - auth (AuthSchema): 认证信息模型
  59. - page_no (int): 页码(从 1 开始)
  60. - page_size (int): 每页条数
  61. - search (RoleQueryParam | None): 查询条件
  62. - order_by (list[dict[str, str]] | None): 排序字段列表
  63. 返回:
  64. - dict: 分页结果(结构由 `CRUD.page` 返回约定)
  65. """
  66. offset = (page_no - 1) * page_size
  67. return await RoleCRUD(auth).page(
  68. offset=offset,
  69. limit=page_size,
  70. order_by=order_by or [{"id": "asc"}],
  71. search=search.__dict__ if search else {},
  72. out_schema=RoleOutSchema,
  73. )
  74. @classmethod
  75. async def create_role_service(cls, auth: AuthSchema, data: RoleCreateSchema) -> dict:
  76. """
  77. 创建角色
  78. 参数:
  79. - auth (AuthSchema): 认证信息模型
  80. - data (RoleCreateSchema): 创建角色模型
  81. 返回:
  82. - dict: 新创建的角色详情字典
  83. """
  84. role = await RoleCRUD(auth).get(name=data.name)
  85. if role:
  86. raise CustomException(msg="创建失败,该角色已存在")
  87. obj = await RoleCRUD(auth).get(code=data.code)
  88. if obj:
  89. raise CustomException(msg="创建失败,编码已存在")
  90. new_role = await RoleCRUD(auth).create(data=data)
  91. return RoleOutSchema.model_validate(new_role).model_dump()
  92. @classmethod
  93. async def update_role_service(cls, auth: AuthSchema, id: int, data: RoleUpdateSchema) -> dict:
  94. """
  95. 更新角色
  96. 参数:
  97. - auth (AuthSchema): 认证信息模型
  98. - id (int): 角色ID
  99. - data (RoleUpdateSchema): 更新角色模型
  100. 返回:
  101. - dict: 更新后的角色详情字典
  102. """
  103. role = await RoleCRUD(auth).get_by_id_crud(id=id)
  104. if not role:
  105. raise CustomException(msg="更新失败,该角色不存在")
  106. exist_role = await RoleCRUD(auth).get(name=data.name)
  107. if exist_role and exist_role.id != id:
  108. raise CustomException(msg="更新失败,角色名称重复")
  109. exist_code = await RoleCRUD(auth).get(code=data.code)
  110. if exist_code and exist_code.id != id:
  111. raise CustomException(msg="更新失败,角色编码已存在")
  112. updated_role = await RoleCRUD(auth).update(id=id, data=data)
  113. return RoleOutSchema.model_validate(updated_role).model_dump()
  114. @classmethod
  115. async def delete_role_service(cls, auth: AuthSchema, ids: list[int]) -> None:
  116. """
  117. 删除角色
  118. 参数:
  119. - auth (AuthSchema): 认证信息模型
  120. - ids (list[int]): 角色ID列表
  121. 返回:
  122. - None
  123. """
  124. if len(ids) < 1:
  125. raise CustomException(msg="删除失败,删除对象不能为空")
  126. for id in ids:
  127. role = await RoleCRUD(auth).get_by_id_crud(id=id)
  128. if not role:
  129. raise CustomException(msg="删除失败,该角色不存在")
  130. await RoleCRUD(auth).delete(ids=ids)
  131. @classmethod
  132. async def set_role_permission_service(
  133. cls, auth: AuthSchema, data: RolePermissionSettingSchema
  134. ) -> None:
  135. """
  136. 设置角色权限
  137. 参数:
  138. - auth (AuthSchema): 认证信息模型
  139. - data (RolePermissionSettingSchema): 角色权限设置模型
  140. 返回:
  141. - None
  142. """
  143. # 设置角色菜单权限
  144. await RoleCRUD(auth).set_role_menus_crud(role_ids=data.role_ids, menu_ids=data.menu_ids)
  145. # 设置数据权限范围
  146. await RoleCRUD(auth).set_role_data_scope_crud(
  147. role_ids=data.role_ids, data_scope=data.data_scope
  148. )
  149. # 设置自定义数据权限部门
  150. if data.data_scope == 5 and data.dept_ids:
  151. await RoleCRUD(auth).set_role_depts_crud(role_ids=data.role_ids, dept_ids=data.dept_ids)
  152. else:
  153. await RoleCRUD(auth).set_role_depts_crud(role_ids=data.role_ids, dept_ids=[])
  154. @classmethod
  155. async def set_role_available_service(cls, auth: AuthSchema, data: BatchSetAvailable) -> None:
  156. """
  157. 设置角色可用状态
  158. 参数:
  159. - auth (AuthSchema): 认证信息模型
  160. - data (BatchSetAvailable): 批量设置可用状态模型
  161. 返回:
  162. - None
  163. """
  164. await RoleCRUD(auth).set_available_crud(ids=data.ids, status=data.status)
  165. @classmethod
  166. async def export_role_list_service(cls, role_list: list[dict[str, Any]]) -> bytes:
  167. """
  168. 导出角色列表
  169. 参数:
  170. - role_list (list[dict[str, Any]]): 角色详情字典列表
  171. 返回:
  172. - bytes: Excel文件字节流
  173. """
  174. # 字段映射配置
  175. mapping_dict = {
  176. "id": "角色编号",
  177. "name": "角色名称",
  178. "order": "显示顺序",
  179. "data_scope": "数据权限",
  180. "status": "状态",
  181. "description": "备注",
  182. "created_time": "创建时间",
  183. "updated_time": "更新时间",
  184. "created_id": "创建者ID",
  185. "updated_id": "更新者ID",
  186. }
  187. # 数据权限映射
  188. data_scope_map = {
  189. 1: "仅本人数据权限",
  190. 2: "本部门数据权限",
  191. 3: "本部门及以下数据权限",
  192. 4: "全部数据权限",
  193. 5: "自定义数据权限",
  194. }
  195. # 处理数据
  196. data = role_list.copy()
  197. for item in data:
  198. item["status"] = "启用" if item.get("status") == "0" else "停用"
  199. item["data_scope"] = data_scope_map.get(item.get("data_scope", 1), "")
  200. item["creator"] = (
  201. item.get("creator", {}).get("name", "未知")
  202. if isinstance(item.get("creator"), dict)
  203. else "未知"
  204. )
  205. return ExcelUtil.export_list2excel(list_data=data, mapping_dict=mapping_dict)