from __future__ import annotations from fastapi import APIRouter, Depends from sqlalchemy import select from sqlalchemy.orm import Session from iti.auth import require_permission from iti.db import get_db from iti.responses import ok from iti_system.enums import MenuTypeEnum, StatusEnum from iti_system.models import SysMenu from iti_system.schemas import MenuCreate, MenuUpdate from iti_system.services import build_tree, current_user, dump_menu, get_or_404, new_id, visible_menu_tree_for_user router = APIRouter(prefix="/sys/menu", tags=["system.menu"]) @router.get("/list", dependencies=[Depends(require_permission("system:menu:list"))]) def list_menu(db: Session = Depends(get_db)): menus = db.scalars(select(SysMenu).order_by(SysMenu.sort, SysMenu.name)).all() return ok([dump_menu(menu) for menu in menus]) @router.get("/tree") def tree_menu(user=Depends(current_user), db: Session = Depends(get_db)): menus = db.scalars( select(SysMenu) .where( SysMenu.status == StatusEnum.ENABLED.value, SysMenu.type != MenuTypeEnum.BUTTON.value, ) .order_by(SysMenu.sort, SysMenu.name) ).all() return ok(visible_menu_tree_for_user(user, menus)) @router.post("", dependencies=[Depends(require_permission("system:menu:create"))]) def create_menu(payload: MenuCreate, db: Session = Depends(get_db)): menu = SysMenu(id=payload.id or new_id(), **payload.model_dump(exclude={"id"})) db.add(menu) db.commit() db.refresh(menu) return ok(dump_menu(menu)) @router.put("/{id}", dependencies=[Depends(require_permission("system:menu:edit"))]) def update_menu(id: str, payload: MenuUpdate, db: Session = Depends(get_db)): menu = get_or_404(db, SysMenu, id, "菜单不存在") for key, value in payload.model_dump(exclude_unset=True).items(): setattr(menu, key, value) db.commit() db.refresh(menu) return ok(dump_menu(menu)) @router.delete("/{id}", dependencies=[Depends(require_permission("system:menu:delete"))]) def delete_menu(id: str, db: Session = Depends(get_db)): menu = get_or_404(db, SysMenu, id, "菜单不存在") db.delete(menu) db.commit() return ok() @router.get("/exists", dependencies=[Depends(require_permission("system:menu:list"))]) def exists_menu( id: str | None = None, name: str | None = None, path: str | None = None, auth_code: str | None = None, authCode: str | None = None, db: Session = Depends(get_db), ): stmt = select(SysMenu) if id: stmt = stmt.where(SysMenu.id != id) if name: stmt = stmt.where(SysMenu.name == name) if path: stmt = stmt.where(SysMenu.path == path) code = auth_code or authCode if code: stmt = stmt.where(SysMenu.auth_code == code) return ok({"exists": db.scalar(stmt) is not None})