Skip to content

参数结构

VEF Framework 使用结构体定义 API 的请求参数。不同类型的操作需要不同的参数结构。

参数类型

类型用途示例
搜索参数查询条件UserSearch
创建参数创建记录UserCreateParams
更新参数更新记录UserUpdateParams
通用参数创建和更新共用UserParams

搜索参数

搜索参数用于定义查询条件,配合 search 标签自动构建 SQL 条件。

go
package payloads

import "github.com/ilxqx/vef-framework-go/api"

// UserSearch defines search parameters for user queries
type UserSearch struct {
    api.P  // Embed api.P for pagination support
    
    // Search by username (contains)
    Username string `json:"username" search:"contains"`
    
    // Search by email (exact match)
    Email string `json:"email" search:"eq"`
    
    // Search by status (in list)
    Status []string `json:"status" search:"in"`
    
    // Search by age range
    MinAge int `json:"minAge" search:"gte,column:age"`
    MaxAge int `json:"maxAge" search:"lte,column:age"`
    
    // Search by active status
    IsActive *bool `json:"isActive" search:"eq"`
    
    // Search by creation date range
    CreatedAtStart string `json:"createdAtStart" search:"gte,column:created_at"`
    CreatedAtEnd   string `json:"createdAtEnd" search:"lte,column:created_at"`
}

api.P 嵌入

所有搜索参数应嵌入 api.P,它提供分页支持:

go
type P struct {
    Page     int `json:"page"`      // Page number (1-based)
    PageSize int `json:"pageSize"`  // Items per page
}

创建/更新参数

通用参数(创建和更新共用)

当创建和更新使用相同的字段时:

go
// UserParams is used for both create and update operations
type UserParams struct {
    api.P
    Id          string `json:"id"`  // Required for update, ignored for create
    Username    string `json:"username" validate:"required,alphanum,min=3,max=32" label:"用户名"`
    Email       string `json:"email" validate:"required,email" label:"邮箱"`
    DisplayName string `json:"displayName" validate:"max=64" label:"显示名称"`
    IsActive    bool   `json:"isActive"`
}

分离的创建和更新参数

当创建和更新有不同的验证规则时,使用结构体嵌入共享字段:

go
// UserBaseParams contains shared fields
type UserBaseParams struct {
    api.P
    Username    string      `json:"username" validate:"required,alphanum,min=3,max=32" label:"用户名"`
    Email       string      `json:"email" validate:"required,email" label:"邮箱"`
    DisplayName null.String `json:"displayName" validate:"omitempty,max=64" label:"显示名称"`
    IsActive    bool        `json:"isActive"`
}

// UserCreateParams requires password for creation
type UserCreateParams struct {
    UserBaseParams `json:",inline"`
    Password       string `json:"password" validate:"required,min=6,max=32" label:"密码"`
    PasswordConfirm string `json:"passwordConfirm" validate:"required,eqfield=Password" label:"确认密码"`
}

// UserUpdateParams has optional password for update
type UserUpdateParams struct {
    UserBaseParams `json:",inline"`
    Id             string      `json:"id"`
    Password       null.String `json:"password" validate:"omitempty,min=6,max=32" label:"密码"`
    PasswordConfirm null.String `json:"passwordConfirm" validate:"omitempty,eqfield=Password" label:"确认密码"`
}

在资源中使用分离的参数

go
type UserResource struct {
    api.Resource
    apis.FindPageApi[models.User, payloads.UserSearch]
    apis.CreateApi[models.User, payloads.UserCreateParams]  // Use create params
    apis.UpdateApi[models.User, payloads.UserUpdateParams]  // Use update params
    apis.DeleteApi[models.User]
}

验证标签

使用 validate 标签定义验证规则:

go
type UserParams struct {
    api.P
    
    // Required field
    Username string `json:"username" validate:"required" label:"用户名"`
    
    // Required with format validation
    Email string `json:"email" validate:"required,email" label:"邮箱"`
    
    // Optional with validation when provided
    Phone string `json:"phone" validate:"omitempty,len=11,numeric" label:"手机号"`
    
    // Length constraints
    Password string `json:"password" validate:"required,min=6,max=32" label:"密码"`
    
    // Enum validation
    Status string `json:"status" validate:"required,oneof=active inactive pending" label:"状态"`
    
    // Cross-field validation
    PasswordConfirm string `json:"passwordConfirm" validate:"required,eqfield=Password" label:"确认密码"`
    
    // Numeric range
    Age int `json:"age" validate:"omitempty,min=0,max=150" label:"年龄"`
}

