重构 #4
| @@ -10,9 +10,12 @@ import ( | |||||||
|  |  | ||||||
| // 定义仓库层可导出的公共错误 | // 定义仓库层可导出的公共错误 | ||||||
| var ( | var ( | ||||||
| 	ErrUpdateWithInvalidRoot = errors.New("更新操作的目标根计划无效或ID为0") | 	ErrUpdateWithInvalidRoot   = errors.New("更新操作的目标根计划无效或ID为0") | ||||||
| 	ErrNewSubPlanInUpdate    = errors.New("计划树中包含一个ID为0的新子计划,更新操作只允许关联已存在的计划") | 	ErrNewSubPlanInUpdate      = errors.New("计划树中包含一个ID为0的新子计划,更新操作只允许关联已存在的计划") | ||||||
| 	ErrNodeDoesNotExist      = errors.New("计划树中包含一个或多个在数据库中不存在的计划") | 	ErrNodeDoesNotExist        = errors.New("计划树中包含一个或多个在数据库中不存在的计划") | ||||||
|  | 	ErrCreateWithNonZeroID     = errors.New("创建操作的计划ID必须为0") | ||||||
|  | 	ErrSubPlanIDIsZeroOnCreate = errors.New("子计划ID为0,创建操作只允许关联已存在的计划") | ||||||
|  | 	ErrMixedContent            = errors.New("计划不能同时包含任务和子计划") | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // PlanRepository 定义了与计划模型相关的数据库操作接口 | // PlanRepository 定义了与计划模型相关的数据库操作接口 | ||||||
| @@ -24,6 +27,8 @@ type PlanRepository interface { | |||||||
| 	GetBasicPlanByID(id uint) (*models.Plan, error) | 	GetBasicPlanByID(id uint) (*models.Plan, error) | ||||||
| 	// GetPlanByID 根据ID获取计划,包含子计划和任务详情 | 	// GetPlanByID 根据ID获取计划,包含子计划和任务详情 | ||||||
| 	GetPlanByID(id uint) (*models.Plan, error) | 	GetPlanByID(id uint) (*models.Plan, error) | ||||||
|  | 	// Create 创建一个新的计划 | ||||||
|  | 	Create(plan *models.Plan) error | ||||||
| 	// UpdatePlan 更新计划,包括子计划和任务 | 	// UpdatePlan 更新计划,包括子计划和任务 | ||||||
| 	UpdatePlan(plan *models.Plan) error | 	UpdatePlan(plan *models.Plan) error | ||||||
| } | } | ||||||
| @@ -107,6 +112,76 @@ func (r *gormPlanRepository) GetPlanByID(id uint) (*models.Plan, error) { | |||||||
| 	return &plan, nil | 	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 是更新计划的公共入口点 | // UpdatePlan 是更新计划的公共入口点 | ||||||
| func (r *gormPlanRepository) UpdatePlan(plan *models.Plan) error { | func (r *gormPlanRepository) UpdatePlan(plan *models.Plan) error { | ||||||
| 	return r.db.Transaction(func(tx *gorm.DB) 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 | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /// ABC | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user