前面实现了getUserInfo,然后我们会发现登陆进去后会自动执行getMenu和getMenuTop方法,由于我们还没有这两个接口,左侧菜单列表是空的,我们来实现一下这两个接口。
首先我们打开menu.js,这里的first展示了菜单格式。
我们将avue-cli的菜单统一放到工具这个一级列表下,我们自己的菜单单独建立一级列表。
首先我们导入一些数据:
菜单:
INSERT INTO `image_processing_platform`.`menu` (`id`, `deleted`, `status`, `remark`, `label`, `path`, `component`, `icon`, `icon_bg_color`, `meta`, `href`, `parent_id`) VALUES (1, 0, 1, NULL, '工具', '/util', NULL, 'icon-caidan', '#fff', '{\"i18n\": \"util\"}', NULL, 0);
INSERT INTO `image_processing_platform`.`menu` (`id`, `deleted`, `status`, `remark`, `label`, `path`, `component`, `icon`, `icon_bg_color`, `meta`, `href`, `parent_id`) VALUES (2, 0, 1, NULL, '缓冲', '/cache', 'views/util/cache', 'icon-caidan', '#fff', '{\"i18n\": \"cache\", \"keepAlive\": true}', NULL, 1);
INSERT INTO `image_processing_platform`.`menu` (`id`, `deleted`, `status`, `remark`, `label`, `path`, `component`, `icon`, `icon_bg_color`, `meta`, `href`, `parent_id`) VALUES (3, 0, 1, NULL, '参数', '/params', 'views/util/params', 'icon-caidan', '#fff', '{\"i18n\": \"params\"}', NULL, 1);
INSERT INTO `image_processing_platform`.`menu` (`id`, `deleted`, `status`, `remark`, `label`, `path`, `component`, `icon`, `icon_bg_color`, `meta`, `href`, `parent_id`) VALUES (4, 0, 1, NULL, '详情页', '/detail', 'views/util/detail', 'icon-caidan', '#fff', '{\"i18n\": \"detail\"}', NULL, 1);
INSERT INTO `image_processing_platform`.`menu` (`id`, `deleted`, `status`, `remark`, `label`, `path`, `component`, `icon`, `icon_bg_color`, `meta`, `href`, `parent_id`) VALUES (5, 0, 1, NULL, '标签', '/tags', 'views/util/tags', 'icon-caidan', '#fff', '{\"i18n\": \"tags\"}', NULL, 1);
INSERT INTO `image_processing_platform`.`menu` (`id`, `deleted`, `status`, `remark`, `label`, `path`, `component`, `icon`, `icon_bg_color`, `meta`, `href`, `parent_id`) VALUES (6, 0, 1, NULL, '存储', '/store', 'views/util/store', 'icon-caidan', '#fff', '{\"i18n\": \"store\"}', NULL, 1);
INSERT INTO `image_processing_platform`.`menu` (`id`, `deleted`, `status`, `remark`, `label`, `path`, `component`, `icon`, `icon_bg_color`, `meta`, `href`, `parent_id`) VALUES (7, 0, 1, NULL, '日志监控', '/logs', 'views/util/logs', 'icon-caidan', '#fff', '{\"i18n\": \"logs\"}', NULL, 1);
INSERT INTO `image_processing_platform`.`menu` (`id`, `deleted`, `status`, `remark`, `label`, `path`, `component`, `icon`, `icon_bg_color`, `meta`, `href`, `parent_id`) VALUES (8, 0, 1, NULL, '通用模板', '/crud', 'views/util/crud', 'icon-caidan', '#fff', '{\"i18n\": \"crud\"}', NULL, 1);
INSERT INTO `image_processing_platform`.`menu` (`id`, `deleted`, `status`, `remark`, `label`, `path`, `component`, `icon`, `icon_bg_color`, `meta`, `href`, `parent_id`) VALUES (9, 0, 1, NULL, '表格', '/table', 'views/util/table', 'icon-caidan', '#fff', '{\"i18n\": \"table\"}', NULL, 1);
INSERT INTO `image_processing_platform`.`menu` (`id`, `deleted`, `status`, `remark`, `label`, `path`, `component`, `icon`, `icon_bg_color`, `meta`, `href`, `parent_id`) VALUES (10, 0, 1, NULL, '表单', '/form', 'views/util/form', 'icon-caidan', '#fff', '{\"i18n\": \"form\"}', NULL, 1);
INSERT INTO `image_processing_platform`.`menu` (`id`, `deleted`, `status`, `remark`, `label`, `path`, `component`, `icon`, `icon_bg_color`, `meta`, `href`, `parent_id`) VALUES (11, 0, 1, NULL, '权限', '/permission', 'views/util/permission', 'icon-caidan', '#fff', '{\"i18n\": \"permission\"}', NULL, 1);
INSERT INTO `image_processing_platform`.`menu` (`id`, `deleted`, `status`, `remark`, `label`, `path`, `component`, `icon`, `icon_bg_color`, `meta`, `href`, `parent_id`) VALUES (12, 0, 1, NULL, '表格表单', '/crud-form', 'views/util/crud-form', 'icon-caidan', '#fff', '{\"i18n\": \"crudForm\"}', NULL, 1);
INSERT INTO `image_processing_platform`.`menu` (`id`, `deleted`, `status`, `remark`, `label`, `path`, `component`, `icon`, `icon_bg_color`, `meta`, `href`, `parent_id`) VALUES (13, 0, 1, NULL, '返回顶部', '/top', 'views/util/top', 'icon-caidan', '#fff', '{\"i18n\": \"top\"}', NULL, 1);
INSERT INTO `image_processing_platform`.`menu` (`id`, `deleted`, `status`, `remark`, `label`, `path`, `component`, `icon`, `icon_bg_color`, `meta`, `href`, `parent_id`) VALUES (14, 0, 1, NULL, '图钉', '/affix', 'views/util/affix', 'icon-caidan', '#fff', '{\"i18n\": \"affix\"}', NULL, 1);
INSERT INTO `image_processing_platform`.`menu` (`id`, `deleted`, `status`, `remark`, `label`, `path`, `component`, `icon`, `icon_bg_color`, `meta`, `href`, `parent_id`) VALUES (15, 0, 1, NULL, '多级菜单', '/deep', NULL, 'icon-caidan', '#fff', NULL, NULL, 1);
INSERT INTO `image_processing_platform`.`menu` (`id`, `deleted`, `status`, `remark`, `label`, `path`, `component`, `icon`, `icon_bg_color`, `meta`, `href`, `parent_id`) VALUES (16, 0, 1, NULL, '外部页面', '/out', NULL, 'icon-caidan', '#fff', '{\"i18n\": \"out\"}', NULL, 1);
INSERT INTO `image_processing_platform`.`menu` (`id`, `deleted`, `status`, `remark`, `label`, `path`, `component`, `icon`, `icon_bg_color`, `meta`, `href`, `parent_id`) VALUES (17, 0, 1, NULL, '异常页', '/error', NULL, 'icon-caidan', '#fff', '{\"i18n\": \"error\"}', NULL, 1);
INSERT INTO `image_processing_platform`.`menu` (`id`, `deleted`, `status`, `remark`, `label`, `path`, `component`, `icon`, `icon_bg_color`, `meta`, `href`, `parent_id`) VALUES (18, 0, 1, NULL, '关于', '/about', 'views/util/about', 'icon-caidan', '#fff', '{\"i18n\": \"about\"}', NULL, 1);
INSERT INTO `image_processing_platform`.`menu` (`id`, `deleted`, `status`, `remark`, `label`, `path`, `component`, `icon`, `icon_bg_color`, `meta`, `href`, `parent_id`) VALUES (19, 0, 1, NULL, '多级菜单1-1', 'deep', NULL, 'icon-caidan', '#fff', NULL, NULL, 15);
INSERT INTO `image_processing_platform`.`menu` (`id`, `deleted`, `status`, `remark`, `label`, `path`, `component`, `icon`, `icon_bg_color`, `meta`, `href`, `parent_id`) VALUES (20, 0, 1, NULL, '多级菜单2-1', 'deep', 'views/util/deep', 'icon-caidan', '#fff', NULL, NULL, 19);
INSERT INTO `image_processing_platform`.`menu` (`id`, `deleted`, `status`, `remark`, `label`, `path`, `component`, `icon`, `icon_bg_color`, `meta`, `href`, `parent_id`) VALUES (21, 0, 1, NULL, '官方网站(内嵌页面)', 'website', NULL, 'icon-caidan', '#fff', '{\"i18n\": \"website\"}', 'https://avuejs.com', 16);
INSERT INTO `image_processing_platform`.`menu` (`id`, `deleted`, `status`, `remark`, `label`, `path`, `component`, `icon`, `icon_bg_color`, `meta`, `href`, `parent_id`) VALUES (22, 0, 1, NULL, '全局函数(外链页面)', 'api', NULL, 'icon-caidan', '#fff', '{\"i18n\": \"api\", \"target\": \"_blank\"}', 'https://avuejs.com/docs/api?test1=1&test2=2', 16);
INSERT INTO `image_processing_platform`.`menu` (`id`, `deleted`, `status`, `remark`, `label`, `path`, `component`, `icon`, `icon_bg_color`, `meta`, `href`, `parent_id`) VALUES (23, 0, 1, NULL, 'error403', 'error', 'components/error-page/403', 'icon-caidan', '#fff', NULL, NULL, 17);
INSERT INTO `image_processing_platform`.`menu` (`id`, `deleted`, `status`, `remark`, `label`, `path`, `component`, `icon`, `icon_bg_color`, `meta`, `href`, `parent_id`) VALUES (24, 0, 1, NULL, 'error404', '404', 'components/error-page/404', 'icon-caidan', '#fff', NULL, NULL, 17);
INSERT INTO `image_processing_platform`.`menu` (`id`, `deleted`, `status`, `remark`, `label`, `path`, `component`, `icon`, `icon_bg_color`, `meta`, `href`, `parent_id`) VALUES (25, 0, 1, NULL, 'error500', '500', 'components/error-page/500', 'icon-caidan', '#fff', NULL, NULL, 17);
INSERT INTO `image_processing_platform`.`menu` (`id`, `deleted`, `status`, `remark`, `label`, `path`, `component`, `icon`, `icon_bg_color`, `meta`, `href`, `parent_id`) VALUES (26, 0, 1, NULL, '系统管理', '/system', NULL, 'icon-caidan', '#fff', '{\"i18n\": \"system\"}', NULL, 0);
INSERT INTO `image_processing_platform`.`menu` (`id`, `deleted`, `status`, `remark`, `label`, `path`, `component`, `icon`, `icon_bg_color`, `meta`, `href`, `parent_id`) VALUES (27, 0, 1, NULL, '参数管理', '/params', 'views/system/params', 'icon-caidan', '#fff', '{\"i18n\": \"params\"}', NULL, 26);
INSERT INTO `image_processing_platform`.`menu` (`id`, `deleted`, `status`, `remark`, `label`, `path`, `component`, `icon`, `icon_bg_color`, `meta`, `href`, `parent_id`) VALUES (28, 0, 1, NULL, '菜单管理', '/menu', 'views/system/menu', 'icon-caidan', '#fff', '{\"i18n\": \"menu\"}', NULL, 26);
菜单权限:
INSERT INTO `image_processing_platform`.`menu_permission` (`id`, `deleted`, `status`, `remark`, `role_id`, `menu_id`) VALUES (1, 0, 1, NULL, 1, 1);
INSERT INTO `image_processing_platform`.`menu_permission` (`id`, `deleted`, `status`, `remark`, `role_id`, `menu_id`) VALUES (2, 0, 1, NULL, 1, 2);
INSERT INTO `image_processing_platform`.`menu_permission` (`id`, `deleted`, `status`, `remark`, `role_id`, `menu_id`) VALUES (3, 0, 1, NULL, 1, 3);
INSERT INTO `image_processing_platform`.`menu_permission` (`id`, `deleted`, `status`, `remark`, `role_id`, `menu_id`) VALUES (4, 0, 1, NULL, 1, 4);
INSERT INTO `image_processing_platform`.`menu_permission` (`id`, `deleted`, `status`, `remark`, `role_id`, `menu_id`) VALUES (5, 0, 1, NULL, 1, 5);
INSERT INTO `image_processing_platform`.`menu_permission` (`id`, `deleted`, `status`, `remark`, `role_id`, `menu_id`) VALUES (6, 0, 1, NULL, 1, 6);
INSERT INTO `image_processing_platform`.`menu_permission` (`id`, `deleted`, `status`, `remark`, `role_id`, `menu_id`) VALUES (7, 0, 1, NULL, 1, 7);
INSERT INTO `image_processing_platform`.`menu_permission` (`id`, `deleted`, `status`, `remark`, `role_id`, `menu_id`) VALUES (8, 0, 1, NULL, 1, 8);
INSERT INTO `image_processing_platform`.`menu_permission` (`id`, `deleted`, `status`, `remark`, `role_id`, `menu_id`) VALUES (9, 0, 1, NULL, 1, 9);
INSERT INTO `image_processing_platform`.`menu_permission` (`id`, `deleted`, `status`, `remark`, `role_id`, `menu_id`) VALUES (10, 0, 1, NULL, 1, 10);
INSERT INTO `image_processing_platform`.`menu_permission` (`id`, `deleted`, `status`, `remark`, `role_id`, `menu_id`) VALUES (11, 0, 1, NULL, 1, 11);
INSERT INTO `image_processing_platform`.`menu_permission` (`id`, `deleted`, `status`, `remark`, `role_id`, `menu_id`) VALUES (12, 0, 1, NULL, 1, 12);
INSERT INTO `image_processing_platform`.`menu_permission` (`id`, `deleted`, `status`, `remark`, `role_id`, `menu_id`) VALUES (13, 0, 1, NULL, 1, 13);
INSERT INTO `image_processing_platform`.`menu_permission` (`id`, `deleted`, `status`, `remark`, `role_id`, `menu_id`) VALUES (14, 0, 1, NULL, 1, 14);
INSERT INTO `image_processing_platform`.`menu_permission` (`id`, `deleted`, `status`, `remark`, `role_id`, `menu_id`) VALUES (15, 0, 1, NULL, 1, 15);
INSERT INTO `image_processing_platform`.`menu_permission` (`id`, `deleted`, `status`, `remark`, `role_id`, `menu_id`) VALUES (16, 0, 1, NULL, 1, 16);
INSERT INTO `image_processing_platform`.`menu_permission` (`id`, `deleted`, `status`, `remark`, `role_id`, `menu_id`) VALUES (17, 0, 1, NULL, 1, 17);
INSERT INTO `image_processing_platform`.`menu_permission` (`id`, `deleted`, `status`, `remark`, `role_id`, `menu_id`) VALUES (18, 0, 1, NULL, 1, 18);
INSERT INTO `image_processing_platform`.`menu_permission` (`id`, `deleted`, `status`, `remark`, `role_id`, `menu_id`) VALUES (19, 0, 1, NULL, 1, 19);
INSERT INTO `image_processing_platform`.`menu_permission` (`id`, `deleted`, `status`, `remark`, `role_id`, `menu_id`) VALUES (20, 0, 1, NULL, 1, 20);
INSERT INTO `image_processing_platform`.`menu_permission` (`id`, `deleted`, `status`, `remark`, `role_id`, `menu_id`) VALUES (21, 0, 1, NULL, 1, 21);
INSERT INTO `image_processing_platform`.`menu_permission` (`id`, `deleted`, `status`, `remark`, `role_id`, `menu_id`) VALUES (22, 0, 1, NULL, 1, 22);
INSERT INTO `image_processing_platform`.`menu_permission` (`id`, `deleted`, `status`, `remark`, `role_id`, `menu_id`) VALUES (23, 0, 1, NULL, 1, 23);
INSERT INTO `image_processing_platform`.`menu_permission` (`id`, `deleted`, `status`, `remark`, `role_id`, `menu_id`) VALUES (24, 0, 1, NULL, 1, 24);
INSERT INTO `image_processing_platform`.`menu_permission` (`id`, `deleted`, `status`, `remark`, `role_id`, `menu_id`) VALUES (25, 0, 1, NULL, 1, 25);
INSERT INTO `image_processing_platform`.`menu_permission` (`id`, `deleted`, `status`, `remark`, `role_id`, `menu_id`) VALUES (26, 0, 1, NULL, 1, 26);
INSERT INTO `image_processing_platform`.`menu_permission` (`id`, `deleted`, `status`, `remark`, `role_id`, `menu_id`) VALUES (27, 0, 1, NULL, 1, 27);
INSERT INTO `image_processing_platform`.`menu_permission` (`id`, `deleted`, `status`, `remark`, `role_id`, `menu_id`) VALUES (28, 0, 1, NULL, 1, 28);
角色:
INSERT INTO `image_processing_platform`.`role` (`id`, `deleted`, `status`, `remark`, `name`) VALUES (1, 0, 1, '超级管理员', 'admin');
INSERT INTO `image_processing_platform`.`role` (`id`, `deleted`, `status`, `remark`, `name`) VALUES (2, 0, 1, '平台管理员', 'app_admin');
INSERT INTO `image_processing_platform`.`role` (`id`, `deleted`, `status`, `remark`, `name`) VALUES (3, 0, 1, 'VIP用户', 'vip_user');
INSERT INTO `image_processing_platform`.`role` (`id`, `deleted`, `status`, `remark`, `name`) VALUES (4, 0, 1, '普通用户', 'user');
用户:
INSERT INTO `image_processing_platform`.`user` (`id`, `deleted`, `status`, `remark`, `username`, `password`, `email`, `role_id`) VALUES (1, 0, 1, NULL, 'admin', '123456', '213269@qq.com', 1);
稍微修改菜单的实体类:
@Data
@NoArgsConstructor
@AllArgsConstructor
@TableName("menu")
@Accessors(chain = true)
public class Menu extends BaseEntity implements Serializable {
private static long serialVersionUID = 1L;
private String label;
private String path;
private String component;
private String icon = "icon-caidan";
private String iconBgColor = "#fff";
private String meta;
private String href;
private Long parentId;
@TableField(exist = false)
private List<Menu> children = new LinkedList<>();
}
然后开始根据token获取菜单,原理是根据token获取缓存中的用户信息,然后用用户信息的roleId和菜单权限表去查菜单,将菜单封装为树形结构:
<select id="getMenuListByRoleId" resultType="com.llpp.entity.Menu">
-- 使用 CTE 进行递归查询
WITH RECURSIVE menu_tree AS (
-- 初始查询,获取所有根菜单(parent_id = 0)
SELECT id,
deleted,
status,
remark,
label,
path,
component,
icon,
icon_bg_color,
meta,
href,
parent_id
FROM menu
WHERE parent_id = 0
AND deleted = 0 -- 只查询未删除的菜单
AND status = 1 -- 只查询正常状态的菜单
UNION ALL
-- 递归部分,获取子菜单
SELECT m.id,
m.deleted,
m.status,
m.remark,
m.label,
m.path,
m.component,
m.icon,
m.icon_bg_color,
m.meta,
m.href,
m.parent_id
FROM menu m
JOIN
menu_tree mt ON m.parent_id = mt.id
WHERE m.deleted = 0 -- 只查询未删除的菜单
AND m.status = 1 -- 只查询正常状态的菜单
)
SELECT DISTINCT t.id,
t.deleted,
t.status,
t.remark,
t.label,
t.path,
t.component,
t.icon,
t.icon_bg_color,
t.meta,
t.href,
t.parent_id
FROM menu_tree t
LEFT JOIN menu_permission mp ON t.id = mp.menu_id
WHERE mp.role_id = #{roleId}
</select>
List<Menu> getMenuListByRoleId(@Param("roleId") Long roleId);
List<Menu> getMenuListByRoleId(Long roleId);
@Override
public List<Menu> getMenuListByRoleId(Long roleId) {
List<Menu> menuList = baseMapper.getMenuListByRoleId(roleId);
List<Menu> result = new LinkedList<>();
Map<Long, Menu> menuMap = menuList.stream().collect(HashMap::new, (k, v) -> k.put(v.getId(), v), (m1, m2) -> m1.putAll(m2));
for (Menu menu : menuList) {
Menu parent = menuMap.get(menu.getParentId());
if (parent != null) {
parent.getChildren().add(menu);
} else {
result.add(menu);
}
}
return result;
}
@GetMapping("/getMenu")
public Result getMenu(HttpServletRequest request) {
return Result.data(Optional.ofNullable(request.getHeader("authorization"))
.map(token -> {
token = token.substring(token.indexOf(" ") + 1);
String info = redisService.getValueOrDefault(token, "").toString();
User user = JSONUtil.toBean(info, User.class);
log.info("用户获取菜单==》" + user);
return menuService.getMenuListByRoleId(user.getRoleId());
}).orElse(null));
}
这样就完成了getMenu,至于getMenuTop,我们直接返回默认就行了。
@GetMapping("/getTopMenu")
public Result getTopMenu(HttpServletRequest request) {
List<Menu> top = List.of(
new Menu("首页", "/wel/index", null, "el-icon-document", null, new JSONObject().put("i18n", "dashboard").toString(), null, 0L, Collections.EMPTY_LIST),
new Menu("测试", "/test", null, "el-icon-document", null, new JSONObject().put("i18n", "test").toString(), null, 1L, Collections.EMPTY_LIST),
new Menu("更多", "/wel/more", null, "el-icon-document", null, new JSONObject().put("menu", false).put("i18n", "more").toString(), null, 2L, Collections.EMPTY_LIST)
);
return Result.data(top);
}
试试效果: