Files
mce/internal/repository/post_stats_repo.go
Victor_Jay 9477155bcf refactor: 文件行数超标拆解(7个文件→14个文件,全部≤200行)
- 移动本地接口定义到 interfaces.go 和 admin/interfaces.go
- favorite_controller.go → favorite_item_controller.go
- space_controller.go → space_loaders.go
- settings_controller.go → settings_api_audit.go
- admin_energy_controller.go → admin_energy_api_controller.go
- admin_post_controller.go → admin_post_action_controller.go
- comment_repo.go → comment_mention_repo.go
- post_repo.go → post_stats_repo.go
2026-06-02 15:58:52 +08:00

109 lines
3.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package repository
import (
"time"
"metazone.cc/metalab/internal/model"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
// CountUserPosts 统计某用户的已发布文章数
func (r *PostRepo) CountUserPosts(userID uint) (int64, error) {
var count int64
err := r.db.Model(&model.Post{}).
Where("user_id = ? AND status = ? AND deleted_at IS NULL", userID, model.PostStatusApproved).
Count(&count).Error
return count, err
}
// GetUserStats 获取用户的文章统计数据(总获赞/总收藏/总阅读)
func (r *PostRepo) GetUserStats(userID uint) (likes, favorites, reads int64, err error) {
type stats struct {
TotalLikes int64
TotalFavorites int64
TotalReads int64
}
var s stats
err = r.db.Model(&model.Post{}).
Select("COALESCE(SUM(likes_count), 0) AS total_likes, COALESCE(SUM(favorites_count), 0) AS total_favorites, COALESCE(SUM(views_count), 0) AS total_reads").
Where("user_id = ? AND status = ? AND deleted_at IS NULL", userID, model.PostStatusApproved).
Scan(&s).Error
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
}
// readCooldown 两次阅读记录最小间隔
const readCooldown = 2 * time.Second
// RecordRead 记录已登录用户阅读文章(防刷量:取去重+冷却)
// 返回 true 表示首次阅读新记录false 表示重复或冷却中
func (r *PostRepo) RecordRead(userID, postID uint) (bool, error) {
// 冷却检查:同用户两次阅读之间至少间隔 2 秒
var lastRead model.PostReadLog
if err := r.db.Where("user_id = ?", userID).
Order("read_at DESC").First(&lastRead).Error; err == nil {
if time.Since(lastRead.ReadAt) < readCooldown {
return false, nil
}
}
result := r.db.Clauses(clause.OnConflict{DoNothing: true}).
Create(&model.PostReadLog{UserID: userID, PostID: postID})
if result.Error != nil {
return false, result.Error
}
return result.RowsAffected > 0, nil
}
// RecordGuestRead 记录访客阅读文章(基于 Cookie visitor_id 去重+冷却)
// 返回 true 表示首次阅读新记录false 表示重复或冷却中
func (r *PostRepo) RecordGuestRead(visitorID string, postID uint) (bool, error) {
// 冷却检查:同访客两次阅读之间至少间隔 2 秒
var lastRead model.PostGuestReadLog
if err := r.db.Where("visitor_id = ?", visitorID).
Order("read_at DESC").First(&lastRead).Error; err == nil {
if time.Since(lastRead.ReadAt) < readCooldown {
return false, nil
}
}
result := r.db.Clauses(clause.OnConflict{DoNothing: true}).
Create(&model.PostGuestReadLog{VisitorID: visitorID, PostID: postID})
if result.Error != nil {
return false, result.Error
}
return result.RowsAffected > 0, nil
}
// IncrementViewsCount 阅读数 +1
func (r *PostRepo) IncrementViewsCount(postID uint) error {
return r.db.Model(&model.Post{}).Where("id = ?", postID).
Update("views_count", gorm.Expr("views_count + 1")).Error
}