kra-oa/internal/biz/menu.go

154 lines
3.9 KiB
Go

package biz
import (
"context"
"time"
)
type MenuButton struct {
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time
ID uint
Name string
Description string
MenuID uint
AuthorityID uint
}
type MenuParameter struct {
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time
ID uint
MenuID uint
Type string
Key string
Value string
}
type Menu struct {
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time
ID uint
MenuID 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 if item.ParentID == 0 {
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. The compatible query does not preload either
// relation here, so parameters must remain absent as well.
item.Buttons = nil
item.Parameters = 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)
}