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{}表单上下文数据,可在字段配置中通过 vIfonChange 使用
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' }
    ]
  }
]

条件显示与联动

通过 vIfvShow 实现字段间的联动显示:

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>

Forge Admin — 基于 Vue3 + Spring Boot 的企业级后台管理框架