vue element form 封装

<template>
  <el-row :gutter="$attrs.gutter">
    {{ formData }}
    <el-form
      v-bind="$attrs"
      v-on="$listeners"
      :label-width="$attrs.labelWidth || '140px'"
    >
      <template v-for="item in formHeader">
        <el-col
          :key="item.prop"
          v-if="!item.hidden"
          :span="item.span || allSpan"
          :class="item.right ? 'flexAlignCenterRight' : ''"
        >
          <el-form-item
            v-bind="item"
            :rules="
              item.required
                ? [
                    {
                      required: true,
                      message: `${item.label.replace(/\(.*?\)/g, '')}必填`,
                      trigger: 'blur',
                    },
                  ]
                : null
            "
            v-required="
              item.dir === true || (item.required && item.dir !== false)
                ? formData[item.prop]
                : '1'
            "
          >
            <!-- 渲染函数 -->
            <template v-if="item.render">
              <ex-slot :render="item.render" :row="formData" />
            </template>
            <!-- 上传 -->
            <template v-else-if="item.type === 'upload'">
              <el-upload
                ref="upload"
                style="width: 200px"
                :file-list="field101fileList"
                :action="field101Action"
                :multiple="item.multiple || false"
                :before-upload="field101BeforeUpload"
                :accept="item.accept || '*'"
                :disabled="item.disabled || false"
              >
                <el-button size="small" type="primary" icon="el-icon-upload"
                  >点击上传</el-button
                >
                <div slot="tip" class="el-upload__tip">
                  {{ item.upload__tip }}
                </div>
              </el-upload>
            </template>
            <!-- 日期范围选择器 -->
            <template v-else-if="item.type === 'daterange'">
              <el-date-picker
                type="daterange"
                v-model="formData[item.prop]"
                v-bind="item"
                :format="item.format || 'yyyy-MM-dd'"
                :value-format="item.valueFormat || 'yyyy-MM-dd'"
                :start-placeholder="item.startPlaceholder || '开始日期'"
                :end-placeholder="item.endPlaceholder || '结束日期'"
                :range-separator="item.rangeSeparator || '至'"
              ></el-date-picker>
            </template>
            <!-- 日期选择器 -->
            <template v-else-if="item.type === 'date'">
              <el-date-picker
                v-model="formData[item.prop]"
                :format="item.format || 'yyyy-MM-dd'"
                :value-format="item.valueFormat || 'yyyy-MM-dd'"
                v-bind="item"
              ></el-date-picker>
            </template>
            <!-- 时间选择器 -->
            <template v-else-if="item.type === 'timerange'">
              <el-time-picker
                v-model="formData[item.prop]"
                v-bind="item"
                is-range
                :format="item.format || 'HH:mm:ss'"
                :value-format="item.valueFormat || 'HH:mm:ss'"
                :start-placeholder="item.startPlaceholder || '开始时间'"
                :end-placeholder="item.endPlaceholder || '结束时间'"
                :range-separator="item.rangeSeparator || '至'"
              ></el-time-picker>
            </template>
            <!-- 时间选择器 -->
            <template v-else-if="item.type === 'time'">
              <el-time-picker
                v-model="formData[item.prop]"
                :format="item.format || 'HH:mm:ss'"
                :value-format="item.valueFormat || 'HH:mm:ss'"
                :picker-options="{ selectableRange: '00:00:00-23:59:59' }"
                v-bind="item"
              ></el-time-picker>
            </template>
            <!-- 下拉 -->
            <template v-else-if="item.type === 'select'">
              <el-select
                v-model="formData[item.prop]"
                v-bind="item"
                :multiple="item.multiple || false"
                :filterable="item.filterable || true"
                :disabled="item.disabled || false"
              >
                <el-option
                  v-for="(el, i) in item.options"
                  :key="i"
                  :label="el.label"
                  :value="el.value"
                  :disabled="el.disabled"
                >
                </el-option>
              </el-select>
            </template>
            <!-- 单选 -->
            <template v-else-if="item.type === 'radio'">
              <el-radio-group
                v-model="formData[item.prop]"
                v-bind="item"
                :disabled="item.disabled || false"
              >
                <el-radio
                  v-for="(el, i) in item.options"
                  :key="i"
                  :label="el.value"
                  :disabled="el.disabled"
                  :border="el.border"
                >
                  {{ el.label }}
                </el-radio>
              </el-radio-group>
            </template>
            <!-- 滑块 -->
            <template v-else-if="item.type === 'switch'">
              <el-switch
                style="width: 200px"
                v-model="formData[item.prop]"
                :active-text="item.activeText"
                :inactive-text="item.inactiveText"
                :active-color="item.activeColor ? item.activeColor : '#13ce66'"
                :inactive-color="
                  item.inactiveColor ? item.inactiveColor : '#ff4949'
                "
                :disabled="item.disabled || false"
              ></el-switch>
            </template>
            <!-- 多选 -->
            <template v-else-if="item.type === 'checkbox'">
              <el-checkbox-group
                v-model="formData[item.prop]"
                v-bind="item"
                :disabled="item.disabled || false"
                :min="item.min"
                :max="item.max"
              >
                <el-checkbox
                  v-for="(el, i) in item.options"
                  :key="i"
                  :label="el.value"
                  :disabled="el.disabled"
                  :border="el.border"
                >
                  {{ el.label }}
                </el-checkbox>
              </el-checkbox-group>
            </template>
            <!-- 输入型 -->
            <!-- 多行 考虑加入富文本-->
            <template v-else-if="item.type === 'textarea'">
              <el-input
                type="textarea"
                v-model.trim="formData[item.prop]"
                v-bind="item"
              >
                <template slot="prepend" v-if="item.prepend">{{
                  item.prepend
                }}</template>
                <template slot="append" v-if="item.append">{{
                  item.append
                }}</template>
              </el-input>
            </template>
            <!-- 计数 -->
            <template
              v-else-if="item.type === 'number' || item.type === 'price'"
            >
              <!-- {{item}}v-model.trim="formData[item.prop]" -->
              <!-- <el-input
                :value="formatterValue(item)"
                @input="change($event,item)"
                @change="change($event,item)"

              ></el-input> -->
               <el-input-number
              v-model.trim="formData[item.prop]"
              :controls="item.controls || false"
              :step="item.step || 0.01"
              v-bind="commonProp(item)"
              :min="
                item.min !== null && item.min !== undefined ? item.min : 0.0
              "
              :precision="
                item.precision !== null && item.precision !== undefined
                  ? item.precision
                  : 2
              "
              :max="
                item.max !== null && item.max !== undefined
                  ? item.max
                  : 100000000
              "
              :step-strictly="item.stepStrictly || true"
            ></el-input-number>
            </template>
            <!-- 单行 -->
            <template v-else>
              <el-input
                v-model.trim="formData[item.prop]"
                v-bind="item"
                :prefix-icon="item.prefixIcon"
                :suffix-icon="item.suffixIcon"
                style="width: 200px"
              >
                <template slot="prepend" v-if="item.prepend">{{
                  item.prepend
                }}</template>
                <template slot="append" v-if="item.append">{{
                  item.append
                }}</template>
              </el-input>
            </template>
          </el-form-item>
        </el-col>
      </template>
    </el-form>
  </el-row>
