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
 | ||
| }
 |