package user import ( "context" "fmt" "sort" "sundynix-micro-go/app/auth/api/internal/svc" sysPb "sundynix-micro-go/app/system/rpc/system" "github.com/zeromicro/go-zero/core/logx" ) type GetUserInfoLogic struct { logx.Logger ctx context.Context svcCtx *svc.ServiceContext } func NewGetUserInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetUserInfoLogic { return &GetUserInfoLogic{Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx} } func (l *GetUserInfoLogic) GetUserInfo() (resp interface{}, err error) { // 1. 从 JWT claims 中获取 userId userId := fmt.Sprintf("%v", l.ctx.Value("userId")) if userId == "" || userId == "" { return nil, fmt.Errorf("用户未登录") } // 2. 调用 system-rpc 获取用户基础信息 userResp, err := l.svcCtx.SystemRpc.GetUserById(l.ctx, &sysPb.GetUserByIdReq{Id: userId}) if err != nil { l.Errorf("[GetUserInfo] ❌ 获取用户信息失败 | userId=%s | err=%v", userId, err) return nil, fmt.Errorf("获取用户信息失败") } // 3. 获取用户角色列表 rolesResp, err := l.svcCtx.SystemRpc.GetRolesByUserId(l.ctx, &sysPb.GetRolesByUserIdReq{UserId: userId}) if err != nil { l.Errorf("[GetUserInfo] ⚠️ 获取用户角色失败(已降级返回空角色) | userId=%s | err=%v", userId, err) rolesResp = &sysPb.GetRolesByUserIdResp{Roles: []*sysPb.RoleInfo{}} } // 4. 根据角色获取菜单权限(合并所有角色的菜单) menuMap := make(map[string]interface{}) var allMenus []interface{} var roleCodes []string for _, role := range rolesResp.Roles { roleCodes = append(roleCodes, role.Code) menusResp, err := l.svcCtx.SystemRpc.GetMenusByRoleId(l.ctx, &sysPb.GetMenusByRoleIdReq{RoleId: role.Id}) if err != nil { l.Errorf("获取角色[%s]菜单失败: %v", role.Name, err) continue } for _, m := range menusResp.Menus { if _, exists := menuMap[m.Id]; !exists { menuMap[m.Id] = true allMenus = append(allMenus, convertMenuInfo(m)) } } } // 5. 对顶层菜单进行重新排序,防止不同角色的合并打乱顺序 sort.Slice(allMenus, func(i, j int) bool { m1 := allMenus[i].(map[string]interface{}) m2 := allMenus[j].(map[string]interface{}) s1 := m1["sort"].(int32) s2 := m2["sort"].(int32) return s1 < s2 }) // 5. 组装完整的用户信息返回 u := userResp.User return map[string]interface{}{ "id": u.Id, "name": u.Name, "account": u.Account, "nickName": u.NickName, "phone": u.Phone, "avatarId": u.AvatarId, "gender": u.Gender, "roles": roleCodes, "menus": allMenus, "createdAt": u.CreatedAt, }, nil } // convertMenuInfo 将proto MenuInfo转为map func convertMenuInfo(m *sysPb.MenuInfo) map[string]interface{} { menu := map[string]interface{}{ "id": m.Id, "parentId": m.ParentId, "category": m.Category, "name": m.Name, "title": m.Title, "code": m.Code, "path": m.Path, "permission": m.Permission, "locale": m.Locale, "icon": m.Icon, "sort": m.Sort, } if len(m.Children) > 0 { var children []map[string]interface{} for _, child := range m.Children { children = append(children, convertMenuInfo(child)) } menu["children"] = children } return menu }