| 
									
										
										
										
											2025-07-20 20:53:26 +08:00
										 |  |  |  | package validator | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | import ( | 
					
						
							|  |  |  |  | 	"fmt" | 
					
						
							|  |  |  |  | 	"net/url" | 
					
						
							|  |  |  |  | 	"regexp" | 
					
						
							|  |  |  |  | 	"strings" | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	"github.com/go-playground/validator/v10" | 
					
						
							|  |  |  |  | ) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // BusinessValidator 业务验证器 | 
					
						
							|  |  |  |  | type BusinessValidator struct { | 
					
						
							|  |  |  |  | 	validator *validator.Validate | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // NewBusinessValidator 创建业务验证器 | 
					
						
							|  |  |  |  | func NewBusinessValidator() *BusinessValidator { | 
					
						
							|  |  |  |  | 	validate := validator.New() | 
					
						
							|  |  |  |  | 	RegisterCustomValidators(validate) | 
					
						
							|  |  |  |  | 	 | 
					
						
							|  |  |  |  | 	return &BusinessValidator{ | 
					
						
							|  |  |  |  | 		validator: validate, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ValidateStruct 验证结构体 | 
					
						
							|  |  |  |  | func (bv *BusinessValidator) ValidateStruct(data interface{}) error { | 
					
						
							|  |  |  |  | 	return bv.validator.Struct(data) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ValidateField 验证单个字段 | 
					
						
							|  |  |  |  | func (bv *BusinessValidator) ValidateField(field interface{}, tag string) error { | 
					
						
							|  |  |  |  | 	return bv.validator.Var(field, tag) | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // 以下是具体的业务验证方法,可以在业务逻辑中直接调用 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ValidatePhone 验证手机号 | 
					
						
							|  |  |  |  | func (bv *BusinessValidator) ValidatePhone(phone string) error { | 
					
						
							|  |  |  |  | 	if phone == "" { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("手机号不能为空") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	matched, _ := regexp.MatchString(`^1[3-9]\d{9}$`, phone) | 
					
						
							|  |  |  |  | 	if !matched { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("手机号格式不正确") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ValidatePassword 验证密码强度 | 
					
						
							|  |  |  |  | func (bv *BusinessValidator) ValidatePassword(password string) error { | 
					
						
							|  |  |  |  | 	if password == "" { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("密码不能为空") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if len(password) < 8 { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("密码长度不能少于8位") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	hasUpper := regexp.MustCompile(`[A-Z]`).MatchString(password) | 
					
						
							|  |  |  |  | 	hasLower := regexp.MustCompile(`[a-z]`).MatchString(password) | 
					
						
							|  |  |  |  | 	hasDigit := regexp.MustCompile(`\d`).MatchString(password) | 
					
						
							|  |  |  |  | 	 | 
					
						
							|  |  |  |  | 	if !hasUpper { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("密码必须包含大写字母") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if !hasLower { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("密码必须包含小写字母") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if !hasDigit { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("密码必须包含数字") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ValidateUsername 验证用户名 | 
					
						
							|  |  |  |  | func (bv *BusinessValidator) ValidateUsername(username string) error { | 
					
						
							|  |  |  |  | 	if username == "" { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("用户名不能为空") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	matched, _ := regexp.MatchString(`^[a-zA-Z][a-zA-Z0-9_]{2,19}$`, username) | 
					
						
							|  |  |  |  | 	if !matched { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("用户名格式不正确,只能包含字母、数字、下划线,且必须以字母开头,长度3-20位") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ValidateSocialCreditCode 验证统一社会信用代码 | 
					
						
							|  |  |  |  | func (bv *BusinessValidator) ValidateSocialCreditCode(code string) error { | 
					
						
							|  |  |  |  | 	if code == "" { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("统一社会信用代码不能为空") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	matched, _ := regexp.MatchString(`^[0-9A-HJ-NPQRTUWXY]{2}\d{6}[0-9A-HJ-NPQRTUWXY]{10}$`, code) | 
					
						
							|  |  |  |  | 	if !matched { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("统一社会信用代码格式不正确,必须是18位统一社会信用代码") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ValidateIDCard 验证身份证号 | 
					
						
							|  |  |  |  | func (bv *BusinessValidator) ValidateIDCard(idCard string) error { | 
					
						
							|  |  |  |  | 	if idCard == "" { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("身份证号不能为空") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	matched, _ := regexp.MatchString(`^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[\dXx]$`, idCard) | 
					
						
							|  |  |  |  | 	if !matched { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("身份证号格式不正确,必须是18位身份证号") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ValidateUUID 验证UUID | 
					
						
							|  |  |  |  | func (bv *BusinessValidator) ValidateUUID(uuid string) error { | 
					
						
							|  |  |  |  | 	if uuid == "" { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("UUID不能为空") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	matched, _ := regexp.MatchString(`^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`, uuid) | 
					
						
							|  |  |  |  | 	if !matched { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("UUID格式不正确") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ValidateURL 验证URL | 
					
						
							|  |  |  |  | func (bv *BusinessValidator) ValidateURL(urlStr string) error { | 
					
						
							|  |  |  |  | 	if urlStr == "" { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("URL不能为空") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	_, err := url.ParseRequestURI(urlStr) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("URL格式不正确: %v", err) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ValidateProductCode 验证产品代码 | 
					
						
							|  |  |  |  | func (bv *BusinessValidator) ValidateProductCode(code string) error { | 
					
						
							|  |  |  |  | 	if code == "" { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("产品代码不能为空") | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-08-18 18:18:04 +08:00
										 |  |  |  | 	matched, _ := regexp.MatchString(`^[a-zA-Z0-9_\-\(\)()]{3,50}$`, code) | 
					
						
							| 
									
										
										
										
											2025-07-20 20:53:26 +08:00
										 |  |  |  | 	if !matched { | 
					
						
							| 
									
										
										
										
											2025-08-18 18:18:04 +08:00
										 |  |  |  | 		return fmt.Errorf("产品代码格式不正确,只能包含字母、数字、下划线、连字符、中英文括号,长度3-50位") | 
					
						
							| 
									
										
										
										
											2025-07-20 20:53:26 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ValidateEmail 验证邮箱 | 
					
						
							|  |  |  |  | func (bv *BusinessValidator) ValidateEmail(email string) error { | 
					
						
							|  |  |  |  | 	if email == "" { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("邮箱不能为空") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	matched, _ := regexp.MatchString(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`, email) | 
					
						
							|  |  |  |  | 	if !matched { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("邮箱格式不正确") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ValidateSortOrder 验证排序方向 | 
					
						
							|  |  |  |  | func (bv *BusinessValidator) ValidateSortOrder(sortOrder string) error { | 
					
						
							|  |  |  |  | 	if sortOrder == "" { | 
					
						
							|  |  |  |  | 		return nil // 允许为空 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if sortOrder != "asc" && sortOrder != "desc" { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("排序方向必须是 asc 或 desc") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ValidatePrice 验证价格 | 
					
						
							|  |  |  |  | func (bv *BusinessValidator) ValidatePrice(price float64) error { | 
					
						
							|  |  |  |  | 	if price < 0 { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("价格不能为负数") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ValidateStringLength 验证字符串长度 | 
					
						
							|  |  |  |  | func (bv *BusinessValidator) ValidateStringLength(str string, fieldName string, min, max int) error { | 
					
						
							|  |  |  |  | 	length := len(strings.TrimSpace(str)) | 
					
						
							|  |  |  |  | 	if min > 0 && length < min { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("%s长度不能少于%d位", fieldName, min) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if max > 0 && length > max { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("%s长度不能超过%d位", fieldName, max) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ValidateRequired 验证必填字段 | 
					
						
							|  |  |  |  | func (bv *BusinessValidator) ValidateRequired(value interface{}, fieldName string) error { | 
					
						
							|  |  |  |  | 	if value == nil { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("%s不能为空", fieldName) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	 | 
					
						
							|  |  |  |  | 	switch v := value.(type) { | 
					
						
							|  |  |  |  | 	case string: | 
					
						
							|  |  |  |  | 		if strings.TrimSpace(v) == "" { | 
					
						
							|  |  |  |  | 			return fmt.Errorf("%s不能为空", fieldName) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	case *string: | 
					
						
							|  |  |  |  | 		if v == nil || strings.TrimSpace(*v) == "" { | 
					
						
							|  |  |  |  | 			return fmt.Errorf("%s不能为空", fieldName) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	 | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ValidateRange 验证数值范围 | 
					
						
							|  |  |  |  | func (bv *BusinessValidator) ValidateRange(value float64, fieldName string, min, max float64) error { | 
					
						
							|  |  |  |  | 	if value < min { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("%s不能小于%v", fieldName, min) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if value > max { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("%s不能大于%v", fieldName, max) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // ValidateSliceNotEmpty 验证切片不为空 | 
					
						
							|  |  |  |  | func (bv *BusinessValidator) ValidateSliceNotEmpty(slice interface{}, fieldName string) error { | 
					
						
							|  |  |  |  | 	if slice == nil { | 
					
						
							|  |  |  |  | 		return fmt.Errorf("%s不能为空", fieldName) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	 | 
					
						
							|  |  |  |  | 	switch v := slice.(type) { | 
					
						
							|  |  |  |  | 	case []string: | 
					
						
							|  |  |  |  | 		if len(v) == 0 { | 
					
						
							|  |  |  |  | 			return fmt.Errorf("%s不能为空", fieldName) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	case []int: | 
					
						
							|  |  |  |  | 		if len(v) == 0 { | 
					
						
							|  |  |  |  | 			return fmt.Errorf("%s不能为空", fieldName) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	 | 
					
						
							|  |  |  |  | 	return nil | 
					
						
							|  |  |  |  | }  |