diff --git a/internal/controller/comment_action_controller.go b/internal/controller/comment_action_controller.go index 3253699..953b7df 100644 --- a/internal/controller/comment_action_controller.go +++ b/internal/controller/comment_action_controller.go @@ -41,7 +41,7 @@ func (ctrl *CommentController) Delete(c *gin.Context) { // SearchUsers GET /api/users/search?q=keyword func (ctrl *CommentController) SearchUsers(c *gin.Context) { - _, _, ok := common.GetGinUser(c) + uid, _, ok := common.GetGinUser(c) if !ok { common.Error(c, http.StatusUnauthorized, "请先登录") return @@ -53,7 +53,7 @@ func (ctrl *CommentController) SearchUsers(c *gin.Context) { return } - users, err := ctrl.commentService.SearchUsers(q) + users, err := ctrl.commentService.SearchUsers(q, uid) if err != nil { common.Error(c, http.StatusInternalServerError, "搜索用户失败") return diff --git a/internal/controller/interfaces.go b/internal/controller/interfaces.go index 2c729dd..5339de5 100644 --- a/internal/controller/interfaces.go +++ b/internal/controller/interfaces.go @@ -115,7 +115,7 @@ type commentUseCase interface { Delete(commentID uint, requesterID uint, isAdmin bool) error ListRootComments(postID uint, page, pageSize int) ([]model.Comment, int64, error) ListReplies(rootID uint) ([]model.Comment, error) - SearchUsers(keyword string) ([]model.UserSearchResult, error) + SearchUsers(keyword string, followerUID uint) ([]model.UserSearchResult, error) } // reactionUseCase ReactionController 对 ReactionService 的最小依赖(ISP:4 个方法) diff --git a/internal/repository/comment_mention_repo.go b/internal/repository/comment_mention_repo.go index cdbfd3a..75b5f3c 100644 --- a/internal/repository/comment_mention_repo.go +++ b/internal/repository/comment_mention_repo.go @@ -67,7 +67,8 @@ func (r *CommentRepo) LoadMentionsForComments(comments []model.Comment) error { } // SearchUsersByLevel 搜索指定等级及以上用户(用于@艾特),返回 uid/username/avatar/exp -func (r *CommentRepo) SearchUsersByLevel(keyword string, minLevel int, limit int) ([]struct { +// followerUID > 0 时按已关注优先排序,其次按exp降序 +func (r *CommentRepo) SearchUsersByLevel(keyword string, minLevel, limit int, followerUID uint) ([]struct { UID uint Username string Avatar string @@ -83,12 +84,17 @@ func (r *CommentRepo) SearchUsersByLevel(keyword string, minLevel int, limit int threshold := model.LevelThresholds[minLevel] - err := r.db.Table("users"). - Select("id AS uid, username, avatar, exp"). - Where("username LIKE ? AND exp >= ? AND deleted_at IS NULL", "%"+keyword+"%", threshold). - Order("exp DESC"). - Limit(limit). - Find(&list).Error + q := r.db.Table("users AS u"). + Select("u.id AS uid, u.username, u.avatar, u.exp"). + Where("u.username LIKE ? AND u.exp >= ? AND u.deleted_at IS NULL", "%"+keyword+"%", threshold). + Order("u.exp DESC") + + if followerUID > 0 { + q = q.Joins("LEFT JOIN user_follows f ON f.followee_id = u.id AND f.follower_id = ?", followerUID). + Order("(f.follower_id IS NOT NULL) DESC, u.exp DESC") + } + + err := q.Limit(limit).Find(&list).Error var res []struct { UID uint diff --git a/internal/service/comment_service.go b/internal/service/comment_service.go index ea31107..8252094 100644 --- a/internal/service/comment_service.go +++ b/internal/service/comment_service.go @@ -190,9 +190,9 @@ func (s *CommentService) ListAllComments(keyword string, showDeleted bool, page, return rows, total, err } -// SearchUsers 搜索LV2+用户(用于@艾特悬浮窗) -func (s *CommentService) SearchUsers(keyword string) ([]model.UserSearchResult, error) { - rows, err := s.repo.SearchUsersByLevel(keyword, 2, 10) +// SearchUsers 搜索LV2+用户(用于@艾特悬浮窗),已关注优先,最多5条 +func (s *CommentService) SearchUsers(keyword string, followerUID uint) ([]model.UserSearchResult, error) { + rows, err := s.repo.SearchUsersByLevel(keyword, 2, 5, followerUID) if err != nil { return nil, fmt.Errorf("搜索用户失败: %w", err) } @@ -219,7 +219,7 @@ func (s *CommentService) parseMentions(commentID uint, body string) { continue } seen[username] = true - rows, _ := s.repo.SearchUsersByLevel(username, 2, 1) + rows, _ := s.repo.SearchUsersByLevel(username, 2, 1, 0) if len(rows) > 0 { _ = s.repo.CreateMention(&model.CommentMention{ CommentID: commentID, diff --git a/internal/service/repository.go b/internal/service/repository.go index f0314da..7853af7 100644 --- a/internal/service/repository.go +++ b/internal/service/repository.go @@ -155,7 +155,7 @@ type commentStore interface { CreateMention(mention *model.CommentMention) error FindPostIDByComment(commentID uint) (uint, error) FindPostAuthorID(postID uint) (uint, error) - SearchUsersByLevel(keyword string, minLevel, limit int) ([]struct { + SearchUsersByLevel(keyword string, minLevel, limit int, followerUID uint) ([]struct { UID uint Username string Avatar string