Skip to content
On this page

表单

FatForm 在 el-form 的基础之上进行了增强,配合原件,我们只需少量的配置就可以完成表单的开发。

以下是 FatForm 相关的套件:







1. 表单布局

FatForm 支持 3 种典型的布局:

查看代码
vue
<template>
  <div>
    <div style="margin-bottom: 20px">
      <el-radio-group v-model="layout">
        <el-radio-button label="horizontal"></el-radio-button>
        <el-radio-button label="vertical"></el-radio-button>
        <el-radio-button label="inline"></el-radio-button>
      </el-radio-group>
    </div>
    <FatForm :layout="layout" :submit="handleSubmit">
      <FatFormItem label="用户名" prop="name" trim="blur"></FatFormItem>
      <FatFormItem label="密码" prop="password" value-type="password"></FatFormItem>
    </FatForm>
  </div>
</template>

<script setup lang="tsx">
  import { FatForm, FatFormItem } from '@wakeadmin/components';
  import { ref } from 'vue';

  const layout = ref<any>('horizontal');

  const handleSubmit = async (value: any) => {
    console.log(value);
  };
</script>


1.1 分组

使用 FatFormGroup 可以对灵活地组合表单项, 让布局更加简单。



水平组合:

查看代码
vue
<template>
  <FatForm :enable-submitter="false">
    <FatFormGroup>
      <FatFormItem prop="name" label="名称"></FatFormItem>
      <FatFormItem prop="password" label="密码" value-type="password"></FatFormItem>
      <FatFormItem prop="remember" value-type="checkbox" :value-props="{ label: '记住密码' }"></FatFormItem>
    </FatFormGroup>
    <FatFormItem label="角色" prop="role" value-type="select"></FatFormItem>
  </FatForm>
</template>

<script lang="tsx" setup>
  import { FatForm, FatFormItem, FatFormGroup } from '@wakeadmin/components';
</script>


垂直组合:

查看代码
vue
<template>
  <FatForm :enable-submitter="false">
    <FatFormGroup label="分组" vertical>
      <FatFormItem prop="group[0]"></FatFormItem>
      <FatFormItem prop="group[1]"></FatFormItem>
      <FatFormItem prop="group[2]"></FatFormItem>
    </FatFormGroup>
  </FatForm>
</template>

<script lang="tsx" setup>
  import { FatForm, FatFormItem, FatFormGroup } from '@wakeadmin/components';
</script>


混编:

查看代码
vue
<template>
  <FatForm :enable-submitter="false">
    <FatFormGroup>
      获取积分后, 第
      <FatFormItem prop="name" value-type="integer" width="mini"></FatFormItem>
      个 3 月 31 日 23:59:59 失效
    </FatFormGroup>
  </FatForm>
</template>

<script lang="tsx" setup>
  import { FatForm, FatFormItem, FatFormGroup } from '@wakeadmin/components';
</script>



1.2 预定义宽度

我们预定义了一些表单项宽度,可以满足大多数表单场景,实现快捷开发的同时,保证 UI 的一致性:




  • mini=104px 适用于短数字、短文本或选项。
  • small=216px 适用于较短字段录入、如姓名、电话、ID 等。
  • medium=328px 标准宽度,适用于大部分字段长度。
  • large=440px 适用于较长字段录入,如长网址、标签组、文件路径等。
  • huge=552px 适用于长文本录入,如长链接、描述、备注等,通常搭配自适应多行输入框或定高文本域使用。

示例:

查看代码
vue
<template>
  <FatForm>
    <FatFormItem prop="mini0" label="短文本(mini)" width="mini"> </FatFormItem>
    <FatFormItem
      prop="mini1"
      label="短数字(mini)"
      width="mini"
      value-type="integer"
      :value-props="{ placeholder: '数字' }"
    >
    </FatFormItem>
    <FatFormItem prop="small" label="较短文本(small)" width="small"></FatFormItem>
    <FatFormItem prop="medium" label="标准文本(medium)" width="medium" message="适合大部分字段长度"></FatFormItem>
    <FatFormItem
      prop="large"
      label="长字段(large)"
      width="large"
      value-type="url"
      message="适用于较长字段录入,如长网址、标签组、文件路径等"
    ></FatFormItem>
    <FatFormItem
      prop="huge"
      label="长文本输入(huge)"
      width="huge"
      value-type="textarea"
      message="552px 适用于长文本录入,如长链接、描述、备注等,通常搭配自适应多行输入框或定高文本域使用"
    ></FatFormItem>
  </FatForm>
