【el】表单

文章展示了如何使用ElementUI构建动态表单,包括处理不同类型的表单元素如输入框、下拉框、日期选择器等,以及如何在父组件和子组件之间交互数据,进行表单验证和文件上传。示例中,父组件调用接口获取表单结构并传给子组件渲染,子组件处理表格行的添加、删除,同时包含了上传文件的验证功能。此外,还涉及了多表单共享数据的验证和提交处理。
摘要由CSDN通过智能技术生成
elementUI中的表单相关问题

一、用法

1、动态表单

调用接口返回表单,后端的接口返回值如下:

这些是渲染后的效果

页面使用(父组件)

 <el-button size="small" class="Cancelbtn" @click="sub(true)">发起新的</el-button>

<!-- 弹窗-新的 -->
    <el-dialog
      style="margin-top: -10vh"
      class="newdialogVisible"
      :visible.sync="dialogVisible"
      width="90%"
    >
      <div class="dialog-header">
        {{ BpmName.appname }}
      </div>
      <div class="center">
        <FromHead ref="FromHead" :List="List"></FromHead>
      </div>
      <div class="dialog-footer" align="center">
        <div
          style="display: inline; margin: 0 5px"
          v-for="(obj, j) in List.button"
          :key="j"
        >
          <el-button
            v-if="obj.type === 0"
            size="small"
            class="Cancelbtn"
            @click="sub(true)"
            >{{ obj.name }}</el-button
          >
          <el-button
            v-if="obj.type === 1"
            size="small"
            class="addbtn"
            @click="sub(false)"
            >{{ obj.name }}</el-button
          >
        </div>
      </div>
    </el-dialog>
<script>
import { mapGetters } from "vuex";
import {
  GetHomeData,
  BpmGetList,
  GetFrom,
  GetFromData,
  AddFromData,
} from "@/api/Bpm";
import FromHead from "@/components/FromHead/index.vue";

export default {
  name: "Process",
  computed: {
    ...mapGetters(["userid", "name"]),
  },
  components: { FromHead },
  data() {
    return {
      dialogVisible:false,
      BpmName: {}, //从常用中携带的项目信息
      List: {}, //新的获取动态表单,以及相关信息
      newform: {
        fromid: 1, //表单编号
        node_uuid: "", //当前节点  保存数据时提交使用
        jsondata: "", //动态表单searchList
        sqr_id: 1, //申请人编号
        sqr: "", //申请人姓名
        draft: false, //是否是草稿
      }, //表单提交
      table: [], //表单中的表头
      table1: [], //表单中的表格
      vDisable: false,
    }
   },
   created() {
      const a = JSON.parse(localStorage.getItem("Goprocess"));
      this.BpmName = a;
      this.form.appid = this.BpmName.id;
   },
   methods: {
     add() {
      GetFrom({ appid: this.userid }).then((res) => {
        res.data.dom.forEach((i) => {
           //处理表格
          if (i.type === 7) {
            // 表头
            i.table = i.attr.map((i, j) => {
              return {
                label: i,
                prop: "a" + [j],
              };
            });
            if (i.default_val.length > 0) {
              i.table1 = i.default_val.filter(function (item, index, arr) {
                return index != 0;
              });
            } else {
              i.table1 = [];
            }
          }
        });
        const a = JSON.stringify(res.data);
        this.List = JSON.parse(a);
        // //这是为了表格中表单的验证,如果不需要则删除这两行,并把table和table1传递给组件EditFrom
        // this.List.table = this.table; //<EditFrom v-else style="width: 69vw" :List="editForm" :table="table" :table1="table1"></EditFrom>
        // this.List.table1 = this.table1; //把组件中表格的验证给去除掉
        console.log(this.List, "新建表单");
        localStorage.setItem("formList", JSON.stringify(this.List)); //为了离开弹窗时,检查是否有所改变
        this.dialogVisible = true;
      });
    },
   } 
}
</script>

封装动态表单(子组件)

