diff --git a/hrm/src/main/java/com/qiujie/controller/MenuController.java b/hrm/src/main/java/com/qiujie/controller/MenuController.java index 0044325..dee2240 100644 --- a/hrm/src/main/java/com/qiujie/controller/MenuController.java +++ b/hrm/src/main/java/com/qiujie/controller/MenuController.java @@ -18,91 +18,148 @@ import java.util.List; /** *

- * 前端控制器 + * 菜单权限模块前端控制器 + * 处理菜单相关的HTTP请求,包括菜单的增删改查、导入导出及权限查询等操作 *

* * @author qiujie * @since 2022-02-28 */ @RestController -@RequestMapping("/menu") +@RequestMapping("/menu") // 基础请求路径,所有接口均以/menu开头 public class MenuController { + // 注入菜单业务逻辑层对象 @Autowired private MenuService menuService; - @ApiOperation("新增") + /** + * 新增菜单 + * @param menu 菜单实体对象(包含菜单名称、编码、权限标识等信息) + * @return 统一响应结果(成功/失败信息) + */ + @ApiOperation("新增菜单") @PostMapping - @PreAuthorize("hasAnyAuthority('permission:menu:add')") + @PreAuthorize("hasAnyAuthority('permission:menu:add')") // 权限校验:需拥有菜单新增权限 public ResponseDTO add(@RequestBody Menu menu) { return this.menuService.add(menu); } - @ApiOperation("逻辑删除") + /** + * 逻辑删除菜单(非物理删除,仅标记删除状态) + * @param id 菜单ID + * @return 统一响应结果 + */ + @ApiOperation("逻辑删除菜单") @DeleteMapping("/{id}") - @PreAuthorize("hasAnyAuthority('permission:menu:delete')") + @PreAuthorize("hasAnyAuthority('permission:menu:delete')") // 权限校验:需拥有菜单删除权限 public ResponseDTO deleteById(@PathVariable Integer id) { return this.menuService.delete(id); } - @ApiOperation("批量逻辑删除") + /** + * 批量逻辑删除菜单 + * @param ids 菜单ID列表 + * @return 统一响应结果 + */ + @ApiOperation("批量逻辑删除菜单") @DeleteMapping("/batch/{ids}") - @PreAuthorize("hasAnyAuthority('permission:menu:delete')") + @PreAuthorize("hasAnyAuthority('permission:menu:delete')") // 权限校验:需拥有菜单删除权限 public ResponseDTO deleteBatch(@PathVariable List ids) { return this.menuService.deleteBatch(ids); } - @ApiOperation("编辑更新") + /** + * 编辑更新菜单信息(支持更新菜单状态等操作) + * @param menu 菜单实体对象(包含更新后的菜单信息) + * @return 统一响应结果 + */ + @ApiOperation("编辑更新菜单") @PutMapping - @PreAuthorize("hasAnyAuthority('permission:menu:edit','permission:menu:enable')") + @PreAuthorize("hasAnyAuthority('permission:menu:edit','permission:menu:enable')") // 权限校验:需拥有菜单编辑或启用权限 public ResponseDTO edit(@RequestBody Menu menu) { return this.menuService.edit(menu); } - @ApiOperation("查询") + /** + * 根据ID查询菜单详情 + * @param id 菜单ID + * @return 统一响应结果(包含菜单详情) + */ + @ApiOperation("查询菜单详情") @GetMapping("/{id}") public ResponseDTO query(@PathVariable Integer id) { return this.menuService.query(id); } - - - @ApiOperation("分页条件查询") + /** + * 分页条件查询菜单列表(仅查询一级菜单,同时关联子菜单) + * @param current 当前页码(默认第1页) + * @param size 每页条数(默认10条) + * @param name 菜单名称(模糊查询条件,可选) + * @return 统一响应结果(包含分页菜单列表) + */ + @ApiOperation("分页条件查询菜单") @GetMapping - @PreAuthorize("hasAnyAuthority('permission:menu:list','permission:menu:search')") + @PreAuthorize("hasAnyAuthority('permission:menu:list','permission:menu:search')") // 权限校验:需拥有菜单列表或查询权限 public ResponseDTO list(@RequestParam(defaultValue = "1") Integer current, @RequestParam(defaultValue = "10") Integer size, String name) { return this.menuService.list(current, size, name); } - @ApiOperation("数据导出接口") + /** + * 导出菜单数据到文件 + * @param response HTTP响应对象(用于输出文件流) + * @param filename 导出文件名 + * @throws IOException 可能的IO异常(如文件写入失败) + */ + @ApiOperation("导出菜单数据") @GetMapping("/export/{filename}") - @PreAuthorize("hasAnyAuthority('permission:menu:export')") + @PreAuthorize("hasAnyAuthority('permission:menu:export')") // 权限校验:需拥有菜单导出权限 public void export(HttpServletResponse response,@PathVariable String filename) throws IOException { - this.menuService.export(response,filename); + this.menuService.export(response,filename); } - @ApiOperation("数据导入接口") + /** + * 从文件导入菜单数据 + * @param file 上传的文件(包含菜单数据) + * @return 统一响应结果(导入成功/失败信息) + * @throws IOException 可能的IO异常(如文件读取失败) + */ + @ApiOperation("导入菜单数据") @PostMapping("/import") - @PreAuthorize("hasAnyAuthority('permission:menu:import')") + @PreAuthorize("hasAnyAuthority('permission:menu:import')") // 权限校验:需拥有菜单导入权限 public ResponseDTO imp(MultipartFile file) throws IOException { return this.menuService.imp(file); } - @ApiOperation("查询所有") + /** + * 查询所有启用状态的菜单,并构建树形结构(一级菜单包含二级菜单,二级菜单包含权限点) + * @return 统一响应结果(包含树形结构的菜单列表) + */ + @ApiOperation("查询所有菜单(树形结构)") @GetMapping("/all") public ResponseDTO queryAll(){ return this.menuService.queryAll(); } - @ApiOperation("获取员工的菜单") + /** + * 根据员工ID查询其拥有的菜单权限(树形结构) + * @param id 员工ID + * @return 统一响应结果(包含员工可访问的菜单列表) + */ + @ApiOperation("获取指定员工的菜单权限") @GetMapping("/staff/{id}") public ResponseDTO queryByStaffId(@PathVariable Integer id){ return this.menuService.queryByStaffId(id); } - @ApiOperation("查询权限") + /** + * 根据员工ID查询其拥有的权限标识集合(如"user:add"、"menu:delete") + * @param id 员工ID + * @return 统一响应结果(包含权限标识列表) + */ + @ApiOperation("查询指定员工的权限标识集合") @GetMapping("/permission/{id}") public ResponseDTO queryPermission(@PathVariable Integer id){ return this.menuService.queryPermission(id); } } - diff --git a/hrm/src/main/java/com/qiujie/controller/RoleController.java b/hrm/src/main/java/com/qiujie/controller/RoleController.java index 7de723d..05b4205 100644 --- a/hrm/src/main/java/com/qiujie/controller/RoleController.java +++ b/hrm/src/main/java/com/qiujie/controller/RoleController.java @@ -18,93 +18,154 @@ import java.util.List; /** *

