sys_user.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. # -*- coding: utf-8 -*-
  2. # @Author : YY
  3. from typing import List, Optional
  4. from flask import g
  5. from sqlalchemy import and_, or_, func, insert, select, update
  6. from ruoyi_common.base.model import ExtraModel
  7. from ruoyi_common.domain.entity import SysDept, SysRole, SysUser
  8. from ruoyi_common.sqlalchemy.model import ColumnEntityList
  9. from ruoyi_common.sqlalchemy.transaction import Transactional
  10. from ruoyi_system.domain.po import SysDeptPo, SysRolePo, SysUserPo, \
  11. SysUserRolePo
  12. from ruoyi_admin.ext import db
  13. class SysUserMapper:
  14. """
  15. 用户数据访问层
  16. """
  17. default_fields = {
  18. "user_id", "dept_id", "user_name", "nick_name", "email", "phonenumber",
  19. "avatar", "status", "password", "sex", "del_flag", "login_ip",
  20. "login_date", "create_by", "create_time", "update_by", "update_time",
  21. "remark"
  22. }
  23. default_columns = ColumnEntityList(SysUserPo, default_fields, False)
  24. @classmethod
  25. def select_user_list(cls, user: SysUser) -> List[SysUser]:
  26. """
  27. 根据条件,查询用户列表
  28. Args:
  29. user: 用户传输条件信息
  30. Returns:
  31. 用户信息列表
  32. """
  33. dept_vo_fields = {"dept_name","leader"}
  34. user_columns = ColumnEntityList(SysUserPo, cls.default_fields)
  35. dept_columns = ColumnEntityList(SysDeptPo, dept_vo_fields)
  36. criterions = [SysUserPo.del_flag=="0"]
  37. if user.user_id is not None and user.user_id != 0:
  38. criterions.append(SysUserPo.user_id==user.user_id)
  39. if user.user_name is not None and user.user_name != '':
  40. criterions.append(SysUserPo.user_name.like(f"%{user.user_name}%"))
  41. if user.status is not None and user.status != 0:
  42. criterions.append(SysUserPo.status==user.status)
  43. if user.phonenumber is not None and user.phonenumber != '':
  44. criterions.append(SysUserPo.phonenumber.like(f"%{user.phonenumber}%"))
  45. if user.dept_id is not None and user.dept_id != 0:
  46. subquery = select(SysUserPo.dept_id).where(or_(
  47. SysUserPo.dept_id==user.dept_id,
  48. func.find_in_set(user.dept_id, SysDeptPo.ancestors)
  49. )).subquery()
  50. criterions.append(SysUserPo.dept_id.in_(subquery))
  51. if g.criterian_meta.extra:
  52. extra:ExtraModel = g.criterian_meta.extra
  53. if extra.start_time and extra.end_time:
  54. criterions.append(SysUserPo.create_time >= extra.start_time)
  55. criterions.append(SysUserPo.create_time <= extra.end_time)
  56. if g.criterian_meta.scope:
  57. criterions.append(g.criterian_meta.scope)
  58. stmt = select(*user_columns, *dept_columns) \
  59. .join(SysDeptPo,SysUserPo.dept_id==SysDeptPo.dept_id) \
  60. .where(*criterions)
  61. if g.criterian_meta.page:
  62. g.criterian_meta.page.stmt = stmt
  63. rows = db.session.execute(stmt).all()
  64. eos = list()
  65. for row in rows:
  66. user = user_columns.cast(row,SysUser)
  67. user.dept = dept_columns.cast(row,SysDept)
  68. eos.append(user)
  69. return eos
  70. @classmethod
  71. def select_allocated_list(cls, user: SysUser) -> List[SysUser]:
  72. """
  73. 根据条件,查询已配用户角色列表
  74. Args:
  75. user (SysUser): 用户传输条件信息
  76. Returns:
  77. List[SysUser]: 用户信息列表
  78. """
  79. fields = {"user_id", "dept_id", "user_name", "nick_name", "email", \
  80. "phonenumber", "status", "create_time"}
  81. columns = ColumnEntityList(SysUserPo, fields, alia_prefix=False)
  82. criterions = [SysUserPo.del_flag=="0"]
  83. if user.user_name:
  84. criterions.append(SysUserPo.user_name.like(f"%{user.user_name}%"))
  85. if user.phonenumber:
  86. criterions.append(SysUserPo.phonenumber.like(f"%{user.phonenumber}%"))
  87. if "criterian_meta" in g and g.criterian_meta.scope:
  88. criterions.append(g.criterian_meta.scope)
  89. stmt = select(*columns).distinct() \
  90. .join(SysDeptPo, SysUserPo.dept_id==SysDeptPo.dept_id) \
  91. .join(SysUserRolePo, SysUserPo.user_id==SysUserRolePo.user_id) \
  92. .join(SysRolePo, SysUserRolePo.role_id==SysRolePo.role_id) \
  93. .where(*criterions)
  94. rows = db.session.execute(stmt).all()
  95. return [columns.cast(row,SysUser) for row in rows]
  96. @classmethod
  97. def select_unallocated_list(cls, user: SysUser) -> List[SysUser]:
  98. """
  99. 根据条件,查询未分配用户角色列表
  100. Args:
  101. user (SysUser): 用户传输条件信息
  102. Returns:
  103. List[SysUser]: 用户信息列表
  104. """
  105. fields = {
  106. "user_id", "dept_id", "user_name", "nick_name", "email", \
  107. "phonenumber", "status", "create_time"
  108. }
  109. columns = ColumnEntityList(SysUserPo, fields, False)
  110. criterions = [SysUserPo.del_flag=="0"]
  111. subquery = select(SysUserPo.user_id) \
  112. .join(SysUserRolePo, and_(
  113. SysUserPo.user_id==SysUserRolePo.user_id,
  114. SysUserRolePo.role_id==user.role_id
  115. )) \
  116. .subquery()
  117. criterions.append(or_(
  118. SysRolePo.role_id!=user.role_id,
  119. SysRolePo.role_id.is_(None)
  120. ))
  121. criterions.append(SysUserPo.user_id.notin_(subquery))
  122. if user.user_name:
  123. criterions.append(SysUserPo.user_name.like(f"%{user.user_name}%"))
  124. if user.phonenumber:
  125. criterions.append(SysUserPo.phonenumber.like(f"%{user.phonenumber}%"))
  126. if "criterian_meta" in g and g.criterian_meta.scope:
  127. criterions.append(g.criterian_meta.scope)
  128. stmt = select(*columns).distinct() \
  129. .join(SysDeptPo, SysUserPo.dept_id==SysDeptPo.dept_id) \
  130. .join(SysUserRolePo, SysUserPo.user_id==SysUserRolePo.user_id) \
  131. .join(SysRolePo, SysUserRolePo.role_id==SysRolePo.role_id) \
  132. .where(*criterions)
  133. rows = db.session.execute(stmt).all()
  134. return [columns.cast(row,SysUser) for row in rows]
  135. @classmethod
  136. def select_user_by_user_name(cls, user_name: str) -> Optional[SysUser]:
  137. """
  138. 通过用户名查询用户
  139. Args:
  140. user_name (str): 用户名
  141. Returns:
  142. Optional[SysUser]: 用户信息
  143. """
  144. return cls.select_user_by_unique_map("user_name", user_name)
  145. @classmethod
  146. def select_user_by_id(cls, user_id: int) -> Optional[SysUser]:
  147. """
  148. 通过用户ID查询用户
  149. Args:
  150. user_id (int): 用户ID
  151. Returns:
  152. Optional[SysUser]: 用户信息
  153. """
  154. return cls.select_user_by_unique_map("user_id", user_id)
  155. @classmethod
  156. def select_user_by_unique_map(
  157. cls,
  158. key: str,
  159. value: int|str
  160. ) -> Optional[SysUser]:
  161. """
  162. 通过含有唯一键的条件,查询用户
  163. Args:
  164. key (str): 唯一键名
  165. value (int|str): 唯一键值
  166. Returns:
  167. Optional[SysUser]: 用户信息
  168. """
  169. dept_vo_fields = {
  170. "dept_id", "parent_id", "dept_name", "order_num", "leader",
  171. "status"
  172. }
  173. role_vo_fields = {
  174. "role_id", "role_name", "role_key", "role_sort", "data_scope",
  175. "status"
  176. }
  177. user_columns = ColumnEntityList(SysUserPo, cls.default_fields)
  178. dept_columns = ColumnEntityList(SysDeptPo, dept_vo_fields)
  179. role_columns = ColumnEntityList(SysRolePo, role_vo_fields)
  180. column = getattr(SysUserPo, key)
  181. stmt = select(*user_columns,*dept_columns,*role_columns).distinct() \
  182. .join(SysDeptPo, SysUserPo.dept_id==SysDeptPo.dept_id) \
  183. .join(SysUserRolePo, SysUserPo.user_id==SysUserRolePo.user_id) \
  184. .join(SysRolePo, SysUserRolePo.role_id==SysRolePo.role_id) \
  185. .where(column==value)
  186. rows = db.session.execute(stmt).all()
  187. eo_tmp = {}
  188. for row in rows:
  189. if key in eo_tmp:
  190. user = eo_tmp[key]
  191. else:
  192. user = user_columns.cast(row,SysUser)
  193. user.dept = dept_columns.cast(row,SysDept)
  194. eo_tmp[key] = user
  195. user.roles.append(role_columns.cast(row,SysRole))
  196. return eo_tmp[key] if rows else None
  197. @classmethod
  198. @Transactional(db.session)
  199. def insert_user(cls, user: SysUser) -> int:
  200. """
  201. 新增用户信息
  202. Args:
  203. user (SysUser): 用户信息
  204. Returns:
  205. int: 新增记录的ID
  206. """
  207. fields = {
  208. "user_id", "dept_id", "user_name", "nick_name", "email", "avatar",
  209. "phonenumber", "sex", "password", "status", "create_by", "remark"
  210. }
  211. data = user.model_dump(
  212. include=fields,
  213. exclude_unset=True,
  214. exclude_none=True
  215. )
  216. stmt = insert(SysUserPo).values(data)
  217. out = db.session.execute(stmt).inserted_primary_key
  218. return out[0] if out else 0
  219. @classmethod
  220. @Transactional(db.session)
  221. def update_user(cls, user: SysUser) -> int:
  222. """
  223. 修改用户信息
  224. Args:
  225. user (SysUser): 用户信息
  226. Returns:
  227. int: 修改数量
  228. """
  229. fields = {
  230. "dept_id", "user_name", "nick_name", "email", "avatar", "login_ip",
  231. "phonenumber", "sex", "password", "login_date", "status", "update_by",
  232. "remark"
  233. }
  234. data = user.model_dump(
  235. include=fields,exclude_unset=True,exclude_none=True
  236. )
  237. stmt = update(SysUserPo) \
  238. .where(SysUserPo.user_id==user.user_id) \
  239. .values(data)
  240. return db.session.execute(stmt).rowcount
  241. @classmethod
  242. @Transactional(db.session)
  243. def update_user_avatar(cls, user_name: str, avatar: str) -> int:
  244. """
  245. 修改用户头像
  246. Args:
  247. user_name (str): 用户名
  248. avatar (str): 头像地址
  249. Returns:
  250. int: 修改数量
  251. """
  252. stmt = update(SysUserPo) \
  253. .where(SysUserPo.user_name==user_name) \
  254. .values(**{'avatar': avatar})
  255. return db.session.execute(stmt).rowcount
  256. @classmethod
  257. @Transactional(db.session)
  258. def reset_user_pwd(cls, user_name: str, password: str) -> int:
  259. """
  260. 重置用户密码
  261. Args:
  262. user_name (str): 用户名
  263. password (str): 密码
  264. Returns:
  265. int: 修改数量
  266. """
  267. stmt = update(SysUserPo) \
  268. .where(SysUserPo.user_name==user_name) \
  269. .values(password=password)
  270. return db.session.execute(stmt).rowcount
  271. @classmethod
  272. @Transactional(db.session)
  273. def delete_user_by_id(cls, user_id: int) -> int:
  274. """
  275. 通过用户ID删除用户
  276. Args:
  277. user_id (int): 用户ID
  278. Returns:
  279. int: 删除数量
  280. """
  281. stmt = update(SysUserPo).where(SysUserPo.user_id==user_id) \
  282. .values(del_flag="2")
  283. num = db.session.execute(stmt).rowcount
  284. return num
  285. @classmethod
  286. @Transactional(db.session)
  287. def delete_user_by_ids(cls, user_ids: List[int]) -> int:
  288. """
  289. 批量删除用户信息
  290. Args:
  291. user_ids (List[int]): 用户ID列表
  292. Returns:
  293. int: 删除数量
  294. """
  295. stmt = update(SysUserPo).where(SysUserPo.user_id.in_(user_ids)) \
  296. .values(del_flag="2")
  297. num = db.session.execute(stmt).rowcount
  298. return num
  299. @classmethod
  300. def check_user_name_unique(cls, user_name: str) -> int:
  301. """
  302. 校验用户名称是否唯一
  303. Args:
  304. user_name (str): 用户名称
  305. Returns:
  306. int: 0-唯一,大于0-已存在
  307. """
  308. stmt = select(func.count()).select_from(SysUserPo) \
  309. .where(SysUserPo.user_name==user_name)
  310. return db.session.execute(stmt).scalar() or 0
  311. @classmethod
  312. def check_phone_unique(cls, phone_number: str) -> Optional[SysUser]:
  313. """
  314. 校验手机号码是否唯一
  315. Args:
  316. phone_number (str): 手机号码
  317. Returns:
  318. Optional[SysUser]: 用户信息
  319. """
  320. fields = {"user_id","phonenumber"}
  321. columns = ColumnEntityList(
  322. SysUserPo, fields, alia_prefix=False
  323. )
  324. stmt = select(*columns) \
  325. .where(SysUserPo.phonenumber==phone_number)
  326. row = db.session.execute(stmt).one_or_none()
  327. return columns.cast(row,SysUser) if row else None
  328. @classmethod
  329. def check_email_unique(cls, email: str) -> Optional[SysUser]:
  330. """
  331. 校验email是否唯一
  332. Args:
  333. email (str): email
  334. Returns:
  335. Optional[SysUser]: 用户信息
  336. """
  337. fields = {"user_id","email"}
  338. columns = ColumnEntityList(
  339. SysUserPo, fields, alia_prefix=False
  340. )
  341. stmt = select(*columns).where(SysUserPo.email==email)
  342. row = db.session.execute(stmt).one_or_none()
  343. return columns.cast(row,SysUser) if row else None