Skip to content

Form 表单

表单组 ElPlusFormGroup

开发过程中,会遇到一个表单被分为很多块的情况,此时就需要用到表单组。表单组的配置大致与 formConfig 一致。

代码
vue
<ElPlusFormGroup v-model="formGroupData" :formGroup="formGroupConfig" />

<script lang="ts" setup>
import { ref, reactive } from 'vue'

let formGroupData = reactive({} as any)
const formGroupConfig = ref({
  column: 2,
  beforeRequest: (formData: any) => {
    console.log('当前表单数据为:', formData)
    if (formData.online.indexOf(3) < 0) {
      ElMessage.warning('上架平台必须包含 拼多多,请重新选择!')
      return false
    }
    // 设置其他属性
    formData.xxx = 'xxx'
    return formData
  },
  requestFn: (postData: any) => {
    return new Promise((resolve) => {
      // 模拟数据异步提交
      setTimeout(() => {
        console.log('数据已成功保存: ', postData)
        resolve({ code: 200, msg: 'success' })
      }, 1000)
    })
  },
  success: ({ response, callBack }: IFormBack) => {
    console.log('请求结果: ', response)
    ElMessage.success('保存成功~')
    callBack()
  },
  group: [
    {
      title: '基本信息',
      column: 2,
      formDesc: {
        name: { type: 'input', label: '商品名称', maxlength: 30, required: true, colspan: 2 },
        price: { type: 'number', label: '商品价格', required: true, precision: 2, tip: '元' },
        type: { type: 'cascader', label: '商品类型', options: 'goodsTypeList', required: true },
        expiration: { type: 'select', label: '保质期', required: true, options: 'expirationOptions' }
      } as IFormDesc
    },
    {
      title: '价格库存信息',
      column: 2,
      formDesc: {
        stock: { type: 'number', label: '商品库存', required: true, tip: '件' },
        storeTime: { type: 'date', label: '入库时间', required: true },
        taxRate: { type: 'select', label: '税率', default: 0.05, required: true, options: 'taxRateOptions' }
      } as IFormDesc
    },
    {
      title: '活动信息',
      column: 2,
      formDesc: {
        online: { type: 'checkbox', label: '上架平台', required: true, options: 'onLineOptions', colspan: 4 },
        sellType: { type: 'radio', label: '折扣类型', required: true, options: 'sellTypeOptions', colspan: 2 },
        activeTime: { type: 'daterange', label: '活动时间', required: true }
      } as IFormDesc
    },
    {
      title: '商品图文信息',
      column: 2,
      formDesc: {
        imageList: { type: 'upload', label: '商品图片', limit: 9, required: true, multiple: true, colspan: 2 },
        fileList: { type: 'upload', upType: 'file', label: '商品附件', multiple: true, colspan: 2, required: true }
      } as IFormDesc
    },
    {
      title: '其他信息',
      column: 2,
      formDesc: {
        enabled: { type: 'switch', label: '启用状态', default: 1, required: true },
        remark: { type: 'textarea', label: '备注', colspan: 2 }
      } as IFormDesc
    }
  ]
} as IFormGroupConfig)
</script>
<ElPlusFormGroup v-model="formGroupData" :formGroup="formGroupConfig" />

<script lang="ts" setup>
import { ref, reactive } from 'vue'

