Skip to content

表单弹层配置(formConfig) ​

ProTable 通过 form-config prop 接收表单配置,自动管理新增 / 编辑 / 复制弹层。本页说明 formConfig 的完整配置项以及 add / edit / save / copy 各场景的行为差异。

如需独立使用表单(不与 ProTable 联动),见 ProForm 表单。

基本用法 ​

vue
<template>
  <pro-table
    :search-config="searchConfig"
    :table-config="tableConfig"
    :form-config="formConfig"
  />
</template>

<script setup>
const formConfig = reactive({
  mode: 'dialog',
  width: '500px',
  model: { name: '', status: 1 },
  fields: [
    { label: '姓名', key: 'name', component: 'input' },
    { label: '状态', key: 'status', component: 'select',
      options: [{ label: '启用', value: 1 }, { label: '禁用', value: 0 }] }
  ],
  rules: {
    name: [{ required: true, message: '请输入姓名', trigger: 'blur' }]
  },
  add: {
    title: '新增用户',
    api: createUser
  },
  edit: {
    title: '编辑用户',
    api: updateUser
  }
})
</script>

formConfig 完整属性 ​

属性说明类型默认值
mode弹层模式:dialog(弹窗)/ drawer(抽屉)/ page(整页)String'dialog'
width弹窗宽度 / 抽屉宽度String'500px'
model表单初始数据,key 与 fields 的 key 对应Object-
fields表单项配置数组,见 字段配置Array[]
tabs分 tab 展示,见 ProForm tabsArray-
rules表单通用校验规则(add / edit 场景若自身有 rules 则优先用自身的,否则回退到这里;save 场景不回退)Object-
labelWidthlabel 宽度String'100px'
labelPositionlabel 对齐:left / right / topString'left'
formAttrs透传给 el-form 的属性(size、disabled、labelSuffix 等)Object-
span表单项栅格占位(每行 24 格),可在 field 上单独覆盖Number24
formWidth表单内容区宽度,如 '600px'、'80%'String-
uploadConfig上传配置,见 上传配置Object-
readonly表单级只读:true 时所有字段只读;支持 ({ formType, formData }) => booleanBoolean | Functionfalse
params传给 fetchInitialData 的参数(编辑=当前行;复制打开时 params 已去主键)Object{}
fetchInitialData编辑 / 复制打开时请求回填:(params) => Promise<Object>;新增不会调用Function-
openBefore打开表单前钩子:({ type, row, params }) => boolean | Promise<boolean>,返回 false 取消Function-
openAfter打开表单后钩子:({ type, row, params }) => voidFunction-
beforeSubmit提交前钩子:({ formData, action }) => boolean | Promise<boolean>,返回 false 取消Function-
afterSubmit提交成功后回调:{ res, formData, action };res 为 responseFormat 转换后的响应Function-
filterEmptyParams提交前是否过滤空值;设为 true 时过滤 ''、null、undefined、空数组Booleanfalse
closeOnSubmit提交成功后是否关闭弹窗;接口返回失败码或请求抛错时不会关闭Booleantrue
closeOnClickModal点击遮罩是否关闭弹窗Booleantrue
popupAttrs透传给 el-dialog / el-drawer 的额外属性Object-
footer底部按钮区配置,见 Footer 配置Object-
add新增配置,见 add 配置Object-
edit编辑配置,见 edit 配置Object-
save保存配置,见 save 配置Object-

提交流程与钩子职责 ​

提交时会先基于当前表单数据生成参数:日期范围字段会按 startKey / endKey 拆分,title / text 展示字段不会提交,nestedKeys 字段会在提交时展平。

如果配置了 filterEmptyParams: true,会在 paramsFormat 之前过滤 ''、null、undefined 和空数组。默认不启用,避免清空字段时无法把空值提交给后端。

执行顺序:

text
表单校验 → beforeSubmit → 生成提交参数 → filterEmptyParams → add/edit/save.paramsFormat → add/edit/save.api → add/edit/save.responseFormat → afterSubmit → submit/save 事件
  • beforeSubmit 用于提交前拦截、二次确认或业务校验,返回 false 会取消本次提交。
  • paramsFormat 用于转换最终提交参数,例如字段改名、类型转换、补充固定字段。
  • responseFormat 用于转换接口响应,它的返回值会作为 afterSubmit 和 submit/save 事件接收到的响应。
  • afterSubmit 用于提交成功后的副作用,例如刷新外部数据、跳转、记录日志等。

