ElementPlus 用Promise.all同时校验多个表单

305 阅读1分钟

业务场景碰到不同的Tab展示不同的表单,最后点击提交的时候,一起校验。

先看下表单的template
 <!-- 基础信息-->
  <el-form
    ref="ruleFormRef"
    :model="ruleForm"
    :rules="rules"
    label-width="120px"
    class="demo-ruleForm mt-20"
    :size="formSize"
    status-icon
    v-show="selectedTab == '基础信息'"
  >
    <el-form-item label="所属层级" prop="dwplId">
      <el-select
        v-model="ruleForm.dwplId"
        placeholder="请选择"
        @change="onLevelChange"
        class="w-full"
      >
        <el-option
          v-for="item in levelArr[0]?.childr"
          :key="item.id"
          :label="item.levelName"
          :value="item.id"
        />
      </el-select>
    </el-form-item>
    <el-form-item label="数据库" prop="databases">
      <el-select
        v-model="ruleForm.databases"
        placeholder="请选择"
        class="w-full"
        :disabled="!ruleForm.dwplId"
      >
        <el-option
          v-for="item in dataBaseList"
          :key="item"
          :label="item"
          :value="item"
        />
      </el-select>
    </el-form-item>
    <el-form-item label="主题域" prop="subject">
      <el-select v-model="ruleForm.subject" placeholder="请选择" class="w-full">
        <el-option
          v-for="item in subjectList"
          :key="item.id"
          :label="item.subjectName"
          :value="item.subjectName"
        />
      </el-select>
    </el-form-item>
    <el-form-item label="表英文名" prop="tableName">
      <el-input v-model="ruleForm.tableName" />
    </el-form-item>
    <el-form-item label="描述" prop="remark">
      <el-input v-model="ruleForm.remark" type="textarea" />
    </el-form-item>
    <!-- <el-form-item>
      <el-button type="primary" @click="submitForm(ruleFormRef)">
        Create
      </el-button>
      <el-button @click="resetForm(ruleFormRef)">Reset</el-button>
    </el-form-item> -->
  </el-form>
  <!-- 字段信息表单 这个一个动态表单 用户可以增删表单字段 -->
  <el-form
    ref="formRef2"
    :model="form2"
    :rules="rules2"
    label-width="150px"
    class="mt-20"
    v-show="selectedTab == '字段信息'"
    label-position="top"
  >
    <el-row v-for="(item, index) in form2.fields" :key="index" :gutter="20">
      <el-col :span="6">
        <el-form-item
          label="列名"
          :prop="`fields[${index}].name`"
          :rules="rules2.name"
        >
          <el-tooltip
            placement="top"
            effect="dark"
            content="只能输入字母、数字、下划线,不超过50个字符"
          >
            <el-input
              v-model.trim="item.name"
              clearable
              maxlength="50"
              placeholder="请输入"
            >
            </el-input>
          </el-tooltip>
        </el-form-item>
      </el-col>
      <el-col :span="6">
        <el-form-item
          label="类型"
          :prop="`fields[${index}].type`"
          :rules="rules2.type"
        >
          <el-select
            v-model="item.type"
            placeholder="请选择"
            style="width: 100%"
            clearable
          >
            <el-option
              v-for="item in typeList"
              :key="item"
              :label="item"
              :value="item"
            />
          </el-select>
        </el-form-item>
      </el-col>
      <el-col :span="6">
        <el-form-item label="描述" :prop="`fields[${index}].remark`">
          <el-tooltip
            placement="top"
            effect="dark"
            content="列名的中文描述,不超过50个字符"
          >
            <el-input
              v-model.trim="item.remark"
              clearable
              maxlength="50"
              placeholder="请输入"
            >
            </el-input>
          </el-tooltip>
        </el-form-item>
      </el-col>
      <el-col :span="6">
        <el-form-item label="操作">
          <div class="opera u-f u-f-ac">
            <i-ep-top
              class="icon mr-15 cursor-pointer"
              style="font-size: 17px"
              :class="{ disable: index === 0 }"
              @click="handleMoveUp(index)"
            />
            <i-ep-bottom
              class="icon mr-15 cursor-pointer"
              :class="{ disable: index === form2.fields.length - 1 }"
              @click="handleDown(index)"
            />
            <i-ep-delete
              class="icon delete cursor-pointer"
              @click="handleDeleteSub(index)"
            />
          </div>
        </el-form-item>
      </el-col>
    </el-row>
    <el-form-item>
      <el-button type="primary" @click="handleAddSubject">添加</el-button>
    </el-form-item>
  </el-form>

  <!-- 高级信息 -->
  <el-form
    ref="ruleFormRef3"
    :model="ruleForm3"
    :rules="rules3"
    label-width="120px"
    class="demo-ruleForm mt-20"
    :size="formSize"
    status-icon
    v-show="selectedTab == '高级信息'"
  >
    <el-form-item label="存储格式" prop="saveFormat">
      <el-select v-model="ruleForm3.saveFormat" placeholder="请选择">
        <el-option
          v-for="item in saveFormatList"
          :key="item"
          :label="item"
          :value="item"
        />
      </el-select>
    </el-form-item>
    <el-form-item label="存储类型" prop="saveType">
      <el-select v-model="ruleForm3.saveType" placeholder="请选择">
        <el-option
          v-for="item in saveTypeList"
          :key="item"
          :label="item"
          :value="item"
        />
      </el-select>
    </el-form-item>
    <el-form-item label="列分割符" prop="fieldCharacter">
      <el-tooltip
        placement="top"
        effect="dark"
        content="用来对数据的字段进行分割,必须和原表列分隔符一致,否则数据接入失败"
      >
        <el-select v-model="ruleForm3.fieldCharacter" placeholder="请选择">
          <el-option
            v-for="item in separatorList"
            :key="item"
            :label="item"
            :value="item"
          />
        </el-select>
      </el-tooltip>
    </el-form-item>
    <el-form-item label="列转义字符" prop="escapeCharacter">
      <el-tooltip
        placement="top"
        effect="dark"
        content="过滤字段中的特殊符号。用户自定义符号,默认值为空"
      >
        <el-input v-model="ruleForm3.escapeCharacter" />
      </el-tooltip>
    </el-form-item>
    <el-form-item label="collection分割符" prop="collectionCharacter">
      <el-input v-model="ruleForm3.collectionCharacter" type="textarea" />
    </el-form-item>
    <el-form-item label="map-kv分割符" prop="kvCharacter">
      <el-input v-model="ruleForm3.kvCharacter" type="textarea" />
    </el-form-item>
  </el-form>
