通用表单组件

169 阅读1分钟

组件:

<template>
  <el-form
    ref="dicTable"
    :inline="inline"
    :model="formData"
    :rules="rulesData"
    :label-position="labelPosition"
    :label-width="labelWidth"
    :class="`form-warp label-width-${labelWidth}`"
    :disabled="disabled"
    :size="size"
  >
    <el-row :key="i" v-for="i in !isCollapse ? row : 1" type="flex">
      <template
        v-for="field in !isCollapse
          ? formFields.slice((i - 1) * col, i * col)
          : formFields.slice(0, col - 1)"
      >
        <el-col
          v-if="field"
          :key="field.code"
          :span="field.span ? field.span : (field.col || 1) * span"
        >
          <el-form-item :label="field.label" :prop="field.prop">
            <slot
              :name="field.slotName || field.code"
              :formData="formData"
              :field="field"
              v-if="field.type == 'slot'"
            ></slot>

            <el-input-number
              v-model="formData[field.code]"
              v-else-if="field.type == 'number'"
              :clearable="field.clearable === undefined ? true : field.clearable"
              :readonly="readonly"
              @change="field.change || function () {}"
              :min="field.min"
              :max="field.max"
            ></el-input-number>

            <el-select
              v-else-if="field.type == 'select'"
              :remote-method="field.remote || function () {}"
              v-model="formData[field.code]"
              :multiple="field.multiple || false"
              :clearable="field.clearable === undefined ? true : field.clearable"
              :readonly="readonly"
              :placeholder="
                field.placeholder === undefined ? '请选择' + field.label : field.placeholder
              "
            >
              <el-option
                v-for="item in field.options || []"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              >
              </el-option>
            </el-select>

            <el-switch
              v-model="formData[field.code]"
              v-else-if="field.type == 'switch'"
              :active-text="field.activeText"
              :inactive-text="field.inactiveText"
              :readonly="readonly"
            >
            </el-switch>

            <el-date-picker
              v-model="formData[field.code]"
              v-else-if="/date/.test(field.type)"
              prop="date"
              :align="field.align || 'right'"
              :type="field.type"
              :clearable="field.clearable === undefined ? true : field.clearable"
              :placeholder="
                field.placeholder === undefined ? '请选择' + field.label : field.placeholder
              "
              :range-separator="field.separator === undefined ? '至' : field.separator"
              :start-placeholder="
                field.placeholder1 === undefined ? '开始日期' : field.placeholder1
              "
              :end-placeholder="field.placeholder2 === undefined ? '结束日期' : field.placeholder2"
              :picker-options="field.pickerOptions"
              :readonly="readonly"
            >
            </el-date-picker>

            <el-input
              v-model="formData[field.code]"
              v-else
              :clearable="field.clearable === undefined ? true : field.clearable"
              :readonly="readonly"
              :placeholder="
                field.placeholder === undefined ? '请输入' + field.label : field.placeholder
              "
            ></el-input>
          </el-form-item>
        </el-col>
      </template>
    </el-row>
    <el-row v-show="acitonable && !isCollapse" type="flex" justify="end">
      <el-col :span="span" style="text-align: end">
        <el-form-item class="action-btn">
          <el-button type="primary" size="small" round @click="onSubmit">提交</el-button>
          <el-button size="small" round @click="resetForm">重置</el-button>
        </el-form-item>
      </el-col>
    </el-row>
  </el-form>
</template>

