refactor: GetOverview 5 次独立查询合并为单次 GROUP BY

- 新增 PostRepo.GetOverviewByUserID 单次 CASE WHEN + GROUP BY 查询
- Service 层 GetOverview 从 5 次 DB 查询减少为 1 次
- 接口 postStore 新增 GetOverviewByUserID 声明
This commit is contained in:
2026-06-02 15:25:17 +08:00
parent 9b315c11cd
commit 7cdb4d6698
3 changed files with 28 additions and 8 deletions

View File

@ -108,6 +108,31 @@ func (r *PostRepo) GetUserStats(userID uint) (likes, favorites, reads int64, err
return s.TotalLikes, s.TotalFavorites, s.TotalReads, err return s.TotalLikes, s.TotalFavorites, s.TotalReads, err
} }
// overviewRow GetOverviewByUserID 单次 GROUP BY 查询结果行
type overviewRow struct {
TotalPosts int64
DraftCount int64
PendingCount int64
ApprovedCount int64
RejectedCount int64
}
// GetOverviewByUserID 用单次 GROUP BY 查询聚合用户各状态文章数
func (r *PostRepo) GetOverviewByUserID(userID uint) (totalPosts, draftCount, pendingCount, approvedCount, rejectedCount int64, err error) {
var row overviewRow
err = r.db.Model(&model.Post{}).
Select(`
COUNT(*) AS total_posts,
COALESCE(SUM(CASE WHEN status = 'draft' THEN 1 ELSE 0 END), 0) AS draft_count,
COALESCE(SUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END), 0) AS pending_count,
COALESCE(SUM(CASE WHEN status = 'approved' THEN 1 ELSE 0 END), 0) AS approved_count,
COALESCE(SUM(CASE WHEN status = 'rejected' THEN 1 ELSE 0 END), 0) AS rejected_count
`).
Where("user_id = ? AND deleted_at IS NULL", userID).
Scan(&row).Error
return row.TotalPosts, row.DraftCount, row.PendingCount, row.ApprovedCount, row.RejectedCount, err
}
// FindByUserIDAndStatus 分页查询某用户指定状态的帖子(空 status=全状态) // FindByUserIDAndStatus 分页查询某用户指定状态的帖子(空 status=全状态)
func (r *PostRepo) FindByUserIDAndStatus(userID uint, status string, offset, limit int) ([]model.Post, int64, error) { func (r *PostRepo) FindByUserIDAndStatus(userID uint, status string, offset, limit int) ([]model.Post, int64, error) {
query := r.buildQuery("", status). query := r.buildQuery("", status).

View File

@ -187,18 +187,12 @@ type StudioOverview struct {
RejectedCount int64 `json:"rejected_count"` RejectedCount int64 `json:"rejected_count"`
} }
// GetOverview 获取创作中心数据概览 // GetOverview 获取创作中心数据概览(单次 GROUP BY 查询)
func (s *PostService) GetOverview(userID uint) (*StudioOverview, error) { func (s *PostService) GetOverview(userID uint) (*StudioOverview, error) {
// 获取各状态文章数量(分页传 1 条只取 total totalPosts, draftCount, pendingCount, approvedCount, rejectedCount, err := s.repo.GetOverviewByUserID(userID)
_, totalPosts, err := s.repo.FindByUserIDAndStatus(userID, "", 0, 1)
if err != nil { if err != nil {
return nil, err return nil, err
} }
_, draftCount, _ := s.repo.FindByUserIDAndStatus(userID, model.PostStatusDraft, 0, 1)
_, pendingCount, _ := s.repo.FindByUserIDAndStatus(userID, model.PostStatusPending, 0, 1)
_, approvedCount, _ := s.repo.FindByUserIDAndStatus(userID, model.PostStatusApproved, 0, 1)
_, rejectedCount, _ := s.repo.FindByUserIDAndStatus(userID, model.PostStatusRejected, 0, 1)
return &StudioOverview{ return &StudioOverview{
TotalPosts: totalPosts, TotalPosts: totalPosts,
DraftCount: draftCount, DraftCount: draftCount,

View File

@ -37,6 +37,7 @@ type postStore interface {
FindPageable(keyword string, offset, limit int) ([]model.Post, int64, error) FindPageable(keyword string, offset, limit int) ([]model.Post, int64, error)
FindAdminPageable(keyword, status string, offset, limit int) ([]model.Post, int64, error) FindAdminPageable(keyword, status string, offset, limit int) ([]model.Post, int64, error)
FindByUserIDAndStatus(userID uint, status string, offset, limit int) ([]model.Post, int64, error) FindByUserIDAndStatus(userID uint, status string, offset, limit int) ([]model.Post, int64, error)
GetOverviewByUserID(userID uint) (totalPosts, draftCount, pendingCount, approvedCount, rejectedCount int64, err error)
FindPendingRevisions(keyword string, offset, limit int) ([]model.Post, int64, error) FindPendingRevisions(keyword string, offset, limit int) ([]model.Post, int64, error)
Update(post *model.Post) error Update(post *model.Post) error
SoftDelete(id uint) error SoftDelete(id uint) error