提交失败处理 ​

add.api / edit.api / save.api 返回对象中包含 codeKey 字段时,组件会根据全局 successCode 判断是否成功:

  • String(res[codeKey]) === String(successCode):视为成功,提示 res[messageKey],并按 closeOnSubmit 决定是否关闭弹窗。
  • 不相等:视为失败,提示 res[messageKey] 或 res.message,并且不会关闭弹窗。
  • 接口请求抛错:提示错误信息,并且不会关闭弹窗。
js
app.use(AdminProTable, {
  successCode: 0,
  codeKey: 'code',
  messageKey: 'message'
})

const formConfig = {
  add: {
    api: async (params) => {
      // 返回 { code: 500, message: '题目已存在' } 时会提示错误,弹窗保持打开
      return addQuestion(params)
    }
  }
}

提交参数处理 ​

提交 add.api / edit.api / save.api 前,组件会先对当前表单数据做统一处理:

  • date-range / date-time-range 会按 startKey / endKey 拆成两个字段,并移除原 range 字段。
  • title / text 仅展示字段不会提交。
  • 配置了 nestedKeys 的字段会在提交时展平。
  • 编辑场景会根据 idKey / idValueKey 补上主键字段。
  • paramsFormat 接收到的是上述处理后的参数。

add 配置 ​

用于新增表单提交,点击工具栏"添加"后触发。

属性说明类型默认值
title弹窗 / 抽屉标题String-
api提交接口:(params) => PromiseFunction-
rules新增场景专属校验规则,优先于 formConfig.rulesObject-
paramsFormat提交前格式化参数:(data) => anyFunction-
responseFormat接口返回格式化:(res) => anyFunction-
js
add: {
  title: '新增用户',
  api: createUser,
  rules: {
    name: [{ required: true, message: '请输入姓名', trigger: 'blur' }]
  },
  paramsFormat: (data) => ({
    ...data,
    source: 'admin'
  })
}

add 校验优先级 ​

  • 有 add.rules → 用 add.rules
  • 没有 add.rules → 回退到 formConfig.rules

edit 配置 ​

用于编辑表单提交,点击操作列"编辑"后触发。

属性说明类型默认值
title弹窗 / 抽屉标题String-
api提交接口:(params) => PromiseFunction-
rules编辑场景专属校验规则,优先于 formConfig.rulesObject-
idKey提交给后端的主键字段名String'id'
idValueKey当前表单数据中取主键值的字段名String'id'
paramsFormat提交前格式化参数:(data) => anyFunction-
responseFormat接口返回格式化:(res) => anyFunction-
js
edit: {
  title: '编辑用户',
  api: updateUser,
  idKey: 'userId',
  idValueKey: 'id',
  rules: {
    status: [{ required: true, message: '请选择状态', trigger: 'change' }]
  }
}

edit 校验优先级 ​

  • 有 edit.rules → 用 edit.rules
  • 没有 edit.rules → 回退到 formConfig.rules

edit / copy 回显优先级 ​

点击操作列「编辑」或「复制」时:

  • 配置了顶层 formConfig.fetchInitialData:调用 fetchInitialData 请求详情并回显。
    • 编辑:传入当前行(含主键)
    • 复制:传入原始行(含主键)请求详情,回填前自动去掉主键字段
  • 未配置顶层 formConfig.fetchInitialData:直接使用当前行数据回显(复制场景会去掉主键)
  • 新增不会调用 fetchInitialData(无 id,避免详情接口报错)

edit 中不需要配置 fetchInitialData;详情请求统一放在顶层 formConfig.fetchInitialData。


save 配置 ​

用于"保存草稿""临时保存"等场景,点击底部"保存"按钮触发。

需要在 footer 里配置 showSave: true 才会显示保存按钮。

属性说明类型默认值
api保存接口:(params) => PromiseFunction-
rules保存场景专属校验规则Object-
paramsFormat提交前格式化参数:(data) => anyFunction-
responseFormat接口返回格式化:(res) => anyFunction-
js
save: {
  api: saveDraft,
  rules: {
    name: [{ required: true, message: '请输入姓名', trigger: 'blur' }]
  }
}

save 校验优先级 ​

  • 有 save.rules → 只用 save.rules
  • 没有 save.rules → 不校验
  • 不会回退到 formConfig.rules