我没有把按钮封装在这里面,因为按钮是需要在父组件中的
<template>
  <div id="SearchHead">
    <el-form
      :inline="true"
      style="width: 100%; height: 100%"
      ref="FromHead"
      :model="List"
      label-width="200px"
      label-position="top"
    >
      <div
        style="display: flex; flex-wrap: wrap; justify-content: space-between"
      >
        <div
          :style="{
            width:
              item.type === 7 || item.type === 8 || item.type === 11
                ? '100%'
                : '49%',
          }"
          v-for="(item, index) in List.dom"
          :key="index"
        >
          <el-form-item
            v-if="item.type === 0"
            :label="item.name"
            :prop="'dom.' + index + '.default_val'"
            :rules="item.required ? item.required : { required: false }"
          >
            <el-input
              v-model="item.default_val"
              placeholder="请输入"
            ></el-input>
          </el-form-item>
          <el-form-item
            v-if="item.type === 1"
            :label="item.name"
            :prop="'dom.' + index + '.default_val'"
            :rules="item.required ? item.required : { required: false }"
          >
            <el-input-number
              v-model="item.default_val"
              placeholder="请输入"
            ></el-input-number>
          </el-form-item>
          <el-form-item
            v-if="item.type === 2"
            :label="item.name"
            :prop="'dom.' + index + '.default_val'"
            :rules="item.required ? item.required : { required: false }"
          >
            <el-select v-model="item.default_val" placeholder="请选择">
              <el-option
                v-for="(i, ind) in item.attr"
                :key="ind"
                :label="i"
                :value="i"
              >
              </el-option>
            </el-select>
          </el-form-item>
          <el-form-item
            v-if="item.type === 3"
            :label="item.name"
            :prop="'dom.' + index + '.default_val'"
            :rules="item.required ? item.required : { required: item.required }"
          >
            <el-date-picker
              v-model="item.default_val"
              type="date"
              placeholder="选择日期"
              format="yyyy-MM-dd"
            >
            </el-date-picker>
          </el-form-item>
          <el-form-item
            v-if="item.type === 4"
            :label="item.name"
            :prop="'dom.' + index + '.default_val'"
            :rules="item.required ? item.required : { required: false }"
          >
            <el-date-picker
              v-model="item.default_val"
              type="datetime"
              placeholder="选择日期时间"
            >
            </el-date-picker>
          </el-form-item>
          <el-form-item
            v-if="item.type === 5"
            :label="item.name"
            :prop="'dom.' + index + '.default_val'"
            :rules="item.required ? item.required : { required: false }"
          >
            <el-radio-group v-model="item.default_val">
              <el-radio :label="ii" v-for="ii in item.attr" :key="ii">{{
                ii
              }}</el-radio>
            </el-radio-group>
          </el-form-item>
          <el-form-item
            v-if="item.type === 6"
            :label="item.name"
            :prop="'dom.' + index + '.default_val'"
            :rules="
              item.required
                ? {
                    required: item.required.required,
                    message: item.required.message,
                    trigger: 'blur',
                  }
                : { required: false }
            "
          >
            <el-checkbox-group v-model="item.default_val">
              <el-checkbox
                :label="jj"
                v-for="jj in item.attr"
                :key="jj"
              ></el-checkbox>
            </el-checkbox-group>
          </el-form-item>
          <el-form-item
            v-if="item.type == 8"
            :label="item.name"
            :prop="'dom.' + index + '.default_val'"
            :rules="[
              item.required
                ? {
                    required: item.required.required,
                    message: item.required.message,
                    trigger: 'change',
                  }
                : { required: false },
            ]"
          >
            <el-upload
              class="upload-demo"
              action="#"
              ref="upload"
              multiple
              :file-list="item.attr"
              :on-change="
                (file, fileList) => {
                  change(file, fileList, index);
                }
              "
              :auto-upload="false"
              :http-request="httprequest"
              :on-remove="remove"
              accept=".xlsx,.xls,.jpg,.jpeg,.gif,.png,.pdf,.doc,.docx"
            >
              <el-button
                slot="trigger"
                icon="el-icon-upload2"
                style="width: 100%; text-align: left"
                size="small"
                class="dashedbtn"
                >上传文件</el-button
              >
            </el-upload>
          </el-form-item>
          <el-form-item
            v-if="item.type === 9"
            :label="item.name"
            :prop="'dom.' + index + '.default_val'"
            :rules="item.required ? item.required : { required: false }"
          >
            <el-select
              filterable
              v-model="item.default_val"
              placeholder="请选择"
            >
              <el-option
                v-for="(i, ind) in item.attr"
                :key="ind"
                :label="i.name"
                :value="i.name"
              >
              </el-option>
            </el-select>
          </el-form-item>
          <el-form-item v-if="item.type == 7" :label="item.name">
            <el-button size="small" @click="addtable(item)" class="addbtn"
              >添加行</el-button
            >
            <el-button size="small" @click="deletetable(item)" class="Cancelbtn"
              >删除</el-button
            >
            <el-table
              :ref="'table' + index"
              :data="item.table1"
              border
              style="width: 100%; margin-top: 1%"
              :header-cell-style="{
                padding: '0',
              }"
              @selection-change="handleSelectionChange"
            >
              <el-table-column type="selection" width="45" align="center">
              </el-table-column>
              <el-table-column
                type="index"
                label="序号"
                width="50"
                align="center"
              >
              </el-table-column>
              <el-table-column
                v-for="(i, index) in item.table"
                :key="i.label"
                :prop="i.prop"
                align="center"
                :label="i.label"
              >
                <template slot-scope="scope">
                  <!-- <div v-if="scope.row[index] instanceof Object ? true : false"> -->
                  <el-input
                    size="small"
                    v-if="scope.row[index].type === 0"
                    v-model="scope.row[index].default_val"
                    placeholder="请输入"
                  ></el-input>
                  <el-input-number
                    size="small"
                    v-if="scope.row[index].type === 1"
                    v-model="scope.row[index].default_val"
                    placeholder="请输入"
                  ></el-input-number>
                  <el-select
                    size="small"
                    v-if="scope.row[index].type === 2"
                    v-model="scope.row[index].default_val"
                    placeholder="请选择"
                  >
                    <el-option
                      v-for="(i, ind) in scope.row[index].attr"
                      :key="ind"
                      :label="i"
                      :value="i"
                    >
                    </el-option>
                  </el-select>
                  <el-date-picker
                    size="small"
                    v-if="scope.row[index].type === 3"
                    v-model="scope.row[index].default_val"
                    type="date"
                    placeholder="选择日期"
                    format="yyyy-MM-dd"
                  >
                  </el-date-picker>
                  <el-date-picker
                    size="small"
                    v-if="scope.row[index].type === 4"
                    v-model="scope.row[index].default_val"
                    type="datetime"
                    placeholder="选择日期时间"
                  >
                  </el-date-picker>
                  <el-radio-group
                    v-if="scope.row[index].type === 5"
                    v-model="scope.row[index].default_val"
                  >
                    <el-radio
                      :label="ii"
                      v-for="ii in scope.row[index].attr"
                      :key="ii"
                      >{{ ii }}</el-radio
                    >
                  </el-radio-group>
                  <el-checkbox-group
                    v-if="scope.row[index].type === 6"
                    v-model="scope.row[index].default_val"
                  >
                    <el-checkbox
                      :label="jj"
                      v-for="jj in scope.row[index].attr"
                      :key="jj"
                    ></el-checkbox>
                  </el-checkbox-group>
                  <el-upload
                    v-if="scope.row[index].type === 8"
                    action="#"
                    :class="{
                      hide: scope.row[index].attr.length === 1 ? true : false,
                    }"
                    name="file_name"
                    :http-request="
                      (file, fileList) =>
                        http(file, fileList, scope.row, 'wenjian', index)
                    "
                    :limit="1"
                    :show-file-list="true"
                    :file-list="scope.row[index].attr"
                    :on-change="
                      (file, fileList) =>
                        handlechange(
                          file,
                          fileList,
                          scope.row,
                          'wenjian',
                          index
                        )
                    "
                    :on-remove="
                      (file, fileList) =>
                        Remove(file, fileList, scope.row, 'wenjian', index)
                    "
                  >
                    <el-button
                      :class="{
                        hide: scope.row[index].attr.length === 1 ? true : false,
                      }"
                      icon="el-icon-upload2"
                      style="width: 100%; text-align: left"
                      size="small"
                      class="dashedbtn"
                      >上传文件</el-button
                    >
                  </el-upload>
                  <el-select
                    size="small"
                    filterable
                    v-if="scope.row[index].type === 9"
                    v-model="scope.row[index].default_val"
                    placeholder="请选择"
                  >
                    <el-option
                      v-for="(i, ind) in scope.row[index].attr"
                      :key="ind"
                      :label="i.name"
                      :value="i.name"
                    >
                    </el-option>
                  </el-select>
                  <el-popover
                    append-to-body
                    ref="editPopover"
                    placement="right-end"
                    width="750"
                    trigger="manual"
                    v-model="scope.row[index].show"
                    v-if="scope.row[index].type === 10"
                    :reference="prevTarget"
                    :key="popperFlag"
                  >
                    <div>
                      <el-button
                        size="small"
                        class="addbtn"
                        @click="add(scope.row[index])"
                        >添加行</el-button
                      >
                      <el-button
                        size="small"
                        class="addbtn"
                        @click="sub(scope.row[index])"
                        >保存</el-button
                      >
                      <el-button
                        size="small"
                        class="addbtn"
                        @click="cancel(scope.row[index])"
                        >取消</el-button
                      >
                    </div>
                    <el-table
                      border
                      height="45vh"
                      style="width: 100%; margin-top: 10px"
                      :data="scope.row[index].attr"
                    >
                      <el-table-column
                        align="center"
                        property="date"
                        label="检测标准"
                      >
                        <template slot-scope="sco">
                          <el-select
                            style="width: 100%"
                            filterable
                            v-model="sco.row.standard"
                            multiple
                            placeholder="请选择"
                            @change="changeStandard"
                            value-key="id"
                          >
                            <el-option
                              v-for="item in standardoptions"
                              :key="item.value"
                              :label="item.no"
                              :value="item"
                            >
                            </el-option>
                          </el-select>
                        </template>
                      </el-table-column>
                      <el-table-column
                        align="center"
                        property="name"
                        label="检测项目"
                      >
                        <template slot-scope="sco">
                          <el-select
                            style="width: 100%"
                            filterable
                            v-model="sco.row.item"
                            multiple
                            placeholder="请选择"
                            @focus="onfocus(sco.row)"
                          >
                            <el-option
                              v-for="item in itemoptions"
                              :key="item.id"
                              :label="
                                item.name + '(' + item.projecttypename + ')'
                              "
                              :value="
                                item.name + '(' + item.projecttypename + ')'
                              "
                            >
                            </el-option>
                          </el-select>
                        </template>
                      </el-table-column>
                      <el-table-column
                        width="60"
                        property="name"
                        label="操作"
                        align="center"
                      >
                        <template slot-scope="sco">
                          <el-button
                            type="text"
                            @click="del(scope.row[index].attr, sco.$index)"
                            >删除</el-button
                          >
                        </template>
                      </el-table-column>
                    </el-table>
                    <el-button
                      type="text"
                      slot="reference"
                      @click="showPopover(scope.row[index], $event, scope.row)"
                      >{{
                        scope.row[index].btn ? scope.row[index].btn : "选择"
                      }}</el-button
                    >
                  </el-popover>
                  <!-- </div>
                  <div v-else>
                    <el-input
                      size="small"
                      v-model="scope.row[index]"
                      placeholder="请输入"
                    ></el-input>
                  </div> -->
                </template>
              </el-table-column>
            </el-table>
          </el-form-item>
          <el-form-item v-if="item.type == 11" :label="item.name">
            <el-button size="small" @click="ad(item)" class="addbtn"
              >添加行</el-button
            >
            <el-button size="small" @click="dele(item)" class="Cancelbtn"
              >删除</el-button
            >
            <el-table
              :ref="'table' + index"
              :data="item.table1"
              border
              :span-method="objectSpanMethod"
              style="width: 100%; margin-top: 1%"
              :header-cell-style="{
                padding: '0',
              }"
              @selection-change="handle"
            >
              <el-table-column type="selection" width="45" align="center">
              </el-table-column>
              <el-table-column
                v-for="i in item.table"
                :key="i.label"
                :prop="i.prop"
                align="center"
                :label="i.label"
              >
                <template slot-scope="scope">
                  {{ scope.row[i.prop] }}
                </template>
              </el-table-column>
              <el-table-column
                type="index"
                label="操作"
                width="120"
                align="center"
              >
                <template slot-scope="scope">
                  <el-button
                    size="small"
                    @click="edit(scope.row, scope.$index, item)"
                    class="addbtn"
                    >编辑</el-button
                  >
                </template>
              </el-table-column>
            </el-table>
          </el-form-item>
          <!-- <el-form-item v-if="item.type == 7" :label="item.name">
            <el-button size="small" @click="addtable(item)" class="addbtn"
              >添加行</el-button
            >
            <el-button size="small" @click="deletetable(item)" class="Cancelbtn"
              >删除</el-button
            >
            <el-table
              ref="table"
              :data="item.table1"
              border
              style="width: 100%; margin-top: 1%"
              :header-cell-style="{
                padding: '0',
              }"
              @selection-change="handleSelectionChange"
            >
              <el-table-column type="selection" width="45" align="center">
              </el-table-column>
              <el-table-column
                type="index"
                label="序号"
                width="50"
                align="center"
              >
              </el-table-column>
              <el-table-column
                v-for="(i, index) in item.table"
                :key="i.label"
                :prop="i.prop"
                align="center"
                :label="i.label"
              >
                <template slot-scope="scope">
                  <el-input
                    size="small"
                    v-model="scope.row[index]"
                    placeholder="请输入"
                  />
                </template>
              </el-table-column>
            </el-table>
          </el-form-item> -->
        </div>
      </div>
    </el-form>

    <!-- 添加行的弹窗 -->
    <el-dialog
      :append-to-body="true"
      :title="title"
      :visible.sync="dialogVisible"
      width="80%"
      @close="closetable"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
    >
      <el-form
        :inline="true"
        :model="ruleForm"
        ref="dynamicValidateForm"
        label-width="100px"
        class="demo-dynamic"
      >
        <el-form-item label="检测标准" prop="jcbz">
          <el-select
            v-model="ruleForm.jcbz"
            placeholder="请选择检测标准"
            filterable
            value-key="id"
            @change="Standard"
          >
            <el-option
              v-for="item in standardoptions"
              :key="item.id"
              :label="item.no"
              :value="item"
            >
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="检测项目" prop="jcxm">
          <el-select
            v-model="ruleForm.jcxm"
            placeholder="请选择检测项目"
            filterable
            value-key="id"
            @focus="focus()"
            @change="jcxm"
          >
            <el-option
              v-for="item in itemoptions"
              :key="item.id"
              :label="item.name"
              :value="item"
            >
            </el-option>
          </el-select>
        </el-form-item>
      </el-form>

      <el-button size="small" @click="diaAdd()" class="addbtn">添加</el-button>
      <el-button size="small" @click="diaDele()" class="Cancelbtn"
        >删除</el-button
      >
      <el-table
        :data="all1"
        style="width: 100%; margin-top: 10px"
        border
        @selection-change="diaHandle"
      >
        <el-table-column type="selection" width="45" align="center">
        </el-table-column>
        <el-table-column
          v-for="(i, index) in all"
          :key="i.label"
          :prop="i.prop"
          align="center"
          :label="i.label"
        >
          <template slot-scope="scope">
            <el-input
              size="small"
              v-if="scope.row[index].type === 0"
              v-model="scope.row[index].default_val"
              placeholder="请输入"
            ></el-input>
            <el-input-number
              size="small"
              v-if="scope.row[index].type === 1"
              v-model="scope.row[index].default_val"
              placeholder="请输入"
            ></el-input-number>
            <el-date-picker
              size="small"
              v-if="scope.row[index].type === 3"
              v-model="scope.row[index].default_val"
              type="date"
              placeholder="选择日期"
              format="yyyy-MM-dd"
            >
            </el-date-picker>
            <el-date-picker
              size="small"
              v-if="scope.row[index].type === 4"
              v-model="scope.row[index].default_val"
              type="datetime"
              placeholder="选择日期时间"
            >
            </el-date-picker>
            <el-select
              size="small"
              filterable
              v-if="scope.row[index].type === 9"
              v-model="scope.row[index].default_val"
              placeholder="请选择"
            >
              <el-option
                v-for="(i, ind) in scope.row[index].attr"
                :key="ind"
                :label="i.name"
                :value="i.name"
              >
              </el-option>
            </el-select>
          </template>
        </el-table-column>
      </el-table>
      <span slot="footer" class="dialog-footer">
        <el-button @click="closetable()">取 消</el-button>
        <el-button type="primary" @click="sure()">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import axios from "axios";
