Appearance
完整示例
fetchInitialData、字段联动、插槽的综合示例。
独立页面表单
挂载时自动调用 fetchInitialData 回填数据;类型/子类型联动;备注通过开关控制显隐;提交走 api。
vue
<template>
<ProForm ref="formRef" :config="formConfig" @submit="onSubmit">
<template #form-extra-name="{ formData }">
<span style="color: #909399">当前:{{ formData?.name || '未填写' }}</span>
</template>
</ProForm>
</template>
<script setup>
import { getUserInfo, updateUserInfo } from '@/api/user'
const formConfig = {
labelWidth: '90px',
span: 12,
params: {},
model: { name: '', status: 1, type: '', subType: '', enableRemark: false, remark: '' },
// 挂载时自动请求并回填
fetchInitialData: async (params) => {
const res = await getUserInfo(params)
return res.data
},
api: async (data) => updateUserInfo(data),
fields: [
{ label: '姓名', key: 'name', component: 'input', extra: 'slot',
rules: [{ required: true, message: '请输入姓名' }] },
{ label: '状态', key: 'status', component: 'select',
options: [{ label: '启用', value: 1 }, { label: '禁用', value: 0 }] },
{ label: '类型', key: 'type', component: 'select',
options: [{ label: '类型 A', value: 'A' }, { label: '类型 B', value: 'B' }] },
{ label: '子类型', key: 'subType', component: 'select',
disabled: (d) => !d.type,
options: (d) => d.type === 'A'
? [{ label: 'A1', value: 'A1' }, { label: 'A2', value: 'A2' }]
: [{ label: 'B1', value: 'B1' }, { label: 'B2', value: 'B2' }] },
{ label: '填写备注', key: 'enableRemark', component: 'switch' },
{ label: '备注', key: 'remark', component: 'textarea', rows: 3, span: 24,
visible: (d) => d.enableRemark === true }
],
footer: { submitText: '保存', showReset: true, align: 'left' }
}
function onSubmit(res, formData) {
console.log('保存成功', formData)
}
</script>长表单校验失败自动滚动
用于验证字段较多、表单内容区域出现滚动条时,点击提交后是否会自动滚动到第一个必填错误项。
vue
<template>
<div class="form-scroll-box">
<ProForm :config="formConfig" />
</div>
</template>
<script setup>
const fillerFields = Array.from({ length: 24 }, (_, index) => ({
label: `普通字段 ${index + 1}`,
key: `field${index + 1}`,
component: 'input'
}))
const formConfig = {
labelWidth: '110px',
span: 24,
model: {
requiredName: '',
requiredCode: '',
...Object.fromEntries(fillerFields.map((field) => [field.key, '']))
},
formAttrs: {
scrollToError: true,
scrollIntoViewOptions: { behavior: 'smooth', block: 'center', inline: 'nearest' }
},
fields: [
{
label: '顶部必填名称',
key: 'requiredName',
component: 'input',
rules: [{ required: true, message: '请输入顶部必填名称', trigger: 'blur' }]
},
{
label: '顶部必填编码',
key: 'requiredCode',
component: 'input',
rules: [{ required: true, message: '请输入顶部必填编码', trigger: 'blur' }]
},
...fillerFields
],
footer: { submitText: '提交测试', showReset: true }
}
</script>
<style scoped>
.form-scroll-box {
height: 420px;
overflow: hidden;
}
.form-scroll-box :deep(.pro-form) {
height: 100%;
}
</style>与 ProTable 联动(弹窗模式)
通过 form-config 传入 ProTable,内部自动管理弹层开关、新增/编辑模式切换:
vue
<template>
<pro-table
:search-config="searchConfig"
:table-config="tableConfig"
:form-config="formConfig"
/>
</template>
<script setup>
import { reactive } from 'vue'
import { getUserList, getUserDetail, saveUser, deleteUser } from '@/api/user'
const searchConfig = reactive({
model: { name: '', status: '' },
fields: [
{ label: '姓名', key: 'name', component: 'input' },
{ label: '状态', key: 'status', component: 'select',
options: [{ label: '启用', value: 1 }, { label: '禁用', value: 0 }] }
]
})
const tableConfig = reactive({
requestConfig: { api: getUserList },
columns: [
{ label: '姓名', key: 'name' },
{ label: '状态', key: 'status',
tag: { map: { 1: '启用', 0: '禁用' }, type: { 1: 'success', 0: 'danger' } } },
{ label: '创建时间', key: 'createTime', width: 160 }
],
deleteConfig: { api: deleteUser, idField: 'id' }
})
const formConfig = reactive({
mode: 'dialog',
width: '500px',
model: { name: '', status: 1, type: 'A', subType: '' },
fields: [
{ label: '姓名', key: 'name', component: 'input',
rules: [{ required: true, message: '请输入姓名' }] },
{ label: '状态', key: 'status', component: 'select',
options: [{ label: '启用', value: 1 }, { label: '禁用', value: 0 }] },
{ label: '类型', key: 'type', component: 'select',
options: [{ label: 'A', value: 'A' }, { label: 'B', value: 'B' }] },
{ label: '子类型', key: 'subType', component: 'select',
disabled: (d) => !d.type,
options: (d) => d.type === 'A'
? [{ label: 'A1', value: 'A1' }, { label: 'A2', value: 'A2' }]
: [{ label: 'B1', value: 'B1' }, { label: 'B2', value: 'B2' }] }
],
add: { title: '新增用户', api: saveUser },
edit: {
title: '编辑用户',
api: saveUser,
fetchInitialData: async (row) => {
const res = await getUserDetail(row.id)
return res.data
}
}
})
</script>可按需查阅 ProForm 表单、字段配置、上传配置。