</template>
<script>
// 自定义内容的组件
let exSlot = {
  functional: true,
  props: {
    row: Object,
    render: Function,
  },
  render: (h, data) => {
    const params = {
      row: data.props.row,
    };
    return data.props.render(h, params);
  },
};
export default {
  name: "form-default",
  inheritAttrs: false,
  components: { exSlot },
  props: {
    //所有col统一栅格
    allSpan: {
      type: Number,
      default: 12,
    },
    //所有控件统一宽度
    allWidth: {
      type: [String, Number],
      default: "200px",
    },
    formData: {
      type: Object,
      default: function () {
        return {};
      },
    },
    // 表头数据
    formHeader: {
      type: Array,
      default: function () {
        return [];
      },
    },
  },
  computed: {
    // formatterValue(e) {
    //   // if (this.formatter && this.precisionValue !== null) {
    //   //   return this.formatter(this.precisionValue);
    //   // } else {
    //   //   return this.precisionValue;
    //   // }
    //   console.log(e.target);
    //   // return 55
    // },
  },
  data() {
    return {
      field101Action: "https://jsonplaceholder.typicode.com/posts/",
      field101Action: "#",
      field101fileList: [],
    };
  },
  // computed: {
  //   comHeader() {
  //     return this.formHeader;
  //   },
  // },
  created() {
    this.formHeader.forEach((item) => {
      if (
        item.format === "array" &&
        Object.prototype.toString.call(this.formData[item.prop]) !==
          "[object Array]"
      ) {
        this.$set(this.formData, item.prop, []);
      }
    });
  },
  methods: {
    formatterValue(item){
      if(item.formatter){
return item.formatter(this.formData[item.prop])
      }else{
return this.formData[item.prop]
      }
      // console.log(item.formatter(50000));
      // console.log(this.change);

      // return item.formatter(this.formData[item.prop])
    },
    change(event,item) {
      if(item.parser){
 this.formData[item.prop]=item.parser(event)
      }else{
 this.formData[item.prop]=event
      }

    },
    validate() {
      return this.$refs.elForm.validate();
    },
    clearValidate() {
      this.$refs.elForm.clearValidate();
    },
    proppath(row, path) {
      let arr = path.split(".");
      let a = row;
      arr.forEach((item) => {
        a = a[item];
      });
      return a;
    },
    field101BeforeUpload(file) {
      let isRightSize = file.size / 1024 / 1024 < 2;
      if (!isRightSize) {
        this.$message.error("文件大小超过 2MB");
      }
      console.log(file.type);
      let isAccept = new RegExp("application").test(file.type);
      if (isAccept) {
        this.$message.error("应该选择非.exe等类型的文件");
      }
      return isRightSize && isAccept;
    },
  },
};
</script>
<style lang="scss" scoped>
::v-deep .el-input-number .el-input__inner {
  text-align: left;
}
</style>

  

