package repository import ( "fmt" "git.huangwc.com/pig/pig-farm-controller/internal/infra/models" "gorm.io/gorm" ) // PlanRepository 定义了与计划模型相关的数据库操作接口 // 这是为了让业务逻辑层依赖于抽象,而不是具体的数据库实现 type PlanRepository interface { // ListBasicPlans 获取所有计划的基本信息,不包含子计划和任务详情 ListBasicPlans() ([]models.Plan, error) // GetBasicPlanByID 根据ID获取计划的基本信息,不包含子计划和任务详情 GetBasicPlanByID(id uint) (*models.Plan, error) // GetPlanByID 根据ID获取计划,包含子计划和任务详情 GetPlanByID(id uint) (*models.Plan, error) } // gormPlanRepository 是 PlanRepository 的 GORM 实现 type gormPlanRepository struct { db *gorm.DB } // NewGormPlanRepository 创建一个新的 PlanRepository GORM 实现实例 func NewGormPlanRepository(db *gorm.DB) PlanRepository { return &gormPlanRepository{ db: db, } } // ListBasicPlans 获取所有计划的基本信息,不包含子计划和任务详情 func (r *gormPlanRepository) ListBasicPlans() ([]models.Plan, error) { var plans []models.Plan // GORM 默认不会加载关联,除非使用 Preload,所以直接 Find 即可满足要求 result := r.db.Find(&plans) if result.Error != nil { return nil, result.Error } return plans, nil } // GetBasicPlanByID 根据ID获取计划的基本信息,不包含子计划和任务详情 func (r *gormPlanRepository) GetBasicPlanByID(id uint) (*models.Plan, error) { var plan models.Plan // GORM 默认不会加载关联,除非使用 Preload,所以直接 First 即可满足要求 result := r.db.First(&plan, id) if result.Error != nil { return nil, result.Error } return &plan, nil } // GetPlanByID 根据ID获取计划,包含子计划和任务详情 func (r *gormPlanRepository) GetPlanByID(id uint) (*models.Plan, error) { var plan models.Plan // 先获取基本计划信息 result := r.db.First(&plan, id) if result.Error != nil { return nil, result.Error } // 根据内容类型加载关联数据 switch plan.ContentType { case models.PlanContentTypeSubPlans: // 加载子计划引用 var subPlans []models.SubPlan result = r.db.Where("parent_plan_id = ?", plan.ID).Order("order").Find(&subPlans) if result.Error != nil { return nil, result.Error } // 递归加载每个子计划的完整信息 for i := range subPlans { // 递归调用确保子计划数据可以被获取 // 注意:SubPlan结构体中没有ChildPlan字段,所以这里只是递归获取确保数据完整性 childPlan, err := r.GetPlanByID(subPlans[i].ChildPlanID) if err != nil { return nil, err } subPlans[i].ChildPlan = childPlan } plan.SubPlans = subPlans case models.PlanContentTypeTasks: // 加载任务 result = r.db.Preload("Tasks", func(taskDB *gorm.DB) *gorm.DB { return taskDB.Order("order") }).Find(&plan) default: return nil, fmt.Errorf("未知的计划内容类型: %v; 计划ID: %v", plan.ContentType, plan.ID) } return &plan, nil }