Skip to content

AiForm 表单组件 ​

通过 JSON Schema 配置动态渲染表单,支持多种字段类型、嵌套验证规则、条件显示、分组布局、折叠等功能。AiForm 是 AiCrudPage、AiSearch 等组件的底层表单引擎。

基础用法 ​

vue
<template>
  <AiForm
    ref="formRef"
    v-model:value="formData"
    :schema="formSchema"
    :grid-cols="2"
    label-width="100px"
    @submit="handleSubmit"
    @cancel="handleCancel"
  />
</template>

<script setup>
import { ref } from 'vue'
import { AiForm } from '@/components/ai-form'

const formRef = ref(null)
const formData = ref({})

const formSchema = [
  { field: 'name', label: '姓名', type: 'input', required: true,
    rules: [{ required: true, message: '请输入姓名', trigger: 'blur' }] },
  { field: 'age', label: '年龄', type: 'number', span: 1 },
  { field: 'gender', label: '性别', type: 'select', span: 1,
    options: [
      { label: '男', value: 1 },
      { label: '女', value: 0 }
    ] },
  { field: 'email', label: '邮箱', type: 'input', span: 2,
    rules: [{ type: 'email', message: '邮箱格式不正确' }] },
  { field: 'status', label: '状态', type: 'switch',
    activeText: '启用', inactiveText: '禁用', defaultValue: 1 },
  { field: 'remark', label: '备注', type: 'textarea', span: 2,
    placeholder: '请输入备注信息' }
]

function handleSubmit(data) {
  console.log('提交数据:', data)
}

function handleCancel() {
  console.log('取消')
}
</script>

Props ​

属性类型默认值说明
schemaArray<object>[]必填,表单字段配置数组
valueObject{}表单数据(支持 v-model:value 双向绑定)
gridColsNumber1表单栅格列数
labelPlacementString'left'标签位置:'left' | 'top'
labelAlignString'right'标签对齐:'left' | 'right'
labelWidthString | Number'auto'标签宽度,如 '100px' 或 120
sizeString'medium'表单项尺寸:'small' | 'medium' | 'large'
xGapNumber16表单项列间距(px)
yGapNumber8表单项行间距(px)
showFeedbackBooleantrue是否显示校验反馈信息
showActionsBooleantrue是否显示底部操作按钮区
showSubmitBooleantrue是否显示提交按钮
showResetBooleantrue是否显示重置按钮
submitTextString'提交'提交按钮文本
resetTextString'重置'重置按钮文本
enableCollapseBooleanfalse是否启用折叠(超过最大可见字段数时折叠)
maxVisibleFieldsNumber6折叠前最大可见字段数
contextObject{}表单上下文数据,可在字段配置中通过 vIf 或 onChange 使用
formAssetsArray<object>[]表单资产列表,用于动态加载独立表单弹窗
formClassString | Object | Array''表单容器自定义 class
formStyleString | Object | Array-表单容器自定义 style

Schema 字段配置 ​

每个 schema 项支持以下属性:

通用属性 ​

