package plant import ( "sundynix-go/global" common "sundynix-go/model/commom/request" "sundynix-go/model/plant" plantReq "sundynix-go/model/plant/request" plantRes "sundynix-go/model/plant/response" "sundynix-go/model/system" "sundynix-go/utils/timer" "time" "gorm.io/gorm" ) type MyPlantService struct{} var MyPlantServiceApp = new(MyPlantService) // AddPlant 添加植物 func (s *MyPlantService) AddPlant(req plantReq.CreateMyPlant, id string) error { err := global.DB.Transaction(func(tx *gorm.DB) error { //1. 验证oss是否存在 var ossList []*system.Oss err := tx.Where("id in ?", req.OssIds).Find(&ossList).Error if err != nil { return err } bgTime := timer.GetZeroTime() //2. 处理养护计划 var carePlans []*plant.CarePlan for _, v := range req.CarePlans { carePlans = append(carePlans, &plant.CarePlan{ UserId: id, Name: v.Name, Icon: v.Icon, Period: v.Period, }) } //3.保存数据 myPlant := plant.MyPlant{ UserId: id, Name: req.Name, PlantTime: bgTime, Status: 1, Placement: req.Placement, PotMaterial: req.PotMaterial, PotSize: req.PotSize, Sunlight: req.Sunlight, PlantingMaterial: req.PlantingMaterial, CarePlans: carePlans, } err = tx.Create(&myPlant).Error if err != nil { return err } //4.处理图片关系 if len(ossList) > 0 { var relations []map[string]interface{} for _, oss := range ossList { relations = append(relations, map[string]interface{}{ "my_plant_id": myPlant.Id, "oss_id": oss.Id, }) } err = tx.Table("sundynix_my_plant_oss").Create(relations).Error if err != nil { return err } } return nil }) return err } // PlantPage 植物列表 func (s *MyPlantService) PlantPage(req common.PageInfo, userId string) (list interface{}, total int64, err error) { limit := req.PageSize offset := req.PageSize * (req.Current - 1) db := global.DB.Model(&plant.MyPlant{}).Preload("ImgList", func(db *gorm.DB) *gorm.DB { return db.Order("created_at desc") }) var myPlants []*plant.MyPlant db = db.Where("user_id = ?", userId) err = db.Count(&total).Error if err != nil { return } err = db.Limit(limit).Offset(offset).Order("created_at desc").Find(&myPlants).Error return myPlants, total, err } // PlantDetail 植物详情 func (s *MyPlantService) PlantDetail(id string) (p plant.MyPlant, err error) { var res plant.MyPlant err = global.DB.Where("id = ?", id). Preload("ImgList", func(db *gorm.DB) *gorm.DB { return db.Order("created_at desc") }). Preload("CarePlans"). Preload("CareRecords", func(db *gorm.DB) *gorm.DB { return db.Order("created_at desc") }). Preload("GrowthRecords", func(db *gorm.DB) *gorm.DB { return db.Preload("ImgList", func(db *gorm.DB) *gorm.DB { return db.Order("created_at desc") }).Order("created_at desc") }). First(&res).Error //不存在的时候不要返回错误,而是返回nil if err != nil { return res, err } return res, nil } func (s *MyPlantService) UpdatePlant(req plantReq.UpdateMyPlant) error { return global.DB.Transaction(func(tx *gorm.DB) error { var myPlant plant.MyPlant err := tx.Where("id = ?", req.Id).First(&myPlant).Error if err != nil { return err } // 以map形式更新 先构建map updateMap := map[string]interface{}{ "name": req.Name, "placement": req.Placement, "planting_material": req.PlantingMaterial, "pot_material": req.PotMaterial, "pot_size": req.PotSize, "sunlight": req.Sunlight, } //1.修改基本信息 err = tx.Model(&plant.MyPlant{}).Where("id = ?", req.Id).Updates(updateMap).Error if err != nil { return err } //2.修改计划 if len(req.CarePlans) > 0 { today := timer.GetZeroTime() for _, plan := range req.CarePlans { err = tx.Model(&plant.CarePlan{}).Where("id = ?", plan.Id).Updates(map[string]interface{}{ "icon": plan.Icon, "name": plan.Name, "period": plan.Period, }).Error if err != nil { return err } //3.重新生成任务 CarePlans 结构体中使用钩子函数自动执行 //3.1 删除旧任务 err = tx.Where("plan_id = ?", plan.Id).Unscoped().Delete(&plant.CareTask{}).Error if err != nil { return err } //3.2 创建新任务 dueDate := today.AddDate(0, 0, plan.Period) task := plant.CareTask{ UserId: myPlant.UserId, PlantId: myPlant.Id, PlanId: plan.Id, Name: plan.Name, Icon: plan.Icon, DueDate: dueDate, Status: 1, } err = tx.Create(&task).Error if err != nil { return err } } } return nil }) } // TodayTask 今日任务 func (s *MyPlantService) TodayTask(userId string) ([]plantRes.PlantTaskVO, error) { today := timer.GetZeroTime() endOfToday := today.Add(24 * time.Hour) var tasks []*plant.CareTask // 查询条件:1.未完成的任务(包含今天和以前逾期的) 2.今天已经完成的任务 err := global.DB.Where("user_id = ? AND ("+ "(status = 1 AND due_date < ?) OR "+ "(status = 2 AND completed_at >= ? AND completed_at < ?)"+ ")", userId, endOfToday, today, endOfToday). Order("due_date ASC"). Find(&tasks).Error if err != nil { return nil, err } // 2.内存处理:聚合数据 plantTaskMap := make(map[string][]*plant.CareTask) expiredMap := make(map[string]bool) var plantIds []string for _, t := range tasks { plantIds = append(plantIds, t.PlantId) plantTaskMap[t.PlantId] = append(plantTaskMap[t.PlantId], t) // 判定右上角红标:状态为待办 且 应做时间早于今天 if t.Status == 1 && t.DueDate.Before(today) { expiredMap[t.PlantId] = true } } //3.批量查询植物 var myPlants []*plant.MyPlant err = global.DB.Where("id in ?", plantIds).Preload("ImgList", func(db *gorm.DB) *gorm.DB { return db.Order("created_at desc") }).Find(&myPlants).Error if err != nil { return nil, err } //4.组装结果 var res []plantRes.PlantTaskVO for _, p := range myPlants { plantTaskVO := plantRes.PlantTaskVO{ MyPlant: p, HasExpired: expiredMap[p.Id], Tasks: plantTaskMap[p.Id], } res = append(res, plantTaskVO) } return res, nil } // CompleteTask 完成任务 func (s *MyPlantService) CompleteTask(req plantReq.CompleteTask) error { return global.DB.Transaction(func(tx *gorm.DB) error { var task plant.CareTask if err := tx.Where("id = ?", req.TaskId).First(&task).Error; err != nil { return err } //1.更新当前任务为完成 updateData := map[string]interface{}{ "status": 2, "completed_at": time.Now(), } if err := tx.Model(&task).Where("id = ?", req.TaskId).Updates(updateData).Error; err != nil { return err } //2.获取计划模版 var plan plant.CarePlan if err := tx.Where("id = ?", task.PlanId).First(&plan).Error; err != nil { return err } //3.生成下个周期的任务 today := timer.GetZeroTime() nextDueDate := today.AddDate(0, 0, plan.Period) newTask := plant.CareTask{ UserId: plan.UserId, PlantId: plan.PlantId, PlanId: plan.Id, Name: plan.Name, Icon: plan.Icon, DueDate: nextDueDate, Status: 1, } if err := tx.Create(&newTask).Error; err != nil { return err } //4.保存养护记录 record := plant.CareRecord{ UserId: plan.UserId, PlantId: plan.PlantId, PlanId: plan.Id, Name: plan.Name, Icon: plan.Icon, Remark: req.Remark, } if err := tx.Create(&record).Error; err != nil { return err } return nil }) } // DeletePlants 删除植物 func (s *MyPlantService) DeletePlants(req common.IdsReq) error { return global.DB.Transaction(func(tx *gorm.DB) error { var plants []plant.MyPlant if err := tx.Where("id in ?", req.Ids).Find(&plants).Error; err != nil { return err } // 删除图片 养护计划 养护任务 养护记录 成长记录 err := tx.Select("ImgList", "CarePlans", "CareTasks", "CareRecords").Unscoped().Delete(&plants).Error if err != nil { return err } return nil }) } // DeletePlans 删除任务 func (s *MyPlantService) DeletePlans(req common.IdsReq) error { return global.DB.Transaction(func(tx *gorm.DB) error { var plans []plant.CarePlan if err := tx.Where("id in ?", req.Ids).Find(&plans).Error; err != nil { return err } var tasks []plant.CareTask if err := tx.Where("plan_id in ?", req.Ids).Find(&tasks).Error; err != nil { return err } //1.删除计划 err := tx.Unscoped().Delete(&plans).Error if err != nil { return err } //2.删除任务 err = tx.Unscoped().Delete(&tasks).Error if err != nil { return err } return nil }) } // AddCarePlan 添加CarePlan func (s *MyPlantService) AddCarePlan(req plantReq.AddPlans) error { return global.DB.Transaction(func(tx *gorm.DB) error { for _, plan := range req.CarePlan { var myPlant plant.MyPlant err := tx.Where("id = ?", plan.PlantId).First(&myPlant).Error if err != nil { return err } //1.新增计划 newPlan := plant.CarePlan{ UserId: myPlant.UserId, PlantId: myPlant.Id, Name: plan.Name, Icon: plan.Icon, Period: plan.Period, } err = tx.Create(&newPlan).Error if err != nil { return err } //2.新增任务 today := timer.GetZeroTime() dueDate := today.AddDate(0, 0, plan.Period) task := plant.CareTask{ UserId: myPlant.UserId, PlantId: myPlant.Id, PlanId: newPlan.Id, Name: plan.Name, Icon: plan.Icon, DueDate: dueDate, Status: 1, } err = tx.Create(&task).Error if err != nil { return err } } return nil }) } // DeletePlan 删除CarePlan func (s *MyPlantService) DeletePlan(id string) error { return global.DB.Transaction(func(tx *gorm.DB) error { var plan plant.CarePlan if err := tx.Where("id = ?", id).First(&plan).Error; err != nil { return err } var tasks []plant.CareTask if err := tx.Where("plan_id = ?", plan.Id).Find(&tasks).Error; err != nil { return err } err := tx.Unscoped().Delete(&plan).Error if err != nil { return err } err = tx.Unscoped().Delete(&tasks).Error if err != nil { return err } return nil }) } // AddGrowthRecord 添加成长记录 func (s *MyPlantService) AddGrowthRecord(req plantReq.CreateGrowthRecord, userId string) error { return global.DB.Transaction(func(tx *gorm.DB) error { //1.验证图片是否存在 var ossList []*system.Oss err := tx.Where("id in ?", req.OssIds).Find(&ossList).Error if err != nil { return err } //2.保存记录 record := plant.GrowthRecord{ UserId: userId, PlantId: req.PlantId, Name: req.Name, Content: req.Content, Desc: req.Desc, Tag: req.Tag, } err = tx.Create(&record).Error if err != nil { return err } //3.保存图片关系 if len(ossList) > 0 { var relations []map[string]interface{} for _, oss := range ossList { relations = append(relations, map[string]interface{}{ "growth_record_id": record.Id, "oss_id": oss.Id, }) } err = tx.Table("sundynix_growth_record_oss").Create(relations).Error if err != nil { return err } } return nil }) }