</template>

<script lang="tsx" setup>
  import { FatForm, FatFormItem } from '@wakeadmin/components';
</script>



1.3 网格布局

大部分场景我们推荐使用 FatFormGroup + width 来进行布局。 当然传统的网格布局我们依旧支持

查看代码
vue
<template>
  <FatForm>
    <FatFormItem label="标题" prop="name" tooltip="最长 24 位"></FatFormItem>
    <FatFormGroup>
      <FatFormItem :col="{ md: 12, xl: 8 }" prop="company" label="姓名"></FatFormItem>
      <FatFormItem :col="{ md: 12, xl: 8 }" prop="phone" label="电话"></FatFormItem>
      <FatFormItem :col="{ md: 12, xl: 8 }" prop="email" label="邮箱"></FatFormItem>
    </FatFormGroup>
    <FatFormItem :col="24" prop="textarea" value-type="textarea" label="文本框"></FatFormItem>
    <FatFormGroup>
      <FatFormItem :col="12" prop="date" value-type="date" label="入职时间"></FatFormItem>
      <FatFormItem :col="12" prop="dateRange" value-type="date-range" label="工作周期"></FatFormItem>
    </FatFormGroup>
  </FatForm>
</template>

<script lang="tsx" setup>
  import { FatForm, FatFormItem, FatFormGroup } from '@wakeadmin/components';
</script>

FatFormGroup 在这里的作用就是充当 Row, 如果要进一步控制 row 的行为,可以通过 FatFormGroup#row 属性进行配置。


FatFormGroupFatFormItem 都可以作为网格的单元格,通过 col 来配置单元格。


TIP

FatFormGroup 会自动检测子节点是否开启了网格,默认情况使用 FatSpace 来分组布局。





1.4 固定网格

某些场景,我们可能想要让所有的字段统一使用一个单元格配置,比如查询表单。这种情况可以使用 FatForm 的 col 属性来配置:


查看代码
vue
<template>
  <FatForm :col="{ xl: 6, lg: 8, sm: 12 }" label-width="100px">
    <FatFormItem prop="a" label="名称"></FatFormItem>
    <FatFormItem prop="b" label="姓名"></FatFormItem>
    <FatFormItem prop="c" label="收货地址"></FatFormItem>
    <FatFormItem prop="d" label="手机号码"></FatFormItem>
  </FatForm>
</template>

<script lang="tsx" setup>
  import { FatForm, FatFormItem } from '@wakeadmin/components';
</script>



1.5 提示信息

FatForm 内置了提示信息


查看代码
vue
<template>
  <FatForm :enable-submitter="false">
    <FatFormItem prop="a" label="默认" message="默认提示信息,位于表单下方"></FatFormItem>
    <FatFormItem prop="b" label="内联" inline-message message="内联提示信息"></FatFormItem>
    <FatFormItem prop="c" label="悬浮信息" tooltip="这是悬浮提示信息"></FatFormItem>
  </FatForm>
</template>

<script lang="tsx" setup>
  import { FatForm, FatFormItem } from '@wakeadmin/components';
</script>




1.6 分类

复杂的表单会包含很多字段,适当分类用户体验会更加好:


查看代码
vue
<template>
  <FatForm :enable-submitter="false">
    <FatFormSection title="基本信息">
      <FatFormItem prop="name" label="名称" width="medium" :rules="{ required: true }"></FatFormItem>
      <FatFormItem prop="age" label="年龄" width="huge"></FatFormItem>
    </FatFormSection>

    <FatFormSection title="详细信息">
      <FatFormItem prop="id" label="身份证" width="large"></FatFormItem>
      <FatFormItem prop="address" label="地址" width="large"></FatFormItem>
      <FatFormItem prop="note" label="备注" width="huge" value-type="textarea"></FatFormItem>
    </FatFormSection>
  </FatForm>
</template>

<script lang="tsx" setup>
  import { FatForm, FatFormItem, FatFormSection } from '@wakeadmin/components';
</script>




1.7 居中布局

居中布局在一些简单的表单场景也是比较常见的,居中可以让界面看起来更加美观

查看代码
vue
<template>
  <FatForm :enable-submitter="false" :style="{ maxWidth: '500px', margin: '0 auto' }">
    <FatFormItem prop="id" label="身份证" width="large"></FatFormItem>
    <FatFormItem prop="address" label="地址" width="large"></FatFormItem>
    <FatFormItem prop="note" label="备注" width="huge" value-type="textarea"></FatFormItem>
  </FatForm>
</template>

<script lang="tsx" setup>
  import { FatForm, FatFormItem } from '@wakeadmin/components';
</script>




1.8 自定义提交按钮

FatForm 也支持自定义提交按钮,不过只是简单的文案修改,可以通过 props 进行修改

查看代码
vue
<template>
  <FatForm :style="{ maxWidth: '500px', margin: '0 auto' }">
    <FatFormItem prop="id" label="身份证" width="large" required></FatFormItem>
    <FatFormItem prop="address" label="地址" width="large"></FatFormItem>
    <FatFormItem prop="note" label="备注" width="huge" value-type="textarea"></FatFormItem>
    <template #submitter="scope">
      <FatFormGroup label-width="auto">
        <el-button type="primary" @click="scope.submit">自定义提交</el-button>
        <el-button>自定义按钮</el-button>
      </FatFormGroup>
    </template>
  </FatForm>
</template>

<script lang="tsx" setup>
  import { FatForm, FatFormItem, FatFormGroup } from '@wakeadmin/components';
</script>


复用内置的提交按钮:

查看代码
vue
<template>
  <FatForm :style="{ maxWidth: '500px', margin: '0 auto' }">
    <FatFormItem prop="id" label="身份证" width="large" required></FatFormItem>
    <FatFormItem prop="address" label="地址" width="large"></FatFormItem>
    <FatFormItem prop="note" label="备注" width="huge" value-type="textarea"></FatFormItem>
    <template #submitter="scope">
      <FatFormGroup label-width="auto">
        <!-- vue template 不是直接渲染 VNode,可以使用 FatVNode 组件间接渲染  -->
        <FatVNode :vnode="scope.renderButtons()" />
        <el-button>自定义按钮</el-button>
      </FatFormGroup>
    </template>
  </FatForm>
</template>

<script lang="tsx" setup>
  import { FatForm, FatFormItem, FatFormGroup, FatVNode } from '@wakeadmin/components';
</script>
查看 defineFatForm 版本代码
tsx
import { defineFatForm } from '@wakeadmin/components';
import { ElButton } from 'element-plus';

export default defineFatForm(({ item, group, renderChild }) => {
  return () => ({
    style: { maxWidth: '500px', margin: '0 auto' },
    children: [
      item({ prop: 'id', label: '身份证', width: 'large', required: true }),
      item({ prop: 'address', label: '地址', width: 'large' }),
      item({ prop: 'note', label: '备注', width: 'huge', valueType: 'textarea' }),
    ],
    renderSubmitter(form) {
      return renderChild(
        group({
          labelWidth: 'auto',
          children: [form.renderButtons(), <ElButton>自定义按钮</ElButton>],
        })
      );
    },
  });
});





2. 表单数据

FatForm 会在内部维护表单的数据,用户有三种方式来设置表单的初始值:

  • 通过 initialValue
  • 通过 request 方法远程请求
  • 通过 FatFormIteminitialValue 配置