看下表单定义的校验规则
// 表单1
const rules = reactive<FormRules<RuleForm>>({
dwplId: [{ required: true, message: '请选择层级', trigger: 'change' }],
databases: [
  {
    required: true,
    message: '请选择数据库',
    trigger: 'change',
  },
],
subject: [
  {
    required: true,
    message: '请选择主题',
    trigger: 'change',
  },
],
tableName: [
  {
    required: true,
    message: '请输入表名',
    trigger: 'blur',
  },
],
remark: [{ required: false, message: '请输入描述', trigger: 'blur' }],
})

// 表单2
const form2 = reactive({
fields: [
  {
    name: '',
    type: '',
    remark: '',
    isDel: 0,
    sort: 1,
  },
],
})
const rules2 = reactive({
name: [
  { required: true, message: '列名不能为空', trigger: 'blur' },
  { validator: noSpecial, trigger: 'blur' },
],
type: [{ required: true, message: '类型不能为空', trigger: 'change' }],
})
通过Promise.all来校验多个表单
const handleSubmit = async () => {
  try {
    // 校验基础信息
    const validateBasic = async () => {
      return new Promise((resolve, reject) => {
        ruleFormRef.value?.validate(valid => {
          if (valid) {
            console.log('success1')
            resolve(true) // Resolve with true if validation succeeds
          } else {
            console.log('failures1')
            reject(false) // Reject with false if validation fails
          }
        })
      })
    }

    // 字段信息
    const validateColumn = () => {
      return new Promise((resolve, reject) => {
        formRef2.value?.validate(valid => {
          if (valid) {
            console.log('success2')
            resolve(true)
          } else {
            console.log('failures2')
            reject(false)
          }
        })
      })
    }

    return Promise.all([validateBasic(), validateColumn()])
      .then(async ([basicValid, columnValid]) => {
      // 校验通过 调用接口保存表单数据
        if (basicValid && columnValid) {
          let params: any = {
            projectId: commonStore.currentProject.id,
            base: ruleForm.value,
            fields: form2.fields,
            conf: ruleForm3.value,
          }
          if (props.row) {
            params.id = props.row.id
          }
          await fetchTableManagementUpdate(params)
          console.log('Both forms are validated successfully')
          return Promise.resolve()
        } else {
          console.log('One or both validations failed.')
          return Promise.reject('表单验证失败')
        }
      })
      .catch(error => {
        console.error('Error occurred111111:', error)
        return Promise.reject('表单验证失败')
      })

    // Do something if both forms are valid
  } catch (error) {
    console.log('Error during form validation:', error.message)
    // Handle validation errors
  }
}

// 父组件调用
const handleSubmit = () => {
  editRef.value?.handleSubmit().then(() => {
    showEdit.value = false
    proxy?.$message({
      message: '操作成功',
      duration: 1000,
      type: 'success',
    })
    handleSearch()
  })
}

image.png 由于validate()返回一个Promise,所以用new Promise((resolve, reject)在里面校验

image.png