This commit is contained in:
2024-09-25 16:35:07 +08:00
parent e952657166
commit 43f78fb688
14 changed files with 347 additions and 0 deletions

134
utils/gin_context.go Normal file
View File

@ -0,0 +1,134 @@
package utils
import (
"api/utils/model/req"
"api/utils/r"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
)
// 在内部 panic 会被 middleware 捕获到并返回错误信息
// Validate 参数合法性校验
func Validate(c *gin.Context, data any) {
validMsg := Validator.Validate(data)
if validMsg != "" {
r.ReturnJson(c, http.StatusOK, r.ERROR_INVALID_PARAM, validMsg, nil)
panic(nil)
}
}
// Bind 绑定
func Bind[T any](c *gin.Context) (data T) {
if err := c.ShouldBind(&data); err != nil {
// Logger.Error("Bind", zap.Error(err))
panic(r.ERROR_REQUEST_PARAM)
}
return
}
// BindValid 绑定验证 + 合法性校验
func BindValid[T any](c *gin.Context) (data T) {
// Json 绑定
if err := c.ShouldBind(&data); err != nil {
// Logger.Error("BindValid", zap.Error(err))
panic(r.ERROR_REQUEST_PARAM)
}
// 参数合法性校验
Validate(c, &data)
return data
}
// BindJson Json 绑定
func BindJson[T any](c *gin.Context) (data T) {
if err := c.ShouldBindJSON(&data); err != nil {
// Logger.Error("BindJson", zap.Error(err))
panic(r.ERROR_REQUEST_PARAM)
}
return
}
// BindValidJson Json 绑定验证 + 合法性校验
func BindValidJson[T any](c *gin.Context) (data T) {
// Json 绑定
if err := c.ShouldBindJSON(&data); err != nil {
// Logger.Error("BindValidJson", zap.Error(err))
panic(r.ERROR_REQUEST_PARAM)
}
// 参数合法性校验
Validate(c, &data)
return data
}
// BindQuery Param 绑定
func BindQuery[T any](c *gin.Context) (data T) {
if err := c.ShouldBindQuery(&data); err != nil {
// Logger.Error("BindQuery", zap.Error(err))
panic(r.ERROR_REQUEST_PARAM)
}
// TODO: 检查是否有 PageSize 或 PageQuery 字段,并处理其值
// val := reflect.ValueOf(data)
// pageSize := val.FieldByName("PageSize").Int()
// fmt.Println("pageSize: ", pageSize)
// val.FieldByName("PageSize").Elem().SetInt(12)
return
}
// BindPageQuery Param 分页绑定(处理了 PageSize 和 PageQuery)
func BindPageQuery(c *gin.Context) (data req.PageQuery) {
if err := c.ShouldBindQuery(&data); err != nil {
// Logger.Error("BindQuery", zap.Error(err))
panic(r.ERROR_REQUEST_PARAM)
}
// 检查分页参数
CheckQueryPage(&data.PageSize, &data.PageNum)
return
}
// BindValidQuery Param 绑定验证 + 合法性校验
func BindValidQuery[T any](c *gin.Context) (data T) {
// Query 绑定
if err := c.ShouldBindQuery(&data); err != nil {
// Logger.Error("BindValidQuery", zap.Error(err))
panic(r.ERROR_REQUEST_PARAM)
}
// 参数合法性校验
Validate(c, &data)
return data
}
// CheckQueryPage 检查分页参数
func CheckQueryPage(pageSize, pageNum *int) {
switch {
case *pageSize >= 100:
*pageSize = 100
case *pageSize <= 0:
*pageSize = 10
}
if *pageNum <= 0 {
*pageNum = 1
}
}
// GetFromContext 从 Gin Context 上获取值, 该值是 JWT middleware 解析 Token 后设置的
// 如果该值不存在, 说明 Token 有问题
func GetFromContext[T any](c *gin.Context, key string) T {
val, exist := c.Get(key)
if !exist {
panic(r.ERROR_TOKEN_RUNTIME)
}
return val.(T)
}
// GetIntParam 从 Context 获取 Int 类型 Param 参数
func GetIntParam(c *gin.Context, key string) int {
val, err := strconv.Atoi(c.Param(key))
if err != nil {
// Logger.Error("GetIntParam", zap.Error(err))
panic(r.ERROR_REQUEST_PARAM)
}
return val
}

View File

@ -0,0 +1,25 @@
package req
// KeywordQuery 关键字查询
type KeywordQuery struct {
Keyword string `form:"keyword"`
}
// PageQuery 获取数据(需要分页)
type PageQuery struct {
PageSize int `form:"page_size"`
PageNum int `form:"page_num"`
Keyword string `form:"keyword"`
}
// SoftDelete 软删除请求(批量)
type SoftDelete struct {
Ids []int `json:"ids"`
IsDelete *int8 `json:"is_delete" validate:"required,min=0,max=1"` // 软删除到回收站, 没有的字段不使用
}
// UpdateReview 修改审核(批量)
type UpdateReview struct {
Ids []int `json:"ids"`
IsReview *int8 `json:"is_review" validate:"required,min=0,max=1"`
}

View File

@ -47,3 +47,13 @@ func SuccessData(c *gin.Context, data any) {
func Success(c *gin.Context) {
Send(c, http.StatusOK, OK, nil)
}
// Error 失败
func Error(c *gin.Context) {
Send(c, http.StatusOK, FAIL, nil)
}
// ErrorData 数据
func ErrorData(c *gin.Context, data any) {
Send(c, http.StatusOK, FAIL, data)
}

53
utils/validator.go Normal file
View File

@ -0,0 +1,53 @@
package utils
import (
"reflect"
"github.com/go-playground/locales/zh_Hans_CN"
unTrans "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
zhTrans "github.com/go-playground/validator/v10/translations/zh"
)
var Validator = new(ValidateUtil)
type ValidateUtil struct{}
var (
uni *unTrans.UniversalTranslator
validate *validator.Validate
)
// Validate 返回验证错误信息, 为 "" 则无错误
func (v *ValidateUtil) Validate(data any) string {
// 验证对象
validate = validator.New()
// 翻译器
trans := v.validateTransInit(validate)
err := validate.Struct(data)
if err != nil {
for _, e := range err.(validator.ValidationErrors) {
return e.Translate(trans)
}
}
return ""
}
// validateTransInit 数据验证翻译器
func (*ValidateUtil) validateTransInit(validate *validator.Validate) unTrans.Translator {
// 万能翻译器,保存所有的语言环境和翻译数据
uni = unTrans.New(zh_Hans_CN.New())
// 翻译器
trans, _ := uni.GetTranslator("zh_Hans_CN")
// 验证器注册翻译器
_ = zhTrans.RegisterDefaultTranslations(validate, trans)
// 读取 Tag 中的 label 标签为字段的翻译
validate.RegisterTagNameFunc(func(field reflect.StructField) string {
return field.Tag.Get("label")
})
return trans
}