- * 前端控制器 + * 角色管理模块前端控制器 + * 处理角色相关的HTTP请求,包括增删改查、权限分配等操作 *

* * @author qiujie * @since 2022-02-28 */ @RestController -@RequestMapping("/role") +@RequestMapping("/role") // 基础请求路径,所有接口均以/role开头 public class RoleController { + // 注入角色业务逻辑层对象 @Autowired private RoleService roleService; + // 注入角色-菜单关联业务逻辑层对象(用于处理角色与菜单的权限关联) @Autowired private RoleMenuService roleMenuService; - @ApiOperation("新增") + /** + * 新增角色 + * @param role 角色实体对象(包含角色名称、描述等信息) + * @return 统一响应结果(成功/失败信息) + */ + @ApiOperation("新增角色") @PostMapping - @PreAuthorize("hasAnyAuthority('permission:role:add')") + @PreAuthorize("hasAnyAuthority('permission:role:add')") // 权限校验:需拥有角色新增权限 public ResponseDTO add(@RequestBody Role role) { return this.roleService.add(role); } - @ApiOperation("逻辑删除") + /** + * 逻辑删除角色(非物理删除,仅标记删除状态) + * @param id 角色ID + * @return 统一响应结果 + */ + @ApiOperation("逻辑删除角色") @DeleteMapping("/{id}") - @PreAuthorize("hasAnyAuthority('permission:role:delete')") + @PreAuthorize("hasAnyAuthority('permission:role:delete')") // 权限校验:需拥有角色删除权限 public ResponseDTO delete(@PathVariable Integer id) { return this.roleService.delete(id); } - @ApiOperation("批量逻辑删除") + /** + * 批量逻辑删除角色 + * @param ids 角色ID列表 + * @return 统一响应结果 + */ + @ApiOperation("批量逻辑删除角色") @DeleteMapping("/batch/{ids}") - @PreAuthorize("hasAnyAuthority('permission:role:delete')") + @PreAuthorize("hasAnyAuthority('permission:role:delete')") // 权限校验:需拥有角色删除权限 public ResponseDTO deleteBatch(@PathVariable List ids) { return this.roleService.deleteBatch(ids); } - @ApiOperation("编辑更新") + /** + * 编辑更新角色信息 + * @param role 角色实体对象(包含更新后的角色信息) + * @return 统一响应结果 + */ + @ApiOperation("编辑更新角色") @PutMapping - @PreAuthorize("hasAnyAuthority('permission:role:edit')") + @PreAuthorize("hasAnyAuthority('permission:role:edit')") // 权限校验:需拥有角色编辑权限 public ResponseDTO edit(@RequestBody Role role) { return this.roleService.edit(role); } - @ApiOperation("查询") + /** + * 根据ID查询角色详情 + * @param id 角色ID + * @return 统一响应结果(包含角色详情) + */ + @ApiOperation("查询角色详情") @GetMapping("/{id}") public ResponseDTO query(@PathVariable Integer id) { return this.roleService.query(id); } - @ApiOperation("查询所有") + /** + * 查询所有角色(无分页) + * @return 统一响应结果(包含所有角色列表) + */ + @ApiOperation("查询所有角色") @GetMapping("/all") public ResponseDTO queryAll(){ return this.roleService.queryAll(); } - @ApiOperation("分页条件查询") + /** + * 分页条件查询角色列表 + * @param current 当前页码(默认第1页) + * @param size 每页条数(默认10条) + * @param name 角色名称(模糊查询条件,可选) + * @return 统一响应结果(包含分页角色列表) + */ + @ApiOperation("分页条件查询角色") @GetMapping - @PreAuthorize("hasAnyAuthority('permission:role:list','permission:role:search')") + @PreAuthorize("hasAnyAuthority('permission:role:list','permission:role:search')") // 权限校验:需拥有角色列表或查询权限 public ResponseDTO list(@RequestParam(defaultValue = "1") Integer current, @RequestParam(defaultValue = "10") Integer size, String name) { return this.roleService.list(current, size, name); } - @ApiOperation("数据导出接口") + /** + * 导出角色数据到文件 + * @param response HTTP响应对象(用于输出文件流) + * @param filename 导出文件名 + * @throws IOException 可能的IO异常(如文件写入失败) + */ + @ApiOperation("导出角色数据") @GetMapping("/export/{filename}") - @PreAuthorize("hasAnyAuthority('permission:role:export')") + @PreAuthorize("hasAnyAuthority('permission:role:export')") // 权限校验:需拥有角色导出权限 public void export(HttpServletResponse response,@PathVariable String filename) throws IOException { - this.roleService.export(response,filename); + this.roleService.export(response,filename); } - @ApiOperation("数据导入接口") + /** + * 从文件导入角色数据 + * @param file 上传的文件(包含角色数据) + * @return 统一响应结果(导入成功/失败信息) + * @throws IOException 可能的IO异常(如文件读取失败) + */ + @ApiOperation("导入角色数据") @PostMapping("/import") - @PreAuthorize("hasAnyAuthority('permission:role:import')") + @PreAuthorize("hasAnyAuthority('permission:role:import')") // 权限校验:需拥有角色导入权限 public ResponseDTO imp(MultipartFile file) throws IOException { return this.roleService.imp(file); } - @ApiOperation("为角色设置菜单") + /** + * 为指定角色分配菜单权限 + * @param id 角色ID + * @param menuIds 菜单ID列表(角色拥有的菜单权限) + * @return 统一响应结果 + */ + @ApiOperation("为角色设置菜单权限") @PostMapping("/set/{id}") - @PreAuthorize("hasAnyAuthority('permission:role:set_menu')") + @PreAuthorize("hasAnyAuthority('permission:role:set_menu')") // 权限校验:需拥有角色菜单分配权限 public ResponseDTO setMenu(@PathVariable Integer id, @RequestBody List menuIds){ return this.roleMenuService.setMenu(id, menuIds); } - @ApiOperation("得到角色所属的菜单") + /** + * 查询指定角色已拥有的菜单权限 + * @param id 角色ID + * @return 统一响应结果(包含角色拥有的菜单ID列表) + */ + @ApiOperation("查询角色所属的菜单权限") @GetMapping("/role/{id}") public ResponseDTO queryByRoleId(@PathVariable Integer id){ return this.roleMenuService.queryByRoleId(id); } -} - +} \ No newline at end of file diff --git a/hrm/src/main/java/com/qiujie/entity/Menu.java b/hrm/src/main/java/com/qiujie/entity/Menu.java index 9207bea..d5d8213 100644 --- a/hrm/src/main/java/com/qiujie/entity/Menu.java +++ b/hrm/src/main/java/com/qiujie/entity/Menu.java @@ -18,70 +18,126 @@ import lombok.Data; /** *

