from fastapi import APIRouter, Depends from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.dependencies import get_db, get_admin_user, get_current_user from app.models.user import User from app.models.menu_config import MenuConfig from app.schemas.menu import MenuConfigCreate, MenuConfigOut from app.utils.id_gen import generate_id router = APIRouter(tags=["menu-configs"]) @router.get("/menu-configs") async def public_list_menu_configs( current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): """Public endpoint: list active menu configs for frontend (frontend + both).""" result = await db.execute( select(MenuConfig) .where( MenuConfig.is_active == True, MenuConfig.menu_target.in_(["frontend", "both"]), ) .order_by(MenuConfig.sort_order) ) menus = result.scalars().all() return [ { "id": m.id, "label": m.label, "path": m.path, "icon": m.icon, "sort_order": m.sort_order, "is_active": m.is_active, "parent_id": m.parent_id, "menu_type": m.menu_type, "menu_target": m.menu_target, "is_default": m.is_default, } for m in menus ] @router.get("/admin/menu-configs", response_model=list[MenuConfigOut]) async def admin_list_menu_configs( admin: User = Depends(get_admin_user), db: AsyncSession = Depends(get_db), ): result = await db.execute(select(MenuConfig).order_by(MenuConfig.sort_order)) return result.scalars().all() @router.post("/admin/menu-configs", response_model=MenuConfigOut) async def create_menu_config( req: MenuConfigCreate, admin: User = Depends(get_admin_user), db: AsyncSession = Depends(get_db), ): menu = MenuConfig(id=generate_id(), **req.model_dump()) db.add(menu) await db.flush() return menu @router.put("/admin/menu-configs/{menu_id}", response_model=MenuConfigOut) async def update_menu_config( menu_id: str, req: MenuConfigCreate, admin: User = Depends(get_admin_user), db: AsyncSession = Depends(get_db), ): result = await db.execute(select(MenuConfig).where(MenuConfig.id == menu_id)) menu = result.scalar_one_or_none() if not menu: from fastapi import HTTPException, status raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="菜单不存在") for k, v in req.model_dump().items(): setattr(menu, k, v) await db.flush() return menu @router.delete("/admin/menu-configs/{menu_id}") async def delete_menu_config( menu_id: str, admin: User = Depends(get_admin_user), db: AsyncSession = Depends(get_db), ): result = await db.execute(select(MenuConfig).where(MenuConfig.id == menu_id)) menu = result.scalar_one_or_none() if not menu: from fastapi import HTTPException, status raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="菜单不存在") await db.delete(menu) await db.flush() return {"message": "ok"}