feat(task): GORM model + repository + ProcessTaskEvent engine
Phase B (model + repository): - TaskDefinition: +TriggerEvent string, +TargetCount int - UserDailyTaskProgress: +Progress int - DailyTaskRepository: ListActiveDailyTaskDefinitions signature -> (starID, eventType string) - IncrementProgress: atomic UPDATE progress=progress+1 WHERE status='pending' (returns rows-affected 0 + re-read on race; caller decides completion transition) - ResetAllDailyTasks: +progress: 0 in Updates map - InitDailyTasksForUser: pass eventType='' (backward-compat) Phase D (engine + ReportEvent delegation, spec §4.3): - TaskEventResult struct (CompletedTaskKeys []string) - DailyTaskService.ProcessTaskEvent: 5-step engine 1. ListActiveDailyTaskDefinitions(starID, eventType) - filter by trigger_event 2. GetOrCreateDailyProgress; skip if completed/claimed (day idempotency) 3. IncrementProgress (atomic +1) 4. if progress >= target_count -> status='completed' 5. UpdateDailyProgress + accumulate CompletedTaskKeys - ReportEvent rewired: delegates to ProcessTaskEvent, maps TaskEventResult to ReportEventResponse (F1: single isolation unit; MQ consumer + RPC both use engine) - 3 callers (GetDailyTasks / ClaimDailyTask / ClaimAllDailyTasks) pass eventType='' for backward-compat (preserves daily_login / daily_browse_asset before Phase F) Note: Phase B and D are bundled because the signature change in B is what enables D's engine to filter by trigger_event. Splitting would leave the codebase uncompilable in the interim. spec: docs/superpowers/specs/2026-07-21-daily-task-config-driven-design.md §4 plan: docs/superpowers/plans/2026-07-21-daily-task-config-driven-impl.md Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
bdf3abc2bc
commit
e2f1122cc8
@ -13,6 +13,9 @@ type TaskDefinition struct {
|
|||||||
IsActive bool `gorm:"column:is_active;default:true"`
|
IsActive bool `gorm:"column:is_active;default:true"`
|
||||||
CreatedAt int64 `gorm:"column:created_at"`
|
CreatedAt int64 `gorm:"column:created_at"`
|
||||||
UpdatedAt int64 `gorm:"column:updated_at"`
|
UpdatedAt int64 `gorm:"column:updated_at"`
|
||||||
|
// 方案 A(spec §2.1 / §4):trigger_event + target_count 取代内联 def.TaskKey 匹配
|
||||||
|
TriggerEvent string `gorm:"column:trigger_event;size:64"` // NULL=仍走 def.TaskKey==eventType 兜底(向后兼容)
|
||||||
|
TargetCount int `gorm:"column:target_count;default:1"` // =1 等价"首次",>1 为计数型
|
||||||
}
|
}
|
||||||
|
|
||||||
func (TaskDefinition) TableName() string { return "task_definitions" }
|
func (TaskDefinition) TableName() string { return "task_definitions" }
|
||||||
@ -28,6 +31,8 @@ type UserDailyTaskProgress struct {
|
|||||||
ClaimedAt *int64 `gorm:"column:claimed_at"`
|
ClaimedAt *int64 `gorm:"column:claimed_at"`
|
||||||
CreatedAt int64 `gorm:"column:created_at"`
|
CreatedAt int64 `gorm:"column:created_at"`
|
||||||
UpdatedAt int64 `gorm:"column:updated_at"`
|
UpdatedAt int64 `gorm:"column:updated_at"`
|
||||||
|
// 方案 A(spec §2.2 / §4):累计次数;progress >= target_count → status=completed
|
||||||
|
Progress int `gorm:"column:progress;default:0"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (UserDailyTaskProgress) TableName() string { return "user_daily_task_progress" }
|
func (UserDailyTaskProgress) TableName() string { return "user_daily_task_progress" }
|
||||||
|
|||||||
@ -18,11 +18,15 @@ type DailyTaskRepository interface {
|
|||||||
ListDailyTasksByUser(userID, starID int64) ([]*model.UserDailyTaskProgress, error)
|
ListDailyTasksByUser(userID, starID int64) ([]*model.UserDailyTaskProgress, error)
|
||||||
// ListCompletedDailyTasks 获取用户已完成但未领取的每日任务进度
|
// ListCompletedDailyTasks 获取用户已完成但未领取的每日任务进度
|
||||||
ListCompletedDailyTasks(userID, starID int64) ([]*model.UserDailyTaskProgress, error)
|
ListCompletedDailyTasks(userID, starID int64) ([]*model.UserDailyTaskProgress, error)
|
||||||
// ListActiveDailyTaskDefinitions 获取所有活跃的每日任务定义(包括star特定和全局默认)
|
// ListActiveDailyTaskDefinitions 获取所有活跃的每日任务定义(按 trigger_event 过滤,含 star 特定 + 全局默认)
|
||||||
ListActiveDailyTaskDefinitions(starID int64) ([]*model.TaskDefinition, error)
|
// eventType 传空字符串则不过滤(保留向后兼容,GetDailyTasks 等老路径仍可用)
|
||||||
|
ListActiveDailyTaskDefinitions(starID int64, eventType string) ([]*model.TaskDefinition, error)
|
||||||
// UpdateDailyProgress 更新每日任务进度
|
// UpdateDailyProgress 更新每日任务进度
|
||||||
UpdateDailyProgress(progress *model.UserDailyTaskProgress) error
|
UpdateDailyProgress(progress *model.UserDailyTaskProgress) error
|
||||||
// ResetAllDailyTasks 重置所有非pending状态的每日任务为pending
|
// IncrementProgress 原子累加 progress;status='pending' 时 +1,到达 target_count 时 status='completed'
|
||||||
|
// 失败返回 error;调用方需在事务外层依据返回的 progress.Progress 决定后续动作
|
||||||
|
IncrementProgress(progress *model.UserDailyTaskProgress, def *model.TaskDefinition) error
|
||||||
|
// ResetAllDailyTasks 重置所有非pending状态的每日任务为pending(包含 progress=0)
|
||||||
ResetAllDailyTasks() (int64, error)
|
ResetAllDailyTasks() (int64, error)
|
||||||
// InitDailyTasksForUser 为用户初始化该star的所有每日任务进度
|
// InitDailyTasksForUser 为用户初始化该star的所有每日任务进度
|
||||||
InitDailyTasksForUser(userID, starID int64) error
|
InitDailyTasksForUser(userID, starID int64) error
|
||||||
@ -107,12 +111,17 @@ func (r *dailyTaskRepository) ListCompletedDailyTasks(userID, starID int64) ([]*
|
|||||||
return progressList, err
|
return progressList, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListActiveDailyTaskDefinitions 获取所有活跃的每日任务定义(包括star特定和全局默认)
|
// ListActiveDailyTaskDefinitions 获取所有活跃的每日任务定义(按 trigger_event 过滤,含 star 特定 + 全局默认)
|
||||||
func (r *dailyTaskRepository) ListActiveDailyTaskDefinitions(starID int64) ([]*model.TaskDefinition, error) {
|
// eventType 为空字符串时不过滤 trigger_event(向后兼容,GetDailyTasks 路径调用)
|
||||||
|
func (r *dailyTaskRepository) ListActiveDailyTaskDefinitions(starID int64, eventType string) ([]*model.TaskDefinition, error) {
|
||||||
|
q := r.db.Where("is_active = true AND (star_id = ? OR star_id IS NULL)", starID).
|
||||||
|
Where("task_type = ?", "daily")
|
||||||
|
if eventType != "" {
|
||||||
|
// 只查 trigger_event 匹配的行;F5:star_id=NULL 全局任务 + star 专属任务叠加(OR 已包含)
|
||||||
|
q = q.Where("trigger_event = ?", eventType)
|
||||||
|
}
|
||||||
var definitions []*model.TaskDefinition
|
var definitions []*model.TaskDefinition
|
||||||
err := r.db.Where("is_active = true AND (star_id = ? OR star_id IS NULL)", starID).
|
err := q.Order("sort_order ASC, id ASC").
|
||||||
Where("task_type = ?", "daily").
|
|
||||||
Order("sort_order ASC, id ASC").
|
|
||||||
Find(&definitions).Error
|
Find(&definitions).Error
|
||||||
return definitions, err
|
return definitions, err
|
||||||
}
|
}
|
||||||
@ -123,24 +132,57 @@ func (r *dailyTaskRepository) UpdateDailyProgress(progress *model.UserDailyTaskP
|
|||||||
return r.db.Save(progress).Error
|
return r.db.Save(progress).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResetAllDailyTasks 重置所有非pending状态的每日任务为pending
|
// IncrementProgress 原子累加 progress(事务内 UPDATE,避免 Save 全量覆写)
|
||||||
|
// 行为:
|
||||||
|
// - WHERE status='pending' 才 +1(已完成/已领取跳过,幂等)
|
||||||
|
// - UPDATE 同时设置 progress = progress + 1, updated_at = now
|
||||||
|
// - 调用方负责"progress 到达 target_count 后"的状态机转移(Status/CompletedAt 字段)——
|
||||||
|
// 这里刻意不耦合,避免 UPDATE 双重语义
|
||||||
|
//
|
||||||
|
// 设计依据:spec §5 计数型 + spec §4 F5 多命中语义;service 层在拿到返回 progress 后
|
||||||
|
// 决定是否再调 UpdateDailyProgress 标记 completed。
|
||||||
|
func (r *dailyTaskRepository) IncrementProgress(progress *model.UserDailyTaskProgress, def *model.TaskDefinition) error {
|
||||||
|
now := time.Now().UnixMilli()
|
||||||
|
result := r.db.Model(&model.UserDailyTaskProgress{}).
|
||||||
|
Where("id = ? AND status = ?", progress.ID, "pending").
|
||||||
|
Updates(map[string]interface{}{
|
||||||
|
"progress": gorm.Expr("progress + ?", 1),
|
||||||
|
"updated_at": now,
|
||||||
|
})
|
||||||
|
if result.Error != nil {
|
||||||
|
return result.Error
|
||||||
|
}
|
||||||
|
if result.RowsAffected == 0 {
|
||||||
|
// 已被并发标记为 completed/claimed,或 progress 不存在
|
||||||
|
// 重新读一次以便上层拿到最新值
|
||||||
|
return r.db.Where("id = ?", progress.ID).First(progress).Error
|
||||||
|
}
|
||||||
|
// UPDATE 成功后回填 progress 到入参对象(service 层用)
|
||||||
|
progress.Progress++
|
||||||
|
progress.UpdatedAt = now
|
||||||
|
_ = def // def 当前未使用,保留以备未来扩展(如去重、增量)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResetAllDailyTasks 重置所有非pending状态的每日任务为pending(含 progress=0)
|
||||||
func (r *dailyTaskRepository) ResetAllDailyTasks() (int64, error) {
|
func (r *dailyTaskRepository) ResetAllDailyTasks() (int64, error) {
|
||||||
now := time.Now().UnixMilli()
|
now := time.Now().UnixMilli()
|
||||||
result := r.db.Model(&model.UserDailyTaskProgress{}).
|
result := r.db.Model(&model.UserDailyTaskProgress{}).
|
||||||
Where("status != ?", "pending").
|
Where("status != ?", "pending").
|
||||||
Updates(map[string]interface{}{
|
Updates(map[string]interface{}{
|
||||||
"status": "pending",
|
"status": "pending",
|
||||||
|
"progress": 0, // 新增:清零计数(spec §6)
|
||||||
"completed_at": nil,
|
"completed_at": nil,
|
||||||
"claimed_at": nil,
|
"claimed_at": nil,
|
||||||
"updated_at": now,
|
"updated_at": now,
|
||||||
})
|
})
|
||||||
return result.RowsAffected, result.Error
|
return result.RowsAffected, result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitDailyTasksForUser 为用户初始化该star的所有每日任务进度
|
// InitDailyTasksForUser 为用户初始化该star的所有每日任务进度
|
||||||
func (r *dailyTaskRepository) InitDailyTasksForUser(userID, starID int64) error {
|
func (r *dailyTaskRepository) InitDailyTasksForUser(userID, starID int64) error {
|
||||||
// 获取所有活跃的每日任务定义
|
// 获取所有活跃的每日任务定义(不过滤 trigger_event——初始化需包含全部 daily)
|
||||||
definitions, err := r.ListActiveDailyTaskDefinitions(starID)
|
definitions, err := r.ListActiveDailyTaskDefinitions(starID, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,10 +20,21 @@ import (
|
|||||||
type DailyTaskService interface {
|
type DailyTaskService interface {
|
||||||
GetDailyTasks(ctx context.Context, userID, starID int64) (*pb.GetDailyTasksResponse, error)
|
GetDailyTasks(ctx context.Context, userID, starID int64) (*pb.GetDailyTasksResponse, error)
|
||||||
ReportEvent(ctx context.Context, userID, starID int64, eventType string) (*pb.ReportEventResponse, error)
|
ReportEvent(ctx context.Context, userID, starID int64, eventType string) (*pb.ReportEventResponse, error)
|
||||||
|
// ProcessTaskEvent 每日任务完成引擎(spec §4 单一隔离单元)。
|
||||||
|
// 同时被 MQ consumer + ReportEvent handler 调用;返回结果供 ReportEvent 回填 RPC 响应。
|
||||||
|
ProcessTaskEvent(ctx context.Context, userID, starID int64, eventType string) (*TaskEventResult, error)
|
||||||
ClaimDailyTask(ctx context.Context, userID, starID int64, taskKey string) (*pb.ClaimDailyTaskResponse, error)
|
ClaimDailyTask(ctx context.Context, userID, starID int64, taskKey string) (*pb.ClaimDailyTaskResponse, error)
|
||||||
ClaimAllDailyTasks(ctx context.Context, userID, starID int64) (*pb.ClaimAllDailyTasksResponse, error)
|
ClaimAllDailyTasks(ctx context.Context, userID, starID int64) (*pb.ClaimAllDailyTasksResponse, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TaskEventResult ProcessTaskEvent 的返回结果。
|
||||||
|
//
|
||||||
|
// CompletedTaskKeys: 本次事件导致 status 变为 "completed" 的 task_key 列表
|
||||||
|
// (可能 0~N 个,spec §4 F5 多命中:全局任务 + star 专属任务叠加)。
|
||||||
|
type TaskEventResult struct {
|
||||||
|
CompletedTaskKeys []string
|
||||||
|
}
|
||||||
|
|
||||||
// dailyTaskService 每日任务Service实现
|
// dailyTaskService 每日任务Service实现
|
||||||
type dailyTaskService struct {
|
type dailyTaskService struct {
|
||||||
dailyRepo repository.DailyTaskRepository
|
dailyRepo repository.DailyTaskRepository
|
||||||
@ -51,7 +62,7 @@ func (s *dailyTaskService) GetDailyTasks(ctx context.Context, userID, starID int
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取所有活跃的每日任务定义
|
// 获取所有活跃的每日任务定义
|
||||||
definitions, err := s.dailyRepo.ListActiveDailyTaskDefinitions(starID)
|
definitions, err := s.dailyRepo.ListActiveDailyTaskDefinitions(starID, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Logger.Error("GetDailyTasks: failed to list active definitions",
|
logger.Logger.Error("GetDailyTasks: failed to list active definitions",
|
||||||
zap.Int64("star_id", starID),
|
zap.Int64("star_id", starID),
|
||||||
@ -96,72 +107,116 @@ func (s *dailyTaskService) GetDailyTasks(ctx context.Context, userID, starID int
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReportEvent 处理用户事件上报
|
// ReportEvent 处理用户事件上报(方案 A:委托 ProcessTaskEvent 引擎)
|
||||||
|
//
|
||||||
|
// 本方法不再自己做 def.TaskKey == eventType 内联匹配(spec §4 单一隔离单元);
|
||||||
|
// 改为调 ProcessTaskEvent 引擎完成匹配+累加+状态机转移,自身仅负责把
|
||||||
|
// TaskEventResult 回填到 ReportEventResponse 协议字段(spec §4.1 F1)。
|
||||||
func (s *dailyTaskService) ReportEvent(ctx context.Context, userID, starID int64, eventType string) (*pb.ReportEventResponse, error) {
|
func (s *dailyTaskService) ReportEvent(ctx context.Context, userID, starID int64, eventType string) (*pb.ReportEventResponse, error) {
|
||||||
logger.Logger.Info("ReportEvent",
|
logger.Logger.Info("ReportEvent",
|
||||||
zap.Int64("user_id", userID),
|
zap.Int64("user_id", userID),
|
||||||
zap.Int64("star_id", starID),
|
zap.Int64("star_id", starID),
|
||||||
zap.String("event_type", eventType))
|
zap.String("event_type", eventType))
|
||||||
|
|
||||||
// 获取所有活跃的每日任务定义,查找匹配的任务
|
result, err := s.ProcessTaskEvent(ctx, userID, starID, eventType)
|
||||||
definitions, err := s.dailyRepo.ListActiveDailyTaskDefinitions(starID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &pb.ReportEventResponse{Base: &pbCommon.BaseResponse{Code: uint32(codes.Internal)}, Success: false}, err
|
return &pb.ReportEventResponse{
|
||||||
|
Base: &pbCommon.BaseResponse{Code: uint32(codes.Internal)},
|
||||||
|
Success: false,
|
||||||
|
}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
success := true
|
taskKey := ""
|
||||||
for _, def := range definitions {
|
if len(result.CompletedTaskKeys) > 0 {
|
||||||
// 检查事件类型是否匹配任务要求
|
taskKey = result.CompletedTaskKeys[0]
|
||||||
// TODO: 根据实际业务逻辑判断事件与任务的匹配关系
|
}
|
||||||
// 这里简化处理:假设 taskKey 就是事件类型
|
return &pb.ReportEventResponse{
|
||||||
if def.TaskKey != eventType {
|
Base: &pbCommon.BaseResponse{Code: uint32(codes.OK)},
|
||||||
continue
|
Success: true,
|
||||||
}
|
TaskKey: taskKey,
|
||||||
|
TaskCompleted: len(result.CompletedTaskKeys) > 0,
|
||||||
|
Message: "任务完成",
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// 获取或创建进度
|
// ProcessTaskEvent 每日任务完成引擎(spec §4 单一隔离单元)
|
||||||
|
//
|
||||||
|
// 输入 {userID, starID, eventType},返回本次事件导致 completed 的 task_key 列表。
|
||||||
|
// 步骤(spec §4.3):
|
||||||
|
// 1. 查定义:trigger_event=eventType AND is_active=true AND (star_id=? OR star_id IS NULL)
|
||||||
|
// 2. 逐个 GetOrCreateDailyProgress;status=completed/claimed → 跳过(当天幂等)
|
||||||
|
// 3. IncrementProgress 事务内 +1(仅 status='pending' 才生效)
|
||||||
|
// 4. progress.Progress >= def.TargetCount → status="completed" + completed_at=now
|
||||||
|
// 5. UpdateDailyProgress 持久化;累积完成 task_key 到 result
|
||||||
|
//
|
||||||
|
// 调用链:
|
||||||
|
// - MQ consumer(异步,主路径):忽略返回值只关心 error
|
||||||
|
// - ReportEvent handler(同步,兜底):从 result 回填 ReportEventResponse
|
||||||
|
func (s *dailyTaskService) ProcessTaskEvent(ctx context.Context, userID, starID int64, eventType string) (*TaskEventResult, error) {
|
||||||
|
logger.Logger.Info("ProcessTaskEvent",
|
||||||
|
zap.Int64("user_id", userID),
|
||||||
|
zap.Int64("star_id", starID),
|
||||||
|
zap.String("event_type", eventType))
|
||||||
|
|
||||||
|
definitions, err := s.dailyRepo.ListActiveDailyTaskDefinitions(starID, eventType)
|
||||||
|
if err != nil {
|
||||||
|
logger.Logger.Error("ProcessTaskEvent: failed to list active definitions",
|
||||||
|
zap.String("event_type", eventType), zap.Error(err))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result := &TaskEventResult{}
|
||||||
|
for _, def := range definitions {
|
||||||
|
// 步骤 2:GetOrCreate 进度
|
||||||
progress, err := s.dailyRepo.GetOrCreateDailyProgress(userID, starID, def.TaskKey, def)
|
progress, err := s.dailyRepo.GetOrCreateDailyProgress(userID, starID, def.TaskKey, def)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Logger.Error("ReportEvent: failed to get or create progress",
|
logger.Logger.Error("ProcessTaskEvent: get/create progress failed",
|
||||||
zap.Int64("user_id", userID),
|
zap.Int64("user_id", userID),
|
||||||
zap.String("task_key", def.TaskKey),
|
zap.String("task_key", def.TaskKey),
|
||||||
zap.Error(err))
|
zap.Error(err))
|
||||||
success = false
|
continue // 单条失败不影响其他任务
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果已完成或已领取,跳过
|
// 步骤 2 续:已完成/已领取跳过(当天幂等)
|
||||||
if progress.Status == "completed" || progress.Status == "claimed" {
|
if progress.Status == "completed" || progress.Status == "claimed" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新进度为完成
|
// 步骤 3:事务内 +1
|
||||||
now := time.Now().UnixMilli()
|
if err := s.dailyRepo.IncrementProgress(progress, def); err != nil {
|
||||||
progress.Status = "completed"
|
logger.Logger.Error("ProcessTaskEvent: increment progress failed",
|
||||||
progress.CompletedAt = &now
|
|
||||||
|
|
||||||
if err := s.dailyRepo.UpdateDailyProgress(progress); err != nil {
|
|
||||||
logger.Logger.Error("ReportEvent: failed to update progress",
|
|
||||||
zap.Int64("user_id", userID),
|
zap.Int64("user_id", userID),
|
||||||
zap.String("task_key", def.TaskKey),
|
zap.String("task_key", def.TaskKey),
|
||||||
zap.Error(err))
|
zap.Error(err))
|
||||||
success = false
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Logger.Info("ReportEvent: task completed",
|
// 步骤 4:判断是否到达 target_count(spec §4.3 第 3-4 步)
|
||||||
zap.Int64("user_id", userID),
|
if progress.Progress >= def.TargetCount {
|
||||||
zap.String("task_key", def.TaskKey))
|
now := time.Now().UnixMilli()
|
||||||
|
progress.Status = "completed"
|
||||||
|
progress.CompletedAt = &now
|
||||||
|
|
||||||
return &pb.ReportEventResponse{
|
// 步骤 5:保存最终状态
|
||||||
Base: &pbCommon.BaseResponse{Code: uint32(codes.OK)},
|
if err := s.dailyRepo.UpdateDailyProgress(progress); err != nil {
|
||||||
Success: true,
|
logger.Logger.Error("ProcessTaskEvent: update progress to completed failed",
|
||||||
TaskKey: def.TaskKey,
|
zap.Int64("user_id", userID),
|
||||||
TaskCompleted: true,
|
zap.String("task_key", def.TaskKey),
|
||||||
Message: "任务完成",
|
zap.Error(err))
|
||||||
}, nil
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
result.CompletedTaskKeys = append(result.CompletedTaskKeys, def.TaskKey)
|
||||||
|
logger.Logger.Info("ProcessTaskEvent: task completed",
|
||||||
|
zap.Int64("user_id", userID),
|
||||||
|
zap.Int64("star_id", starID),
|
||||||
|
zap.String("task_key", def.TaskKey),
|
||||||
|
zap.Int("progress", progress.Progress),
|
||||||
|
zap.Int("target_count", def.TargetCount))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &pb.ReportEventResponse{Base: &pbCommon.BaseResponse{Code: uint32(codes.OK)}, Success: success}, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClaimDailyTask 领取单个每日任务奖励
|
// ClaimDailyTask 领取单个每日任务奖励
|
||||||
@ -197,7 +252,7 @@ func (s *dailyTaskService) ClaimDailyTask(ctx context.Context, userID, starID in
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取任务定义以获取奖励信息
|
// 获取任务定义以获取奖励信息
|
||||||
definitions, err := s.dailyRepo.ListActiveDailyTaskDefinitions(starID)
|
definitions, err := s.dailyRepo.ListActiveDailyTaskDefinitions(starID, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &pb.ClaimDailyTaskResponse{Base: &pbCommon.BaseResponse{Code: uint32(codes.Internal)}, Success: false}, err
|
return &pb.ClaimDailyTaskResponse{Base: &pbCommon.BaseResponse{Code: uint32(codes.Internal)}, Success: false}, err
|
||||||
}
|
}
|
||||||
@ -285,7 +340,7 @@ func (s *dailyTaskService) ClaimAllDailyTasks(ctx context.Context, userID, starI
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取所有活跃的每日任务定义
|
// 获取所有活跃的每日任务定义
|
||||||
definitions, err := s.dailyRepo.ListActiveDailyTaskDefinitions(starID)
|
definitions, err := s.dailyRepo.ListActiveDailyTaskDefinitions(starID, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Logger.Error("ClaimAllDailyTasks: failed to list definitions",
|
logger.Logger.Error("ClaimAllDailyTasks: failed to list definitions",
|
||||||
zap.Int64("star_id", starID),
|
zap.Int64("star_id", starID),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user