瀏覽代碼

菜单部分

zhaopeiqing 1 年之前
父節點
當前提交
2d671d6c47
共有 25 個文件被更改,包括 799 次插入34 次删除
  1. 1 0
      yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java
  2. 5 3
      yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/permission/RoleCodeEnum.java
  3. 32 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/MenuController.java
  4. 98 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/MenuTenantRelateController.java
  5. 3 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuListReqVO.java
  6. 6 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuRespVO.java
  7. 31 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuTenantRelatePageReqVO.java
  8. 35 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuTenantRelateRespVO.java
  9. 26 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuTenantRelateSaveReqVO.java
  10. 10 2
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantController.java
  11. 2 1
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/permission/MenuDO.java
  12. 43 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/permission/MenuTenantRelateDO.java
  13. 30 1
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/MenuMapper.java
  14. 26 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/MenuTenantRelateMapper.java
  15. 2 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/RoleMenuMapper.java
  16. 28 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuService.java
  17. 99 4
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImpl.java
  18. 56 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuTenantRelateService.java
  19. 71 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuTenantRelateServiceImpl.java
  20. 5 3
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java
  21. 7 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleService.java
  22. 5 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java
  23. 125 15
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java
  24. 45 0
      yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/permission/MenuMapper.xml
  25. 8 5
      yudao-server/src/main/resources/application.yaml

+ 1 - 0
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java

