diff --git a/internal/core/data_initializer.go b/internal/core/data_initializer.go index 044b2ad..26180f3 100644 --- a/internal/core/data_initializer.go +++ b/internal/core/data_initializer.go @@ -51,7 +51,8 @@ func (app *Application) initializeSystemPlans(ctx context.Context) error { // 1. 获取所有已存在的系统计划 existingPlans, _, err := app.Infra.repos.planRepo.ListPlans(appCtx, repository.ListPlansOptions{ - PlanType: repository.PlanTypeFilterSystem, + PlanType: repository.PlanTypeFilterSystem, + IncludeAssociations: true, }, 1, 99999) // 使用一个较大的 pageSize 来获取所有系统计划 if err != nil { return fmt.Errorf("获取现有系统计划失败: %w", err) @@ -123,11 +124,6 @@ func (app *Application) initializePeriodicSystemHealthCheckPlan(ctx context.Cont } } - // 重新设置所有任务的 ExecutionOrder - for i := range newTasks { - newTasks[i].ExecutionOrder = i + 1 - } - predefinedPlan := &models.Plan{ Name: models.PlanNamePeriodicSystemHealthCheck, Description: fmt.Sprintf("这是一个系统预定义的计划, 每 %d 分钟自动触发一次全量数据采集, 并进行阈值校验告警。", app.Config.Collection.Interval), @@ -139,6 +135,9 @@ func (app *Application) initializePeriodicSystemHealthCheckPlan(ctx context.Cont Tasks: newTasks, } + // 刷新所有任务的 ExecutionOrder + predefinedPlan.ReorderSteps() + if foundExistingPlan, ok := existingPlanMap[predefinedPlan.Name]; ok { // 如果计划存在,则进行无差别更新 logger.Infof("预定义计划 '%s' 已存在,正在进行无差别更新...", predefinedPlan.Name) @@ -196,6 +195,11 @@ func (app *Application) initializeAlarmNotificationPlan(ctx context.Context, exi }, } + err := predefinedPlan.Tasks[0].SaveParameters(app.Config.AlarmNotification.NotificationIntervals) + if err != nil { + return fmt.Errorf("序列化告警通知任务参数失败: %w", err) + } + if foundExistingPlan, ok := existingPlanMap[predefinedPlan.Name]; ok { // 如果计划存在,则进行无差别更新 logger.Infof("预定义计划 '%s' 已存在,正在进行无差别更新...", predefinedPlan.Name) diff --git a/internal/infra/repository/device_repository.go b/internal/infra/repository/device_repository.go index 72b01d6..2c1f36e 100644 --- a/internal/infra/repository/device_repository.go +++ b/internal/infra/repository/device_repository.go @@ -76,7 +76,7 @@ func (r *gormDeviceRepository) Create(ctx context.Context, device *models.Device func (r *gormDeviceRepository) FindByID(ctx context.Context, id uint32) (*models.Device, error) { repoCtx := logs.AddFuncName(ctx, r.ctx, "FindByID") var device models.Device - if err := r.db.WithContext(repoCtx).Preload("AreaController").Preload("DeviceTemplate").First(&device, id).Error; err != nil { + if err := r.db.WithContext(repoCtx).Preload("AreaControllers").Preload("DeviceTemplates").First(&device, id).Error; err != nil { return nil, err } return &device, nil @@ -111,7 +111,7 @@ func (r *gormDeviceRepository) FindByIDString(ctx context.Context, id string) (* func (r *gormDeviceRepository) ListAll(ctx context.Context) ([]*models.Device, error) { repoCtx := logs.AddFuncName(ctx, r.ctx, "ListAll") var devices []*models.Device - if err := r.db.WithContext(repoCtx).Preload("AreaController").Preload("DeviceTemplate").Find(&devices).Error; err != nil { + if err := r.db.WithContext(repoCtx).Preload("AreaControllers").Preload("DeviceTemplates").Find(&devices).Error; err != nil { return nil, err } return devices, nil @@ -121,7 +121,7 @@ func (r *gormDeviceRepository) ListAll(ctx context.Context) ([]*models.Device, e func (r *gormDeviceRepository) ListAllSensors(ctx context.Context) ([]*models.Device, error) { repoCtx := logs.AddFuncName(ctx, r.ctx, "ListAllSensors") var sensors []*models.Device - err := r.db.WithContext(repoCtx).Preload("AreaController").Preload("DeviceTemplate"). + err := r.db.WithContext(repoCtx).Preload("AreaControllers").Preload("DeviceTemplates"). Joins("JOIN device_templates ON device_templates.id = devices.device_template_id"). Where("device_templates.category = ?", models.CategorySensor). Find(&sensors).Error @@ -135,7 +135,7 @@ func (r *gormDeviceRepository) ListAllSensors(ctx context.Context) ([]*models.De func (r *gormDeviceRepository) ListByAreaControllerID(ctx context.Context, areaControllerID uint32) ([]*models.Device, error) { repoCtx := logs.AddFuncName(ctx, r.ctx, "ListByAreaControllerID") var devices []*models.Device - err := r.db.WithContext(repoCtx).Preload("AreaController").Preload("DeviceTemplate").Where("area_controller_id = ?", areaControllerID).Find(&devices).Error + err := r.db.WithContext(repoCtx).Preload("AreaControllers").Preload("DeviceTemplates").Where("area_controller_id = ?", areaControllerID).Find(&devices).Error if err != nil { return nil, err } @@ -171,7 +171,7 @@ func (r *gormDeviceRepository) Delete(ctx context.Context, id uint32) error { func (r *gormDeviceRepository) FindByAreaControllerAndPhysicalAddress(ctx context.Context, areaControllerID uint32, busNumber int, busAddress int) (*models.Device, error) { repoCtx := logs.AddFuncName(ctx, r.ctx, "FindByAreaControllerAndPhysicalAddress") var device models.Device - err := r.db.WithContext(repoCtx).Preload("AreaController").Preload("DeviceTemplate"). + err := r.db.WithContext(repoCtx).Preload("AreaControllers").Preload("DeviceTemplates"). Where("area_controller_id = ?", areaControllerID). Where("properties->>'bus_number' = ?", strconv.Itoa(busNumber)). Where("properties->>'bus_address' = ?", strconv.Itoa(busAddress)). diff --git a/internal/infra/repository/execution_log_repository.go b/internal/infra/repository/execution_log_repository.go index 9d58856..bd3ae1e 100644 --- a/internal/infra/repository/execution_log_repository.go +++ b/internal/infra/repository/execution_log_repository.go @@ -165,7 +165,7 @@ func (r *gormExecutionLogRepository) ListTaskExecutionLogs(ctx context.Context, orderBy = opts.OrderBy } // 预加载关联的Task信息 - query = query.Order(orderBy).Preload("Task") + query = query.Order(orderBy).Preload("Tasks") offset := (page - 1) * pageSize err := query.Limit(pageSize).Offset(offset).Find(&results).Error @@ -231,8 +231,8 @@ func (r *gormExecutionLogRepository) UpdateTaskExecutionLog(ctx context.Context, func (r *gormExecutionLogRepository) FindTaskExecutionLogByID(ctx context.Context, id uint32) (*models.TaskExecutionLog, error) { repoCtx := logs.AddFuncName(ctx, r.ctx, "FindTaskExecutionLogByID") var log models.TaskExecutionLog - // 使用 Preload("Task") 来确保关联的任务信息被一并加载 - err := r.db.WithContext(repoCtx).Preload("Task").First(&log, id).Error + // 使用 Preload("Tasks") 来确保关联的任务信息被一并加载 + err := r.db.WithContext(repoCtx).Preload("Tasks").First(&log, id).Error if err != nil { return nil, err } diff --git a/internal/infra/repository/pending_task_repository.go b/internal/infra/repository/pending_task_repository.go index 053a546..ba650e4 100644 --- a/internal/infra/repository/pending_task_repository.go +++ b/internal/infra/repository/pending_task_repository.go @@ -57,7 +57,7 @@ func (r *gormPendingTaskRepository) FindAllPendingTasks(ctx context.Context) ([] var tasks []models.PendingTask // 预加载 Task 以便后续访问 Task.PlanID // 预加载 TaskExecutionLog 以便后续访问 PlanExecutionLogID - err := r.db.WithContext(repoCtx).Preload("Task").Preload("TaskExecutionLog").Find(&tasks).Error + err := r.db.WithContext(repoCtx).Preload("Tasks").Preload("TaskExecutionLogs").Find(&tasks).Error return tasks, err } @@ -154,8 +154,8 @@ func (r *gormPendingTaskRepository) ClaimNextAvailableTask(ctx context.Context, return err } - // 在 Preload("Task") 时,使用 Unscoped() 来忽略 Task 的软删除状态 - if err := tx.WithContext(repoCtx).Preload("Task", func(db *gorm.DB) *gorm.DB { + // 在 Preload("Tasks") 时,使用 Unscoped() 来忽略 Task 的软删除状态 + if err := tx.WithContext(repoCtx).Preload("Tasks", func(db *gorm.DB) *gorm.DB { return db.Unscoped() }).First(&log, pendingTask.TaskExecutionLogID).Error; err != nil { return err diff --git a/internal/infra/repository/plan_repository.go b/internal/infra/repository/plan_repository.go index acf7720..5ce1474 100644 --- a/internal/infra/repository/plan_repository.go +++ b/internal/infra/repository/plan_repository.go @@ -36,6 +36,9 @@ const ( // ListPlansOptions 定义了查询计划时的可选参数 type ListPlansOptions struct { PlanType PlanTypeFilter + + // IncludeAssociations 控制是否预加载关联的任务和子计划,以便计算 HasTasks 和 HasSubPlans 字段。 + IncludeAssociations bool } // TaskListOptions 定义了查询任务时的可选参数 @@ -154,6 +157,11 @@ func (r *gormPlanRepository) ListPlans(ctx context.Context, opts ListPlansOption query = query.Where("plan_type = ?", models.PlanTypeCustom) } + // 如果需要包含关联,则进行预加载 + if opts.IncludeAssociations { + query = query.Preload("Tasks").Preload("SubPlans") + } + if err := query.Count(&total).Error; err != nil { return nil, 0, err } diff --git a/internal/infra/repository/raw_material_repository.go b/internal/infra/repository/raw_material_repository.go index 2795167..25e4c43 100644 --- a/internal/infra/repository/raw_material_repository.go +++ b/internal/infra/repository/raw_material_repository.go @@ -90,7 +90,7 @@ func (r *gormRawMaterialRepository) ListRawMaterialPurchases(ctx context.Context if opts.OrderBy != "" { orderBy = opts.OrderBy } - query = query.Order(orderBy).Preload("RawMaterial") + query = query.Order(orderBy).Preload("RawMaterials") offset := (page - 1) * pageSize err := query.Limit(pageSize).Offset(offset).Find(&results).Error @@ -178,7 +178,7 @@ func (r *gormRawMaterialRepository) ListFeedUsageRecords(ctx context.Context, op if opts.OrderBy != "" { orderBy = opts.OrderBy } - query = query.Order(orderBy).Preload("Pen").Preload("FeedFormula") + query = query.Order(orderBy).Preload("Pens").Preload("FeedFormulas") offset := (page - 1) * pageSize err := query.Limit(pageSize).Offset(offset).Find(&results).Error