diff --git a/internal/core/application.go b/internal/core/application.go index 7ce4bce..84b265f 100644 --- a/internal/core/application.go +++ b/internal/core/application.go @@ -122,7 +122,13 @@ func initStorage(cfg config.DatabaseConfig, logger *logs.Logger) (database.Stora // 执行数据库迁移 // 这里需要添加所有需要自动迁移的模型 - var dbModels = []interface{}{&models.User{}, &models.Device{}} + var dbModels = []interface{}{ + &models.User{}, + &models.Device{}, + &models.Plan{}, + &models.SubPlan{}, + &models.Task{}, + } if err := storage.Migrate(dbModels...); err != nil { return nil, fmt.Errorf("数据库迁移失败: %w", err) } diff --git a/internal/infra/models/plan.go b/internal/infra/models/plan.go new file mode 100644 index 0000000..ea7c419 --- /dev/null +++ b/internal/infra/models/plan.go @@ -0,0 +1,86 @@ +package models + +import ( + "gorm.io/datatypes" + "gorm.io/gorm" +) + +// PlanExecutionType 定义了计划的执行类型 +type PlanExecutionType string + +const ( + PlanExecutionTypeAutomatic PlanExecutionType = "automatic" // 自动执行 (包含定时和循环) + PlanExecutionTypeManual PlanExecutionType = "manual" // 手动执行 +) + +// PlanContentType 定义了计划包含的内容类型 +type PlanContentType string + +const ( + PlanContentTypeSubPlans PlanContentType = "sub_plans" // 计划包含子计划 + PlanContentTypeTasks PlanContentType = "tasks" // 计划包含任务 +) + +// TaskType 定义了任务的类型,每个类型可以对应 task 包中的一个具体动作 +type TaskType string + +const ( + TaskTypeWaiting TaskType = "waiting" // 等待任务 +) + +// Plan 代表系统中的一个计划,可以包含子计划或任务 +type Plan struct { + gorm.Model + + Name string `gorm:"not null" json:"name"` + Description string `json:"description"` + ExecutionType PlanExecutionType `gorm:"not null" json:"execution_type"` + + // 针对 PlanExecutionTypeAutomatic,使用 Cron 表达式定义调度规则 + CronExpression string `json:"cron_expression"` + + // ContentType 标识此计划是包含子计划还是任务。 + // 应用程序层应确保只设置其中一种类型的内容。 + ContentType PlanContentType `gorm:"not null" json:"content_type"` + + // SubPlans 直接与此计划关联的子计划。仅当 ContentType 为 PlanContentTypeSubPlans 时有效。 + SubPlans []SubPlan `gorm:"foreignKey:ParentPlanID" json:"sub_plans"` + // Tasks 直接与此计划关联的任务。仅当 ContentType 为 PlanContentTypeTasks 时有效。 + Tasks []Task `gorm:"foreignKey:PlanID" json:"tasks"` +} + +// TableName 自定义 GORM 使用的数据库表名 +func (Plan) TableName() string { + return "plans" +} + +// SubPlan 代表作为另一个计划一部分的子计划,具有执行顺序 +type SubPlan struct { + gorm.Model + + ParentPlanID uint `gorm:"not null;index" json:"parent_plan_id"` // 父计划的ID + ChildPlanID uint `gorm:"not null;index" json:"child_plan_id"` // 子计划的ID (它本身也是一个 Plan) + Order int `gorm:"not null" json:"order"` // 在父计划中的执行顺序 +} + +// TableName 自定义 GORM 使用的数据库表名 +func (SubPlan) TableName() string { + return "sub_plans" +} + +// Task 代表计划中的一个任务,具有执行顺序 +type Task struct { + gorm.Model + + PlanID uint `gorm:"not null;index" json:"plan_id"` // 此任务所属计划的ID + Name string `gorm:"not null" json:"name"` + Description string `json:"description"` + Order int `gorm:"not null" json:"order"` // 在计划中的执行顺序 + Type TaskType `gorm:"not null" json:"type"` // 任务的类型,对应 task 包中的具体动作 + Parameters datatypes.JSON `json:"parameters"` // 任务特定参数的JSON (例如: 设备ID, 值) +} + +// TableName 自定义 GORM 使用的数据库表名 +func (Task) TableName() string { + return "tasks" +}