属性类型说明
fieldString必填,字段名,对应 formData 中的 key
labelString标签文本
typeString字段类型(详见下方类型列表)
spanNumber栅格列占位(基于 gridCols),默认为 1
requiredBoolean是否必填(显示红色星号)
rulesArray验证规则数组,格式同 Naive UI FormItem rule
defaultValueAny默认值
placeholderString占位提示文本
tipString提示信息(显示在字段下方)
disabledBoolean | Function是否禁用,支持函数 (formData, context) => boolean
hiddenBoolean | Function是否隐藏,支持函数 (formData, context) => boolean
vIfBoolean | Function条件显示,支持函数 (formData, context) => boolean
vShowBoolean | Function条件可见(DOM 保留),支持函数
onChangeFunction值变化回调:(value, formData, context) => void
slotString自定义插槽名(通过父组件 <template #slotName> 渲染)
renderLabelFunction自定义标签渲染:(fieldConfig) => VNode | string
groupString所属分组标识(配合 AiFormGroupTitle 使用)

分组标题 ​

schema 中可插入分组标题项来组织表单布局:

js
const formSchema = [
  { type: 'group-title', label: '基本信息', field: 'basicGroup' },
  { field: 'name', label: '姓名', type: 'input' },
  { field: 'age', label: '年龄', type: 'number' },
  { type: 'group-title', label: '联系方式', field: 'contactGroup' },
  { field: 'email', label: '邮箱', type: 'input' },
  { field: 'phone', label: '电话', type: 'input' }
]

区块标题 ​

区块标题用于更细粒度的表单分区:

js
{ type: 'section-title', label: '高级配置', field: 'advancedSection' }

支持的字段类型 ​

基础输入 ​

type 值说明额外属性
input文本输入框maxlength, showPassword, prefix, suffix
textarea多行文本域rows, maxlength, showCount
number数字输入框min, max, step, precision

选择类 ​

type 值说明额外属性
select下拉选择options, filterable, clearable, multiple, remote, remoteMethod
radio单选框组options, buttonMode
checkbox多选框组options
switch开关activeText, inactiveText, activeValue, inactiveValue
tree-select树形选择treeData, checkable, cascade, filterable

日期时间 ​

type 值说明额外属性
date日期选择format, valueFormat
datetime日期时间选择format, valueFormat
time时间选择format
year年份选择-
month月份选择format

文件上传 ​

type 值说明额外属性
file-upload文件上传accept, max, maxSize, listType
image-upload图片上传max, maxSize, listType, crop
avatar-upload头像上传max, maxSize

高级组件 ​

type 值说明额外属性
dict-select字典下拉选择dictType(字典类型编码)
dict-radio字典单选dictType
dict-checkbox字典多选dictType
region-select行政区划选择level, multiple
user-select用户选择multiple, deptId
dept-select部门选择multiple
icon-select图标选择器-
editor富文本编辑器height, toolbarConfig
slot自定义插槽需配合父组件 <template #slotName> 使用
custom-select自定义下拉configKey(动态 CRUD 配置键), labelField, valueField, searchFields

验证规则 ​

支持 Naive UI FormItem 的完整验证规则体系:

js
const formSchema = [
  {
    field: 'username',
    label: '用户名',
    type: 'input',
    required: true,
    rules: [
      { required: true, message: '请输入用户名', trigger: 'blur' },
      { min: 3, max: 20, message: '用户名长度在 3 到 20 个字符', trigger: 'blur' },
      { pattern: /^[a-zA-Z0-9_]+$/, message: '用户名只能包含字母、数字和下划线', trigger: 'blur' }
    ]
  },
  {
    field: 'email',
    label: '邮箱',
    type: 'input',
    rules: [
      { required: true, message: '请输入邮箱' },
      { type: 'email', message: '邮箱格式不正确', trigger: 'blur' }
    ]
  },
  {
    field: 'age',
    label: '年龄',
    type: 'number',
    rules: [
      { required: true, message: '请输入年龄' },
      { type: 'number', min: 0, max: 150, message: '年龄范围 0-150', trigger: 'blur' }
    ]
  }
]

条件显示与联动 ​

通过 vIf 和 vShow 实现字段间的联动显示:

js
const formSchema = [
  { field: 'type', label: '证件类型', type: 'select',
    options: [
      { label: '身份证', value: 'idcard' },
      { label: '护照', value: 'passport' },
      { label: '其他', value: 'other' }
    ] },
  // 仅当选择「身份证」时显示
  { field: 'idCard', label: '身份证号', type: 'input',
    vIf: (formData) => formData.type === 'idcard' },
  // 仅当选择「护照」时显示
  { field: 'passport', label: '护照号', type: 'input',
    vIf: (formData) => formData.type === 'passport' }
]

onChange 回调中也可以通过 context 动态修改表单状态:

js
const formSchema = [
  {
    field: 'province',
    label: '省份',
    type: 'select',
    options: provinceOptions,
    onChange: (value, formData, context) => {
      // 省份变化时清空城市
      formData.city = undefined
      // 通过 context 访问表单引用
    }
  }
]

方法 ​

通过 ref 获取组件实例:

js
const formRef = ref(null)

// 表单验证(返回 Promise,验证失败 reject)
await formRef.value.validate()

// 恢复验证状态(清除错误提示)
formRef.value.restoreValidation()

// 重置表单到初始值(根据 schema 中的 defaultValue)
formRef.value.reset()

// 手动重置为指定值
formRef.value.resetFields({ name: '', age: 0 })

// 获取当前表单数据
const data = formRef.value.getFormData()

// 设置表单数据(替换所有字段值)
formRef.value.setFormData({ name: '张三', age: 25 })

// 设置单个字段值
formRef.value.setFieldValue('name', '李四')

// 获取单个字段值
const name = formRef.value.getFieldValue('name')

事件 ​

事件名参数说明
submit(formData)点击提交按钮并通过验证后触发
reset(formData)点击重置按钮后触发
cancel-点击取消按钮
field-change(field, value, formData)任意字段值变化

插槽 ​

表单字段插槽 ​

使用 type: 'slot' 声明插槽字段,然后在父组件中通过插槽渲染:

vue
<template>
  <AiForm ref="formRef" v-model:value="formData" :schema="formSchema">
    <template #customField="{ field, value, formData }">
      <CustomRichEditor v-model:value="formData.content" />
    </template>

    <template #formAction="{ formData }">
      <n-space>
        <n-button type="primary" @click="handleCustomSubmit">自定义提交</n-button>
        <n-button @click="handlePreview">预览</n-button>
      </n-space>
    </template>
  </AiForm>
</template>

<script setup>
const formSchema = [
  { field: 'title', label: '标题', type: 'input' },
  { field: 'content', label: '内容', type: 'slot', slot: 'customField' }
]
</script>