• liang's avatar
    init · dad95e78
    liang authored
    dad95e78
index.vue 8.86 KB
<template>
  <el-form
    ref="form"
    :model="form"
    :disabled="options.disabled"
    :label-position="options.labelPosition || 'left'"
    :label-width="(options.labelWidth || 100) + 'px'"
    :size="size"
    @submit.native.prevent="handleConfirm()"
    :style="formStyle"
    class="avue-form-self"
  >
    <template v-if="options.column && options.column.length > 0">
      <form-content
        ref="form-content"
        :form="form"
        :columns="{ column: options.column }"
        :options="options"
        :is-show-important="isShowImportant"
      ></form-content>
    </template>
    <template v-if="options.group && options.group.length > 0">
      <el-tabs v-if="options.tabs" v-model="activeName" type="card">
        <el-tab-pane
          :label="g.label || `标签${gIndex + 1}`"
          :name="`${gIndex}`"
          v-for="(g, gIndex) in options.group"
          :key="gIndex"
        >
          <form-content
            ref="form-content"
            :form="form"
            :columns="g"
            :options="options"
            :is-show-important="isShowImportant"
          ></form-content>
        </el-tab-pane>
      </el-tabs>

      <el-collapse v-model="collapseNames" v-else>
        <template v-for="(g, gIndex) in options.group">
          <el-collapse-item
            :title="g.label"
            :name="g.prop"
            :key="gIndex"
            v-show="g.display"
            :disabled="!g.arrow"
          >
            <form-content
              v-if="collapseNames.includes(g.prop)"
              ref="form-content"
              :form="form"
              :columns="g"
              :options="options"
              :is-show-important="isShowImportant"
            ></form-content>
          </el-collapse-item>
        </template>
      </el-collapse>
    </template>
    <div class="form-footer">
      <template v-if="options.menuBtn">
        <template v-if="options.submitBtn">
          <el-button
            type="primary"
            icon="el-icon-check"
            @click="handleConfirm"
            :loading="loading"
            size="large"
          >
            {{ options.submitText || "提交" }}
          </el-button>
        </template>
        <template v-if="options.emptyBtn">
          <el-button
            plain
            icon="el-icon-delete "
            size="large"
            @click="resetForm(true)"
          >
            {{ options.emptyText || "清空" }}
          </el-button>
        </template>
      </template>
      <template v-if="nextTabBtnShow">
        <el-form style="display: inline-block; margin-left: 10px">
          <el-button
            plain
            icon="el-icon-caret-right"
            size="large"
            @click="nextTab"
          >
            {{ options.nextTabText || "下一页" }}
          </el-button>
        </el-form>
      </template>
    </div>
  </el-form>
</template>

<script>
/**
 * @description 自定义表单
 */
