Files
tyapi-server/internal/shared/validator/custom_validators.go
2025-09-20 17:46:33 +08:00

871 lines
24 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package validator
import (
"fmt"
"net/url"
"regexp"
"strconv"
"strings"
"time"
"github.com/go-playground/validator/v10"
)
// RegisterCustomValidators 注册所有自定义验证器
func RegisterCustomValidators(validate *validator.Validate) {
// 手机号验证器
validate.RegisterValidation("phone", validatePhone)
// 用户名验证器字母开头允许字母数字下划线3-20位
validate.RegisterValidation("username", validateUsername)
// 强密码验证器至少8位包含大小写字母和数字
validate.RegisterValidation("strong_password", validateStrongPassword)
// 统一社会信用代码验证器
validate.RegisterValidation("social_credit_code", validateSocialCreditCode)
// 姓名验证器不能为空字符串长度1-50字符
validate.RegisterValidation("validName", validateName)
// 身份证号验证器(兼容两种标签)
validate.RegisterValidation("validIDCard", validateIDCard)
validate.RegisterValidation("id_card", validateIDCard)
// 统一社会信用代码验证器
validate.RegisterValidation("validUSCI", validateUSCI)
// 手机号验证器
validate.RegisterValidation("validMobileNo", validateMobileNo)
// 手机类型验证器
validate.RegisterValidation("validMobileType", validateMobileType)
// 日期验证器
validate.RegisterValidation("validDate", validateDate)
// 时间范围验证器
validate.RegisterValidation("validTimeRange", validateTimeRange)
// 银行卡验证器
validate.RegisterValidation("validBankCard", validateBankCard)
// 价格验证器(非负数)
validate.RegisterValidation("price", validatePrice)
// 排序方向验证器
validate.RegisterValidation("sort_order", validateSortOrder)
// 产品代码验证器字母数字下划线连字符3-50位
validate.RegisterValidation("product_code", validateProductCode)
// UUID验证器
validate.RegisterValidation("uuid", validateUUID)
// URL验证器
validate.RegisterValidation("url", validateURL)
// 企业邮箱验证器
validate.RegisterValidation("enterprise_email", validateEnterpriseEmail)
// 企业地址验证器
validate.RegisterValidation("enterprise_address", validateEnterpriseAddress)
// IP地址验证器
validate.RegisterValidation("ip", validateIP)
// 非空字符串验证器(不能为空字符串或只包含空格)
validate.RegisterValidation("notEmpty", validateNotEmpty)
// 授权日期验证器
validate.RegisterValidation("auth_date", validateAuthDate)
validate.RegisterValidation("validAuthDate", validateAuthDate)
// 授权书URL验证器
validate.RegisterValidation("authorization_url", validateAuthorizationURL)
// 唯一标识验证器小于等于32位字符串
validate.RegisterValidation("validUniqueID", validateUniqueID)
// 回调地址验证器
validate.RegisterValidation("validReturnURL", validateReturnURL)
// 企业名称验证器
validate.RegisterValidation("enterprise_name", validateEnterpriseName)
validate.RegisterValidation("validEnterpriseName", validateEnterpriseName)
}
// validatePhone 手机号验证
func validatePhone(fl validator.FieldLevel) bool {
phone := fl.Field().String()
matched, _ := regexp.MatchString(`^1[3-9]\d{9}$`, phone)
return matched
}
// validateUsername 用户名验证
func validateUsername(fl validator.FieldLevel) bool {
username := fl.Field().String()
matched, _ := regexp.MatchString(`^[a-zA-Z][a-zA-Z0-9_]{2,19}$`, username)
return matched
}
// validateStrongPassword 强密码验证
func validateStrongPassword(fl validator.FieldLevel) bool {
password := fl.Field().String()
if len(password) < 8 {
return false
}
hasUpper := regexp.MustCompile(`[A-Z]`).MatchString(password)
hasLower := regexp.MustCompile(`[a-z]`).MatchString(password)
hasDigit := regexp.MustCompile(`\d`).MatchString(password)
return hasUpper && hasLower && hasDigit
}
// validateSocialCreditCode 统一社会信用代码验证
func validateSocialCreditCode(fl validator.FieldLevel) bool {
code := fl.Field().String()
matched, _ := regexp.MatchString(`^[0-9A-HJ-NPQRTUWXY]{2}\d{6}[0-9A-HJ-NPQRTUWXY]{10}$`, code)
return matched
}
// validateIDCard 身份证号验证
func validateIDCard(fl validator.FieldLevel) bool {
idCard := fl.Field().String()
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)
return matched
}
// validatePrice 价格验证
func validatePrice(fl validator.FieldLevel) bool {
price := fl.Field().Float()
return price >= 0
}
// validateSortOrder 排序方向验证
func validateSortOrder(fl validator.FieldLevel) bool {
sortOrder := fl.Field().String()
return sortOrder == "" || sortOrder == "asc" || sortOrder == "desc"
}
// validateProductCode 产品代码验证
func validateProductCode(fl validator.FieldLevel) bool {
code := fl.Field().String()
matched, _ := regexp.MatchString(`^[a-zA-Z0-9_-]{3,50}$`, code)
return matched
}
// validateUUID UUID验证
func validateUUID(fl validator.FieldLevel) bool {
uuid := fl.Field().String()
matched, _ := regexp.MatchString(`^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`, uuid)
return matched
}
// validateURL URL验证
func validateURL(fl validator.FieldLevel) bool {
urlStr := fl.Field().String()
_, err := url.ParseRequestURI(urlStr)
return err == nil
}
// validateEnterpriseEmail 企业邮箱验证
func validateEnterpriseEmail(fl validator.FieldLevel) bool {
email := fl.Field().String()
// 邮箱格式验证:用户名@域名.顶级域名
matched, _ := regexp.MatchString(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`, email)
return matched
}
// validateEnterpriseAddress 企业地址验证
func validateEnterpriseAddress(fl validator.FieldLevel) bool {
address := fl.Field().String()
// 地址长度验证2-200字符不能只包含空格
if len(strings.TrimSpace(address)) < 2 || len(address) > 200 {
return false
}
// 地址不能只包含特殊字符
matched, _ := regexp.MatchString(`^[^\s]+.*[^\s]+$`, strings.TrimSpace(address))
return matched
}
// validateIP IP地址验证支持IPv4
func validateIP(fl validator.FieldLevel) bool {
ip := fl.Field().String()
// 使用正则表达式验证IPv4格式
pattern := `^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$`
matched, _ := regexp.MatchString(pattern, ip)
return matched
}
// validateName 姓名验证器
func validateName(fl validator.FieldLevel) bool {
name := fl.Field().String()
// 去除首尾空格后检查长度
trimmedName := strings.TrimSpace(name)
if len(trimmedName) < 1 || len(trimmedName) > 50 {
return false
}
// 姓名不能只包含空格或特殊字符
// 必须包含至少一个中文字符或英文字母
hasValidChar := regexp.MustCompile(`[\p{Han}a-zA-Z]`).MatchString(trimmedName)
return hasValidChar
}
// validateAuthDate 授权日期验证器
// 格式YYYYMMDD-YYYYMMDD之前的日期范围必须包括今天
func validateAuthDate(fl validator.FieldLevel) bool {
authDate := fl.Field().String()
if authDate == "" {
return true // 空值由required标签处理
}
// 检查格式YYYYMMDD-YYYYMMDD
parts := strings.Split(authDate, "-")
if len(parts) != 2 {
return false
}
startDateStr := parts[0]
endDateStr := parts[1]
// 检查日期格式是否为8位数字
if len(startDateStr) != 8 || len(endDateStr) != 8 {
return false
}
// 解析开始日期
startDate, err := parseYYYYMMDD(startDateStr)
if err != nil {
return false
}
// 解析结束日期
endDate, err := parseYYYYMMDD(endDateStr)
if err != nil {
return false
}
// 检查开始日期不能晚于结束日期
if startDate.After(endDate) {
return false
}
// 获取今天的日期(去掉时间部分)
today := time.Now().Truncate(24 * time.Hour)
// 检查日期范围是否包括今天
// 如果两个日期都是今天也行
return !startDate.After(today) && !endDate.Before(today)
}
// parseYYYYMMDD 解析YYYYMMDD格式的日期字符串
func parseYYYYMMDD(dateStr string) (time.Time, error) {
if len(dateStr) != 8 {
return time.Time{}, fmt.Errorf("日期格式错误")
}
year, err := strconv.Atoi(dateStr[:4])
if err != nil {
return time.Time{}, err
}
month, err := strconv.Atoi(dateStr[4:6])
if err != nil {
return time.Time{}, err
}
day, err := strconv.Atoi(dateStr[6:8])
if err != nil {
return time.Time{}, err
}
// 验证日期有效性
date := time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC)
// 检查解析后的日期是否与输入一致防止无效日期如20230230
expectedDateStr := date.Format("20060102")
if expectedDateStr != dateStr {
return time.Time{}, fmt.Errorf("无效日期")
}
return date, nil
}
// validateUSCI 统一社会信用代码验证器
func validateUSCI(fl validator.FieldLevel) bool {
usci := fl.Field().String()
// 统一社会信用代码格式18位由数字和大写字母组成
// 格式1位登记管理部门代码 + 1位机构类别代码 + 6位登记管理机关行政区划码 + 9位主体标识码 + 1位校验码
matched, _ := regexp.MatchString(`^[0-9A-HJ-NPQRTUWXY]{2}\d{6}[0-9A-HJ-NPQRTUWXY]{10}$`, usci)
return matched
}
// validateMobileNo 手机号验证器
func validateMobileNo(fl validator.FieldLevel) bool {
mobile := fl.Field().String()
// 中国手机号格式1开头第二位是3-9总共11位数字
matched, _ := regexp.MatchString(`^1[3-9]\d{9}$`, mobile)
return matched
}
// validateMobileType 手机类型验证器
func validateMobileType(fl validator.FieldLevel) bool {
mobileType := fl.Field().String()
// 手机类型:移动、联通、电信等
validTypes := []string{"移动", "联通", "电信", "广电", "虚拟运营商"}
for _, validType := range validTypes {
if mobileType == validType {
return true
}
}
return false
}
// validateDate 日期验证器
func validateDate(fl validator.FieldLevel) bool {
dateStr := fl.Field().String()
// 检查日期格式YYYY-MM-DD
matched, _ := regexp.MatchString(`^\d{4}-\d{2}-\d{2}$`, dateStr)
if !matched {
return false
}
// 尝试解析日期
_, err := time.Parse("2006-01-02", dateStr)
return err == nil
}
// validateTimeRange 时间范围验证器
func validateTimeRange(fl validator.FieldLevel) bool {
timeRange := fl.Field().String()
if timeRange == "" {
return true // 空值由omitempty标签处理
}
// 时间范围格式HH:MM-HH:MM
parts := strings.Split(timeRange, "-")
if len(parts) != 2 {
return false
}
startTime := parts[0]
endTime := parts[1]
// 检查时间格式HH:MM
timePattern := `^([01]?[0-9]|2[0-3]):[0-5][0-9]$`
startMatched, _ := regexp.MatchString(timePattern, startTime)
endMatched, _ := regexp.MatchString(timePattern, endTime)
if !startMatched || !endMatched {
return false
}
// 检查开始时间不能晚于结束时间
start, _ := time.Parse("15:04", startTime)
end, _ := time.Parse("15:04", endTime)
return start.Before(end) || start.Equal(end)
}
// validateNotEmpty 非空字符串验证器
func validateNotEmpty(fl validator.FieldLevel) bool {
value := fl.Field().String()
// 去除首尾空格后检查是否为空
trimmedValue := strings.TrimSpace(value)
return len(trimmedValue) > 0
}
// validateBankCard 银行卡验证器
func validateBankCard(fl validator.FieldLevel) bool {
bankCard := fl.Field().String()
// 银行卡号格式13-19位数字
matched, _ := regexp.MatchString(`^\d{13,19}$`, bankCard)
if !matched {
return false
}
// 使用Luhn算法验证银行卡号
return validateLuhn(bankCard)
}
// validateLuhn Luhn算法验证银行卡号
func validateLuhn(cardNumber string) bool {
sum := 0
alternate := false
// 从右到左遍历
for i := len(cardNumber) - 1; i >= 0; i-- {
digit, err := strconv.Atoi(string(cardNumber[i]))
if err != nil {
return false
}
if alternate {
digit *= 2
if digit > 9 {
digit = digit%10 + digit/10
}
}
sum += digit
alternate = !alternate
}
return sum%10 == 0
}
// validateAuthorizationURL 授权书URL验证器
func validateAuthorizationURL(fl validator.FieldLevel) bool {
urlStr := fl.Field().String()
if urlStr == "" {
return true // 空值由required标签处理
}
// 解析URL
parsedURL, err := url.Parse(urlStr)
if err != nil {
return false
}
// 检查协议
if parsedURL.Scheme != "http" && parsedURL.Scheme != "https" {
return false
}
// 检查文件扩展名
path := parsedURL.Path
validExtensions := []string{".pdf", ".jpg", ".jpeg", ".png", ".bmp"}
hasValidExtension := false
for _, ext := range validExtensions {
if strings.HasSuffix(strings.ToLower(path), ext) {
hasValidExtension = true
break
}
}
return hasValidExtension
}
// validateUniqueID 唯一标识验证器小于等于32位字符串
func validateUniqueID(fl validator.FieldLevel) bool {
uniqueID := fl.Field().String()
if uniqueID == "" {
return true // 空值由required标签处理
}
// 检查长度小于等于32位
if len(uniqueID) > 32 {
return false
}
// 检查是否只包含允许的字符:字母、数字、下划线、连字符
matched, _ := regexp.MatchString(`^[a-zA-Z0-9_-]+$`, uniqueID)
return matched
}
// validateReturnURL 回调地址验证器
func validateReturnURL(fl validator.FieldLevel) bool {
returnURL := fl.Field().String()
if returnURL == "" {
return true // 空值由required标签处理
}
// 检查长度不能超过500字符
if len(returnURL) > 500 {
return false
}
// 检查URL格式
parsedURL, err := url.Parse(returnURL)
if err != nil {
return false
}
// 检查协议只允许http和https
if parsedURL.Scheme != "http" && parsedURL.Scheme != "https" {
return false
}
// 检查是否有域名
if parsedURL.Host == "" {
return false
}
return true
}
// validateEnterpriseName 企业名称验证器
func validateEnterpriseName(fl validator.FieldLevel) bool {
enterpriseName := fl.Field().String()
// 去除首尾空格
trimmedName := strings.TrimSpace(enterpriseName)
if trimmedName == "" {
return false
}
// 长度验证2-100个字符
if len(trimmedName) < 2 || len(trimmedName) > 100 {
return false
}
// 检查是否包含非法字符(允许中英文括号)
invalidChars := []string{
"`", "~", "!", "@", "#", "$", "%", "^", "&", "*",
"+", "=", "{", "}", "[", "]", "\\", "|", ";", ":", "'", "\"", "<", ">", ",", ".", "?", "/",
}
for _, char := range invalidChars {
if strings.Contains(trimmedName, char) {
return false
}
}
// 必须包含至少一个中文字符或英文字母
hasValidChar := regexp.MustCompile(`[\p{Han}a-zA-Z]`).MatchString(trimmedName)
if !hasValidChar {
return false
}
// 验证企业名称的基本格式(支持各种类型的企业)
// 支持:有限公司、股份有限公司、工作室、个体工商户、合伙企业等
validSuffixes := []string{
"有限公司", "有限责任公司", "股份有限公司", "股份公司",
"工作室", "个体工商户", "个人独资企业", "合伙企业",
"集团有限公司", "集团股份有限公司",
"Co.,Ltd", "Co., Ltd", "Ltd", "LLC", "Inc", "Corp",
"Company", "Studio", "Workshop", "Enterprise",
}
// 检查是否以合法的企业类型结尾(不强制要求,因为有些企业名称可能没有标准后缀)
// 但如果有后缀,必须是合法的
hasValidSuffix := false
for _, suffix := range validSuffixes {
if strings.HasSuffix(trimmedName, suffix) {
hasValidSuffix = true
break
}
}
// 如果名称中包含常见的企业类型关键词,则必须是合法的后缀
enterpriseKeywords := []string{"公司", "工作室", "企业", "集团", "Co", "Ltd", "LLC", "Inc", "Corp", "Company", "Studio", "Workshop", "Enterprise"}
containsKeyword := false
for _, keyword := range enterpriseKeywords {
if strings.Contains(trimmedName, keyword) {
containsKeyword = true
break
}
}
// 如果包含企业关键词但没有合法后缀,则验证失败
if containsKeyword && !hasValidSuffix {
return false
}
return true
}
// ================ 统一的业务校验方法 ================
// ValidatePhone 验证手机号
func 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 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 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 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 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 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 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 ValidateProductCode(code string) error {
if code == "" {
return fmt.Errorf("产品代码不能为空")
}
matched, _ := regexp.MatchString(`^[a-zA-Z0-9_\-\(\)]{3,50}$`, code)
if !matched {
return fmt.Errorf("产品代码格式不正确只能包含字母、数字、下划线、连字符、中英文括号长度3-50位")
}
return nil
}
// ValidateEmail 验证邮箱
func 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 ValidateSortOrder(sortOrder string) error {
if sortOrder == "" {
return nil // 允许为空
}
if sortOrder != "asc" && sortOrder != "desc" {
return fmt.Errorf("排序方向必须是 asc 或 desc")
}
return nil
}
// ValidatePrice 验证价格
func ValidatePrice(price float64) error {
if price < 0 {
return fmt.Errorf("价格不能为负数")
}
return nil
}
// ValidateStringLength 验证字符串长度
func 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 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 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 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
}
// ValidateEnterpriseName 验证企业名称
func ValidateEnterpriseName(enterpriseName string) error {
if enterpriseName == "" {
return fmt.Errorf("企业名称不能为空")
}
// 去除首尾空格
trimmedName := strings.TrimSpace(enterpriseName)
if trimmedName == "" {
return fmt.Errorf("企业名称不能为空")
}
// 长度验证2-100个字符
if len(trimmedName) < 2 {
return fmt.Errorf("企业名称长度不能少于2个字符")
}
if len(trimmedName) > 100 {
return fmt.Errorf("企业名称长度不能超过100个字符")
}
// 检查是否包含非法字符(允许中英文括号)
invalidChars := []string{
"`", "~", "!", "@", "#", "$", "%", "^", "&", "*",
"+", "=", "{", "}", "[", "]", "\\", "|", ";", ":", "'", "\"", "<", ">", ",", ".", "?", "/",
}
for _, char := range invalidChars {
if strings.Contains(trimmedName, char) {
return fmt.Errorf("企业名称不能包含特殊字符: %s", char)
}
}
// 必须包含至少一个中文字符或英文字母
hasValidChar := regexp.MustCompile(`[\p{Han}a-zA-Z]`).MatchString(trimmedName)
if !hasValidChar {
return fmt.Errorf("企业名称必须包含中文字符或英文字母")
}
// 验证企业名称的基本格式(支持各种类型的企业)
// 支持:有限公司、股份有限公司、工作室、个体工商户、合伙企业等
validSuffixes := []string{
"有限公司", "有限责任公司", "股份有限公司", "股份公司",
"工作室", "个体工商户", "个人独资企业", "合伙企业",
"集团有限公司", "集团股份有限公司",
"Co.,Ltd", "Co., Ltd", "Ltd", "LLC", "Inc", "Corp",
"Company", "Studio", "Workshop", "Enterprise",
}
// 检查是否以合法的企业类型结尾
hasValidSuffix := false
for _, suffix := range validSuffixes {
if strings.HasSuffix(trimmedName, suffix) {
hasValidSuffix = true
break
}
}
// 如果名称中包含常见的企业类型关键词,则必须是合法的后缀
enterpriseKeywords := []string{"公司", "工作室", "企业", "集团", "Co", "Ltd", "LLC", "Inc", "Corp", "Company", "Studio", "Workshop", "Enterprise"}
containsKeyword := false
for _, keyword := range enterpriseKeywords {
if strings.Contains(trimmedName, keyword) {
containsKeyword = true
break
}
}
// 如果包含企业关键词但没有合法后缀,则验证失败
if containsKeyword && !hasValidSuffix {
return fmt.Errorf("企业名称格式不正确,请使用标准的企业类型后缀(如:有限公司、工作室等)")
}
return nil
}
// ================ 便捷的校验器创建函数 ================
// NewBusinessValidator 创建业务验证器(保持向后兼容)
func NewBusinessValidator() *BusinessValidator {
// 确保全局校验器已初始化
InitGlobalValidator()
return &BusinessValidator{
validator: GetGlobalValidator(), // 使用全局校验器
}
}
// BusinessValidator 业务验证器(保持向后兼容)
type BusinessValidator struct {
validator *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)
}