324 lines
9.2 KiB
Go
324 lines
9.2 KiB
Go
package repository
|
||
|
||
import (
|
||
"errors"
|
||
|
||
"github.com/topfans/backend/pkg/database"
|
||
"github.com/topfans/backend/pkg/models"
|
||
"gorm.io/gorm"
|
||
)
|
||
|
||
// ActivityRepository Activity仓库接口
|
||
type ActivityRepository interface {
|
||
// CreateActivity 创建活动
|
||
CreateActivity(activity *models.Activity) error
|
||
|
||
// GetActivityByID 根据ID获取活动
|
||
GetActivityByID(id int64) (*models.Activity, error)
|
||
|
||
// GetActivitiesByStar 根据star_id获取活动列表
|
||
GetActivitiesByStar(starID int64, status string, page, pageSize int) ([]*models.Activity, int64, error)
|
||
|
||
// UpdateActivityProgress 更新活动进度
|
||
UpdateActivityProgress(id int64, progress int64) error
|
||
|
||
// GetActivityItems 获取活动道具列表
|
||
GetActivityItems(activityID int64) ([]*models.ActivityItem, error)
|
||
|
||
// GetActivityItemByType 根据类型获取道具
|
||
GetActivityItemByType(activityID int64, itemType string) (*models.ActivityItem, error)
|
||
|
||
// CreateContribution 创建贡献记录
|
||
CreateContribution(contribution *models.ActivityContribution) error
|
||
|
||
// GetUserStats 获取用户活动统计
|
||
GetUserStats(activityID, userID, starID int64) (*models.ActivityUserStats, error)
|
||
|
||
// UpdateUserStats 更新用户活动统计
|
||
UpdateUserStats(stats *models.ActivityUserStats) error
|
||
|
||
// GetRanking 获取排行榜
|
||
GetRanking(activityID, starID int64, page, pageSize int) ([]*models.ActivityUserStats, int64, error)
|
||
|
||
// GetUserRank 获取用户排名
|
||
GetUserRank(userID, activityID, starID int64) (int, error)
|
||
|
||
// GetLatestContributions 获取最新贡献记录(用于实时显示)
|
||
GetLatestContributions(activityID int64, sinceTimestamp int64, sinceID int64, limit int) ([]*models.ActivityContribution, error)
|
||
}
|
||
|
||
// activityRepository Activity仓库实现
|
||
type activityRepository struct {
|
||
db *gorm.DB
|
||
}
|
||
|
||
// NewActivityRepository 创建Activity仓库实例
|
||
func NewActivityRepository() ActivityRepository {
|
||
return &activityRepository{
|
||
db: database.GetDB(),
|
||
}
|
||
}
|
||
|
||
// CreateActivity 创建活动
|
||
func (r *activityRepository) CreateActivity(activity *models.Activity) error {
|
||
if activity == nil {
|
||
return errors.New("activity cannot be nil")
|
||
}
|
||
return r.db.Create(activity).Error
|
||
}
|
||
|
||
// GetActivityByID 根据ID获取活动
|
||
func (r *activityRepository) GetActivityByID(id int64) (*models.Activity, error) {
|
||
if id <= 0 {
|
||
return nil, errors.New("activity id must be greater than 0")
|
||
}
|
||
|
||
var activity models.Activity
|
||
if err := r.db.Preload("Items", "is_active = ?", true).First(&activity, id).Error; err != nil {
|
||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||
return nil, nil
|
||
}
|
||
return nil, err
|
||
}
|
||
|
||
return &activity, nil
|
||
}
|
||
|
||
// GetActivitiesByStar 根据star_id获取活动列表
|
||
func (r *activityRepository) GetActivitiesByStar(starID int64, status string, page, pageSize int) ([]*models.Activity, int64, error) {
|
||
if starID <= 0 {
|
||
return nil, 0, errors.New("star_id must be greater than 0")
|
||
}
|
||
|
||
if page <= 0 {
|
||
page = 1
|
||
}
|
||
if pageSize <= 0 {
|
||
pageSize = 10
|
||
}
|
||
|
||
query := r.db.Model(&models.Activity{}).Where("star_id = ?", starID)
|
||
|
||
if status != "" {
|
||
query = query.Where("status = ?", status)
|
||
}
|
||
|
||
var total int64
|
||
if err := query.Count(&total).Error; err != nil {
|
||
return nil, 0, err
|
||
}
|
||
|
||
offset := (page - 1) * pageSize
|
||
var activities []*models.Activity
|
||
if err := query.Preload("Items", "is_active = ?", true).
|
||
Order("start_time DESC").
|
||
Offset(offset).
|
||
Limit(pageSize).
|
||
Find(&activities).Error; err != nil {
|
||
return nil, 0, err
|
||
}
|
||
|
||
return activities, total, nil
|
||
}
|
||
|
||
// UpdateActivityProgress 更新活动进度
|
||
func (r *activityRepository) UpdateActivityProgress(id int64, progress int64) error {
|
||
if id <= 0 {
|
||
return errors.New("activity id must be greater than 0")
|
||
}
|
||
|
||
return r.db.Model(&models.Activity{}).
|
||
Where("id = ?", id).
|
||
Update("current_progress", progress).Error
|
||
}
|
||
|
||
// GetActivityItems 获取活动道具列表
|
||
func (r *activityRepository) GetActivityItems(activityID int64) ([]*models.ActivityItem, error) {
|
||
if activityID <= 0 {
|
||
return nil, errors.New("activity_id must be greater than 0")
|
||
}
|
||
|
||
var items []*models.ActivityItem
|
||
if err := r.db.Where("activity_id = ? AND is_active = ?", activityID, true).
|
||
Order("sort_order ASC").
|
||
Find(&items).Error; err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
return items, nil
|
||
}
|
||
|
||
// GetActivityItemByType 根据类型获取道具
|
||
func (r *activityRepository) GetActivityItemByType(activityID int64, itemType string) (*models.ActivityItem, error) {
|
||
if activityID <= 0 {
|
||
return nil, errors.New("activity_id must be greater than 0")
|
||
}
|
||
|
||
if itemType == "" {
|
||
return nil, errors.New("item_type cannot be empty")
|
||
}
|
||
|
||
var item models.ActivityItem
|
||
if err := r.db.Where("activity_id = ? AND item_type = ? AND is_active = ?", activityID, itemType, true).
|
||
First(&item).Error; err != nil {
|
||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||
return nil, nil
|
||
}
|
||
return nil, err
|
||
}
|
||
|
||
return &item, nil
|
||
}
|
||
|
||
// CreateContribution 创建贡献记录
|
||
func (r *activityRepository) CreateContribution(contribution *models.ActivityContribution) error {
|
||
if contribution == nil {
|
||
return errors.New("contribution cannot be nil")
|
||
}
|
||
|
||
return r.db.Create(contribution).Error
|
||
}
|
||
|
||
// GetUserStats 获取用户活动统计
|
||
func (r *activityRepository) GetUserStats(activityID, userID, starID int64) (*models.ActivityUserStats, error) {
|
||
if activityID <= 0 || userID <= 0 || starID <= 0 {
|
||
return nil, errors.New("activity_id, user_id, star_id must be greater than 0")
|
||
}
|
||
|
||
var stats models.ActivityUserStats
|
||
if err := r.db.Where("activity_id = ? AND user_id = ? AND star_id = ?", activityID, userID, starID).
|
||
First(&stats).Error; err != nil {
|
||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||
return nil, nil
|
||
}
|
||
return nil, err
|
||
}
|
||
|
||
return &stats, nil
|
||
}
|
||
|
||
// UpdateUserStats 更新用户活动统计
|
||
func (r *activityRepository) UpdateUserStats(stats *models.ActivityUserStats) error {
|
||
if stats == nil {
|
||
return errors.New("stats cannot be nil")
|
||
}
|
||
|
||
// 使用 upsert 逻辑
|
||
var existing models.ActivityUserStats
|
||
err := r.db.Where("activity_id = ? AND user_id = ? AND star_id = ?",
|
||
stats.ActivityID, stats.UserID, stats.StarID).First(&existing).Error
|
||
|
||
if err != nil {
|
||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||
// 不存在,创建新记录
|
||
return r.db.Create(stats).Error
|
||
}
|
||
return err
|
||
}
|
||
|
||
// 存在,更新记录
|
||
return r.db.Model(&existing).
|
||
Updates(map[string]interface{}{
|
||
"total_contribution": stats.TotalContribution,
|
||
"total_crystal_spent": stats.TotalCrystalSpent,
|
||
"total_items": stats.TotalItems,
|
||
"last_contribute_at": stats.LastContributeAt,
|
||
"updated_at": stats.UpdatedAt,
|
||
}).Error
|
||
}
|
||
|
||
// GetRanking 获取排行榜
|
||
func (r *activityRepository) GetRanking(activityID, starID int64, page, pageSize int) ([]*models.ActivityUserStats, int64, error) {
|
||
if activityID <= 0 {
|
||
return nil, 0, errors.New("activity_id must be greater than 0")
|
||
}
|
||
|
||
if page <= 0 {
|
||
page = 1
|
||
}
|
||
if pageSize <= 0 {
|
||
pageSize = 10
|
||
}
|
||
|
||
query := r.db.Model(&models.ActivityUserStats{}).Where("activity_id = ?", activityID)
|
||
|
||
// 添加 star_id 过滤
|
||
if starID > 0 {
|
||
query = query.Where("star_id = ?", starID)
|
||
}
|
||
|
||
var total int64
|
||
if err := query.Count(&total).Error; err != nil {
|
||
return nil, 0, err
|
||
}
|
||
|
||
offset := (page - 1) * pageSize
|
||
var stats []*models.ActivityUserStats
|
||
if err := query.Order("total_contribution DESC").
|
||
Offset(offset).
|
||
Limit(pageSize).
|
||
Find(&stats).Error; err != nil {
|
||
return nil, 0, err
|
||
}
|
||
|
||
return stats, total, nil
|
||
}
|
||
|
||
// GetUserRank 获取用户排名
|
||
func (r *activityRepository) GetUserRank(userID, activityID, starID int64) (int, error) {
|
||
if userID <= 0 || activityID <= 0 || starID <= 0 {
|
||
return 0, errors.New("user_id, activity_id, star_id must be greater than 0")
|
||
}
|
||
|
||
// 获取用户的贡献值
|
||
var userStats models.ActivityUserStats
|
||
if err := r.db.Where("activity_id = ? AND user_id = ? AND star_id = ?", activityID, userID, starID).
|
||
First(&userStats).Error; err != nil {
|
||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||
return 0, nil // 用户没有贡献记录
|
||
}
|
||
return 0, err
|
||
}
|
||
|
||
// 计算排名:统计贡献值大于当前用户的数量
|
||
var count int64
|
||
if err := r.db.Model(&models.ActivityUserStats{}).
|
||
Where("activity_id = ? AND star_id = ? AND total_contribution > ?", activityID, starID, userStats.TotalContribution).
|
||
Count(&count).Error; err != nil {
|
||
return 0, err
|
||
}
|
||
|
||
return int(count) + 1, nil
|
||
}
|
||
|
||
// GetLatestContributions 获取最新贡献记录(用于实时显示)
|
||
func (r *activityRepository) GetLatestContributions(activityID int64, sinceTimestamp int64, sinceID int64, limit int) ([]*models.ActivityContribution, error) {
|
||
if activityID <= 0 {
|
||
return nil, errors.New("activity_id must be greater than 0")
|
||
}
|
||
|
||
if limit <= 0 {
|
||
limit = 5
|
||
}
|
||
if limit > 20 {
|
||
limit = 20 // 最多返回20条
|
||
}
|
||
|
||
query := r.db.Model(&models.ActivityContribution{}).
|
||
Where("activity_id = ?", activityID).
|
||
Order("created_at DESC, id DESC")
|
||
|
||
// 如果有 sinceTimestamp 和 sinceID,进行分页查询
|
||
// 用于增量获取:获取 created_at > sinceTimestamp 或者 (created_at == sinceTimestamp AND id > sinceID) 的记录
|
||
if sinceTimestamp > 0 {
|
||
query = query.Where("created_at > ? OR (created_at = ? AND id > ?)", sinceTimestamp, sinceTimestamp, sinceID)
|
||
}
|
||
|
||
var contributions []*models.ActivityContribution
|
||
if err := query.Limit(limit).Find(&contributions).Error; err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
return contributions, nil
|
||
}
|