<template>
  <FormDefault
    :formData="info"
    :formHeader="defaultHeader"
    :rules="rules"
    class="mt10"
    ref="elForm"
    :model="info"
    size="mini"
  ></FormDefault>
</template>

<script>
import FormDefault from "./form.vue";
export default {
  components: { FormDefault },
  data() {
    return {
      info: {
        f1: 12,
      },
      rules: {
        f1: [{ required: true }],
      },
      defaultHeader: [
        {
          prop: "f0",
          label: "评测预算费(元)",
          placeholder: "请输5入金额",
          type: "upload",
          required: true,
          render: (h, params) => {
            return [<div>4545</div>];
          },
        },

        {
          prop: "f1",
          label: "评测预算费(元)",
          placeholder: "请输5入金额",
          type: "number",
          formatter: (value) =>
            `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ","),
          parser: (value) => `${value}`.replace(/$s?|(,*)/g, ""),
          required: true,
        },
        {
          prop: "f2",
          label: "研发预算费(元)",
          placeholder: "请输入金额",
          type: "daterange",
        },
        {
          prop: "f3",
          label: "专利预算费(元)",
          placeholder: "请输入金额",
          type: "date",
        },
        {
          prop: "f4",
          label: "专家验收预算费(元)",
          placeholder: "请输入金额",
          type: "timerange",
        },

        {
          prop: "f53",
          label: "采购预算费(元)",
          placeholder: "请输入金额",
          type: "time",
        },

        {
          prop: "f54",
          label: "实施预算费(元))",
          placeholder: "请输入金额",
          type: "select",
          multiple: true,
          options: [
            {
              value: "选项1",
              label: "黄金糕",
            },
            {
              value: "选项2",
              label: "双皮奶",
            },
            {
              value: "选项3",
              label: "蚵仔煎",
            },
          ],
        },

        {
          prop: "f5",
          label: "其他预算费(元)",
          placeholder: "请输入金额",
          type: "radio",
          options: [
            {
              value: "选项1",
              label: "黄金糕",
            },
            {
              value: "选项2",
              label: "双皮奶",
            },
            {
              value: "选项3",
              label: "蚵仔煎",
            },
          ],
        },
        {
          prop: "f6",
          label: "论文预算费(元)",
          placeholder: "请输入金额",
          type: "switch",
        },
        {
          prop: "f7",
          label: "论文预算费(元)",
          placeholder: "请输入金额",
          type: "checkbox",
          format: "array",
          options: [
            {
              value: "选项1",
              label: "黄金糕",
            },
            {
              value: "选项2",
              label: "双皮奶",
            },
            {
              value: "选项3",
              label: "蚵仔煎",
            },
          ],
        },
        {
          prop: "f8",
          label: "论文预算费(元)",
          placeholder: "请输入金额",
          type: "textarea",
        },
        {
          prop: "f9",
          label: "论文预算费(元)",
          placeholder: "请输入金额",
          type: "number",
        },
        {
          prop: "f10",
          label: "论文预算费(元)",
        },
        {
          prop: "sum",
          label: "预算总额(元)",
          placeholder: "自动计算",
          render: (h, params) => {
            return [<span>4454545</span>];
          },
        },
      ],
    };
  },
};
</script>

<style scoped>
</style>

  

posted @ 2021-08-03 15:37  7c89  阅读(255)  评论(0编辑  收藏  举报