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
This commit is contained in:
137
internal/repository/comment_mention_repo.go
Normal file
137
internal/repository/comment_mention_repo.go
Normal file
@ -0,0 +1,137 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"metazone.cc/metalab/internal/model"
|
||||
"metazone.cc/metalab/internal/service"
|
||||
)
|
||||
|
||||
// CreateMention 创建@提及记录
|
||||
func (r *CommentRepo) CreateMention(mention *model.CommentMention) error {
|
||||
return r.db.Create(mention).Error
|
||||
}
|
||||
|
||||
// FindMentionsByComment 查询某条评论的@提及列表
|
||||
func (r *CommentRepo) FindMentionsByComment(commentID uint) ([]model.CommentMention, error) {
|
||||
var list []model.CommentMention
|
||||
err := r.db.Where("comment_id = ?", commentID).Find(&list).Error
|
||||
return list, err
|
||||
}
|
||||
|
||||
// SearchUsersByLevel 搜索指定等级及以上用户(用于@艾特),返回 uid/username/exp
|
||||
func (r *CommentRepo) SearchUsersByLevel(keyword string, minLevel int, limit int) ([]struct {
|
||||
UID string
|
||||
Username string
|
||||
Exp int
|
||||
}, error) {
|
||||
type result struct {
|
||||
UID uint
|
||||
Username string
|
||||
Exp int
|
||||
}
|
||||
var list []result
|
||||
|
||||
threshold := model.LevelThresholds[minLevel]
|
||||
|
||||
err := r.db.Table("users").
|
||||
Select("uid, username, exp").
|
||||
Where("username LIKE ? AND exp >= ? AND deleted_at IS NULL", "%"+keyword+"%", threshold).
|
||||
Order("exp DESC").
|
||||
Limit(limit).
|
||||
Find(&list).Error
|
||||
|
||||
var res []struct {
|
||||
UID string
|
||||
Username string
|
||||
Exp int
|
||||
}
|
||||
for _, u := range list {
|
||||
res = append(res, struct {
|
||||
UID string
|
||||
Username string
|
||||
Exp int
|
||||
}{UID: strconv.FormatUint(uint64(u.UID), 10), Username: u.Username, Exp: u.Exp})
|
||||
}
|
||||
return res, err
|
||||
}
|
||||
|
||||
// GetUserUIDByID 通过 uint ID 获取 user 的 UID 字符串
|
||||
func (r *CommentRepo) GetUserUIDByID(userID uint) (string, error) {
|
||||
var uid uint
|
||||
err := r.db.Table("users").Select("uid").Where("uid = ?", userID).Scan(&uid).Error
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return strconv.FormatUint(uint64(uid), 10), nil
|
||||
}
|
||||
|
||||
// GetUsernameByID 通过 userID 获取用户名(用于通知内容)
|
||||
func (r *CommentRepo) GetUsernameByID(userID uint) (string, error) {
|
||||
var username string
|
||||
err := r.db.Table("users").Select("username").Where("uid = ?", userID).Scan(&username).Error
|
||||
return username, err
|
||||
}
|
||||
|
||||
// FindPostIDByComment 查询评论所属的文章ID
|
||||
func (r *CommentRepo) FindPostIDByComment(commentID uint) (uint, error) {
|
||||
var postID uint
|
||||
err := r.db.Table("comments").Select("post_id").Where("id = ?", commentID).Scan(&postID).Error
|
||||
return postID, err
|
||||
}
|
||||
|
||||
// UpdateRootID 更新评论的 root_id 字段(顶级评论创建后回填)
|
||||
func (r *CommentRepo) UpdateRootID(id, rootID uint) error {
|
||||
return r.db.Model(&model.Comment{}).Where("id = ?", id).Update("root_id", rootID).Error
|
||||
}
|
||||
|
||||
// FindPostAuthorID 查询文章的作者 user_id
|
||||
func (r *CommentRepo) FindPostAuthorID(postID uint) (uint, error) {
|
||||
var authorID uint
|
||||
err := r.db.Table("posts").Select("user_id").Where("id = ?", postID).Scan(&authorID).Error
|
||||
return authorID, err
|
||||
}
|
||||
|
||||
// AggregateCommentsByAuthor 按日期聚合评论量(作者所有文章在时间段内的评论)
|
||||
func (r *CommentRepo) AggregateCommentsByAuthor(userID uint, since string) ([]service.TrendPoint, error) {
|
||||
var results []service.TrendPoint
|
||||
err := r.db.Table("comments").
|
||||
Select("TO_CHAR(comments.created_at, 'YYYY-MM-DD') AS date, COUNT(*) AS value").
|
||||
Joins("JOIN posts ON posts.id = comments.post_id").
|
||||
Where("posts.user_id = ? AND comments.created_at >= ?", userID, since).
|
||||
Group("TO_CHAR(comments.created_at, 'YYYY-MM-DD')").
|
||||
Order("date ASC").
|
||||
Scan(&results).Error
|
||||
if results == nil {
|
||||
results = []service.TrendPoint{}
|
||||
}
|
||||
return results, err
|
||||
}
|
||||
|
||||
// ListAllComments 后台评论列表(支持关键词搜索、分页)
|
||||
func (r *CommentRepo) ListAllComments(keyword string, showDeleted bool, offset, limit int) ([]model.AdminCommentRow, int64, error) {
|
||||
var total int64
|
||||
q := r.db.Table("comments").
|
||||
Joins("LEFT JOIN users ON users.uid = comments.user_id").
|
||||
Joins("LEFT JOIN posts ON posts.id = comments.post_id")
|
||||
|
||||
if !showDeleted {
|
||||
q = q.Where("comments.is_deleted = false")
|
||||
}
|
||||
if keyword != "" {
|
||||
like := "%" + keyword + "%"
|
||||
q = q.Where("comments.body LIKE ? OR users.username LIKE ? OR posts.title LIKE ?", like, like, like)
|
||||
}
|
||||
|
||||
if err := q.Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
var rows []model.AdminCommentRow
|
||||
err := q.
|
||||
Select("comments.id, comments.post_id, posts.title as post_title, comments.body, users.username as author_name, comments.is_deleted, comments.created_at, comments.updated_at").
|
||||
Order("comments.created_at DESC").
|
||||
Offset(offset).Limit(limit).
|
||||
Scan(&rows).Error
|
||||
return rows, total, err
|
||||
}
|
||||
@ -2,8 +2,6 @@ package repository
|
||||
|
||||
import (
|
||||
"metazone.cc/metalab/internal/model"
|
||||
"metazone.cc/metalab/internal/service"
|
||||
"strconv"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
@ -173,132 +171,3 @@ func (r *CommentRepo) CountRepliesByRoot(rootID uint, includeDeleted bool) (int,
|
||||
err := q.Count(&count).Error
|
||||
return int(count), err
|
||||
}
|
||||
|
||||
// CreateMention 创建@提及记录
|
||||
func (r *CommentRepo) CreateMention(mention *model.CommentMention) error {
|
||||
return r.db.Create(mention).Error
|
||||
}
|
||||
|
||||
// FindMentionsByComment 查询某条评论的@提及列表
|
||||
func (r *CommentRepo) FindMentionsByComment(commentID uint) ([]model.CommentMention, error) {
|
||||
var list []model.CommentMention
|
||||
err := r.db.Where("comment_id = ?", commentID).Find(&list).Error
|
||||
return list, err
|
||||
}
|
||||
|
||||
// SearchUsersByLevel 搜索指定等级及以上用户(用于@艾特),返回 uid/username/exp
|
||||
func (r *CommentRepo) SearchUsersByLevel(keyword string, minLevel int, limit int) ([]struct {
|
||||
UID string
|
||||
Username string
|
||||
Exp int
|
||||
}, error) {
|
||||
type result struct {
|
||||
UID uint
|
||||
Username string
|
||||
Exp int
|
||||
}
|
||||
var list []result
|
||||
|
||||
threshold := model.LevelThresholds[minLevel]
|
||||
|
||||
err := r.db.Table("users").
|
||||
Select("uid, username, exp").
|
||||
Where("username LIKE ? AND exp >= ? AND deleted_at IS NULL", "%"+keyword+"%", threshold).
|
||||
Order("exp DESC").
|
||||
Limit(limit).
|
||||
Find(&list).Error
|
||||
|
||||
var res []struct {
|
||||
UID string
|
||||
Username string
|
||||
Exp int
|
||||
}
|
||||
for _, u := range list {
|
||||
res = append(res, struct {
|
||||
UID string
|
||||
Username string
|
||||
Exp int
|
||||
}{UID: strconv.FormatUint(uint64(u.UID), 10), Username: u.Username, Exp: u.Exp})
|
||||
}
|
||||
return res, err
|
||||
}
|
||||
|
||||
// GetUserUIDByID 通过 uint ID 获取 user 的 UID 字符串
|
||||
func (r *CommentRepo) GetUserUIDByID(userID uint) (string, error) {
|
||||
var uid uint
|
||||
err := r.db.Table("users").Select("uid").Where("uid = ?", userID).Scan(&uid).Error
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return strconv.FormatUint(uint64(uid), 10), nil
|
||||
}
|
||||
|
||||
// GetUsernameByID 通过 userID 获取用户名(用于通知内容)
|
||||
func (r *CommentRepo) GetUsernameByID(userID uint) (string, error) {
|
||||
var username string
|
||||
err := r.db.Table("users").Select("username").Where("uid = ?", userID).Scan(&username).Error
|
||||
return username, err
|
||||
}
|
||||
|
||||
// FindPostIDByComment 查询评论所属的文章ID
|
||||
func (r *CommentRepo) FindPostIDByComment(commentID uint) (uint, error) {
|
||||
var postID uint
|
||||
err := r.db.Table("comments").Select("post_id").Where("id = ?", commentID).Scan(&postID).Error
|
||||
return postID, err
|
||||
}
|
||||
|
||||
// UpdateRootID 更新评论的 root_id 字段(顶级评论创建后回填)
|
||||
func (r *CommentRepo) UpdateRootID(id, rootID uint) error {
|
||||
return r.db.Model(&model.Comment{}).Where("id = ?", id).Update("root_id", rootID).Error
|
||||
}
|
||||
|
||||
// FindPostAuthorID 查询文章的作者 user_id
|
||||
func (r *CommentRepo) FindPostAuthorID(postID uint) (uint, error) {
|
||||
var authorID uint
|
||||
err := r.db.Table("posts").Select("user_id").Where("id = ?", postID).Scan(&authorID).Error
|
||||
return authorID, err
|
||||
}
|
||||
|
||||
// AggregateCommentsByAuthor 按日期聚合评论量(作者所有文章在时间段内的评论)
|
||||
func (r *CommentRepo) AggregateCommentsByAuthor(userID uint, since string) ([]service.TrendPoint, error) {
|
||||
var results []service.TrendPoint
|
||||
err := r.db.Table("comments").
|
||||
Select("TO_CHAR(comments.created_at, 'YYYY-MM-DD') AS date, COUNT(*) AS value").
|
||||
Joins("JOIN posts ON posts.id = comments.post_id").
|
||||
Where("posts.user_id = ? AND comments.created_at >= ?", userID, since).
|
||||
Group("TO_CHAR(comments.created_at, 'YYYY-MM-DD')").
|
||||
Order("date ASC").
|
||||
Scan(&results).Error
|
||||
if results == nil {
|
||||
results = []service.TrendPoint{}
|
||||
}
|
||||
return results, err
|
||||
}
|
||||
|
||||
// ListAllComments 后台评论列表(支持关键词搜索、分页)
|
||||
func (r *CommentRepo) ListAllComments(keyword string, showDeleted bool, offset, limit int) ([]model.AdminCommentRow, int64, error) {
|
||||
var total int64
|
||||
q := r.db.Table("comments").
|
||||
Joins("LEFT JOIN users ON users.uid = comments.user_id").
|
||||
Joins("LEFT JOIN posts ON posts.id = comments.post_id")
|
||||
|
||||
if !showDeleted {
|
||||
q = q.Where("comments.is_deleted = false")
|
||||
}
|
||||
if keyword != "" {
|
||||
like := "%" + keyword + "%"
|
||||
q = q.Where("comments.body LIKE ? OR users.username LIKE ? OR posts.title LIKE ?", like, like, like)
|
||||
}
|
||||
|
||||
if err := q.Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
var rows []model.AdminCommentRow
|
||||
err := q.
|
||||
Select("comments.id, comments.post_id, posts.title as post_title, comments.body, users.username as author_name, comments.is_deleted, comments.created_at, comments.updated_at").
|
||||
Order("comments.created_at DESC").
|
||||
Offset(offset).Limit(limit).
|
||||
Scan(&rows).Error
|
||||
return rows, total, err
|
||||
}
|
||||
|
||||
@ -1,12 +1,9 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"metazone.cc/metalab/internal/model"
|
||||
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
)
|
||||
|
||||
// PostRepo 帖子数据访问
|
||||
@ -84,55 +81,6 @@ func (r *PostRepo) FindByUserID(userID uint, offset, limit int) ([]model.Post, i
|
||||
return r.pageResults(query, offset, limit)
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// FindByUserIDAndStatus 分页查询某用户指定状态的帖子(空 status=全状态)
|
||||
func (r *PostRepo) FindByUserIDAndStatus(userID uint, status string, offset, limit int) ([]model.Post, int64, error) {
|
||||
query := r.buildQuery("", status).
|
||||
@ -218,52 +166,3 @@ func (r *PostRepo) Restore(id uint) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
108
internal/repository/post_stats_repo.go
Normal file
108
internal/repository/post_stats_repo.go
Normal file
@ -0,0 +1,108 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user