- * + * 菜单权限实体类 + * 用于存储系统中的菜单、子菜单及权限点信息,支持多级菜单结构 *

* * @author qiujie * @since 2022-02-28 */ -@Data -@TableName("per_menu") -@ApiModel(value = "Menu对象", description = "") +@Data // Lombok注解,自动生成getter、setter、toString等方法 +@TableName("per_menu") // 对应数据库表名:per_menu(权限_菜单) +@ApiModel(value = "Menu对象", description = "系统菜单及权限点信息实体类") public class Menu implements Serializable { - @Serial + @Serial // 序列化版本号标识,用于对象序列化时的版本一致性校验 private static final long serialVersionUID = 1L; - @ApiModelProperty("菜单id") + /** + * 菜单主键ID + * 自增类型,唯一标识一条菜单/权限点记录 + */ + @ApiModelProperty("菜单id(主键)") @TableId(value = "id", type = IdType.AUTO) private Integer id; - @ApiModelProperty("菜单编码") + /** + * 菜单编码 + * 用于标识菜单的唯一编码,通常用于前端路由或权限判断 + */ + @ApiModelProperty("菜单编码(唯一标识)") @TableField("code") private String code; - @ApiModelProperty("菜单名称") + /** + * 菜单名称 + * 显示在前端的菜单名称,如"用户管理"、"角色配置"等 + */ + @ApiModelProperty("菜单名称(显示用)") @TableField("name") private String name; + /** + * 菜单图标 + * 前端显示的菜单图标标识(如FontAwesome图标类名) + */ @TableField("icon") private String icon; - @ApiModelProperty("权限标识") + /** + * 权限标识 + * 用于Spring Security权限控制的标识,如"user:list"、"role:add"等 + */ + @ApiModelProperty("权限标识(用于权限控制)") @TableField("permission") private String permission; + /** + * 父菜单ID + * 用于构建多级菜单结构,0表示当前菜单为根菜单(一级菜单) + */ @ApiModelProperty("父菜单id,0代表根菜单") @TableField("parent_id") private Integer parentId; + /** + * 菜单级别 + * 0:一级菜单(顶层菜单) + * 1:二级菜单(一级菜单的子菜单) + * 2:权限点(具体操作权限,如新增、删除按钮) + */ @ApiModelProperty("0一级菜单,1二级菜单,2权限点") @TableField("level") private Integer level; + /** + * 状态标识 + * 0:禁用(前端不显示,权限失效) + * 1:正常(默认值,可用状态) + */ @ApiModelProperty("权限点是否启用,0禁用、1正常,默认1") @TableField("status") private Integer status; - @ApiModelProperty("备注") + /** + * 备注信息 + * 存储菜单的额外说明,如用途、特殊规则等 + */ + @ApiModelProperty("备注信息") @TableField("remark") private String remark; - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + /** + * 创建时间 + * 记录菜单的创建时间,JSON序列化时按指定格式显示 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") // 格式化日期时间,指定时区 @ApiModelProperty("创建时间") @TableField("create_time") private Timestamp createTime; - @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") + /** + * 更新时间 + * 记录菜单最后一次修改的时间,JSON序列化时按指定格式显示 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @ApiModelProperty("更新时间") @TableField("update_time") private Timestamp updateTime; + /** + * 逻辑删除标记 + * MyBatis-Plus逻辑删除字段,0:未删除,1:已删除(查询时自动过滤已删除记录) + */ @TableField("is_deleted") - @TableLogic + @TableLogic // 标识为逻辑删除字段 private Integer deleteFlag; - @TableField(exist = false) + /** + * 子菜单列表 + * 非数据库字段(exist=false),用于在内存中存储当前菜单的子菜单,构建树形结构 + */ + @TableField(exist = false) // 标识该字段不对应数据库表列 private List children; } diff --git a/hrm/src/main/java/com/qiujie/entity/RoleMenu.java b/hrm/src/main/java/com/qiujie/entity/RoleMenu.java index 186aaf5..c256a9d 100644 --- a/hrm/src/main/java/com/qiujie/entity/RoleMenu.java +++ b/hrm/src/main/java/com/qiujie/entity/RoleMenu.java @@ -3,23 +3,20 @@ package com.qiujie.entity; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableName; - -import java.io.Serial; -import java.io.Serializable; -import java.sql.Timestamp; - -import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; +import java.io.Serial; +import java.io.Serializable; + /** *

