feat: add multi-source breed encyclopedia and two-hour refresh sessions
ci-cd / verify (push) Successful in 1m59s
ci-cd / deploy (push) Skipped

This commit is contained in:
2026-10-05 13:38:24 +08:00
parent 607d709100
commit 9d7cf720a5
73 changed files with 25771 additions and 264 deletions
+24 -1
View File
@@ -15,6 +15,7 @@ type petInput struct {
Name string `json:"name" binding:"required"`
Species string `json:"species"`
Breed string `json:"breed"`
BreedID *string `json:"breed_id"`
Gender string `json:"gender"`
BirthDate string `json:"birth_date"`
WeightKg float64 `json:"weight_kg"`
@@ -81,6 +82,7 @@ func (a *API) updatePet(c *gin.Context) {
}
pet.Name, pet.Species, pet.Breed, pet.Gender = updated.Name, updated.Species, updated.Breed, updated.Gender
pet.BirthDate, pet.WeightKg, pet.AvatarFileID = updated.BirthDate, updated.WeightKg, updated.AvatarFileID
pet.BreedID = updated.BreedID
pet.Coat, pet.Allergies, pet.CareNotes = updated.Coat, updated.Allergies, updated.CareNotes
if err := a.db.Save(&pet).Error; err != nil {
fail(c, http.StatusInternalServerError, "更新宠物失败")
@@ -110,6 +112,27 @@ func (a *API) buildPet(c *gin.Context, in petInput) (model.Pet, bool) {
return pet, false
}
}
in.Breed = strings.TrimSpace(in.Breed)
if len([]rune(in.Breed)) > 128 {
fail(c, http.StatusBadRequest, "品种名称过长")
return pet, false
}
if in.BreedID != nil {
var breed model.Breed
if !validID(*in.BreedID) || a.db.First(&breed, "id = ?", *in.BreedID).Error != nil {
fail(c, http.StatusBadRequest, "品种不存在,请重新选择或手动填写")
return pet, false
}
// A disabled breed can be retained on an existing pet, but not newly selected.
if !breed.Enabled {
var current model.Pet
if !validID(c.Param("id")) || a.db.Where("id = ? AND user_id = ? AND breed_id = ?", c.Param("id"), actor(c), *in.BreedID).First(&current).Error != nil {
fail(c, http.StatusBadRequest, "该品种已停用,请手动填写或重新选择")
return pet, false
}
}
in.Breed = breed.Name
}
var birthday *time.Time
if in.BirthDate != "" {
d, err := parseDay(in.BirthDate)
@@ -120,7 +143,7 @@ func (a *API) buildPet(c *gin.Context, in petInput) (model.Pet, bool) {
birthday = &d
}
pet = model.Pet{Name: in.Name, Species: in.Species, Breed: strings.TrimSpace(in.Breed),
Gender: in.Gender, BirthDate: birthday, WeightKg: in.WeightKg,
BreedID: in.BreedID, Gender: in.Gender, BirthDate: birthday, WeightKg: in.WeightKg,
AvatarFileID: in.AvatarFileID, Coat: in.Coat, Allergies: in.Allergies, CareNotes: in.CareNotes}
return pet, true
}