package dto import ( "carrot_bbs/internal/model" "carrot_bbs/internal/pkg/utils" "context" "encoding/json" "strconv" ) // ==================== User 转换 ==================== // getAvatarOrDefault 获取头像URL,如果为空则返回在线头像生成服务的URL func getAvatarOrDefault(user *model.User) string { return utils.GetAvatarOrDefault(user.Username, user.Nickname, user.Avatar) } // ConvertUserToResponse 将User转换为UserResponse func ConvertUserToResponse(user *model.User) *UserResponse { if user == nil { return nil } return &UserResponse{ ID: user.ID, Username: user.Username, Nickname: user.Nickname, Email: user.Email, Phone: user.Phone, EmailVerified: user.EmailVerified, Avatar: getAvatarOrDefault(user), CoverURL: user.CoverURL, Bio: user.Bio, Website: user.Website, Location: user.Location, PostsCount: user.PostsCount, FollowersCount: user.FollowersCount, FollowingCount: user.FollowingCount, CreatedAt: FormatTime(user.CreatedAt), } } // ConvertUserToResponseWithFollowing 将User转换为UserResponse(包含关注状态) func ConvertUserToResponseWithFollowing(user *model.User, isFollowing bool) *UserResponse { if user == nil { return nil } return &UserResponse{ ID: user.ID, Username: user.Username, Nickname: user.Nickname, Email: user.Email, Phone: user.Phone, EmailVerified: user.EmailVerified, Avatar: getAvatarOrDefault(user), CoverURL: user.CoverURL, Bio: user.Bio, Website: user.Website, Location: user.Location, PostsCount: user.PostsCount, FollowersCount: user.FollowersCount, FollowingCount: user.FollowingCount, IsFollowing: isFollowing, IsFollowingMe: false, // 默认false,需要单独计算 CreatedAt: FormatTime(user.CreatedAt), } } // ConvertUserToResponseWithPostsCount 将User转换为UserResponse(使用实时计算的帖子数量) func ConvertUserToResponseWithPostsCount(user *model.User, postsCount int) *UserResponse { if user == nil { return nil } return &UserResponse{ ID: user.ID, Username: user.Username, Nickname: user.Nickname, Email: user.Email, Phone: user.Phone, EmailVerified: user.EmailVerified, Avatar: getAvatarOrDefault(user), CoverURL: user.CoverURL, Bio: user.Bio, Website: user.Website, Location: user.Location, PostsCount: postsCount, FollowersCount: user.FollowersCount, FollowingCount: user.FollowingCount, CreatedAt: FormatTime(user.CreatedAt), } } // ConvertUserToResponseWithMutualFollow 将User转换为UserResponse(包含双向关注状态) func ConvertUserToResponseWithMutualFollow(user *model.User, isFollowing, isFollowingMe bool) *UserResponse { if user == nil { return nil } return &UserResponse{ ID: user.ID, Username: user.Username, Nickname: user.Nickname, Email: user.Email, Phone: user.Phone, EmailVerified: user.EmailVerified, Avatar: getAvatarOrDefault(user), CoverURL: user.CoverURL, Bio: user.Bio, Website: user.Website, Location: user.Location, PostsCount: user.PostsCount, FollowersCount: user.FollowersCount, FollowingCount: user.FollowingCount, IsFollowing: isFollowing, IsFollowingMe: isFollowingMe, CreatedAt: FormatTime(user.CreatedAt), } } // ConvertUserToResponseWithMutualFollowAndPostsCount 将User转换为UserResponse(包含双向关注状态和实时计算的帖子数量) func ConvertUserToResponseWithMutualFollowAndPostsCount(user *model.User, isFollowing, isFollowingMe bool, postsCount int) *UserResponse { if user == nil { return nil } return &UserResponse{ ID: user.ID, Username: user.Username, Nickname: user.Nickname, Email: user.Email, Phone: user.Phone, EmailVerified: user.EmailVerified, Avatar: getAvatarOrDefault(user), CoverURL: user.CoverURL, Bio: user.Bio, Website: user.Website, Location: user.Location, PostsCount: postsCount, FollowersCount: user.FollowersCount, FollowingCount: user.FollowingCount, IsFollowing: isFollowing, IsFollowingMe: isFollowingMe, CreatedAt: FormatTime(user.CreatedAt), } } // ConvertUserToDetailResponse 将User转换为UserDetailResponse func ConvertUserToDetailResponse(user *model.User) *UserDetailResponse { if user == nil { return nil } return &UserDetailResponse{ ID: user.ID, Username: user.Username, Nickname: user.Nickname, Email: user.Email, EmailVerified: user.EmailVerified, Avatar: getAvatarOrDefault(user), CoverURL: user.CoverURL, Bio: user.Bio, Website: user.Website, Location: user.Location, PostsCount: user.PostsCount, FollowersCount: user.FollowersCount, FollowingCount: user.FollowingCount, IsVerified: user.IsVerified, CreatedAt: FormatTime(user.CreatedAt), } } // ConvertUserToDetailResponseWithPostsCount 将User转换为UserDetailResponse(使用实时计算的帖子数量) func ConvertUserToDetailResponseWithPostsCount(user *model.User, postsCount int) *UserDetailResponse { if user == nil { return nil } return &UserDetailResponse{ ID: user.ID, Username: user.Username, Nickname: user.Nickname, Email: user.Email, EmailVerified: user.EmailVerified, Phone: user.Phone, // 仅当前用户自己可见 Avatar: getAvatarOrDefault(user), CoverURL: user.CoverURL, Bio: user.Bio, Website: user.Website, Location: user.Location, PostsCount: postsCount, FollowersCount: user.FollowersCount, FollowingCount: user.FollowingCount, IsVerified: user.IsVerified, CreatedAt: FormatTime(user.CreatedAt), } } // ConvertUsersToResponse 将User列表转换为响应列表 func ConvertUsersToResponse(users []*model.User) []*UserResponse { result := make([]*UserResponse, 0, len(users)) for _, user := range users { result = append(result, ConvertUserToResponse(user)) } return result } // ConvertUsersToResponseWithMutualFollow 将User列表转换为响应列表(包含双向关注状态) // followingStatusMap: key是用户ID,value是[isFollowing, isFollowingMe] func ConvertUsersToResponseWithMutualFollow(users []*model.User, followingStatusMap map[string][2]bool) []*UserResponse { result := make([]*UserResponse, 0, len(users)) for _, user := range users { status, ok := followingStatusMap[user.ID] if ok { result = append(result, ConvertUserToResponseWithMutualFollow(user, status[0], status[1])) } else { result = append(result, ConvertUserToResponse(user)) } } return result } // ConvertUsersToResponseWithMutualFollowAndPostsCount 将User列表转换为响应列表(包含双向关注状态和实时计算的帖子数量) // followingStatusMap: key是用户ID,value是[isFollowing, isFollowingMe] // postsCountMap: key是用户ID,value是帖子数量 func ConvertUsersToResponseWithMutualFollowAndPostsCount(users []*model.User, followingStatusMap map[string][2]bool, postsCountMap map[string]int64) []*UserResponse { result := make([]*UserResponse, 0, len(users)) for _, user := range users { status, hasStatus := followingStatusMap[user.ID] postsCount, hasPostsCount := postsCountMap[user.ID] // 如果没有帖子数量,使用数据库中的值 if !hasPostsCount { postsCount = int64(user.PostsCount) } if hasStatus { result = append(result, ConvertUserToResponseWithMutualFollowAndPostsCount(user, status[0], status[1], int(postsCount))) } else { result = append(result, ConvertUserToResponseWithPostsCount(user, int(postsCount))) } } return result } // ==================== Post 转换 ==================== // ConvertPostImageToResponse 将PostImage转换为PostImageResponse func ConvertPostImageToResponse(img *model.PostImage) PostImageResponse { if img == nil { return PostImageResponse{} } return PostImageResponse{ ID: img.ID, URL: img.URL, ThumbnailURL: img.ThumbnailURL, Width: img.Width, Height: img.Height, } } // ConvertPostImagesToResponse 将PostImage列表转换为响应列表 func ConvertPostImagesToResponse(images []model.PostImage) []PostImageResponse { result := make([]PostImageResponse, 0, len(images)) for i := range images { result = append(result, ConvertPostImageToResponse(&images[i])) } return result } // ConvertPostToResponse 将Post转换为PostResponse(列表用) func ConvertPostToResponse(post *model.Post, isLiked, isFavorited bool) *PostResponse { if post == nil { return nil } images := make([]PostImageResponse, 0) for _, img := range post.Images { images = append(images, ConvertPostImageToResponse(&img)) } var author *UserResponse if post.User != nil { author = ConvertUserToResponse(post.User) } return &PostResponse{ ID: post.ID, UserID: post.UserID, Title: post.Title, Content: post.Content, Images: images, Status: string(post.Status), LikesCount: post.LikesCount, CommentsCount: post.CommentsCount, FavoritesCount: post.FavoritesCount, SharesCount: post.SharesCount, ViewsCount: post.ViewsCount, IsPinned: post.IsPinned, IsLocked: post.IsLocked, IsVote: post.IsVote, CreatedAt: FormatTime(post.CreatedAt), UpdatedAt: FormatTime(post.UpdatedAt), Author: author, IsLiked: isLiked, IsFavorited: isFavorited, } } // ConvertPostToDetailResponse 将Post转换为PostDetailResponse func ConvertPostToDetailResponse(post *model.Post, isLiked, isFavorited bool) *PostDetailResponse { if post == nil { return nil } images := make([]PostImageResponse, 0) for _, img := range post.Images { images = append(images, ConvertPostImageToResponse(&img)) } var author *UserResponse if post.User != nil { author = ConvertUserToResponse(post.User) } return &PostDetailResponse{ ID: post.ID, UserID: post.UserID, Title: post.Title, Content: post.Content, Images: images, Status: string(post.Status), LikesCount: post.LikesCount, CommentsCount: post.CommentsCount, FavoritesCount: post.FavoritesCount, SharesCount: post.SharesCount, ViewsCount: post.ViewsCount, IsPinned: post.IsPinned, IsLocked: post.IsLocked, IsVote: post.IsVote, CreatedAt: FormatTime(post.CreatedAt), UpdatedAt: FormatTime(post.UpdatedAt), Author: author, IsLiked: isLiked, IsFavorited: isFavorited, } } // ConvertPostsToResponse 将Post列表转换为响应列表(每个帖子独立检查点赞/收藏状态) func ConvertPostsToResponse(posts []*model.Post, isLikedMap, isFavoritedMap map[string]bool) []*PostResponse { result := make([]*PostResponse, 0, len(posts)) for _, post := range posts { isLiked := false isFavorited := false if isLikedMap != nil { isLiked = isLikedMap[post.ID] } if isFavoritedMap != nil { isFavorited = isFavoritedMap[post.ID] } result = append(result, ConvertPostToResponse(post, isLiked, isFavorited)) } return result } // ==================== Comment 转换 ==================== // ConvertCommentToResponse 将Comment转换为CommentResponse func ConvertCommentToResponse(comment *model.Comment, isLiked bool) *CommentResponse { if comment == nil { return nil } var author *UserResponse if comment.User != nil { author = ConvertUserToResponse(comment.User) } // 转换子回复(扁平化结构) var replies []*CommentResponse if len(comment.Replies) > 0 { replies = make([]*CommentResponse, 0, len(comment.Replies)) for _, reply := range comment.Replies { replies = append(replies, ConvertCommentToResponse(reply, false)) } } // TargetID 就是 ParentID,前端根据这个 ID 找到被回复用户的昵称 var targetID *string if comment.ParentID != nil && *comment.ParentID != "" { targetID = comment.ParentID } // 解析图片JSON var images []CommentImageResponse if comment.Images != "" { var urlList []string if err := json.Unmarshal([]byte(comment.Images), &urlList); err == nil { images = make([]CommentImageResponse, 0, len(urlList)) for _, url := range urlList { images = append(images, CommentImageResponse{URL: url}) } } } return &CommentResponse{ ID: comment.ID, PostID: comment.PostID, UserID: comment.UserID, ParentID: comment.ParentID, RootID: comment.RootID, Content: comment.Content, Images: images, LikesCount: comment.LikesCount, RepliesCount: comment.RepliesCount, CreatedAt: FormatTime(comment.CreatedAt), Author: author, IsLiked: isLiked, TargetID: targetID, Replies: replies, } } // ConvertCommentsToResponse 将Comment列表转换为响应列表 func ConvertCommentsToResponse(comments []*model.Comment, isLiked bool) []*CommentResponse { result := make([]*CommentResponse, 0, len(comments)) for _, comment := range comments { result = append(result, ConvertCommentToResponse(comment, isLiked)) } return result } // IsLikedChecker 点赞状态检查器接口 type IsLikedChecker interface { IsLiked(ctx context.Context, commentID, userID string) bool } // ConvertCommentToResponseWithUser 将Comment转换为CommentResponse(根据用户ID检查点赞状态) func ConvertCommentToResponseWithUser(comment *model.Comment, userID string, checker IsLikedChecker) *CommentResponse { if comment == nil { return nil } // 检查当前用户是否点赞了该评论 isLiked := false if userID != "" && checker != nil { isLiked = checker.IsLiked(context.Background(), comment.ID, userID) } var author *UserResponse if comment.User != nil { author = ConvertUserToResponse(comment.User) } // 转换子回复(扁平化结构),递归检查点赞状态 var replies []*CommentResponse if len(comment.Replies) > 0 { replies = make([]*CommentResponse, 0, len(comment.Replies)) for _, reply := range comment.Replies { replies = append(replies, ConvertCommentToResponseWithUser(reply, userID, checker)) } } // TargetID 就是 ParentID,前端根据这个 ID 找到被回复用户的昵称 var targetID *string if comment.ParentID != nil && *comment.ParentID != "" { targetID = comment.ParentID } // 解析图片JSON var images []CommentImageResponse if comment.Images != "" { var urlList []string if err := json.Unmarshal([]byte(comment.Images), &urlList); err == nil { images = make([]CommentImageResponse, 0, len(urlList)) for _, url := range urlList { images = append(images, CommentImageResponse{URL: url}) } } } return &CommentResponse{ ID: comment.ID, PostID: comment.PostID, UserID: comment.UserID, ParentID: comment.ParentID, RootID: comment.RootID, Content: comment.Content, Images: images, LikesCount: comment.LikesCount, RepliesCount: comment.RepliesCount, CreatedAt: FormatTime(comment.CreatedAt), Author: author, IsLiked: isLiked, TargetID: targetID, Replies: replies, } } // ConvertCommentsToResponseWithUser 将Comment列表转换为响应列表(根据用户ID检查点赞状态) func ConvertCommentsToResponseWithUser(comments []*model.Comment, userID string, checker IsLikedChecker) []*CommentResponse { result := make([]*CommentResponse, 0, len(comments)) for _, comment := range comments { result = append(result, ConvertCommentToResponseWithUser(comment, userID, checker)) } return result } // ==================== Notification 转换 ==================== // ConvertNotificationToResponse 将Notification转换为NotificationResponse func ConvertNotificationToResponse(notification *model.Notification) *NotificationResponse { if notification == nil { return nil } return &NotificationResponse{ ID: notification.ID, UserID: notification.UserID, Type: string(notification.Type), Title: notification.Title, Content: notification.Content, Data: notification.Data, IsRead: notification.IsRead, CreatedAt: FormatTime(notification.CreatedAt), } } // ConvertNotificationsToResponse 将Notification列表转换为响应列表 func ConvertNotificationsToResponse(notifications []*model.Notification) []*NotificationResponse { result := make([]*NotificationResponse, 0, len(notifications)) for _, n := range notifications { result = append(result, ConvertNotificationToResponse(n)) } return result } // ==================== Message 转换 ==================== // ConvertMessageToResponse 将Message转换为MessageResponse func ConvertMessageToResponse(message *model.Message) *MessageResponse { if message == nil { return nil } // 直接使用 segments,不需要解析 segments := make(model.MessageSegments, len(message.Segments)) for i, seg := range message.Segments { segments[i] = model.MessageSegment{ Type: seg.Type, Data: seg.Data, } } return &MessageResponse{ ID: message.ID, ConversationID: message.ConversationID, SenderID: message.SenderID, Seq: message.Seq, Segments: segments, ReplyToID: message.ReplyToID, Status: string(message.Status), Category: string(message.Category), CreatedAt: FormatTime(message.CreatedAt), } } // ConvertConversationToResponse 将Conversation转换为ConversationResponse // participants: 会话参与者列表(用户信息) // unreadCount: 当前用户的未读消息数 // lastMessage: 最后一条消息 func ConvertConversationToResponse(conv *model.Conversation, participants []*model.User, unreadCount int, lastMessage *model.Message, isPinned bool) *ConversationResponse { if conv == nil { return nil } var participantResponses []*UserResponse for _, p := range participants { participantResponses = append(participantResponses, ConvertUserToResponse(p)) } // 转换群组信息 var groupResponse *GroupResponse if conv.Group != nil { groupResponse = GroupToResponse(conv.Group) } return &ConversationResponse{ ID: conv.ID, Type: string(conv.Type), IsPinned: isPinned, Group: groupResponse, LastSeq: conv.LastSeq, LastMessage: ConvertMessageToResponse(lastMessage), LastMessageAt: FormatTimePointer(conv.LastMsgTime), UnreadCount: unreadCount, Participants: participantResponses, CreatedAt: FormatTime(conv.CreatedAt), UpdatedAt: FormatTime(conv.UpdatedAt), } } // ConvertConversationToDetailResponse 将Conversation转换为ConversationDetailResponse func ConvertConversationToDetailResponse(conv *model.Conversation, participants []*model.User, unreadCount int64, lastMessage *model.Message, myLastReadSeq int64, otherLastReadSeq int64, isPinned bool) *ConversationDetailResponse { if conv == nil { return nil } var participantResponses []*UserResponse for _, p := range participants { participantResponses = append(participantResponses, ConvertUserToResponse(p)) } return &ConversationDetailResponse{ ID: conv.ID, Type: string(conv.Type), IsPinned: isPinned, LastSeq: conv.LastSeq, LastMessage: ConvertMessageToResponse(lastMessage), LastMessageAt: FormatTimePointer(conv.LastMsgTime), UnreadCount: unreadCount, Participants: participantResponses, MyLastReadSeq: myLastReadSeq, OtherLastReadSeq: otherLastReadSeq, CreatedAt: FormatTime(conv.CreatedAt), UpdatedAt: FormatTime(conv.UpdatedAt), } } // ConvertMessagesToResponse 将Message列表转换为响应列表 func ConvertMessagesToResponse(messages []*model.Message) []*MessageResponse { result := make([]*MessageResponse, 0, len(messages)) for _, msg := range messages { result = append(result, ConvertMessageToResponse(msg)) } return result } // ConvertConversationsToResponse 将Conversation列表转换为响应列表 func ConvertConversationsToResponse(convs []*model.Conversation) []*ConversationResponse { result := make([]*ConversationResponse, 0, len(convs)) for _, conv := range convs { result = append(result, ConvertConversationToResponse(conv, nil, 0, nil, false)) } return result } // ==================== PushRecord 转换 ==================== // PushRecordToResponse 将PushRecord转换为PushRecordResponse func PushRecordToResponse(record *model.PushRecord) *PushRecordResponse { if record == nil { return nil } resp := &PushRecordResponse{ ID: record.ID, MessageID: record.MessageID, PushChannel: string(record.PushChannel), PushStatus: string(record.PushStatus), RetryCount: record.RetryCount, CreatedAt: record.CreatedAt, } if record.PushedAt != nil { resp.PushedAt = *record.PushedAt } if record.DeliveredAt != nil { resp.DeliveredAt = *record.DeliveredAt } return resp } // PushRecordsToResponse 将PushRecord列表转换为响应列表 func PushRecordsToResponse(records []*model.PushRecord) []*PushRecordResponse { result := make([]*PushRecordResponse, 0, len(records)) for _, record := range records { result = append(result, PushRecordToResponse(record)) } return result } // ==================== DeviceToken 转换 ==================== // DeviceTokenToResponse 将DeviceToken转换为DeviceTokenResponse func DeviceTokenToResponse(token *model.DeviceToken) *DeviceTokenResponse { if token == nil { return nil } resp := &DeviceTokenResponse{ ID: token.ID, DeviceID: token.DeviceID, DeviceType: string(token.DeviceType), IsActive: token.IsActive, DeviceName: token.DeviceName, CreatedAt: token.CreatedAt, } if token.LastUsedAt != nil { resp.LastUsedAt = *token.LastUsedAt } return resp } // DeviceTokensToResponse 将DeviceToken列表转换为响应列表 func DeviceTokensToResponse(tokens []*model.DeviceToken) []*DeviceTokenResponse { result := make([]*DeviceTokenResponse, 0, len(tokens)) for _, token := range tokens { result = append(result, DeviceTokenToResponse(token)) } return result } // ==================== SystemMessage 转换 ==================== // SystemMessageToResponse 将Message转换为SystemMessageResponse func SystemMessageToResponse(msg *model.Message) *SystemMessageResponse { if msg == nil { return nil } // 从 segments 中提取文本内容 content := ExtractTextContentFromModel(msg.Segments) resp := &SystemMessageResponse{ ID: msg.ID, SenderID: msg.SenderID, ReceiverID: "", // 系统消息的接收者需要从上下文获取 Content: content, Category: string(msg.Category), SystemType: string(msg.SystemType), CreatedAt: msg.CreatedAt, } if msg.ExtraData != nil { resp.ExtraData = map[string]interface{}{ "actor_id": msg.ExtraData.ActorID, "actor_name": msg.ExtraData.ActorName, "avatar_url": msg.ExtraData.AvatarURL, "target_id": msg.ExtraData.TargetID, "target_type": msg.ExtraData.TargetType, "action_url": msg.ExtraData.ActionURL, "action_time": msg.ExtraData.ActionTime, } } return resp } // SystemMessagesToResponse 将Message列表转换为SystemMessageResponse列表 func SystemMessagesToResponse(messages []*model.Message) []*SystemMessageResponse { result := make([]*SystemMessageResponse, 0, len(messages)) for _, msg := range messages { result = append(result, SystemMessageToResponse(msg)) } return result } // SystemNotificationToResponse 将SystemNotification转换为SystemMessageResponse func SystemNotificationToResponse(n *model.SystemNotification) *SystemMessageResponse { if n == nil { return nil } resp := &SystemMessageResponse{ ID: strconv.FormatInt(n.ID, 10), SenderID: model.SystemSenderIDStr, // 系统发送者 ReceiverID: n.ReceiverID, Content: n.Content, Category: "notification", SystemType: string(n.Type), IsRead: n.IsRead, CreatedAt: n.CreatedAt, } if n.ExtraData != nil { resp.ExtraData = map[string]interface{}{ "actor_id": n.ExtraData.ActorID, "actor_id_str": n.ExtraData.ActorIDStr, "actor_name": n.ExtraData.ActorName, "avatar_url": n.ExtraData.AvatarURL, "target_id": n.ExtraData.TargetID, "target_title": n.ExtraData.TargetTitle, "target_type": n.ExtraData.TargetType, "action_url": n.ExtraData.ActionURL, "action_time": n.ExtraData.ActionTime, "group_id": n.ExtraData.GroupID, "group_name": n.ExtraData.GroupName, "group_avatar": n.ExtraData.GroupAvatar, "group_description": n.ExtraData.GroupDescription, "flag": n.ExtraData.Flag, "request_type": n.ExtraData.RequestType, "request_status": n.ExtraData.RequestStatus, "reason": n.ExtraData.Reason, "target_user_id": n.ExtraData.TargetUserID, "target_user_name": n.ExtraData.TargetUserName, "target_user_avatar": n.ExtraData.TargetUserAvatar, } } return resp } // SystemNotificationsToResponse 将SystemNotification列表转换为SystemMessageResponse列表 func SystemNotificationsToResponse(notifications []*model.SystemNotification) []*SystemMessageResponse { result := make([]*SystemMessageResponse, 0, len(notifications)) for _, n := range notifications { result = append(result, SystemNotificationToResponse(n)) } return result } // ==================== Group 转换 ==================== // GroupToResponse 将Group转换为GroupResponse func GroupToResponse(group *model.Group) *GroupResponse { if group == nil { return nil } return &GroupResponse{ ID: group.ID, Name: group.Name, Avatar: group.Avatar, Description: group.Description, OwnerID: group.OwnerID, MemberCount: group.MemberCount, MaxMembers: group.MaxMembers, JoinType: int(group.JoinType), MuteAll: group.MuteAll, CreatedAt: FormatTime(group.CreatedAt), } } // GroupsToResponse 将Group列表转换为GroupResponse列表 func GroupsToResponse(groups []model.Group) []*GroupResponse { result := make([]*GroupResponse, 0, len(groups)) for i := range groups { result = append(result, GroupToResponse(&groups[i])) } return result } // GroupMemberToResponse 将GroupMember转换为GroupMemberResponse func GroupMemberToResponse(member *model.GroupMember) *GroupMemberResponse { if member == nil { return nil } return &GroupMemberResponse{ ID: member.ID, GroupID: member.GroupID, UserID: member.UserID, Role: member.Role, Nickname: member.Nickname, Muted: member.Muted, JoinTime: FormatTime(member.JoinTime), } } // GroupMemberToResponseWithUser 将GroupMember转换为GroupMemberResponse(包含用户信息) func GroupMemberToResponseWithUser(member *model.GroupMember, user *model.User) *GroupMemberResponse { if member == nil { return nil } resp := GroupMemberToResponse(member) if user != nil { resp.User = ConvertUserToResponse(user) } return resp } // GroupMembersToResponse 将GroupMember列表转换为GroupMemberResponse列表 func GroupMembersToResponse(members []model.GroupMember) []*GroupMemberResponse { result := make([]*GroupMemberResponse, 0, len(members)) for i := range members { result = append(result, GroupMemberToResponse(&members[i])) } return result } // GroupAnnouncementToResponse 将GroupAnnouncement转换为GroupAnnouncementResponse func GroupAnnouncementToResponse(announcement *model.GroupAnnouncement) *GroupAnnouncementResponse { if announcement == nil { return nil } return &GroupAnnouncementResponse{ ID: announcement.ID, GroupID: announcement.GroupID, Content: announcement.Content, AuthorID: announcement.AuthorID, IsPinned: announcement.IsPinned, CreatedAt: FormatTime(announcement.CreatedAt), } } // GroupAnnouncementsToResponse 将GroupAnnouncement列表转换为GroupAnnouncementResponse列表 func GroupAnnouncementsToResponse(announcements []model.GroupAnnouncement) []*GroupAnnouncementResponse { result := make([]*GroupAnnouncementResponse, 0, len(announcements)) for i := range announcements { result = append(result, GroupAnnouncementToResponse(&announcements[i])) } return result }