|
|
@@ -0,0 +1,284 @@
|
|
|
+<template>
|
|
|
+ <el-form :model="formData" class="demo-ruleForm" :ref="refVerification" label-position="left" label-width="120px">
|
|
|
+ <el-col v-for=" (formItems, index) in formItems" v-show="!formItems.notShow" :key="index"
|
|
|
+ :span="formItems.width ? formItems.width : 24">
|
|
|
+ <el-form-item :label="formItems.label" :prop="formItems.prop" :rules="formItems.rules">
|
|
|
+ <!-- inupt输入框 -->
|
|
|
+ <el-input v-if="formItems.input" v-model="formData[formItems.prop]" size="small"
|
|
|
+ :disabled="formItems.disabled" :placeholder="formItems.placeholder"
|
|
|
+ @input="inputINPUT($event, index, formItems.prop)"
|
|
|
+ @change="inputChange($event, index, formItems.prop)" />
|
|
|
+ <!-- textarea输入框 -->
|
|
|
+ <el-input v-if="formItems.textarea" v-model="formData[formItems.prop]" size="small" type="textarea"
|
|
|
+ :rows="formItems.rows" :disabled="formItems.disabled" :placeholder="formItems.placeholder" />
|
|
|
+ <!-- select选择器 -->
|
|
|
+ <el-select v-if="formItems.select" v-model="formData[formItems.prop]" size="small"
|
|
|
+ :disabled="formItems.disabled" :placeholder="formItems.placeholder"
|
|
|
+ @change="selectChange($event, index, formItems.prop)">
|
|
|
+ <el-option v-for="(options, sIndex) in formItems.options" :key="sIndex" :label="options.label"
|
|
|
+ :value="options.value" />
|
|
|
+ </el-select>
|
|
|
+ <!-- select搜索框 -->
|
|
|
+ <el-select v-if="formItems.searchSelect" v-model="formData[formItems.prop]" size="small"
|
|
|
+ :disabled="formItems.disabled" filterable remote reserve-keyword :placeholder="formItems.placeholder"
|
|
|
+ :remote-method="(query) => remoteMethod(query, index, formItems.prop)" :loading="searchSelectLoading"
|
|
|
+ @change="selectChange($event, index, formItems.prop)">
|
|
|
+ <el-option v-for="(item, ssIndex) in formItems.options" :key="ssIndex" :label="item.label"
|
|
|
+ :value="item.value" />
|
|
|
+ </el-select>
|
|
|
+ <!-- 年月日时分秒选择器 -->
|
|
|
+ <el-date-picker v-if="formItems.dateTime" v-model="formData[formItems.prop]"
|
|
|
+ value-format="yyyy-MM-dd HH:mm:ss" type="datetime" size="small" :disabled="formItems.disabled"
|
|
|
+ :placeholder="formItems.placeholder" />
|
|
|
+ <!-- 年月日时分秒,开始和结束时间 -->
|
|
|
+ <el-date-picker v-if="formItems.dateTimeRange" v-model="formData[formItems.prop]"
|
|
|
+ value-format="yyyy-MM-dd HH:mm:ss" format="yyyy-MM-dd HH:mm:ss" size="small" type="datetimerange"
|
|
|
+ :disabled="formItems.disabled" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" />
|
|
|
+ <!-- 时分秒选择器 -->
|
|
|
+ <el-time-picker v-if="formItems.timePicker" v-model="formData[formItems.prop]" value-format="HH:mm:ss"
|
|
|
+ format="HH:mm:ss" size="small" :disabled="formItems.disabled" :placeholder="formItems.placeholder"
|
|
|
+ :picker-options="formItems.options" />
|
|
|
+ <!-- 时分秒选择器,开始和结束时间 -->
|
|
|
+ <el-time-picker v-if="formItems.timePickerIsRange" v-model="formData[formItems.prop]"
|
|
|
+ value-format="HH:mm:ss" format="HH:mm:ss" is-range size="small" :disabled="formItems.disabled"
|
|
|
+ range-separator="至" start-placeholder="开始时间" end-placeholder="结束时间" placeholder="选择时间范围" />
|
|
|
+ <!-- 年月日选择器 -->
|
|
|
+ <el-date-picker v-if="formItems.datePicker" v-model="formData[formItems.prop]" value-format="yyyy-MM-dd"
|
|
|
+ size="small" :disabled="formItems.disabled" :placeholder="formItems.placeholder" />
|
|
|
+ <!-- 年月日选择器,开始和介绍年月日 -->
|
|
|
+ <el-date-picker v-if="formItems.datePickerIsRange" v-model="formData[formItems.prop]"
|
|
|
+ value-format="yyyy-MM-dd" type="daterange" size="small" :disabled="formItems.disabled"
|
|
|
+ :placeholder="formItems.placeholder" range-separator="至" start-placeholder="开始日期"
|
|
|
+ end-placeholder="结束日期" />
|
|
|
+ <!-- switch开关 -->
|
|
|
+ <el-switch v-if="formItems.switch" v-model="formData[formItems.prop]" size="small"
|
|
|
+ :disabled="formItems.disabled" @change="formSwitchChange($event, index, formItems.prop)" />
|
|
|
+ <!-- radio单选框 -->
|
|
|
+ <el-radio-group v-if="formItems.radio" v-model="formData[formItems.prop]" :disabled="formItems.disabled">
|
|
|
+ <el-radio v-for="(options, rIndex) in formItems.options" :key="rIndex" :label="options.label"
|
|
|
+ :value="options.value" />
|
|
|
+ </el-radio-group>
|
|
|
+ <!-- checkbox复选框 -->
|
|
|
+ <el-checkbox-group v-if="formItems.checkbox" v-model="formData[formItems.prop]"
|
|
|
+ :disabled="formItems.disabled">
|
|
|
+ <el-checkbox v-for="options in formItems.options" :key="options.value" :label="options.label" />
|
|
|
+ </el-checkbox-group>
|
|
|
+
|
|
|
+ <!-- 文件上传 -->
|
|
|
+ <!-- 如果对象有值就回显,没有值就为空 -->
|
|
|
+ <el-upload v-if="formItems.upload" :ref="formItems.prop"
|
|
|
+ :accept="formItems.accept ? formItems.accept : 'PNG,JPEG'"
|
|
|
+ :file-list="formData[formItems.prop] ? formData[formItems.prop] : []"
|
|
|
+ :action="`${uploadUrl}${formItems.uploadObj.fileType ? formItems.uploadObj.fileType : ''}`"
|
|
|
+ :limit="formItems.uploadObj.limit"
|
|
|
+ :class="{ 'hide': formItems.uploadObj.hideUpload || formData[formItems.prop].length == formItems.uploadObj.limit }"
|
|
|
+ :on-preview="handlePictureCardPreview"
|
|
|
+ :on-remove="(file, fileList) => handleRemove(file, fileList, formItems.uploadObj.limit, formItems.prop, index)"
|
|
|
+ :on-success="(response, file, fileList) => uploadSuccess(response, file, fileList, formItems.uploadObj.limit, formItems.prop, index)"
|
|
|
+ list-type="picture-card" :auto-upload="true">
|
|
|
+ <i slot="default" class="el-icon-plus" />
|
|
|
+ </el-upload>
|
|
|
+ <el-dialog v-if="formItems.upload" :visible.sync="dialogVisible" :append-to-body="true" width="40%">
|
|
|
+ <img width="100%" :src="dialogImageUrl" alt="">
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <!-- 按钮 -->
|
|
|
+ <el-button v-if="formItems.button" size="small" :disabled="formItems.disabled" :loading="formItems.loading"
|
|
|
+ :type="formItems.buttonType || 'primary'" @click="buttonClick(formItems.prop, index)">
|
|
|
+ {{ formItems.placeholder }}
|
|
|
+ </el-button>
|
|
|
+ <!-- text展示 -->
|
|
|
+ <span v-if="formItems.text" v-text="formData[formItems.prop]" />
|
|
|
+ <!-- 计量单位 -->
|
|
|
+ <span v-if="formItems.unit" class="left10">{{ formItems.unit }}</span>
|
|
|
+
|
|
|
+ <!-- 高德地图 -->
|
|
|
+ <!-- <div class="amap_div" v-if="formItems.aMap">
|
|
|
+ <el-input size="small" v-model="formData[formItems.prop]" @input="aMapInput($event,formItems.prop)"></el-input>
|
|
|
+ <ul v-show="searchShow==formItems.prop" class="sreach_ul">
|
|
|
+ <li @click="selectVal(sval,formItems.prop,index)" v-for=" (sval, index) in setSearchVal" :key="index">{{sval.name}}
|
|
|
+ <span style="color:#8591A6 ;font-size: 12px;">{{sval.district}}</span>
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+ <aMap :ref="'aMap'+formItems.prop" :aMapId="'aMapId'+formItems.prop" :location="formData[formItems.prop+'location']" @cbSearch="cbSearch($event,formItems.prop)"></aMap>
|
|
|
+ </div> -->
|
|
|
+
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-form>
|
|
|
+</template>
|
|
|
+<script>
|
|
|
+export default {
|
|
|
+ name: "MyForm",
|
|
|
+ model: {
|
|
|
+ prop: 'modelValue',
|
|
|
+ event: 'update:modelValue',
|
|
|
+ },
|
|
|
+ props: {
|
|
|
+ modelValue: Object,
|
|
|
+ formItems: {
|
|
|
+ type: Array,
|
|
|
+ required: true
|
|
|
+ },
|
|
|
+ searchSelectOptionsCb: {
|
|
|
+ type: Array,
|
|
|
+ },
|
|
|
+ refVerification: {
|
|
|
+ type:String,
|
|
|
+ }
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ let uploadFileUrl = this.$store.state.user.uploadFileUrl;
|
|
|
+ return {
|
|
|
+ formData: {},
|
|
|
+ uploadUrl: uploadFileUrl,
|
|
|
+ dialogImageUrl: '',
|
|
|
+ searchSelectLoading: false,
|
|
|
+ dialogVisible: false,
|
|
|
+ disabled: false,
|
|
|
+ searchShow: '', //高德地图input收索联想
|
|
|
+ setSearchVal: [], //高德地图赋值搜索内容
|
|
|
+ };
|
|
|
+ },
|
|
|
+ emits: ['update:modelValue'],
|
|
|
+ created() {
|
|
|
+ // 表单初始化
|
|
|
+ for (let item of this.formItems) {
|
|
|
+ // 注意:这里要进行响应式的设置,否则表单控件会无法输入的
|
|
|
+ this.$set(this.formData, item.prop, '')
|
|
|
+ }
|
|
|
+ this.$emit('update:modelValue', this.formData)
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ formData: {
|
|
|
+ handler(newValue) {
|
|
|
+ },
|
|
|
+ deep: true,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ //select变化调用
|
|
|
+ selectChange(value, index, prop) {
|
|
|
+ this.$emit('selectChange', value, index, prop);
|
|
|
+ },
|
|
|
+ // input的input事件
|
|
|
+ inputINPUT(value, index, prop) {
|
|
|
+ this.$emit('inputINPUT', value, index, prop);
|
|
|
+ },
|
|
|
+ // input的change事件
|
|
|
+ inputChange(value, index, prop) {
|
|
|
+ this.$emit('inputChange', value, index, prop);
|
|
|
+ },
|
|
|
+ // 搜索类型select搜索
|
|
|
+ remoteMethod(query, index, prop) {
|
|
|
+ if (query) {
|
|
|
+ this.searchSelectLoading = true;
|
|
|
+ this.$emit('querySelectValue', query, index, prop);
|
|
|
+ setTimeout(() => {
|
|
|
+ this.formItems[index].options = this.searchSelectOptionsCb;
|
|
|
+ this.searchSelectLoading = false;
|
|
|
+ }, 500)
|
|
|
+ } else {
|
|
|
+ this.searchSelectOptios = [];
|
|
|
+ }
|
|
|
+ },
|
|
|
+ //switch变化
|
|
|
+ formSwitchChange(val, index, prop) {
|
|
|
+ this.$emit("formSwitchChange", val, index, prop);
|
|
|
+ },
|
|
|
+ //按钮点击事件
|
|
|
+ buttonClick(prop, index) {
|
|
|
+ this.$emit("buttonClick", prop, index);
|
|
|
+ },
|
|
|
+
|
|
|
+ //文件上传成功回调
|
|
|
+ uploadSuccess(response, file, fileList, limit, prop, index) {
|
|
|
+ this.formItems[index].uploadObj.hideUpload = fileList.length == limit;//文件列表变化后判断当前文件列表长度是否等于限制长度。目的,当长度相等时隐藏文件上传按钮
|
|
|
+ this.pushUpload(file, fileList, limit, prop);
|
|
|
+ },
|
|
|
+ //文件删除
|
|
|
+ handleRemove(file, fileList, limit, prop, index) {
|
|
|
+ this.formItems[index].uploadObj.hideUpload = fileList.length == limit;//文件删除后判断当前文件列表长度是否等于限制长度。目的,当长度相等时隐藏文件上传按钮
|
|
|
+ this.pushUpload(file, fileList, limit, prop);
|
|
|
+ },
|
|
|
+ // 文件预览
|
|
|
+ handlePictureCardPreview(file) {
|
|
|
+ this.dialogImageUrl = file.url;
|
|
|
+ this.dialogVisible = true;
|
|
|
+ },
|
|
|
+
|
|
|
+ //提交时验证表单,直接在父级调用
|
|
|
+ submitForm() {
|
|
|
+ let formValidate = Boolean;
|
|
|
+ this.$refs.refVerification.validate((valid) => {
|
|
|
+ if (valid) {
|
|
|
+ formValidate = true;
|
|
|
+ } else {
|
|
|
+ this.$message.warning("请把信息填写完整!");
|
|
|
+ formValidate = false;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return formValidate;
|
|
|
+ },
|
|
|
+ /* 清空表单
|
|
|
+ 逻辑:
|
|
|
+ 1 、如果要清空文件上传列表,要传入要清空的upload的字段名,假如多个upload用for循环,调用清空方法!
|
|
|
+ 2、清空upload之后,还要把upload上传框展示出来,通过字段名比对,获取到在formItems中的下标,通过下标操作对象属性,进行展示
|
|
|
+ */
|
|
|
+ resetForm(uploadArr) {
|
|
|
+ this.$refs.ruleForm.resetFields();
|
|
|
+ if (uploadArr) {
|
|
|
+ for (let i = 0; i < uploadArr.length; i++) {
|
|
|
+ this.$refs[uploadArr[i]][0].clearFiles();
|
|
|
+ let index = this.formItems.findIndex(item => item.prop == uploadArr[i]);
|
|
|
+ this.formItems[index].uploadObj.hideUpload = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 单个字段验证
|
|
|
+ validateFieldProp(prop) {
|
|
|
+ let formValidate = Boolean;
|
|
|
+ this.$refs.ruleForm.validateField(prop, valid => {
|
|
|
+ if (!valid) {
|
|
|
+ formValidate = true;
|
|
|
+ } else {
|
|
|
+ formValidate = false;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return formValidate;
|
|
|
+ },
|
|
|
+ // 对文件上传,删除进行赋值,调用form验证
|
|
|
+ pushUpload(file, fileList, limit, prop) {
|
|
|
+ if (fileList.length > 0) {
|
|
|
+ this.formData[prop] = fileList;
|
|
|
+ } else {
|
|
|
+ // 表示没有数据,把字段置空
|
|
|
+ this.formData[prop] = "";
|
|
|
+ }
|
|
|
+ this.$refs.ruleForm.validateField(prop);//调用验证form表单的文件上传
|
|
|
+ },
|
|
|
+ //地图input的input事件
|
|
|
+ aMapInput(value, prop) {
|
|
|
+ this.$refs[`aMap${prop}`][0].getSearch(value);
|
|
|
+ },
|
|
|
+ //子组件返回地图搜索值
|
|
|
+ cbSearch(val, prop) {
|
|
|
+ this.setSearchVal = val.tips; //子组件
|
|
|
+ this.searchShow = prop; //显示input输入联想
|
|
|
+ },
|
|
|
+ //选中地图值
|
|
|
+ selectVal(val, prop, index) {
|
|
|
+ // 赋值的时候,拿到键,及formItems的下标,进行赋值
|
|
|
+ this.formData[prop] = val.name; //input输入框赋值
|
|
|
+ this.formData.district = val.district; //传入省市区
|
|
|
+ let lngLat = {
|
|
|
+ lng: val.location.lng,
|
|
|
+ lat: val.location.lat
|
|
|
+ };
|
|
|
+ this.formData[`${prop}location`] = lngLat;
|
|
|
+ this.searchShow = ''; //隐藏input输入联想
|
|
|
+ },
|
|
|
+
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|