<template> <el-form ref="form" :model="form" inline-message :disabled="options.disabled" :label-position="options.labelPosition || 'left'" :label-width="(options.labelWidth || 100) + 'px'" :size="size" :style="formStyle" class="avue-form-self" @submit.native.prevent="handleConfirm()" > <template v-if="options.column && options.column.length > 0"> <form-content ref="formContent" :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 v-for="(g, gIndex) in options.group" :key="gIndex" :label="g.label || `标签${gIndex + 1}`" :name="`${gIndex}`" > <form-content ref="formContent" :form="form" :columns="g" :options="options" :is-show-important="isShowImportant" ></form-content> </el-tab-pane> </el-tabs> <!-- 表单的折叠组件 --> <el-collapse v-else v-model="collapseNames"> <template v-for="(g, gIndex) in options.group"> <el-collapse-item v-show="g.display" :key="gIndex" :name="g.prop" :disabled="true" :class="g.prop == '1669858313508_15760' ? 'otherItemClass' : ''" > <template slot="title"> {{ g.label }} <span v-if="g.label == '二、排除标准'" class="noCol"> {{ errorText }} </span> </template> <form-content v-if="collapseNames.includes(g.prop)" ref="formContent" :form="form" :columns="g" :options="options" :is-show-important="isShowImportant" @showError="showError" ></form-content> </el-collapse-item> </template> </el-collapse> </template> <div v-if="!options.closeBtn" class="form-footer"> <template v-if="options.menuBtn"> <template v-if="options.prevBtn"> <el-button type="primary" :loading="loading" size="large" :disabled="disabled" @click="onPrev" >上一步</el-button > </template> <!-- 下一步按钮 --> <template v-if="options.submitBtn"> <el-button type="primary" :icon="options.submitText == '提交' ? 'el-icon-check' : ''" :loading="loading" size="large" :disabled="disabled" @click="handleConfirm" >{{ 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 }, mixins: [handleFormData], props: { options: { //配置 数据 type: Object, default: () => { return {} }, }, size: { type: String, default: "small" }, formStyle: { type: Object }, formEdit: { type: Object, default: () => { return {} }, }, }, provide() { return { vwForm: () => { const vwForm = {} for (const k in this.options) { if (k !== "column" && k !== "group") { vwForm[k] = this.options[k] } } return vwForm }, // formId: "", } }, data() { return { collapseNames: [], activeName: "0", loading: false, isShowImportant: false, form: {}, errorText: "", disabled: false, } }, computed: { nextTabBtnShow() { const { nextTabBtn, tabs, group } = this.options return tabs && group && group.length > 1 && nextTabBtn }, }, watch: { formEdit: { handler() { // console.log("configforms:", this.formEdit) this.initfields(this.formEdit) }, }, }, created() { this.initforms() this.$nextTick(() => { // this.setformWatch(this.options, "form") }) }, mounted() { // 处理computeIndex let domArr = document.querySelectorAll(".computeIndex") for (let i = 0; i < domArr.length; i++) { domArr[i].style.height = "54px" domArr[i].innerHTML = "" if ((domArr.length - 1) / i == 2) { domArr[i].innerHTML = "6" } if (i == domArr.length - 1) { domArr[i].style.height = "53px" } } }, methods: { clearAge() { // 去除年龄文本 for (let i = 0; i < this.$refs.formContent.length; i++) { this.$refs.formContent[i].clearAge() } }, // 显示不符合筛查条件 showError(data) { if (data) { this.disabled = true this.errorText = "不符合筛查条件" } else { this.disabled = false this.errorText = "" } }, nextTab() { this.initforms() 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") console.log(this.activeName) }, 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, () => {}) }) }, onPrev() { this.$emit("onPrev", () => { // 完成之后的回调 this.loading = false }) }, // 临时保存 temporarySave() { //? 只传数据 获取当前步数,如果个人信息已经提交可以临时保存 // 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("temporaryConfirm", data, () => { // 完成之后的回调 this.loading = false }) // } else { // this.loading = false // } // }) }, 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] // } } }, }, } </script> <style lang="scss" scoped> .avue-form-self { padding: 0 11px; ::v-deep .el-collapse { border: none; .el-collapse-item { &:nth-child(1) { border-top: 1px solid #cccccc; } } .el-collapse-item__content { padding-bottom: 0px; } .el-collapse-item__header { border-radius: 4px; background: #fafafa; padding-left: 20px; border: 1px solid #cccccc; border-bottom-color: #ccc; border-top: 0px; font-size: 14px; font-family: AlibabaPuHuiTiM; color: #333333; } .el-collapse-item__wrap { border: none; padding: 10px; border-left: 1px solid #cccccc; border-right: 1px solid #cccccc; // border-bottom: 1px solid #cccccc !important; padding: 0px; // &: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 { // position: absolute; // left: 50%; // transform: translateX(-50%); // bottom: -50px; margin-top: 20px; margin-bottom: 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; } .noCol { font-size: 12px; margin-left: 12px; font-family: AlibabaPuHuiTiR; color: #ff4d4f; } .otherItemClass { ::v-deep { .row24:not(:last-child) { border-left: 0px; } .row24:last-child { border-left: 1px solid #cccccc; } } } ::v-deep .el-collapse-item.is-disabled .el-collapse-item__header { // color: #bbb; cursor: default; } </style>