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

132 lines
4.2 KiB
Go

package menu_manage
import (
"context"
"sort"
"github.com/gogf/gf/v2/errors/gerror"
"service.xpcool.com/internal/consts"
"service.xpcool.com/internal/dao"
"service.xpcool.com/internal/library/response"
"service.xpcool.com/internal/model/do"
"service.xpcool.com/internal/model/dto"
"service.xpcool.com/internal/model/entity"
)
// IMenuManage 管理菜单树(菜单 + 按钮权限)。
type IMenuManage interface {
Tree(context.Context) ([]*dto.MenuNode, error)
Create(context.Context, dto.MenuCreateInput) (uint64, error)
Update(context.Context, dto.MenuUpdateInput) error
Delete(context.Context, uint64) error
}
type menuManage struct{}
var localMenuManage IMenuManage
func NewMenuManage() IMenuManage { return &menuManage{} }
func MenuManage() IMenuManage {
if localMenuManage == nil {
panic("MenuManage implementation not registered")
}
return localMenuManage
}
func RegisterMenuManage(i IMenuManage) { localMenuManage = i }
// ---------------------- Menu manage ----------------------
func (s *menuManage) Tree(ctx context.Context) ([]*dto.MenuNode, error) {
var list []entity.AdminMenu
if err := dao.AdminMenu.Ctx(ctx).OrderAsc("sort").Scan(&list); err != nil {
return nil, gerror.Wrap(err, "query menus")
}
byID := make(map[uint64]*dto.MenuNode, len(list))
for i := range list {
m := &list[i]
byID[m.Id] = &dto.MenuNode{
Id: m.Id, ParentId: m.ParentId, Name: m.Name, Icon: m.Icon, Type: m.Type,
Path: m.Path, Component: m.Component, Permission: m.Permission,
Sort: m.Sort, Status: m.Status, Hidden: m.Hidden,
}
}
var roots []*dto.MenuNode
for i := range list {
m := &list[i]
node := byID[m.Id]
if m.ParentId == 0 {
roots = append(roots, node)
} else if p, ok := byID[m.ParentId]; ok {
p.Children = append(p.Children, node)
}
}
sort.Slice(roots, func(i, j int) bool { return roots[i].Sort < roots[j].Sort })
for _, r := range roots {
sortMenuChildren(r)
}
return roots, nil
}
func sortMenuChildren(n *dto.MenuNode) {
sort.Slice(n.Children, func(i, j int) bool { return n.Children[i].Sort < n.Children[j].Sort })
for _, c := range n.Children {
sortMenuChildren(c)
}
}
func (s *menuManage) Create(ctx context.Context, in dto.MenuCreateInput) (uint64, error) {
count, err := dao.AdminMenu.Ctx(ctx).Where(do.AdminMenu{Permission: in.Permission}).Count()
if err != nil {
return 0, gerror.Wrap(err, "check menu permission")
}
if count > 0 {
return 0, response.Error(consts.CodeInvalidParam, "permission already exists")
}
id, err := dao.AdminMenu.Ctx(ctx).Data(do.AdminMenu{
ParentId: in.ParentId, Name: in.Name, Icon: in.Icon, Type: in.Type, Path: in.Path,
Component: in.Component, Permission: in.Permission, Sort: in.Sort, Status: in.Status, Hidden: in.Hidden,
}).InsertAndGetId()
if err != nil {
return 0, gerror.Wrap(err, "insert menu")
}
return uint64(id), nil
}
func (s *menuManage) Update(ctx context.Context, in dto.MenuUpdateInput) error {
count, err := dao.AdminMenu.Ctx(ctx).Where("permission = ? AND id != ?", in.Permission, in.Id).Count()
if err != nil {
return gerror.Wrap(err, "check menu permission")
}
if count > 0 {
return response.Error(consts.CodeInvalidParam, "permission already exists")
}
_, err = dao.AdminMenu.Ctx(ctx).Where(do.AdminMenu{Id: in.Id}).Data(do.AdminMenu{
ParentId: in.ParentId, Name: in.Name, Icon: in.Icon, Type: in.Type, Path: in.Path,
Component: in.Component, Permission: in.Permission, Sort: in.Sort, Status: in.Status, Hidden: in.Hidden,
}).Update()
if err != nil {
return gerror.Wrap(err, "update menu")
}
return nil
}
func (s *menuManage) Delete(ctx context.Context, id uint64) error {
// 删除前检查是否存在子节点。
cnt, err := dao.AdminMenu.Ctx(ctx).Where(do.AdminMenu{ParentId: id}).Count()
if err != nil {
return gerror.Wrap(err, "check menu children")
}
if cnt > 0 {
return response.Error(consts.CodeInvalidParam, "delete children first")
}
if _, err = dao.AdminMenu.Ctx(ctx).Where(do.AdminMenu{Id: id}).Delete(); err != nil {
return gerror.Wrap(err, "delete menu")
}
if _, err = dao.AdminRoleMenu.Ctx(ctx).Unscoped().Where(do.AdminRoleMenu{MenuId: id}).Delete(); err != nil {
return gerror.Wrap(err, "delete role menu bindings")
}
return nil
}