let formGroupData = reactive({} as any)
const formGroupConfig = ref({
  column: 2,
  beforeRequest: (formData: any) => {
    console.log('当前表单数据为:', formData)
    if (formData.online.indexOf(3) < 0) {
      ElMessage.warning('上架平台必须包含 拼多多,请重新选择!')
      return false
    }
    // 设置其他属性
    formData.xxx = 'xxx'
    return formData
  },
  requestFn: (postData: any) => {
    return new Promise((resolve) => {
      // 模拟数据异步提交
      setTimeout(() => {
        console.log('数据已成功保存: ', postData)
        resolve({ code: 200, msg: 'success' })
      }, 1000)
    })
  },
  success: ({ response, callBack }: IFormBack) => {
    console.log('请求结果: ', response)
    ElMessage.success('保存成功~')
    callBack()
  },
  group: [
    {
      title: '基本信息',
      column: 2,
      formDesc: {
        name: { type: 'input', label: '商品名称', maxlength: 30, required: true, colspan: 2 },
        price: { type: 'number', label: '商品价格', required: true, precision: 2, tip: '元' },
        type: { type: 'cascader', label: '商品类型', options: 'goodsTypeList', required: true },
        expiration: { type: 'select', label: '保质期', required: true, options: 'expirationOptions' }
      } as IFormDesc
    },
    {
      title: '价格库存信息',
      column: 2,
      formDesc: {
        stock: { type: 'number', label: '商品库存', required: true, tip: '件' },
        storeTime: { type: 'date', label: '入库时间', required: true },
        taxRate: { type: 'select', label: '税率', default: 0.05, required: true, options: 'taxRateOptions' }
      } as IFormDesc
    },
    {
      title: '活动信息',
      column: 2,
      formDesc: {
        online: { type: 'checkbox', label: '上架平台', required: true, options: 'onLineOptions', colspan: 4 },
        sellType: { type: 'radio', label: '折扣类型', required: true, options: 'sellTypeOptions', colspan: 2 },
        activeTime: { type: 'daterange', label: '活动时间', required: true }
      } as IFormDesc
    },
    {
      title: '商品图文信息',
      column: 2,
      formDesc: {
        imageList: { type: 'upload', label: '商品图片', limit: 9, required: true, multiple: true, colspan: 2 },
        fileList: { type: 'upload', upType: 'file', label: '商品附件', multiple: true, colspan: 2, required: true }
      } as IFormDesc
    },
    {
      title: '其他信息',
      column: 2,
      formDesc: {
        enabled: { type: 'switch', label: '启用状态', default: 1, required: true },
        remark: { type: 'textarea', label: '备注', colspan: 2 }
      } as IFormDesc
    }
  ]
} as IFormGroupConfig)
</script>

动态组 & 插槽

单个 group 对象也支持动态 vif: boolean | () => boolean 。如果仅仅表单不满足你的需求时,可以使用插槽进行扩展。目前可使用的插槽分别为 titleX / topXdefaultX (其中 X 表示表单组所在的下标,以 0 开始)。注:本例子使用的 ElPlusTable 组件,是 CRUD 中另一个核心组件。

代码
html
<ElPlusFormGroup v-model="formGroupData2" :formGroup="formGroupConfig2">
  <template #top0>
    <div style="border: 1px solid var(--vp-c-brand); margin-bottom: 12px; padding: 12px;">这里是第1组表单的 top 插槽</div>
  </template>
  <template #title1>
    <div class="title-line">
      这里是第2组表单的 title 插槽
      <span style="color: var(--vp-c-primary)">(修改 是否入库 可动态显示和隐藏)</span>
    </div>
  </template>
  <template #default2>
    <div style="margin-bottom: 12px; border-radius: 4px; border: 1px solid var(--el-color-info-light-3); padding: 20px;">
      活动列表(这里是第3组表单的 default 插槽)
      <ElPlusTable v-model="tableData" :tableConfig="tableConfig" :isPager="false"></ElPlusTable>
    </div>
  </template>
</ElPlusFormGroup>

<script lang="ts" setup>
  import { ref, reactive } from 'vue'

  let formGroupData2 = reactive({} as any)
  const formGroupConfig2 = ref({
    column: 2,
    group: [
      {
        title: '基本信息',
        column: 2,
        formDesc: {
          name: { type: 'input', label: '商品名称', maxlength: 30, required: true, colspan: 2 },
          isStore: { type: 'switch', label: '是否入库', default: 1, required: true }
        } as IFormDesc
      },
      {
        title: '价格库存信息',
        column: 2,
        vif: () => formGroupData2.isStore,
        formDesc: {
          stock: { type: 'number', label: '商品库存', required: true, tip: '件' },
          storeTime: { type: 'date', label: '入库时间', required: true },
          taxRate: { type: 'select', label: '税率', default: 0.05, required: true, options: 'taxRateOptions' }
        } as IFormDesc
      },
      {
        title: '活动信息',
        column: 2,
        formDesc: {
          online: { type: 'checkbox', label: '上架平台', required: true, options: 'onLineOptions', colspan: 4 },
          sellType: { type: 'radio', label: '折扣类型', required: true, options: 'sellTypeOptions', colspan: 2 },
          activeTime: { type: 'daterange', label: '活动时间', required: true }
        } as IFormDesc
      },
      {
        title: '其他信息',
        column: 2,
        formDesc: {
          enabled: { type: 'switch', label: '启用状态', default: 1, required: true },
          remark: { type: 'textarea', label: '备注', colspan: 2 }
        } as IFormDesc
      }
    ]
  } as IFormGroupConfig)

  let tableData = reactive([
    { name: '国庆中秋大促', startTime: '2023-09-25', endTime: '2023-10-10', createBy: 'admin', createTime: '2023-09-20' },
    { name: '双11抢购', startTime: '2023-11-01', endTime: '2023-11-30', createBy: 'admin', createTime: '2023-10-20' }
  ] as any[])
  const tableConfig = ref({
    column: [
      { prop: 'name', label: '活动名称' },
      { prop: 'startTime', label: '开始时间' },
      { prop: 'endTime', label: '结束时间' },
      { prop: 'createBy', label: '创建人' },
      { prop: 'createTime', label: '创建时间' }
    ]
  } as ITableConfig)
