import json from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.dependencies import get_db, get_admin_user, get_backend_user from app.models.user import User from app.models.menu_config import MenuConfig from app.schemas.menu import MenuConfigCreate, MenuConfigOut from app.services.operation_log import log_operation from app.utils.id_gen import generate_id router = APIRouter(prefix="/admin/menu-configs", tags=["admin-menu-configs"]) @router.get("", response_model=list[MenuConfigOut]) async def admin_list_menu_configs( admin: User = Depends(get_backend_user), db: AsyncSession = Depends(get_db), ): result = await db.execute(select(MenuConfig).order_by(MenuConfig.sort_order)) return result.scalars().all() @router.post("", 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() await log_operation( db, admin.id, admin.username, f"创建菜单 {menu.label}", "POST", "/admin/menu-configs", detail=json.dumps( { "id": menu.id, "label": menu.label, "path": menu.path, "menu_target": menu.menu_target, "menu_type": menu.menu_type, }, ensure_ascii=False, ), ) return menu @router.put("/{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).limit(1)) menu = result.scalar_one_or_none() if not menu: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="菜单不存在") before_label = menu.label for k, v in req.model_dump().items(): setattr(menu, k, v) await db.flush() await log_operation( db, admin.id, admin.username, f"更新菜单 {before_label}", "PUT", f"/admin/menu-configs/{menu_id}", detail=json.dumps( { "id": menu_id, "before": {"label": before_label}, "after": { "label": menu.label, "path": menu.path, "is_active": menu.is_active, "sort_order": menu.sort_order, }, }, ensure_ascii=False, ), ) return menu @router.delete("/{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).limit(1)) menu = result.scalar_one_or_none() if not menu: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="菜单不存在") menu_label = menu.label await db.delete(menu) await db.flush() await log_operation( db, admin.id, admin.username, f"删除菜单 {menu_label}", "DELETE", f"/admin/menu-configs/{menu_id}", detail=json.dumps( { "id": menu_id, "label": menu_label, "path": menu.path, }, ensure_ascii=False, ), ) return {"message": "ok"}