前些天写的一个小模块了,记录一下,后面还会用到~
这是一个查询菜单接口,要求是:分页查询,一级菜单(父),二级菜单(子)等。这里接口是post类型,传参为:pagenum和pagesize为我们要分页查询的必须值,返回值为如下样式:
//实例
{
"code": 200,
"message": "操作成功!",
"data": {
"total": 12,
"pageSize": 2,
"list": [
{
"id": "04f29f26-2eb8-4dfb-bfb2-856937b1d454",
"name": "订单管理",
"pid": null,
"pathUrl": "/layout/sysmanager/dictionary",
"iconUrl": "123",
"type": false,
"desc": null,
"applicationId": null,
"tenantName": "龙傲天",
"tenantId": "1",
"ordernum": "1",
"createUser": "demo",
"updateUser": "demo",
"createTime": "2024-12-24T16:00:00.000+00:00",
"updateTime": "2025-02-05T00:40:34.464+00:00",
"children": [
{
"id": "7006eaf2-a479-43c7-876c-d8d9541a28c8",
"name": "订单管理",
"pid": "04f29f26-2eb8-4dfb-bfb2-856937b1d454",
"pathUrl": "/layout/sysmanager/user",
"iconUrl": "223",
"type": false,
"desc": null,
"applicationId": null,
"tenantName": "龙傲天",
"tenantId": "1",
"ordernum": "1",
"createUser": "demo",
"updateUser": "demo",
"createTime": "2024-12-24T16:00:00.000+00:00",
"updateTime": "2024-12-29T16:00:00.000+00:00",
"children": [],
"deleted": false,
"pagenum": 0,
"pagesize": 0
}
],
"deleted": false,
"pagenum": 0,
"pagesize": 0
}
],
"pageNum": 1
}
}
弄清楚我们的想法后,接下来是代码实现:
- controller层:
/** * 查询所有菜单 * @param queryMenuListDTO * @return */ @PostMapping("/getAllMenu") public ApiResponse getAllMenu(@RequestBody QueryMenuListDTO queryMenuListDTO){ return ApiResponse.success(menuService.getAllMenu(queryMenuListDTO)); }
- service层:
/** * 获取所有菜单 * @param queryMenuListDTO * @return */ @Override public Map getAllMenu(QueryMenuListDTO queryMenuListDTO) { log.info("getAllMenu 开始执行,参数:{}", queryMenuListDTO); // 创建分页对象 Page<QueryMenuListDTO> page = new Page<>(queryMenuListDTO.getPageNum(), queryMenuListDTO.getPageSize()); try { // 执行分页查询 Page<QueryMenuListDTO> menuPage = menuMapper.selectMenusWithPagination1(page, queryMenuListDTO); List<QueryMenuListDTO> allMenus = menuPage.getRecords(); // 打印分页信息用于调试 log.info("分页信息 - 当前页:{}, 每页大小:{}, 总记录数:{}", menuPage.getCurrent(), menuPage.getSize(), menuPage.getTotal()); if (allMenus.isEmpty()) { Map<String, Object> emptyResult = new HashMap<>(); emptyResult.put("total", 0); emptyResult.put("list", new ArrayList<>()); emptyResult.put("pageNum", queryMenuListDTO.getPageNum()); emptyResult.put("pageSize", queryMenuListDTO.getPageSize()); return emptyResult; } // 构建菜单树 Map<String, QueryMenuListDTO> menuMap = new HashMap<>(); for (QueryMenuListDTO menu : allMenus) { menu.setChildren(new ArrayList<>()); menuMap.put(menu.getId(), menu); } List<QueryMenuListDTO> menuTree = new ArrayList<>(); for (QueryMenuListDTO menu : allMenus) { String pid = menu.getPid(); if (pid == null || pid.trim().isEmpty()) { menuTree.add(menu); } else { QueryMenuListDTO parentMenu = menuMap.get(pid); if (parentMenu != null) { parentMenu.getChildren().add(menu); } else { log.warn("找不到菜单[{}]的父菜单[{}],作为一级菜单处理", menu.getName(), pid); menuTree.add(menu); } } } // 构建返回结果 Map<String, Object> result = new HashMap<>(); result.put("total", menuPage.getTotal()); result.put("list", menuTree); result.put("pageNum", menuPage.getCurrent()); result.put("pageSize", menuPage.getSize()); log.info("getAllMenu 执行完成,返回数据大小:{}", menuTree.size()); return result; } catch (ServiceException e) { log.error("getAllMenu 执行异常", e); throw new ServiceException("获取菜单失败"); } }
- Mapper层:
<select id="selectMenusWithPagination1" resultType="org.xxx.domain.dto.QueryMenuListDTO"> SELECT DISTINCT m.* ,t.name as tenant_name FROM ycb_server_admin.tb_function m LEFT JOIN ycb_server_admin.tb_tenant t ON m.tenant_id = t.id WHERE m.deleted = 0 <if test="queryMenuListDTO.tenantId != null and queryMenuListDTO.tenantId != ''"> AND m.tenant_id = #{queryMenuListDTO.tenantId} </if> <if test="queryMenuListDTO.id != null and queryMenuListDTO.id != ''"> AND m.id = #{queryMenuListDTO.id} || m.pid = #{queryMenuListDTO.id} </if> <if test="queryMenuListDTO.type != null and queryMenuListDTO.type != ''"> AND m.type = #{queryMenuListDTO.type} </if> ORDER BY m.ordernum ASC, m.create_time ASC </select>
- 总结:关键点在于构建菜单树,我是有一个字段pid,如果a数据的id在数据库中查询pid,查到有数据的pid等于该id,那他就有子菜单,把该数据存为children数据里,如果数据的pid字段没有数据,那么就存为一级菜单(父)来构建,最后保存到一起返回这个菜单树,最终的效果在最上面已经展示了,效果还可以,下次还用哈哈哈