Browse Source

perf: 优化用户管理和角色管理模块分页查询

master
insistence 1 year ago
parent
commit
4cdbaa5157
  1. 20
      ruoyi-fastapi-backend/module_admin/controller/role_controller.py
  2. 12
      ruoyi-fastapi-backend/module_admin/controller/user_controller.py
  3. 9
      ruoyi-fastapi-backend/module_admin/dao/role_dao.py
  4. 47
      ruoyi-fastapi-backend/module_admin/dao/user_dao.py
  5. 34
      ruoyi-fastapi-backend/module_admin/service/role_service.py
  6. 20
      ruoyi-fastapi-backend/module_admin/service/user_service.py
  7. 4
      ruoyi-fastapi-backend/utils/common_util.py
  8. 104
      ruoyi-fastapi-backend/utils/page_util.py

20
ruoyi-fastapi-backend/module_admin/controller/role_controller.py

@ -7,7 +7,7 @@ from module_admin.service.dept_service import DeptService, DeptModel
from module_admin.service.user_service import UserService, UserRoleQueryModel, UserRolePageQueryModel, CrudUserRoleModel
from utils.response_util import *
from utils.log_util import *
from utils.page_util import *
from utils.page_util import PageResponseModel
from utils.common_util import bytes2file_response
from module_admin.aspect.interface_auth import CheckUserInterfaceAuth
from module_admin.aspect.data_scope import GetDataScope
@ -33,10 +33,7 @@ async def get_system_role_dept_tree(request: Request, role_id: int, query_db: Se
@roleController.get("/list", response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('system:role:list'))])
async def get_system_role_list(request: Request, role_page_query: RolePageQueryModel = Depends(RolePageQueryModel.as_query), query_db: Session = Depends(get_db)):
try:
role_query = RoleQueryModel(**role_page_query.model_dump(by_alias=True))
role_query_result = RoleService.get_role_list_services(query_db, role_query)
# 分页操作
role_page_query_result = get_page_obj(role_query_result, role_page_query.page_num, role_page_query.page_size)
role_page_query_result = RoleService.get_role_list_services(query_db, role_page_query, is_page=True)
logger.info('获取成功')
return ResponseUtil.success(model_content=role_page_query_result)
except Exception as e:
@ -134,9 +131,8 @@ async def query_detail_system_role(request: Request, role_id: int, query_db: Ses
@log_decorator(title='角色管理', business_type=5)
async def export_system_role_list(request: Request, role_page_query: RolePageQueryModel = Depends(RolePageQueryModel.as_form), query_db: Session = Depends(get_db)):
try:
role_query = RoleQueryModel(**role_page_query.model_dump(by_alias=True))
# 获取全量数据
role_query_result = RoleService.get_role_list_services(query_db, role_query)
role_query_result = RoleService.get_role_list_services(query_db, role_page_query, is_page=False)
role_export_result = RoleService.export_role_list_services(role_query_result)
logger.info('导出成功')
return ResponseUtil.streaming(data=bytes2file_response(role_export_result))
@ -167,10 +163,7 @@ async def reset_system_role_status(request: Request, edit_role: AddRoleModel, qu
@roleController.get("/authUser/allocatedList", response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('common'))])
async def get_system_allocated_user_list(request: Request, user_role: UserRolePageQueryModel = Depends(UserRolePageQueryModel.as_query), query_db: Session = Depends(get_db)):
try:
role_user_query = UserRoleQueryModel(**user_role.model_dump(by_alias=True))
role_user_allocated_query_result = RoleService.get_role_user_allocated_list_services(query_db, role_user_query)
# 分页操作
role_user_allocated_page_query_result = get_page_obj(role_user_allocated_query_result, user_role.page_num, user_role.page_size)
role_user_allocated_page_query_result = RoleService.get_role_user_allocated_list_services(query_db, user_role, is_page=True)
logger.info('获取成功')
return ResponseUtil.success(model_content=role_user_allocated_page_query_result)
except Exception as e:
@ -181,10 +174,7 @@ async def get_system_allocated_user_list(request: Request, user_role: UserRolePa
@roleController.get("/authUser/unallocatedList", response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('common'))])
async def get_system_unallocated_user_list(request: Request, user_role: UserRolePageQueryModel = Depends(UserRolePageQueryModel.as_query), query_db: Session = Depends(get_db)):
try:
role_user_query = UserRoleQueryModel(**user_role.model_dump(by_alias=True))
role_user_unallocated_query_result = RoleService.get_role_user_unallocated_list_services(query_db, role_user_query)
# 分页操作
role_user_unallocated_page_query_result = get_page_obj(role_user_unallocated_query_result, user_role.page_num, user_role.page_size)
role_user_unallocated_page_query_result = RoleService.get_role_user_unallocated_list_services(query_db, user_role, is_page=True)
logger.info('获取成功')
return ResponseUtil.success(model_content=role_user_unallocated_page_query_result)
except Exception as e:

