v0.1
This commit is contained in:
246
internal/shared/validator/AUTH_DATE_VALIDATOR.md
Normal file
246
internal/shared/validator/AUTH_DATE_VALIDATOR.md
Normal file
@@ -0,0 +1,246 @@
|
||||
# AuthDate 授权日期验证器
|
||||
|
||||
## 概述
|
||||
|
||||
`authDate` 是一个自定义验证器,用于验证授权日期格式和有效性。该验证器确保日期格式正确,并且日期范围必须包括今天。
|
||||
|
||||
## 验证规则
|
||||
|
||||
### 1. 格式要求
|
||||
- 必须为 `YYYYMMDD-YYYYMMDD` 格式
|
||||
- 两个日期之间用连字符 `-` 分隔
|
||||
- 每个日期必须是8位数字
|
||||
|
||||
### 2. 日期有效性
|
||||
- 开始日期不能晚于结束日期
|
||||
- 日期范围必须包括今天(如果两个日期都是今天也行)
|
||||
- 支持闰年验证
|
||||
- 验证月份和日期的有效性
|
||||
|
||||
### 3. 业务逻辑
|
||||
- 空值由 `required` 标签处理,本验证器返回 `true`
|
||||
- 日期范围必须覆盖今天,确保授权在有效期内
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 在 DTO 中使用
|
||||
|
||||
```go
|
||||
type FLXG0V4BReq struct {
|
||||
Name string `json:"name" validate:"required,name"`
|
||||
IDCard string `json:"id_card" validate:"required,idCard"`
|
||||
AuthDate string `json:"auth_date" validate:"required,authDate"`
|
||||
}
|
||||
```
|
||||
|
||||
### 在结构体中使用
|
||||
|
||||
```go
|
||||
type AuthorizationRequest struct {
|
||||
UserID string `json:"user_id" validate:"required"`
|
||||
AuthDate string `json:"auth_date" validate:"required,authDate"`
|
||||
Scope string `json:"scope" validate:"required"`
|
||||
}
|
||||
```
|
||||
|
||||
## 有效示例
|
||||
|
||||
### ✅ 有效的日期范围
|
||||
|
||||
```json
|
||||
{
|
||||
"auth_date": "20240101-20240131" // 1月1日到1月31日(如果今天是1月15日)
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"auth_date": "20240115-20240115" // 今天到今天
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"auth_date": "20240110-20240120" // 昨天到明天(如果今天是1月15日)
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"auth_date": "20240101-20240201" // 上个月到下个月(如果今天是1月15日)
|
||||
}
|
||||
```
|
||||
|
||||
### ❌ 无效的日期范围
|
||||
|
||||
```json
|
||||
{
|
||||
"auth_date": "20240116-20240120" // 明天到后天(不包括今天)
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"auth_date": "20240101-20240114" // 上个月到昨天(不包括今天)
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"auth_date": "20240131-20240101" // 开始日期晚于结束日期
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"auth_date": "20240101-2024013A" // 非数字字符
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"auth_date": "202401-20240131" // 日期长度不对
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"auth_date": "2024010120240131" // 缺少连字符
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"auth_date": "20240230-20240301" // 无效日期(2月30日)
|
||||
}
|
||||
```
|
||||
|
||||
## 错误消息
|
||||
|
||||
当验证失败时,会返回中文错误消息:
|
||||
|
||||
```
|
||||
"授权日期格式不正确,必须是YYYYMMDD-YYYYMMDD格式,且日期范围必须包括今天"
|
||||
```
|
||||
|
||||
## 测试用例
|
||||
|
||||
验证器包含完整的测试用例,覆盖以下场景:
|
||||
|
||||
### 有效场景
|
||||
- 今天到今天
|
||||
- 昨天到今天
|
||||
- 今天到明天
|
||||
- 上周到今天
|
||||
- 今天到下周
|
||||
- 昨天到明天
|
||||
|
||||
### 无效场景
|
||||
- 明天到后天(不包括今天)
|
||||
- 上周到昨天(不包括今天)
|
||||
- 格式错误(缺少连字符、多个连字符、长度不对、非数字)
|
||||
- 无效日期(2月30日、13月等)
|
||||
- 开始日期晚于结束日期
|
||||
|
||||
## 实现细节
|
||||
|
||||
### 核心验证逻辑
|
||||
|
||||
```go
|
||||
func validateAuthDate(fl validator.FieldLevel) bool {
|
||||
authDate := fl.Field().String()
|
||||
if authDate == "" {
|
||||
return true // 空值由required标签处理
|
||||
}
|
||||
|
||||
// 1. 检查格式:YYYYMMDD-YYYYMMDD
|
||||
parts := strings.Split(authDate, "-")
|
||||
if len(parts) != 2 {
|
||||
return false
|
||||
}
|
||||
|
||||
// 2. 解析日期
|
||||
startDate, err := parseYYYYMMDD(parts[0])
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
endDate, err := parseYYYYMMDD(parts[1])
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// 3. 检查日期顺序
|
||||
if startDate.After(endDate) {
|
||||
return false
|
||||
}
|
||||
|
||||
// 4. 检查是否包括今天
|
||||
today := time.Now().Truncate(24 * time.Hour)
|
||||
return !startDate.After(today) && !endDate.Before(today)
|
||||
}
|
||||
```
|
||||
|
||||
### 日期解析
|
||||
|
||||
```go
|
||||
func parseYYYYMMDD(dateStr string) (time.Time, error) {
|
||||
if len(dateStr) != 8 {
|
||||
return time.Time{}, fmt.Errorf("日期格式错误")
|
||||
}
|
||||
|
||||
year, _ := strconv.Atoi(dateStr[:4])
|
||||
month, _ := strconv.Atoi(dateStr[4:6])
|
||||
day, _ := strconv.Atoi(dateStr[6:8])
|
||||
|
||||
date := time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
// 验证日期有效性
|
||||
expectedDateStr := date.Format("20060102")
|
||||
if expectedDateStr != dateStr {
|
||||
return time.Time{}, fmt.Errorf("无效日期")
|
||||
}
|
||||
|
||||
return date, nil
|
||||
}
|
||||
```
|
||||
|
||||
## 注册方式
|
||||
|
||||
验证器已在 `RegisterCustomValidators` 函数中自动注册:
|
||||
|
||||
```go
|
||||
func RegisterCustomValidators(validate *validator.Validate) {
|
||||
// ... 其他验证器
|
||||
validate.RegisterValidation("auth_date", validateAuthDate)
|
||||
}
|
||||
```
|
||||
|
||||
翻译也已自动注册:
|
||||
|
||||
```go
|
||||
validate.RegisterTranslation("auth_date", trans, func(ut ut.Translator) error {
|
||||
return ut.Add("auth_date", "{0}格式不正确,必须是YYYYMMDD-YYYYMMDD格式,且日期范围必须包括今天", true)
|
||||
}, func(ut ut.Translator, fe validator.FieldError) string {
|
||||
t, _ := ut.T("auth_date", getFieldDisplayName(fe.Field()))
|
||||
return t
|
||||
})
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **时区处理**:验证器使用 UTC 时区进行日期比较
|
||||
2. **空值处理**:空字符串由 `required` 标签处理,本验证器返回 `true`
|
||||
3. **日期精度**:只比较日期部分,忽略时间部分
|
||||
4. **闰年支持**:自动处理闰年验证
|
||||
5. **错误消息**:提供中文错误消息,便于用户理解
|
||||
|
||||
## 运行测试
|
||||
|
||||
```bash
|
||||
# 运行所有 authDate 相关测试
|
||||
go test ./internal/shared/validator -v -run TestValidateAuthDate
|
||||
|
||||
# 运行所有验证器测试
|
||||
go test ./internal/shared/validator -v
|
||||
```
|
||||
180
internal/shared/validator/auth_date_test.go
Normal file
180
internal/shared/validator/auth_date_test.go
Normal file
@@ -0,0 +1,180 @@
|
||||
package validator
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
)
|
||||
|
||||
func TestValidateAuthDate(t *testing.T) {
|
||||
validate := validator.New()
|
||||
validate.RegisterValidation("auth_date", validateAuthDate)
|
||||
|
||||
today := time.Now().Format("20060102")
|
||||
yesterday := time.Now().AddDate(0, 0, -1).Format("20060102")
|
||||
tomorrow := time.Now().AddDate(0, 0, 1).Format("20060102")
|
||||
lastWeek := time.Now().AddDate(0, 0, -7).Format("20060102")
|
||||
nextWeek := time.Now().AddDate(0, 0, 7).Format("20060102")
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
authDate string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "今天到今天 - 有效",
|
||||
authDate: today + "-" + today,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "昨天到今天 - 有效",
|
||||
authDate: yesterday + "-" + today,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "今天到明天 - 有效",
|
||||
authDate: today + "-" + tomorrow,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "上周到今天 - 有效",
|
||||
authDate: lastWeek + "-" + today,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "今天到下周 - 有效",
|
||||
authDate: today + "-" + nextWeek,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "昨天到明天 - 有效",
|
||||
authDate: yesterday + "-" + tomorrow,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "明天到后天 - 无效(不包括今天)",
|
||||
authDate: tomorrow + "-" + time.Now().AddDate(0, 0, 2).Format("20060102"),
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "上周到昨天 - 无效(不包括今天)",
|
||||
authDate: lastWeek + "-" + yesterday,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "格式错误 - 缺少连字符",
|
||||
authDate: "2024010120240131",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "格式错误 - 多个连字符",
|
||||
authDate: "20240101-20240131-20240201",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "格式错误 - 日期长度不对",
|
||||
authDate: "202401-20240131",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "格式错误 - 非数字",
|
||||
authDate: "20240101-2024013A",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "无效日期 - 2月30日",
|
||||
authDate: "20240230-20240301",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "无效日期 - 13月",
|
||||
authDate: "20241301-20241331",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "开始日期晚于结束日期",
|
||||
authDate: "20240131-20240101",
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "空字符串 - 由required处理",
|
||||
authDate: "",
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := validate.Var(tt.authDate, "auth_date")
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("validateAuthDate() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseYYYYMMDD(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
dateStr string
|
||||
want time.Time
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "有效日期",
|
||||
dateStr: "20240101",
|
||||
want: time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "闰年2月29日",
|
||||
dateStr: "20240229",
|
||||
want: time.Date(2024, 2, 29, 0, 0, 0, 0, time.UTC),
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "非闰年2月29日",
|
||||
dateStr: "20230229",
|
||||
want: time.Time{},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "长度错误",
|
||||
dateStr: "202401",
|
||||
want: time.Time{},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "非数字",
|
||||
dateStr: "2024010A",
|
||||
want: time.Time{},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "无效月份",
|
||||
dateStr: "20241301",
|
||||
want: time.Time{},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "无效日期",
|
||||
dateStr: "20240230",
|
||||
want: time.Time{},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := parseYYYYMMDD(tt.dateStr)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("parseYYYYMMDD() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !tt.wantErr && !got.Equal(tt.want) {
|
||||
t.Errorf("parseYYYYMMDD() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,12 @@
|
||||
package validator
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
)
|
||||
@@ -38,6 +42,18 @@ func RegisterCustomValidators(validate *validator.Validate) {
|
||||
|
||||
// URL验证器
|
||||
validate.RegisterValidation("url", validateURL)
|
||||
|
||||
// 企业邮箱验证器
|
||||
validate.RegisterValidation("enterprise_email", validateEnterpriseEmail)
|
||||
|
||||
// 企业地址验证器
|
||||
validate.RegisterValidation("enterprise_address", validateEnterpriseAddress)
|
||||
|
||||
// IP地址验证器
|
||||
validate.RegisterValidation("ip", validateIP)
|
||||
|
||||
// 授权日期验证器
|
||||
validate.RegisterValidation("auth_date", validateAuthDate)
|
||||
}
|
||||
|
||||
// validatePhone 手机号验证
|
||||
@@ -111,4 +127,113 @@ 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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
@@ -162,6 +162,38 @@ func registerCustomFieldTranslations(validate *validator.Validate, trans ut.Tran
|
||||
t, _ := ut.T("url", getFieldDisplayName(fe.Field()))
|
||||
return t
|
||||
})
|
||||
|
||||
// 企业邮箱翻译
|
||||
validate.RegisterTranslation("enterprise_email", trans, func(ut ut.Translator) error {
|
||||
return ut.Add("enterprise_email", "{0}必须是有效的企业邮箱地址", true)
|
||||
}, func(ut ut.Translator, fe validator.FieldError) string {
|
||||
t, _ := ut.T("enterprise_email", getFieldDisplayName(fe.Field()))
|
||||
return t
|
||||
})
|
||||
|
||||
// 企业地址翻译
|
||||
validate.RegisterTranslation("enterprise_address", trans, func(ut ut.Translator) error {
|
||||
return ut.Add("enterprise_address", "{0}长度必须在2-200字符之间,且不能只包含空格", true)
|
||||
}, func(ut ut.Translator, fe validator.FieldError) string {
|
||||
t, _ := ut.T("enterprise_address", getFieldDisplayName(fe.Field()))
|
||||
return t
|
||||
})
|
||||
|
||||
// IP地址翻译
|
||||
validate.RegisterTranslation("ip", trans, func(ut ut.Translator) error {
|
||||
return ut.Add("ip", "{0}必须是有效的IPv4地址格式", true)
|
||||
}, func(ut ut.Translator, fe validator.FieldError) string {
|
||||
t, _ := ut.T("ip", getFieldDisplayName(fe.Field()))
|
||||
return t
|
||||
})
|
||||
|
||||
// 授权日期翻译
|
||||
validate.RegisterTranslation("auth_date", trans, func(ut ut.Translator) error {
|
||||
return ut.Add("auth_date", "{0}格式不正确,必须是YYYYMMDD-YYYYMMDD格式,且日期范围必须包括今天", true)
|
||||
}, func(ut ut.Translator, fe validator.FieldError) string {
|
||||
t, _ := ut.T("auth_date", getFieldDisplayName(fe.Field()))
|
||||
return t
|
||||
})
|
||||
}
|
||||
|
||||
// getFieldDisplayName 获取字段显示名称(中文)
|
||||
@@ -176,6 +208,9 @@ func getFieldDisplayName(field string) string {
|
||||
"code": "验证码",
|
||||
"username": "用户名",
|
||||
"email": "邮箱",
|
||||
"enterprise_email": "企业邮箱",
|
||||
"enterprise_address": "企业地址",
|
||||
"ip_address": "IP地址",
|
||||
"display_name": "显示名称",
|
||||
"scene": "使用场景",
|
||||
"Password": "密码",
|
||||
@@ -244,6 +279,10 @@ func getFieldDisplayName(field string) string {
|
||||
"ID": "ID",
|
||||
"ids": "ID列表",
|
||||
"IDs": "ID列表",
|
||||
"auth_date": "授权日期",
|
||||
"AuthDate": "授权日期",
|
||||
"id_card": "身份证号",
|
||||
"IDCard": "身份证号",
|
||||
}
|
||||
|
||||
if displayName, exists := fieldNames[field]; exists {
|
||||
|
||||
@@ -65,7 +65,7 @@ func (v *RequestValidator) ValidateQuery(c *gin.Context, dto interface{}) error
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ func (v *RequestValidator) ValidateParam(c *gin.Context, dto interface{}) error
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -213,4 +213,4 @@ func (v *RequestValidator) ValidateValue(field interface{}, tag string) error {
|
||||
// ValidateStruct 验证结构体(用于业务逻辑)
|
||||
func (v *RequestValidator) ValidateStruct(s interface{}) error {
|
||||
return v.validator.Struct(s)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user