package system import ( "context" "kra/internal/biz/system" "kra/internal/server/middleware" "github.com/go-kratos/kratos/v2/errors" "github.com/go-kratos/kratos/v2/transport/http" ) // MenuService 菜单服务 type MenuService struct { uc *system.MenuUsecase } // NewMenuService 创建菜单服务 func NewMenuService(uc *system.MenuUsecase) *MenuService { return &MenuService{uc: uc} } // MenuInfo 菜单信息 type MenuInfo struct { ID uint `json:"ID"` ParentId uint `json:"parentId"` Path string `json:"path"` Name string `json:"name"` Hidden bool `json:"hidden"` Component string `json:"component"` Sort int `json:"sort"` Meta MenuMeta `json:"meta"` AuthorityId uint `json:"authorityId,omitempty"` MenuId uint `json:"menuId,omitempty"` Parameters []*MenuParamInfo `json:"parameters,omitempty"` MenuBtn []*MenuBtnInfo `json:"menuBtn,omitempty"` Btns map[string]uint `json:"btns,omitempty"` Children []*MenuInfo `json:"children,omitempty"` } // MenuMeta 菜单元信息 type MenuMeta struct { ActiveName string `json:"activeName"` KeepAlive bool `json:"keepAlive"` DefaultMenu bool `json:"defaultMenu"` Title string `json:"title"` Icon string `json:"icon"` CloseTab bool `json:"closeTab"` TransitionType string `json:"transitionType"` } // MenuParamInfo 菜单参数信息 type MenuParamInfo struct { ID uint `json:"ID"` SysBaseMenuID uint `json:"sysBaseMenuId"` Type string `json:"type"` Key string `json:"key"` Value string `json:"value"` } // MenuBtnInfo 菜单按钮信息 type MenuBtnInfo struct { ID uint `json:"ID"` SysBaseMenuID uint `json:"sysBaseMenuId"` Name string `json:"name"` Desc string `json:"desc"` } // BaseMenuRequest 基础菜单请求 type BaseMenuRequest struct { ID uint `json:"ID"` ParentId uint `json:"parentId"` Path string `json:"path"` Name string `json:"name"` Hidden bool `json:"hidden"` Component string `json:"component"` Sort int `json:"sort"` Meta MenuMeta `json:"meta"` Parameters []*MenuParamInfo `json:"parameters"` MenuBtn []*MenuBtnInfo `json:"menuBtn"` } // GetMenu 获取用户动态路由 func (s *MenuService) GetMenu(ctx context.Context, authorityId uint) ([]*MenuInfo, error) { menus, err := s.uc.GetMenuTree(ctx, authorityId) if err != nil { return nil, err } return toMenuInfoList(menus), nil } // GetBaseMenuTree 获取基础菜单树 func (s *MenuService) GetBaseMenuTree(ctx context.Context, authorityId uint) ([]*MenuInfo, error) { menus, err := s.uc.GetBaseMenuTree(ctx, authorityId) if err != nil { return nil, err } return toBaseMenuInfoList(menus), nil } // GetMenuList 获取菜单列表 func (s *MenuService) GetMenuList(ctx context.Context, authorityId uint) ([]*MenuInfo, error) { menus, err := s.uc.GetInfoList(ctx, authorityId) if err != nil { return nil, err } return toBaseMenuInfoList(menus), nil } // AddBaseMenu 添加基础菜单 func (s *MenuService) AddBaseMenu(ctx context.Context, req *BaseMenuRequest) error { menu := toBaseMenu(req) return s.uc.AddBaseMenu(ctx, menu) } // UpdateBaseMenu 更新基础菜单 func (s *MenuService) UpdateBaseMenu(ctx context.Context, req *BaseMenuRequest) error { menu := toBaseMenu(req) return s.uc.UpdateBaseMenu(ctx, menu) } // DeleteBaseMenu 删除基础菜单 func (s *MenuService) DeleteBaseMenu(ctx context.Context, id uint) error { return s.uc.DeleteBaseMenu(ctx, id) } // GetBaseMenuById 根据ID获取基础菜单 func (s *MenuService) GetBaseMenuById(ctx context.Context, id uint) (*MenuInfo, error) { menu, err := s.uc.GetBaseMenuById(ctx, id) if err != nil { return nil, err } return toBaseMenuInfo(menu), nil } // AddMenuAuthorityRequest 添加菜单权限请求 type AddMenuAuthorityRequest struct { AuthorityId uint `json:"authorityId"` Menus []*BaseMenuRequest `json:"menus"` } // AddMenuAuthority 添加菜单权限 func (s *MenuService) AddMenuAuthority(ctx context.Context, adminAuthorityID uint, req *AddMenuAuthorityRequest) error { menus := make([]*system.BaseMenu, len(req.Menus)) for i, m := range req.Menus { menus[i] = toBaseMenu(m) } return s.uc.AddMenuAuthority(ctx, menus, adminAuthorityID, req.AuthorityId) } // GetMenuAuthority 获取角色菜单权限 func (s *MenuService) GetMenuAuthority(ctx context.Context, authorityId uint) ([]*MenuInfo, error) { menus, err := s.uc.GetMenuAuthority(ctx, authorityId) if err != nil { return nil, err } return toMenuInfoList(menus), nil } // 转换函数 func toBaseMenu(req *BaseMenuRequest) *system.BaseMenu { menu := &system.BaseMenu{ ID: req.ID, ParentId: req.ParentId, Path: req.Path, Name: req.Name, Hidden: req.Hidden, Component: req.Component, Sort: req.Sort, ActiveName: req.Meta.ActiveName, KeepAlive: req.Meta.KeepAlive, DefaultMenu: req.Meta.DefaultMenu, Title: req.Meta.Title, Icon: req.Meta.Icon, CloseTab: req.Meta.CloseTab, TransitionType: req.Meta.TransitionType, } if len(req.Parameters) > 0 { menu.Parameters = make([]*system.MenuParameter, len(req.Parameters)) for i, p := range req.Parameters { menu.Parameters[i] = &system.MenuParameter{ ID: p.ID, SysBaseMenuID: p.SysBaseMenuID, Type: p.Type, Key: p.Key, Value: p.Value, } } } if len(req.MenuBtn) > 0 { menu.MenuBtn = make([]*system.MenuBtn, len(req.MenuBtn)) for i, b := range req.MenuBtn { menu.MenuBtn[i] = &system.MenuBtn{ ID: b.ID, SysBaseMenuID: b.SysBaseMenuID, Name: b.Name, Desc: b.Desc, } } } return menu } func toMenuInfoList(menus []*system.Menu) []*MenuInfo { if menus == nil { return []*MenuInfo{} } result := make([]*MenuInfo, len(menus)) for i, m := range menus { result[i] = toMenuInfo(m) } return result } func toMenuInfo(m *system.Menu) *MenuInfo { info := &MenuInfo{ ID: m.ID, ParentId: m.ParentId, Path: m.Path, Name: m.Name, Hidden: m.Hidden, Component: m.Component, Sort: m.Sort, AuthorityId: m.AuthorityId, MenuId: m.MenuId, Btns: m.Btns, Meta: MenuMeta{ ActiveName: m.ActiveName, KeepAlive: m.KeepAlive, DefaultMenu: m.DefaultMenu, Title: m.Title, Icon: m.Icon, CloseTab: m.CloseTab, TransitionType: m.TransitionType, }, } if len(m.Parameters) > 0 { info.Parameters = make([]*MenuParamInfo, len(m.Parameters)) for i, p := range m.Parameters { info.Parameters[i] = &MenuParamInfo{ ID: p.ID, SysBaseMenuID: p.SysBaseMenuID, Type: p.Type, Key: p.Key, Value: p.Value, } } } if len(m.Children) > 0 { info.Children = toMenuInfoList(m.Children) } return info } func toBaseMenuInfoList(menus []*system.BaseMenu) []*MenuInfo { if menus == nil { return []*MenuInfo{} } result := make([]*MenuInfo, len(menus)) for i, m := range menus { result[i] = toBaseMenuInfo(m) } return result } func toBaseMenuInfo(m *system.BaseMenu) *MenuInfo { info := &MenuInfo{ ID: m.ID, ParentId: m.ParentId, Path: m.Path, Name: m.Name, Hidden: m.Hidden, Component: m.Component, Sort: m.Sort, Meta: MenuMeta{ ActiveName: m.ActiveName, KeepAlive: m.KeepAlive, DefaultMenu: m.DefaultMenu, Title: m.Title, Icon: m.Icon, CloseTab: m.CloseTab, TransitionType: m.TransitionType, }, } if len(m.Parameters) > 0 { info.Parameters = make([]*MenuParamInfo, len(m.Parameters)) for i, p := range m.Parameters { info.Parameters[i] = &MenuParamInfo{ ID: p.ID, SysBaseMenuID: p.SysBaseMenuID, Type: p.Type, Key: p.Key, Value: p.Value, } } } if len(m.MenuBtn) > 0 { info.MenuBtn = make([]*MenuBtnInfo, len(m.MenuBtn)) for i, b := range m.MenuBtn { info.MenuBtn[i] = &MenuBtnInfo{ ID: b.ID, SysBaseMenuID: b.SysBaseMenuID, Name: b.Name, Desc: b.Desc, } } } if len(m.Children) > 0 { info.Children = toBaseMenuInfoList(m.Children) } return info } // RegisterRoutes 注册路由 func (s *MenuService) RegisterRoutes(rg *RouterGroup) { // 私有路由 + 操作记录(写操作) rg.PrivateWithRecord.POST("/menu/addBaseMenu", s.handleAddBaseMenu) rg.PrivateWithRecord.POST("/menu/addMenuAuthority", s.handleAddMenuAuthority) rg.PrivateWithRecord.POST("/menu/deleteBaseMenu", s.handleDeleteBaseMenu) rg.PrivateWithRecord.POST("/menu/updateBaseMenu", s.handleUpdateBaseMenu) // 私有路由(读操作,不记录) rg.Private.POST("/menu/getMenu", s.handleGetMenu) rg.Private.POST("/menu/getMenuList", s.handleGetMenuList) rg.Private.POST("/menu/getBaseMenuTree", s.handleGetBaseMenuTree) rg.Private.POST("/menu/getMenuAuthority", s.handleGetMenuAuthority) rg.Private.POST("/menu/getBaseMenuById", s.handleGetBaseMenuById) } // HTTP Handlers func (s *MenuService) handleGetMenu(ctx http.Context) error { authorityId := middleware.GetAuthorityID(ctx) menus, err := s.GetMenu(ctx, authorityId) if err != nil { return errors.InternalServer("GET_MENU_FAILED", err.Error()) } return ctx.Result(200, map[string]any{"code": 0, "msg": "获取成功", "data": map[string]any{"menus": menus}}) } func (s *MenuService) handleGetBaseMenuTree(ctx http.Context) error { authorityId := middleware.GetAuthorityID(ctx) menus, err := s.GetBaseMenuTree(ctx, authorityId) if err != nil { return errors.InternalServer("GET_MENU_FAILED", err.Error()) } return ctx.Result(200, map[string]any{"code": 0, "msg": "获取成功", "data": map[string]any{"menus": menus}}) } func (s *MenuService) handleGetMenuList(ctx http.Context) error { authorityId := middleware.GetAuthorityID(ctx) menus, err := s.GetMenuList(ctx, authorityId) if err != nil { return errors.InternalServer("GET_MENU_FAILED", err.Error()) } return ctx.Result(200, map[string]any{"code": 0, "msg": "获取成功", "data": menus}) } func (s *MenuService) handleAddBaseMenu(ctx http.Context) error { var req BaseMenuRequest if err := ctx.Bind(&req); err != nil { return err } if err := s.AddBaseMenu(ctx, &req); err != nil { return errors.BadRequest("ADD_MENU_FAILED", err.Error()) } return ctx.Result(200, map[string]any{"code": 0, "msg": "添加成功"}) } func (s *MenuService) handleUpdateBaseMenu(ctx http.Context) error { var req BaseMenuRequest if err := ctx.Bind(&req); err != nil { return err } if err := s.UpdateBaseMenu(ctx, &req); err != nil { return errors.BadRequest("UPDATE_MENU_FAILED", err.Error()) } return ctx.Result(200, map[string]any{"code": 0, "msg": "更新成功"}) } func (s *MenuService) handleDeleteBaseMenu(ctx http.Context) error { var req struct { ID uint `json:"ID"` } if err := ctx.Bind(&req); err != nil { return err } if err := s.DeleteBaseMenu(ctx, req.ID); err != nil { return errors.BadRequest("DELETE_MENU_FAILED", err.Error()) } return ctx.Result(200, map[string]any{"code": 0, "msg": "删除成功"}) } func (s *MenuService) handleGetBaseMenuById(ctx http.Context) error { var req struct { ID uint `json:"ID"` } if err := ctx.Bind(&req); err != nil { return err } menu, err := s.GetBaseMenuById(ctx, req.ID) if err != nil { return errors.NotFound("MENU_NOT_FOUND", err.Error()) } return ctx.Result(200, map[string]any{"code": 0, "msg": "获取成功", "data": map[string]any{"menu": menu}}) } func (s *MenuService) handleAddMenuAuthority(ctx http.Context) error { var req AddMenuAuthorityRequest if err := ctx.Bind(&req); err != nil { return err } adminAuthorityID := middleware.GetAuthorityID(ctx) if err := s.AddMenuAuthority(ctx, adminAuthorityID, &req); err != nil { return errors.BadRequest("ADD_AUTHORITY_FAILED", err.Error()) } return ctx.Result(200, map[string]any{"code": 0, "msg": "添加成功"}) } func (s *MenuService) handleGetMenuAuthority(ctx http.Context) error { var req struct { AuthorityId uint `json:"authorityId"` } if err := ctx.Bind(&req); err != nil { return err } menus, err := s.GetMenuAuthority(ctx, req.AuthorityId) if err != nil { return errors.InternalServer("GET_AUTHORITY_FAILED", err.Error()) } return ctx.Result(200, map[string]any{"code": 0, "msg": "获取成功", "data": map[string]any{"menus": menus}}) }