package biz import "context" type MenuButton struct { ID uint Name string Description string MenuID uint AuthorityID uint } type MenuParameter struct { ID uint MenuID uint Type string Key string Value string } type Menu struct { ID uint ParentID uint Path string Name string Hidden bool Component string Sort int ActiveName string KeepAlive bool DefaultMenu bool Title string Icon string CloseTab bool TransitionType string Children []*Menu Buttons []*MenuButton Parameters []*MenuParameter } type MenuRepo interface { Create(context.Context, *Menu) error Update(context.Context, *Menu) error Delete(context.Context, uint) error Find(context.Context, uint) (*Menu, error) List(context.Context) ([]*Menu, error) SetAuthorityMenus(context.Context, uint, []uint) error AuthorityMenuIDs(context.Context, uint) ([]uint, error) MenuRoleIDs(context.Context, uint) ([]uint, error) DefaultRouterRoleIDs(context.Context, uint) ([]uint, error) SetMenuRoles(context.Context, uint, []uint) error } type MenuUsecase struct{ repo MenuRepo } func NewMenuUsecase(repo MenuRepo) *MenuUsecase { return &MenuUsecase{repo: repo} } func (uc *MenuUsecase) List(ctx context.Context) ([]*Menu, error) { return uc.repo.List(ctx) } func (uc *MenuUsecase) Tree(ctx context.Context) ([]*Menu, error) { items, err := uc.repo.List(ctx) if err != nil { return nil, err } byID := make(map[uint]*Menu, len(items)) for _, item := range items { item.Children = []*Menu{} byID[item.ID] = item } roots := make([]*Menu, 0) for _, item := range items { if parent := byID[item.ParentID]; parent != nil { parent.Children = append(parent.Children, item) } else { roots = append(roots, item) } } return roots, nil } func (uc *MenuUsecase) Create(ctx context.Context, menu *Menu) error { return uc.repo.Create(ctx, menu) } func (uc *MenuUsecase) Update(ctx context.Context, menu *Menu) error { return uc.repo.Update(ctx, menu) } func (uc *MenuUsecase) Delete(ctx context.Context, id uint) error { return uc.repo.Delete(ctx, id) } func (uc *MenuUsecase) Find(ctx context.Context, id uint) (*Menu, error) { return uc.repo.Find(ctx, id) } func (uc *MenuUsecase) SetAuthorityMenus(ctx context.Context, authorityID uint, ids []uint) error { return uc.repo.SetAuthorityMenus(ctx, authorityID, ids) } func (uc *MenuUsecase) AuthorityMenus(ctx context.Context, authorityID uint) ([]*Menu, error) { ids, err := uc.repo.AuthorityMenuIDs(ctx, authorityID) if err != nil { return nil, err } items, err := uc.repo.List(ctx) if err != nil { return nil, err } selected := make(map[uint]struct{}, len(ids)) for _, id := range ids { selected[id] = struct{}{} } result := make([]*Menu, 0, len(ids)) for _, item := range items { if _, ok := selected[item.ID]; ok { // The authority-menu endpoint returns menu relations only. Keep its // existing contract: button details are loaded by the dedicated // authority-button endpoints. item.Buttons = nil result = append(result, item) } } return result, nil } func (uc *MenuUsecase) RoleIDs(ctx context.Context, menuID uint) ([]uint, error) { return uc.repo.MenuRoleIDs(ctx, menuID) } func (uc *MenuUsecase) DefaultRouterRoleIDs(ctx context.Context, menuID uint) ([]uint, error) { return uc.repo.DefaultRouterRoleIDs(ctx, menuID) } func (uc *MenuUsecase) SetRoles(ctx context.Context, menuID uint, ids []uint) error { return uc.repo.SetMenuRoles(ctx, menuID, ids) }