add backend source code
This commit is contained in:
136
backend/app/services/menu_service.py
Normal file
136
backend/app/services/menu_service.py
Normal file
@@ -0,0 +1,136 @@
|
||||
"""
|
||||
菜单服务层
|
||||
"""
|
||||
from typing import Optional, List, Dict, Any
|
||||
from sqlalchemy import select, and_
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy.orm import selectinload
|
||||
|
||||
from app.models.models import Menu, MenuType
|
||||
|
||||
|
||||
class MenuService:
|
||||
"""菜单服务"""
|
||||
|
||||
@staticmethod
|
||||
async def get_tree(db: AsyncSession, visible_only: bool = True) -> List[Dict[str, Any]]:
|
||||
"""获取菜单树形结构"""
|
||||
query = select(Menu).options(selectinload(Menu.children))
|
||||
|
||||
if visible_only:
|
||||
query = query.where(Menu.is_visible == True, Menu.is_active == True)
|
||||
|
||||
query = query.where(Menu.parent_id.is_(None))
|
||||
query = query.order_by(Menu.sort_order, Menu.id)
|
||||
|
||||
result = await db.execute(query)
|
||||
menus = result.scalars().all()
|
||||
|
||||
return [MenuService._menu_to_dict(menu) for menu in menus]
|
||||
|
||||
@staticmethod
|
||||
async def get_list(
|
||||
db: AsyncSession,
|
||||
menu_type: Optional[str] = None,
|
||||
is_visible: Optional[bool] = None
|
||||
) -> List[Menu]:
|
||||
"""获取菜单列表"""
|
||||
query = select(Menu).options(selectinload(Menu.children))
|
||||
|
||||
conditions = []
|
||||
if menu_type:
|
||||
conditions.append(Menu.menu_type == menu_type)
|
||||
if is_visible is not None:
|
||||
conditions.append(Menu.is_visible == is_visible)
|
||||
|
||||
if conditions:
|
||||
query = query.where(and_(*conditions))
|
||||
|
||||
query = query.order_by(Menu.sort_order, Menu.id)
|
||||
result = await db.execute(query)
|
||||
return result.scalars().all()
|
||||
|
||||
@staticmethod
|
||||
async def get_by_id(db: AsyncSession, menu_id: int) -> Optional[Menu]:
|
||||
"""根据 ID 获取菜单"""
|
||||
result = await db.execute(
|
||||
select(Menu).where(Menu.id == menu_id)
|
||||
)
|
||||
return result.scalar_one_or_none()
|
||||
|
||||
@staticmethod
|
||||
async def create(db: AsyncSession, menu_data: dict) -> Menu:
|
||||
"""创建菜单"""
|
||||
menu = Menu(**menu_data)
|
||||
db.add(menu)
|
||||
await db.commit()
|
||||
await db.refresh(menu)
|
||||
return menu
|
||||
|
||||
@staticmethod
|
||||
async def update(db: AsyncSession, menu_id: int, menu_data: dict) -> Optional[Menu]:
|
||||
"""更新菜单"""
|
||||
menu = await MenuService.get_by_id(db, menu_id)
|
||||
if not menu:
|
||||
return None
|
||||
|
||||
for key, value in menu_data.items():
|
||||
if value is not None and hasattr(menu, key):
|
||||
setattr(menu, key, value)
|
||||
|
||||
await db.commit()
|
||||
await db.refresh(menu)
|
||||
return menu
|
||||
|
||||
@staticmethod
|
||||
async def delete(db: AsyncSession, menu_id: int) -> bool:
|
||||
"""删除菜单"""
|
||||
menu = await MenuService.get_by_id(db, menu_id)
|
||||
if not menu:
|
||||
return False
|
||||
|
||||
# 检查是否有子菜单
|
||||
if menu.children:
|
||||
return False
|
||||
|
||||
await db.delete(menu)
|
||||
await db.commit()
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def _menu_to_dict(menu: Menu) -> Dict[str, Any]:
|
||||
"""将菜单对象转换为字典"""
|
||||
return {
|
||||
"id": menu.id,
|
||||
"menu_name": menu.menu_name,
|
||||
"menu_icon": menu.menu_icon,
|
||||
"path": menu.path,
|
||||
"children": [MenuService._menu_to_dict(child) for child in menu.children]
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
async def init_default_menus(db: AsyncSession) -> None:
|
||||
"""初始化默认菜单"""
|
||||
# 检查是否已有菜单
|
||||
result = await db.execute(select(Menu))
|
||||
if result.scalar_one_or_none():
|
||||
return
|
||||
|
||||
# 默认菜单数据
|
||||
default_menus = [
|
||||
{"menu_name": "工作台", "menu_icon": "HomeFilled", "path": "/dashboard", "component": "Dashboard", "sort_order": 1},
|
||||
{"menu_name": "科室管理", "menu_icon": "OfficeBuilding", "path": "/departments", "component": "Departments", "sort_order": 2},
|
||||
{"menu_name": "员工管理", "menu_icon": "User", "path": "/staff", "component": "Staff", "sort_order": 3},
|
||||
{"menu_name": "考核指标", "menu_icon": "DataAnalysis", "path": "/indicators", "component": "Indicators", "sort_order": 4},
|
||||
{"menu_name": "考核管理", "menu_icon": "Document", "path": "/assessments", "component": "Assessments", "sort_order": 5},
|
||||
{"menu_name": "绩效计划", "menu_icon": "Setting", "path": "/plans", "component": "Plans", "sort_order": 6},
|
||||
{"menu_name": "工资核算", "menu_icon": "Money", "path": "/salary", "component": "Salary", "sort_order": 7},
|
||||
{"menu_name": "经济核算", "menu_icon": "Coin", "path": "/finance", "component": "Finance", "sort_order": 8},
|
||||
{"menu_name": "统计报表", "menu_icon": "TrendCharts", "path": "/reports", "component": "Reports", "sort_order": 9},
|
||||
]
|
||||
|
||||
for menu_data in default_menus:
|
||||
menu = Menu(**menu_data)
|
||||
db.add(menu)
|
||||
|
||||
await db.commit()
|
||||
Reference in New Issue
Block a user