优化更新
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
# BasicForm 表单
|
||||
|
||||
:::tip 说明
|
||||
`BasicForm` 位于 `src/components/Form/src/BasicForm.vue`,基于 ElementPlus 的 `el-form` 二次封装,通过 schemas 配置化定义表单字段,支持查询表单和业务表单两种模式。
|
||||
`BasicForm` 位于 `src/components/Form/src/BasicForm.vue`,基于 AntDesign Vue 的 `a-form` 二次封装,通过 schemas 配置化定义表单字段,支持查询表单和业务表单两种模式。
|
||||
:::
|
||||
|
||||
## 组件架构
|
||||
@@ -9,13 +9,13 @@
|
||||
```
|
||||
src/components/Form/
|
||||
├── src/
|
||||
│ ├── BasicForm.vue # 主组件
|
||||
│ ├── props.ts # 属性定义
|
||||
│ ├── helper.ts # 工具函数(placeholder 生成)
|
||||
│ ├── types/form.ts # 类型定义(FormSchema、FormProps)
|
||||
│ └── hooks/
|
||||
│ ├── useFormEvents.ts # 表单事件(submit、reset、validate)
|
||||
│ └── useFormValues.ts # 表单值处理(默认值初始化)
|
||||
│ ├── BasicForm.vue # 主组件
|
||||
│ ├── props.ts # 属性定义
|
||||
│ ├── helper.ts # 工具函数(placeholder 生成)
|
||||
│ ├── types/form.ts # 类型定义(FormSchema、FormProps)
|
||||
│ └── hooks/
|
||||
│ ├── useFormEvents.ts # 表单事件(submit、reset、validate)
|
||||
│ └── useFormValues.ts # 表单值处理(默认值初始化)
|
||||
└── index.ts # 导出 useForm、FormSchema 等
|
||||
```
|
||||
|
||||
@@ -24,9 +24,9 @@ src/components/Form/
|
||||
列表页的搜索区域使用 `useForm` 注册表单:
|
||||
|
||||
```vue
|
||||
<el-card :bordered="false" class="pt-3 mb-3 proCard">
|
||||
<a-card :bordered="false" class="pt-3 mb-3 proCard">
|
||||
<BasicForm @register="register" @submit="handleSubmit" @reset="handleReset" />
|
||||
</el-card>
|
||||
</a-card>
|
||||
```
|
||||
|
||||
### querySchemas 定义
|
||||
@@ -38,7 +38,7 @@ import { FormSchema } from '@/components/Form/index';
|
||||
|
||||
export const schemas: FormSchema[] = [
|
||||
{
|
||||
field: 'name',
|
||||
name: 'name',
|
||||
component: 'Input',
|
||||
label: '岗位名称',
|
||||
componentProps: {
|
||||
@@ -46,7 +46,7 @@ export const schemas: FormSchema[] = [
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'status',
|
||||
name: 'status',
|
||||
component: 'Select',
|
||||
label: '状态',
|
||||
componentProps: {
|
||||
@@ -66,26 +66,37 @@ export const schemas: FormSchema[] = [
|
||||
```typescript
|
||||
import { schemas } from './querySchemas';
|
||||
import { useForm } from '@/components/Form/index';
|
||||
import { ColProps } from 'element-plus';
|
||||
|
||||
const formParams = reactive({ name: '', status: '' });
|
||||
|
||||
const [register, {}] = useForm({
|
||||
labelWidth: 80,
|
||||
layout: 'horizontal',
|
||||
colProps: { span: 6 } as ColProps,
|
||||
submitOnReset: true,
|
||||
rowProps: { gutter: [16, 0] },
|
||||
colProps: {
|
||||
xs: 24,
|
||||
sm: 24,
|
||||
md: 12,
|
||||
lg: 8,
|
||||
xl: 6,
|
||||
},
|
||||
labelCol: { span: 6, offset: 0 },
|
||||
schemas,
|
||||
});
|
||||
|
||||
function handleSubmit(values: Recordable) {
|
||||
handleReset();
|
||||
for (const key in values) { formParams[key] = values[key]; }
|
||||
for (const key in formParams) {
|
||||
formParams[key] = '';
|
||||
}
|
||||
for (const key in values) {
|
||||
formParams[key] = values[key];
|
||||
}
|
||||
reloadTable();
|
||||
}
|
||||
|
||||
function handleReset() {
|
||||
for (const key in formParams) { formParams[key] = ''; }
|
||||
for (const key in formParams) {
|
||||
formParams[key] = '';
|
||||
}
|
||||
reloadTable();
|
||||
}
|
||||
```
|
||||
|
||||
@@ -93,73 +104,75 @@ function handleReset() {
|
||||
|
||||
## 业务表单(编辑弹窗)
|
||||
|
||||
编辑弹窗中直接使用 `el-form` + `el-form-item` 构建表单:
|
||||
编辑弹窗中直接使用 `a-form` + `a-form-item` 构建表单:
|
||||
|
||||
```vue
|
||||
<!-- src/views/system/position/edit.vue -->
|
||||
<template>
|
||||
<el-dialog v-model="props.visible" :title="props.positionId ? '编辑' : '新增'" width="500">
|
||||
<el-form class="ls-form" ref="formRef" :model="formData" label-width="80px">
|
||||
<el-form-item
|
||||
<a-modal v-model:visible="props.visible" :title="props.positionId ? '编辑' : '新增'" width="500px" @cancel="dialogClose">
|
||||
<a-form class="ls-form" ref="formRef" :model="formData" :label-col="{ style: { width: '85px' } }">
|
||||
<a-form-item
|
||||
label="岗位名称"
|
||||
prop="name"
|
||||
name="name"
|
||||
:rules="{ required: true, message: '请输入岗位名称', trigger: 'blur' }"
|
||||
>
|
||||
<el-input v-model="formData.name" placeholder="请输入岗位名称" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="岗位状态" prop="status">
|
||||
<el-radio-group v-model="formData.status">
|
||||
<el-radio :value="1">正常</el-radio>
|
||||
<el-radio :value="2">停用</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" prop="sort">
|
||||
<el-input-number v-model="formData.sort" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
<a-input v-model:value="formData.name" placeholder="请输入岗位名称" allow-clear />
|
||||
</a-form-item>
|
||||
<a-form-item label="岗位状态" name="status">
|
||||
<a-radio-group v-model:value="formData.status" name="status">
|
||||
<a-radio :value="1">正常</a-radio>
|
||||
<a-radio :value="2">停用</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="排序" name="sort">
|
||||
<a-input-number v-model:value="formData.sort" />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</template>
|
||||
```
|
||||
|
||||
## BasicForm 内部渲染机制
|
||||
|
||||
`BasicForm.vue` 根据 `schema.component` 动态渲染对应的 ElementPlus 组件:
|
||||
`BasicForm.vue` 根据 `schema.component` 动态渲染对应的 AntDesign Vue 组件:
|
||||
|
||||
```vue
|
||||
<!-- src/components/Form/src/BasicForm.vue 核心逻辑 -->
|
||||
<template v-for="schema in getSchema" :key="schema.field">
|
||||
<template v-for="schema in getSchema" :key="schema.name">
|
||||
<!-- Checkbox -->
|
||||
<template v-if="schema.component === 'Checkbox'">
|
||||
<el-checkbox-group v-model="formModel[schema.field]">
|
||||
<el-checkbox v-for="item in schema.componentProps?.options" :value="item.value">
|
||||
{{ item.label }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
<a-checkbox-group v-bind="getSpecComponentProps(schema)" v-model:value="formModel[schema.name]">
|
||||
<a-space>
|
||||
<a-checkbox v-for="item in schema.componentProps?.options" :key="item.value" :value="item.value">
|
||||
{{ item.label }}
|
||||
</a-checkbox>
|
||||
</a-space>
|
||||
</a-checkbox-group>
|
||||
</template>
|
||||
|
||||
<!-- RadioGroup -->
|
||||
<template v-else-if="schema.component === 'RadioGroup'">
|
||||
<el-radio-group v-model="formModel[schema.field]">
|
||||
<el-radio v-for="item in schema.componentProps?.options" :value="item.value">
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
<a-radio-group v-bind="getSpecComponentProps(schema)" v-model:value="formModel[schema.name]">
|
||||
<a-space>
|
||||
<a-radio v-for="item in schema.componentProps?.options" :key="item.value" :value="item.value">
|
||||
{{ item.label }}
|
||||
</a-radio>
|
||||
</a-space>
|
||||
</a-radio-group>
|
||||
</template>
|
||||
|
||||
<!-- Select -->
|
||||
<template v-else-if="schema.component === 'Select'">
|
||||
<el-select v-model="formModel[schema.field]">
|
||||
<el-option v-for="item in schema.componentProps?.options" :value="item.value" :label="item.label" />
|
||||
</el-select>
|
||||
<!-- BasicSelect -->
|
||||
<template v-else-if="schema.component === 'BasicSelect'">
|
||||
<BasicSelect v-model:value="formModel[schema.name]" v-bind="schema.componentProps" />
|
||||
</template>
|
||||
|
||||
<!-- Daterange -->
|
||||
<template v-else-if="schema.component === 'Daterange'">
|
||||
<el-date-picker v-model="formModel[schema.field]" type="daterange" value-format="YYYY-MM-DD" />
|
||||
</template>
|
||||
|
||||
<!-- 其他组件:动态渲染 el-{component} -->
|
||||
<component v-else :is="`el-${schema.component}`" v-model="formModel[schema.field]" />
|
||||
<!-- 其他组件:动态渲染 a-{component} -->
|
||||
<component
|
||||
v-else
|
||||
v-bind="getComponentProps(schema)"
|
||||
:is="`a-${schema.component}`"
|
||||
v-model:value="formModel[schema.name]"
|
||||
/>
|
||||
</template>
|
||||
```
|
||||
|
||||
@@ -167,19 +180,18 @@ function handleReset() {
|
||||
|
||||
```typescript
|
||||
interface FormSchema {
|
||||
field: string; // 字段名
|
||||
label: string; // 标签文本
|
||||
component: string; // 组件类型:Input / Select / RadioGroup / Checkbox / DatePicker 等
|
||||
componentProps?: any; // 组件属性(placeholder、options、clearable 等)
|
||||
required?: boolean; // 是否必填
|
||||
rules?: any[]; // 自定义校验规则
|
||||
defaultValue?: any; // 默认值
|
||||
hidden?: boolean | (({ schema, values, model }) => boolean); // 是否隐藏
|
||||
slot?: string; // 自定义插槽名
|
||||
suffix?: string; // 后缀插槽名
|
||||
labelMessage?: string; // 标签提示信息
|
||||
isFull?: boolean; // 是否全宽
|
||||
type?: string; // 组件子类型
|
||||
name: string; // 字段名
|
||||
label: string; // 标签文本
|
||||
component?: string; // 组件类型:Input / Select / RadioGroup / Checkbox / DatePicker 等
|
||||
componentProps?: any; // 组件属性(placeholder、options、clearable 等)
|
||||
rules?: object | object[]; // 自定义校验规则
|
||||
defaultValue?: any; // 默认值
|
||||
hidden?: boolean | (({ schema, values, model }) => boolean); // 是否隐藏
|
||||
slot?: string; // 自定义插槽名
|
||||
suffix?: string; // 后缀插槽名
|
||||
labelMessage?: string; // 标签提示信息
|
||||
isFull?: boolean; // 是否全宽
|
||||
colProps?: object; // 栅格配置
|
||||
}
|
||||
```
|
||||
|
||||
@@ -196,11 +208,11 @@ const handleSubmit = async () => {
|
||||
formRef.value?.clearValidate();
|
||||
```
|
||||
|
||||
Schema 中的 `required: true` 会自动生成必填校验规则,也可以通过 `rules` 自定义:
|
||||
Schema 中的 `rules` 支持自定义校验规则:
|
||||
|
||||
```typescript
|
||||
{
|
||||
field: 'name',
|
||||
name: 'name',
|
||||
label: '岗位名称',
|
||||
component: 'Input',
|
||||
rules: [
|
||||
@@ -237,4 +249,4 @@ onMounted(() => {
|
||||
|
||||
## 总结
|
||||
|
||||
BasicForm 通过 schemas 配置化定义表单字段,内部根据 `component` 动态渲染对应的 ElementPlus 组件。查询表单使用 `useForm` 注册并绑定 `@submit`/`@reset` 事件,业务表单直接使用 `el-form` + `reactive` 管理数据。支持多种组件类型、表单校验、数据绑定、条件隐藏等能力。
|
||||
BasicForm 通过 schemas 配置化定义表单字段,内部根据 `component` 动态渲染对应的 AntDesign Vue 组件。查询表单使用 `useForm` 注册并绑定 `@submit`/`@reset` 事件,业务表单直接使用 `a-form` + `reactive` 管理数据。支持多种组件类型、表单校验、数据绑定、条件隐藏等能力。
|
||||
|
||||
Reference in New Issue
Block a user