package plant import ( "errors" "sundynix-go/global" common "sundynix-go/model/commom/request" "sundynix-go/model/plant" plantReq "sundynix-go/model/plant/request" "sundynix-go/model/system" "gorm.io/gorm" ) type WikiService struct{} var WikiServiceApp = new(WikiClassService) // CreateWiki 创建百科 func (s *WikiService) CreateWiki(req plantReq.CreateWiki) error { return global.DB.Transaction(func(tx *gorm.DB) error { //1.先模糊查询name是否存在 如果存在 则返回错误 if !errors.Is(tx.Where("name like ?", "%"+req.Name+"%").First(&plant.Wiki{}).Error, gorm.ErrRecordNotFound) { return errors.New("植物已经存在") } //2.图片 var ossList []*system.Oss err := tx.Where("id in ?", req.OssIds).Find(&ossList).Error if err != nil { return err } //3. 分类 var classes []*plant.Class err = tx.Where("id in ?", req.ClassIds).Find(&classes).Error if err != nil { return err } //4. 相关的植物 var relatedWiki []*plant.Wiki err = tx.Where("id in ?", req.RelatedWikiIds).Find(&relatedWiki).Error if err != nil { return err } //6.保存数据 wiki := plant.Wiki{ IsHot: req.IsHot, Name: req.Name, LatinName: req.LatinName, Aliases: req.Aliases, Difficulty: req.Difficulty, DistributionArea: req.DistributionArea, Stem: req.Stem, Fruit: req.Fruit, Genus: req.Genus, LifeCycle: req.LifeCycle, GrowthHabit: req.GrowthHabit, ReproductionMethod: req.ReproductionMethod, PestsDiseases: req.PestsDiseases, LightIntensity: req.LightIntensity, LightType: req.LightType, OptimalTempPeriod: req.OptimalTempPeriod, FoliageType: req.FoliageType, FoliageColor: req.FoliageColor, FoliageShape: req.FoliageShape, Height: req.Height, FloweringPeriod: req.FloweringPeriod, FloweringColor: req.FloweringColor, FloweringShape: req.FloweringShape, FlowerDiameter: req.FlowerDiameter, } err = tx.Create(&wiki).Error if err != nil { return err } //7.处理图片关系 if len(ossList) > 0 { var relations []map[string]interface{} for _, oss := range ossList { relations = append(relations, map[string]interface{}{ "wiki_id": wiki.Id, "oss_id": oss.Id, }) } err = tx.Table("sundynix_wiki_oss").Create(relations).Error if err != nil { return err } } //8.处理分类关系 if len(classes) > 0 { var classRelations []map[string]interface{} for _, class := range classes { classRelations = append(classRelations, map[string]interface{}{ "wiki_id": wiki.Id, "class_id": class.Id, }) } err = tx.Table("sundynix_wiki_class").Create(classRelations).Error if err != nil { return err } } //9.处理相关植物关系 if len(relatedWiki) > 0 { var relatedWikiRelations []map[string]interface{} for _, item := range relatedWiki { relatedWikiRelations = append(relatedWikiRelations, map[string]interface{}{ "wiki_id": wiki.Id, "related_wiki_id": item.Id, }) } err = tx.Table("sundynix_wiki_related").Create(relatedWikiRelations).Error if err != nil { return err } } return nil }) } // UpdateWiki 修改百科 func (s *WikiService) UpdateWiki(req plantReq.UpdateWiki) error { updateData := map[string]interface{}{ "name": req.Name, "latin_name": req.LatinName, "aliases": req.Aliases, "difficulty": req.Difficulty, "genus": req.Genus, "distribution_area": req.DistributionArea, "life_cycle": req.LifeCycle, "growth_habit": req.GrowthHabit, "pests_diseases": req.PestsDiseases, "light_intensity": req.LightIntensity, "light_type": req.LightType, "optimal_temp_period": req.OptimalTempPeriod, "stem": req.Stem, "fruit": req.Fruit, "foliage_type": req.FoliageType, "foliage_color": req.FoliageColor, "foliage_shape": req.FoliageShape, "height": req.Height, "flowering_period": req.FloweringPeriod, "flowering_color": req.FloweringColor, "flowering_shape": req.FloweringShape, "flower_diameter": req.FlowerDiameter, } err := global.DB.Model(&plant.Wiki{}).Where("id = ?", req.Id).Updates(updateData).Error return err } // WikiPage 分页 func (s *WikiService) WikiPage(req plantReq.WikiPage, userId string) (list interface{}, total int64, err error) { limit := req.PageSize offset := req.PageSize * (req.Current - 1) db := global.DB.Model(&plant.Wiki{}).Preload("ImgList", func(db *gorm.DB) *gorm.DB { return db.Order("created_at desc") }).Preload("Classes", func(db *gorm.DB) *gorm.DB { return db.Order("created_at desc") }) var wikis []plant.Wiki if req.Name != "" { db = db.Where("name like ?", "%"+req.Name+"%") } if req.IsHot != nil { db = db.Where("is_hot = ?", *req.IsHot) } if len(req.ClassIdIs) > 0 { db = db.Joins("inner join sundynix_wiki_class on sundynix_wiki_class.wiki_id = sundynix_wiki.id"). Where("sundynix_wiki_class.class_id IN (?)", req.ClassIdIs) } err = db.Count(&total).Error if err != nil { return } err = db.Limit(limit).Offset(offset).Order("is_hot desc,created_at desc").Find(&wikis).Error // 优化 N+1 查询 var wikiIds []string for _, v := range wikis { wikiIds = append(wikiIds, v.Id) } //批量查询当前用户的收藏 var stars []*plant.UserStar err = global.DB.Where("user_id = ? and wiki_id in ?", userId, wikiIds).Find(&stars).Error if err != nil { return } starsMap := make(map[string]bool) for _, v := range stars { starsMap[v.WikiId] = true } // 是否收藏 for i := range wikis { if starsMap[wikis[i].Id] { wikis[i].HasStar = 1 } else { wikis[i].HasStar = 0 } } return wikis, total, err } // Detail 详情 func (s *WikiService) Detail(id, userId string) (w plant.Wiki, err error) { var wiki plant.Wiki err = global.DB.Where("id = ?", id). Preload("Classes", func(db *gorm.DB) *gorm.DB { return db.Order("created_at desc") }). Preload("ImgList", func(db *gorm.DB) *gorm.DB { return db.Order("created_at desc") }). Preload("RelatedWiki", func(db *gorm.DB) *gorm.DB { return db.Order("created_at desc") }). First(&wiki).Error if err != nil { return } var stars []plant.UserStar err = global.DB.Where("user_id = ? and wiki_id = ?", userId, id).Find(&stars).Error if err != nil { return } if len(stars) > 0 { wiki.HasStar = 1 } return wiki, nil } // StarWiki 收藏 func (s *WikiService) StarWiki(userId, wikiId, class string) error { if class == "1" { return global.DB.Transaction(func(tx *gorm.DB) error { var wiki plant.Wiki err := tx.Where("id = ?", wikiId).First(&wiki).Error if err != nil { return err } //2.添加到我的收藏 star := plant.UserStar{ UserId: userId, Type: 1, WikiId: wikiId, } return tx.Create(&star).Error }) } else if class == "2" { return global.DB.Transaction(func(tx *gorm.DB) error { var star plant.UserStar err := tx.Where("wiki_id = ? and user_id = ?", wikiId, userId).First(&star).Error if err != nil { return err } //2.删除收藏 return tx.Unscoped().Delete(&star).Error }) } return nil } // UploadImg 上传图片 func (s *WikiService) UploadImg(req common.UploadOss) error { return global.DB.Transaction(func(tx *gorm.DB) error { var wiki plant.Wiki err := tx.Where("id = ?", req.Id).First(&wiki).Error if err != nil { return err } var ossList []system.Oss err = tx.Where("id in ?", req.OssIds).Find(&ossList).Error if err != nil { return err } var relations []map[string]interface{} for _, oss := range ossList { relations = append(relations, map[string]interface{}{ "wiki_id": wiki.Id, "oss_id": oss.Id, }) } //3.添加关联关系(添加引用) return global.DB.Table("sundynix_wiki_oss").Create(relations).Error }) } // DeleteWiki 删除百科 func (s *WikiService) DeleteWiki(req common.IdsReq) error { return global.DB.Transaction(func(tx *gorm.DB) error { var imgIds []string tx.Table("sundynix_wiki_oss").Where("wiki_id IN ?", req.Ids).Pluck("oss_id", &imgIds) // 3. 物理删除图片记录本身 if len(imgIds) > 0 { if err := tx.Unscoped().Where("id IN ?", imgIds).Delete(&system.Oss{}).Error; err != nil { return err } } // 2. 清理中间表记录 (解开多对多关系) // 使用 Exec 直接操作中间表比循环 Clear 快得多 if err := tx.Exec("DELETE FROM sundynix_wiki_oss WHERE wiki_id IN ?", req.Ids).Error; err != nil { return err } if err := tx.Exec("DELETE FROM sundynix_wiki_class WHERE wiki_id IN ?", req.Ids).Error; err != nil { return err } if err := tx.Exec("DELETE FROM sundynix_wiki_related WHERE wiki_id IN ? or related_wiki_id in ?", req.Ids, req.Ids).Error; err != nil { return err } //删除百科本身 return tx.Unscoped().Where("id IN ?", req.Ids).Delete(&plant.Wiki{}).Error }) }