<script>
  import { cloneDeep } from 'lodash';

  export default {
    props: {
      // 行内表单模式
      inline: {
        type: Boolean,
        default: true,
      },
      // 用于控制该表单内组件的尺寸
      size: {
        type: String,
        default: 'small',
      },
      // label宽度
      labelWidth: {
        type: String,
        default: '120px',
      },
      // label对齐方式
      labelPosition: {
        type: String,
        default: 'right',
      },
      // 一行有几列
      col: {
        type: Number,
        default: 4,
      },
      // 默认是否折叠
      collapse: {
        type: Boolean,
        default: false,
      },
      // 默认是否可折叠
      collapseable: {
        type: Boolean,
        default: true,
      },
      // 组件绑定的对象
      formData: {
        type: Object,
        default() {
          return {};
        },
      },
      // 组件的字段定义集合
      formFields: {
        type: Array,
        default() {
          return [];
        },
      },
      // 是否禁用
      disabled: {
        type: Boolean,
        default: false,
      },
      // 是否只读
      readonly: {
        type: Boolean,
        default: false,
      },
      // 是否需要按钮组
      acitonable: {
        type: Boolean,
        default: true,
      },
      // 校验规则
      rules: {
        type: Object,
        default() {
          return {};
        },
      },
    },
    emits: ['submit'],
    data() {
      return {
        // 当前是否折叠
        isCollapse: this.collapse,
        // 原始绑定的对象的克隆对象
        originData: {},
        originOption: {},
        // 存储字典管理对应编码
        dicCodes: [],
        parentId: '',
        options: [],
        rulesData: this.rules,
      };
    },
    computed: {
      // 每列的span数
      span() {
        return 24 / this.col;
      },
      // 行数
      row() {
        return Math.ceil(this.formFields.length / this.col);
      },
    },
    watch: {
      formData: {
        handler(nv) {
          nv && (this.originData = cloneDeep(nv));
        },
        immediate: true,
        deep: true,
      },
    },
    mounted() {
      this.getDemoList();
      this.handleDicOption();
    },
    methods: {
      // 获取字典管理编码
      getDemoList() {
        this.$api['getDictList']({})
          .then((res) => {
            res.data.list.map((arr) => {
              // 存储字典编码
              this.dicCodes.push({
                code: arr.code,
                id: arr.sysDictionaryId,
              });
            });
          })
          .catch((res) => {
            this.$message.error(res.message);
          });
      },
      // 处理字典管理编码的字典值
      handleDicOption() {
        setTimeout(() => {
          this.dicCodes.map((dicCode) => {
            for (const field of this.formFields) {
              if (field.code === dicCode.code || field.label === dicCode.code) {
                this.$api['getDictList']({ parentId: dicCode.id })
                  .then((res) => {
                    res.data.list.map((i) => {
                      // console.log(i);
                      this.options.push({
                        label: i.code,
                        value: i.name,
                      });
                    });
                    field.options = this.options;
                  })
                  .catch((res) => {
                    this.$message.error(res.message);
                  });
                // console.log(this.options);
              }
            }
          });
        }, 1000);
      },

      onSubmit() {
        this.$emit('submit', this.formData);
        // console.log(this.$refs.dicTable.validate);
        this.$refs.dicTable.validate((valid) => {
          // console.log(valid);
          console.log(this.formData['operator']);
          console.log(this.formData);
        });
        // this.$nextTick(() => {
        //   let af = this.$refs.dicTable
        //   if (af) {
        //     af.validate();
        //   }
        // });
      },
      resetForm() {
        // this.$refs.dicTable.resetFields();
        Object.assign(this.formData, this.originData);
      },
    },
  };
</script>

<style lang="scss" scoped>
  .form-warp {
    padding: 1.5rem 1.5rem 0 1.5rem;
    border-radius: $border-radius;
    background-color: #fff;

    .el-form-item {
      margin-bottom: 1.5rem;
    }

    ::v-deep .el-input-number,
    .el-form-item,
    .el-select,
    .el-date-editor {
      width: 100%;
    }
  }

  .label-width-80px {
    ::v-deep .el-form-item__content {
      width: calc(100% - 80px);
    }
  }
  .label-width-100px {
    ::v-deep .el-form-item__content {
      width: calc(100% - 100px);
    }
  }
  .label-width-120px {
    ::v-deep .el-form-item__content {
      width: calc(100% - 120px);
    }
  }
  .label-width-160px {
    ::v-deep .el-form-item__content {
      width: calc(100% - 160px);
    }
  }

  .action-btn {
    ::v-deep .el-form-item__content {
      width: 100%;
    }
  }
</style>


/*
//操作列示范
    formFields中的prop、formData、formFields中的code、rules中的对象名最好一一对应
    data() {
      return {
        formFields: [
          {
            code: 'amendNum',
            label: 'order-from',
            type: 'select',
            options: [],
            prop: 'amendNum',
          },
          {
            code: 'amendState',
            label: '质检更正单状态',
            type: 'date',
            prop: 'amendState'
          },
        ],

        formData: {
          amendNum: '',
          amendState: '',
        },
        // 校验规则
        rules: {
          amendNum: [
            { required: true, message: '请输入活动名称', trigger: 'blur' },
          ],
          amendState: [
            { required: true, message: '请输入状态', trigger: 'blur' },
          ],
        },
      };
    },
*/

实例代码:

<template>
  <div>
    <h1>测试表单</h1>
    <DicTable
      :formData="correctionData"
      :formFields="correctionFields"
      @submit="test"
      :rules="rules"
    ></DicTable>
  </div>
</template>
<script>
  export default {
    data() {
      return {
        // 更正单标签
        correctionFields: [
          {
            code: 'amendNum',
            label: 'order-from',
            type: 'select',
            options: [],
            prop: 'amendNum',
          },
          {
            code: 'amendState',
            label: '质检更正单状态',
            type: 'date',
            prop: 'amendState'
          },
          {
            code: 'operator',
            label: '质检人',
            prop: 'operator'
          },
        ],
        // 更正单数据
        correctionData: {
          amendNum: '',
          amendState: '',
          operator: '',
        },
        // 校验规则
        rules: {
          amendNum: [
            { required: true, message: '请输入活动名称', trigger: 'blur' },
          ],
          amendState: [
            { required: true, message: '请输入状态', trigger: 'blur' },
          ],
          operator: [
            { required: true, message: '请输入人', trigger: 'blur' },
          ]
        },
      };
    },
    methods: {
      test() {
        // console.log('提交了');
        // console.log(this.correctionData);
      },
    },
  };
</script>
<style scoped></style>