- * + * 角色与菜单关联表实体类 + * 用于存储角色和菜单之间的多对多映射关系,实现权限分配 *

* * @author qiujie @@ -27,22 +24,34 @@ import lombok.experimental.Accessors; */ @Getter @Setter -@Accessors(chain = true) -@TableName("per_role_menu") -@ApiModel(value = "RoleMenu对象", description = "") +@Accessors(chain = true) // 开启链式调用,支持setter方法连续赋值 +@TableName("per_role_menu") // 对应数据库表名:per_role_menu(权限_角色_菜单) +@ApiModel(value = "RoleMenu对象", description = "角色与菜单的关联关系实体") public class RoleMenu implements Serializable { - @Serial + @Serial // 序列化版本号标识,用于对象序列化时的版本一致性校验 private static final long serialVersionUID = 1L; + /** + * 主键ID + * 自增类型,唯一标识一条角色-菜单关联记录 + */ @TableId(value = "id", type = IdType.AUTO) private Integer id; - @ApiModelProperty("角色id") + /** + * 角色ID + * 关联角色表的主键,标识当前关联记录所属的角色 + */ + @ApiModelProperty("角色id,关联角色表主键") @TableField("role_id") private Integer roleId; - @ApiModelProperty("菜单id") + /** + * 菜单ID + * 关联菜单表的主键,标识当前角色拥有的菜单权限 + */ + @ApiModelProperty("菜单id,关联菜单表主键") @TableField("menu_id") private Integer menuId; -} +} \ No newline at end of file diff --git a/hrm/src/main/java/com/qiujie/service/MenuService.java b/hrm/src/main/java/com/qiujie/service/MenuService.java index 40cf6ca..539aeb0 100644 --- a/hrm/src/main/java/com/qiujie/service/MenuService.java +++ b/hrm/src/main/java/com/qiujie/service/MenuService.java @@ -21,7 +21,8 @@ import java.util.*; /** *