如果没配置初始值,FatForm 会自动初始化。


2.1 通过 initialValue 传入初始值



查看代码
vue
<template>
  <FatForm :initial-value="initialValue">
    <FatFormItem label="账号名" prop="name"></FatFormItem>
    <FatFormItem label="昵称" prop="nickName"></FatFormItem>
  </FatForm>
</template>

<script lang="tsx" setup>
  import { FatForm, FatFormItem } from '@wakeadmin/components';

  const initialValue = {
    name: 'ivan',
    nickName: '狗蛋',
  };
</script>


默认情况下, 在 FatForm 启动时,initialValue 会进行一次深拷贝,然后作为表单的初始化状态。

如果你想要将表单变更的状态回写到 initialValue,可以开启 syncToInitialValues 选项:

查看代码
vue
<template>
  <FatForm :initial-value="initialValue" sync-to-initial-values>
    <FatFormItem label="账号名" prop="name"></FatFormItem>
    <FatFormItem label="昵称" prop="nickName"></FatFormItem>
    <FatFormGroup label="数据">
      <pre><code>{{JSON.stringify(initialValue, null, 2)}}</code></pre>
    </FatFormGroup>
  </FatForm>
</template>

<script lang="tsx" setup>
  import { FatForm, FatFormItem, FatFormGroup } from '@wakeadmin/components';
  import { reactive } from 'vue';

  const initialValue = reactive({
    name: 'ivan',
    nickName: '狗蛋',
  });
</script>



FatFormItem 上也可以设置初始化值,这种方式会更加灵活,尤其是在 动态表单 的场景:

查看代码
vue
<template>
  <FatForm>
    <FatFormItem label="账号名" prop="name" initial-value="ivan"></FatFormItem>
    <FatFormItem label="昵称" prop="nickName" initial-value="狗蛋"></FatFormItem>
  </FatForm>
</template>

<script lang="tsx" setup>
  import { FatForm, FatFormItem } from '@wakeadmin/components';
</script>




2.2 通过 request 远程请求数据

很多场景我们是从远程服务器拉取数据来编辑的,这种情况可以使用 request 方法:


查看代码
vue
<template>
  <FatForm :request="request">
    <FatFormItem label="账号名" prop="name"></FatFormItem>
    <FatFormItem label="昵称" prop="nickName"></FatFormItem>
  </FatForm>
</template>

<script lang="tsx" setup>
  import { FatForm, FatFormItem } from '@wakeadmin/components';

  const request = async () => {
    return {
      name: 'ivan',
      nickName: '狗蛋',
    };
  };
</script>



从远程返回的数据未必符合要求。比如时间区间,后端通常会拆成两个字段,而我们的组件用一个字段。另外一种场景是数据格式的转换。

  • 这两者都可以在 request 中处理。
  • 如果是纯粹的数据转换,也可以通过 FatFormItem 的 convert 属性来处理

使用示例:

查看代码
vue
<template>
  <FatForm :request="request" layout="inline">
    <FatFormItem label="时间区间" prop="dateRange" value-type="date-range"></FatFormItem>
    <FatFormItem label="生日" prop="birthday" value-type="date" :convert="timestampToDate"></FatFormItem>
  </FatForm>
</template>

<script lang="tsx" setup>
  import { FatForm, FatFormItem } from '@wakeadmin/components';

  // 模拟请求, 假设后端返回时间戳
  const fetchData = () =>
    Promise.resolve({
      startDate: new Date('2012/12/12 12:12:12').getTime(),
      endDate: new Date('2012/12/14 12:12:12').getTime(),
      birthday: Date.now(),
    });

  const timestampToDate = (timestamp: number | undefined) => timestamp && new Date(timestamp);

  // 复杂转换推荐在 request 中进行
  const request = async () => {
    const { startDate, endDate, ...other } = await fetchData();

    return {
      dateRange: [timestampToDate(startDate), timestampToDate(endDate)],
      ...other,
    };
  };
</script>




2.3 表单项

