<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>