- * 服务类 + * 菜单权限服务实现类 + * 处理菜单的增删改查、树形结构构建、导入导出等业务逻辑 *

* * @author qiujie @@ -31,16 +32,27 @@ import java.util.*; public class MenuService extends ServiceImpl { @Autowired - private MenuMapper menuMapper; + private MenuMapper menuMapper; // 注入菜单数据访问层对象 + /** + * 新增菜单 + * @param menu 菜单实体对象 + * @return 统一响应结果(成功/失败) + */ public ResponseDTO add(Menu menu) { + // 调用MyBatis-Plus的save方法保存菜单,成功返回成功响应,否则返回失败响应 if (save(menu)) { return Response.success(); } return Response.error(); } + /** + * 根据ID删除菜单(逻辑删除,依赖MyBatis-Plus的逻辑删除配置) + * @param id 菜单ID + * @return 统一响应结果 + */ public ResponseDTO delete(Integer id) { if (removeById(id)) { return Response.success(); @@ -48,7 +60,12 @@ public class MenuService extends ServiceImpl { return Response.error(); } - @Transactional(rollbackFor = Exception.class) + /** + * 批量删除菜单(逻辑删除) + * @param ids 菜单ID列表 + * @return 统一响应结果 + */ + @Transactional(rollbackFor = Exception.class) // 声明事务,发生异常时回滚 public ResponseDTO deleteBatch(List ids) { if (removeBatchByIds(ids)) { return Response.success(); @@ -57,6 +74,11 @@ public class MenuService extends ServiceImpl { } + /** + * 编辑更新菜单信息 + * @param menu 包含更新信息的菜单实体 + * @return 统一响应结果 + */ public ResponseDTO edit(Menu menu) { if (updateById(menu)) { return Response.success(); @@ -65,6 +87,11 @@ public class MenuService extends ServiceImpl { } + /** + * 根据ID查询菜单详情 + * @param id 菜单ID + * @return 统一响应结果(包含菜单详情) + */ public ResponseDTO query(Integer id) { Menu menu = getById(id); if (menu != null) { @@ -74,23 +101,26 @@ public class MenuService extends ServiceImpl { } /** - * 查找所有菜单 - * - * @return + * 查找所有启用状态的菜单,并构建树形结构(一级菜单包含二级菜单,二级菜单包含权限点) + * @return 统一响应结果(包含树形结构的菜单列表) */ public ResponseDTO queryAll() { + // 查询所有状态为"正常"(1)的菜单 List list = list(new QueryWrapper().eq("status",1)); - // 为父级菜单设置子菜单 - // 一级菜单 + + // 筛选一级菜单(level=0) List firstList = list.stream().parallel() .filter(menu -> menu.getLevel() == 0).toList(); + + // 为一级菜单设置二级菜单 for (Menu firstMenu : firstList) { - // 二级菜单 + // 筛选当前一级菜单的二级菜单(parentId=一级菜单ID,level=1) List secondList = list.stream().parallel() .filter(menu -> Objects.equals(menu.getParentId(), firstMenu.getId())).toList(); firstMenu.setChildren(secondList); + + // 为二级菜单设置权限点(level=2) for (Menu secondMenu : secondList) { - // 权限点 List thirdList = list.stream().parallel() .filter(menu -> Objects.equals(menu.getParentId(), secondMenu.getId())).toList(); secondMenu.setChildren(thirdList); @@ -100,28 +130,45 @@ public class MenuService extends ServiceImpl { } + /** + * 分页条件查询菜单(仅查询一级菜单,同时关联查询其子菜单) + * @param current 当前页码 + * @param size 每页条数 + * @param name 菜单名称(模糊查询条件) + * @return 统一响应结果(包含分页信息和树形菜单列表) + */ public ResponseDTO list(Integer current, Integer size, String name) { + // 构建分页对象 IPage config = new Page<>(current, size); QueryWrapper wrapper = new QueryWrapper<>(); + + // 若名称不为空,添加模糊查询条件 if (name != "" && name != null) { wrapper.like("name", name); } + // 仅查询一级菜单(level=0) wrapper.eq("level", 0); + + // 执行分页查询 IPage page = page(config, wrapper); + // 查询所有非一级菜单(用于构建子菜单) List list = list(new QueryWrapper().ne("level", 0)); - // 菜单 + + // 为一级菜单设置子菜单 List firstList = page.getRecords(); for (Menu firstMenu : firstList) { - // 设置子菜单 + // 筛选二级菜单 List secondList = list.stream().filter(menu -> Objects.equals(menu.getParentId(), firstMenu.getId())).toList(); firstMenu.setChildren(secondList); + + // 为二级菜单设置权限点 for (Menu secondMenu : secondList) { - // 设置子菜单 List thirdList = list.stream().filter(menu -> Objects.equals(menu.getParentId(), secondMenu.getId())).toList(); secondMenu.setChildren(thirdList); } } - // 将响应数据填充到map中 + + // 封装分页结果(总页数、总条数、菜单列表) Map map = new HashMap(); map.put("pages", page.getPages()); map.put("total", page.getTotal()); @@ -130,40 +177,50 @@ public class MenuService extends ServiceImpl { } /** - * 数据导出 - * - * @param response - * @return + * 导出菜单数据到Excel文件 + * @param response HTTP响应对象(用于输出文件流) + * @param filename 导出文件名 + * @throws IOException IO异常(如文件写入失败) */ public void export(HttpServletResponse response, String filename) throws IOException { + // 查询所有菜单 List list = list(); + // 调用工具类导出Excel HutoolExcelUtil.writeExcel(response, list, filename, Menu.class); } /** - * 数据导入 - * - * @param file - * @return + * 从Excel文件导入菜单数据 + * @param file 上传的Excel文件 + * @return 统一响应结果 + * @throws IOException IO异常(如文件读取失败) */ - @Transactional(rollbackFor = Exception.class) + @Transactional(rollbackFor = Exception.class) // 声明事务,确保批量插入的原子性 public ResponseDTO imp(MultipartFile file) throws IOException { InputStream inputStream = file.getInputStream(); + // 调用工具类读取Excel(从第2行开始读取,跳过表头) List list = HutoolExcelUtil.readExcel(inputStream, 1, Menu.class); - // IService接口中的方法.批量插入数据 + // 批量插入数据 if (saveBatch(list)) { return Response.success(); } return Response.error(); } + /** + * 根据员工ID查询其拥有的菜单权限(构建树形结构) + * @param id 员工ID + * @return 统一响应结果(包含员工可访问的树形菜单) + */ public ResponseDTO queryByStaffId(Integer id) { + // 通过mapper查询该员工拥有的所有菜单 List list = this.menuMapper.queryByStaffId(id); - // 一级菜单 + + // 筛选一级菜单并构建树形结构 List firstList = list.stream().parallel() .filter(menu -> menu.getLevel() == 0).toList(); for (Menu firstMenu : firstList) { - // 二级菜单 + // 为一级菜单设置二级菜单 List secondList = list.stream().parallel() .filter(menu -> Objects.equals(menu.getParentId(), firstMenu.getId())).toList(); firstMenu.setChildren(secondList); @@ -172,11 +229,12 @@ public class MenuService extends ServiceImpl { } + /** + * 根据员工ID查询其拥有的权限标识集合(如"user:add"、"role:delete") + * @param id 员工ID + * @return 统一响应结果(包含权限标识列表) + */ public ResponseDTO queryPermission(Integer id){ return Response.success(this.menuMapper.queryPermission(id)); } -} - - - - +} \ No newline at end of file