『博客开发日记-后台』之更新菜单接口的实现

本文最后更新于 2026年5月6日 晚上

修改菜单接口的实现


修改菜单接口的需求

根据菜单id获得旧的友链信息

检查菜单是否存在

校验父菜单是否存在

校验 目录/菜单 必须有路由路径

校验同一父菜单下是否存在同名菜单(排除自己)

处理 params 字段


代码实现

创建 UpdateMenuDto 请求对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/**
* 更新菜单请求DTO
*
* @author mengze
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(description = "更新菜单请求对象")
public class UpdateMenuDto {

@ApiModelProperty(value = "菜单ID", required = true, example = "1")
private Long id;

@NotNull(message = "父菜单ID不能为空")
@ApiModelProperty(value = "父菜单ID(0表示顶级菜单)", required = true, example = "0")
private Long parentId;

@NotBlank(message = "菜单名称不能为空")
@ApiModelProperty(value = "菜单名称", required = true, example = "博客管理")
private String name;

@NotBlank(message = "菜单类型不能为空")
@Pattern(regexp = "^[CMB]$", message = "菜单类型只能为C(目录)、M(菜单)或B(按钮)")
@ApiModelProperty(value = "菜单类型(C-目录 M-菜单 B-按钮)", required = true, example = "C")
private String type;

@ApiModelProperty(value = "路由路径", example = "/blog")
private String path;

@ApiModelProperty(value = "路由名称(前端路由name)", example = "Blog")
private String routeName;

@ApiModelProperty(value = "路由路径(自定义路由路径(菜单和目录必填,按钮可不填))", example = "/blog/list")
private String routePath;

@ApiModelProperty(value = "重定向路径", example = "/blog/list")
private String redirect;

@ApiModelProperty(value = "组件路径(目录填Layout,菜单填组件路径)", example = "blog/index")
private String component;

@ApiModelProperty(value = "菜单图标", example = "el-icon-document")
private String icon;

@ApiModelProperty(value = "显示排序(数字越小越靠前)", example = "1")
private Integer sort;

@Pattern(regexp = "^[01]$", message = "菜单可见状态只能为0或1")
@ApiModelProperty(value = "菜单是否可见(0-显示 1-隐藏)",example = "0")
private String visible;

@ApiModelProperty(value = "目录是否始终显示(0-显示 1-隐藏)",example = "0")
private String alwaysShow;

@ApiModelProperty(value = "权限标识(按钮必填)", example = "system:user:add")
private String perm;

@ApiModelProperty(value = "是否缓存(0-缓存 1-不缓存)", example = "0")
private String keepAlive;

@ApiModelProperty(value = "路由参数数组", example = "[{\"key\":\"from\",\"value\":\"admin\"}]")
private List<MenuParamDto> params;
}

在 AdminLinkServiceImpl 中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
//更新菜单
@Override
public ResponseResult updateMenu(Long id, UpdateMenuDto updateMenuDto)
{
//获得菜单id
updateMenuDto.setId(id);

//检查菜单是否存在
SysMenu oldMenu = sysMenuService.getById(id);
if (oldMenu == null) {
return ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR, "菜单不存在!");
}

//校验父菜单是否存在
if (updateMenuDto.getParentId() != 0L) {
SysMenu parentMenu = getById(updateMenuDto.getParentId());
if (parentMenu == null) {
return ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR, "父菜单不存在!");
}
if (updateMenuDto.getParentId().equals(id)) {
return ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR, "父菜单不能是自己!");
}
}

//校验目录/菜单必须有路由路径
if ((SystemConstants.MENU_TYPE_C.equals(updateMenuDto.getType()) ||
SystemConstants.MENU_TYPE_M.equals(updateMenuDto.getType())) &&
!StringUtils.hasText(updateMenuDto.getRoutePath())) {
return ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR, "目录和菜单的路由路径不能为空!");
}

//校验同一父菜单下是否存在同名菜单(排除自己)
LambdaQueryWrapper<SysMenu> nameQuery = new LambdaQueryWrapper<>();
nameQuery.eq(SysMenu::getParentId, updateMenuDto.getParentId())
.eq(SysMenu::getName, updateMenuDto.getName())
.ne(SysMenu::getId, id);

if (count(nameQuery) > 0) {
return ResponseResult.errorResult(AppHttpCodeEnum.SYSTEM_ERROR, "该父菜单下已存在同名菜单!");
}

//复制属性
SysMenu menu = BeanCopyUtils.copyBean(updateMenuDto, SysMenu.class);

//将routePath的值同时保存到path中
if (StringUtils.hasText(updateMenuDto.getRoutePath())) {
menu.setPath(updateMenuDto.getRoutePath());
}

//处理 params 字段
if (updateMenuDto.getParams() != null) {
menu.setParams(JSON.toJSONString(updateMenuDto.getParams()));
}

//更新菜单
sysMenuService.updateById(menu);

return ResponseResult.okResult();
}



PS:该系列只做为作者学习开发项目做的笔记用

不一定符合读者来学习,仅供参考


预告

后续会记录博客的开发过程

每次学习会做一份笔记来进行发表

“一花一世界,一叶一菩提”


版权所有 © 2026 云梦泽
欢迎访问我的个人网站:https://hgt12.github.io/


『博客开发日记-后台』之更新菜单接口的实现
http://example.com/2026/05/05/『博客开发日记-后台』之更新菜单接口的实现/
作者
云梦泽
发布于
2026年5月5日
更新于
2026年5月6日
许可协议