常用验证规则

规则说明示例
required必填validate:"required"
omitempty可选(空值跳过验证)validate:"omitempty,email"
min最小值/长度validate:"min=6"
max最大值/长度validate:"max=32"
len精确长度validate:"len=11"
email邮箱格式validate:"email"
urlURL 格式validate:"url"
uuidUUID 格式validate:"uuid"
alpha仅字母validate:"alpha"
alphanum字母数字validate:"alphanum"
numeric数字字符串validate:"numeric"
oneof枚举值validate:"oneof=a b c"
eqfield等于另一字段validate:"eqfield=Password"

label 标签

label 标签用于在验证错误消息中显示友好的字段名称:

go
type Params struct {
    Username string `json:"username" validate:"required" label:"用户名"`
}

// Validation error: "用户名 is required"
// Without label: "Username is required"

嵌套参数

支持嵌套结构体:

go
// Address is a nested structure
type Address struct {
    Street  string `json:"street" validate:"required" label:"街道"`
    City    string `json:"city" validate:"required" label:"城市"`
    ZipCode string `json:"zipCode" validate:"required,len=6" label:"邮编"`
}

// UserParams with nested address
type UserParams struct {
    api.P
    Username string  `json:"username" validate:"required" label:"用户名"`
    Address  Address `json:"address" validate:"required"`
}

数组参数

支持数组类型的参数:

go
// OrderParams with array of items
type OrderParams struct {
    api.P
    CustomerId string      `json:"customerId" validate:"required" label:"客户ID"`
    Items      []OrderItem `json:"items" validate:"required,min=1,dive" label:"订单项"`
}

// OrderItem is validated for each element
type OrderItem struct {
    ProductId string `json:"productId" validate:"required" label:"产品ID"`
    Quantity  int    `json:"quantity" validate:"required,min=1" label:"数量"`
}

dive 标签表示验证数组中的每个元素。

完整示例

go
package payloads

import (
    "github.com/ilxqx/vef-framework-go/api"
    "github.com/ilxqx/vef-framework-go/null"
)

// UserSearch for query operations
type UserSearch struct {
    api.P
    Username   string   `json:"username" search:"contains"`
    Email      string   `json:"email" search:"contains"`
    Status     []string `json:"status" search:"in"`
    IsActive   *bool    `json:"isActive" search:"eq"`
    DeptId     string   `json:"deptId" search:"eq"`
}

// UserBaseParams shared fields
type UserBaseParams struct {
    api.P
    Username    string      `json:"username" validate:"required,alphanum,min=3,max=32" label:"用户名"`
    Email       string      `json:"email" validate:"required,email,max=64" label:"邮箱"`
    DisplayName null.String `json:"displayName" validate:"omitempty,max=64" label:"显示名称"`
    Phone       null.String `json:"phone" validate:"omitempty,len=11,numeric" label:"手机号"`
    DeptId      null.String `json:"deptId" label:"部门"`
    RoleIds     []string    `json:"roleIds" label:"角色"`
    IsActive    bool        `json:"isActive"`
}

// UserCreateParams for create operation
type UserCreateParams struct {
    UserBaseParams  `json:",inline"`
    Password        string `json:"password" validate:"required,min=6,max=32" label:"密码"`
    PasswordConfirm string `json:"passwordConfirm" validate:"required,eqfield=Password" label:"确认密码"`
}

// UserUpdateParams for update operation
type UserUpdateParams struct {
    UserBaseParams  `json:",inline"`
    Id              string      `json:"id"`
    Password        null.String `json:"password" validate:"omitempty,min=6,max=32" label:"密码"`
    PasswordConfirm null.String `json:"passwordConfirm" validate:"omitempty,eqfield=Password" label:"确认密码"`
}

下一步

基于 Apache License 2.0 许可发布