import handleFormData from "./handleFormData"
import FormContent from "./FormContent"
import { isObject } from "@/utils/validate"
export default {
  name: "CustomForm",
  components: { FormContent },
  props: {
    options: {  //配置 数据
      type: Object,
      default: () => {
        return {}
      },
    },
    size: { type: String, default: "small" },
    formStyle: { type: Object },
    formEdit: {
      type: Object,
      default: () => {
        return {}
      },
    },
  },
  provide() {
    const vwForm = {}
    for (const k in this.options) {
      if (k !== "column" && k !== "group") {
        vwForm[k] = this.options[k]
      }
    }

    return {
      vwForm,
    }
  },
  mixins: [handleFormData],
  data() {
    return {
      collapseNames: [],
      activeName: "0",
      loading: false,
      isShowImportant: false,
      form: {},
    }
  },

  methods: {
    nextTab() {
      const tabsLen = this.options.group.length
      let active = Number(this.activeName)
      let next = ++active
      if (next >= tabsLen) next = 0
      this.activeName = String(next)
      this.$emit("scrollTop")
    },

    imFieldChange(val = false) {
      this.isShowImportant = val
    },
    // 查询
    submit() {
      this.$emit("submit", this.form)
    },

    // 重置
    resetForm(flag) {
      if (flag) {
        this.$confirm("是否清空数据?", "提示", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning",
        })
          .then(() => {
            this.$message({
              type: "success",
              message: "清空成功!",
            })
            this.$refs.form.resetFields()
          })
          .catch(() => {})
      } else {
        if (this.$refs.form) this.$refs.form.resetFields()
      }
    },

    validate(func) {
      this.$refs.form.validate((valid) => {
        func(valid, () => {})
      })
    },

    handleConfirm() {
      this.loading = true
      this.$refs.form.validate((valid) => {
        if (valid) {
          const data = {}
          const form = this.deepClone(this.form)
          Object.keys(form).forEach((k) => {
            if (form[k] === undefined) {
              data[k] = ""
              return false
            }
            if (k === "YZZKJC") {
              // 牙周表格
              data[k] = JSON.stringify(form[k])
            } else if (
              Array.isArray(form[k]) &&
              form[k][0] &&
              isObject(form[k][0])
            ) {
              // 子表单 去除前端添加的显隐辅助数据($_)和 删除按钮辅助数据(showDelBtn)
              data[k] = form[k].map((item) => {
                for (let key in item) {
                  if (["$_keyField", "$_hidden", "showDelBtn"].includes(key))
                    delete item[key]
                }
                return item
              })
            } else {
              data[k] = form[k]
            }
          })
          this.$emit("handleConfirm", data, () => {
            this.loading = false
          })
        } else {
          this.loading = false
        }
      })
    },

    // 表单赋值
    initforms() {
      const form = {}
      const collapseNames = []
      const initFunc = (column = []) => {
        if (column.length > 0) {
          column.forEach((item) => {
            if (!item.prop) return false

            if (
              item.type === "dynamic" ||
              item.type === "checkbox" ||
              item.type === "cascader" ||
              item.type === "upload" ||
              (item.type === "select" && item.multiple)
            ) {
              form[item.prop] = []
            } else if (
              item.type === "dental-tab" ||
              item.type === "dental-tab-tj"
            ) {
              form[item.prop] = {}
            } else if (item.type === "group") {
              initFunc(item.children.column)
            } else if (item.type !== "title") {
              form[item.prop] = item.value ? item.value : ""
            }
          })
        }
      }
      const { group, column } = this.options
      initFunc(column)
      group &&
        group.forEach((g) => {
          if (g.collapse) {
            collapseNames.push(g.prop)
          }
          initFunc(g.column)
        })
      this.collapseNames = collapseNames
      this.form = form
      this.loading = false
      this.$nextTick(() => {
        // 子组件数据初始化完成后
        setTimeout(() => {
          this.initfields(this.formEdit)
        }, 0)
        if (this.$refs.form && this.$refs.form.clearValidate) {
          this.$refs.form.clearValidate()
        }
      })
    },
    // 绑定部分值(此时表单已渲染)
    initfields(obj) {
      for (let k in obj) {
        if (this.form.hasOwnProperty(k)) {
          this.form[k] = obj[k]
        }
      }
    },
  },
  computed: {
    nextTabBtnShow() {
      const { nextTabBtn, tabs, group } = this.options
      return tabs && group && group.length > 1 && nextTabBtn
    },
  },
  watch: {
    formEdit: {
      handler() {
        this.initfields(this.formEdit)
      },
    },
  },
  created() {
    this.initforms()
    this.$nextTick(() => {
      // this.setformWatch(this.options, "form")
    })
  },
}
</script>

<style lang="scss" scoped>
.avue-form-self {
  padding: 0 11px;

  ::v-deep .el-collapse {
    border: none;

    .el-collapse-item__header.is-active {
      border-bottom-color: #ebeef5;
    }
    .el-collapse-item__wrap {
      border: none;
      padding: 10px;
      &:hover {
        background-color: #ecf8ff;
        outline: 1px dashed #ccc;
      }
    }
    .el-collapse-item__header {
      font-size: 16px;
      font-weight: 600;
      color: rgba(0, 0, 0, 0.85);
      height: 50px;
      line-height: 50px;
    }
  }
  .form-footer {
    margin-top: 20px;
    text-align: center;
  }
}
::v-deep .el-col {
}
::v-deep .el-radio__input.is-disabled .el-radio__inner {
  // background-color: $base-color-default;
  // border-color: $base-color-default;
}
</style>