</script>
<ElPlusFormGroup v-model="formGroupData2" :formGroup="formGroupConfig2">
  <template #top0>
    <div style="border: 1px solid var(--vp-c-brand); margin-bottom: 12px; padding: 12px;">这里是第1组表单的 top 插槽</div>
  </template>
  <template #title1>
    <div class="title-line">
      这里是第2组表单的 title 插槽
      <span style="color: var(--vp-c-primary)">(修改 是否入库 可动态显示和隐藏)</span>
    </div>
  </template>
  <template #default2>
    <div style="margin-bottom: 12px; border-radius: 4px; border: 1px solid var(--el-color-info-light-3); padding: 20px;">
      活动列表(这里是第3组表单的 default 插槽)
      <ElPlusTable v-model="tableData" :tableConfig="tableConfig" :isPager="false"></ElPlusTable>
    </div>
  </template>
</ElPlusFormGroup>

<script lang="ts" setup>
  import { ref, reactive } from 'vue'

  let formGroupData2 = reactive({} as any)
  const formGroupConfig2 = ref({
    column: 2,
    group: [
      {
        title: '基本信息',
        column: 2,
        formDesc: {
          name: { type: 'input', label: '商品名称', maxlength: 30, required: true, colspan: 2 },
          isStore: { type: 'switch', label: '是否入库', default: 1, required: true }
        } as IFormDesc
      },
      {
        title: '价格库存信息',
        column: 2,
        vif: () => formGroupData2.isStore,
        formDesc: {
          stock: { type: 'number', label: '商品库存', required: true, tip: '件' },
          storeTime: { type: 'date', label: '入库时间', required: true },
          taxRate: { type: 'select', label: '税率', default: 0.05, required: true, options: 'taxRateOptions' }
        } as IFormDesc
      },
      {
        title: '活动信息',
        column: 2,
        formDesc: {
          online: { type: 'checkbox', label: '上架平台', required: true, options: 'onLineOptions', colspan: 4 },
          sellType: { type: 'radio', label: '折扣类型', required: true, options: 'sellTypeOptions', colspan: 2 },
          activeTime: { type: 'daterange', label: '活动时间', required: true }
        } as IFormDesc
      },
      {
        title: '其他信息',
        column: 2,
        formDesc: {
          enabled: { type: 'switch', label: '启用状态', default: 1, required: true },
          remark: { type: 'textarea', label: '备注', colspan: 2 }
        } as IFormDesc
      }
    ]
  } as IFormGroupConfig)

  let tableData = reactive([
    { name: '国庆中秋大促', startTime: '2023-09-25', endTime: '2023-10-10', createBy: 'admin', createTime: '2023-09-20' },
    { name: '双11抢购', startTime: '2023-11-01', endTime: '2023-11-30', createBy: 'admin', createTime: '2023-10-20' }
  ] as any[])
  const tableConfig = ref({
    column: [
      { prop: 'name', label: '活动名称' },
      { prop: 'startTime', label: '开始时间' },
      { prop: 'endTime', label: '结束时间' },
      { prop: 'createBy', label: '创建人' },
      { prop: 'createTime', label: '创建时间' }
    ]
  } as ITableConfig)
</script>