GetMenuTree 获取菜单树形结构
(ctx context.Context)
| 276 | |
| 277 | // GetMenuTree 获取菜单树形结构 |
| 278 | func (m *menuDAO) GetMenuTree(ctx context.Context) ([]*Menu, error) { |
| 279 | // 预分配合适的初始容量 |
| 280 | menus := make([]*Menu, 0, 50) |
| 281 | |
| 282 | // 使用索引字段优化查询 |
| 283 | if err := m.db.WithContext(ctx). |
| 284 | Select("id, name, parent_id, path, component, icon, sort_order, route_name, hidden, create_time, update_time"). |
| 285 | Where("is_deleted = ?", 0). |
| 286 | Order("sort_order ASC, id ASC"). |
| 287 | Find(&menus).Error; err != nil { |
| 288 | return nil, fmt.Errorf("查询菜单列表失败: %v", err) |
| 289 | } |
| 290 | |
| 291 | // 预分配map容量 |
| 292 | menuMap := make(map[int]*Menu, len(menus)) |
| 293 | rootMenus := make([]*Menu, 0, len(menus)/3) // 假设大约1/3的菜单是根菜单 |
| 294 | |
| 295 | // 第一次遍历,建立ID到菜单的映射 |
| 296 | for _, menu := range menus { |
| 297 | if menu == nil { |
| 298 | continue |
| 299 | } |
| 300 | menu.Children = make([]*Menu, 0, 4) // 预分配子菜单切片,假设平均4个子菜单 |
| 301 | menuMap[menu.ID] = menu |
| 302 | } |
| 303 | |
| 304 | // 第二次遍历,构建树形结构 |
| 305 | for _, menu := range menus { |
| 306 | if menu == nil { |
| 307 | continue |
| 308 | } |
| 309 | if menu.ParentID == 0 { |
| 310 | rootMenus = append(rootMenus, menu) |
| 311 | } else { |
| 312 | if parent, exists := menuMap[menu.ParentID]; exists { |
| 313 | parent.Children = append(parent.Children, menu) |
| 314 | } else { |
| 315 | // 如果找不到父节点,作为根节点处理 |
| 316 | rootMenus = append(rootMenus, menu) |
| 317 | } |
| 318 | } |
| 319 | } |
| 320 | |
| 321 | return rootMenus, nil |
| 322 | } |
nothing calls this directly
no outgoing calls
no test coverage detected