From c6ba03c4072a931474b0e8d4177de5296b59e348 Mon Sep 17 00:00:00 2001 From: hy001 Date: Sat, 9 May 2026 14:12:07 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=90=8E=E5=8F=B0=E4=BF=9D?= =?UTF-8?q?=E5=AD=98=E6=97=A0=E6=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/service/taskcenter/admin.go | 46 ++++++++++++++++- .../service/taskcenter/taskcenter_test.go | 50 +++++++++++++++++++ 2 files changed, 94 insertions(+), 2 deletions(-) diff --git a/internal/service/taskcenter/admin.go b/internal/service/taskcenter/admin.go index 5d1c836..a6ee2cf 100644 --- a/internal/service/taskcenter/admin.go +++ b/internal/service/taskcenter/admin.go @@ -83,6 +83,11 @@ func (s *Service) SaveConfig(ctx context.Context, req SaveConfigRequest) (*Confi if err != nil { return nil, err } + replaceConditionJumps := saveConditionJumps + if !saveConditionJumps { + conditionJumps = buildConditionJumpConfigRowsFromTasks(tasks) + saveConditionJumps = len(conditionJumps) > 0 + } if saveConditionJumps { applyConditionJumpsToTasks(tasks, conditionJumps) } @@ -134,7 +139,7 @@ func (s *Service) SaveConfig(ctx context.Context, req SaveConfigRequest) (*Confi } if saveConditionJumps { - if err := s.saveConditionJumpConfigsTx(tx, configRow, category, conditionJumps, now); err != nil { + if err := s.saveConditionJumpConfigsTx(tx, configRow, category, conditionJumps, now, replaceConditionJumps); err != nil { return err } } @@ -414,7 +419,7 @@ func defaultConditionJump(conditionType string) (string, string) { } } -func (s *Service) saveConditionJumpConfigsTx(tx *gorm.DB, configRow model.TaskCenterConfig, category string, rows []model.TaskCenterConditionJumpConfig, now time.Time) error { +func (s *Service) saveConditionJumpConfigsTx(tx *gorm.DB, configRow model.TaskCenterConfig, category string, rows []model.TaskCenterConditionJumpConfig, now time.Time, deleteMissing bool) error { var existingRows []model.TaskCenterConditionJumpConfig if err := tx. Where("config_id = ? AND task_category = ?", configRow.ID, category). @@ -459,6 +464,9 @@ func (s *Service) saveConditionJumpConfigsTx(tx *gorm.DB, configRow model.TaskCe keepIDs = append(keepIDs, rows[index].ID) } + if !deleteMissing { + return nil + } deleteQuery := tx.Where("config_id = ? AND task_category = ?", configRow.ID, category) if len(keepIDs) > 0 { deleteQuery = deleteQuery.Where("id NOT IN ?", keepIDs) @@ -466,6 +474,40 @@ func (s *Service) saveConditionJumpConfigsTx(tx *gorm.DB, configRow model.TaskCe return deleteQuery.Delete(&model.TaskCenterConditionJumpConfig{}).Error } +func buildConditionJumpConfigRowsFromTasks(tasks []model.TaskCenterTaskConfig) []model.TaskCenterConditionJumpConfig { + seenConditions := make(map[string]struct{}, len(tasks)) + rows := make([]model.TaskCenterConditionJumpConfig, 0, len(tasks)) + for _, task := range tasks { + conditionType := strings.ToUpper(strings.TrimSpace(task.ConditionType)) + if conditionType == "" { + continue + } + if _, exists := seenConditions[conditionType]; exists { + continue + } + jumpType := normalizeJumpType(task.JumpType) + jumpPage := strings.TrimSpace(task.JumpPage) + if jumpType == "NONE" && jumpPage == "" { + jumpType, jumpPage = defaultConditionJump(conditionType) + } + rows = append(rows, model.TaskCenterConditionJumpConfig{ + TaskCategory: task.TaskCategory, + ConditionType: conditionType, + JumpType: jumpType, + JumpPage: normalizeConditionJumpPage(jumpType, jumpPage), + SortOrder: task.SortOrder, + }) + seenConditions[conditionType] = struct{}{} + } + sort.SliceStable(rows, func(i, j int) bool { + if rows[i].SortOrder == rows[j].SortOrder { + return rows[i].ConditionType < rows[j].ConditionType + } + return rows[i].SortOrder < rows[j].SortOrder + }) + return rows +} + func (s *Service) loadTaskConfigs(ctx context.Context, configID int64, category string, enabledOnly bool) ([]model.TaskCenterTaskConfig, error) { if configID <= 0 { return []model.TaskCenterTaskConfig{}, nil diff --git a/internal/service/taskcenter/taskcenter_test.go b/internal/service/taskcenter/taskcenter_test.go index 5fcc6ea..5be61fa 100644 --- a/internal/service/taskcenter/taskcenter_test.go +++ b/internal/service/taskcenter/taskcenter_test.go @@ -268,6 +268,56 @@ func TestConditionJumpConfigAppliesToTasks(t *testing.T) { } } +func TestSaveConfigDerivesConditionJumpsWhenPayloadOmitted(t *testing.T) { + service, _ := newTestService(t, nil) + ctx := context.Background() + + resp, err := service.SaveConfig(ctx, SaveConfigRequest{ + SysOrigin: "LIKEI", + Enabled: true, + Timezone: "Asia/Riyadh", + TaskCategory: TaskCategoryDaily, + Tasks: []SaveTaskConfigInput{ + { + TaskCode: "DAILY_MIC", + Enabled: true, + TaskName: "Mic task", + ConditionType: "MIC_DURATION_SECONDS", + TargetValue: 60, + TargetUnit: "second", + RewardGold: 100, + JumpType: "APP_ROUTE", + JumpPage: "/task/mic-guide", + SortOrder: 10, + }, + { + TaskCode: "DAILY_GIFT", + Enabled: true, + TaskName: "Gift task", + ConditionType: "GIFT_CONSUME_GOLD", + TargetValue: 1, + TargetUnit: "gold", + RewardGold: 100, + JumpType: "ROOM_RANDOM", + JumpPage: "/room?source=custom", + SortOrder: 20, + }, + }, + }) + if err != nil { + t.Fatalf("SaveConfig() error = %v", err) + } + if len(resp.ConditionJumps) != 2 { + t.Fatalf("condition jumps = %+v, want derived rows", resp.ConditionJumps) + } + if resp.ConditionJumps[0].JumpPage != "/task/mic-guide" || resp.ConditionJumps[1].JumpPage != "/room?source=custom" { + t.Fatalf("condition jump pages = %+v, want task jump fields persisted", resp.ConditionJumps) + } + if resp.Tasks[0].JumpType != "APP_ROUTE" || resp.Tasks[0].JumpPage != "/task/mic-guide" { + t.Fatalf("mic task jump = %s %s, want APP_ROUTE /task/mic-guide", resp.Tasks[0].JumpType, resp.Tasks[0].JumpPage) + } +} + func TestResolveJumpPageUsesRechargeRouteForRechargeTask(t *testing.T) { tests := []struct { name string