2024-09-10 21:48:51 +08:00
|
|
|
|
---
|
|
|
|
|
outline: deep
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
# Vben Form 表单
|
|
|
|
|
|
2024-09-22 14:16:06 +08:00
|
|
|
|
框架提供的表单组件,可适配 `Element Plus`、`Ant Design Vue`、`Naive UI` 等框架。
|
2024-09-10 21:48:51 +08:00
|
|
|
|
|
2024-09-22 14:16:06 +08:00
|
|
|
|
> 如果文档内没有参数说明,可以尝试在在线示例内寻找
|
2024-09-10 21:48:51 +08:00
|
|
|
|
|
2024-09-22 14:16:06 +08:00
|
|
|
|
::: info 写在前面
|
|
|
|
|
|
|
|
|
|
如果你觉得现有组件的封装不够理想,或者不完全符合你的需求,大可以直接使用原生组件,亦或亲手封装一个适合的组件。框架提供的组件并非束缚,使用与否,完全取决于你的需求与自由。
|
|
|
|
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
|
|
|
## 适配器
|
|
|
|
|
|
|
|
|
|
表单底层使用 [vee-validate](https://vee-validate.logaretm.com/v4/) 进行表单验证,所以你可以使用 `vee-validate` 的所有功能。对于不同的 UI 框架,我们提供了适配器,以便更好的适配不同的 UI 框架。
|
|
|
|
|
|
|
|
|
|
### 适配器说明
|
|
|
|
|
|
2024-10-13 18:33:43 +08:00
|
|
|
|
每个应用都有不同的 UI 框架,所以在应用的 `src/adapter/form` 和 `src/adapter/component` 内部,你可以根据自己的需求,进行组件适配。下面是 `Ant Design Vue` 的适配器示例代码,可根据注释查看说明:
|
2024-09-22 14:16:06 +08:00
|
|
|
|
|
2024-10-13 18:33:43 +08:00
|
|
|
|
::: details ant design vue 表单适配器
|
2024-09-22 14:16:06 +08:00
|
|
|
|
|
|
|
|
|
```ts
|
|
|
|
|
import type {
|
|
|
|
|
VbenFormSchema as FormSchema,
|
|
|
|
|
VbenFormProps,
|
|
|
|
|
} from '@vben/common-ui';
|
|
|
|
|
|
2024-10-13 18:33:43 +08:00
|
|
|
|
import type { ComponentType } from './component';
|
|
|
|
|
|
|
|
|
|
import { setupVbenForm, useVbenForm as useForm, z } from '@vben/common-ui';
|
|
|
|
|
import { $t } from '@vben/locales';
|
|
|
|
|
|
|
|
|
|
setupVbenForm<ComponentType>({
|
|
|
|
|
config: {
|
|
|
|
|
// ant design vue组件库默认都是 v-model:value
|
|
|
|
|
baseModelPropName: 'value',
|
|
|
|
|
// 一些组件是 v-model:checked 或者 v-model:fileList
|
|
|
|
|
modelPropNameMap: {
|
|
|
|
|
Checkbox: 'checked',
|
|
|
|
|
Radio: 'checked',
|
|
|
|
|
Switch: 'checked',
|
|
|
|
|
Upload: 'fileList',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
defineRules: {
|
|
|
|
|
// 输入项目必填国际化适配
|
|
|
|
|
required: (value, _params, ctx) => {
|
|
|
|
|
if (value === undefined || value === null || value.length === 0) {
|
2024-10-19 14:28:21 +08:00
|
|
|
|
return $t('ui.formRules.required', [ctx.label]);
|
2024-10-13 18:33:43 +08:00
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
},
|
|
|
|
|
// 选择项目必填国际化适配
|
|
|
|
|
selectRequired: (value, _params, ctx) => {
|
|
|
|
|
if (value === undefined || value === null) {
|
2024-10-19 14:28:21 +08:00
|
|
|
|
return $t('ui.formRules.selectRequired', [ctx.label]);
|
2024-10-13 18:33:43 +08:00
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const useVbenForm = useForm<ComponentType>;
|
|
|
|
|
|
|
|
|
|
export { useVbenForm, z };
|
|
|
|
|
export type VbenFormSchema = FormSchema<ComponentType>;
|
|
|
|
|
export type { VbenFormProps };
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
|
|
|
::: details ant design vue 组件适配器
|
|
|
|
|
|
|
|
|
|
```ts
|
|
|
|
|
/**
|
|
|
|
|
* 通用组件共同的使用的基础组件,原先放在 adapter/form 内部,限制了使用范围,这里提取出来,方便其他地方使用
|
|
|
|
|
* 可用于 vben-form、vben-modal、vben-drawer 等组件使用,
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import type { BaseFormComponentType } from '@vben/common-ui';
|
|
|
|
|
|
2024-10-03 15:15:50 +08:00
|
|
|
|
import type { Component, SetupContext } from 'vue';
|
2024-09-22 14:16:06 +08:00
|
|
|
|
import { h } from 'vue';
|
|
|
|
|
|
2024-12-04 21:42:21 +08:00
|
|
|
|
import { globalShareState, IconPicker } from '@vben/common-ui';
|
2024-09-22 14:16:06 +08:00
|
|
|
|
import { $t } from '@vben/locales';
|
|
|
|
|
|
|
|
|
|
import {
|
|
|
|
|
AutoComplete,
|
|
|
|
|
Button,
|
|
|
|
|
Checkbox,
|
|
|
|
|
CheckboxGroup,
|
|
|
|
|
DatePicker,
|
|
|
|
|
Divider,
|
|
|
|
|
Input,
|
|
|
|
|
InputNumber,
|
|
|
|
|
InputPassword,
|
|
|
|
|
Mentions,
|
2024-10-13 18:33:43 +08:00
|
|
|
|
notification,
|
2024-09-22 14:16:06 +08:00
|
|
|
|
Radio,
|
|
|
|
|
RadioGroup,
|
|
|
|
|
RangePicker,
|
|
|
|
|
Rate,
|
|
|
|
|
Select,
|
|
|
|
|
Space,
|
|
|
|
|
Switch,
|
|
|
|
|
Textarea,
|
|
|
|
|
TimePicker,
|
|
|
|
|
TreeSelect,
|
|
|
|
|
Upload,
|
|
|
|
|
} from 'ant-design-vue';
|
|
|
|
|
|
2024-10-13 18:33:43 +08:00
|
|
|
|
const withDefaultPlaceholder = <T extends Component>(
|
|
|
|
|
component: T,
|
|
|
|
|
type: 'input' | 'select',
|
|
|
|
|
) => {
|
|
|
|
|
return (props: any, { attrs, slots }: Omit<SetupContext, 'expose'>) => {
|
2024-10-19 14:28:21 +08:00
|
|
|
|
const placeholder = props?.placeholder || $t(`ui.placeholder.${type}`);
|
2024-10-13 18:33:43 +08:00
|
|
|
|
return h(component, { ...props, ...attrs, placeholder }, slots);
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
2024-09-22 14:16:06 +08:00
|
|
|
|
// 这里需要自行根据业务组件库进行适配,需要用到的组件都需要在这里类型说明
|
2024-10-13 18:33:43 +08:00
|
|
|
|
export type ComponentType =
|
2024-09-22 14:16:06 +08:00
|
|
|
|
| 'AutoComplete'
|
|
|
|
|
| 'Checkbox'
|
|
|
|
|
| 'CheckboxGroup'
|
|
|
|
|
| 'DatePicker'
|
2024-10-13 18:33:43 +08:00
|
|
|
|
| 'DefaultButton'
|
2024-09-22 14:16:06 +08:00
|
|
|
|
| 'Divider'
|
|
|
|
|
| 'Input'
|
|
|
|
|
| 'InputNumber'
|
|
|
|
|
| 'InputPassword'
|
|
|
|
|
| 'Mentions'
|
2024-10-13 18:33:43 +08:00
|
|
|
|
| 'PrimaryButton'
|
2024-09-22 14:16:06 +08:00
|
|
|
|
| 'Radio'
|
|
|
|
|
| 'RadioGroup'
|
|
|
|
|
| 'RangePicker'
|
|
|
|
|
| 'Rate'
|
|
|
|
|
| 'Select'
|
|
|
|
|
| 'Space'
|
|
|
|
|
| 'Switch'
|
|
|
|
|
| 'Textarea'
|
|
|
|
|
| 'TimePicker'
|
|
|
|
|
| 'TreeSelect'
|
|
|
|
|
| 'Upload'
|
2024-12-04 21:42:21 +08:00
|
|
|
|
| 'IconPicker';
|
2024-09-22 14:16:06 +08:00
|
|
|
|
| BaseFormComponentType;
|
|
|
|
|
|
2024-10-13 18:33:43 +08:00
|
|
|
|
async function initComponentAdapter() {
|
|
|
|
|
const components: Partial<Record<ComponentType, Component>> = {
|
|
|
|
|
// 如果你的组件体积比较大,可以使用异步加载
|
|
|
|
|
// Button: () =>
|
|
|
|
|
// import('xxx').then((res) => res.Button),
|
2024-10-03 15:15:50 +08:00
|
|
|
|
|
2024-09-22 14:16:06 +08:00
|
|
|
|
AutoComplete,
|
|
|
|
|
Checkbox,
|
|
|
|
|
CheckboxGroup,
|
|
|
|
|
DatePicker,
|
2024-10-13 18:33:43 +08:00
|
|
|
|
// 自定义默认按钮
|
|
|
|
|
DefaultButton: (props, { attrs, slots }) => {
|
2024-09-22 14:16:06 +08:00
|
|
|
|
return h(Button, { ...props, attrs, type: 'default' }, slots);
|
|
|
|
|
},
|
|
|
|
|
Divider,
|
2024-12-04 21:42:21 +08:00
|
|
|
|
IconPicker,
|
2024-10-03 15:15:50 +08:00
|
|
|
|
Input: withDefaultPlaceholder(Input, 'input'),
|
|
|
|
|
InputNumber: withDefaultPlaceholder(InputNumber, 'input'),
|
|
|
|
|
InputPassword: withDefaultPlaceholder(InputPassword, 'input'),
|
|
|
|
|
Mentions: withDefaultPlaceholder(Mentions, 'input'),
|
2024-10-13 18:33:43 +08:00
|
|
|
|
// 自定义主要按钮
|
|
|
|
|
PrimaryButton: (props, { attrs, slots }) => {
|
|
|
|
|
return h(Button, { ...props, attrs, type: 'primary' }, slots);
|
|
|
|
|
},
|
2024-09-22 14:16:06 +08:00
|
|
|
|
Radio,
|
|
|
|
|
RadioGroup,
|
|
|
|
|
RangePicker,
|
|
|
|
|
Rate,
|
2024-10-03 15:15:50 +08:00
|
|
|
|
Select: withDefaultPlaceholder(Select, 'select'),
|
2024-09-22 14:16:06 +08:00
|
|
|
|
Space,
|
|
|
|
|
Switch,
|
2024-10-03 15:15:50 +08:00
|
|
|
|
Textarea: withDefaultPlaceholder(Textarea, 'input'),
|
2024-09-22 14:16:06 +08:00
|
|
|
|
TimePicker,
|
2024-10-03 15:15:50 +08:00
|
|
|
|
TreeSelect: withDefaultPlaceholder(TreeSelect, 'select'),
|
2024-09-22 14:16:06 +08:00
|
|
|
|
Upload,
|
2024-10-13 18:33:43 +08:00
|
|
|
|
};
|
2024-09-22 14:16:06 +08:00
|
|
|
|
|
2024-10-13 18:33:43 +08:00
|
|
|
|
// 将组件注册到全局共享状态中
|
|
|
|
|
globalShareState.setComponents(components);
|
|
|
|
|
|
|
|
|
|
// 定义全局共享状态中的消息提示
|
|
|
|
|
globalShareState.defineMessage({
|
|
|
|
|
// 复制成功消息提示
|
|
|
|
|
copyPreferencesSuccess: (title, content) => {
|
|
|
|
|
notification.success({
|
|
|
|
|
description: content,
|
|
|
|
|
message: title,
|
|
|
|
|
placement: 'bottomRight',
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
2024-09-22 14:16:06 +08:00
|
|
|
|
|
2024-10-13 18:33:43 +08:00
|
|
|
|
export { initComponentAdapter };
|
2024-09-22 14:16:06 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
|
|
|
## 基础用法
|
|
|
|
|
|
|
|
|
|
::: tip README
|
|
|
|
|
|
|
|
|
|
下方示例代码中的,存在一些国际化、主题色未适配问题,这些问题只在文档内会出现,实际使用并不会有这些问题,可忽略,不必纠结。
|
|
|
|
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
|
|
|
使用 `useVbenForm` 创建最基础的表单。
|
|
|
|
|
|
|
|
|
|
<DemoPreview dir="demos/vben-form/basic" />
|
|
|
|
|
|
|
|
|
|
## 查询表单
|
|
|
|
|
|
|
|
|
|
查询表单是一种特殊的表单,用于查询数据。查询表单不会触发表单验证,只会触发查询事件。
|
|
|
|
|
|
|
|
|
|
<DemoPreview dir="demos/vben-form/query" />
|
|
|
|
|
|
|
|
|
|
## 表单校验
|
|
|
|
|
|
|
|
|
|
表单校验是一个非常重要的功能,可以通过 `rules` 属性进行校验。
|
|
|
|
|
|
|
|
|
|
<DemoPreview dir="demos/vben-form/rules" />
|
|
|
|
|
|
|
|
|
|
## 表单联动
|
|
|
|
|
|
|
|
|
|
表单联动是一个非常常见的功能,可以通过 `dependencies` 属性进行联动。
|
|
|
|
|
|
|
|
|
|
_注意_ 需要指定 `dependencies` 的 `triggerFields` 属性,设置由谁的改动来触发,以便表单组件能够正确的联动。
|
|
|
|
|
|
|
|
|
|
<DemoPreview dir="demos/vben-form/dynamic" />
|
|
|
|
|
|
|
|
|
|
## 自定义组件
|
|
|
|
|
|
|
|
|
|
如果你的业务组件库没有提供某个组件,你可以自行封装一个组件,然后加到表单内部。
|
|
|
|
|
|
|
|
|
|
<DemoPreview dir="demos/vben-form/custom" />
|
|
|
|
|
|
|
|
|
|
## 操作
|
|
|
|
|
|
|
|
|
|
一些常见的表单操作。
|
|
|
|
|
|
|
|
|
|
<DemoPreview dir="demos/vben-form/api" />
|
|
|
|
|
|
|
|
|
|
## API
|
|
|
|
|
|
|
|
|
|
`useVbenForm` 返回一个数组,第一个元素是表单组件,第二个元素是表单的方法。
|
|
|
|
|
|
|
|
|
|
```vue
|
|
|
|
|
<script setup lang="ts">
|
2024-10-14 22:53:23 +08:00
|
|
|
|
import { useVbenForm } from '#/adapter/form';
|
2024-09-22 14:16:06 +08:00
|
|
|
|
|
|
|
|
|
// Form 为弹窗组件
|
|
|
|
|
// formApi 为弹窗的方法
|
|
|
|
|
const [Form, formApi] = useVbenForm({
|
|
|
|
|
// 属性
|
|
|
|
|
// 事件
|
|
|
|
|
});
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
<Form />
|
|
|
|
|
</template>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### FormApi
|
|
|
|
|
|
|
|
|
|
useVbenForm 返回的第二个参数,是一个对象,包含了一些表单的方法。
|
|
|
|
|
|
2025-03-10 02:24:58 +08:00
|
|
|
|
| 方法名 | 描述 | 类型 | 版本号 |
|
|
|
|
|
| --- | --- | --- | --- |
|
|
|
|
|
| submitForm | 提交表单 | `(e:Event)=>Promise<Record<string,any>>` | - |
|
|
|
|
|
| validateAndSubmitForm | 提交并校验表单 | `(e:Event)=>Promise<Record<string,any>>` | - |
|
|
|
|
|
| resetForm | 重置表单 | `()=>Promise<void>` | - |
|
|
|
|
|
| setValues | 设置表单值, 默认会过滤不在schema中定义的field, 可通过filterFields形参关闭过滤 | `(fields: Record<string, any>, filterFields?: boolean, shouldValidate?: boolean) => Promise<void>` | - |
|
|
|
|
|
| getValues | 获取表单值 | `(fields:Record<string, any>,shouldValidate: boolean = false)=>Promise<void>` | - |
|
|
|
|
|
| validate | 表单校验 | `()=>Promise<void>` | - |
|
|
|
|
|
| validateField | 校验指定字段 | `(fieldName: string)=>Promise<ValidationResult<unknown>>` | - |
|
|
|
|
|
| isFieldValid | 检查某个字段是否已通过校验 | `(fieldName: string)=>Promise<boolean>` | - |
|
|
|
|
|
| resetValidate | 重置表单校验 | `()=>Promise<void>` | - |
|
|
|
|
|
| updateSchema | 更新formSchema | `(schema:FormSchema[])=>void` | - |
|
|
|
|
|
| setFieldValue | 设置字段值 | `(field: string, value: any, shouldValidate?: boolean)=>Promise<void>` | - |
|
|
|
|
|
| setState | 设置组件状态(props) | `(stateOrFn:\| ((prev: VbenFormProps) => Partial<VbenFormProps>)\| Partial<VbenFormProps>)=>Promise<void>` | - |
|
|
|
|
|
| getState | 获取组件状态(props) | `()=>Promise<VbenFormProps>` | - |
|
|
|
|
|
| form | 表单对象实例,可以操作表单,见 [useForm](https://vee-validate.logaretm.com/v4/api/use-form/) | - | - |
|
|
|
|
|
| getFieldComponentRef | 获取指定字段的组件实例 | `<T=unknown>(fieldName: string)=>T` | >5.5.3 |
|
|
|
|
|
| getFocusedField | 获取当前已获得焦点的字段 | `()=>string\|undefined` | >5.5.3 |
|
2024-09-22 14:16:06 +08:00
|
|
|
|
|
|
|
|
|
## Props
|
|
|
|
|
|
|
|
|
|
所有属性都可以传入 `useVbenForm` 的第一个参数中。
|
|
|
|
|
|
|
|
|
|
| 属性名 | 描述 | 类型 | 默认值 |
|
|
|
|
|
| --- | --- | --- | --- |
|
|
|
|
|
| layout | 表单项布局 | `'horizontal' \| 'vertical'` | `horizontal` |
|
|
|
|
|
| showCollapseButton | 是否显示折叠按钮 | `boolean` | `false` |
|
|
|
|
|
| wrapperClass | 表单的布局,基于tailwindcss | `any` | - |
|
|
|
|
|
| actionWrapperClass | 表单操作区域class | `any` | - |
|
|
|
|
|
| handleReset | 表单重置回调 | `(values: Record<string, any>,) => Promise<void> \| void` | - |
|
|
|
|
|
| handleSubmit | 表单提交回调 | `(values: Record<string, any>,) => Promise<void> \| void` | - |
|
2024-12-11 14:48:08 +08:00
|
|
|
|
| handleValuesChange | 表单值变化回调 | `(values: Record<string, any>,) => void` | - |
|
2024-12-11 15:29:25 +08:00
|
|
|
|
| actionButtonsReverse | 调换操作按钮位置 | `boolean` | `false` |
|
2024-09-22 14:16:06 +08:00
|
|
|
|
| resetButtonOptions | 重置按钮组件参数 | `ActionButtonOptions` | - |
|
|
|
|
|
| submitButtonOptions | 提交按钮组件参数 | `ActionButtonOptions` | - |
|
|
|
|
|
| showDefaultActions | 是否显示默认操作按钮 | `boolean` | `true` |
|
2024-12-16 22:37:29 +08:00
|
|
|
|
| collapsed | 是否折叠,在`showCollapseButton`为`true`时生效 | `boolean` | `false` |
|
2024-10-04 23:05:28 +08:00
|
|
|
|
| collapseTriggerResize | 折叠时,触发`resize`事件 | `boolean` | `false` |
|
2024-09-22 14:16:06 +08:00
|
|
|
|
| collapsedRows | 折叠时保持的行数 | `number` | `1` |
|
2025-01-14 18:15:00 +08:00
|
|
|
|
| fieldMappingTime | 用于将表单内的数组值值映射成 2 个字段 | `[string, [string, string],Nullable<string>\|[string,string]\|((any,string)=>any)?][]` | - |
|
2024-09-22 14:16:06 +08:00
|
|
|
|
| commonConfig | 表单项的通用配置,每个配置都会传递到每个表单项,表单项可覆盖 | `FormCommonConfig` | - |
|
2024-12-16 22:37:29 +08:00
|
|
|
|
| schema | 表单项的每一项配置 | `FormSchema[]` | - |
|
2024-10-17 22:53:05 +08:00
|
|
|
|
| submitOnEnter | 按下回车健时提交表单 | `boolean` | false |
|
2024-12-16 22:37:29 +08:00
|
|
|
|
| submitOnChange | 字段值改变时提交表单(内部防抖,这个属性一般用于表格的搜索表单) | `boolean` | false |
|
2024-09-22 14:16:06 +08:00
|
|
|
|
|
2025-01-09 22:49:28 +08:00
|
|
|
|
::: tip fieldMappingTime
|
|
|
|
|
|
2025-01-14 18:15:00 +08:00
|
|
|
|
此属性用于将表单内的数组值映射成 2 个字段,它应当传入一个数组,数组的每一项是一个映射规则,规则的第一个成员是一个字符串,表示需要映射的字段名,第二个成员是一个数组,表示映射后的字段名,第三个成员是一个可选的格式掩码,用于格式化日期时间字段;也可以提供一个格式化函数(参数分别为当前值和当前字段名,返回格式化后的值)。如果明确地将格式掩码设为null,则原值映射而不进行格式化(适用于非日期时间字段)。例如:`[['timeRange', ['startTime', 'endTime'], 'YYYY-MM-DD']]`,`timeRange`应当是一个至少具有2个成员的数组类型的值。Form会将`timeRange`的值前两个值分别按照格式掩码`YYYY-MM-DD`格式化后映射到`startTime`和`endTime`字段上。每一项的第三个参数是一个可选的格式掩码,
|
2025-01-09 22:49:28 +08:00
|
|
|
|
|
|
|
|
|
:::
|
|
|
|
|
|
2024-09-22 14:16:06 +08:00
|
|
|
|
### TS 类型说明
|
|
|
|
|
|
|
|
|
|
::: details ActionButtonOptions
|
|
|
|
|
|
|
|
|
|
```ts
|
|
|
|
|
export interface ActionButtonOptions {
|
|
|
|
|
/** 样式 */
|
2024-11-09 14:07:41 +08:00
|
|
|
|
class?: ClassType;
|
2024-09-22 14:16:06 +08:00
|
|
|
|
/** 是否禁用 */
|
|
|
|
|
disabled?: boolean;
|
|
|
|
|
/** 是否加载中 */
|
|
|
|
|
loading?: boolean;
|
|
|
|
|
/** 按钮大小 */
|
|
|
|
|
size?: ButtonVariantSize;
|
|
|
|
|
/** 按钮类型 */
|
|
|
|
|
variant?: ButtonVariants;
|
|
|
|
|
/** 是否显示 */
|
|
|
|
|
show?: boolean;
|
|
|
|
|
/** 按钮文本 */
|
2025-02-06 09:45:28 +08:00
|
|
|
|
content?: string;
|
2024-10-21 20:14:25 +08:00
|
|
|
|
/** 任意属性 */
|
|
|
|
|
[key: string]: any;
|
2024-09-22 14:16:06 +08:00
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
|
|
|
::: details FormCommonConfig
|
|
|
|
|
|
|
|
|
|
```ts
|
|
|
|
|
export interface FormCommonConfig {
|
|
|
|
|
/**
|
|
|
|
|
* 所有表单项的props
|
|
|
|
|
*/
|
|
|
|
|
componentProps?: ComponentProps;
|
2024-12-17 20:51:17 +08:00
|
|
|
|
/**
|
|
|
|
|
* 是否紧凑模式(移除表单底部为显示校验错误信息所预留的空间)。
|
|
|
|
|
* 在有设置校验规则的场景下,建议不要将其设置为true
|
|
|
|
|
* 默认为false。但用作表格的搜索表单时,默认为true
|
|
|
|
|
* @default false
|
|
|
|
|
*/
|
|
|
|
|
compact?: boolean;
|
2024-09-22 14:16:06 +08:00
|
|
|
|
/**
|
|
|
|
|
* 所有表单项的控件样式
|
|
|
|
|
*/
|
|
|
|
|
controlClass?: string;
|
2024-12-16 22:37:29 +08:00
|
|
|
|
/**
|
|
|
|
|
* 在表单项的Label后显示一个冒号
|
|
|
|
|
*/
|
|
|
|
|
colon?: boolean;
|
2024-09-22 14:16:06 +08:00
|
|
|
|
/**
|
|
|
|
|
* 所有表单项的禁用状态
|
|
|
|
|
* @default false
|
|
|
|
|
*/
|
|
|
|
|
disabled?: boolean;
|
|
|
|
|
/**
|
|
|
|
|
* 所有表单项的控件样式
|
|
|
|
|
* @default {}
|
|
|
|
|
*/
|
|
|
|
|
formFieldProps?: Partial<typeof Field>;
|
|
|
|
|
/**
|
|
|
|
|
* 所有表单项的栅格布局
|
|
|
|
|
* @default ""
|
|
|
|
|
*/
|
|
|
|
|
formItemClass?: string;
|
|
|
|
|
/**
|
|
|
|
|
* 隐藏所有表单项label
|
|
|
|
|
* @default false
|
|
|
|
|
*/
|
|
|
|
|
hideLabel?: boolean;
|
|
|
|
|
/**
|
|
|
|
|
* 是否隐藏必填标记
|
|
|
|
|
* @default false
|
|
|
|
|
*/
|
|
|
|
|
hideRequiredMark?: boolean;
|
|
|
|
|
/**
|
|
|
|
|
* 所有表单项的label样式
|
|
|
|
|
* @default ""
|
|
|
|
|
*/
|
|
|
|
|
labelClass?: string;
|
|
|
|
|
/**
|
|
|
|
|
* 所有表单项的label宽度
|
|
|
|
|
*/
|
|
|
|
|
labelWidth?: number;
|
2025-01-09 22:49:28 +08:00
|
|
|
|
/**
|
|
|
|
|
* 所有表单项的model属性名。使用自定义组件时可通过此配置指定组件的model属性名。已经在modelPropNameMap中注册的组件不受此配置影响
|
|
|
|
|
* @default "modelValue"
|
|
|
|
|
*/
|
|
|
|
|
modelPropName?: string;
|
2024-09-22 14:16:06 +08:00
|
|
|
|
/**
|
|
|
|
|
* 所有表单项的wrapper样式
|
|
|
|
|
*/
|
|
|
|
|
wrapperClass?: string;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
|
|
|
::: details FormSchema
|
|
|
|
|
|
|
|
|
|
```ts
|
|
|
|
|
export interface FormSchema<
|
|
|
|
|
T extends BaseFormComponentType = BaseFormComponentType,
|
|
|
|
|
> extends FormCommonConfig {
|
|
|
|
|
/** 组件 */
|
|
|
|
|
component: Component | T;
|
|
|
|
|
/** 组件参数 */
|
|
|
|
|
componentProps?: ComponentProps;
|
|
|
|
|
/** 默认值 */
|
|
|
|
|
defaultValue?: any;
|
|
|
|
|
/** 依赖 */
|
|
|
|
|
dependencies?: FormItemDependencies;
|
|
|
|
|
/** 描述 */
|
|
|
|
|
description?: string;
|
2024-12-16 22:37:29 +08:00
|
|
|
|
/** 字段名,也作为自定义插槽的名称 */
|
2024-09-22 14:16:06 +08:00
|
|
|
|
fieldName: string;
|
|
|
|
|
/** 帮助信息 */
|
2025-02-20 23:05:08 +08:00
|
|
|
|
help?: CustomRenderType;
|
|
|
|
|
/** 表单的标签(如果是一个string,会用于默认必选规则的消息提示) */
|
|
|
|
|
label?: CustomRenderType;
|
2024-12-01 21:37:19 +08:00
|
|
|
|
/** 自定义组件内部渲染 */
|
2024-09-22 14:16:06 +08:00
|
|
|
|
renderComponentContent?: RenderComponentContentType;
|
|
|
|
|
/** 字段规则 */
|
|
|
|
|
rules?: FormSchemaRuleType;
|
|
|
|
|
/** 后缀 */
|
|
|
|
|
suffix?: CustomRenderType;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
:::
|
|
|
|
|
|
|
|
|
|
### 表单联动
|
|
|
|
|
|
|
|
|
|
表单联动需要通过 schema 内的 `dependencies` 属性进行联动,允许您添加字段之间的依赖项,以根据其他字段的值控制字段。
|
|
|
|
|
|
|
|
|
|
```ts
|
|
|
|
|
dependencies: {
|
2024-12-16 22:37:29 +08:00
|
|
|
|
// 触发字段。只有这些字段值变动时,联动才会触发
|
2024-09-22 14:16:06 +08:00
|
|
|
|
triggerFields: ['name'],
|
|
|
|
|
// 动态判断当前字段是否需要显示,不显示则直接销毁
|
|
|
|
|
if(values,formApi){},
|
|
|
|
|
// 动态判断当前字段是否需要显示,不显示用css隐藏
|
|
|
|
|
show(values,formApi){},
|
|
|
|
|
// 动态判断当前字段是否需要禁用
|
|
|
|
|
disabled(values,formApi){},
|
|
|
|
|
// 字段变更时,都会触发该函数
|
|
|
|
|
trigger(values,formApi){},
|
|
|
|
|
// 动态rules
|
|
|
|
|
rules(values,formApi){},
|
|
|
|
|
// 动态必填
|
|
|
|
|
required(values,formApi){},
|
|
|
|
|
// 动态组件参数
|
|
|
|
|
componentProps(values,formApi){},
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 表单校验
|
|
|
|
|
|
2024-12-16 22:37:29 +08:00
|
|
|
|
表单校验需要通过 schema 内的 `rules` 属性进行配置。
|
2024-09-22 14:16:06 +08:00
|
|
|
|
|
2024-12-16 22:37:29 +08:00
|
|
|
|
rules的值可以是字符串(预定义的校验规则名称),也可以是一个zod的schema。
|
2024-09-22 14:16:06 +08:00
|
|
|
|
|
2024-12-16 22:37:29 +08:00
|
|
|
|
#### 预定义的校验规则
|
2024-09-22 14:16:06 +08:00
|
|
|
|
|
|
|
|
|
```ts
|
|
|
|
|
// 表示字段必填,默认会根据适配器的required进行国际化
|
|
|
|
|
{
|
|
|
|
|
rules: 'required';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 表示字段必填,默认会根据适配器的required进行国际化,用于下拉选择之类
|
|
|
|
|
{
|
|
|
|
|
rules: 'selectRequired';
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### zod
|
|
|
|
|
|
|
|
|
|
rules也支持 zod 的 schema,可以进行更复杂的校验,zod 的使用请查看 [zod文档](https://zod.dev/)。
|
|
|
|
|
|
|
|
|
|
```ts
|
2024-10-14 22:53:23 +08:00
|
|
|
|
import { z } from '#/adapter/form';
|
2024-09-22 14:16:06 +08:00
|
|
|
|
|
|
|
|
|
// 基础类型
|
|
|
|
|
{
|
|
|
|
|
rules: z.string().min(1, { message: '请输入字符串' });
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-16 22:37:29 +08:00
|
|
|
|
// 可选(可以是undefined),并且携带默认值。注意zod的optional不包括空字符串''
|
2024-09-22 14:16:06 +08:00
|
|
|
|
{
|
2025-02-27 17:27:00 +08:00
|
|
|
|
rules: z.string().default('默认值').optional();
|
2024-09-22 14:16:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
2025-02-27 17:27:00 +08:00
|
|
|
|
// 可以是空字符串、undefined或者一个邮箱地址(两种不同的用法)
|
2024-12-16 22:37:29 +08:00
|
|
|
|
{
|
2025-02-27 17:27:00 +08:00
|
|
|
|
rules: z.union([z.string().email().optional(), z.literal('')]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
rules: z.string().email().or(z.literal('')).optional();
|
2024-12-16 22:37:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
2024-09-22 14:16:06 +08:00
|
|
|
|
// 复杂校验
|
|
|
|
|
{
|
2025-02-27 17:27:00 +08:00
|
|
|
|
z.string()
|
|
|
|
|
.min(1, { message: '请输入' })
|
|
|
|
|
.refine((value) => value === '123', {
|
|
|
|
|
message: '值必须为123',
|
|
|
|
|
});
|
2024-09-22 14:16:06 +08:00
|
|
|
|
}
|
|
|
|
|
```
|
2024-12-01 21:37:19 +08:00
|
|
|
|
|
|
|
|
|
## Slots
|
|
|
|
|
|
|
|
|
|
可以使用以下插槽在表单中插入自定义的内容
|
|
|
|
|
|
|
|
|
|
| 插槽名 | 描述 |
|
|
|
|
|
| ------------- | ------------------ |
|
|
|
|
|
| reset-before | 重置按钮之前的位置 |
|
|
|
|
|
| submit-before | 提交按钮之前的位置 |
|
|
|
|
|
| expand-before | 展开按钮之前的位置 |
|
|
|
|
|
| expand-after | 展开按钮之后的位置 |
|
|
|
|
|
|
|
|
|
|
::: tip 字段插槽
|
|
|
|
|
|
|
|
|
|
除了以上内置插槽之外,`schema`属性中每个字段的`fieldName`都可以作为插槽名称,这些字段插槽的优先级高于`component`定义的组件。也就是说,当提供了与`fieldName`同名的插槽时,这些插槽的内容将会作为这些字段的组件,此时`component`的值将会被忽略。
|
|
|
|
|
|
|
|
|
|
:::
|