251 lines
6.2 KiB
Go
251 lines
6.2 KiB
Go
package admin_menu
|
||
|
||
import (
|
||
"context"
|
||
"sort"
|
||
"strconv"
|
||
|
||
"tyc-server/app/main/api/internal/svc"
|
||
"tyc-server/app/main/api/internal/types"
|
||
"tyc-server/common/ctxdata"
|
||
"tyc-server/common/xerr"
|
||
|
||
"github.com/Masterminds/squirrel"
|
||
"github.com/bytedance/sonic"
|
||
"github.com/pkg/errors"
|
||
"github.com/samber/lo"
|
||
"github.com/zeromicro/go-zero/core/logx"
|
||
"github.com/zeromicro/go-zero/core/mr"
|
||
)
|
||
|
||
type GetMenuAllLogic struct {
|
||
logx.Logger
|
||
ctx context.Context
|
||
svcCtx *svc.ServiceContext
|
||
}
|
||
|
||
func NewGetMenuAllLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetMenuAllLogic {
|
||
return &GetMenuAllLogic{
|
||
Logger: logx.WithContext(ctx),
|
||
ctx: ctx,
|
||
svcCtx: svcCtx,
|
||
}
|
||
}
|
||
|
||
func (l *GetMenuAllLogic) GetMenuAll(req *types.GetMenuAllReq) (resp *[]types.GetMenuAllResp, err error) {
|
||
userId, err := ctxdata.GetUidFromCtx(l.ctx)
|
||
if err != nil {
|
||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取用户ID失败, %+v", err)
|
||
}
|
||
|
||
// 使用MapReduceVoid并发获取用户角色
|
||
var roleIds []int64
|
||
var permissions []*struct {
|
||
RoleId int64
|
||
}
|
||
|
||
type UserRoleResult struct {
|
||
RoleId int64
|
||
}
|
||
|
||
err = mr.MapReduceVoid(
|
||
func(source chan<- interface{}) {
|
||
adminUserRoleBuilder := l.svcCtx.AdminUserRoleModel.SelectBuilder().Where(squirrel.Eq{"user_id": userId})
|
||
source <- adminUserRoleBuilder
|
||
},
|
||
func(item interface{}, writer mr.Writer[*UserRoleResult], cancel func(error)) {
|
||
builder := item.(squirrel.SelectBuilder)
|
||
result, err := l.svcCtx.AdminUserRoleModel.FindAll(l.ctx, builder, "role_id DESC")
|
||
if err != nil {
|
||
cancel(errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取用户角色信息失败, %+v", err))
|
||
return
|
||
}
|
||
|
||
for _, r := range result {
|
||
writer.Write(&UserRoleResult{RoleId: r.RoleId})
|
||
}
|
||
},
|
||
func(pipe <-chan *UserRoleResult, cancel func(error)) {
|
||
for item := range pipe {
|
||
permissions = append(permissions, &struct{ RoleId int64 }{RoleId: item.RoleId})
|
||
}
|
||
},
|
||
)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
for _, permission := range permissions {
|
||
roleIds = append(roleIds, permission.RoleId)
|
||
}
|
||
|
||
// 使用MapReduceVoid并发获取角色菜单
|
||
var menuIds []int64
|
||
var roleMenus []*struct {
|
||
MenuId int64
|
||
}
|
||
|
||
type RoleMenuResult struct {
|
||
MenuId int64
|
||
}
|
||
|
||
err = mr.MapReduceVoid(
|
||
func(source chan<- interface{}) {
|
||
getRoleMenuBuilder := l.svcCtx.AdminRoleMenuModel.SelectBuilder().Where(squirrel.Eq{"role_id": roleIds})
|
||
source <- getRoleMenuBuilder
|
||
},
|
||
func(item interface{}, writer mr.Writer[*RoleMenuResult], cancel func(error)) {
|
||
builder := item.(squirrel.SelectBuilder)
|
||
result, err := l.svcCtx.AdminRoleMenuModel.FindAll(l.ctx, builder, "id DESC")
|
||
if err != nil {
|
||
cancel(errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取角色菜单信息失败, %+v", err))
|
||
return
|
||
}
|
||
|
||
for _, r := range result {
|
||
writer.Write(&RoleMenuResult{MenuId: r.MenuId})
|
||
}
|
||
},
|
||
func(pipe <-chan *RoleMenuResult, cancel func(error)) {
|
||
for item := range pipe {
|
||
roleMenus = append(roleMenus, &struct{ MenuId int64 }{MenuId: item.MenuId})
|
||
}
|
||
},
|
||
)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
for _, roleMenu := range roleMenus {
|
||
menuIds = append(menuIds, roleMenu.MenuId)
|
||
}
|
||
|
||
// 使用MapReduceVoid并发获取菜单
|
||
type AdminMenuStruct struct {
|
||
Id int64
|
||
Pid int64
|
||
Name string
|
||
Path string
|
||
Component string
|
||
Redirect struct {
|
||
String string
|
||
Valid bool
|
||
}
|
||
Meta string
|
||
Sort int64
|
||
Type int64
|
||
Status int64
|
||
}
|
||
|
||
var menus []*AdminMenuStruct
|
||
|
||
err = mr.MapReduceVoid(
|
||
func(source chan<- interface{}) {
|
||
adminMenuBuilder := l.svcCtx.AdminMenuModel.SelectBuilder().Where(squirrel.Eq{"id": menuIds})
|
||
source <- adminMenuBuilder
|
||
},
|
||
func(item interface{}, writer mr.Writer[*AdminMenuStruct], cancel func(error)) {
|
||
builder := item.(squirrel.SelectBuilder)
|
||
result, err := l.svcCtx.AdminMenuModel.FindAll(l.ctx, builder, "sort ASC")
|
||
if err != nil {
|
||
cancel(errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取菜单信息失败, %+v", err))
|
||
return
|
||
}
|
||
|
||
for _, r := range result {
|
||
menu := &AdminMenuStruct{
|
||
Id: r.Id,
|
||
Pid: r.Pid,
|
||
Name: r.Name,
|
||
Path: r.Path,
|
||
Component: r.Component,
|
||
Redirect: r.Redirect,
|
||
Meta: r.Meta,
|
||
Sort: r.Sort,
|
||
Type: r.Type,
|
||
Status: r.Status,
|
||
}
|
||
writer.Write(menu)
|
||
}
|
||
},
|
||
func(pipe <-chan *AdminMenuStruct, cancel func(error)) {
|
||
for item := range pipe {
|
||
menus = append(menus, item)
|
||
}
|
||
},
|
||
)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 转换为types.Menu结构并存储到映射表
|
||
menuMap := make(map[string]types.GetMenuAllResp)
|
||
for _, menu := range menus {
|
||
// 只处理状态正常的菜单
|
||
if menu.Status != 1 {
|
||
continue
|
||
}
|
||
|
||
meta := make(map[string]interface{})
|
||
err = sonic.Unmarshal([]byte(menu.Meta), &meta)
|
||
if err != nil {
|
||
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "解析菜单Meta信息失败, %+v", err)
|
||
}
|
||
|
||
redirect := func() string {
|
||
if menu.Redirect.Valid {
|
||
return menu.Redirect.String
|
||
}
|
||
return ""
|
||
}()
|
||
|
||
menuId := strconv.FormatInt(menu.Id, 10)
|
||
menuMap[menuId] = types.GetMenuAllResp{
|
||
Name: menu.Name,
|
||
Path: menu.Path,
|
||
Redirect: redirect,
|
||
Component: menu.Component,
|
||
Sort: menu.Sort,
|
||
Meta: meta,
|
||
Children: make([]types.GetMenuAllResp, 0),
|
||
}
|
||
}
|
||
|
||
// 按ParentId将菜单分组
|
||
menuGroups := lo.GroupBy(menus, func(item *AdminMenuStruct) int64 {
|
||
return item.Pid
|
||
})
|
||
|
||
// 递归构建菜单树
|
||
var buildMenuTree func(parentId int64) []types.GetMenuAllResp
|
||
buildMenuTree = func(parentId int64) []types.GetMenuAllResp {
|
||
children := make([]types.GetMenuAllResp, 0)
|
||
|
||
childMenus, ok := menuGroups[parentId]
|
||
if !ok {
|
||
return children
|
||
}
|
||
|
||
// 按Sort排序
|
||
sort.Slice(childMenus, func(i, j int) bool {
|
||
return childMenus[i].Sort < childMenus[j].Sort
|
||
})
|
||
|
||
for _, childMenu := range childMenus {
|
||
menuId := strconv.FormatInt(childMenu.Id, 10)
|
||
if menu, exists := menuMap[menuId]; exists && childMenu.Status == 1 {
|
||
// 递归构建子菜单
|
||
menu.Children = buildMenuTree(childMenu.Id)
|
||
children = append(children, menu)
|
||
}
|
||
}
|
||
|
||
return children
|
||
}
|
||
|
||
// 从根菜单开始构建(ParentId为0的是根菜单)
|
||
menuTree := buildMenuTree(0)
|
||
|
||
return &menuTree, nil
|
||
}
|