🎨 better model code
This commit is contained in:
parent
eaf4bb4ad8
commit
9b24a1f645
@ -2,8 +2,10 @@ package errcode
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
ErrAnimalSqlFind = iota + ErrAnimal
|
ErrAnimalSqlFind = iota + ErrAnimal
|
||||||
|
AnimalNoFind
|
||||||
)
|
)
|
||||||
|
|
||||||
func AnimalMsgInit(m msg) {
|
func AnimalMsgInit(m msg) {
|
||||||
m[ErrAnimalSqlFind] = "Animals 表单查询失败"
|
m[ErrAnimalSqlFind] = "Animals 表单查询失败"
|
||||||
|
m[AnimalNoFind] = "Animals 没有查询到符合条件的目标"
|
||||||
}
|
}
|
||||||
|
@ -3,122 +3,56 @@ package web
|
|||||||
import (
|
import (
|
||||||
"catface/app/global/consts"
|
"catface/app/global/consts"
|
||||||
"catface/app/global/errcode"
|
"catface/app/global/errcode"
|
||||||
"catface/app/global/variable"
|
"catface/app/service/animals/curd"
|
||||||
"catface/app/model"
|
|
||||||
"catface/app/utils/model_handler"
|
|
||||||
"catface/app/utils/query_handler"
|
|
||||||
"catface/app/utils/response"
|
"catface/app/utils/response"
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"gorm.io/gorm"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Animals struct { // INFO 起到一个标记的作用,这样 web.xxx 的时候不同模块就不会命名冲突了。
|
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) {
|
func (a *Animals) List(context *gin.Context) {
|
||||||
// 1. Get Params
|
// 1. Get Params
|
||||||
attrs := context.GetString(consts.ValidatorPrefix + "attrs")
|
attrs := context.GetString(consts.ValidatorPrefix + "attrs")
|
||||||
gender := query_handler.StringToUint8Array(context.GetString(consts.ValidatorPrefix + "gender"))
|
gender := context.GetString(consts.ValidatorPrefix + "gender")
|
||||||
breed := query_handler.StringToUint8Array(context.GetString(consts.ValidatorPrefix + "breed"))
|
breed := context.GetString(consts.ValidatorPrefix + "breed")
|
||||||
sterilzation := query_handler.StringToUint8Array(context.GetString(consts.ValidatorPrefix + "sterilzation"))
|
sterilzation := context.GetString(consts.ValidatorPrefix + "sterilzation")
|
||||||
status := query_handler.StringToUint8Array(context.GetString(consts.ValidatorPrefix + "status"))
|
status := context.GetString(consts.ValidatorPrefix + "status")
|
||||||
num := context.GetFloat64(consts.ValidatorPrefix + "num")
|
num := context.GetFloat64(consts.ValidatorPrefix + "num")
|
||||||
skip := context.GetFloat64(consts.ValidatorPrefix + "skip")
|
skip := context.GetFloat64(consts.ValidatorPrefix + "skip")
|
||||||
|
|
||||||
// 创建条件映射
|
animals := curd.CreateUserCurdFactory().List(attrs, gender, breed, sterilzation, status, int(num), int(skip))
|
||||||
conditions := map[string][]uint8{
|
if animals != nil {
|
||||||
"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 {
|
|
||||||
response.Success(context, consts.CurdStatusOkMsg, animals)
|
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) {
|
func (a *Animals) Detail(context *gin.Context) {
|
||||||
// 1. Get Params
|
// 1. Get Params
|
||||||
anmId, err := strconv.Atoi(context.Param("anm_id"))
|
anmId := context.Param("anm_id")
|
||||||
if err != nil {
|
|
||||||
response.Fail(context, errcode.ErrAnimalSqlFind, errcode.ErrMsg[errcode.ErrAnimalSqlFind], err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fmt.Println("anmId:", anmId)
|
|
||||||
|
|
||||||
// 2. Select & Filter
|
animal := curd.CreateUserCurdFactory().Detail(anmId)
|
||||||
var animal model.Animal
|
if animal != nil {
|
||||||
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)
|
response.Success(context, consts.CurdStatusOkMsg, animal)
|
||||||
|
} else {
|
||||||
|
response.Fail(context, errcode.AnimalNoFind, errcode.ErrMsg[errcode.AnimalNoFind], "")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,16 @@
|
|||||||
package model
|
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 {
|
type Animal struct {
|
||||||
BaseModel // 假设 BaseModel 中不需要添加 omitempty 标签
|
BaseModel // 假设 BaseModel 中不需要添加 omitempty 标签
|
||||||
Name string `gorm:"type:varchar(20)" json:"name,omitempty"` // 名称
|
Name string `gorm:"type:varchar(20)" json:"name,omitempty"` // 名称
|
||||||
@ -21,37 +32,35 @@ type Animal struct {
|
|||||||
Tags string `json:"tags,omitempty"` // 活动半径
|
Tags string `json:"tags,omitempty"` // 活动半径
|
||||||
}
|
}
|
||||||
|
|
||||||
type Breed struct {
|
func (a *Animal) TableName() string {
|
||||||
BriefModel
|
return "animals"
|
||||||
}
|
}
|
||||||
|
|
||||||
type Sterilzation struct { // TEST How to use BriefModel, the dif between Common
|
func (a *Animal) Show(attrs []string, gender []uint8, breed []uint8, sterilzation []uint8, status []uint8, num int, skip int) (temp []Animal) {
|
||||||
Id int64 `json:"id"`
|
db := a.DB.Table(a.TableName()).Limit(int(num)).Offset(int(skip)).Select(attrs)
|
||||||
NameZh string `json:"name_zh"`
|
|
||||||
NameEn string `json:"name_en"`
|
// 创建条件映射
|
||||||
|
conditions := map[string][]uint8{
|
||||||
|
"gender": gender,
|
||||||
|
"breed": breed,
|
||||||
|
"sterilization": sterilzation,
|
||||||
|
"status": status,
|
||||||
}
|
}
|
||||||
|
|
||||||
type AnmStatus struct {
|
db = gorm_v2.BuildWhere(db, conditions)
|
||||||
BriefModel
|
|
||||||
|
err := db.Find(&temp).Error
|
||||||
|
if err != nil {
|
||||||
|
variable.ZapLog.Error("Animal Show Error", zap.Error(err))
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
type AnmGender struct {
|
func (a *Animal) ShowByID(id int) *Animal {
|
||||||
BriefModel
|
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
|
||||||
/**
|
|
||||||
* @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
|
|
||||||
}
|
}
|
||||||
|
21
app/model/animal_com.go
Normal file
21
app/model/animal_com.go
Normal file
@ -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
|
||||||
|
}
|
18
app/model/animal_face_breed.go
Normal file
18
app/model/animal_face_breed.go
Normal file
@ -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
|
||||||
|
}
|
6
app/model/encounter.go
Normal file
6
app/model/encounter.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
type post struct { // Encounter 或者称为 post,指的就是 Human 单次的记录。
|
||||||
|
BaseModel
|
||||||
|
UserID int
|
||||||
|
}
|
@ -17,7 +17,7 @@ import (
|
|||||||
// 参数说明: 传递空值,默认使用 配置文件选项:UseDbType(mysql)
|
// 参数说明: 传递空值,默认使用 配置文件选项:UseDbType(mysql)
|
||||||
|
|
||||||
func CreateUserFactory(sqlType string) *UsersModel {
|
func CreateUserFactory(sqlType string) *UsersModel {
|
||||||
return &UsersModel{BaseModel: BaseModel{DB: UseDbConn(sqlType)}}
|
return &UsersModel{BaseModel: BaseModel{DB: UseDbConn(sqlType)}} // INFO 这里补充 DB 的指针
|
||||||
}
|
}
|
||||||
|
|
||||||
type UsersModel struct {
|
type UsersModel struct {
|
||||||
|
74
app/service/animals/curd/animals_curd.go
Normal file
74
app/service/animals/curd/animals_curd.go
Normal file
@ -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)
|
||||||
|
}
|
19
app/utils/gorm_v2/utils.go
Normal file
19
app/utils/gorm_v2/utils.go
Normal file
@ -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
|
||||||
|
}
|
@ -30,7 +30,7 @@ func getProcessedJSONTag(field reflect.StructField) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetModelField(v interface{}) map[string]bool {
|
func GetModelField(v interface{}) map[string]bool {
|
||||||
t := reflect.TypeOf(v)
|
t := reflect.TypeOf(v) // TODO 特化处理掉 BaseModel 这样的继承字段
|
||||||
|
|
||||||
fieldMap := make(map[string]bool)
|
fieldMap := make(map[string]bool)
|
||||||
for i := 0; i < t.NumField(); i++ {
|
for i := 0; i < t.NumField(); i++ {
|
||||||
|
Binary file not shown.
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user