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)
|
||
}
|
||
}
|