import { uploadFileDev } from "@/api/dev";

import { mapGetters } from "vuex";
import {
  GetTypeListById,
  GetParameterListById,
  GetAllStandardList,
  GetStandardListById,
} from "@/api/Basic";
import { Time } from "@/utils/index";

export default {
  name: "SearchHead",
  computed: {
    ...mapGetters(["userid", "name", "btnsUrl", "token"]),
  },
  props: {
    List: [Object, Array],
    // table: Array,
    // table1: Array,
  },
  data() {
    return {
      multipleSelection: [], //多选
      tableFormrules: [],
      tableForm: {},
      ta: [],
      fileList: [], //文件列表
      formData: new FormData(),
      up: [],
      url: "", //项目类别的地址
      standardoptions: [], //检测标准的列表
      itemoptions: [], //检测项目的列表
      ids: "", //检测标准id的集合
      ite: {}, //产品大类的选择
      it: "", //资质
      ie: "", //参数
      im: [], //产品名称(产品类别)
      tablevisible: false, //检测标准和项目的弹出框
      prevTarget: null, // 编辑 Popover 的 Reference (参照),用于 popover.js 对齐两个元素
      popperFlag: false, // 用于编辑 Popover 的刷新
      row: [],
      index: 0,
      TName: "选择",

      all: [],
      all1: [],
      dialogVisible: false,
      arr: {}, //弹窗所需的当前表格信息
      ruleForm: { jcbz: "", jcxm: "" },
      spanArr: [],
      position: 0,
      editnum: 1,
      row: {},
      multiple: [],
      title: "新增",
    };
  },
  watch: {
    List: {
      handler(newVal, oldVal) {
        if (JSON.stringify(newVal) !== "{}") {
          this.editchange(); //处理数据
          this.ne();
        }
      },
      immediate: true, // //immediate:true代表如果在 wacth 里声明了之后,就会立即先去执行里面的handler方法,如果为 false,不会在绑定的时候就执行。
      // deep: true, //默认值是 false,代表是否深度监听
    },
  },
  methods: {
    editchange() {
      // console.log(this.List, "111");
      this.List.dom.forEach((i, j) => {
        // 表单中type===9下拉框的数据
        if (i.type === 9) {
          var before = i.events[0].command.split("/")[0];
          this.btnsUrl.map((obj) => {
            if (obj.key === before) {
              this.url = i.events[0].command.replace(before, obj.value); //变量的形式
              axios({
                method: "get",
                url: this.url,
                headers: {
                  token: this.token,
                },
              }).then((res) => {
                // console.log(res.data.data);
                i.attr = res.data.data;
              });
            }
          });
        }
        // 表格中的参评名称,加载数据
        if (i.type === 7) {
          // 工装夹具
          if (i.attr[1] instanceof Array) {
            i.attr[1].forEach((ele) => {
              // 下拉框(项目类别)
              if (ele.type === 9) {
                var before = ele.events[0].command.split("/")[0];
                this.btnsUrl.map((obj) => {
                  if (obj.key === before) {
                    this.url = ele.events[0].command.replace(before, obj.value); //变量的形式

                    // 判断是否有拼接
                    if (JSON.stringify(this.url).indexOf("{dataid}") != -1) {
                      this.url = this.url.replace(/{dataid}/, this.List.dataid);
                    }
                    // console.log(this.url, "this.url");
                    axios({
                      method: "get",
                      url: this.url,
                      // params: {
                      //   name: this.names,
                      // },
                      headers: {
                        token: this.token,
                      },
                    }).then((res) => {
                      // console.log(res.data.data, "111111");
                      ele.attr = res.data.data;
                    });
                  }
                });
              }
            });
          }
        }
      });
      // // 检测标准
      // GetAllStandardList().then((res) => {
      //   this.standardoptions = res.data;
      // });
    },

    // toSearch() {
    //   this.$emit("getSearchParam", this.List);
    // },
    // // 一种方法
    // sub(callback) {
    //   this.$refs["FromHead"].validate(async (valid) => {
    //     if (valid) {
    //       //   const res = await AddFromData({ ...this.newform });
    //       //   console.log(res);
    //       //   if (res.code === 200) {
    //       //     if (this.newform.draft) {
    //       //       this.$notify({
    //       //         type: "success",
    //       //         position: "bottom-left",
    //       //         message: "添加成功",
    //       //         duration: 2000,
    //       //         offset: 100,
    //       //       });
    //       //     } else {
    //       //       this.$notify({
    //       //         type: "success",
    //       //         position: "bottom-left",
    //       //         message: "暂存成功",
    //       //         duration: 2000,
    //       //         offset: 100,
    //       //       });
    //       //     }
    //       //   }
    //     } else {
    //       this.$message.error("请将必填项填写完整");
    //       return false;
    //     }
    //   });
    // },

    // 验证表单    两种方法
    validate(callback) {
      this.$refs["FromHead"].validate((valid) => {
        callback(valid);
      });
    },
    resetFields() {
      this.$refs["FromHead"].resetFields();
    },
    // 表单中的上传文件验证
    upload(rule, value, callback, i) {
      // console.log(value);
      if (i.default_val !== "" || i.default_val !== []) {
        callback();
      } else {
        callback(new Error("请先上传相关文件"));
      }
    },

    // 表格添加行====================================
    addtable(item) {
      // console.log(item);
      // 工装夹具表格
      if (item.attr[1] instanceof Array) {
        var a = [];
        a = item.attr[1].map((obj, idx) => {
          // if (obj.type === 9) {
          //   return {
          //     name: "",
          //     sort: obj.sort,
          //     type: obj.type,
          //     required: obj.required,
          //     default_val: obj.default_val,
          //     attr: [],
          //   };
          // } else {
          return {
            name: "",
            sort: obj.sort,
            type: obj.type,
            required: obj.required,
            default_val: obj.default_val,
            attr: obj.type === 10 ? [] : obj.attr,
          };
          // }
        });
        item.table1.push(a);
      } else {
        // 其他表格(全都是输入框)
        const lis = Array(item.table.length).fill("");
        // lis=['','','','','','']
        item.table1.push(lis);
      }
      // console.log(item);
      // 为了表格表单校验
      // const aaa = lis.map((ele, ind) => {
      //   return "a" + [ind];
      // });
      // let obj = {}; //初始化js对象
      // for (let i = 0; i < aaa.length; i++) {
      //   this.$set(obj, aaa[i], "");
      // }
      // this.List.table1.push(obj);
      // this.List.table1.push(lis);

      // // 判断表格最后一行是否都填完整
      // if (this.table1.length > 0) {
      //   this.table1[this.table1.length - 1].forEach((item) => {
      //     if (item === "") {
      //       ar = true;
      //     } else {
      //       ar = false;
      //     }
      //   });
      //   if (ar) {
      //     this.$message.error("请将表格填写完整");
      //   } else {
      //     this.table1.push(lis);
      //   }
      // } else {
      //   this.table1.push(lis);
      // }
    },
    // 表格删除
    deletetable(item) {
      // console.log(item);
      var da = [];
      da = item.table1.filter((itemA) => {
        return this.multipleSelection.every((itemB) => {
          return itemB !== itemA;
        });
      });
      item.table1 = da;
      this.multipleSelection = [];
      this.$forceUpdate(); //这个是给二级表单用的,二级表单如果不加这个,则数据更新了但是视图没变;而发起新的弹窗则不会出现这个问题,不知道是不是组件嵌套的问题
    },
    toggleSelection(rows) {
      if (rows) {
        rows.forEach((row) => {
          this.$refs.table.toggleRowSelection(row);
        });
      } else {
        this.$refs.table.clearSelection();
      }
    },
    handleSelectionChange(val) {
      this.multipleSelection = val;
      // console.log(this.multipleSelection);
    },

    // 新测试明细=================================
    ne() {
      this.List.dom.forEach((i, j) => {
        if (i.type === 11) {
          this.all1 = [
            // 需要的类型
            // [
            //   {
            //     sort: 45,
            //     type: 0,
            //     name: "产品名称",
            //     attr: [],
            //     required: false,
            //     default_val: "1",
            //     events: [],
            //   },
            //   {
            //     sort: 46,
            //     type: 0,
            //     name: "商标",
            //     attr: [],
            //     required: false,
            //     default_val: "",
            //     events: [],
            //   },
            //   {
            //     sort: 47,
            //     type: 0,
            //     name: "型号规格",
            //     attr: [],
            //     required: false,
            //     default_val: "",
            //     events: [],
            //   },
            // ],
          ];
          this.all = [
            { label: "产品名称", prop: "a3" },
            { label: "商标", prop: "a4" },
            { label: "型号规格", prop: "a5" },
            { label: "产品编号/批号", prop: "a6" },
            { label: "生产日期", prop: "a7" },
            { label: "数量", prop: "a8" },
            { label: "备注", prop: "a9" },
          ];
          i.table = [
            { label: "序号", prop: "a0" },
            { label: "检测标准", prop: "a1" },
            { label: "检测项目", prop: "a2" },
            { label: "产品名称", prop: "a3" },
            { label: "商标", prop: "a4" },
            { label: "型号规格", prop: "a5" },
            { label: "产品编号/批号", prop: "a6" },
            { label: "生产日期", prop: "a7" },
            { label: "数量", prop: "a8" },
            { label: "备注", prop: "a9" },
          ];
          i.attr = [
            [
              "编号",
              "检测标准",
              "检测项目",
              "产品名称",
              "商标",
              "型号规格",
              "产品编号/批号",
              "生产日期",
              "数量",
              "备注",
            ],
            [
              {
                sort: 42,
                type: 0,
                name: "编号",
                attr: [],
                required: false,
                default_val: "",
                events: [],
              },
              {
                sort: 43,
                type: 9,
                name: "检测标准",
                attr: [],
                required: false,
                default_val: "",
                events: [],
              },
              {
                sort: 44,
                type: 9,
                name: "检测项目",
                attr: [],
                required: false,
                default_val: "",
                events: [],
              },
              {
                sort: 45,
                type: 9,
                name: "产品名称",
                attr: [],
                required: false,
                default_val: "",
                events: [],
              },
              {
                sort: 46,
                type: 0,
                name: "商标",
                attr: [],
                required: false,
                default_val: "",
                events: [],
              },
              {
                sort: 47,
                type: 0,
                name: "型号规格",
                attr: [],
                required: false,
                default_val: "",
                events: [],
              },
              {
                sort: 48,
                type: 0,
                name: "产品编号/批号",
                attr: [],
                required: false,
                default_val: "",
                events: [],
              },
              {
                sort: 49,
                type: 3,
                name: "生产日期",
                attr: [],
                required: false,
                default_val: "",
                events: [],
              },
              {
                sort: 50,
                type: 1,
                name: "数量",
                attr: [],
                required: false,
                default_val: "",
                events: [],
              },
              {
                sort: 51,
                type: 0,
                name: "备注",
                attr: [],
                required: false,
                default_val: "",
                events: [],
              },
            ],
          ];
          i.table1 = [
            //需要的形式
            // {
            //   a0: "1",
            //   a1: "YY/T 0520-2009 5.2",
            //   a2: "尺寸",
            //   a3: "个性化基台及螺钉1",
            //   a4: "N/A",
            //   a5: "三边形ANT-R",
            //   a6: "QY2205034",
            //   a7: "2022.05.14",
            //   a8: 5,
            //   a9: "备注",
            // },
          ];
          // 有没有默认值
          if (i.default_val.length > 0) {
            i.default_val.forEach((item, index) => {
              item.cpmc.forEach((n) => {
                i.table1.push({
                  a0: item.no,
                  a1: item.jcbz,
                  a2: item.jcxm,
                  a3: n.cpmc,
                  a4: n.sb,
                  a5: n.ggxh,
                  a6: n.cpbhph,
                  a7: n.scrq,
                  a8: n.sl,
                  a9: n.bz,
                });
              });
            });
          }

          for (let index = 0; index < i.table1.length; index++) {
            this.rowspan(i.table1);
          }
        }
      });
    },
    rowspan(tableData, spanArr, position, spanName) {
      // 每次调用清空数据
      this.spanArr = [];
      this.position = 0;

      tableData.forEach((item, index) => {
        if (index === 0) {
          this.spanArr.push(1);
          this.position = 0;
        } else {
          // 为需要合并查询的项
          if (tableData[index].a0 === tableData[index - 1].a0) {
            this.spanArr[this.position] += 1;
            this.spanArr.push(0);
          } else {
            this.spanArr.push(1);
            this.position = index;
          }
        }
      });
    },
    //合并行列
    objectSpanMethod({ row, column, rowIndex, columnIndex }) {
      if (
        columnIndex === 0 ||
        columnIndex === 1 ||
        columnIndex === 2 ||
        columnIndex === 3 ||
        columnIndex === 11
      ) {
        const _row = this.spanArr[rowIndex];
        const _col = _row > 0 ? 1 : 0;
        return {
          rowspan: _row,
          colspan: _col,
        };
      }
    },
    edit(row, index, item) {
      this.arr = [];
      this.row = {};
      this.title = "编辑";
      this.arr = item; //赋值给this.arr,不能使用json,不然编辑保存的时候没有用
      this.row = JSON.parse(JSON.stringify(row));
      this.editnum = 1;
      const at = JSON.parse(JSON.stringify(item.table1)).filter((i) => {
        if (i.a0 === row.a0) {
          return i;
        }
      });
      this.ruleForm.jcbz = at[0]["a1"];
      this.ruleForm.jcxm = at[0]["a2"];
      // 删除前三个数据
      at.forEach((j) => {
        delete j.a0;
        delete j.a1;
        delete j.a2;
      });
      this.all1 = at;
      const ii = JSON.parse(JSON.stringify(item.table));
      const jj = JSON.parse(JSON.stringify(item.attr[1]));
      ii.splice(0, 3);
      jj.splice(0, 3);

      let ab = [];
      this.all1.filter((ele, ij) => {
        let bt = [];
        bt = jj.map((obj, index) => {
          return {
            name: "",
            sort: obj.sort,
            type: obj.type,
            required: obj.required,
            default_val: ele["a" + (index + 3)],
            attr: obj.type === 10 ? [] : obj.attr,
          };
        });
        ab.push(bt);
      });
      this.all = ii;
      this.all1 = ab;
      this.dialogVisible = true;
    },
    ad(item) {
      // 判断产品大类和报告用章类型是否为空
      let pro = {};
      let baogao = {};
      this.List.dom.forEach((i, j) => {
        if (i.name === "产品大类") {
          pro = i;
        } else if (i.name === "报告用章类型") {
          baogao = i;
        }
      });

      if (pro.default_val === "") {
        this.$message.error("请先填写表单中的产品大类和报告用章类型");
      } else if (baogao.default_val === "") {
        this.$message.error("请先填写表单中的产品大类和报告用章类型");
      } else {
        // 获取产品大类对应的id
        this.ite = pro.attr.find((obj) => {
          return obj.name === pro.default_val;
        });
        const abc = baogao.default_val.filter((ele) => {
          return ele !== "无";
        });

        if (abc.length === 0) {
          this.it = "";
        } else {
          this.it = abc.join(",");
        }

        GetStandardListById({
          productlineid: this.ite.id,
          qualifications: this.it,
        }).then((res) => {
          // console.log(res);
          this.standardoptions = res.data;
        });
        this.arr = [];
        this.all1 = [];
        this.title = "新增";
        this.editnum = 0;
        this.dialogVisible = true;
        this.arr = item;
      }
    },
    dele(item) {
      var da = [];
      da = item.table1.filter((itemA) => {
        return this.multipleSelection.every((itemB) => {
          // console.log(itemB);
          return itemB.a0 !== itemA.a0;
        });
      });
      item.table1 = da;
      this.multipleSelection = [];
      this.$forceUpdate(); //这个是给二级表单用的,二级表单如果不加这个,则数据更新了但是视图没变;而发起新的弹窗则不会出现这个问题,不知道是不是组件嵌套的问题
    },
    handle(val) {
      this.multipleSelection = val;
    },
    // 新测试明细弹窗中的表格操作=================================
    closetable() {
      this.ruleForm = { jcbz: "", jcxm: "" };
      this.all1 = [];
      this.dialogVisible = false;
    },
    Standard(val) {
      this.ids = val.id;
      this.ruleForm.jcxm = "";
      this.ie = "";
      // this.ids = [];
      // const arr = val.map((i) => {
      //   return i.id;
      // });
      // this.ids = arr.toString(",");
    },
    focus() {
      // if (this.ids.length > 0) {
      // console.log(this.ids);
      GetParameterListById({
        standardid: this.ids,
        qualifications: this.it,
      }).then((res) => {
        // console.log(res);
        this.itemoptions = res.data;
      });
      // }
    },
    async jcxm(val) {
      // console.log(val, "jcxm");
      this.ie = val.id;

      // 检测项目选完后调用接口获取产品名称
      const re = await GetTypeListById({
        standardid: this.ids,
        parameterid: this.ie,
      });
      this.im = re.data;
    },
    sure() {
      const b = this.arr.table.map((obj, idx) => {
        return obj.prop;
      });
      // console.log(this.ruleForm);
      // 添加
      if (this.editnum === 0) {
        // 序号
        let num = 0;
        if (this.arr.table1.length > 0) {
          num = Number(this.arr.table1[this.arr.table1.length - 1].a0) + 1;
        } else {
          num = 1;
        }
        var aa = [];
        this.all1.forEach((item, index) => {
          var a = {};
          this.$set(a, b[0], String(num));
          this.$set(a, b[1], this.ruleForm.jcbz.no);
          this.$set(a, b[2], this.ruleForm.jcxm.name);
          for (let index = 0; index < item.length; index++) {
            this.$set(a, b[index + 3], item[index].default_val);
          }
          aa.push(a);
        });
        this.arr.table1.push(...aa);
        this.rowspan(this.arr.table1);
        this.dialogVisible = false;
      } else {
        // 编辑
        // 序号
        const num = this.row.a0;
        var aa = [];
        this.all1.forEach((item, index) => {
          var a = {};
          this.$set(a, b[0], num);
          this.$set(a, b[1], this.ruleForm.jcbz.no);
          this.$set(a, b[2], this.ruleForm.jcxm.name);
          for (let index = 0; index < item.length; index++) {
            this.$set(a, b[index + 3], item[index].default_val);
          }
          aa.push(a);
        });
        // 获取第一个符合条件的下标
        const findIndex = this.arr.table1.findIndex(
          (item) => item.a0 === aa[0].a0
        );
        // 获取所有符合条件的长度
        let nu = 0;
        this.arr.table1.forEach((re, ind) => {
          if (re.a0 === aa[0].a0) {
            nu += 1;
          }
        });
        // 进行替换
        this.arr.table1.splice(findIndex, nu, ...aa);
        this.rowspan(this.arr.table1);
        this.dialogVisible = false;
      }
    },
    async diaAdd() {
      if (this.ruleForm.jcbz !== "" && this.ruleForm.jcxm !== "") {
        let newar = [];
        newar = JSON.parse(JSON.stringify(this.arr.attr[1]));

        if (this.im.length > 0) {
          var a = [];
          newar.splice(0, 3);
          a = newar.map((obj, idx) => {
            return {
              name: "",
              sort: obj.sort,
              type: obj.type,
              required: obj.required,
              default_val: obj.default_val,
              attr: obj.type === 11 ? [] : obj.attr,
            };
          });
          a[0].attr = this.im; //赋值给产品名称
          this.all1.push(a);
        } else {
          this.$message.error("暂无产品名称,请到基础库添加相关信息");
        }
      } else {
        this.$message.error("请先选择检测标准和检测项目");
      }
    },
    diaDele() {
      var da = [];
      da = this.all1.filter((itemA) => {
        return this.multiple.every((itemB) => {
          return itemB !== itemA;
        });
      });
      this.all1 = da;
      this.multipleSelection = [];
      this.$forceUpdate(); //这个是给二级表单用的,二级表单如果不加这个,则数据更新了但是视图没变;而发起新的弹窗则不会出现这个问题,不知道是不是组件嵌套的问题
    },
    diaHandle(val) {
      this.multiple = val;
    },

    // 表单中的导入=======================================================
    remove(file, fileList) {
      this.fileList = fileList;
      this.List.dom.forEach((i, j) => {
        if (i.type === 8) {
          i.default_val = this.fileList.map((item, index) => {
            return item.FileUrl;
          });
        }
      });
    },
    change(file, fileList, index) {
      this.fileList = []; // 清空图片已经上传的图片列表(绑定在上传组件的file-list)
      let a = 0;
      fileList.forEach((item, idx) => {
        /*在此处,对比文件名,将文件名相同的对比次数累加,
      相同的文件名累加值为 2 时,说明文件名已经重复,直接删掉。*/
        if (file.name === item.name) {
          a++;
          // console.log(a, file, fileList);
          if (a === 2) {
            this.$mess.info("不能重复上传,已把重复文件删除");
            fileList.splice(idx, 1);
          }
        }
      });
      this.fileList = fileList;
      if (a !== 2) {
        this.httprequest(file, index);
      }
    },
    async httprequest(file, index) {
      // console.log(this.List);
      // 一个一个上传
      var formData = new FormData();
      formData.append("files", file.raw);
      // 上传需要的存放地址
      let data = Time(new Date());
      let pas = "/app-" + this.List.appid + "/" + data;
      formData.append("storageAddress", pas); //携带其他参数
      const res = await uploadFileDev(formData);
      // console.log(res, "123");
      if (res.code === 200) {
        const a = [];
        a.push(res.data[0].fileUrl);
        this.List.dom.forEach((i, j) => {
          if (i.type === 8 && j === index) {
            i.default_val = a;
          }
        });
        this.$mess.success("上传成功"); //这个是封装的,无论调用多少次,都只显示一次
      }

      // this.up = [];
      // if (this.fileList.length > 0) {
      //   this.fileList.forEach((file) => {
      //     this.formData.append("files", file.raw);
      //   });
      //   const res = await UploadData(this.formData);
      //   console.log(res, "123");
      //   if (res.code === 200) {
      //     for (let item of res.data) {
      //       this.up.push(item.FileUrl);
      //     }
      //     // console.log(this.up, "up");
      //     this.List.dom.forEach((i, j) => {
      //       if (i.type === 8) {
      //         i.default_val = this.up;
      //       }
      //     });
      //     this.$mess.success("上传成功"); //这个是封装的,无论调用多少次,都只显示一次
      //     this.formData.delete("files"); //清除
      //     console.log(this.List.dom[0], "888");
      //   }
      //   // if (this.$refs.upload) {
      //   //   this.$refs.upload.uploadFiles = [];
      //   // }
      // }
    },

    // 表格中的导入=====================================
    handlechange(file, fileList, row, col, index) {
      row[index].attr = fileList;
    },
    Remove(file, fileList, row, col, index) {
      row[index].attr = [];
    },
    async http(file, fileList, row, col, index) {
      var formData = new FormData();
      formData.append("files", file.file);
      let data = Time(new Date());
      let pas = "/app-" + this.List.appid + "/" + data;
      // console.log(pas);
      formData.append("storageAddress", pas); //携带其他参数
      const res = await uploadFileDev(formData);
      // console.log(res, "123");
      if (res.code === 200) {
        row[index].default_val = res.data[0].fileUrl;
        this.$mess.success("上传成功"); //这个是封装的,无论调用多少次,都只显示一次
      }
    },

    // 检测标准和检测项目======================
    showPopover(row, e, i) {
      // console.log(i);
      //阻止事件冒泡,兼容ie
      if (event.stopPropagation) {
        event.stopPropagation();
      } else if (window.event) {
        window.event.cancelBubble = true;
      }
      let currentTarget = e.target; // 赋值当前点击的编辑
      // this.row = row;
      // this.index = index;
      // 判断是否需要切换
      if (this.prevTarget === currentTarget) {
        // 同一个元素重复点击
        // this.tablevisible = !this.tablevisible;
        row.show = !row.show;
      } else {
        // 切换不同元素, 判断之前是否有点击其他编辑 prevTarget
        if (this.prevTarget) {
          // 先清除之前的编辑框
          this.clearEditPopperComponent(row);
          // 然后生成新的编辑框
          this.$nextTick(() => {
            this.prevTarget = currentTarget;
            // this.tablevisible = true;
            row.show = true;
          });
        } else {
          // 首次
          // console.log("首次--->this.prevTarget");
          this.prevTarget = currentTarget;
          // this.tablevisible = true;
          row.show = true;
        }
      }
    },
    // 清空编辑组件
    clearEditPopperComponent(row) {
      this.prevTarget = null;
      this.popperFlag = !this.popperFlag;
      // this.tablevisible = false;
      row.show = false;
      // this.row = [];
    },
    changeStandard(val) {
      this.ids = [];
      const arr = val.map((i) => {
        return i.id;
      });
      this.ids = arr.toString(",");
    },
    onfocus(row) {
      if (row.standard.length > 0) {
        // console.log(this.ids);
        GetParameterListById({ standardid: this.ids }).then((res) => {
          // console.log(res);
          this.itemoptions = res.data;
        });
      }
    },
    add(i, index) {
      // console.log(i);
      const ar = {
        standard: [],
        item: [],
        show: false,
        btn: "选择",
      };
      i.attr.push(ar);
    },
    del(i, index) {
      i.splice(index, 1);
    },
    sub(obj) {
      console.log(obj);

      var nos = [];
      // console.log(obj.attr);
      obj.default_val = obj.attr.map((i) => {
        nos = i.standard.map((obj) => {
          return obj.no;
        });
        return {
          standard: nos,
          item: i.item,
        };
      });
      obj.show = !obj.show;

      if (obj.default_val.length > 0) {
        obj.btn = "已选择";
      }

      // this.tablevisible = false;
    },
    cancel(obj) {
      obj.attr.splice(
        obj.default_val.length,
        obj.attr.length - obj.default_val.length
      );
      // this.tablevisible = false;
      obj.show = !obj.show;
    },
  }
};
</script>

