<template> <el-dialog center :title="title" :class="dialogComponent" :visible.sync="visible" :width="width" @close="close" :append-to-body="appendToBody" :close-on-click-modal="closeModal" > <div class="main"> <el-form :rules="rules" :model="form" ref="form" label-position="right" :label-width="labelWidth" @submit.native.prevent > <el-row> <template v-for="(item, index) in formDataSet"> <!-- <el-col v-if="!item.hidden" :span="item.spanCount ? item.spanCount : countLine" :key="item.prop" :class="item.class" > --> <el-form-item :key="index" :label="item.label ? `${item.label}:` : ''" :label-width="item.labelWidth" :prop="item.prop" :rules="item.rules" :class="item.className" :style="item.style" > <!-- 按钮控制 --> <el-button v-if="item.operation" class="operBtn" :type="item.operation.type ? item.operation.type : 'text'" :autofocus="item.autofocus" @click="item.operation.func ? item.operation.func(form) : {}" > {{ item.operation.text ? item.operation.text : "新增" }}</el-button > <!-- 提示 --> <el-tooltip v-if="item.tips" effect="dark" :content="item.tips" placement="top" slot="label" > <span :style="item.tipsStyle">{{ item.label }}:</span> </el-tooltip> <!-- 输入框 input --> <el-input v-if="item.type === 'input'" :type="item.inputType ? item.inputType : ''" :maxlength="item.maxlength" :minlength="item.minlength" :placeholder="item.placeholder" clearable :disabled="item.disabled" v-model="form[item.prop]" @input="item.func ? item.func($event) : {}" :resize="item.resize" :rows="item.rows" :autosize="item.autosize" > <span :slot="item.slot ? item.slot : 'append'" v-if="item.unit" >{{ item.unit }}</span > </el-input> <!-- 数字输入框 --> <div v-if="item.type === 'number'" style="display: inline-table"> <el-input-number :min="item.min" :max="item.max" clearable :precision="item.precision" :controls="item.controls || false" :disabled="item.disabled" v-model="form[item.prop]" :placeholder="item.placeholder" @input="item.func ? item.func($event) : {}" style="display: table-cell" ></el-input-number> <span v-if="item.append" class="el-input-group__append" style="line-height: 28px" >{{ item.append }}</span > </div> <!-- 模糊查询输入 --> <el-autocomplete v-else-if="item.type === 'autocomplete'" popper-class="my-autocomplete" v-model="form[item.prop]" :fetch-suggestions="item.func" :placeholder="item.placeholder" @select="item.selectfun" clearable > <template slot-scope="{ item }"> <div class="name"> {{ item.value }} <span v-if="item.specification" >({{ item.specification }})</span > </div> <span class="description">{{ item.description }}</span> </template> </el-autocomplete> <!-- 选择器 --> <el-select v-else-if="item.type === 'select'" :multiple="item.multiple" :disabled="item.disabled" v-model="form[item.prop]" :placeholder="item.placeholder ? item.placeholder : '请选择'" :filterable="item.filterable ? false : true" clearable :value-key="item.key ? item.key : 'value'" @change="item.func ? item.func($event) : {}" > <el-option v-for="(opt, optIndex) in item.opts" :key="optIndex" :label="opt.label" :value="item.isSelect ? opt.selectValue : opt.value" :disabled="opt.disabled" > <span style="float: left">{{ opt.label }}</span> <span style="float: right; color: #8492a6; font-size: 10px">{{ opt.description }}</span> </el-option> </el-select> <!-- 模糊查询选择 --> <el-select v-else-if="item.type === 'remote'" v-model="form[item.prop]" filterable remote reserve-keyword :multiple="item.multiple ? true : false" :placeholder="item.placeholder" :remote-method="item.remoteFunc" v-el-select-loadmore="loadmore" @change="item.func ? item.func($event) : {}" > <!--禁用all的条件: value有值,并且值不是all--> <el-option :key="'all'" label="全部" value="all" :disabled=" form[item.prop] ? form[item.prop].length > 0 && form[item.prop].indexOf('all') < 0 : false " ></el-option> <!--禁用非all条件: form[item.prop]为all--> <el-option :disabled="form[item.prop] == 'all'" v-for="(opt, optIndex) in item.opts" :key="optIndex" :label="opt.label" :value="item.isSelect ? opt.selectValue : opt.value" ></el-option> </el-select> <!-- 日期 --> <el-date-picker v-else-if="item.type === 'date'" v-model="form[item.prop]" :type="item.dateType ? item.dateType : 'date'" :placeholder="item.placeholder" :picker-options="item.options" :format="item.format" :value-format="item.valueFormat" @change="item.func ? item.func($event) : {}" ></el-date-picker> <!-- 时间 --> <el-time-picker v-else-if="item.type === 'time'" :format="item.format" :value-format="item.valueFormat" v-model="form[item.prop]" :picker-options="item.options" @change="item.func ? item.func($event) : {}" ></el-time-picker> <!-- 开关 --> <el-switch v-else-if="item.type === 'switch'" :disabled="item.disabled" :active-value="item.activeValue || 1" :inactive-value="item.inactiveValue || 0" v-model="form[item.prop]" > </el-switch> <!-- 单选框 --> <el-radio :class="item.class" v-else-if="item.type === 'radio'" v-model="form[item.prop]" v-for="(opt, optIndex) in item.opts" :key="optIndex" :label="opt.value" @change="item.func ? item.func($event) : {}" >{{ opt.label }}</el-radio > <!-- 多选框 --> <el-checkbox-group v-else-if="item.type === 'checkbox'" v-model="form[item.prop]" > <el-checkbox v-for="(opt, optIndex) in item.opts" :key="optIndex" :label="opt.label" ></el-checkbox> </el-checkbox-group> <!-- 级联 --> <el-cascader v-else-if="item.type === 'cascader'" :options="item.list" v-model="form[item.prop]" :clearable="true" :filterable="true" ></el-cascader> <!-- 树形 --> <el-tree v-else-if="item.type === 'tree'" ref="tree" :data="treeList" show-checkbox :node-key="item.nodeKey || 'id'" :props="item.props || defaultProps" ></el-tree> <!-- 导入文件 --> <template v-else-if="item.type === 'import'"> <div class="import-container" @click="handleImport"> <span v-if="form[item.prop]">{{ form[item.prop] }}</span> <span v-else class="wait">{{ item.placeholder }}</span> <i class="el-icon-upload"></i> </div> <input ref="fileInput" type="file" class="import-file" :accept="item.accept" @change="handleFileChange($event)" /> </template> <span v-else-if="item.type === 'text'">{{ form[item.prop] }}</span> </el-form-item> <!-- </el-col> --> </template> </el-row> </el-form> </div> <div slot="footer"> <el-button size="medium" v-if="btnCancel" @click="visible = false" >取 消</el-button > <el-button size="medium" type="primary" :loading="loading" @click="handleConfirm" >{{ confirmText }}</el-button > <slot name="otherButton" :form="form"></slot> </div> </el-dialog> </template> <script> export default { data() { return { loading: false, visible: false, form: {}, defaultProps: { children: "children", label: "name", }, } }, props: { confirmText: { type: String, default: "确 认", }, appendToBody: { type: Boolean, default: false, }, closeModal: { type: Boolean, default: false, }, title: { type: String, default: "系统提示", }, countLine: { // 一行排列几个 default: 24, }, width: { type: String, default: "365px", }, labelWidth: { type: String, default: "100px", }, btnCancel: { type: Boolean, default: true, }, current: Number, formData: { type: Array, }, formEdit: { type: Object, }, rules: { type: Object, }, dialogComponent: { type: String, default: "dialog-component", }, treeList: { type: Array, }, }, directives: { /** 下拉框懒加载 */ "el-select-loadmore": { bind(el, binding) { const SELECTWRAP_DOM = el.querySelector( ".el-select-dropdown .el-select-dropdown__wrap" ) SELECTWRAP_DOM.addEventListener("scroll", function () { const condition = this.scrollHeight - this.scrollTop <= this.clientHeight if (condition) { binding.value() } }) }, }, }, methods: { loadmore() { // this.$emit("loadMore", this.current + 1) }, open() { this.visible = true }, close() { this.loading = false this.visible = false }, handleConfirm() { this.loading = true this.$refs.form.validate((valid) => { if (valid) { if (this.$refs.tree) { const halfChecks = this.$refs.tree[0].getHalfCheckedKeys() const checks = this.$refs.tree[0].getCheckedKeys() this.form.treeList = [...new Set(checks.concat(halfChecks))] } this.$emit("handleConfirm", this.form) } else { this.loading = false } }) }, // 初始化整个表单(可在初始化时赋值) initforms(formEdit) { const form = {} this.formData.forEach((item) => { if (!item.prop || item.hidden) return false if (item.type === "select-input" || item.type === "input-input") { form[item.prop1] = "" form[item.prop2] = "" } else if ( item.type === "checkbox" || item.type === "cascader" || item.multiple ) { form[item.prop] = [] } else if (item.type === "number") { form[item.prop] = undefined } else { form[item.prop] = "" } }) // 树形菜单 if (this.treeList) { this.$nextTick(() => { this.$refs.tree[0].setCheckedKeys([]) const list = (this.formEdit && this.formEdit.treeList) || [] list.forEach((item) => { this.$refs.tree[0].setChecked(item, true) }) }) if (this.formEdit && this.formEdit.imageUrl) { this.imageUrl = this.webDomain + this.formEdit.imageUrl } } if (formEdit) { this.form = Object.assign(form, formEdit) } if (this.formEdit) { this.form = Object.assign(form, this.formEdit) } else { this.form = Object.assign({}, form) } this.loading = false this.$nextTick(() => { if (this.$refs.fileInput && this.$refs.fileInput[0]) { this.$refs.fileInput[0].value = "" } this.$refs.form.clearValidate() }) }, // 给表单部分字段赋值(此时表单已初始化) initFields(obj) { for (const key in obj) { this.form[key] = obj[key] } this.$nextTick(() => { this.$refs.form.clearValidate() }) }, }, watch: { visible() { if (this.visible) { this.initforms() } }, }, computed: { formDataSet() { return this.formData.map((item) => { if ( item.optsFormatter && Object.prototype.toString.call(item.optsFormatter) === "[object Function]" ) { try { item.opts = item.optsFormatter() } catch (error) {} } return { ...item, } }) }, }, } </script> <style lang="scss"> .dialog-component { .el-form-item { // margin-bottom: 15px; } .el-select, .el-input { width: 100%; } .el-input-number .el-input__inner { text-align: left; } .input-with-select { .el-input__suffix { position: relative !important; right: 20px; font-size: 14px; } .el-input__inner { width: 130px; } .el-input--mini .el-input__inner { text-align: center; } } .input-with-input { .el-input-group__prepend { background-color: #ffffff; width: 120px; padding: 0; border: 0; } } .red-background .el-input__inner { background: #c92639; color: #fff; border-color: #c30d23 !important; } .blue-background .el-input__inner { background: #0097ff; color: #fff; border-color: #036eb8 !important; } } </style> <style lang="scss" scoped> .avatar-line { text-align: center; img { width: 120px; } } .my-autocomplete { li { line-height: normal; padding: 7px; .name { text-overflow: ellipsis; overflow: hidden; + .description, span { font-size: 12px; } + .description { color: #b4b4b4; } } .highlighted .description { color: #ddd; } } } .dialog-component .el-input__suffix { position: relative !important; } .el-autocomplete { width: 100%; } .el-row { display: flex; flex-wrap: wrap; } </style>