Files
DjangoAdmin_FastAPI_EleVue/modules/system/role/service.py
T
ClaudeandClaude 64a5504396 feat(phase4): 全部业务模块迁移到 modules/(结构迁移)
- 21 个模块目录(auth/system/dictionary/configuration/cms/member/region/link/notice/job/log/upload/index)
- 每个模块 router.py(合并模块导出多个 router)/schemas.py/service.py/repository.py/models.py
- routers/v1.py 与 routers/__init__.py 改为直接引用 modules,前缀与权限串原样保留
- core/middleware.py 懒加载指向 modules.system.menu / modules.log;core/redis_client.py 指向 modules.job.scheduler
- apps/views|services|forms 全部改为 re-export 垫片
- 迁移后 grep 守门通过:modules/core 无 apps/extensions 残留引用
- 实测登录、27+ 模块接口、写操作 commit、操作日志落库均正常

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-07 10:13:30 +08:00

259 lines
7.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import asyncio
from datetime import datetime, timezone
from fastapi.logger import logger
from sqlalchemy import and_
from shared.constants import PAGE_SIZE
from modules.system.role.schemas import RoleForm, RoleStatusForm
from modules.system.role.models import Role
from core.database import get_db_session
from core import R
from core.security import get_user_id
from utils.request import like_contains, parse_id_list
from utils.perm_cache import invalidate_role_perms
# 查询角色分页数据
def get_role_page(request):
db = get_db_session()
# 页码
page = int(request.query_params.get("pageNo", 1))
# 每页数
limit = int(request.query_params.get("pageSize", PAGE_SIZE))
# 分页查询
query = db.query(Role).filter(Role.is_delete == 0)
# 角色名称
name = request.query_params.get('name')
if name:
query = query.filter(Role.name.like(like_contains(name), escape='\\'))
# 排序
query = query.order_by(Role.sort.asc())
# 记录总数
count = query.count()
# 查询分页数据
role_list = query.limit(limit).offset((page - 1) * limit).all()
# 若当前页超出末页(数据被并发删除),自动回退到第一页
if page > 1 and not role_list:
page = 1
count = query.count()
role_list = query.limit(limit).offset(0).all()
# 实例化返回对象
result = []
# 遍历数据源
if len(role_list) > 0:
for item in role_list:
# 对象转字典
data = item.to_dict()
# 加入列表
result.append(data)
# 返回结果
return R.ok(data=result, count=count)
# 根据角色ID查询详情
def get_role_detail(role_id):
db = get_db_session()
# 根据ID查询角色
role = db.query(Role).filter(and_(Role.id == role_id, Role.is_delete == 0)).first()
# 查询结果判空
if not role:
return None
# 对象转字典
data = role.to_dict()
# 返回结果
return data
# 添加角色
def add_role(request, data: RoleForm):
db = get_db_session()
# 唯一性校验
if db.query(Role).filter(and_(Role.name == data.name, Role.is_delete == 0)).first():
return R.failed("角色名称不能重复")
# 表单数据赋值给对象
role = Role(**data.model_dump(exclude={'id'}))
role.create_user = get_user_id(request)
# 插入数据
role.save()
# 返回结果
return R.ok(msg="添加成功")
# 更新角色
def update_role(request, data: RoleForm):
db = get_db_session()
# 记录ID判空
if not data.id or data.id <= 0:
return R.failed("记录ID不能为空")
# 唯一性校验(排除自身)
if db.query(Role).filter(and_(Role.name == data.name, Role.id != data.id, Role.is_delete == 0)).first():
return R.failed("角色名称不能重复")
# 根据ID查询记录
role = db.query(Role).filter(and_(Role.id == data.id, Role.is_delete == 0)).first()
# 查询结果判空
if not role:
return R.failed("记录不存在")
# 构造更新数据(排除 id)
updData = data.model_dump(exclude={'id'})
updData['update_user'] = get_user_id(request)
updData['update_time'] = datetime.now(tz=timezone.utc)
result = db.query(Role).filter_by(id=data.id).update(updData)
# 提交数据
if not result:
return R.failed("更新失败")
# 返回结果
return R.ok(msg="更新成功")
# 删除角色
async def delete_role(role_id):
def _delete():
db = get_db_session()
# 记录ID为空判断
if not role_id:
return R.failed("记录ID不存在"), None
# 分裂字符串
id_list = parse_id_list(role_id)
if not id_list:
return R.failed("记录ID不存在"), None
# 批量查询并校验
records = db.query(Role).filter(and_(Role.id.in_(id_list), Role.is_delete == 0)).all()
if len(records) != len(id_list):
return R.failed("记录不存在"), None
# 批量设置删除标识
for record in records:
record.is_delete = 1
return None, (id_list, records)
# 同步DB操作放入线程池,避免阻塞事件循环
err, result = await asyncio.to_thread(_delete)
if err:
return err
id_list, records = result
# 清理被删角色下所有用户的权限缓存
for rid in id_list:
await invalidate_role_perms(rid)
# 返回结果
return R.ok(msg="本次共删除{0}条数据".format(len(records)))
# 设置状态
def update_role_status(request, data: RoleStatusForm):
db = get_db_session()
# 根据ID查询记录
role = db.query(Role).filter(and_(Role.id == data.id, Role.is_delete == 0)).first()
# 查询结果判空
if not role:
return R.failed("记录不存在")
# 更新记录
result = db.query(Role).filter_by(id=data.id).update({
"status": data.status,
"update_user": get_user_id(request),
"update_time": datetime.now(tz=timezone.utc)
})
# 提交数据
if not result:
return R.failed("设置失败")
# 返回结果
return R.ok(msg="设置成功")
# 获取角色列表
def get_role_list():
db = get_db_session()
# 查询角色列表
role_rows = db.query(Role).filter(and_(Role.is_delete == 0, Role.status == 1)).order_by(Role.sort.asc()).all()
# 实例化角色列表
role_list = []
# 遍历数据源
if role_rows:
for v in role_rows:
# 对象转字典
item = v.to_dict()
# 加入数组
role_list.append(item)
# 返回结果
return role_list
import asyncio
from fastapi.logger import logger
from sqlalchemy import and_
from modules.system.role.schemas import RoleMenuForm
from modules.system.menu.models import Menu
from modules.system.role.models import RoleMenu
from core.database import get_db_session
from core import R
from utils.perm_cache import invalidate_role_perms
# 根据角色ID查询菜单列表
def get_role_menu_list(role_id):
db = get_db_session()
# 获取全部菜单列表(仅查询 id、title、parent_id,避免 SELECT * 全量拉取大字段)
menuList = db.query(Menu.id, Menu.title, Menu.parent_id).filter(and_(Menu.is_delete == 0, Menu.status == 1)).order_by(Menu.sort.asc()).all()
if len(menuList) == 0:
return None
# 根据角色ID查询角色菜单关系数据
role_menu = db.query(RoleMenu).filter(RoleMenu.role_id == role_id).all()
# 菜单ID集合
idList = []
# 遍历角色菜单数据源
if role_menu:
for v in role_menu:
# 加入数组
idList.append(v.menu_id)
# 实例化菜单列表
menu_list = []
# 遍历菜单数据
for menu in menuList:
# 菜单ID
menu_id = menu.id
data = {
'id': menu_id,
'title': menu.title,
'open': True,
'parentId': menu.parent_id,
}
if menu_id in idList:
data['checked'] = True
# 加入数组
menu_list.append(data)
# 返回结果
return menu_list
# 保存角色菜单数据
async def save_role_menu(request, data: RoleMenuForm):
def _save():
db = get_db_session()
# 角色ID
role_id = data.role_id
# 菜单ID列表
menuIdList = data.menu_id or []
# 删除当前角色ID相关菜单权限
db.query(RoleMenu).filter(RoleMenu.role_id == role_id).delete()
# 处理菜单数据
if menuIdList:
new_menus = []
for menu_id in menuIdList:
if not menu_id:
continue
new_menus.append(RoleMenu(role_id=role_id, menu_id=menu_id))
db.add_all(new_menus)
return role_id
# 同步DB操作放入线程池,避免阻塞事件循环
role_id = await asyncio.to_thread(_save)
# 清理该角色下所有用户的权限缓存
await invalidate_role_perms(role_id)
# 返回结果
return R.ok()