• 中文
  • Schema Form - JSON 表单

    SchemaForm 是根据 JSON Schema 来生成表单的工具。SchemaForm 会根据 valueType 来映射成不同的表单项。

    Tips: 如您遇到卡顿问题或有更高的性能要求可参考示例使用

    API

    SchemaForm 提供了与 ProForm 相同的 API,并且增加了部分 API,以下的 SchemaForm 新增的 API。

    监听表单值变化请使用 onValuesChange(changedValues, allValues),而不是 onChange。

    字段名称类型说明
    layoutTypeProFormLayoutType使用的表单布局模式
    stepsStepFormProps[]layoutType=steps中的分步表单配置,需要配置 columns 为数组使用
    columnsProFormColumnsType[] | ProFormColumnsType[][]表单的定义,一般是 json 对象,如果是分步表单,需要使用 json 数组来生成多个表单
    shouldUpdateboolean | ((newValues: Record<string, any>, oldValues?: Record<string, any>) => boolean)细粒化控制是否渲染。
    为 true 时会自动重新渲染表单项。
    为 false 时不会更新表单项但可以使用 dependencies 触发更新。
    为 function 时根据返回值判断是否重新渲染表单项
    titleReactNode表单标题
    actionMutableRefObject<ProCoreActionType | undefined>用于操作表单的 action,支持 reload 等操作
    formRefMutableRefObject<ProFormInstance | undefined>获取 form 实例,支持 antd form 的所有方法
    openboolean控制 ModalForm 和 DrawerForm 的显示隐藏

    ProFormLayoutType

    字段名称说明
    FormProForm 是基本的表单类型
    ModalForm弹框表单,配置之后支持 ModalForm 的所有配置
    DrawerForm抽屉表单,配置之后支持 DrawerForm 的所有配置
    StepsForm|StepForm配置之后为分步表单,有两种模式一种使用 steps 和 columns 来生成,一种是通过 layoutType=StepsForm 嵌套 layoutType=StepForm 来实现
    LightFilter轻量筛选,配置之后支持 LightFilter 的所有配置
    QueryFilter查询表单,配置之后支持 QueryFilter 的所有配置
    Embed内嵌模式,只生成表单项,不生成 Form 可以混合使用

    Schema 定义

    SchemaForm 表单最重要就是 Schema 的类型定义,我们使用了与 table 的相同的表单定义,同时扩展了部分字段。

    字段名称类型说明
    keyReact.Key确定这个列的唯一值,一般用于 dataIndex 重复的情况
    dataIndexReact.Key | React.Key[]与实体映射的 key,数组会被转化 [a,b] => Entity.a.b
    valueTypeProFieldValueType数据的渲染方式,我们自带了一部分,你也可以自定义 valueType
    titleReactNode |(props,type,dom)=> ReactNode标题的内容,在 form 中是 label
    tooltipLabelTooltipType | string会在 title 旁边展示一个 icon,鼠标浮动之后展示
    widthnumber | string宽度。
    xs: 104px - 短数字、短文本
    sm: 216px - 短字段(姓名、电话)
    md: 328px - 标准宽度
    lg: 440px - 长字段(网址、标签组)
    xl: 552px - 长文本(描述、备注)
    colSizenumber每个表单占据的格子大小,总宽度 = span * colSize,默认为 1
    readonlyboolean是否只读模式
    initialValueany表单的默认值
    valueEnum(Entity)=> ValueEnum | ValueEnum支持 object 和 Map,Map 是支持其他基础类型作为 key
    fieldProps(form,config)=>fieldProps| fieldProps传给渲染的组件的 props,自定义的时候也会传递
    formItemProps(form,config)=>formItemProps | formItemProps传递给 Form.Item 的配置
    formItemProps.rulesRule[]表单项的校验规则。需要注意的是,如果当前表单项为formList时,此规则仅校验列表是否为空,且仅接受元组[{required: boolean, message: string}],用于开启和关闭非空校验及指定空列表提示消息
    proFieldPropsproFieldProps设置到 ProField 上面的 props,内部属性
    renderText(text: any, record: Entity, index: number, action: ProCoreActionType) => any修改的数据是会被 valueType 定义的渲染组件消费
    render(dom,entity,index, action, schema) => React.ReactNode自定义只读模式的 dom,render 方法只管理的只读模式,编辑模式需要使用 formItemRender
    formItemRender(schema,config,form,action) => React.ReactNode自定义编辑模式,返回一个 ReactNode,会自动包裹 value 和 onChange。如返回 false,null,undefined 将不展示表单项 请使用 dependency 组件控制是否渲染列
    request(params,props) => Promise<{label,value}[]>从远程请求网络数据,一般用于选择类组件
    paramsRecord<string, any>额外传递给 request 的参数,组件不做处理,但是变化会引起request 重新请求数据
    dependenciesNamePath[]所依赖的 values 变化后,触发 formItemRender,fieldProps,formItemProps 重新执行,并把 values 注入到 params 里 示例
    hideInDescriptionsboolean在 descriptions 中隐藏
    hideInFormboolean在 Form 中隐藏
    hideInTableboolean在 Table 中隐藏
    searchboolean | { transform: (value: any) => any }在 Table 的查询表格中隐藏可设为 false,对象配置 transform 用于转化提交的 key
    columnsProFormColumnsType[] | (values) => ProFormColumnsType[]嵌套子项,valueType 为 dependency 时,请使用(values) => ProFormColumnsType[]其他情况使用 ProFormColumnsType[]
    colPropsColProps在开启 grid 模式时传递给 Col
    rowPropsRowProps开启栅格化模式时传递给 Row
    convertValue(value, namePath)=> any获取时转化值,一般用于将数据格式化为组件接收的格式,如 [a,b] => a,b
    transform(value, namePath, allValues)=> any提交时转化值,一般用于将值转化为提交的数据,如 string => { newName: string }
    ordernumberForm 的排序,默认是 index,order 越大越靠前
    debounceTimenumberrequest 防抖时间
    defaultKeyWordsstring搜索时的默认关键字
    ignoreFormItemboolean不包裹 Form.Item,直接渲染组件

    valueEnum

    valueEnum 用值作为 key 映射展示文本和状态,支持 object、Map,也支持根据当前数据返回枚举的函数。

    常见 ValueType

    值类型描述
    text文本输入框
    textarea多行文本域
    password密码输入框
    digit数字输入框
    money金额输入框
    select下拉选择器
    checkbox多选框
    radio单选框
    date日期选择器
    dateRange日期范围选择器
    time时间选择器
    switch开关
    group表单分组
    dependency依赖联动
    formList列表表单

    fieldProps 与 formItemProps 的区别

    • fieldProps: 传递给具体输入组件(如 Input, Select, DatePicker)的属性。例如 placeholder, allowClear, style 等。
    • formItemProps: 传递给 Ant Design 的 Form.Item 的属性。例如 label, name, rules, extra, help 等。
    {
      title: '标题',
      dataIndex: 'title',
      formItemProps: {
        rules: [{ required: true, message: '此项必填' }],
        extra: '这是一段辅助说明',
      },
      fieldProps: {
        placeholder: '请输入标题',
        allowClear: true,
      },
    }

    代码示例 - 布局类型

    基础表单 (Form)

    SchemaForm 最基础的用法,通过 JSON 配置生成标准的表单页面。支持通过 columns 定义表单项,通过 layoutType 切换布局。

    Form
    请选择
    分组
    请选择
    全部
    请选择
    基础 Schema 表单
    import type {
      ProFormColumnsType,
      ProFormLayoutType,
    } from '@ant-design/pro-components';
    import { BetaSchemaForm, ProFormSelect } from '@ant-design/pro-components';
    import { Alert, DatePicker, Space } from 'antd';
    import { useState } from 'react';
    
    import { FIXED_BASE_DATE } from '../../mockData';
    
    const valueEnum = {
      all: { text: '全部', status: 'Default' },
      open: {
        text: '未解决',
        status: 'Error',
      },
      closed: {
        text: '已解决',
        status: 'Success',
        disabled: true,
      },
      processing: {
        text: '解决中',
        status: 'Processing',
      },
    };
    
    type DataItem = {
      name: string;
      state: string;
    };
    
    const columns: ProFormColumnsType<DataItem>[] = [
      {
        title: '标题',
        dataIndex: 'title',
        formItemProps: {
          rules: [
            {
              required: true,
              message: '此项为必填项',
            },
          ],
        },
        width: 'md',
        colProps: {
          xs: 24,
          md: 12,
        },
        initialValue: '默认值',
        convertValue: (value) => {
          return `标题:${value}`;
        },
        transform: (value) => {
          return {
            title: `${value}-转换`,
          };
        },
      },
      {
        title: '状态',
        dataIndex: 'state',
        valueType: 'select',
        valueEnum,
        width: 'md',
        colProps: {
          xs: 24,
          md: 12,
        },
      },
      {
        title: '标签',
        dataIndex: 'labels',
        width: 'md',
        colProps: {
          xs: 12,
          md: 4,
        },
      },
      {
        valueType: 'switch',
        title: '开关',
        dataIndex: 'Switch',
        fieldProps: {
          style: {
            width: '200px',
          },
        },
        width: 'md',
        colProps: {
          xs: 12,
          md: 20,
        },
      },
      {
        title: '创建时间',
        key: 'showTime',
        valueType: 'dateRange',
        dataIndex: 'createName',
        initialValue: [FIXED_BASE_DATE.add(-1, 'm'), FIXED_BASE_DATE],
        formItemRender: () => <DatePicker.RangePicker />,
        width: 'md',
        colProps: {
          xs: 24,
          md: 12,
        },
      },
      {
        title: '更新时间',
        dataIndex: 'updateName',
        valueType: 'dateRange',
        initialValue: [FIXED_BASE_DATE.add(-1, 'm'), FIXED_BASE_DATE],
        formItemRender: () => <DatePicker.RangePicker />,
        width: 'md',
        colProps: {
          xs: 24,
          md: 12,
        },
      },
      {
        title: '分组',
        valueType: 'group',
        columns: [
          {
            title: '状态',
            dataIndex: 'groupState',
            valueType: 'select',
            width: 'xs',
            colProps: {
              xs: 12,
            },
            valueEnum,
          },
          {
            title: '标题',
            width: 'md',
            dataIndex: 'groupTitle',
            colProps: {
              xs: 12,
            },
            formItemProps: {
              rules: [
                {
                  required: true,
                  message: '此项为必填项',
                },
              ],
            },
          },
        ],
      },
      {
        title: '列表',
        valueType: 'formList',
        dataIndex: 'list',
        initialValue: [{ state: 'all', title: '标题' }],
        colProps: {
          xs: 24,
          sm: 12,
        },
        columns: [
          {
            valueType: 'group',
            columns: [
              {
                title: '状态',
                dataIndex: 'state',
                valueType: 'select',
                colProps: {
                  xs: 24,
                  sm: 12,
                },
                width: 'xs',
                valueEnum,
              },
              {
                title: '标题',
                dataIndex: 'title',
                width: 'md',
                formItemProps: {
                  rules: [
                    {
                      required: true,
                      message: '此项为必填项',
                    },
                  ],
                },
                colProps: {
                  xs: 24,
                  sm: 12,
                },
              },
            ],
          },
          {
            valueType: 'dateTime',
            initialValue: FIXED_BASE_DATE.toDate(),
            dataIndex: 'currentTime',
            width: 'md',
          },
        ],
      },
      {
        title: 'FormSet',
        valueType: 'formSet',
        dataIndex: 'formSet',
        colProps: {
          xs: 24,
          sm: 12,
        },
        rowProps: {
          gutter: [16, 0],
        },
        columns: [
          {
            title: '状态',
            dataIndex: 'groupState',
            valueType: 'select',
            width: 'md',
            valueEnum,
          },
          {
            width: 'xs',
            title: '标题',
            dataIndex: 'groupTitle',
            tooltip: '标题过长会自动收缩',
            formItemProps: {
              rules: [
                {
                  required: true,
                  message: '此项为必填项',
                },
              ],
            },
          },
        ],
      },
      {
        title: '创建时间',
        dataIndex: 'created_at',
        valueType: 'dateRange',
        width: 'md',
        colProps: {
          span: 24,
        },
        transform: (value) => {
          return {
            startTime: value[0],
            endTime: value[1],
          };
        },
      },
    ];
    
    const Demo = () => {
      const [layoutType, setLayoutType] = useState<ProFormLayoutType>('Form');
      return (
        <>
          <Space
            style={{
              width: '100%',
            }}
            orientation="vertical"
          >
            <Alert
              type="warning"
              title="QueryFilter 和 lightFilter 暂不支持grid模式"
              style={{
                marginBlockEnd: 24,
              }}
            />
            <ProFormSelect
              label="布局方式"
              options={[
                'Form',
                'ModalForm',
                'DrawerForm',
                'LightFilter',
                'QueryFilter',
                'StepsForm',
                'StepForm',
                'Embed',
              ]}
              fieldProps={{
                value: layoutType,
                onChange: (e) => setLayoutType(e),
              }}
            />
          </Space>
          <BetaSchemaForm<DataItem>
            name="schema-form-schema-demo"
            trigger={<a>点击我</a>}
            layoutType={layoutType}
            steps={[
              {
                title: 'ProComponent',
              },
            ]}
            rowProps={{
              gutter: [16, 16],
            }}
            colProps={{
              span: 12,
            }}
            grid={layoutType !== 'LightFilter' && layoutType !== 'QueryFilter'}
            onFinish={async () => {
    
            }}
            columns={(layoutType === 'StepsForm' ? [columns] : columns) as any}
          />
        </>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    浮层表单 (ModalForm & DrawerForm)

    通过设置 layoutType 为 ModalForm 或 DrawerForm,可以快速将表单转换为弹窗或抽屉模式,无需手动维护 open 状态。

    ModalForm
    ModalForm 和 DrawerForm
    import type { ProFormLayoutType } from '@ant-design/pro-components';
    import { BetaSchemaForm, ProFormSelect } from '@ant-design/pro-components';
    import { Alert, Button, Space } from 'antd';
    import { useState } from 'react';
    
    type DataItem = {
      name: string;
      state: string;
    };
    
    const Demo = () => {
      const [layoutType, setLayoutType] = useState<ProFormLayoutType>('ModalForm');
      return (
        <>
          <Space
            style={{
              width: '100%',
            }}
            orientation="vertical"
          >
            <Alert
              type="warning"
              title="QueryFilter 和 lightFilter 暂不支持grid模式"
              style={{
                marginBlockEnd: 24,
              }}
            />
            <ProFormSelect
              label="布局方式"
              options={['ModalForm', 'DrawerForm']}
              fieldProps={{
                value: layoutType,
                onChange: (e) => setLayoutType(e),
              }}
            />
          </Space>
          <BetaSchemaForm<DataItem>
            name="schema-form-modal-and-drawer-form-demo"
            trigger={<Button>点击我</Button>}
            layoutType={layoutType as 'ModalForm'}
            onFinish={async () => {
    
            }}
            {...(layoutType === 'ModalForm'
              ? {
                  modalProps: { destroyOnHidden: true },
                }
              : {
                  drawerProps: { destroyOnHidden: true },
                })}
            columns={[
              {
                title: '标题',
                dataIndex: 'title',
                formItemProps: {
                  rules: [
                    {
                      required: true,
                      message: '此项为必填项',
                    },
                  ],
                },
                width: 'md',
              },
            ]}
          />
        </>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    分步表单 (StepsForm)

    通过设置 layoutType 为 StepsForm 或 StepForm,可以生成分步表单。此时 columns 应该是一个二维数组,每个数组元素代表一步的表单项配置。

    请选择
    分组
    请选择
    全部
    请选择
    JSON 生成分步表单
    import type {
      ProFormColumnsType,
      ProFormInstance,
    } from '@ant-design/pro-components';
    import { BetaSchemaForm } from '@ant-design/pro-components';
    import { message } from 'antd';
    import { useRef } from 'react';
    
    const valueEnum = {
      all: { text: '全部', status: 'Default' },
      open: {
        text: '未解决',
        status: 'Error',
      },
      closed: {
        text: '已解决',
        status: 'Success',
        disabled: true,
      },
      processing: {
        text: '解决中',
        status: 'Processing',
      },
    };
    
    type DataItem = {
      name: string;
      state: string;
    };
    
    const columns: ProFormColumnsType<DataItem>[][] = [
      [
        {
          title: '标题',
          dataIndex: 'title',
          formItemProps: {
            rules: [
              {
                required: true,
                message: '此项为必填项',
              },
            ],
          },
          width: 'm',
        },
        {
          title: '状态',
          dataIndex: 'state',
          valueType: 'select',
          valueEnum,
          width: 'm',
        },
      ],
      [
        {
          title: '标签',
          dataIndex: 'labels',
          width: 'm',
        },
        {
          title: '创建时间',
          key: 'showTime',
          dataIndex: 'createName',
          valueType: 'date',
        },
        {
          title: '分组',
          valueType: 'group',
          columns: [
            {
              title: '状态',
              dataIndex: 'groupState',
              valueType: 'select',
              width: 'xs',
              valueEnum,
            },
            {
              title: '标题',
              width: 'md',
              dataIndex: 'groupTitle',
              formItemProps: {
                rules: [
                  {
                    required: true,
                    message: '此项为必填项',
                  },
                ],
              },
            },
          ],
        },
      ],
      [
        {
          title: '列表',
          valueType: 'formList',
          dataIndex: 'list',
          initialValue: [{ state: 'all', title: '标题' }],
          columns: [
            {
              valueType: 'group',
              columns: [
                {
                  title: '状态',
                  dataIndex: 'state',
                  valueType: 'select',
                  width: 'xs',
                  valueEnum,
                },
                {
                  title: '标题',
                  dataIndex: 'title',
                  formItemProps: {
                    rules: [
                      {
                        required: true,
                        message: '此项为必填项',
                      },
                    ],
                  },
                  width: 'm',
                },
              ],
            },
          ],
        },
        {
          title: 'FormSet',
          valueType: 'formSet',
          dataIndex: 'formSet',
          columns: [
            {
              title: '状态',
              dataIndex: 'groupState',
              valueType: 'select',
              width: 'xs',
              valueEnum,
            },
            {
              title: '标题',
              dataIndex: 'groupTitle',
              tooltip: '标题过长会自动收缩',
              formItemProps: {
                rules: [
                  {
                    required: true,
                    message: '此项为必填项',
                  },
                ],
              },
              width: 'm',
            },
          ],
        },
        {
          title: '创建时间',
          dataIndex: 'created_at',
          valueType: 'dateRange',
          transform: (value) => {
            return {
              startTime: value[0],
              endTime: value[1],
            };
          },
        },
      ],
    ];
    
    const Demo = () => {
      const formRef = useRef<ProFormInstance>();
    
      return (
        <BetaSchemaForm<DataItem>
          name="schema-form-steps-form-demo"
          layoutType="StepsForm"
          steps={[
            {
              title: '第一步',
            },
            {
              title: '第二步',
            },
            {
              title: '第三步',
            },
          ]}
          onCurrentChange={(_current) => {
    
          }}
          formRef={formRef}
          onFinish={async () => {
            return new Promise((resolve) => {
    
              message.success('提交成功');
              setTimeout(() => {
                resolve(true);
                formRef.current?.resetFields();
              }, 2000);
            });
          }}
          columns={columns}
        />
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    嵌入模式 (Embed)

    通过设置 layoutType 为 Embed,可以只生成表单项而不生成 Form 容器。这在需要将 SchemaForm 嵌入到已有的 ProForm 或其他容器中时非常有用。

    ProForm

    表单1

    请选择

    表单2

    分组
    请选择
    嵌入到 ProForm 中
    import type { ProFormColumnsType } from '@ant-design/pro-components';
    import {
      BetaSchemaForm,
      ProForm,
      ProFormSelect,
      ProFormText,
    } from '@ant-design/pro-components';
    
    const valueEnum = {
      all: { text: '全部', status: 'Default' },
      open: {
        text: '未解决',
        status: 'Error',
      },
      closed: {
        text: '已解决',
        status: 'Success',
        disabled: true,
      },
      processing: {
        text: '解决中',
        status: 'Processing',
      },
    };
    
    type DataItem = {
      name: string;
      state: string;
    };
    
    const columns: ProFormColumnsType<DataItem>[] = [
      {
        title: '标题',
        dataIndex: 'title',
        formItemProps: {
          rules: [
            {
              required: true,
              message: '此项为必填项',
            },
          ],
        },
        width: 'm',
      },
      {
        title: '状态',
        dataIndex: 'state',
        valueType: 'select',
        valueEnum,
        width: 'm',
      },
    ];
    
    const Demo = () => {
      return (
        <ProForm name="schema-form-embed-demo">
          <h1>ProForm </h1>
          <ProFormText name="username" />
          <ProFormSelect
            name="select-multiple"
            label="多选"
            valueEnum={{
              red: 'Red',
              green: 'Green',
              blue: 'Blue',
            }}
            fieldProps={{
              mode: 'multiple',
            }}
            placeholder="Please select favorite colors"
            rules={[
              {
                required: true,
                message: 'Please select your favorite colors!',
                type: 'array',
              },
            ]}
          />
          <h1>表单1 </h1>
          <BetaSchemaForm<DataItem> layoutType="Embed" columns={columns} />
          <h1>表单2</h1>
          <BetaSchemaForm<DataItem>
            layoutType="Embed"
            columns={[
              {
                title: '创建时间',
                key: 'showTime',
                dataIndex: 'createName',
                valueType: 'date',
              },
              {
                title: '分组',
                valueType: 'group',
                columns: [
                  {
                    title: '状态',
                    dataIndex: 'groupState',
                    valueType: 'select',
                    width: 'xs',
                    valueEnum,
                  },
                  {
                    title: '标题',
                    width: 'md',
                    dataIndex: 'groupTitle',
                    formItemProps: {
                      rules: [
                        {
                          required: true,
                          message: '此项为必填项',
                        },
                      ],
                    },
                  },
                ],
              },
            ]}
          />
        </ProForm>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    高级用法

    表单联动

    使用 valueType: 'dependency' 可以实现复杂的表单联动。当依赖的字段发生变化时,会自动触发当前项的更新。

    普通json表单

    请选择

    嵌套json表单

    按金额
    使用 ProFormDependency
    import type { ProFormColumnsType } from '@ant-design/pro-components';
    import { BetaSchemaForm, ProForm } from '@ant-design/pro-components';
    
    const valueEnum = {
      money: { text: '按金额' },
      discount: { text: '按折扣' },
    };
    
    type DataItem = {
      name: string;
      state: string;
    };
    
    const columns: ProFormColumnsType<DataItem>[] = [
      {
        title: '优惠方式',
        dataIndex: 'type',
        formItemProps: {
          rules: [
            {
              required: true,
              message: '此项为必填项',
            },
          ],
        },
        valueType: 'select',
        valueEnum,
        width: 'm',
      },
      {
        valueType: 'dependency',
        name: ['type'],
        columns: ({ type }) => {
          if (type === 'money') {
            return [
              {
                dataIndex: 'money',
                title: '优惠金额',
                width: 'm',
                valueType: 'money',
              },
            ];
          }
    
          if (type === 'discount') {
            return [
              {
                dataIndex: 'discount',
                title: '折扣',
                valueType: 'digit',
                width: 'm',
                fieldProps: {
                  precision: 2,
                },
              },
            ];
          }
    
          return [];
        },
      },
    ];
    
    const Demo = () => {
      return (
        <>
          <h1>普通json表单</h1>
          <BetaSchemaForm<DataItem>
            onFinish={async () => {
    
            }}
            columns={columns}
          />
          <h1>嵌套json表单</h1>
          <ProForm
            name="schema-form-dependency-demo"
            initialValues={{
              type: 'money',
            }}
          >
            <BetaSchemaForm<DataItem>
              layoutType="Embed"
              onFinish={async () => {
    
              }}
              columns={columns}
            />
          </ProForm>
        </>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    高性能模式

    对于大型表单,可以使用 shouldUpdate 和 dependencies 来进行细粒度的渲染控制,避免整个表单的重复渲染。

    • dependencies: 指定依赖字段,仅当依赖字段变化时更新。
    • shouldUpdate: 自定义更新逻辑,返回 false 阻止更新。
    normal
    结合 shouldUpdate=false 和 dependencies 触发更新
    import type { ProFormColumnsType } from '@ant-design/pro-components';
    import { BetaSchemaForm } from '@ant-design/pro-components';
    import { Input } from 'antd';
    
    const valueEnum = {
      all: { text: '全部', status: 'Default' },
      open: {
        text: '未解决',
        status: 'Error',
      },
      closed: {
        text: '已解决',
        status: 'Success',
        disabled: true,
      },
      processing: {
        text: '解决中',
        status: 'Processing',
      },
    };
    
    type DataItem = {
      name: string;
      state: string;
    };
    
    const columns: ProFormColumnsType<DataItem>[] = [
      {
        title: '标题',
        dataIndex: 'title',
        initialValue: '必填',
        formItemProps: {
          rules: [
            {
              required: true,
              message: '此项为必填项',
            },
          ],
        },
        width: 'm',
      },
      {
        title: '状态',
        dataIndex: 'state',
        valueType: 'select',
        valueEnum,
        width: 'm',
        tooltip: '当title为disabled时状态无法选择',
        dependencies: ['title'],
        fieldProps: (form) => {
          if (form.getFieldValue('title') === 'disabled') {
            return {
              disabled: true,
              placeholder: 'disabled',
            };
          } else {
            return {
              placeholder: 'normal',
            };
          }
        },
      },
      {
        title: '标签',
        dataIndex: 'labels',
        width: 'm',
        tooltip: '当title为必填时此项将为必填',
        dependencies: ['title'],
        formItemProps(form) {
          if (form.getFieldValue('title') === '必填') {
            return {
              rules: [
                {
                  required: true,
                },
              ],
            };
          } else {
            return {};
          }
        },
      },
      {
        valueType: 'dependency',
        name: ['title'],
        columns: ({ title }) => {
          return title !== 'hidden'
            ? [
                {
                  title: 'title为hidden时隐藏',
                  dataIndex: 'hidden',
                  valueType: 'date',
                  formItemRender: () => {
                    return <Input />;
                  },
                },
              ]
            : [];
        },
      },
      {
        title: '创建时间',
        key: 'showTime',
        dataIndex: 'createName',
        valueType: 'date',
      },
      {
        valueType: 'divider',
      },
    ];
    
    const Demo = () => {
      return (
        <>
          <BetaSchemaForm<DataItem>
            shouldUpdate={false}
            layoutType="Form"
            onFinish={async () => {
    
            }}
            columns={columns}
          />
        </>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    
    normal
    动态控制是否重渲染
    import type { ProFormColumnsType } from '@ant-design/pro-components';
    import { BetaSchemaForm } from '@ant-design/pro-components';
    import { Input } from 'antd';
    
    const valueEnum = {
      all: { text: '全部', status: 'Default' },
      open: {
        text: '未解决',
        status: 'Error',
      },
      closed: {
        text: '已解决',
        status: 'Success',
        disabled: true,
      },
      processing: {
        text: '解决中',
        status: 'Processing',
      },
    };
    
    type DataItem = {
      name: string;
      state: string;
      title: string;
    };
    
    const columns: ProFormColumnsType<DataItem>[] = [
      {
        title: '标题',
        dataIndex: 'title',
        initialValue: '必填',
        formItemProps: {
          rules: [
            {
              required: true,
              message: '此项为必填项',
            },
          ],
        },
        width: 'm',
      },
      {
        title: '状态',
        dataIndex: 'state',
        valueType: 'select',
        valueEnum,
        width: 'm',
        tooltip: '当title为disabled时状态无法选择',
        fieldProps: (form) => {
          if (form.getFieldValue('title') === 'disabled') {
            return {
              disabled: true,
              placeholder: 'disabled',
            };
          } else {
            return {
              placeholder: 'normal',
            };
          }
        },
      },
      {
        title: '标签',
        dataIndex: 'labels',
        width: 'm',
        tooltip: '当title为必填时此项将为必填',
        dependencies: ['title'],
        formItemProps(form) {
          if (form.getFieldValue('title') === '必填') {
            return {
              rules: [
                {
                  required: true,
                },
              ],
            };
          } else {
            return {};
          }
        },
      },
      {
        valueType: 'dependency',
        name: ['title'],
        columns: ({ title }) => {
          return title !== 'hidden'
            ? [
                {
                  title: 'title为hidden时隐藏',
                  dataIndex: 'hidden',
                  valueType: 'date',
                  formItemRender: () => {
                    return <Input />;
                  },
                },
              ]
            : [];
        },
      },
      {
        title: '创建时间',
        key: 'showTime',
        dataIndex: 'createName',
        valueType: 'date',
      },
    ];
    
    const Demo = () => {
      return (
        <>
          <BetaSchemaForm<DataItem>
            shouldUpdate={(newValues, oldValues) => {
              if (newValues.title !== oldValues?.title) {
                return true;
              }
              return false;
            }}
            layoutType="Form"
            onFinish={async () => {
    
            }}
            columns={columns}
          />
        </>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    列表配置 (FormList)

    支持 valueType: 'formList' 来生成动态增减的列表表单。

    normal
    FormList Required 校验
    import type { ProFormColumnsType } from '@ant-design/pro-components';
    import { BetaSchemaForm } from '@ant-design/pro-components';
    import { Input } from 'antd';
    
    const valueEnum = {
      all: { text: '全部', status: 'Default' },
      open: {
        text: '未解决',
        status: 'Error',
      },
      closed: {
        text: '已解决',
        status: 'Success',
        disabled: true,
      },
      processing: {
        text: '解决中',
        status: 'Processing',
      },
    };
    
    type DataItem = {
      name: string;
      state: string;
    };
    
    const columns: ProFormColumnsType<DataItem>[] = [
      {
        title: '标题',
        dataIndex: 'title',
        initialValue: '必填',
        formItemProps: {
          rules: [
            {
              required: true,
              message: '此项为必填项',
            },
          ],
        },
        width: 'm',
      },
      {
        title: '必填但没显示*',
        dataIndex: 'list',
        valueType: 'formList',
        formItemProps: {
          rules: [{ required: true, message: '请填写列表' }],
        },
        columns: [
          {
            dataIndex: 'isSettlement',
            valueType: 'switch',
            formItemProps: {
              rules: [{ required: true, message: '请填写1' }],
            },
          },
        ],
      },
      {
        title: '状态',
        dataIndex: 'state',
        valueType: 'select',
        valueEnum,
        width: 'm',
        tooltip: '当title为disabled时状态无法选择',
        dependencies: ['title'],
        fieldProps: (form) => {
          if (form.getFieldValue('title') === 'disabled') {
            return {
              disabled: true,
              placeholder: 'disabled',
            };
          } else {
            return {
              placeholder: 'normal',
            };
          }
        },
      },
      {
        title: '标签',
        dataIndex: 'labels',
        width: 'm',
        tooltip: '当title为必填时此项将为必填',
        dependencies: ['title'],
        formItemProps(form) {
          if (form.getFieldValue('title') === '必填') {
            return {
              rules: [
                {
                  required: true,
                },
              ],
            };
          } else {
            return {};
          }
        },
      },
      {
        valueType: 'dependency',
        name: ['title'],
        columns: ({ title }) => {
          return title !== 'hidden'
            ? [
                {
                  title: 'title为hidden时隐藏',
                  dataIndex: 'hidden',
                  valueType: 'date',
                  formItemRender: () => {
                    return <Input />;
                  },
                },
              ]
            : [];
        },
      },
      {
        title: '创建时间',
        key: 'showTime',
        dataIndex: 'createName',
        valueType: 'date',
      },
      {
        valueType: 'divider',
      },
    ];
    
    const Demo = () => {
      return (
        <>
          <BetaSchemaForm<DataItem>
            shouldUpdate={false}
            layoutType="Form"
            onFinish={async () => {
    
            }}
            columns={columns}
          />
        </>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    valueType 映射

    演示内置 valueType 在 BetaSchemaForm 中的基础用法。

    分组
    123456
    Schema valueType 映射
    import type { ProFieldValueType } from '@ant-design/pro-components';
    import { BetaSchemaForm, ProFormSelect } from '@ant-design/pro-components';
    
    import { useState } from 'react';
    import { FIXED_BASE_TIMESTAMP } from '../../mockData';
    
    const valueEnum = {
      all: { text: '全部', status: 'Default' },
      open: {
        text: '未解决',
        status: 'Error',
      },
      closed: {
        text: '已解决',
        status: 'Success',
        disabled: true,
      },
      processing: {
        text: '解决中',
        status: 'Processing',
      },
    };
    
    const options = [
      { value: `password`, label: `密码输入框`, initialValue: '123456' },
      { value: `money`, label: `金额输入`, initialValue: '123456' },
      { value: `textarea`, label: `文本域`, initialValue: '123456\n121212' },
      { value: `date`, label: `日期`, initialValue: FIXED_BASE_TIMESTAMP },
      { value: `dateTime`, label: `日期时间`, initialValue: FIXED_BASE_TIMESTAMP },
      { value: `dateWeek`, label: `周`, initialValue: FIXED_BASE_TIMESTAMP },
      { value: `dateMonth`, label: `月`, initialValue: FIXED_BASE_TIMESTAMP },
      {
        value: `dateQuarter`,
        label: `季度输入`,
        initialValue: FIXED_BASE_TIMESTAMP,
      },
      { value: `dateYear`, label: `年份输入`, initialValue: FIXED_BASE_TIMESTAMP },
      {
        value: `dateRange`,
        label: `日期区间`,
        initialValue: [FIXED_BASE_TIMESTAMP, FIXED_BASE_TIMESTAMP],
      },
      {
        value: `dateTimeRange`,
        label: `日期时间区间`,
        initialValue: [FIXED_BASE_TIMESTAMP, FIXED_BASE_TIMESTAMP],
      },
      { value: `time`, label: `时间`, initialValue: FIXED_BASE_TIMESTAMP },
      {
        value: `timeRange`,
        label: `时间区间`,
        initialValue: [FIXED_BASE_TIMESTAMP, FIXED_BASE_TIMESTAMP],
      },
      { value: `text`, label: `文本框`, initialValue: '123456' },
      { value: `select`, label: `下拉框`, initialValue: 'open' },
      { value: `checkbox`, label: `多选框`, initialValue: 'open' },
      { value: `rate`, label: `星级组件`, initialValue: '' },
      { value: `radio`, label: `单选框`, initialValue: 'open' },
      { value: `radioButton`, label: `按钮单选框`, initialValue: 'open' },
      { value: `progress`, label: `进度条`, initialValue: '10' },
      { value: `percent`, label: `百分比组件`, initialValue: '20' },
      { value: `digit`, label: `数字输入框`, initialValue: '200000' },
      { value: `second`, label: `秒格式化`, initialValue: 20000 },
      {
        value: `avatar`,
        label: `头像`,
        initialValue:
          'https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg',
      },
      { value: `code`, label: `代码框`, initialValue: '# 2121' },
      { value: `switch`, label: `开关`, initialValue: 'open' },
      {
        value: `fromNow`,
        label: `相对于当前时间`,
        initialValue: FIXED_BASE_TIMESTAMP,
      },
      {
        value: `image`,
        label: `图片`,
        initialValue:
          'https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg',
      },
      {
        value: `jsonCode`,
        label: `JSON代码框`,
        initialValue: '{ "name":"demo_user" }',
      },
      {
        value: `color`,
        label: `颜色选择器`,
        initialValue: '#1890ff',
      },
    ];
    
    type DataItem = {
      name: string;
      state: string;
    };
    
    const Demo = () => {
      const [valueType, setValueType] = useState<ProFieldValueType>('text');
      return (
        <>
          <ProFormSelect.SearchSelect
            label="valueType 选择"
            options={options}
            width={200}
            mode="single"
            fieldProps={{
              labelInValue: false,
              value: valueType,
              onChange: (value) => setValueType(value),
            }}
          />
          <BetaSchemaForm<DataItem>
            name="schema-form-value-type-demo"
            layoutType="Form"
            onFinish={async () => {
    
            }}
            initialValues={options.reduce((pre, item) => {
              return {
                ...pre,
                [item.value]: item.initialValue,
              };
            }, {})}
            columns={[
              {
                title: '分组',
                valueType: 'group',
                columns: [
                  {
                    valueType,
                    title: '编辑器',
                    dataIndex: valueType || 'text',
                    valueEnum,
                    formItemProps: {
                      rules: [
                        {
                          required: true,
                          message: '此项为必填项',
                        },
                      ],
                    },
                    width: 'm',
                  },
                  {
                    valueType,
                    title: '只读',
                    dataIndex: valueType || 'text',
                    valueEnum,
                    readonly: true,
                    width: 'm',
                  },
                ],
              },
            ]}
          />
        </>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );
    

    自定义 valueType

    标签
    路径
    running
    online
    runningonline
    Schema 自定义 valueType
    import type { ProFormColumnsType } from '@ant-design/pro-components';
    import { BetaSchemaForm, ProProvider } from '@ant-design/pro-components';
    import type { InputRef } from 'antd';
    import { Input, Space, Tag } from 'antd';
    import React, { useContext, useRef, useState } from 'react';
    
    import { DEMO_VALUE_ENUM } from '../../mockData';
    
    const _valueEnum = {
      0: 'close',
      1: 'running',
      2: 'online',
      3: 'error',
    };
    
    export type TableListItem = {
      key: number;
      name: string;
      status: {
        label: string | number;
        value: number;
      }[];
    };
    
    const TagList: React.FC<{
      value?: {
        key: string;
        label: string;
      }[];
      onChange?: (
        value: {
          key: string;
          label: string;
        }[],
      ) => void;
    }> = ({ value, onChange }) => {
      const ref = useRef<InputRef | null>(null);
      const [newTags, setNewTags] = useState<
        {
          key: string;
          label: string;
        }[]
      >([]);
      const [inputValue, setInputValue] = useState<string>('');
    
      const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        setInputValue(e.target.value);
      };
    
      const handleInputConfirm = () => {
        let tempsTags = [...(value || [])];
        if (
          inputValue &&
          tempsTags.filter((tag) => tag.label === inputValue).length === 0
        ) {
          tempsTags = [
            ...tempsTags,
            { key: `new-${tempsTags.length}`, label: inputValue },
          ];
        }
        onChange?.(tempsTags);
        setNewTags([]);
        setInputValue('');
      };
    
      return (
        <Space>
          {(value || []).concat(newTags).map((item) => (
            <Tag key={item.key}>{item.label}</Tag>
          ))}
          <Input
            ref={ref}
            type="text"
            size="small"
            style={{ width: 78 }}
            value={inputValue}
            onChange={handleInputChange}
            onBlur={handleInputConfirm}
            onPressEnter={handleInputConfirm}
          />
        </Space>
      );
    };
    
    const columns: ProFormColumnsType<TableListItem, 'link' | 'tags'>[] = [
      {
        title: '标签',
        valueType: 'group',
        columns: [
          {
            title: '只读链接',
            readonly: true,
            dataIndex: 'name',
            valueType: 'link',
          },
          {
            title: '链接',
            dataIndex: 'name',
            valueType: 'link',
          },
        ],
      },
      {
        title: '路径',
        valueType: 'group',
        columns: [
          {
            title: '标签',
            dataIndex: 'status',
            key: 'status',
            valueType: 'tags',
          },
          {
            title: '只读标签',
            readonly: true,
            dataIndex: 'status',
            key: 'status',
            valueType: 'tags',
          },
        ],
      },
    ];
    
    const Demo = () => {
      const values = useContext(ProProvider);
      return (
        <ProProvider.Provider
          value={{
            ...values,
            valueTypeMap: {
              link: {
                render: (text) => <a>{text}</a>,
                formItemRender: (text, props) => (
                  <Input placeholder="请输入链接" {...props?.fieldProps} />
                ),
              },
              tags: {
                render: (text) => {
                  return (
                    <>
                      {[text].flat(1).map((item) => (
                        <Tag key={item.value}>{item.label}</Tag>
                      ))}
                    </>
                  );
                },
                formItemRender: (text, props) => (
                  <TagList {...props} {...props?.fieldProps} />
                ),
              },
            },
          }}
        >
          <BetaSchemaForm<TableListItem, 'link' | 'tags'>
            initialValues={{
              key: 1,
              name: '用户认证服务',
              status: [
                {
                  value: 1,
                  label: DEMO_VALUE_ENUM[1],
                },
                {
                  value: 2,
                  label: DEMO_VALUE_ENUM[2],
                },
              ],
            }}
            columns={columns}
            title="自定义 valueType"
          />
        </ProProvider.Provider>
      );
    };
    
    export default () => (
      <div style={{ padding: 24 }}>
        <Demo />
      </div>
    );