From 269d453e07fc340f7349e5e161ef3767094a6905 Mon Sep 17 00:00:00 2001 From: NoahLan <6995syu@163.com> Date: Wed, 14 Jan 2026 03:20:40 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=9F=BA=E4=BA=8E=E5=AE=9E=E9=99=85?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E6=8B=A5=E6=9C=89=E8=8F=9C=E5=8D=95=E8=BF=94?= =?UTF-8?q?=E5=9B=9Etree?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- iti/applications/routes/sys/menu.py | 10 +++++++--- iti/applications/service/sys_menu.py | 26 ++++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/iti/applications/routes/sys/menu.py b/iti/applications/routes/sys/menu.py index c0d2327..e9a20f1 100644 --- a/iti/applications/routes/sys/menu.py +++ b/iti/applications/routes/sys/menu.py @@ -1,6 +1,6 @@ import copy from apiflask import APIBlueprint -from flask_jwt_extended import jwt_required +from flask_jwt_extended import jwt_required, current_user from iti.applications.common.exceptions.biz_exp import BizException from iti.applications.extensions import db from iti.applications.models import SysMenu, sys_role_menu @@ -10,7 +10,7 @@ from iti.applications.routes.sys.schemas.menu import ( MenuUpdateRequest, MenuExistsRequest, ) -from iti.applications.service.sys_menu import get_menu_tree +from iti.applications.service.sys_menu import get_menu_tree, get_user_menu_ids from iti.applications.models import SysMenuSchema from iti.applications.common.enums import MenuTypeEnum from sqlalchemy import select, delete, func, exists @@ -40,7 +40,10 @@ def get_menu_tree_api(): 过滤条件: - 状态为启用 - 类型为非按钮 + - 基于当前用户实际拥有的菜单 """ + # 获取当前用户拥有的菜单ID + user_menu_ids = get_user_menu_ids(current_user.id) return success( get_menu_tree( type_filter=[ @@ -48,7 +51,8 @@ def get_menu_tree_api(): MenuTypeEnum.CATALOG, MenuTypeEnum.EMBEDDED, MenuTypeEnum.LINK, - ] + ], + user_menu_ids=user_menu_ids, ) ) diff --git a/iti/applications/service/sys_menu.py b/iti/applications/service/sys_menu.py index 10ea9c5..2ba959c 100644 --- a/iti/applications/service/sys_menu.py +++ b/iti/applications/service/sys_menu.py @@ -1,13 +1,31 @@ from sqlalchemy.orm import noload from sqlalchemy.sql._typing import ColumnExpressionArgument -from typing import List, Dict, Any, Optional +from typing import List, Dict, Any, Optional, Set from iti.applications.extensions import db from iti.applications.models import SysMenu +from iti.applications.models.sys_rel_role_menu import sys_role_menu +from iti.applications.models.sys_rel_user_role import sys_user_role from iti.applications.common.enums import StatusEnum, MenuTypeEnum from iti.applications.common.utils import ( build_tree_from_list, ) -from sqlalchemy import select +from sqlalchemy import select, distinct + + +def get_user_menu_ids(user_id: str) -> Set[str]: + """ + 获取用户拥有的所有菜单ID(通过角色关联) + Args: + user_id: 用户ID + Returns: + 用户拥有的菜单ID集合 + """ + menu_ids = db.session.scalars( + select(distinct(sys_role_menu.c.menu_id)) + .join(sys_user_role, sys_role_menu.c.role_id == sys_user_role.c.role_id) + .filter(sys_user_role.c.user_id == user_id) + ).all() + return set(menu_ids) def get_menu_tree( @@ -15,6 +33,7 @@ def get_menu_tree( include_disabled: bool = True, type_filter: Optional[List[MenuTypeEnum]] = None, status_filter: Optional[List[StatusEnum]] = None, + user_menu_ids: Optional[Set[str]] = None, ) -> List[Dict[str, Any]]: """ 获取菜单树 @@ -23,6 +42,7 @@ def get_menu_tree( include_disabled: 是否包含禁用菜单 type_filter: 菜单类型过滤 不填为不限制 status_filter: 状态过滤 不填为不限制 + user_menu_ids: 用户拥有的菜单ID集合,用于过滤用户实际拥有的菜单 """ # 获取所有菜单数据 cte_query = build_descendants_cte(SysMenu.parent_id == parent_id) @@ -32,6 +52,8 @@ def get_menu_tree( cte_query = cte_query.filter(SysMenu.type.in_(type_filter)) if status_filter: cte_query = cte_query.filter(SysMenu.status.in_(status_filter)) + if user_menu_ids is not None: + cte_query = cte_query.filter(SysMenu.id.in_(user_menu_ids)) cte_query = cte_query.order_by(SysMenu.parent_id, SysMenu.sort).options( noload(SysMenu.parent), noload(SysMenu.children) )