catface_backend_go/app/http/controller/web/animal_controller.go

241 lines
9.1 KiB
Go
Raw Normal View History

2024-10-14 13:49:16 +08:00
package web
import (
"catface/app/global/consts"
"catface/app/global/errcode"
2024-10-30 17:21:09 +08:00
"catface/app/global/variable"
"catface/app/http/validator/core/data_transfer"
"catface/app/model"
2024-10-14 19:27:46 +08:00
"catface/app/service/animals/curd"
2024-10-30 17:21:09 +08:00
"catface/app/service/upload_file"
2024-11-07 21:28:41 +08:00
"catface/app/utils/query_handler"
"catface/app/utils/redis_factory"
2024-10-14 13:49:16 +08:00
"catface/app/utils/response"
2024-10-30 17:21:09 +08:00
"os"
"path/filepath"
"strconv"
2024-10-14 13:49:16 +08:00
"github.com/gin-gonic/gin"
)
type Animals struct { // INFO 起到一个标记的作用,这样 web.xxx 的时候不同模块就不会命名冲突了。
}
2024-11-07 21:28:41 +08:00
// contains 检查 id 是否在 ids 切片中
func contains(ids []int, id int) bool {
for _, v := range ids {
if v == id {
return true
}
}
return false
}
2024-10-14 13:49:16 +08:00
func (a *Animals) List(context *gin.Context) {
// 1. Get Params
attrs := context.GetString(consts.ValidatorPrefix + "attrs")
2024-10-14 19:27:46 +08:00
gender := context.GetString(consts.ValidatorPrefix + "gender")
breed := context.GetString(consts.ValidatorPrefix + "breed")
2024-10-25 05:03:27 +08:00
sterilization := context.GetString(consts.ValidatorPrefix + "sterilization")
2024-10-14 19:27:46 +08:00
status := context.GetString(consts.ValidatorPrefix + "status")
2024-11-06 18:50:39 +08:00
department := context.GetString(consts.ValidatorPrefix + "department")
2024-11-07 21:28:41 +08:00
num := int(context.GetFloat64(consts.ValidatorPrefix + "num"))
skip := int(context.GetFloat64(consts.ValidatorPrefix + "skip"))
2024-10-23 12:51:41 +08:00
userId := context.GetFloat64(consts.ValidatorPrefix + "user_id")
2024-10-14 13:49:16 +08:00
2024-11-07 00:11:37 +08:00
mode := context.GetString(consts.ValidatorPrefix + "mode")
2024-11-07 21:28:41 +08:00
var preferCatsId []int64
2024-11-08 16:57:47 +08:00
var redis_preferCatsId []int64
2024-11-07 21:28:41 +08:00
var key int64
2024-11-07 00:11:37 +08:00
if mode == consts.AnimalPreferMode {
2024-11-07 21:28:41 +08:00
key = int64(context.GetFloat64(consts.ValidatorPrefix + "key"))
redisClient := redis_factory.GetOneRedisClient()
defer redisClient.ReleaseOneRedisClient()
if key != 0 {
2024-11-08 16:57:47 +08:00
redis_preferCatsId, _ = redisClient.Int64sFromList(redisClient.Execute("lrange", key, 0, -1))
2024-11-07 00:11:37 +08:00
} else {
2024-11-07 21:28:41 +08:00
key = variable.SnowFlake.GetId()
}
2024-11-08 16:57:47 +08:00
if len(redis_preferCatsId) == skip {
2024-11-07 21:28:41 +08:00
preferCatsId, _ = getPreferCatsId(int(userId), int(num))
2024-11-08 16:57:47 +08:00
redis_preferCatsId = append(redis_preferCatsId, preferCatsId...)
2024-11-07 21:28:41 +08:00
2024-11-08 16:57:47 +08:00
if _, err := redisClient.String(redisClient.Execute("lpush", key, redis_preferCatsId)); err != nil {
}
2024-11-07 21:28:41 +08:00
}
}
var animalsWithLike []model.AnimalWithLikeList
if len(preferCatsId) > 0 {
// 创建一个 map 来存储查询结果
animalMap := make(map[int64]model.Animal, len(preferCatsId))
attrsSlice := query_handler.StringToStringArray(attrs)
attrsSlice = append(attrsSlice, "id")
animals := model.CreateAnimalFactory("").ShowByIDs(preferCatsId, attrsSlice...)
for _, v := range animals {
animalMap[v.Id] = v
}
// 根据 preferCatsId 的顺序构建最终结果列表
for _, id := range preferCatsId {
if animal, ok := animalMap[id]; ok {
animalsWithLike = append(animalsWithLike, model.AnimalWithLikeList{Animal: animal})
}
2024-11-07 00:11:37 +08:00
}
2024-10-14 13:49:16 +08:00
}
2024-11-07 21:28:41 +08:00
// 计算还需要多少动物
num -= len(animalsWithLike)
2024-11-08 16:57:47 +08:00
skip = max(0, skip-len(redis_preferCatsId))
2024-11-07 21:28:41 +08:00
if num > 0 {
2024-11-08 16:57:47 +08:00
additionalAnimals := curd.CreateAnimalsCurdFactory().List(attrs, gender, breed, sterilization, status, department, redis_preferCatsId, num, skip, int(userId))
2024-11-07 21:28:41 +08:00
// 将 additionalAnimals 整合到 animalsWithLike 的后面
animalsWithLike = append(animalsWithLike, additionalAnimals...)
}
if animalsWithLike != nil {
response.Success(context, consts.CurdStatusOkMsg, gin.H{
"animals": animalsWithLike,
"key": key,
})
} else {
response.Fail(context, errcode.AnimalNoFind, errcode.ErrMsg[errcode.AnimalNoFind], "")
}
2024-10-14 13:49:16 +08:00
}
2024-11-07 21:28:41 +08:00
// UPDATE 就先简单一些,主要就依靠 encounter - animal_id 来获取一个目标。
func getPreferCatsId(userId, num int) ([]int64, error) {
// STAGE check 一下 key 是否存在。
// if key != "" {
// redisClient := redis_factory.GetOneRedisClient()
// defer redisClient.ReleaseOneRedisClient()
// if res, err := redisClient.Bool(redisClient.Execute("get", key)); err != nil {
// if res { // 如果 redis 返回的是 1则代表 prefer 已经耗尽了。
// return nil, err
// }
// }
// }
// STAGE - 1 模块一,无视条件,获取路遇过的 id 列表;先获取 ID然后再去查询细节信息。
encounteredCats, err := model.CreateEncounterFactory("").EncounteredCats(userId, num)
if err != nil {
// variable.ZapLog.Error("获取用户浏览记录失败", Zap.Error(err))
return encounteredCats, err
}
return encounteredCats, nil
2024-11-07 00:11:37 +08:00
}
2024-10-16 11:33:32 +08:00
// v0.1
2024-10-14 19:27:46 +08:00
// func (a *Animals) Detail(context *gin.Context) {
// // 1. Get Params
// anmId, err := strconv.Atoi(context.Param("anm_id"))
// // 2. Select & Filter
// var animal model.Animal
// err = variable.GormDbMysql.Table("animals").Model(&animal).Where("id = ?", anmId).Scan(&animal).Error // TIP GORM.First 采取默认的
// if err != nil {
// response.Fail(context, errcode.ErrAnimalSqlFind, errcode.ErrMsg[errcode.ErrAnimalSqlFind], err) // UPDATE consts ?
// } else {
// response.Success(context, consts.CurdStatusOkMsg, animal)
// }
// }
2024-10-14 13:49:16 +08:00
func (a *Animals) Detail(context *gin.Context) {
// 1. Get Params
2024-10-14 19:27:46 +08:00
anmId := context.Param("anm_id")
2024-10-14 13:49:16 +08:00
2024-10-18 20:28:34 +08:00
animal := curd.CreateAnimalsCurdFactory().Detail(anmId)
2024-10-14 19:27:46 +08:00
if animal != nil {
2024-10-14 13:49:16 +08:00
response.Success(context, consts.CurdStatusOkMsg, animal)
2024-10-14 19:27:46 +08:00
} else {
response.Fail(context, errcode.AnimalNoFind, errcode.ErrMsg[errcode.AnimalNoFind], "")
2024-10-14 13:49:16 +08:00
}
}
2024-11-08 16:57:47 +08:00
2024-10-24 15:26:09 +08:00
func (a *Animals) Create(context *gin.Context) {
2024-10-30 17:21:09 +08:00
userId := strconv.Itoa(int(context.GetFloat64(consts.ValidatorPrefix + "user_id")))
// STAGE-1 Get Params
photos := data_transfer.GetStringSlice(context, "photos")
if len(photos) > 0 {
avatar := photos[0]
avatarWidth := variable.ConfigYml.GetFloat64("FileUploadSetting.AvatarWidth")
srcPath := filepath.Join(variable.BasePath, variable.ConfigYml.GetString("FileUploadSetting.UploadFileSavePath"), "catsPhotos", "hum_"+userId, avatar)
dstPath := filepath.Join(variable.BasePath, variable.ConfigYml.GetString("FileUploadSetting.UploadFileSavePath"), "catsAvatar", avatar)
avatarHeight, err := upload_file.ResizeImage(srcPath, dstPath, int(avatarWidth))
if err != nil {
response.Fail(context, consts.FilesUploadFailCode, consts.FilesUploadFailMsg, "")
return
}
context.Set(consts.ValidatorPrefix+"avatar", avatar)
context.Set(consts.ValidatorPrefix+"avatar_height", float64(avatarHeight))
context.Set(consts.ValidatorPrefix+"avatar_width", float64(avatarWidth))
}
2024-10-24 15:26:09 +08:00
poi := context.GetStringMap(consts.ValidatorPrefix + "poi")
2024-10-30 17:21:09 +08:00
if poi != nil {
// 感觉这里就是获取信息之后,然后解析后再存储,方便后续 Model 直接绑定到数据。
latitude := poi["latitude"].(float64)
longitude := poi["longitude"].(float64)
context.Set(consts.ValidatorPrefix+"latitude", latitude)
context.Set(consts.ValidatorPrefix+"longitude", longitude)
}
health := context.GetStringMap(consts.ValidatorPrefix + "health")
if health != nil {
sterilization := health["sterilization"].(float64)
vaccination := health["vaccination"].(float64)
deworming := health["deworming"].(float64)
context.Set(consts.ValidatorPrefix+"sterilization", uint8(sterilization))
context.Set(consts.ValidatorPrefix+"vaccination", uint8(vaccination))
context.Set(consts.ValidatorPrefix+"deworming", uint8(deworming))
}
extra := context.GetStringMap(consts.ValidatorPrefix + "extra")
var nickNames []string
var tags []string
if extra != nil {
context.Set(consts.ValidatorPrefix+"nick_names", extra["nick_names"])
context.Set(consts.ValidatorPrefix+"tags", extra["tags"])
nickNames = data_transfer.GetStringSlice(context, "nick_names")
tags = data_transfer.GetStringSlice(context, "tags")
context.Set(consts.ValidatorPrefix+"nick_names", nickNames)
context.Set(consts.ValidatorPrefix+"tags", tags) // UPDATE 有点冗余,但是不用复杂代码;
}
// STAGE-2
if res, err := data_transfer.ConvertSliceToString(photos); err == nil {
context.Set(consts.ValidatorPrefix+"photos", res)
} else {
response.Fail(context, consts.ValidatorParamsCheckFailCode, consts.ValidatorParamsCheckFailMsg, "")
return
}
if res, err := data_transfer.ConvertSliceToString(nickNames); err == nil {
context.Set(consts.ValidatorPrefix+"nick_names", res)
} else {
response.Fail(context, consts.ValidatorParamsCheckFailCode, consts.ValidatorParamsCheckFailMsg, "")
return
}
if res, err := data_transfer.ConvertSliceToString(tags); err == nil {
context.Set(consts.ValidatorPrefix+"tags", res)
} else {
response.Fail(context, consts.ValidatorParamsCheckFailCode, consts.ValidatorParamsCheckFailMsg, "")
return
}
// STAGE-3
if anm_id, ok := model.CreateAnimalFactory("").InsertDate(context); ok {
// 转移 photos 到 anm采用 rename dir 的方式
oldName := filepath.Join(variable.BasePath, variable.ConfigYml.GetString("FileUploadSetting.UploadFileSavePath"), "catsPhotos", "hum_"+userId)
newName := filepath.Join(variable.BasePath, variable.ConfigYml.GetString("FileUploadSetting.UploadFileSavePath"), "catsPhotos", "anm_"+strconv.FormatInt(anm_id, 10))
err := os.Rename(oldName, newName)
if err != nil {
// TODO 特殊返回,成功了一半?或者需要清空原有的操作?不过感觉这一步几乎不会出错。
}
2024-10-31 20:36:06 +08:00
response.Success(context, consts.CurdStatusOkMsg, gin.H{
"anm_id": anm_id,
})
2024-10-30 17:21:09 +08:00
} else {
response.Fail(context, consts.CurdCreatFailCode, consts.CurdCreatFailMsg+",新增错误", "")
}
2024-10-24 15:26:09 +08:00
}