package repository import ( "errors" "time" "github.com/topfans/backend/services/taskService/model" "gorm.io/gorm" ) // DailyTaskRepository 每日任务数据访问层接口 type DailyTaskRepository interface { // GetUserDailyProgress 获取用户指定每日任务的进度 GetUserDailyProgress(userID, starID int64, taskKey string) (*model.UserDailyTaskProgress, error) // GetOrCreateDailyProgress 获取或创建用户每日任务进度 GetOrCreateDailyProgress(userID, starID int64, taskKey string, def *model.TaskDefinition) (*model.UserDailyTaskProgress, error) // ListDailyTasksByUser 获取用户的所有每日任务进度 ListDailyTasksByUser(userID, starID int64) ([]*model.UserDailyTaskProgress, error) // ListCompletedDailyTasks 获取用户已完成但未领取的每日任务进度 ListCompletedDailyTasks(userID, starID int64) ([]*model.UserDailyTaskProgress, error) // ListActiveDailyTaskDefinitions 获取所有活跃的每日任务定义(包括star特定和全局默认) ListActiveDailyTaskDefinitions(starID int64) ([]*model.TaskDefinition, error) // UpdateDailyProgress 更新每日任务进度 UpdateDailyProgress(progress *model.UserDailyTaskProgress) error // ResetAllDailyTasks 重置所有非pending状态的每日任务为pending ResetAllDailyTasks() (int64, error) // InitDailyTasksForUser 为用户初始化该star的所有每日任务进度 InitDailyTasksForUser(userID, starID int64) error // AcquireAdvisoryLock 获取PostgreSQL advisory lock AcquireAdvisoryLock(lockID int64) bool // ReleaseAdvisoryLock 释放PostgreSQL advisory lock ReleaseAdvisoryLock(lockID int64) } // dailyTaskRepository Repository实现 type dailyTaskRepository struct { db *gorm.DB } // NewDailyTaskRepository 创建Repository实例 func NewDailyTaskRepository(db *gorm.DB) DailyTaskRepository { return &dailyTaskRepository{db: db} } // GetUserDailyProgress 获取用户指定每日任务的进度 func (r *dailyTaskRepository) GetUserDailyProgress(userID, starID int64, taskKey string) (*model.UserDailyTaskProgress, error) { var progress model.UserDailyTaskProgress err := r.db.Where("user_id = ? AND star_id = ? AND task_key = ?", userID, starID, taskKey). First(&progress).Error if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, nil } return nil, err } return &progress, nil } // GetOrCreateDailyProgress 获取或创建用户每日任务进度 func (r *dailyTaskRepository) GetOrCreateDailyProgress(userID, starID int64, taskKey string, def *model.TaskDefinition) (*model.UserDailyTaskProgress, error) { progress, err := r.GetUserDailyProgress(userID, starID, taskKey) if err != nil { return nil, err } if progress != nil { return progress, nil } // 创建新的进度记录 now := time.Now().UnixMilli() progress = &model.UserDailyTaskProgress{ UserID: userID, StarID: starID, TaskKey: taskKey, Status: "pending", CreatedAt: now, UpdatedAt: now, } if def != nil { progress.CreatedAt = now progress.UpdatedAt = now } err = r.db.Create(progress).Error if err != nil { return nil, err } return progress, nil } // ListDailyTasksByUser 获取用户的所有每日任务进度 func (r *dailyTaskRepository) ListDailyTasksByUser(userID, starID int64) ([]*model.UserDailyTaskProgress, error) { var progressList []*model.UserDailyTaskProgress err := r.db.Where("user_id = ? AND star_id = ?", userID, starID). Order("id ASC"). Find(&progressList).Error return progressList, err } // ListCompletedDailyTasks 获取用户已完成但未领取的每日任务进度 func (r *dailyTaskRepository) ListCompletedDailyTasks(userID, starID int64) ([]*model.UserDailyTaskProgress, error) { var progressList []*model.UserDailyTaskProgress err := r.db.Where("user_id = ? AND star_id = ? AND status = ?", userID, starID, "completed"). Order("id ASC"). Find(&progressList).Error return progressList, err } // ListActiveDailyTaskDefinitions 获取所有活跃的每日任务定义(包括star特定和全局默认) func (r *dailyTaskRepository) ListActiveDailyTaskDefinitions(starID int64) ([]*model.TaskDefinition, error) { var definitions []*model.TaskDefinition err := r.db.Where("is_active = true AND (star_id = ? OR star_id IS NULL)", starID). Where("task_type = ?", "daily"). Order("sort_order ASC, id ASC"). Find(&definitions).Error return definitions, err } // UpdateDailyProgress 更新每日任务进度 func (r *dailyTaskRepository) UpdateDailyProgress(progress *model.UserDailyTaskProgress) error { progress.UpdatedAt = time.Now().UnixMilli() return r.db.Save(progress).Error } // ResetAllDailyTasks 重置所有非pending状态的每日任务为pending func (r *dailyTaskRepository) ResetAllDailyTasks() (int64, error) { now := time.Now().UnixMilli() result := r.db.Model(&model.UserDailyTaskProgress{}). Where("status != ?", "pending"). Updates(map[string]interface{}{ "status": "pending", "completed_at": nil, "claimed_at": nil, "updated_at": now, }) return result.RowsAffected, result.Error } // InitDailyTasksForUser 为用户初始化该star的所有每日任务进度 func (r *dailyTaskRepository) InitDailyTasksForUser(userID, starID int64) error { // 获取所有活跃的每日任务定义 definitions, err := r.ListActiveDailyTaskDefinitions(starID) if err != nil { return err } if len(definitions) == 0 { return nil } now := time.Now().UnixMilli() return r.db.Transaction(func(tx *gorm.DB) error { for _, def := range definitions { // 检查是否已存在该任务的进度 var count int64 err := tx.Model(&model.UserDailyTaskProgress{}). Where("user_id = ? AND star_id = ? AND task_key = ?", userID, starID, def.TaskKey). Count(&count).Error if err != nil { return err } // 如果已存在,跳过 if count > 0 { continue } // 创建新的进度记录 progress := &model.UserDailyTaskProgress{ UserID: userID, StarID: starID, TaskKey: def.TaskKey, Status: "pending", CreatedAt: now, UpdatedAt: now, } if err := tx.Create(progress).Error; err != nil { return err } } return nil }) } // AcquireAdvisoryLock 获取PostgreSQL advisory lock func (r *dailyTaskRepository) AcquireAdvisoryLock(lockID int64) bool { var result bool err := r.db.Raw("SELECT pg_try_advisory_lock(?)", lockID).Scan(&result).Error if err != nil { return false } return result } // ReleaseAdvisoryLock 释放PostgreSQL advisory lock func (r *dailyTaskRepository) ReleaseAdvisoryLock(lockID int64) { r.db.Exec("SELECT pg_advisory_unlock(?)", lockID) }