# /system/menu/treeselect 接口执行流程详解 ## 完整执行顺序 ### 1. 控制器层 - SysMenuController.treeselect() **位置**: `SysMenuController.java:84-89` ```java @SaCheckPermission("system:menu:query") // ← 步骤1: 权限校验 @GetMapping("/treeselect") public R>> treeselect(SysMenuBo menu) { // 步骤2: 查询菜单列表 List menus = menuService.selectMenuList(menu, LoginHelper.getUserId()); // 步骤3: 构建树形结构 return R.ok(menuService.buildMenuTreeSelect(menus)); } ``` **执行步骤**: 1. **权限校验**: `@SaCheckPermission("system:menu:query")` - 检查用户是否有 `system:menu:query` 权限 2. **获取用户ID**: `LoginHelper.getUserId()` - 从当前登录上下文获取用户ID 3. **调用服务层**: `menuService.selectMenuList(menu, userId)` 4. **构建树结构**: `menuService.buildMenuTreeSelect(menus)` 5. **返回结果**: 包装成 `R>>` 返回 --- ### 2. 服务层 - SysMenuServiceImpl.selectMenuList() **位置**: `SysMenuServiceImpl.java:73-93` ```java public List selectMenuList(SysMenuBo menu, Long userId) { List menuList; LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); // ========== 步骤A: 权限过滤 ========== if (!LoginHelper.isSuperAdmin(userId)) { // 非超管用户,需要通过角色过滤菜单 wrapper.inSql(SysMenu::getMenuId, baseMapper.buildMenuByUserSql(userId)); } // ========== 步骤B: 平台过滤 ========== int platformId = menu.getPlatformId()==null? PlatformUtils.getId() : menu.getPlatformId(); // ========== 步骤C: 构建查询条件并执行 ========== menuList = baseMapper.selectVoList( wrapper.like(StringUtils.isNotBlank(menu.getMenuName()), SysMenu::getMenuName, menu.getMenuName()) .eq(StringUtils.isNotBlank(menu.getVisible()), SysMenu::getVisible, menu.getVisible()) .eq(StringUtils.isNotBlank(menu.getStatus()), SysMenu::getStatus, menu.getStatus()) .eq(SysMenu::getPlatformId, platformId) // ← 关键:平台过滤 .eq(StringUtils.isNotBlank(menu.getMenuType()), SysMenu::getMenuType, menu.getMenuType()) .eq(ObjectUtil.isNotNull(menu.getParentId()), SysMenu::getParentId, menu.getParentId()) .orderByAsc(SysMenu::getParentId) .orderByAsc(SysMenu::getOrderNum) ); return menuList; } ``` **详细执行流程**: #### 步骤A: 权限过滤(非超管用户) ```java if (!LoginHelper.isSuperAdmin(userId)) { wrapper.inSql(SysMenu::getMenuId, baseMapper.buildMenuByUserSql(userId)); } ``` **生成的SQL子查询** (`buildMenuByUserSql`): ```sql SELECT menu_id FROM sys_role_menu WHERE role_id IN ( SELECT sur.role_id FROM sys_user_role sur LEFT JOIN sys_role sr ON sr.role_id = sur.role_id WHERE sur.user_id = ? AND sr.status = '0' ) ``` **作用**: 获取该用户所有角色分配的菜单ID列表 #### 步骤B: 平台过滤 ```java int platformId = PlatformUtils.getId(); ``` **执行流程**: 1. `PlatformUtils.getId()` 调用 2. 从请求头获取 `PLATFORM_CODE` 3. 根据 `PLATFORM_CODE` 转换为平台ID: - `"PINGTAIDUAN"` → 0 (平台端) - `"SHANGHUDUAN"` → 1 (商户端) #### 步骤C: 最终SQL查询 **商户端用户的完整SQL**: ```sql SELECT * FROM sys_menu WHERE menu_id IN ( -- 用户角色分配的菜单ID列表 SELECT menu_id FROM sys_role_menu WHERE role_id IN (...) ) AND platform_id = 1 -- 商户端 ORDER BY parent_id, order_num ``` **关键点**: 这是一个 **AND 条件**,必须同时满足: - 菜单ID在用户角色分配的列表中 - 菜单的 platform_id = 1 --- ### 3. 数据层 - SysMenuMapper **位置**: `SysMenuMapper.java` 使用 MyBatis-Plus 的 `LambdaQueryWrapper` 自动生成SQL并执行。 --- ### 4. 树结构构建 - buildMenuTreeSelect() **位置**: `SysMenuServiceImpl.java:250-265` ```java public List> buildMenuTreeSelect(List menus) { if (CollUtil.isEmpty(menus)) { return CollUtil.newArrayList(); // ← 如果查询结果为空,返回空列表 } return TreeBuildUtils.build(menus, (menu, tree) -> { tree.setId(menu.getMenuId()) .setParentId(menu.getParentId()) .setName(menu.getMenuName()) .setWeight(menu.getOrderNum()); // ... 设置其他属性 }); } ``` --- ## 为什么商户端查不到数据? ### 问题定位 根据执行流程,商户端查询的SQL实际上是: ```sql SELECT * FROM sys_menu WHERE menu_id IN ( -- 步骤1: 获取用户角色分配的菜单 SELECT menu_id FROM sys_role_menu WHERE role_id IN ( SELECT role_id FROM sys_user_role WHERE user_id = 2038434195944886273 ) ) AND platform_id = 1 -- 步骤2: 过滤商户端菜单 ``` ### 问题原因 **两个条件的交集为空**: 1. **步骤1结果**: 用户角色分配的菜单(假设有 100 条) - 这些菜单的 `platform_id` 可能是 0、NULL 或其他值 2. **步骤2过滤**: `platform_id = 1` - 只保留商户端菜单 3. **交集**: 如果步骤1的100条菜单中,没有一条的 `platform_id = 1` - 最终结果为空 ### 验证方法 执行以下SQL验证: ```sql -- 查看用户角色分配的菜单的平台分布 SELECT sm.platform_id, COUNT(*) as count FROM sys_user_role sur LEFT JOIN sys_role_menu srm ON sur.role_id = srm.role_id LEFT JOIN sys_menu sm ON srm.menu_id = sm.menu_id WHERE sur.user_id = 2038434195944886273 GROUP BY sm.platform_id; ``` **如果结果显示**: - `platform_id = 0`: 100 条 - `platform_id = 1`: 0 条 **说明**: 用户角色分配的菜单都是平台端的,没有商户端的,所以查询结果为空。 --- ## 解决方案 ### 方案1: 修改菜单数据(推荐) 将用户角色需要的菜单改为 `platform_id = 1`: ```sql UPDATE sys_menu SET platform_id = 1 WHERE menu_id IN ( SELECT menu_id FROM sys_role_menu WHERE role_id IN ( SELECT role_id FROM sys_user_role WHERE user_id = 2038434195944886273 ) ); ``` ### 方案2: 重新分配角色菜单 删除旧的菜单权限,分配新的 `platform_id = 1` 的菜单: ```sql -- 1. 获取角色ID SELECT role_id FROM sys_user_role WHERE user_id = 2038434195944886273; -- 2. 删除旧权限 DELETE FROM sys_role_menu WHERE role_id = ?; -- 3. 分配新权限 INSERT INTO sys_role_menu (role_id, menu_id) SELECT ?, menu_id FROM sys_menu WHERE platform_id = 1; ``` --- ## 调试建议 在以下位置添加日志: 1. **SysMenuServiceImpl.java:82** - 查看 `platformId` 的值 2. **SysMenuServiceImpl.java:92** - 查看 `menuList.size()` 3. **PlatformUtils.java:8** - 查看请求头中的 `PLATFORM_CODE` ```java log.info("查询菜单 - userId={}, platformId={}, isSuperAdmin={}", userId, platformId, LoginHelper.isSuperAdmin(userId)); log.info("查询结果 - menuList.size()={}", menuList.size()); ```