diff --git a/app/global/errcode/animal.go b/app/global/errcode/animal.go index a2ceab1..89ba807 100644 --- a/app/global/errcode/animal.go +++ b/app/global/errcode/animal.go @@ -2,8 +2,10 @@ package errcode const ( ErrAnimalSqlFind = iota + ErrAnimal + AnimalNoFind ) func AnimalMsgInit(m msg) { m[ErrAnimalSqlFind] = "Animals 表单查询失败" + m[AnimalNoFind] = "Animals 没有查询到符合条件的目标" } diff --git a/app/http/controller/web/animal_controller.go b/app/http/controller/web/animal_controller.go index 194f402..5f7a729 100644 --- a/app/http/controller/web/animal_controller.go +++ b/app/http/controller/web/animal_controller.go @@ -3,122 +3,56 @@ package web import ( "catface/app/global/consts" "catface/app/global/errcode" - "catface/app/global/variable" - "catface/app/model" - "catface/app/utils/model_handler" - "catface/app/utils/query_handler" + "catface/app/service/animals/curd" "catface/app/utils/response" - "fmt" - "strconv" "github.com/gin-gonic/gin" - "gorm.io/gorm" ) type Animals struct { // INFO 起到一个标记的作用,这样 web.xxx 的时候不同模块就不会命名冲突了。 } -func buildSelectAttrs(db *gorm.DB, attrs string) *gorm.DB { - if len(attrs) > 0 { - // 1. 获取空 Field - fieldMap := model_handler.GetModelField(model.Animal{}) - - // 2. 开始检查请求字段 - attrsArray := query_handler.StringToStringArray(attrs) - for _, attr := range attrsArray { - if attr == "*" { // 不需要过滤,直接返回 - return db - } else if attr == "avatar" { - fieldMap["avatar_height"] = true - fieldMap["avatar_width"] = true - } - // 过滤 无效 的请求字段 - if _, ok := fieldMap[attr]; ok { - fieldMap[attr] = true - continue - } - } - - // 3. 装填字段,并 Select - var validSelectedFields []string - for key, value := range fieldMap { - if value { - validSelectedFields = append(validSelectedFields, key) - } - } - db = db.Select(validSelectedFields) - } - return db -} - -/** - * @description: 通过检查字段的方式构建 Where 函数。 - * @param {*gorm.DB} db - * @param {map[string][]uint8} conditions - * @return {*} - */ -func buildQuery(db *gorm.DB, conditions map[string][]uint8) *gorm.DB { - for field, values := range conditions { - if len(values) == 0 || len(values) == 1 && values[0] == 0 { - continue - } - db = db.Where(field+" in (?)", values) - } - return db -} - func (a *Animals) List(context *gin.Context) { // 1. Get Params attrs := context.GetString(consts.ValidatorPrefix + "attrs") - gender := query_handler.StringToUint8Array(context.GetString(consts.ValidatorPrefix + "gender")) - breed := query_handler.StringToUint8Array(context.GetString(consts.ValidatorPrefix + "breed")) - sterilzation := query_handler.StringToUint8Array(context.GetString(consts.ValidatorPrefix + "sterilzation")) - status := query_handler.StringToUint8Array(context.GetString(consts.ValidatorPrefix + "status")) + gender := context.GetString(consts.ValidatorPrefix + "gender") + breed := context.GetString(consts.ValidatorPrefix + "breed") + sterilzation := context.GetString(consts.ValidatorPrefix + "sterilzation") + status := context.GetString(consts.ValidatorPrefix + "status") num := context.GetFloat64(consts.ValidatorPrefix + "num") skip := context.GetFloat64(consts.ValidatorPrefix + "skip") - // 创建条件映射 - conditions := map[string][]uint8{ - "gender": gender, - "breed": breed, - "sterilization": sterilzation, - "status": status, - } - - // 2. Select & Filter - if num == 0 { - num = 10 - } - db := variable.GormDbMysql.Table("animals").Limit(int(num)).Offset(int(skip)) - db = buildSelectAttrs(db, attrs) - db = buildQuery(db, conditions) - - // 3. Find - var animals []model.Animal - err := db.Find(&animals).Error - if err != nil { - response.Fail(context, errcode.ErrAnimalSqlFind, errcode.ErrMsg[errcode.ErrAnimalSqlFind], err) // UPDATE consts ? - } else { + animals := curd.CreateUserCurdFactory().List(attrs, gender, breed, sterilzation, status, int(num), int(skip)) + if animals != nil { response.Success(context, consts.CurdStatusOkMsg, animals) + } else { + response.Fail(context, errcode.AnimalNoFind, errcode.ErrMsg[errcode.AnimalNoFind], "") } } +// v1 +// 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) +// } +// } + func (a *Animals) Detail(context *gin.Context) { // 1. Get Params - anmId, err := strconv.Atoi(context.Param("anm_id")) - if err != nil { - response.Fail(context, errcode.ErrAnimalSqlFind, errcode.ErrMsg[errcode.ErrAnimalSqlFind], err) - return - } - fmt.Println("anmId:", anmId) + anmId := 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 { + animal := curd.CreateUserCurdFactory().Detail(anmId) + if animal != nil { response.Success(context, consts.CurdStatusOkMsg, animal) + } else { + response.Fail(context, errcode.AnimalNoFind, errcode.ErrMsg[errcode.AnimalNoFind], "") } - } diff --git a/app/model/animal.go b/app/model/animal.go index d1109b0..a69a642 100644 --- a/app/model/animal.go +++ b/app/model/animal.go @@ -1,5 +1,16 @@ package model +import ( + "catface/app/global/variable" + "catface/app/utils/gorm_v2" + + "go.uber.org/zap" +) + +func CreateAnimalFactory(sqlType string) *Animal { + return &Animal{BaseModel: BaseModel{DB: UseDbConn(sqlType)}} +} + type Animal struct { BaseModel // 假设 BaseModel 中不需要添加 omitempty 标签 Name string `gorm:"type:varchar(20)" json:"name,omitempty"` // 名称 @@ -21,37 +32,35 @@ type Animal struct { Tags string `json:"tags,omitempty"` // 活动半径 } -type Breed struct { - BriefModel +func (a *Animal) TableName() string { + return "animals" } -type Sterilzation struct { // TEST How to use BriefModel, the dif between Common - Id int64 `json:"id"` - NameZh string `json:"name_zh"` - NameEn string `json:"name_en"` +func (a *Animal) Show(attrs []string, gender []uint8, breed []uint8, sterilzation []uint8, status []uint8, num int, skip int) (temp []Animal) { + db := a.DB.Table(a.TableName()).Limit(int(num)).Offset(int(skip)).Select(attrs) + + // 创建条件映射 + conditions := map[string][]uint8{ + "gender": gender, + "breed": breed, + "sterilization": sterilzation, + "status": status, + } + + db = gorm_v2.BuildWhere(db, conditions) + + err := db.Find(&temp).Error + if err != nil { + variable.ZapLog.Error("Animal Show Error", zap.Error(err)) + } + return } -type AnmStatus struct { - BriefModel -} - -type AnmGender struct { - BriefModel -} - -/** - * @description: 保留 Top 3, 辅助 catface - breed 子模型判断; 单独建表,因为只会被 CatFace 模块使用。 - * @return {*} - */ -type AnmFaceBreed struct { // TODO 迁移 python 的时候再考虑一下细节 - BriefModel - Top1 uint8 - Prob1 float64 - Top2 uint8 - Prob2 float64 - Top3 uint8 - Prob3 float64 - - AnimalId int64 // INFO 外键设定? - Animal Animal +func (a *Animal) ShowByID(id int) *Animal { + var temp Animal + err := a.DB.Table(a.TableName()).Model(&temp).Where("id = ?", id).Scan(&temp).Error + if err != nil { + variable.ZapLog.Error("Animal ShowByID Error", zap.Error(err)) + } + return &temp } diff --git a/app/model/animal_com.go b/app/model/animal_com.go new file mode 100644 index 0000000..bc07fa1 --- /dev/null +++ b/app/model/animal_com.go @@ -0,0 +1,21 @@ +package model + +// INFO 一些基础表单的整合 + +type Breed struct { + BriefModel +} + +type Sterilzation struct { // TEST How to use BriefModel, the dif between Common + Id int64 `json:"id"` + NameZh string `json:"name_zh"` + NameEn string `json:"name_en"` +} + +type AnmStatus struct { + BriefModel +} + +type AnmGender struct { + BriefModel +} diff --git a/app/model/animal_face_breed.go b/app/model/animal_face_breed.go new file mode 100644 index 0000000..a50e54c --- /dev/null +++ b/app/model/animal_face_breed.go @@ -0,0 +1,18 @@ +package model + +/** + * @description: 保留 Top 3, 辅助 catface - breed 子模型判断; 单独建表,因为只会被 CatFace 模块使用。 + * @return {*} + */ +type AnmFaceBreed struct { // TODO 迁移 python 的时候再考虑一下细节 + BriefModel + Top1 uint8 + Prob1 float64 + Top2 uint8 + Prob2 float64 + Top3 uint8 + Prob3 float64 + + AnimalId int64 // INFO 外键设定? + Animal Animal +} diff --git a/app/model/encounter.go b/app/model/encounter.go new file mode 100644 index 0000000..212e681 --- /dev/null +++ b/app/model/encounter.go @@ -0,0 +1,6 @@ +package model + +type post struct { // Encounter 或者称为 post,指的就是 Human 单次的记录。 + BaseModel + UserID int +} diff --git a/app/model/users.go b/app/model/users.go index 576268f..551de81 100644 --- a/app/model/users.go +++ b/app/model/users.go @@ -17,7 +17,7 @@ import ( // 参数说明: 传递空值,默认使用 配置文件选项:UseDbType(mysql) func CreateUserFactory(sqlType string) *UsersModel { - return &UsersModel{BaseModel: BaseModel{DB: UseDbConn(sqlType)}} + return &UsersModel{BaseModel: BaseModel{DB: UseDbConn(sqlType)}} // INFO 这里补充 DB 的指针 } type UsersModel struct { diff --git a/app/service/animals/curd/animals_curd.go b/app/service/animals/curd/animals_curd.go new file mode 100644 index 0000000..e7f99cf --- /dev/null +++ b/app/service/animals/curd/animals_curd.go @@ -0,0 +1,74 @@ +package curd + +import ( + "catface/app/model" + "catface/app/utils/model_handler" + "catface/app/utils/query_handler" + "fmt" + "strconv" +) + +func CreateUserCurdFactory() *AnimalsCurd { + return &AnimalsCurd{model.CreateAnimalFactory("")} +} + +type AnimalsCurd struct { + animals *model.Animal // INFO 难道数据就是存储到这里? +} + +func getSelectAttrs(attrs string) (validSelectedFields []string) { + if len(attrs) == 0 { + return nil + } + // 1. 获取空 Field + fieldMap := model_handler.GetModelField(model.Animal{}) + + // 2. 开始检查请求字段 + attrsArray := query_handler.StringToStringArray(attrs) + for _, attr := range attrsArray { + if attr == "*" { // 不需要过滤,直接返回 + return nil + } else if attr == "avatar" { + fieldMap["avatar_height"] = true + fieldMap["avatar_width"] = true + } + // 过滤 无效 的请求字段 + if _, ok := fieldMap[attr]; ok { + fieldMap[attr] = true + continue + } + } + + // 3. 装填字段 + for key, value := range fieldMap { + if value { + validSelectedFields = append(validSelectedFields, key) + } + } + return +} + +func (a *AnimalsCurd) List(attrs string, gender string, breed string, sterilzation string, status string, num int, skip int) []model.Animal { + validSelectedFields := getSelectAttrs(attrs) + genderArray := query_handler.StringToUint8Array(gender) + breedArray := query_handler.StringToUint8Array(breed) + sterilzationArray := query_handler.StringToUint8Array(sterilzation) + statusArray := query_handler.StringToUint8Array(status) + + if num == 0 { + num = 10 + } + + return model.CreateAnimalFactory("mysql").Show(validSelectedFields, genderArray, breedArray, sterilzationArray, statusArray, num, skip) +} + +func (a *AnimalsCurd) Detail(id string) *model.Animal { + idInt, err := strconv.Atoi(id) + if err != nil { + // TODO LOG + fmt.Println("Detail id error:", err) + return nil + } + + return model.CreateAnimalFactory("mysql").ShowByID(idInt) +} diff --git a/app/utils/gorm_v2/utils.go b/app/utils/gorm_v2/utils.go new file mode 100644 index 0000000..eb8ad5c --- /dev/null +++ b/app/utils/gorm_v2/utils.go @@ -0,0 +1,19 @@ +package gorm_v2 + +import "gorm.io/gorm" + +/** + * @description: 通过检查字段的方式构建 Where 函数。 + * @param {*gorm.DB} db + * @param {map[string][]uint8} conditions + * @return {*} + */ +func BuildWhere(db *gorm.DB, conditions map[string][]uint8) *gorm.DB { + for field, values := range conditions { + if len(values) == 0 || len(values) == 1 && values[0] == 0 { + continue + } + db = db.Where(field+" in (?)", values) + } + return db +} diff --git a/app/utils/model_handler/model_handler.go b/app/utils/model_handler/model_handler.go index 897053e..10ba475 100644 --- a/app/utils/model_handler/model_handler.go +++ b/app/utils/model_handler/model_handler.go @@ -30,7 +30,7 @@ func getProcessedJSONTag(field reflect.StructField) string { } func GetModelField(v interface{}) map[string]bool { - t := reflect.TypeOf(v) + t := reflect.TypeOf(v) // TODO 特化处理掉 BaseModel 这样的继承字段 fieldMap := make(map[string]bool) for i := 0; i < t.NumField(); i++ { diff --git a/tmp/runner-build.exe b/tmp/runner-build.exe index 71912a5..98fbe11 100644 Binary files a/tmp/runner-build.exe and b/tmp/runner-build.exe differ diff --git a/tmp/runner-build.exe~ b/tmp/runner-build.exe~ index d5e201a..1b8f07e 100644 Binary files a/tmp/runner-build.exe~ and b/tmp/runner-build.exe~ differ