<style lang="scss">
#SearchHead {
  width: 100%;
  .el-form-item {
    width: 100%;
  }
  .el-form-item__content {
    width: 100%;
  }
  .el-select {
    width: 100%;
  }
  .el-textarea__inner {
    border: 1px solid #dcdfe6 !important;
  }
  .el-date-editor.el-input {
    width: 100%;
  }
  .el-upload {
    width: 100%;
  }
  .upload {
    .el-upload-list {
      text-align: left !important;
    }
  }
  .hide .el-upload--text {
    display: none !important;
  }
  .el-table__body-wrapper {
    overflow-y: scroll;
  }
}
</style>

<style lang="scss" scoped>
.el-dialog {
  .el-date-editor.el-input {
    width: 100% !important;
  }
}
</style>

2、多个表单共用一个对象,但要同时验证

<template>
  <div id="Detail" class="Detail">
    <!-- 收样信息 -->
    <div class="top">
      <div
        style="
          display: flex;
          justify-content: space-between;
          border-bottom: 1px solid #e4e7ed;
          margin-bottom: 20px;
        "
      >
        <div class="titleBox">
          <img src="@/assets/wd.png" style="width: 20px; height: 20px" />
          <div>收样信息 Receiver Information</div>
        </div>
      </div>

      <div class="formbox">
        <el-form
          :inline="false"
          ref="formA"
          :model="editformReceiver"
          :rules="editformReceiverRules"
        >
          <el-form-item label="Name(收样名称)" prop="receivername">
            <el-input v-model="editformReceiver.receivername"></el-input>
          </el-form-item>
          <el-form-item label="Address(收样地址)" prop="receiveraddress">
            <el-input
              v-model="editformReceiver.receiveraddress"
              type="textarea"
            ></el-input>
          </el-form-item>
          <el-form-item
            label="Contact person(联系人)"
            prop="receivercontactperson"
          >
            <el-input
              v-model="editformReceiver.receivercontactperson"
            ></el-input>
          </el-form-item>
          <el-form-item label="E-mail(邮箱)" prop="receiveremail">
            <el-input v-model="editformReceiver.receiveremail"></el-input>
          </el-form-item>
          <el-form-item label="Phone(电话)" prop="receiverphone">
            <el-input v-model="editformReceiver.receiverphone"></el-input>
          </el-form-item>
        </el-form>
      </div>
    </div>
    <!-- 送样信息  -->
    <div class="top">
      <div
        style="
          display: flex;
          justify-content: space-between;
          border-bottom: 1px solid #e4e7ed;
          margin-bottom: 20px;
        "
      >
        <div class="titleBox">
          <img src="@/assets/wd.png" style="width: 20px; height: 20px" />
          <div>送样信息 Sender Information</div>
        </div>
      </div>
      <div class="formbox">
        <el-form
          :inline="false"
          ref="formB"
          :model="editformReceiver"
          :rules="editformReceiverRules"
        >
          <el-form-item label="Name(客户名称)" prop="sendername">
            <el-input v-model="editformReceiver.sendername"></el-input>
          </el-form-item>
          <el-form-item label="Address(客户地址)" prop="senderaddress">
            <el-input
              v-model="editformReceiver.senderaddress"
              type="textarea"
            ></el-input>
          </el-form-item>
          <el-form-item
            label="Contact person(联系人)"
            prop="sendercontactperson"
          >
            <el-input v-model="editformReceiver.sendercontactperson"></el-input>
          </el-form-item>
          <el-form-item label="E-mail(邮箱)" prop="senderemail">
            <el-input v-model="editformReceiver.senderemail"></el-input>
          </el-form-item>
          <el-form-item label="Phone(电话)" prop="senderphone">
            <el-input v-model="editformReceiver.senderphone"></el-input>
          </el-form-item>
          <el-form-item label="Way of Delivery(送样方式)">
            <br />
            <el-radio-group
              v-model="editformReceiver.sendsampletype"
              @change="changeRadio"
            >
              <el-radio :label="0">自送</el-radio>
              <el-radio :label="1">赴厂</el-radio>
              <el-radio :label="2">快递</el-radio>
            </el-radio-group>
            <br />
          </el-form-item>
          <el-form-item
            label="快递单号"
            v-if="editformReceiver.sendsampletype === 2"
          >
            <el-input v-model="editformReceiver.couriernumber"></el-input>
          </el-form-item>
        </el-form>
      </div>
    </div>
 </div>
