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>