FatForm 并没有提供直接修改表单数据的手段,比如 el-form 官方使用 v-model 来修改状态:

html
<el-form :inline="true" :model="formInline" class="demo-form-inline">
  <el-form-item label="审批人">
    <el-input v-model="formInline.user" placeholder="审批人"></el-input>
  </el-form-item>
  <el-form-item label="活动区域">
    <el-select v-model="formInline.region" placeholder="活动区域">
      <el-option label="区域一" value="shanghai"></el-option>
      <el-option label="区域二" value="beijing"></el-option>
    </el-select>
  </el-form-item>
  <el-form-item>
    <el-button type="primary" @click="onSubmit">查询</el-button>
  </el-form-item>
</el-form>


而 FatForm 下统一使用 FatFormItem 的 prop 来定义字段的路径:

查看代码
vue
<template>
  <FatForm>
    <FatFormItem label="审批人" prop="user" placeholder="审批人" width="small"></FatFormItem>
    <FatFormItem
      label="活动区域"
      prop="region"
      placeholder="活动区域"
      width="small"
      value-type="select"
      :value-props="{
        options: [
          { label: '区域一', value: 'shanghai' },
          { label: '区域二', value: 'beijing' },
        ],
      }"
    ></FatFormItem>
  </FatForm>
</template>

<script lang="tsx" setup>
  import { FatForm, FatFormItem } from '@wakeadmin/components';
</script>

prop 是一个查询路径, 和 JavaScript 的对象成员语法一致, 格式示例:

shell
a.b.c
a.b[0]    # 数组
a.b[0].c  # 数组




2.4 表单联动

复杂的表单绕不开表单之间的联动。 在 FatForm 中,我们推荐使用 FatFormConsumer 组件来实现联动:

查看代码
vue
<template>
  <FatForm :enable-submitter="false">
    <FatFormItem label="签约客户名称" prop="user" width="medium"></FatFormItem>
    <FatFormConsumer v-slot="scope">
      <FatFormItem
        prop="agree"
        label-width="auto"
        value-type="checkbox"
        :disabled="!scope.values.user"
        :value-props="{ label: `同意与 《${scope.values.user || '客户名称'}》签订合同` }"
      ></FatFormItem>
    </FatFormConsumer>
  </FatForm>
</template>

<script lang="tsx" setup>
  import { FatForm, FatFormItem, FatFormConsumer } from '@wakeadmin/components';
</script>

TIP

如上面的代码所示,如果 FatFormItem 没有配置 label,如果想要和其他 FatFormItem 对齐,需要显式配置 labelWidthauto





3. 表单提交

下面介绍 FatForm 表单提交的处理过程

数据提交的过程如上所示。



3.1 表单验证

表单验证的过程基本和 el-form 没多大差别。FatForm 增强了联动验证的支持。比如修改密码的场景:

查看代码
vue
<template>
  <FatForm>
    <FatFormItem label="密码" prop="password" value-type="password" :rules="passwordRule"></FatFormItem>
    <FatFormItem
      label="确认密码"
      prop="passwordConfirm"
      value-type="password"
      :rules="passwordConfirmRule"
      dependencies="password"
    ></FatFormItem>
  </FatForm>
</template>

<script lang="tsx" setup>
  import { FatForm, FatFormItem, FatFormItemRules } from '@wakeadmin/components';

  interface T {
    password?: string;
    passwordConfirm?: string;
  }

  const rule: (compareKey: keyof T) => FatFormItemRules<T> = compareKey => values =>
    [
      { required: true },
      {
        validator(_rule: any, value, callback) {
          if (value && values[compareKey] && value !== values[compareKey]) {
            callback(new Error('密码不匹配'));
          } else {
            callback();
          }
        },
      },
    ];

  const passwordRule = rule('passwordConfirm');
  const passwordConfirmRule = rule('password');
</script>

  • FatForm, FatFormItem 的 rules 支持传入函数,可以获取表单值和表单实例。实现联动验证
  • FatFormItemdependencies 属性可以用于设置依赖字段。当依赖的字段变动时,会触发当前字段重新验证