</template>

<script>
export default {
    methods: {
            // 提交
    addsub() {
      let formArr = ["formA", "formB", "formC"]; //三个form表单的ref
      var resultArr = []; //用来接受返回结果的数组
      var _self = this;
      function checkForm(formName) {
        //封装验证表单的函数
        var result = new Promise(function (resolve, reject) {
          _self.$refs[formName].validate((valid) => {
            if (valid) {
              resolve();
            } else {
              reject();
            }
          });
        });
        resultArr.push(result); //push 得到promise的结果
      }
      formArr.forEach((item) => {
        //根据表单的ref校验
        checkForm(item);
      });
      Promise.all(resultArr)
        .then(async (values) => {
          //提交表单的相关操作
          //_self.$refs.editformReceiver.resetFields();
          if (res.code === 200) {
            _self.$message.success("提交成功");
            _self.cancel();
          } else {
            _self.$message.error("提交失败");
          }
        })
        .catch((_) => {
          // _self.$message.error("请将必填项填写完整");
        });
    },
    }
}

3、表单中的上传图片不显示

使用上传el-upload,若ruleForm没有原始数据,上传图片后,图片无法显示。只要把<el-form-item的绑定属性和<el-upload内部<img的属性设置为不同变量,上传完成后设置img的src即可。