save 标题说明 ​

save.title 不生效。弹窗 / 抽屉标题只看 formConfig.title、add.title、edit.title。

显示保存按钮 ​

js
formConfig: {
  footer: { showSave: true, saveText: '保存草稿' },
  save: { api: saveDraft }
}

copy 场景 ​

点击操作列"复制"时,组件内部以 copy 类型打开表单,但提交逻辑走新增:

  • 提交接口走 add.api
  • 校验规则走 add.rules
  • 标题走 add.title
  • 表单数据预填当前行数据(去除主键)

需在 operationConfig 里开启复制按钮:

js
tableConfig: {
  operationConfig: { showCopy: true }
}

标题优先级 ​

弹窗 / 抽屉 / page 模式下的标题取值:

  1. formConfig.title(如果配了,所有场景统一使用)
  2. 当前为新增 / 复制时:add.title
  3. 当前为编辑时:edit.title
  4. 未配置以上标题时,新增 / 复制默认显示 新增,编辑默认显示 编辑

save.title 不参与标题计算。


底部按钮区域配置。

属性说明类型默认值
show是否显示底部区域Booleantrue
showCancel是否显示取消按钮Booleantrue
showSubmit是否显示提交按钮Booleantrue
showSave是否显示保存按钮(需配合 save.api)Booleanfalse
cancelText取消按钮文案String'取消'
submitText提交按钮文案String'提交'
saveText保存按钮文案String'保存'
align按钮对齐方式:left / center / right;page 模式默认 'left',dialog/drawer 默认 'right'String见说明
js
footer: {
  show: true,
  showCancel: true,
  showSubmit: true,
  showSave: true,
  cancelText: '取消',
  submitText: '确认提交',
  saveText: '保存草稿',
  align: 'right'
}

与表格联动流程 ​

传入 form-config 后,ProTable 自动管理表单弹层:

  1. 点击工具栏"添加" → 以 add 配置打开新增表单(不会调用 fetchInitialData)
  2. 点击操作列"编辑" → 以 edit 配置打开编辑表单,自动传入当前行数据
  3. 点击操作列"复制" → 以 copy 方式打开,预填当前行(去主键),提交走 add.api
  4. 配置了 formConfig.fetchInitialData → 打开编辑 / 复制弹层会自动请求详情接口并回填
  5. 提交成功后自动刷新列表

表单插槽 ​

表单相关插槽需加 form- 前缀:

vue
<pro-table :table-config="tableConfig" :form-config="formConfig">
  <!-- 自定义表单字段 -->
  <template #form-custom-avatar="{ modelValue, formData }">
    <el-upload v-model="formData.avatar" />
  </template>

  <!-- 表单头部 / 底部 -->
  <template #form-header="{ formData }">
    <el-alert title="提示信息" type="info" />
  </template>
</pro-table>

外部控制表单 ​

通过 ref 可以在外部控制表单的打开、关闭和数据:

js
const tableRef = ref(null)

// 打开新增,可传初始数据
tableRef.value?.openAdd({ type: 'admin' })

// 打开编辑 / 复制
tableRef.value?.openEdit(row)
tableRef.value?.openCopy(row)

// 关闭表单
tableRef.value?.closeForm()

// 读取 / 操作表单数据
const data = tableRef.value?.getFormData()
tableRef.value?.patchFormData({ status: 1 })
await tableRef.value?.validateForm()

更多实例方法见 实例方法与事件。


完整示例 ​

js
const formConfig = reactive({
  mode: 'dialog',
  width: '500px',
  model: { name: '', status: 1, type: 'A', remark: '' },
  fields: [
    { label: '姓名', key: 'name', component: 'input' },
    { 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: 'remark', component: 'textarea', rows: 3, span: 24 }
  ],
  rules: {
    name: [{ required: true, message: '请输入姓名', trigger: 'blur' }]
  },
  add: {
    title: '新增用户',
    api: createUser,
    paramsFormat: (data) => ({ ...data, source: 'web' })
  },
  edit: {
    title: '编辑用户',
    api: updateUser,
    idKey: 'id',
    fetchInitialData: async (row) => {
      const res = await getUserDetail(row.id)
      return res.data
    }
  },
  save: {
    api: saveDraft,
    rules: {}
  },
  footer: {
    showSave: true,
    saveText: '保存草稿',
    submitText: '确认提交',
    align: 'right'
  }
})