子表单验证

还有一种复杂的表单场景,即父子表单:



即某个字段底层也是一个 FatForm, 我们期望在触发验证或重置时也能带动这些子表单。FatForm 通过开启 hierarchyConnect 选项来支持这种关联。 默认开启。


开启后,父子 FatForm 会建立以下关联关系:

  1. 全局验证: 父 FatForm 在验证时,同时会触发子 FatForm 的验证
  2. 全局清理验证




3.2 表单数据转换

和上文 request 中的数据转换一样。如果输入端转换了,输出端的转换也是必然的过程。

对应的,复杂的数据转换可以在 submit 处理器中处理,简单的数据转换可以在 FatFormItem transform 中处理:

查看代码
vue
<template>
  <FatForm :submit="submit" layout="inline">
    <FatFormItem
      label="时间区间"
      prop="dateRange"
      value-type="date-range"
      :value-props="{ valueFormat: 'x' }"
      :transform="v => ({ startDate: v?.[0], endDate: v?.[1] })"
    ></FatFormItem>
    <FatFormItem label="生日" prop="birthday" value-type="date" :value-props="{ valueFormat: 'x' }"></FatFormItem>
  </FatForm>
</template>

<script lang="tsx" setup>
  import { FatForm, FatFormItem } from '@wakeadmin/components';

  // 复杂转换推荐在 submit 中进行
  const submit = async (values: any) => {
    console.log(values);
  };
</script>

transform 的转换规则如下:

ts
 /**
  * @param value 当前值
  * @param values 当前所有表单的值
  * @param prop 字段路径
  */
transform?: (value: any, values: Store, prop: string) => any

  • 如果返回一个对象,key 为新属性的 path, 例如 {'a.b': 0, 'a.c': 2, 'a.d[0]': 3}, 同时原本的字段会被移除
  • 如果返回非对象的值,将作为当前字段的值

假设:
prop 为  dataRange
transform 返回的是 {startTime、endTime}
最后的结果是 dataRange 会从 query 中移除,并且 startTime、endTime 会合并到 query 中





3.3 表单提交

接下来就是提交数据到远程了。数据经过验证和转换之后会传递给 submit 属性。如果数据保存成功,会触发 onFinish 事件:

vue
<template>
  <FatForm :submit="handleSubmit" @finish="handleFinish">
    <!-- ... -->
  </FatForm>
</template>

<script setup>
  const handleSubmit = async values => {
    // 后端数据请求
  };

  // 处理表单提交完成
  const handleFinish = async values => {
    // 成功保存
    message.success('保存成功');

    // or
    history.back();
  };
</script>




4. 动态表单

动态增删字段也是很常见的表单需求。

查看代码
vue
<template>
  <FatForm ref="formRef" :initial-value="initialValue">
    <FatFormConsumer v-slot="form">
      <FatFormGroup label="动态列表" vertical>
        <FatFormGroup v-for="(item, index) of form.values.list" :key="item.key">
          <FatFormItem :prop="`list[${index}].name`" placeholder="名称"></FatFormItem>
          <FatFormItem :prop="`list[${index}].note`" placeholder="备注"></FatFormItem>
          <el-button @click="handleRemove(item.key)">删除</el-button>
        </FatFormGroup>
        <el-button @click="handleAdd">新增</el-button>
      </FatFormGroup>
    </FatFormConsumer>
    <FatFormItem label="显示隐藏字段" prop="visible" value-type="checkbox"></FatFormItem>
    <FatFormConsumer v-slot="form">
      <FatFormItem
        v-if="form.values.visible"
        label="我是隐藏字段"
        prop="hidden"
        initial-value="hidden"
        width="medium"
        :preserve="false"
      ></FatFormItem>
    </FatFormConsumer>
    <FatFormGroup label="数据">
      <FatFormConsumer v-slot="form">
        <pre><code>{{JSON.stringify(form.values, null, 2)}}</code></pre>
      </FatFormConsumer>
    </FatFormGroup>
  </FatForm>
