service.xpcool.com/internal/service/admin/system/menu/menu.go
夏犀麟 6e3ef67709 refactor(service): 重构服务层结构并更新导入路径
- 将 admin 相关服务移动到 internal/service/admin 目录下
- 更新控制器中的服务导入路径引用
- 移除已合并的服务文件
- 添加统一工作约定文档
- 更新 API 接口定义的包路径
2026-08-26 15:40:13 +08:00

91 lines
2.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package menu
import (
"context"
"sort"
"strings"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/text/gstr"
"service.xpcool.com/internal/dao"
"service.xpcool.com/internal/model/dto"
"service.xpcool.com/internal/model/entity"
)
type IAdminMenu interface {
// Routes returns the visible menu tree of an admin as vben route items.
Routes(context.Context, uint64) ([]*dto.RouteItem, error)
}
type adminMenu struct{}
func NewAdminMenu() IAdminMenu { return &adminMenu{} }
var localAdminMenu IAdminMenu
func AdminMenu() IAdminMenu {
if localAdminMenu == nil {
panic("AdminMenu implementation not registered")
}
return localAdminMenu
}
func RegisterAdminMenu(i IAdminMenu) { localAdminMenu = i }
// routeName converts a permission code like "system:admin" to a unique
// vben route name, e.g. "SystemAdmin".
func routeName(permission string) string {
if permission == "" {
return ""
}
return gstr.CaseCamel(strings.ReplaceAll(permission, ":", "_"))
}
func (s *adminMenu) Routes(ctx context.Context, adminID uint64) ([]*dto.RouteItem, error) {
// 当前管理员所有启用角色可见的菜单type=1含按钮行但不作为路由节点。
var list []entity.AdminMenu
if err := dao.AdminUserRole.Ctx(ctx).As("ur").
LeftJoin("admin_role_menu rm", "ur.role_id=rm.role_id").
LeftJoin("admin_menu m", "rm.menu_id=m.id").
Where("ur.admin_user_id", adminID).
Where("m.type", 1).
Where("m.status", 1).
Where("m.deleted_at IS NULL").
Fields("m.*").
Scan(&list); err != nil {
return nil, gerror.Wrap(err, "query admin menu routes")
}
byID := make(map[uint64]*dto.RouteItem, len(list))
for i := range list {
m := &list[i]
byID[m.Id] = &dto.RouteItem{
Name: routeName(m.Permission),
Path: m.Path,
Component: m.Component,
Meta: dto.RouteMeta{Title: m.Name, Icon: m.Icon, Order: m.Sort, HideInMenu: m.Hidden},
}
}
var roots []*dto.RouteItem
for i := range list {
m := &list[i]
item := byID[m.Id]
if m.ParentId == 0 {
roots = append(roots, item)
} else if p, ok := byID[m.ParentId]; ok {
p.Children = append(p.Children, item)
}
}
sort.Slice(roots, func(i, j int) bool { return roots[i].Meta.Order < roots[j].Meta.Order })
for _, r := range roots {
sortRouteChildren(r)
}
return roots, nil
}
func sortRouteChildren(r *dto.RouteItem) {
sort.Slice(r.Children, func(i, j int) bool { return r.Children[i].Meta.Order < r.Children[j].Meta.Order })
for _, c := range r.Children {
sortRouteChildren(c)
}
}