@@ -24,6 +24,7 @@ public interface ErrorCodeConstants {
     ErrorCode MENU_NOT_EXISTS = new ErrorCode(1_002_001_003, "菜单不存在");
     ErrorCode MENU_EXISTS_CHILDREN = new ErrorCode(1_002_001_004, "存在子菜单,无法删除");
     ErrorCode MENU_PARENT_NOT_DIR_OR_MENU = new ErrorCode(1_002_001_005, "父菜单的类型必须是目录或者菜单");
+    ErrorCode TENANT_RELATE_NOT_EXISTS = new ErrorCode(1_002_001_006, "菜单租户关系不存在");
 
     // ========== 角色模块 1-002-002-000 ==========
     ErrorCode ROLE_NOT_EXISTS = new ErrorCode(1_002_002_000, "角色不存在");

+ 5 - 3
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/permission/RoleCodeEnum.java

@@ -13,9 +13,11 @@ public enum RoleCodeEnum {
 
     SUPER_ADMIN("super_admin", "超级管理员"),
     TENANT_ADMIN("tenant_admin", "租户管理员"),
-    CRM_ADMIN("crm_admin", "CRM 管理员"),
-    TENANT_SUPER_ADMIN("tenant_super_admin", "租户超级管理员"),; // CRM 系统专用
-    ;
+    CRM_ADMIN("crm_admin", "CRM 管理员"),// CRM 系统专用
+    SYSTEM_SUPER_ADMIN("system_super_admin", "系统管理员"),
+    SYSTEM_ADMIN("system_admin", "管理员"),
+    COMMON_EMPLOYEE("common_employee", "普通员工"),
+    DEPARTMENT_LEADER("department_leader", "部门负责人");
 
     /**
      * 角色编码

+ 32 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/MenuController.java

@@ -3,11 +3,14 @@ package cn.iocoder.yudao.module.system.controller.admin.permission;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthPermissionInfoRespVO;
 import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuListReqVO;
 import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuRespVO;
 import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuSaveVO;
 import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuSimpleRespVO;
+import cn.iocoder.yudao.module.system.convert.auth.AuthConvert;
 import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
+import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
 import cn.iocoder.yudao.module.system.service.permission.MenuService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
@@ -20,8 +23,10 @@ import javax.annotation.Resource;
 import javax.validation.Valid;
 import java.util.Comparator;
 import java.util.List;
+import java.util.Set;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
 
 @Tag(name = "管理后台 - 菜单")
 @RestController
@@ -84,4 +89,31 @@ public class MenuController {
         return success(BeanUtils.toBean(menu, MenuRespVO.class));
     }
 
+    @GetMapping("/getListByMenuId")
+    @Operation(summary = "通过menuId查询本身及子级树", description = "parentId=0的菜单,表示应用")
+    public CommonResult<List<AuthPermissionInfoRespVO.MenuVO>> getListByMenuId(@RequestParam("menuId") Long menuId) {
+        List<MenuDO> menuList = menuService.getListByMenuId(menuId);
+        List<AuthPermissionInfoRespVO.MenuVO> menuVOList = AuthConvert.INSTANCE.buildMenuTree(menuList);
+        return success(menuVOList);
+    }
+
+    // 获取所有一、二级菜单,用于首页显示
+    @GetMapping("/getPrimarySecondaryMenus")
+    @Operation(summary = "获取所有一、二级菜单", description = "用于首页显示")
+    public CommonResult<List<MenuRespVO>> getPrimarySecondaryMenus() {
+        List<MenuRespVO> list = menuService.getPrimarySecondaryMenus();
+        list.sort(Comparator.comparing(MenuRespVO::getSort));
+        return success(list);
+    }
+
+    // 通过menuId查询本身及子级树
+
+    @GetMapping("/getTenantMenus")
+    @Operation(summary = "获取租户下的菜单", description = "用于【分配菜单权限】界面")
+    public CommonResult<List<MenuRespVO>> getTenantMenus(MenuListReqVO reqVO) {
+        List<MenuRespVO> list = menuService.getTenantMenus(reqVO);
+        list.sort(Comparator.comparing(MenuRespVO::getSort));
+        return success(BeanUtils.toBean(list, MenuRespVO.class));
+    }
+
 }

+ 98 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/MenuTenantRelateController.java

@@ -0,0 +1,98 @@
+package cn.iocoder.yudao.module.system.controller.admin.permission;
+
+import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuTenantRelatePageReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuTenantRelateRespVO;
+import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuTenantRelateSaveReqVO;
+import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuTenantRelateDO;
+import cn.iocoder.yudao.module.system.service.permission.MenuTenantRelateService;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.security.access.prepost.PreAuthorize;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Operation;
+
+import java.io.IOException;
+import java.util.List;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
+
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+
+import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
+
+
+@Tag(name = "管理后台 - 菜单租户关系")
+@RestController
+@RequestMapping("/menu/tenant-relate")
+@Validated
+public class MenuTenantRelateController {
+
+    @Resource
+    private MenuTenantRelateService tenantRelateService;
+
+    @PostMapping("/create")
+    @Operation(summary = "创建菜单租户关系")
+    @PreAuthorize("@ss.hasPermission('menu:tenant-relate:create')")
+    public CommonResult<Long> createTenantRelate(@Valid @RequestBody MenuTenantRelateSaveReqVO createReqVO) {
+        return success(tenantRelateService.createTenantRelate(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新菜单租户关系")
+    @PreAuthorize("@ss.hasPermission('menu:tenant-relate:update')")
+    public CommonResult<Boolean> updateTenantRelate(@Valid @RequestBody MenuTenantRelateSaveReqVO updateReqVO) {
+        tenantRelateService.updateTenantRelate(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除菜单租户关系")
+    @Parameter(name = "id", description = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('menu:tenant-relate:delete')")
+    public CommonResult<Boolean> deleteTenantRelate(@RequestParam("id") Long id) {
+        tenantRelateService.deleteTenantRelate(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得菜单租户关系")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('menu:tenant-relate:query')")
+    public CommonResult<MenuTenantRelateRespVO> getTenantRelate(@RequestParam("id") Long id) {
+        MenuTenantRelateDO tenantRelate = tenantRelateService.getTenantRelate(id);
+        return success(BeanUtils.toBean(tenantRelate, MenuTenantRelateRespVO.class));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得菜单租户关系分页")
+    @PreAuthorize("@ss.hasPermission('menu:tenant-relate:query')")
+    public CommonResult<PageResult<MenuTenantRelateRespVO>> getTenantRelatePage(@Valid MenuTenantRelatePageReqVO pageReqVO) {
+        PageResult<MenuTenantRelateDO> pageResult = tenantRelateService.getTenantRelatePage(pageReqVO);
+        return success(BeanUtils.toBean(pageResult, MenuTenantRelateRespVO.class));
+    }
+
+    @GetMapping("/export-excel")
+    @Operation(summary = "导出菜单租户关系 Excel")
+    @PreAuthorize("@ss.hasPermission('menu:tenant-relate:export')")
+    @ApiAccessLog(operateType = EXPORT)
+    public void exportTenantRelateExcel(@Valid MenuTenantRelatePageReqVO pageReqVO,
+              HttpServletResponse response) throws IOException {
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        List<MenuTenantRelateDO> list = tenantRelateService.getTenantRelatePage(pageReqVO).getList();
+        // 导出 Excel
+        ExcelUtils.write(response, "菜单租户关系.xls", "数据", MenuTenantRelateRespVO.class,
+                        BeanUtils.toBean(list, MenuTenantRelateRespVO.class));
+    }
+
+}

+ 3 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuListReqVO.java

@@ -16,4 +16,7 @@ public class MenuListReqVO {
     @Schema(description = "租户编码", example = "1")
     private Long tenantId;
 
+    @Schema(description = "父级ID", example = "0")
+    private Long parentId;
+
 }

+ 6 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuRespVO.java

@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu;
 
+import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.AllArgsConstructor;
 import lombok.Data;
@@ -10,6 +11,8 @@ import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.NotNull;
 import javax.validation.constraints.Size;
 import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
 
 @Schema(description = "管理后台 - 菜单信息 Response VO")
 @Data
@@ -69,4 +72,7 @@ public class MenuRespVO {
     @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "时间戳格式")
     private LocalDateTime createTime;
 
+    // 假设有一个子菜单列表
+    private List<MenuDO> children = new ArrayList<>();
+
 }

+ 31 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuTenantRelatePageReqVO.java

@@ -0,0 +1,31 @@
+package cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu;
+
+import lombok.*;
+import java.util.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 菜单租户关系分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class MenuTenantRelatePageReqVO extends PageParam {
+
+    @Schema(description = "菜单ID", example = "29703")
+    private Long menuId;
+
+    @Schema(description = "租户ID", example = "29703")
+    private Long tenantId;
+
+    @Schema(description = "状态", example = "2")
+    private Integer status;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+}

+ 35 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuTenantRelateRespVO.java

@@ -0,0 +1,35 @@
+package cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import java.util.*;
+import java.util.*;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDateTime;
+import com.alibaba.excel.annotation.*;
+
+@Schema(description = "管理后台 - 菜单租户关系 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class MenuTenantRelateRespVO {
+
+    @Schema(description = "关系ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "17346")
+    @ExcelProperty("关系ID")
+    private Long id;
+
+    @Schema(description = "菜单ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "29703")
+    @ExcelProperty("菜单ID")
+    private Long menuId;
+
+    @Schema(description = "租户ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "29703")
+    private Long tenantId;
+
+    @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+    @ExcelProperty("状态")
+    private Integer status;
+
+    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+
+}

+ 26 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/menu/MenuTenantRelateSaveReqVO.java

@@ -0,0 +1,26 @@
+package cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+
+import javax.validation.constraints.NotNull;
+
+@Schema(description = "管理后台 - 菜单租户关系新增/修改 Request VO")
+@Data
+public class MenuTenantRelateSaveReqVO {
+
+    @Schema(description = "关系ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "17346")
+    private Long id;
+
+    @Schema(description = "菜单ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "29703")
+    @NotNull(message = "菜单ID不能为空")
+    private Long menuId;
+
+    @Schema(description = "租户ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "29703")
+    @NotNull(message = "租户ID不能为空")
+    private Long tenantId;
+
+    @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+    private Integer status;
+
+}

+ 10 - 2
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantController.java

@@ -12,7 +12,9 @@ import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
 import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthLoginRespVO;
 import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.*;
 import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
+import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
 import cn.iocoder.yudao.module.system.service.tenant.TenantService;
+import cn.iocoder.yudao.module.system.service.user.AdminUserService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.tags.Tag;
@@ -41,6 +43,8 @@ public class TenantController {
     private TenantService tenantService;
     @Resource
     private SecurityProperties securityProperties;
+    @Resource
+    private AdminUserService userService;
 
     @GetMapping("/get-id-by-name")
     @PermitAll
@@ -114,10 +118,14 @@ public class TenantController {
     public CommonResult<TenantRespVO> getTenant() {
         // 获得用户信息
         LoginUser user = SecurityFrameworkUtils.getLoginUser();
-        if (user == null || user.getTenantId() == null) {
+        if (user == null) {
+            throw exception(USER_NOT_EXISTS);
+        }
+        AdminUserDO adminUserDO = userService.getUser(user.getId());
+        if (adminUserDO == null || adminUserDO.getTenantId() == null) {
             throw exception(USER_NOT_EXISTS);
         }
-        TenantDO tenant = tenantService.getTenant(user.getTenantId());
+        TenantDO tenant = tenantService.getTenant(adminUserDO.getTenantId());
         return success(BeanUtils.toBean(tenant, TenantRespVO.class));
     }
 

+ 2 - 1
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/permission/MenuDO.java

@@ -14,7 +14,8 @@ import lombok.EqualsAndHashCode;
  *
  * @author ruoyi
  */
-@TableName("system_menu")
+// todo: 临时
+@TableName("system_menu_copy1")
 @KeySequence("system_menu_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
 @Data
 @EqualsAndHashCode(callSuper = true)

+ 43 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/permission/MenuTenantRelateDO.java

@@ -0,0 +1,43 @@
+package cn.iocoder.yudao.module.system.dal.dataobject.permission;
+
+import lombok.*;
+import java.util.*;
+import java.time.LocalDateTime;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.*;
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+
+/**
+ * 菜单租户关系 DO
+ *
+ * @author zhaopq
+ */
+@TableName("menu_tenant_relate")
+@KeySequence("menu_tenant_relate_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class MenuTenantRelateDO extends BaseDO {
+
+    /**
+     * 关系ID
+     */
+    @TableId
+    private Long id;
+    /**
+     * 菜单ID
+     */
+    private Long menuId;
+    /**
+     * 租户ID
+     */
+    private Long tenantId;
+    /**
+     * 状态
+     */
+    private Integer status;
+
+}

+ 30 - 1
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/MenuMapper.java

@@ -2,30 +2,59 @@ package cn.iocoder.yudao.module.system.dal.mysql.permission;
 
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
 import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuListReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuRespVO;
+import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuSaveVO;
 import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
 
+import java.util.Collection;
 import java.util.List;
 
 @Mapper
 public interface MenuMapper extends BaseMapperX<MenuDO> {
 
+    @TenantIgnore
     default MenuDO selectByParentIdAndName(Long parentId, String name) {
         return selectOne(MenuDO::getParentId, parentId, MenuDO::getName, name);
     }
 
+    @TenantIgnore
     default Long selectCountByParentId(Long parentId) {
         return selectCount(MenuDO::getParentId, parentId);
     }
 
+    @TenantIgnore
     default List<MenuDO> selectList(MenuListReqVO reqVO) {
         return selectList(new LambdaQueryWrapperX<MenuDO>()
                 .likeIfPresent(MenuDO::getName, reqVO.getName())
-                .eqIfPresent(MenuDO::getStatus, reqVO.getStatus()));
+                .eqIfPresent(MenuDO::getStatus, reqVO.getStatus())
+                .eqIfPresent(MenuDO::getParentId, reqVO.getParentId()));
     }
 
+    @TenantIgnore
     default List<MenuDO> selectListByPermission(String permission) {
         return selectList(MenuDO::getPermission, permission);
     }
+
+    @TenantIgnore
+    List<MenuRespVO> getTenantMenus(@Param("reqVO") MenuListReqVO reqVO);
+
+    @TenantIgnore
+    default MenuDO getMenuById(Long menuId) {
+        return selectOne(MenuDO::getId, menuId);
+    }
+
+    @TenantIgnore
+    default List<MenuDO> getMenuListByIds(Collection<Long> ids) {
+        return selectBatchIds(ids);
+    }
+
+//    @TenantIgnore
+//    default Long updateMenuById(MenuSaveVO updateReqVO) {
+//        return updateById(updateReqVO);
+//    }
+
 }

+ 26 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/MenuTenantRelateMapper.java

@@ -0,0 +1,26 @@
+package cn.iocoder.yudao.module.system.dal.mysql.permission;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuTenantRelatePageReqVO;
+import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuTenantRelateDO;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 菜单租户关系 Mapper
+ *
+ * @author zhaopq
+ */
+@Mapper
+public interface MenuTenantRelateMapper extends BaseMapperX<MenuTenantRelateDO> {
+
+    default PageResult<MenuTenantRelateDO> selectPage(MenuTenantRelatePageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<MenuTenantRelateDO>()
+                .eqIfPresent(MenuTenantRelateDO::getMenuId, reqVO.getMenuId())
+                .eqIfPresent(MenuTenantRelateDO::getStatus, reqVO.getStatus())
+                .betweenIfPresent(MenuTenantRelateDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(MenuTenantRelateDO::getId));
+    }
+
+}

+ 2 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/RoleMenuMapper.java

@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.system.dal.mysql.permission;
 
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
 import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleMenuDO;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import org.apache.ibatis.annotations.Mapper;
@@ -15,6 +16,7 @@ public interface RoleMenuMapper extends BaseMapperX<RoleMenuDO> {
         return selectList(RoleMenuDO::getRoleId, roleId);
     }
 
+    @TenantIgnore
     default List<RoleMenuDO> selectListByRoleId(Collection<Long> roleIds) {
         return selectList(RoleMenuDO::getRoleId, roleIds);
     }

+ 28 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuService.java

@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.module.system.service.permission;
 
+import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuRespVO;
 import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuSaveVO;
 import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuListReqVO;
 import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
@@ -84,4 +85,31 @@ public interface MenuService {
      */
     List<MenuDO> getMenuList(Collection<Long> ids);
 
+    /**
+     * 通过parentId和Name查询菜单
+     *
+     * @param parentId
+     * @param name
+     * @return
+     */
+    MenuDO selectByParentIdAndName(Long parentId, String name);
+
+    /**
+     * 获取租户下的菜单
+     *
+     * @param reqVO 筛选条件请求 VO
+     * @return 菜单列表
+     */
+    List<MenuRespVO> getTenantMenus(MenuListReqVO reqVO);
+
+    /**
+     * 获取一、二级菜单
+     *
+     * @return
+     */
+    List<MenuRespVO> getPrimarySecondaryMenus();
+
+    List<MenuDO> getListByMenuId(Long menuId);
+
+//    List<MenuDO> getMenuListByIds(Collection<Long> ids);
 }

+ 99 - 4
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuServiceImpl.java

@@ -1,14 +1,21 @@
 package cn.iocoder.yudao.module.system.service.permission;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.security.core.LoginUser;
+import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
+import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
 import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuListReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuRespVO;
 import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuSaveVO;
 import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
+import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
 import cn.iocoder.yudao.module.system.dal.mysql.permission.MenuMapper;
 import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants;
 import cn.iocoder.yudao.module.system.enums.permission.MenuTypeEnum;
 import cn.iocoder.yudao.module.system.service.tenant.TenantService;
+import cn.iocoder.yudao.module.system.service.user.AdminUserService;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.Lists;
 import lombok.extern.slf4j.Slf4j;
@@ -19,8 +26,8 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
-import java.util.Collection;
-import java.util.List;
+import java.util.*;
+import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
@@ -43,6 +50,8 @@ public class MenuServiceImpl implements MenuService {
     @Resource
     @Lazy // 延迟,避免循环依赖报错
     private TenantService tenantService;
+    @Resource
+    private AdminUserService userService;
 
     @Override
     @CacheEvict(value = RedisKeyConstants.PERMISSION_MENU_ID_LIST, key = "#createReqVO.permission",
@@ -64,6 +73,7 @@ public class MenuServiceImpl implements MenuService {
     @Override
     @CacheEvict(value = RedisKeyConstants.PERMISSION_MENU_ID_LIST,
             allEntries = true) // allEntries 清空所有缓存,因为 permission 如果变更,涉及到新老两个 permission。直接清理,简单有效
+    @TenantIgnore
     public void updateMenu(MenuSaveVO updateReqVO) {
         // 校验更新的菜单是否存在
         if (menuMapper.selectById(updateReqVO.getId()) == null) {
@@ -126,7 +136,7 @@ public class MenuServiceImpl implements MenuService {
 
     @Override
     public MenuDO getMenu(Long id) {
-        return menuMapper.selectById(id);
+        return menuMapper.getMenuById(id);
     }
 
     @Override
@@ -135,9 +145,75 @@ public class MenuServiceImpl implements MenuService {
         if (CollUtil.isEmpty(ids)) {
             return Lists.newArrayList();
         }
-        return menuMapper.selectBatchIds(ids);
+        return menuMapper.getMenuListByIds(ids);
+    }
+
+    @Override
+    public MenuDO selectByParentIdAndName(Long parentId, String name) {
+        MenuDO menu = menuMapper.selectByParentIdAndName(parentId, name);
+        return menu;
+    }
+
+    @Override
+    public List<MenuRespVO> getTenantMenus(MenuListReqVO reqVO) {
+        if (reqVO.getTenantId() == null) {
+            // 获得用户信息
+            LoginUser user = SecurityFrameworkUtils.getLoginUser();
+            if (user == null) {
+                throw exception(USER_NOT_EXISTS);
+            }
+            AdminUserDO adminUserDO = userService.getUser(user.getId());
+            if (adminUserDO == null || adminUserDO.getTenantId() == null) {
+                throw exception(USER_NOT_EXISTS);
+            }
+            reqVO.setTenantId(adminUserDO.getTenantId());
+        }
+        return menuMapper.getTenantMenus(reqVO);
+    }
+
+    @Override
+    public List<MenuRespVO> getPrimarySecondaryMenus() {
+        // 获取所有一级菜单
+        List<MenuDO> primaryMenus = getMenuList(new MenuListReqVO().setParentId(0L));
+        List<MenuDO> secondaryMenus = new ArrayList<>();
+        // 将一级菜单转换为响应对象,并为其添加二级菜单(如果有的话)
+        List<MenuRespVO> respMenus = primaryMenus.stream()
+                .map(primaryMenu -> {
+                    MenuRespVO respMenu = BeanUtils.toBean(primaryMenu, MenuRespVO.class);
+                    // 获取当前一级菜单下的所有二级菜单
+                    List<MenuDO> childMenus = getMenuList(new MenuListReqVO().setParentId(primaryMenu.getId()));
+                     respMenu.setChildren(childMenus);
+
+                    // 这里我们假设直接返回了简化版的一级菜单响应对象
+                    return respMenu;
+                })
+                .collect(Collectors.toList());
+
+        return respMenus;
     }
 
+    @Override
+    public List<MenuDO> getListByMenuId(Long menuId) {
+        MenuDO menuDO = this.getMenu(menuId);
+        if (menuDO == null || menuDO.getId() == null) {
+            throw exception(MENU_NOT_EXISTS);
+        }
+        // 获取OA菜单下所有子级菜单ID
+        Set<Long> oaChildrenMenuIds = this.collectAllMenuIds(menuDO.getId());
+        oaChildrenMenuIds.add(menuDO.getId());
+        List<MenuDO> menuList = this.getMenuList(oaChildrenMenuIds);
+        return menuList;
+    }
+
+//    @Override
+//    public List<MenuDO> getMenuListByIds(Collection<Long> ids) {
+//        // 当 ids 为空时,返回一个空的实例对象
+//        if (CollUtil.isEmpty(ids)) {
+//            return Lists.newArrayList();
+//        }
+//        return menuMapper.getMenuListByIds(ids);
+//    }
+
     /**
      * 校验父菜单是否合法
      * <p>
@@ -210,4 +286,23 @@ public class MenuServiceImpl implements MenuService {
         }
     }
 
+    // 递归方法,收集所有menuId并放入Set中
+    private Set<Long> collectAllMenuIds(Long parentId) {
+        Set<Long> menuIds = new HashSet<>();
+
+        // 获取当前parentId的直接子菜单
+        List<MenuDO> childrenMenus = this.getMenuList(new MenuListReqVO().setStatus(CommonStatusEnum.ENABLE.getStatus()).setParentId(parentId));
+
+        // 将当前层级的menuId添加到Set中
+        for (MenuDO menu : childrenMenus) {
+            menuIds.add(menu.getId()); // 假设Menu类有一个getId()方法返回menuId
+
+            // 递归收集子菜单的menuId
+            Set<Long> subMenuIds = collectAllMenuIds(menu.getId());
+            menuIds.addAll(subMenuIds); // 将子菜单的menuId也添加到Set中
+        }
+
+        return menuIds;
+    }
+
 }

+ 56 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuTenantRelateService.java

@@ -0,0 +1,56 @@
+package cn.iocoder.yudao.module.system.service.permission;
+
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuTenantRelatePageReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuTenantRelateSaveReqVO;
+import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuTenantRelateDO;
+
+import javax.validation.Valid;
+
+/**
+ * 菜单租户关系 Service 接口
+ *
+ * @author zhaopq
+ */
+public interface MenuTenantRelateService {
+
+    /**
+     * 创建菜单租户关系
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createTenantRelate(@Valid MenuTenantRelateSaveReqVO createReqVO);
+
+    /**
+     * 更新菜单租户关系
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateTenantRelate(@Valid MenuTenantRelateSaveReqVO updateReqVO);
+
+    /**
+     * 删除菜单租户关系
+     *
+     * @param id 编号
+     */
+    void deleteTenantRelate(Long id);
+
+    /**
+     * 获得菜单租户关系
+     *
+     * @param id 编号
+     * @return 菜单租户关系
+     */
+    MenuTenantRelateDO getTenantRelate(Long id);
+
+    /**
+     * 获得菜单租户关系分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 菜单租户关系分页
+     */
+    PageResult<MenuTenantRelateDO> getTenantRelatePage(MenuTenantRelatePageReqVO pageReqVO);
+
+}

+ 71 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/MenuTenantRelateServiceImpl.java

@@ -0,0 +1,71 @@
+package cn.iocoder.yudao.module.system.service.permission;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuTenantRelatePageReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuTenantRelateSaveReqVO;
+import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuTenantRelateDO;
+import cn.iocoder.yudao.module.system.dal.mysql.permission.MenuTenantRelateMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+
+import javax.annotation.Resource;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.TENANT_RELATE_NOT_EXISTS;
+
+/**
+ * 菜单租户关系 Service 实现类
+ *
+ * @author zhaopq
+ */
+@Service
+@Validated
+public class MenuTenantRelateServiceImpl implements MenuTenantRelateService {
+
+    @Resource
+    private MenuTenantRelateMapper tenantRelateMapper;
+
+    @Override
+    public Long createTenantRelate(MenuTenantRelateSaveReqVO createReqVO) {
+        // 插入
+        MenuTenantRelateDO tenantRelate = BeanUtils.toBean(createReqVO, MenuTenantRelateDO.class);
+        tenantRelateMapper.insert(tenantRelate);
+        // 返回
+        return tenantRelate.getId();
+    }
+
+    @Override
+    public void updateTenantRelate(MenuTenantRelateSaveReqVO updateReqVO) {
+        // 校验存在
+        validateTenantRelateExists(updateReqVO.getId());
+        // 更新
+        MenuTenantRelateDO updateObj = BeanUtils.toBean(updateReqVO, MenuTenantRelateDO.class);
+        tenantRelateMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteTenantRelate(Long id) {
+        // 校验存在
+        validateTenantRelateExists(id);
+        // 删除
+        tenantRelateMapper.deleteById(id);
+    }
+
+    private void validateTenantRelateExists(Long id) {
+        if (tenantRelateMapper.selectById(id) == null) {
+            throw exception(TENANT_RELATE_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public MenuTenantRelateDO getTenantRelate(Long id) {
+        return tenantRelateMapper.selectById(id);
+    }
+
+    @Override
+    public PageResult<MenuTenantRelateDO> getTenantRelatePage(MenuTenantRelatePageReqVO pageReqVO) {
+        return tenantRelateMapper.selectPage(pageReqVO);
+    }
+
+}

+ 5 - 3
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java

@@ -8,6 +8,8 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
 import cn.iocoder.yudao.module.system.api.permission.dto.DeptDataPermissionRespDTO;
+import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuListReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuRespVO;
 import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
 import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleMenuDO;
@@ -183,9 +185,9 @@ public class PermissionServiceImpl implements PermissionService {
         }
 
         // 如果是管理员的情况下,获取全部菜单编号
-        if (roleService.hasAnySuperAdmin(roleIds)) {
-            return convertSet(menuService.getMenuList(), MenuDO::getId);
-        }
+//        if (roleService.hasAnySuperAdmin(roleIds)) {
+//            return convertSet(menuService.getMenuList(), MenuDO::getId);
+//        }
         // 如果是非管理员的情况下,获得拥有的菜单编号
         return convertSet(roleMenuMapper.selectListByRoleId(roleIds), RoleMenuDO::getMenuId);
     }

+ 7 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleService.java

@@ -121,4 +121,11 @@ public interface RoleService {
      */
     void validateRoleList(Collection<Long> ids);
 
+    /**
+     * 根据名称查询角色
+     *
+     * @param name
+     * @return
+     */
+    RoleDO selectByName(String name);
 }

+ 5 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java

@@ -249,6 +249,11 @@ public class RoleServiceImpl implements RoleService {
         });
     }
 
+    @Override
+    public RoleDO selectByName(String name) {
+        return roleMapper.selectByName(name);
+    }
+
     /**
      * 获得自身的代理对象,解决 AOP 生效问题
      *

+ 125 - 15
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java

@@ -24,6 +24,7 @@ import cn.iocoder.yudao.module.employee.api.dto.EmployeeRespDTO;
 import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO;
 import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthLoginRespVO;
 import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuListReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuTenantRelateSaveReqVO;
 import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleSaveReqVO;
 import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.*;
 import cn.iocoder.yudao.module.system.controller.admin.user.vo.tenant.UserTenantRelateSaveReqVO;
@@ -39,12 +40,14 @@ import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantMapper;
 import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum;
 import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum;
 import cn.iocoder.yudao.module.system.enums.oauth2.OAuth2ClientConstants;
+import cn.iocoder.yudao.module.system.enums.permission.DataScopeEnum;
 import cn.iocoder.yudao.module.system.enums.permission.RoleCodeEnum;
 import cn.iocoder.yudao.module.system.enums.permission.RoleTypeEnum;
 import cn.iocoder.yudao.module.system.service.auth.AdminAuthService;
 import cn.iocoder.yudao.module.system.service.logger.LoginLogService;
 import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService;
 import cn.iocoder.yudao.module.system.service.permission.MenuService;
+import cn.iocoder.yudao.module.system.service.permission.MenuTenantRelateService;
 import cn.iocoder.yudao.module.system.service.permission.PermissionService;
 import cn.iocoder.yudao.module.system.service.permission.RoleService;
 import cn.iocoder.yudao.module.system.service.tenant.handler.TenantInfoHandler;
@@ -60,9 +63,7 @@ import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
 import java.time.LocalDateTime;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
+import java.util.*;
 import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -108,6 +109,8 @@ public class TenantServiceImpl implements TenantService {
     private OAuth2TokenService oauth2TokenService;
     @Resource
     private AdminAuthService authService;
+    @Resource
+    private MenuTenantRelateService menuTenantRelateService;
 
     @Override
     public List<Long> getTenantIdList() {
@@ -166,10 +169,12 @@ public class TenantServiceImpl implements TenantService {
         } else {
             throw exception(USER_TENANT_EMPLOYEE_DUPLICATE, tenant.getName());
         }
-        // 创建租户的管理员
         TenantUtils.execute(tenant.getId(), () -> {
-            // 创建角色
-            Long roleId = createRole(0L);
+            // 创建租户内置角色
+            Long roleId = createSystemSuperAdminRole(tenant.getId());
+            createSystemAdminRole(tenant.getId());
+            createCommonEmployeeRole(tenant.getId());
+            createDepartmentLeaderRole(tenant.getId());
             // 分配角色
             permissionService.assignUserRole(user.getId(), singleton(roleId));
             // 修改租户的管理员
@@ -215,6 +220,14 @@ public class TenantServiceImpl implements TenantService {
         } else {
             throw exception(USER_TENANT_EMPLOYEE_DUPLICATE, tenant.getName());
         }
+        TenantUtils.execute(tenant.getId(), () -> {
+            RoleDO roleDO = roleService.selectByName(RoleCodeEnum.COMMON_EMPLOYEE.getName());
+            if (roleDO == null || roleDO.getId() == null) {
+                throw exception(ROLE_NOT_EXISTS);
+            }
+            // 分配角色
+            permissionService.assignUserRole(user.getId(), singleton(roleDO.getId()));
+        });
         TenantSimpleRespVO tenantSimpleRespVO = new TenantSimpleRespVO();
         tenantSimpleRespVO.setId(tenant.getId());
         tenantSimpleRespVO.setName(tenant.getName());
@@ -241,21 +254,95 @@ public class TenantServiceImpl implements TenantService {
         return roleId;
     }
 
-    private Long createRole(Long tenantId) {
+    // 创建系统管理员:拥有所有OA磁贴权限和企业管理磁贴权限,只有本人数据权限,是给创建人默认授予的角色。
+    private Long createSystemSuperAdminRole(Long tenantId) {
         // 创建角色
         RoleSaveReqVO reqVO = new RoleSaveReqVO();
-        reqVO.setName(RoleCodeEnum.TENANT_SUPER_ADMIN.getName()).setCode(RoleCodeEnum.TENANT_SUPER_ADMIN.getCode())
-                .setSort(0).setRemark("系统自动生成");
+        reqVO.setName(RoleCodeEnum.SYSTEM_SUPER_ADMIN.getName()).setCode(RoleCodeEnum.SYSTEM_SUPER_ADMIN.getCode())
+                .setSort(0).setRemark("创建租户内置角色");
+        Long roleId = roleService.createRole(reqVO, RoleTypeEnum.CUSTOM.getType());
+        Set<Long> menuIds = new HashSet<>();
+        // 获取OA菜单
+        MenuDO oaMenu = menuService.selectByParentIdAndName(0L, "OA");
+        // 获取其他菜单
+        MenuDO otherMenu = menuService.selectByParentIdAndName(0L, "其他");
+        // 获取企业管理菜单
+        MenuDO manageMenu = menuService.selectByParentIdAndName(otherMenu.getId(), "企业管理");
+        // 获取OA菜单下所有子级菜单ID
+        Set<Long> oaChildrenMenuIds = this.collectAllMenuIds(oaMenu.getId());
+        // 获取企业管理菜单下所有子级菜单ID
+        Set<Long> manageChildrenMenuIds = this.collectAllMenuIds(manageMenu.getId());
+        menuIds.add(oaMenu.getId());
+        menuIds.addAll(oaChildrenMenuIds);
+        menuIds.add(otherMenu.getId());
+        menuIds.add(manageMenu.getId());
+        menuIds.addAll(manageChildrenMenuIds);
+        menuIds.stream()
+                .forEach(menuId ->
+                        menuTenantRelateService.createTenantRelate(new MenuTenantRelateSaveReqVO().setMenuId(menuId).setTenantId(tenantId))
+                );
+        // 分配菜单权限
+        permissionService.assignRoleMenu(roleId, menuIds);
+        // 分配数据权限
+        permissionService.assignRoleDataScope(roleId, DataScopeEnum.SELF.getScope(), null);
+        return roleId;
+    }
+    // 创建管理员:拥有所有磁贴权限,拥有全部数据权限,默认没有人拥有此角色,需要手动授予。
+    private Long createSystemAdminRole(Long tenantId) {
+        // 创建角色
+        RoleSaveReqVO reqVO = new RoleSaveReqVO();
+        reqVO.setName(RoleCodeEnum.SYSTEM_ADMIN.getName()).setCode(RoleCodeEnum.SYSTEM_ADMIN.getCode())
+                .setSort(0).setRemark("创建租户内置角色");
         Long roleId = roleService.createRole(reqVO, RoleTypeEnum.CUSTOM.getType());
         // 获取菜单Ids
-        List<MenuDO> menus = menuService.getMenuList(new MenuListReqVO().setTenantId(tenantId).setStatus(CommonStatusEnum.ENABLE.getStatus()));
+        List<MenuDO> menus = menuService.getMenuList(new MenuListReqVO().setStatus(CommonStatusEnum.ENABLE.getStatus()));
         Set<Long> menuIds = menus.stream()
-            .map(MenuDO::getId) // 映射每个MenuDO对象到它的id
-            .collect(Collectors.toSet()); // 收集到一个新的Set中
+                .map(MenuDO::getId) // 映射每个MenuDO对象到它的id
+                .collect(Collectors.toSet()); // 收集到一个新的Set中
+        // 分配菜单权限
+        permissionService.assignRoleMenu(roleId, menuIds);
+        // 分配数据权限
+        permissionService.assignRoleDataScope(roleId, DataScopeEnum.ALL.getScope(), null);
+        return roleId;
+    }
+    // 普通员工:拥有所有OA磁贴权限,只有本人数据权限,是加入企业时,默认授予的角色。
+    private Long createCommonEmployeeRole(Long tenantId) {
+        // 创建角色
+        RoleSaveReqVO reqVO = new RoleSaveReqVO();
+        reqVO.setName(RoleCodeEnum.COMMON_EMPLOYEE.getName()).setCode(RoleCodeEnum.COMMON_EMPLOYEE.getCode())
+                .setSort(0).setRemark("创建租户内置角色");
+        Long roleId = roleService.createRole(reqVO, RoleTypeEnum.CUSTOM.getType());
+        Set<Long> menuIds = new HashSet<>();
+        // 获取OA菜单
+        MenuDO oaMenu = menuService.selectByParentIdAndName(0L, "OA");
+        // 获取OA菜单下所有子级菜单ID
+        Set<Long> oaChildrenMenuIds = this.collectAllMenuIds(oaMenu.getId());
+        menuIds.add(oaMenu.getId());
+        menuIds.addAll(oaChildrenMenuIds);
+        // 分配菜单权限
+        permissionService.assignRoleMenu(roleId, menuIds);
+        // 分配数据权限
+        permissionService.assignRoleDataScope(roleId, DataScopeEnum.SELF.getScope(), null);
+        return roleId;
+    }
+    // 部门负责人:拥有所有OA磁贴权限,有本部门及以下数据权限,默认没有人拥有此角色,需要手动授予。
+    private Long createDepartmentLeaderRole(Long tenantId) {
+        // 创建角色
+        RoleSaveReqVO reqVO = new RoleSaveReqVO();
+        reqVO.setName(RoleCodeEnum.DEPARTMENT_LEADER.getName()).setCode(RoleCodeEnum.DEPARTMENT_LEADER.getCode())
+                .setSort(0).setRemark("创建租户内置角色");
+        Long roleId = roleService.createRole(reqVO, RoleTypeEnum.CUSTOM.getType());
+        Set<Long> menuIds = new HashSet<>();
+        // 获取OA菜单
+        MenuDO oaMenu = menuService.selectByParentIdAndName(0L, "OA");
+        // 获取OA菜单下所有子级菜单ID
+        Set<Long> oaChildrenMenuIds = this.collectAllMenuIds(oaMenu.getId());
+        menuIds.add(oaMenu.getId());
+        menuIds.addAll(oaChildrenMenuIds);
         // 分配菜单权限
         permissionService.assignRoleMenu(roleId, menuIds);
         // 分配数据权限
-        permissionService.assignRoleDataScope(roleId, 1, null);
+        permissionService.assignRoleDataScope(roleId, DataScopeEnum.DEPT_AND_CHILD.getScope(), null);
         return roleId;
     }
 
@@ -264,11 +351,15 @@ public class TenantServiceImpl implements TenantService {
     public void updateTenant(TenantSaveReqVO updateReqVO) {
         // 1.1 获得用户信息
         AdminUserDO user = userService.getUser(getLoginUserId());
-        if (user == null || user.getTenantId() == null) {
+        if (user == null) {
+            throw exception(USER_NOT_EXISTS);
+        }
+        AdminUserDO adminUserDO = userService.getUser(user.getId());
+        if (adminUserDO == null || adminUserDO.getTenantId() == null) {
             throw exception(USER_NOT_EXISTS);
         }
         if (updateReqVO.getId() == null) {
-            updateReqVO.setId(user.getTenantId());
+            updateReqVO.setId(adminUserDO.getTenantId());
         }
         // 校验存在
         TenantDO tenant = validateUpdateTenant(updateReqVO.getId());
@@ -518,4 +609,23 @@ public class TenantServiceImpl implements TenantService {
         return UserTypeEnum.ADMIN;
     }
 
+    // 递归方法,收集所有menuId并放入Set中
+    private Set<Long> collectAllMenuIds(Long parentId) {
+        Set<Long> menuIds = new HashSet<>();
+
+        // 获取当前parentId的直接子菜单
+        List<MenuDO> childrenMenus = menuService.getMenuList(new MenuListReqVO().setStatus(CommonStatusEnum.ENABLE.getStatus()).setParentId(parentId));
+
+        // 将当前层级的menuId添加到Set中
+        for (MenuDO menu : childrenMenus) {
+            menuIds.add(menu.getId()); // 假设Menu类有一个getId()方法返回menuId
+
+            // 递归收集子菜单的menuId
+            Set<Long> subMenuIds = collectAllMenuIds(menu.getId());
+            menuIds.addAll(subMenuIds); // 将子菜单的menuId也添加到Set中
+        }
+
+        return menuIds;
+    }
+
 }

+ 45 - 0
yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/permission/MenuMapper.xml

@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="cn.iocoder.yudao.module.system.dal.mysql.permission.MenuMapper">
+
+    <!-- 定义resultMap -->
+    <resultMap id="BaseResultMap" type="cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuRespVO">
+        <!-- id字段映射,通常是数据库中的主键 -->
+        <id property="id" column="id" jdbcType="BIGINT"/>
+        <!-- 基本字段映射 -->
+        <result property="name" column="name" jdbcType="VARCHAR"/>
+        <result property="permission" column="permission" jdbcType="VARCHAR"/>
+        <result property="type" column="type" jdbcType="INTEGER"/>
+        <result property="sort" column="sort" jdbcType="INTEGER"/>
+        <result property="parentId" column="parent_id" jdbcType="BIGINT"/>
+        <result property="path" column="path" jdbcType="VARCHAR"/>
+        <result property="icon" column="icon" jdbcType="VARCHAR"/>
+        <result property="component" column="component" jdbcType="VARCHAR"/>
+        <result property="componentName" column="component_name" jdbcType="VARCHAR"/>
+        <result property="status" column="status" jdbcType="INTEGER"/>
+        <result property="visible" column="visible" jdbcType="BIT"/>
+        <result property="keepAlive" column="keep_alive" jdbcType="BIT"/>
+        <result property="alwaysShow" column="always_show" jdbcType="BIT"/>
+        <result property="createTime" column="create_time" jdbcType="TIMESTAMP" />
+        <!-- 其他字段映射可以根据需要添加 -->
+    </resultMap>
+
+    <!--
+        一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
+        无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
+        代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
+        文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
+     -->
+
+    <select id="getTenantMenus" resultMap="BaseResultMap">
+        SELECT
+            m.*
+        FROM
+            menu_tenant_relate mtr
+        JOIN
+            system_menu_copy1 m ON mtr.menu_id = m.id
+        WHERE
+            mtr.tenant_id = #{reqVO.tenantId}
+    </select>
+
+</mapper>

+ 8 - 5
yudao-server/src/main/resources/application.yaml

@@ -197,11 +197,14 @@ yudao:
       - /admin-api/system/auth/sms-login # 使用验证码登录,和租户无关
       - /admin-api/system/auth/sms-register # 使用验证码注册,和租户无关
       - /admin-api/system/user/profile/reset-password # 使用验证码重置密码,和租户无关
-      - /admin-api/system/auth/login # 使用账号登录,和租户无关
-      - /admin-api/system/tenant/create # 创建租户,不携带租户编号
-      - /admin-api/system/tenant/join # 加入租户,不携带租户编号
-      - /admin-api/system/tenant/change # 切换租户,不携带租户编号
-      - /admin-api/presonnel/employee/create  # 创建员工,不携带租户编号
+#      - /admin-api/system/auth/login # 使用账号登录,和租户无关
+#      - /admin-api/system/tenant/create # 创建租户,不携带租户编号
+#      - /admin-api/system/tenant/join # 加入租户,不携带租户编号
+#      - /admin-api/system/tenant/change # 切换租户,不携带租户编号
+#      - /admin-api/presonnel/employee/create  # 创建员工,不携带租户编号
+      - /admin-api/system/auth/getCurrentTenantIdByUsername # 通过用户账号获取租户列表,不携带租户编号
+#      - /admin-api/system/tenant/getOwnCreateTenants # 获取自己的创建的租户列表,不携带租户编号
+#      - /admin-api/system/tenant/getOwnJoinTenants # 获取自己的加入的租户列表,不携带租户编号
     ignore-tables:
       - system_tenant
       - system_tenant_package