12
ruoyi-fastapi-backend/module_admin/controller/user_controller.py

@ -5,7 +5,7 @@ from config.env import UploadConfig
from module_admin.service.login_service import LoginService
from module_admin.service.user_service import *
from module_admin.service.dept_service import DeptService
from utils.page_util import *
from utils.page_util import PageResponseModel
from utils.response_util import *
from utils.log_util import *
from utils.common_util import bytes2file_response
@ -32,11 +32,8 @@ async def get_system_dept_tree(request: Request, query_db: Session = Depends(get
@userController.get("/list", response_model=PageResponseModel, dependencies=[Depends(CheckUserInterfaceAuth('system:user:list'))])
async def get_system_user_list(request: Request, user_page_query: UserPageQueryModel = Depends(UserPageQueryModel.as_query), query_db: Session = Depends(get_db), data_scope_sql: str = Depends(GetDataScope('SysUser'))):
try:
user_query = UserQueryModel(**user_page_query.model_dump(by_alias=True))
# 获取全量数据
user_query_result = UserService.get_user_list_services(query_db, user_query, data_scope_sql)
# 分页操作
user_page_query_result = get_page_obj(user_query_result, user_page_query.page_num, user_page_query.page_size)
# 获取分页数据
user_page_query_result = UserService.get_user_list_services(query_db, user_page_query, data_scope_sql, is_page=True)
logger.info('获取成功')
return ResponseUtil.success(model_content=user_page_query_result)
except Exception as e:
@ -272,9 +269,8 @@ async def export_system_user_template(request: Request, query_db: Session = Depe
@log_decorator(title='用户管理', business_type=5)
async def export_system_user_list(request: Request, user_page_query: UserPageQueryModel = Depends(UserPageQueryModel.as_form), query_db: Session = Depends(get_db), data_scope_sql: str = Depends(GetDataScope('SysUser'))):
try:
user_query = UserQueryModel(**user_page_query.model_dump(by_alias=True))
# 获取全量数据
user_query_result = UserService.get_user_list_services(query_db, user_query, data_scope_sql)
user_query_result = UserService.get_user_list_services(query_db, user_page_query, data_scope_sql, is_page=False)
user_export_result = UserService.export_user_list_services(user_query_result)
logger.info('导出成功')
return ResponseUtil.streaming(data=bytes2file_response(user_export_result))

9
ruoyi-fastapi-backend/module_admin/dao/role_dao.py

@ -3,6 +3,7 @@ from sqlalchemy.orm import Session
from module_admin.entity.do.role_do import SysRole, SysRoleMenu, SysRoleDept
from module_admin.entity.do.dept_do import SysDept
from module_admin.entity.vo.role_vo import *
from utils.page_util import PageUtil
from datetime import datetime, time
@ -85,14 +86,15 @@ class RoleDao:
return role_info
@classmethod
def get_role_list(cls, db: Session, query_object: RoleQueryModel):
def get_role_list(cls, db: Session, query_object: RolePageQueryModel, is_page: bool = False):
"""
根据查询参数获取角色列表信息
:param db: orm对象
:param query_object: 查询参数对象
:param is_page: 是否开启分页
:return: 角色列表信息对象
"""
role_list = db.query(SysRole) \
query = db.query(SysRole) \
.filter(SysRole.del_flag == 0,
SysRole.role_name.like(f'%{query_object.role_name}%') if query_object.role_name else True,
SysRole.role_key.like(f'%{query_object.role_key}%') if query_object.role_key else True,
@ -103,7 +105,8 @@ class RoleDao:
if query_object.begin_time and query_object.end_time else True
) \
.order_by(SysRole.role_sort) \
.distinct().all()
.distinct()
role_list = PageUtil.paginate(query, query_object.page_num, query_object.page_size, is_page)
return role_list

47
ruoyi-fastapi-backend/module_admin/dao/user_dao.py

@ -6,7 +6,7 @@ from module_admin.entity.do.dept_do import SysDept
from module_admin.entity.do.post_do import SysPost
from module_admin.entity.do.menu_do import SysMenu
from module_admin.entity.vo.user_vo import *
from utils.time_format_util import list_format_datetime
from utils.page_util import PageUtil
from datetime import datetime, time
@ -137,15 +137,16 @@ class UserDao:
return results
@classmethod
def get_user_list(cls, db: Session, query_object: UserQueryModel, data_scope_sql: str):
def get_user_list(cls, db: Session, query_object: UserPageQueryModel, data_scope_sql: str, is_page: bool = False):
"""
根据查询参数获取用户列表信息
:param db: orm对象
:param query_object: 查询参数对象
:param data_scope_sql: 数据权限对应的查询sql语句
:param is_page: 是否开启分页
:return: 用户列表信息对象
"""
user_list = db.query(SysUser, SysDept) \
query = db.query(SysUser, SysDept) \
.filter(SysUser.del_flag == 0,
or_(SysUser.dept_id == query_object.dept_id, SysUser.dept_id.in_(
db.query(SysDept.dept_id).filter(func.find_in_set(query_object.dept_id, SysDept.ancestors))
@ -163,7 +164,8 @@ class UserDao:
eval(data_scope_sql)
) \
.outerjoin(SysDept, and_(SysUser.dept_id == SysDept.dept_id, SysDept.status == 0, SysDept.del_flag == 0)) \
.distinct().all()
.distinct()
user_list = PageUtil.paginate(query, query_object.page_num, query_object.page_size, is_page)
return user_list
@ -227,35 +229,15 @@ class UserDao:
return allocated_role_list
@classmethod
def get_user_role_unallocated_list_by_user_id(cls, db: Session, query_object: UserRoleQueryModel):
"""
根据用户id获取用户未分配的角色列表信息数据库操作
:param db: orm对象
:param query_object: 用户角色查询对象
:return: 用户未分配的角色列表信息
"""
unallocated_role_list = db.query(SysRole) \
.filter(
SysRole.del_flag == 0,
SysRole.role_id != 1,
SysRole.role_name == query_object.role_name if query_object.role_name else True,
SysRole.role_key == query_object.role_key if query_object.role_key else True,
~SysRole.role_id.in_(
db.query(SysUserRole.role_id).filter(SysUserRole.user_id == query_object.user_id)
)
).distinct().all()
return list_format_datetime(unallocated_role_list)
@classmethod
def get_user_role_allocated_list_by_role_id(cls, db: Session, query_object: UserRoleQueryModel):
def get_user_role_allocated_list_by_role_id(cls, db: Session, query_object: UserRolePageQueryModel, is_page: bool = False):
"""
根据角色id获取已分配的用户列表信息
:param db: orm对象
:param query_object: 用户角色查询对象
:param is_page: 是否开启分页
:return: 角色已分配的用户列表信息
"""
allocated_user_list = db.query(SysUser) \
query = db.query(SysUser) \
.filter(
SysUser.del_flag == 0,
SysUser.user_id != 1,
@ -264,19 +246,21 @@ class UserDao:
SysUser.user_id.in_(
db.query(SysUserRole.user_id).filter(SysUserRole.role_id == query_object.role_id)
)
).distinct().all()
).distinct()
allocated_user_list = PageUtil.paginate(query, query_object.page_num, query_object.page_size, is_page)
return allocated_user_list
@classmethod
def get_user_role_unallocated_list_by_role_id(cls, db: Session, query_object: UserRoleQueryModel):
def get_user_role_unallocated_list_by_role_id(cls, db: Session, query_object: UserRolePageQueryModel, is_page: bool = False):
"""
根据角色id获取未分配的用户列表信息
:param db: orm对象
:param query_object: 用户角色查询对象
:param is_page: 是否开启分页
:return: 角色未分配的用户列表信息
"""
unallocated_user_list = db.query(SysUser) \
query = db.query(SysUser) \
.filter(
SysUser.del_flag == 0,
SysUser.user_id != 1,
@ -285,7 +269,8 @@ class UserDao:
~SysUser.user_id.in_(
db.query(SysUserRole.user_id).filter(SysUserRole.role_id == query_object.role_id)
)
).distinct().all()
).distinct()
unallocated_user_list = PageUtil.paginate(query, query_object.page_num, query_object.page_size, is_page)
return unallocated_user_list

34
ruoyi-fastapi-backend/module_admin/service/role_service.py

@ -1,7 +1,8 @@
from module_admin.entity.vo.user_vo import UserInfoModel, UserRoleQueryModel
from module_admin.entity.vo.user_vo import UserInfoModel, UserRolePageQueryModel
from module_admin.entity.vo.common_vo import CrudResponseModel
from module_admin.dao.user_dao import UserDao
from module_admin.dao.role_dao import *
from utils.page_util import PageResponseModel
from utils.common_util import export_list2excel, CamelCaseUtil
@ -38,16 +39,17 @@ class RoleService:
return result
@classmethod
def get_role_list_services(cls, query_db: Session, query_object: RoleQueryModel):
def get_role_list_services(cls, query_db: Session, query_object: RolePageQueryModel, is_page: bool = False):
"""
获取角色列表信息service
:param query_db: orm对象
:param query_object: 查询参数对象
:param is_page: 是否开启分页
:return: 角色列表信息对象
"""
role_list_result = RoleDao.get_role_list(query_db, query_object)
role_list_result = RoleDao.get_role_list(query_db, query_object, is_page)
return CamelCaseUtil.transform_result(role_list_result)
return role_list_result
@classmethod
def add_role_services(cls, query_db: Session, page_object: AddRoleModel):
@ -230,27 +232,39 @@ class RoleService:
return binary_data
@classmethod
def get_role_user_allocated_list_services(cls, query_db: Session, page_object: UserRoleQueryModel):
def get_role_user_allocated_list_services(cls, query_db: Session, page_object: UserRolePageQueryModel, is_page: bool = False):
"""
根据角色id获取已分配用户列表
:param query_db: orm对象
:param page_object: 用户关联角色对象
:param is_page: 是否开启分页
:return: 已分配用户列表
"""
query_user_list = UserDao.get_user_role_allocated_list_by_role_id(query_db, page_object)
allocated_list = [UserInfoModel(**CamelCaseUtil.transform_result(row)) for row in query_user_list]
query_user_list = UserDao.get_user_role_allocated_list_by_role_id(query_db, page_object, is_page)
allocated_list = PageResponseModel(
**{
**query_user_list.model_dump(by_alias=True),
'rows': [UserInfoModel(**row) for row in query_user_list.rows]
}
)
return allocated_list
@classmethod
def get_role_user_unallocated_list_services(cls, query_db: Session, page_object: UserRoleQueryModel):
def get_role_user_unallocated_list_services(cls, query_db: Session, page_object: UserRolePageQueryModel, is_page: bool = False):
"""
根据角色id获取未分配用户列表
:param query_db: orm对象
:param page_object: 用户关联角色对象
:param is_page: 是否开启分页
:return: 未分配用户列表
"""
query_user_list = UserDao.get_user_role_unallocated_list_by_role_id(query_db, page_object)
unallocated_list = [UserInfoModel(**CamelCaseUtil.transform_result(row)) for row in query_user_list]
query_user_list = UserDao.get_user_role_unallocated_list_by_role_id(query_db, page_object, is_page)
unallocated_list = PageResponseModel(
**{
**query_user_list.model_dump(by_alias=True),
'rows': [UserInfoModel(**row) for row in query_user_list.rows]
}
)
return unallocated_list

20
ruoyi-fastapi-backend/module_admin/service/user_service.py

@ -3,6 +3,7 @@ from module_admin.service.role_service import RoleService
from module_admin.service.post_service import PostService
from module_admin.entity.vo.common_vo import CrudResponseModel
from module_admin.dao.user_dao import *
from utils.page_util import PageResponseModel
from utils.pwd_util import *
from utils.common_util import *
@ -13,18 +14,27 @@ class UserService:
"""
@classmethod
def get_user_list_services(cls, query_db: Session, query_object: UserQueryModel, data_scope_sql: str):
def get_user_list_services(cls, query_db: Session, query_object: UserPageQueryModel, data_scope_sql: str, is_page: bool = False):
"""
获取用户列表信息service
:param query_db: orm对象
:param query_object: 查询参数对象
:param data_scope_sql: 数据权限对应的查询sql语句
:param is_page: 是否开启分页
:return: 用户列表信息对象
"""
query_result = UserDao.get_user_list(query_db, query_object, data_scope_sql)
user_list_result = []
if query_result:
user_list_result = [{**CamelCaseUtil.transform_result(row[0]), 'dept': CamelCaseUtil.transform_result(row[1])} for row in query_result]
query_result = UserDao.get_user_list(query_db, query_object, data_scope_sql, is_page)
if is_page:
user_list_result = PageResponseModel(
**{
**query_result.model_dump(by_alias=True),
'rows': [{**row[0], 'dept': row[1]} for row in query_result.rows]
}
)
else:
user_list_result = []
if query_result:
user_list_result = [{**row[0], 'dept': row[1]} for row in query_result]
return user_list_result

4
ruoyi-fastapi-backend/utils/common_util.py

@ -5,6 +5,7 @@ from openpyxl import Workbook
from openpyxl.styles import Alignment, PatternFill
from openpyxl.utils import get_column_letter
from openpyxl.worksheet.datavalidation import DataValidation
from sqlalchemy.engine.row import Row
from typing import List
from config.env import CachePathConfig
@ -66,6 +67,9 @@ class CamelCaseUtil:
return {cls.__to_camel_case(k): v for k, v in result.items()}
# 如果是一组字典或其他类型的列表,遍历列表进行转换
elif isinstance(result, list):
return [cls.transform_result(row) if isinstance(row, (dict, Row)) else cls.transform_result({c.name: getattr(row, c.name) for c in row.__table__.columns}) for row in result]
# 如果是sqlalchemy的Row实例,遍历Row进行转换
elif isinstance(result, Row):
return [cls.transform_result(row) if isinstance(row, dict) else cls.transform_result({c.name: getattr(row, c.name) for c in row.__table__.columns}) for row in result]
# 如果是其他类型,如模型实例,先转换为字典
else:

104
ruoyi-fastapi-backend/utils/page_util.py

@ -1,30 +1,9 @@
import math
from typing import Optional, List
from sqlalchemy.orm.query import Query
from pydantic import BaseModel, ConfigDict
from pydantic.alias_generators import to_camel
class PageModel(BaseModel):
"""
分页模型
"""
offset: int
page_num: int
page_size: int
total: int
has_next: bool
class PageObjectResponse(BaseModel):
"""
用户管理列表分页查询返回模型
"""
rows: List = []
page_num: int
page_size: int
total: int
has_next: bool
from utils.common_util import CamelCaseUtil
class PageResponseModel(BaseModel):
@ -40,33 +19,64 @@ class PageResponseModel(BaseModel):
has_next: Optional[bool] = None
def get_page_info(offset: int, page_num: int, page_size: int, count: int):
class PageUtil:
"""
根据分页参数获取分页信息
:param offset: 起始数据位置
:param page_num: 当前页码
:param page_size: 当前页面数据量
:param count: 数据总数
:return: 分页信息对象
分页工具类
"""
has_next = False
if offset >= count:
res_offset_1 = (page_num - 2) * page_size
if res_offset_1 < 0:
res_offset = 0
res_page_num = 1
else:
res_offset = res_offset_1
res_page_num = page_num - 1
else:
res_offset = offset
if (res_offset + page_size) < count:
has_next = True
res_page_num = page_num
result = dict(offset=res_offset, page_num=res_page_num, page_size=page_size, total=count, has_next=has_next)
@classmethod
def get_page_obj(cls, data_list: List, page_num: int, page_size: int):
"""
输入数据列表data_list和分页信息返回分页数据列表结果
:param data_list: 原始数据列表
:param page_num: 当前页码
:param page_size: 当前页面数据量
:return: 分页数据对象
"""
# 计算起始索引和结束索引
start = (page_num - 1) * page_size
end = page_num * page_size
# 根据计算得到的起始索引和结束索引对数据列表进行切片
paginated_data = data_list[start:end]
has_next = True if math.ceil(len(data_list) / page_size) > page_num else False
result = PageResponseModel(
rows=paginated_data,
pageNum=page_num,
pageSize=page_size,
total=len(data_list),
hasNext=has_next
)
return result
@classmethod
def paginate(cls, query: Query, page_num: int, page_size: int, is_page: bool = False):
"""
输入查询语句和分页信息返回分页数据列表结果
:param query: sqlalchemy查询语句
:param page_num: 当前页码
:param page_size: 当前页面数据量
:param is_page: 是否开启分页
:return: 分页数据对象
"""
if is_page:
total = query.count()
paginated_data = query.offset((page_num - 1) * page_size).limit(page_size).all()
has_next = True if math.ceil(len(paginated_data) / page_size) > page_num else False
result = PageResponseModel(
rows=CamelCaseUtil.transform_result(paginated_data),
pageNum=page_num,
pageSize=page_size,
total=total,
hasNext=has_next
)
else:
no_paginated_data = query.all()
result = CamelCaseUtil.transform_result(no_paginated_data)
return PageModel(**result)
return result
def get_page_obj(data_list: List, page_num: int, page_size: int):
@ -94,5 +104,3 @@ def get_page_obj(data_list: List, page_num: int, page_size: int):
)
return result

Loading…
Cancel
Save