diff --git a/app/global/errcode/code.go b/app/global/errcode/code.go index 1330340..8a06e1c 100644 --- a/app/global/errcode/code.go +++ b/app/global/errcode/code.go @@ -4,6 +4,7 @@ const ( ErrGeneral = (iota + 1) * 100000 ErrAnimal ErrUser + ErrEncounter ) const ( diff --git a/app/global/errcode/encounter.go b/app/global/errcode/encounter.go new file mode 100644 index 0000000..8aeff76 --- /dev/null +++ b/app/global/errcode/encounter.go @@ -0,0 +1,9 @@ +package errcode + +const ( + ErrEaLinkInstert = ErrEncounter + iota +) + +func EnocunterMsgInit(m msg) { + m[ErrEaLinkInstert] = "路遇添加成功,但关联毛茸茸失败" +} \ No newline at end of file diff --git a/app/global/errcode/msg.go b/app/global/errcode/msg.go index 252fd9e..a39ba5e 100644 --- a/app/global/errcode/msg.go +++ b/app/global/errcode/msg.go @@ -9,6 +9,7 @@ func init() { GeneralMsgInit(ErrMsg) AnimalMsgInit(ErrMsg) UserMsgInit(ErrMsg) + EnocunterMsgInit(ErrMsg) } func GeneralMsgInit(m msg) { diff --git a/app/http/controller/web/encounter_controller.go b/app/http/controller/web/encounter_controller.go index f7434ed..045282a 100644 --- a/app/http/controller/web/encounter_controller.go +++ b/app/http/controller/web/encounter_controller.go @@ -37,24 +37,25 @@ func (e *Encounters) Create(context *gin.Context) { context.Set(consts.ValidatorPrefix+"avatar_width", float64(avatarWidth)) } // 将 Array 转化为 string 类型 - animals_id := data_transfer.GetFloat64Slice(context, "animals_id") - if res, err := data_transfer.ConvertSliceToString(animals_id); err == nil { - context.Set(consts.ValidatorPrefix+"animals_id", res) - } else { - response.Fail(context, consts.ValidatorParamsCheckFailCode, consts.ValidatorParamsCheckFailMsg, "") - return - } if res, err := data_transfer.ConvertSliceToString(photos); err == nil { context.Set(consts.ValidatorPrefix+"photos", res) } else { response.Fail(context, consts.ValidatorParamsCheckFailCode, consts.ValidatorParamsCheckFailMsg, "") return } - // Real Insert - if model.CreateEncounterFactory("").InsertDate(context) { + // Real Insert - 1: EA LINK + animals_id := data_transfer.GetFloat64Slice(context, "animals_id") // 由于是 Slice 就交给 EAlink 内部遍历时处理。 + // Real Insert - 2: ENC + if encounter_id, ok := model.CreateEncounterFactory("").InsertDate(context); ok && encounter_id > 0 { + if !model.CreateEncounterAnimalLinkFactory("").Insert(int(encounter_id), animals_id) { + // TODO 异常处理。 + response.Fail(context, errcode.ErrEaLinkInstert, errcode.ErrMsg[errcode.ErrEaLinkInstert], "") + return + } + response.Success(context, consts.CurdStatusOkMsg, "") } else { - response.Fail(context, consts.CurdCreatFailCode, consts.CurdCreatFailMsg+",新增错误", "") + response.Fail(context, consts.CurdCreatFailCode, consts.CurdCreatFailMsg+", 新增错误", "") } } diff --git a/app/model/encounter.go b/app/model/encounter.go index 0bb930c..a06cb2e 100644 --- a/app/model/encounter.go +++ b/app/model/encounter.go @@ -19,8 +19,8 @@ type Encounter struct { // Encounter 或者称为 post,指的就是 Human 单 BaseModel // TAG 外键关联 UsersModelId int64 `gorm:"column:user_id" json:"user_id"` - UsersModel *UsersModel `json:"users_model,omitempty"` // INFO 由于 Detail 返回空子段有些麻烦,先尝试采用指针。 - AnimalsId string `gorm:"size:20" json:"animals_id"` // TODO 关联对象存在上限 + UsersModel *UsersModel `json:"users_model,omitempty"` // INFO 由于 Detail 返回空子段有些麻烦,先尝试采用指针。 + // AnimalsId string `gorm:"size:20" json:"animals_id"` // 关联对象存在上限 // INFO 还是采取分表,方便查询。 Title string `gorm:"size:20;column:title" json:"title"` Content string `json:"content"` @@ -44,18 +44,18 @@ func (e *Encounter) TableName() string { return "encounters" } -func (e *Encounter) InsertDate(c *gin.Context) bool { +func (e *Encounter) InsertDate(c *gin.Context) (int64, bool) { var tmp Encounter if err := data_bind.ShouldBindFormDataToModel(c, &tmp); err == nil { if res := e.Create(&tmp); res.Error == nil { - return true + return tmp.Id, true } else { variable.ZapLog.Error("Encounter 数据新增出错", zap.Error(res.Error)) } } else { variable.ZapLog.Error("Encounter 数据绑定出错", zap.Error(err)) } - return false + return 0, false } func formatEncounterList(rows *gorm.DB) (temp []EncounterList, err error) { diff --git a/app/model/encounter_animal_link.go b/app/model/encounter_animal_link.go index 8b53790..17ad86a 100644 --- a/app/model/encounter_animal_link.go +++ b/app/model/encounter_animal_link.go @@ -1 +1,30 @@ package model + +import "gorm.io/gorm" + +func CreateEncounterAnimalLinkFactory(sqlType string) *EncounterAnimalLink { + return &EncounterAnimalLink{DB: UseDbConn(sqlType)} +} + +/** + * @description: 路遇 & 关联毛茸茸 的关联表,将 []int 拆为 int 的子表,方便查询。 + * @return {*} + */ +type EncounterAnimalLink struct { + *gorm.DB `gorm:"-" json:"-"` + EncounterId int `gorm:"column:encounter_id;index" json:"encounter_id"` + Encounter Encounter + AnimalId int `gorm:"column:animal_id;index" json:"animal_id"` + Animal Animal +} + +func (e *EncounterAnimalLink) Insert(encounterId int, animalId []float64) bool { + // Build Slice + var results []EncounterAnimalLink + for _, id := range animalId { + results = append(results, EncounterAnimalLink{EncounterId: encounterId, AnimalId: int(id)}) + } + + // 调用批处理插入方法 + return e.Create(&results).Error == nil +} diff --git a/app/service/encounter/curd/encounter_curd.go b/app/service/encounter/curd/encounter_curd.go index 8ea767b..79d6fad 100644 --- a/app/service/encounter/curd/encounter_curd.go +++ b/app/service/encounter/curd/encounter_curd.go @@ -50,17 +50,16 @@ func (e *EncounterCurd) Detail(id string) *model.EncounterDetail { if err != nil { return nil } - _ = user // 3. animals data - animals_id := query_handler.StringToint64Array(encounter.AnimalsId) - animals := model.CreateAnimalFactory("").ShowByIDs(animals_id, "avatar", "name", "id") - _ = animals + // animals_id := query_handler.StringToint64Array(encounter.AnimalsId) + // animals := model.CreateAnimalFactory("").ShowByIDs(animals_id, "avatar", "name", "id") + // _ = animals // 4. 合并 return &model.EncounterDetail{ Encounter: *encounter, UsersModel: *user, - Animals: animals, + // Animals: animals, } } diff --git a/test/models_test.go b/test/models_test.go index 0734a98..1183235 100644 --- a/test/models_test.go +++ b/test/models_test.go @@ -4,6 +4,9 @@ package test import ( "catface/app/model" "fmt" + "reflect" + "strconv" + "strings" "testing" ) @@ -104,3 +107,77 @@ func TestAnimalLike(t *testing.T) { t.Error(err) } } + +func TestEaLink(t *testing.T) { + Init() + eaLink := model.EncounterAnimalLink{} + err := DB.AutoMigrate(&eaLink) + if err != nil { + t.Error(err) + } +} + +// 测试函数 +func TestInsertEncounterAnimalLinks(t *testing.T) { + Init() + + // 定义要插入的数据 + data := []struct { + EncounterId int + AnimalIds string + }{ + {10, "4"}, + {11, "2,3"}, + {13, "4"}, + {14, "4"}, + {15, "4"}, + {16, "4"}, + {17, "4"}, + {18, "4"}, + {19, "4"}, + {20, "4"}, + } + + // 插入数据 + for _, item := range data { + animalIds := strings.Split(item.AnimalIds, ",") + for _, animalIdStr := range animalIds { + animalId, err := strconv.Atoi(animalIdStr) + if err != nil { + t.Errorf("Failed to convert animal Id: %v", err) + continue + } + link := model.EncounterAnimalLink{ + EncounterId: item.EncounterId, + AnimalId: animalId, + } + if err := DB.Create(&link).Error; err != nil { + t.Errorf("Failed to insert link: %v", err) + } + } + } + + // 验证数据是否正确插入 + var links []model.EncounterAnimalLink + if err := DB.Find(&links).Error; err != nil { + t.Errorf("Failed to fetch links: %v", err) + } + + expectedLinks := []model.EncounterAnimalLink{ + {EncounterId: 10, AnimalId: 4}, + {EncounterId: 11, AnimalId: 2}, + {EncounterId: 11, AnimalId: 3}, + {EncounterId: 13, AnimalId: 4}, + {EncounterId: 14, AnimalId: 4}, + {EncounterId: 15, AnimalId: 4}, + {EncounterId: 16, AnimalId: 4}, + {EncounterId: 17, AnimalId: 4}, + {EncounterId: 18, AnimalId: 4}, + {EncounterId: 19, AnimalId: 4}, + {EncounterId: 20, AnimalId: 4}, + } + + if !reflect.DeepEqual(links, expectedLinks) { + t.Errorf("Expected links: %v, but got: %v", expectedLinks, links) + } +}