124 lines
3.2 KiB
Go
124 lines
3.2 KiB
Go
|
|
package libs
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"fmt"
|
|||
|
|
"strings"
|
|||
|
|
|
|||
|
|
"git.apinb.com/bsm-sdk/core/errcode"
|
|||
|
|
"github.com/go-playground/validator/v10"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
var (
|
|||
|
|
validate *validator.Validate
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
func init() {
|
|||
|
|
validate = validator.New()
|
|||
|
|
// 注册自定义验证规则
|
|||
|
|
registerCustomValidators()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// registerCustomValidators 注册自定义验证器
|
|||
|
|
func registerCustomValidators() {
|
|||
|
|
// 注册手机号验证
|
|||
|
|
validate.RegisterValidation("phone", validatePhone)
|
|||
|
|
// 注册邮箱验证
|
|||
|
|
validate.RegisterValidation("email_format", validateEmail)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// validatePhone 验证手机号(11位数字,以1开头)
|
|||
|
|
func validatePhone(fl validator.FieldLevel) bool {
|
|||
|
|
phone := fl.Field().String()
|
|||
|
|
// 空字符串由omitempty或required处理,这里返回true
|
|||
|
|
if phone == "" {
|
|||
|
|
return true
|
|||
|
|
}
|
|||
|
|
if len(phone) != 11 {
|
|||
|
|
return false
|
|||
|
|
}
|
|||
|
|
if len(phone) > 0 && phone[0] != '1' {
|
|||
|
|
return false
|
|||
|
|
}
|
|||
|
|
for _, char := range phone {
|
|||
|
|
if char < '0' || char > '9' {
|
|||
|
|
return false
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return true
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// validateEmail 验证邮箱格式(简单的邮箱格式验证)
|
|||
|
|
func validateEmail(fl validator.FieldLevel) bool {
|
|||
|
|
email := fl.Field().String()
|
|||
|
|
if email == "" {
|
|||
|
|
return true // 允许为空,使用omitempty处理
|
|||
|
|
}
|
|||
|
|
parts := strings.Split(email, "@")
|
|||
|
|
if len(parts) != 2 {
|
|||
|
|
return false
|
|||
|
|
}
|
|||
|
|
if len(parts[0]) == 0 || len(parts[1]) == 0 {
|
|||
|
|
return false
|
|||
|
|
}
|
|||
|
|
if !strings.Contains(parts[1], ".") {
|
|||
|
|
return false
|
|||
|
|
}
|
|||
|
|
return true
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ValidateStruct 验证结构体,返回格式化的错误信息
|
|||
|
|
func ValidateStruct(s interface{}) error {
|
|||
|
|
if err := validate.Struct(s); err != nil {
|
|||
|
|
return formatValidationError(err)
|
|||
|
|
}
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// formatValidationError 格式化验证错误信息
|
|||
|
|
func formatValidationError(err error) error {
|
|||
|
|
if validationErrors, ok := err.(validator.ValidationErrors); ok {
|
|||
|
|
var errMsg strings.Builder
|
|||
|
|
errMsg.WriteString("参数验证失败: ")
|
|||
|
|
for i, validationError := range validationErrors {
|
|||
|
|
if i > 0 {
|
|||
|
|
errMsg.WriteString("; ")
|
|||
|
|
}
|
|||
|
|
errMsg.WriteString(getFieldErrorMsg(validationError))
|
|||
|
|
}
|
|||
|
|
// 返回ErrInvalidArgument错误
|
|||
|
|
return errcode.ErrInvalidArgument
|
|||
|
|
}
|
|||
|
|
return errcode.ErrInvalidArgument
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// getFieldErrorMsg 获取字段错误信息
|
|||
|
|
func getFieldErrorMsg(fe validator.FieldError) string {
|
|||
|
|
field := fe.Field()
|
|||
|
|
tag := fe.Tag()
|
|||
|
|
|
|||
|
|
switch tag {
|
|||
|
|
case "required":
|
|||
|
|
return fmt.Sprintf("%s 字段为必填项", field)
|
|||
|
|
case "min":
|
|||
|
|
return fmt.Sprintf("%s 字段长度不能小于 %s", field, fe.Param())
|
|||
|
|
case "max":
|
|||
|
|
return fmt.Sprintf("%s 字段长度不能大于 %s", field, fe.Param())
|
|||
|
|
case "len":
|
|||
|
|
return fmt.Sprintf("%s 字段长度必须为 %s", field, fe.Param())
|
|||
|
|
case "email_format":
|
|||
|
|
return fmt.Sprintf("%s 字段邮箱格式不正确", field)
|
|||
|
|
case "phone":
|
|||
|
|
return fmt.Sprintf("%s 字段手机号格式不正确(应为11位数字)", field)
|
|||
|
|
case "gte":
|
|||
|
|
return fmt.Sprintf("%s 字段值必须大于或等于 %s", field, fe.Param())
|
|||
|
|
case "lte":
|
|||
|
|
return fmt.Sprintf("%s 字段值必须小于或等于 %s", field, fe.Param())
|
|||
|
|
case "gt":
|
|||
|
|
return fmt.Sprintf("%s 字段值必须大于 %s", field, fe.Param())
|
|||
|
|
case "lt":
|
|||
|
|
return fmt.Sprintf("%s 字段值必须小于 %s", field, fe.Param())
|
|||
|
|
default:
|
|||
|
|
return fmt.Sprintf("%s 字段验证失败 (%s)", field, tag)
|
|||
|
|
}
|
|||
|
|
}
|