重构 #4
| @@ -13,6 +13,9 @@ var ( | ||||
| 	ErrUpdateWithInvalidRoot   = errors.New("更新操作的目标根计划无效或ID为0") | ||||
| 	ErrNewSubPlanInUpdate      = errors.New("计划树中包含一个ID为0的新子计划,更新操作只允许关联已存在的计划") | ||||
| 	ErrNodeDoesNotExist        = errors.New("计划树中包含一个或多个在数据库中不存在的计划") | ||||
| 	ErrCreateWithNonZeroID     = errors.New("创建操作的计划ID必须为0") | ||||
| 	ErrSubPlanIDIsZeroOnCreate = errors.New("子计划ID为0,创建操作只允许关联已存在的计划") | ||||
| 	ErrMixedContent            = errors.New("计划不能同时包含任务和子计划") | ||||
| ) | ||||
|  | ||||
| // PlanRepository 定义了与计划模型相关的数据库操作接口 | ||||
| @@ -24,6 +27,8 @@ type PlanRepository interface { | ||||
| 	GetBasicPlanByID(id uint) (*models.Plan, error) | ||||
| 	// GetPlanByID 根据ID获取计划,包含子计划和任务详情 | ||||
| 	GetPlanByID(id uint) (*models.Plan, error) | ||||
| 	// Create 创建一个新的计划 | ||||
| 	Create(plan *models.Plan) error | ||||
| 	// UpdatePlan 更新计划,包括子计划和任务 | ||||
| 	UpdatePlan(plan *models.Plan) error | ||||
| } | ||||
| @@ -107,6 +112,76 @@ func (r *gormPlanRepository) GetPlanByID(id uint) (*models.Plan, error) { | ||||
| 	return &plan, nil | ||||
| } | ||||
|  | ||||
| // Create 创建一个新的计划 | ||||
| func (r *gormPlanRepository) Create(plan *models.Plan) error { | ||||
| 	return r.db.Transaction(func(tx *gorm.DB) error { | ||||
| 		// 1. 前置校验 | ||||
| 		if plan.ID != 0 { | ||||
| 			return ErrCreateWithNonZeroID | ||||
| 		} | ||||
|  | ||||
| 		// 检查是否同时包含任务和子计划 | ||||
| 		if len(plan.Tasks) > 0 && len(plan.SubPlans) > 0 { | ||||
| 			return ErrMixedContent | ||||
| 		} | ||||
|  | ||||
| 		// 如果是子计划类型,验证所有子计划是否存在且ID不为0 | ||||
| 		if plan.ContentType == models.PlanContentTypeSubPlans { | ||||
| 			childIDsToValidate := make(map[uint]bool) | ||||
| 			for _, subPlanLink := range plan.SubPlans { | ||||
| 				if subPlanLink.ChildPlan == nil || subPlanLink.ChildPlan.ID == 0 { | ||||
| 					return ErrSubPlanIDIsZeroOnCreate | ||||
| 				} | ||||
| 				childIDsToValidate[subPlanLink.ChildPlan.ID] = true | ||||
| 			} | ||||
|  | ||||
| 			var ids []uint | ||||
| 			for id := range childIDsToValidate { | ||||
| 				ids = append(ids, id) | ||||
| 			} | ||||
|  | ||||
| 			if len(ids) > 0 { | ||||
| 				var count int64 | ||||
| 				if err := tx.Model(&models.Plan{}).Where("id IN ?", ids).Count(&count).Error; err != nil { | ||||
| 					return fmt.Errorf("验证子计划存在性失败: %w", err) | ||||
| 				} | ||||
| 				if int(count) != len(ids) { | ||||
| 					return ErrNodeDoesNotExist | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// 2. 创建根计划 | ||||
| 		// GORM 会自动处理关联的 Tasks (如果 ContentType 是 tasks 且 Task.ID 为 0) | ||||
| 		if err := tx.Create(plan).Error; err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		// 3. 处理子计划关联 (如果 ContentType 是 sub_plans) | ||||
| 		// GORM 不会自动创建 SubPlan 关联记录,需要手动处理 | ||||
| 		if plan.ContentType == models.PlanContentTypeSubPlans { | ||||
| 			// 收集所有 SubPlan 关联,设置 ParentPlanID | ||||
| 			var subPlanLinksToCreate []models.SubPlan | ||||
| 			for i := range plan.SubPlans { | ||||
| 				plan.SubPlans[i].ParentPlanID = plan.ID // 设置父计划ID | ||||
| 				// 确保 ChildPlanID 被正确设置,因为 ChildPlan 对象可能只在内存中 | ||||
| 				if plan.SubPlans[i].ChildPlanID == 0 && plan.SubPlans[i].ChildPlan != nil { | ||||
| 					plan.SubPlans[i].ChildPlanID = plan.SubPlans[i].ChildPlan.ID | ||||
| 				} | ||||
| 				subPlanLinksToCreate = append(subPlanLinksToCreate, plan.SubPlans[i]) | ||||
| 			} | ||||
|  | ||||
| 			// 批量创建 SubPlan 关联记录 | ||||
| 			if len(subPlanLinksToCreate) > 0 { | ||||
| 				if err := tx.CreateInBatches(subPlanLinksToCreate, 100).Error; err != nil { // 批量大小100 | ||||
| 					return err | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		return nil | ||||
| 	}) | ||||
| } | ||||
|  | ||||
| // UpdatePlan 是更新计划的公共入口点 | ||||
| func (r *gormPlanRepository) UpdatePlan(plan *models.Plan) error { | ||||
| 	return r.db.Transaction(func(tx *gorm.DB) error { | ||||
| @@ -299,3 +374,5 @@ func (r *gormPlanRepository) reconcileSubPlans(tx *gorm.DB, plan *models.Plan) e | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| /// ABC | ||||
|   | ||||
		Reference in New Issue
	
	Block a user