</template>

<script lang="tsx" setup>
  import { FatForm, FatFormGroup, FatFormConsumer, FatFormItem, useFatFormRef } from '@wakeadmin/components';

  interface S {
    list: { name: string; note: string; key: number }[];
  }

  const formRef = useFatFormRef<S>();
  let uid = 0;

  const initialValue = {
    list: [],
  };

  const handleAdd = () => {
    formRef.value?.values.list.push({ name: '', note: '', key: uid++ });
  };

  const handleRemove = (key: number) => {
    const idx = formRef.value?.values.list.findIndex(i => i.key === key);
    if (idx != null && idx !== -1) {
      formRef.value?.values.list.splice(idx, 1);
    }
  };
</script>

上面的代码展示了动态表单的简单处理过程。

另外还展示了条件展示字段, 通过 preserve 属性来控制,条件展示字段卸载后是否保留数据。





5. 预览模式

利用原件的 预览形态编辑形态, 我们现在可以做到一套代码就能满足 增改查, 即编辑页面和详情预览。

查看代码
vue
<template>
  <div>
    <div>
      <el-switch v-model="previewMode" active-text="预览模式" inactive-text="编辑模式"></el-switch>
    </div>
    <FatForm :mode="previewMode ? 'preview' : 'editable'">
      <FatFormItem prop="text" label="text" value-type="text" width="small" />
      <FatFormItem prop="password" label="password" value-type="password" width="small" />
      <FatFormItem prop="search" label="search" value-type="search" width="medium" />
      <FatFormItem prop="textarea" label="textarea" value-type="textarea" width="huge" />
      <FatFormItem prop="url" label="url" value-type="url" width="huge" />
      <FatFormItem prop="date" label="date" value-type="date" width="medium" />
      <FatFormItem prop="time" label="time" value-type="time" width="medium" />
      <FatFormItem prop="dateTime" label="date-time" value-type="date-time" width="medium" />
      <FatFormItem prop="dateRange" label="date-range" value-type="date-range" width="large" />
      <FatFormItem prop="dateTimeRange" label="date-time-range" value-type="date-time-range" width="large" />
      <FatFormItem prop="timeRange" label="time-range" value-type="time-range" width="large" />
      <FatFormItem prop="switch" label="switch" value-type="switch" width="mini" />
      <FatFormItem
        prop="select"
        label="select"
        value-type="select"
        width="small"
        :value-props="{
          options: [
            { label: '选项1', value: '1', color: 'primary' },
            { label: '选项2', value: '2', color: 'success' },
          ],
        }"
      />
      <FatFormItem
        prop="multi-select"
        label="multi-select"
        value-type="multi-select"
        width="small"
        :value-props="{
          options: [
            { label: '选项1', value: '1' },
            { label: '选项2', value: '2' },
          ],
          separator: ' - ',
        }"
      />
      <FatFormGroup label="checkbox1">
        <FatFormItem prop="checkbox1" value-type="checkbox" />
        <span>同意 996 吗</span>
      </FatFormGroup>
      <FatFormItem prop="checkbox2" label-width="auto" value-type="checkbox" :value-props="{ label: '是否开启' }" />
      <FatFormItem
        prop="radio"
        label="radio"
        value-type="radio"
        :value-props="{
          options: [
            { label: '', value: 1 },
            { label: '', value: 0 },
          ],
        }"
      />
      <FatFormItem
        prop="checkboxs"
        label="checkboxs"
        value-type="checkboxs"
        :value-props="{
          options: [
            { label: '选我', value: 1 },
            { label: '选我啊', value: 0 },
          ],
        }"
      />
      <FatFormItem prop="integer" label="integer" value-type="integer"></FatFormItem>
      <FatFormItem prop="float" label="float" value-type="float"></FatFormItem>
      <FatFormItem prop="currency" label="currency" value-type="currency"></FatFormItem>
      <FatFormItem prop="rate" label="rate" value-type="rate"></FatFormItem>
      <FatFormItem prop="slider" label="slider" value-type="slider" width="large"></FatFormItem>
      <FatFormItem
        prop="sliderVertical"
        label="slider-vertical"
        value-type="slider"
        :value-props="{ vertical: true }"
      ></FatFormItem>
      <FatFormItem prop="progress" label="progress" value-type="progress" :initial-value="50"></FatFormItem>
      <FatFormItem
        prop="images"
        label="images"
        value-type="images"
        :value-props="{ sizeLimit: 1024 * 100, accept: ['.png', '.jpg'] }"
        :rules="{ required: true }"
        message="请上传文件,大小不超过 100 KB"
      ></FatFormItem>
    </FatForm>
  </div>