4、输入框使用正则表达式进行实时校验,正则如正整数、负整数、整数、非负整数、浮点数等

@input事件

每输入一个字符都会触发该事件,可用于实时查询。
<el-input
       v-model="day"
       placeholder="请输入延期天数"
       @input="input"
/>

使用方法:

methods: {
    input(e) {
      const num = /^[1-9]\d*$/
      if (num.test(e)) {
        this.day = e
      } else {
        // this.day = e.replace(/[^\d.]/g, '')
        this.day = e.replace(e, '')
        this.$message.error('延期天数只能输入正整数')
      }
    },
}

还有一些其他常用正则:

/^([1-9]|10)$/   //匹配1-10整数
​
^[1-9]\d*$     //匹配正整数

^-[1-9]\d*$     //匹配负整数

^-?[1-9]\d*$   //匹配整数

^[1-9]\d*|0$    //匹配非负整数(正整数 + 0)

^-[1-9]\d*|0$   //匹配非正整数(负整数 + 0)

^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$   //匹配正浮点数

^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$  //匹配负浮点数

^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$  //匹配浮点数

^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$   //匹配非负浮点数(正浮点数 + 0)

^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$  //匹配非正浮点数(负浮点数 + 0)

​

5、父组件提交子组件的表单

方法一:

父组件