</template>

<script lang="tsx" setup>
  import { ref } from 'vue';
  import { FatForm, FatFormGroup, FatFormItem } from '@wakeadmin/components';

  const previewMode = ref(false);
</script>




6. 自定义表单项

自定义表单项有两种方式:




原件@wakeadmin/components 的核心概念,我们优先推荐使用这种形式,将其构建成真正具备复用能力的组件。 详见自定义原件




使用 FatFormConsumer 也可以使用将外部表单组件集成到 FatForm 的体系下:

查看代码
vue
<template>
  <FatForm :enable-submitter="false">
    <FatFormItem label="姓名" prop="name" width="medium"></FatFormItem>
    <FatFormConsumer v-slot="scope">
      <el-form-item label="年龄">
        <el-input-number
          :model-value="scope.getFieldValue('age')"
          @update:model-value="scope.setFieldValue('age', $event)"
        />
      </el-form-item>
    </FatFormConsumer>
    <FatFormConsumer v-slot="scope">
      <el-form-item label="JSON">
        {{ JSON.stringify(scope.values, null, 2) }}
      </el-form-item>
    </FatFormConsumer>
  </FatForm>
</template>

<script lang="tsx" setup>
  import { FatForm, FatFormItem, FatFormConsumer } from '@wakeadmin/components';
</script>





7. 原件值映射(1.8+)

在 1.8 版本之前,表单项的数据转换只能通过 converttransform props 来实现, 而这两个方法的执行时机分别是在数据请求之后和表单提交之前。无法应付以下场景:

  • 将日期字符串双向转换为 Date
  • 将逗号分割的字符串转换为 数组
  • 将 JSON 字符串还原
  • 将字符串转换为数字
  • 等等

为了应付这些场景,我们在 1.8 版本为 FatFormItem 引入了 valueMap 属性,使用方法如下:

查看代码
tsx
import { defineFatForm } from '@wakeadmin/components';

export default defineFatForm<{ json?: string }>(({ item, consumer }) => {
  return () => ({
    children: [
      item({
        label: 'JSON',
        valueType: 'multi-select',
        prop: 'json',
        valueProps: {
          options: [
            { label: '1', value: 1 },
            { label: '2', value: 2 },
          ],
        },
        valueMap: {
          in: value => {
            if (!value) {
              return [];
            }
            try {
              return JSON.parse(value as string);
            } catch (e) {
              return [];
            }
          },
          out: value => {
            if (!value) {
              return '';
            }
            return JSON.stringify(value);
          },
        },
      }),
      consumer(scope => {
        return <pre>{JSON.stringify(scope.values, null, 2)}</pre>;
      }),
    ],
  });
});

@wakeadmin/components 也内置了一些常见的 valueMap 供直接导入,例如:

  • numberToString: 将原件的 number 类型转换为 string 类型
  • toJSONArrayString: 将原件的数组转换为 JSON 字符串, 默认值为 []
  • toJSONObjectString: 将原件的对象转换为 JSON 字符串, 默认值为 {}
  • toCommaSplitArray: 将原件的数组转换为逗号分割的字符串, 默认值为 []
  • toCommaSplitNumberArray: 将原件的数字数组转换为逗号分割的字符串, 默认值为 []




8. API

8.1 FatForm Props



8.2 FatForm Events




8.3 FatForm Methods