<FromHead
          v-show="dialogVisible"
          ref="FromHead"
          :List="List"
          :editForm="editForm"
        ></FromHead>
methods: { 
    async sub(i, callback) {
       this.$refs["FromHead"].validate(async (valid) => {
        if (valid) {
          const res = await AddFromData({ ...this.newform });
          if (res.code === 200) {
              this.$notify({
                type: "success",
                position: "bottom-left",
                message: "添加成功",
                duration: 2000,
                offset: 100,
              });
              callback(res.data);
            } 
          }
        } else {
          this.$message.error("请将必填项填写完整");
          return false;
        }
    }
}

子组件

methods: { 
    // 验证表单  
    validate(callback) {
      this.$refs["FromHead"].validate((valid) => {
        callback(valid);
      });
    },
    //清除表单验证
    resetFields() {
      this.$refs["FromHead"].resetFields();
    },
}

方法二:

父组件

<FromHead
          v-show="dialogVisible"
          ref="FromHead"
          :List="List"
          :editForm="editForm"
          @sub="sub"
        ></FromHead>
methods: { 
    async sub(i, callback) {
        this.$refs.FromHead.shu();
    }
}

子组件

methods: { 
   // 一种方法
    sub(callback) {
      this.$refs["FromHead"].validate(async (valid) => {
        if (valid) {
             const res = await AddFromData({ ...this.newform });
             console.log(res);
             if (res.code === 200) {
                 this.$notify({
                   type: "success",
                   position: "bottom-left",
                   message: "添加成功",
                   duration: 2000,
                   offset: 100,
                 });
             }
        } else {
          this.$message.error("请将必填项填写完整");
          return false;
        }
      });
    }
}

二、样式

1、输入框自动填充的背景色修改

进入登录页,账号和密码会自动填入时,会出现填充背景色,这个背景色和我们的页面样式不符合,需要改写成自己所需颜色。

//vue2
      &:-webkit-autofill {
        transition: background-color 5000s ease-in-out 0s;
        background-color: transparent !important;
     // box-shadow: 000px1000px $bg inset !important;
        -webkit-text-fill-color: $cursor !important; //字体颜色
      }


//vue3
    input:-internal-autofill-selected {
       transition: background-color 5000s ease-in-out 0s;
       background-color: transparent !important;
     }

2、日期图标显示在右侧

.el-input__inner {
    border: 1px solid #496ef9;
    width: 100%;
    height: 30px;
    line-height: 30px;
  }
  .el-date-editor.el-input {
    width: 100%;
  }
  .el-input--small .el-input__inner {
    width: 100%;
  }
  .el-input--small,
  .el-input--suffix {
    width: 100%;
  }
  // 日期图标
  .el-input__prefix {
    left: auto;
  }
  .el-icon-date:after {
    content: '\e78e';
    position: absolute;
    right: 50px;
    color: #496ef9;
  }
  .el-icon-date:before {
    content: '';
  }
  // 日期清除键
  .el-input__suffix {
      display: none;
  }

或者是

.el-date-editor.el-input {
      width: 44%;
    }
    .el-input__prefix {
      position: absolute;
      top: 0;
      right: 5px;
      display: block;
      width: 100%;
    }
    .el-icon-date:after {
      content: '\e78e';
      position: absolute;
      top: 1px;
      right: 30px;
      color: #496ef9;
    }
    .el-icon-date:before {
      content: '';
    }
    .el-input__icon {
      width: 100%;
    }

3、输入框提示文字的样式

.el-input__inner {
    &::placeholder {
      text-align: center;
    }
  }

这篇文章看完如果您觉得有所收获,认为还行的话,就点个赞收藏一下呗

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值