vue基于elementUI的form表单进行二次封装

<template>
    <div>
        <el-form class="form" ref="refForm" :model="searchData" :rules="rules"  :size="size"  :label-width="labelWidth" :hide-required-asterisk="isShowRequired" :width="width">
            <el-form-item v-for='item in searchForm' :label="item.label" :key='item.prop' :prop="item.prop" class="formItem">
                <!-- 输入框 -->
                <el-input v-if="item.type==='Input'"  v-model="searchData[item.prop]"  size="mini"  :style="{width:item.width}" :placeholder="item.placeholder"></el-input>
                <!-- 下拉框 -->
                <el-select v-if="item.type==='Select'" v-model="searchData[item.prop]" size="mini" @change="item.change(searchData[item.prop])"  :style="{width:item.width}">
                    <el-option v-for="op in item.options" :label="op.label" :value="op.value" :key="op.value"></el-option>
                </el-select>
                <!-- 单选 -->
                <el-radio-group v-if="item.type==='Radio'" v-model="searchData[item.prop]">
                    <el-radio v-for="ra in item.radios" :label="ra.value" :key="ra.value">{{ra.label}}</el-radio>
                </el-radio-group>
                <!-- 单选按钮 -->
                <el-radio-group v-if="item.type==='RadioButton'" v-model="searchData[item.prop]" @change="item.change && item.change(searchData[item.prop])">
                    <el-radio-button v-for="ra in item.radios" :label="ra.value" :key="ra.value">{{ra.label}}</el-radio-button>
                </el-radio-group>
                <!-- 复选框 -->
                <el-checkbox-group v-if="item.type==='Checkbox'" v-model="searchData[item.prop]" >
                    <el-checkbox v-for="ch in item.checkboxs" :label="ch.value" :key="ch.value">{{ch.label}}</el-checkbox>
                </el-checkbox-group>
                <!-- 日期 -->
                <el-date-picker v-if="item.type==='Date'" v-model="searchData[item.prop]"></el-date-picker>
                <!-- 时间 -->
                <el-time-select v-if="item.type==='Time'" v-model="searchData[item.prop]"></el-time-select>
                <!-- 日期时间 -->
                <el-date-picker v-if="item.type==='DateTime'" type='datetime' v-model="searchData[item.prop]" :disabled="item.disable && item.disable(searchData[item.prop])"></el-date-picker>
                 <!-- 日期范围 -->
                <el-date-picker v-if="item.type==='datetimerange'" type='datetimerange' v-model="searchData[item.prop]"  range-separator="至"  start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
                <!-- 滑块 -->
                <el-slider v-if="item.type==='Slider'" v-model="searchData[item.prop]"></el-slider>
                <!-- 开关 -->
                <el-switch v-if="item.type==='Switch'" v-model="searchData[item.prop]" ></el-switch>
                <!-- 上传照片 -->
                <el-upload
                    v-if="item.type==='upload'"
                    ref="upload"
                    :multiple="true"
                    :action="action"
                    list-type="picture-card"
                    :on-preview="handlePictureCardPreview"
                    :on-exceed="onExceedLimit"
                    :http-request="handleSuccess"
                    :file-list="fileList"
                    accept=".JPG,.png,.GIF"
                    :limit="limit"
                >
                    <i class="el-icon-plus"></i>
                </el-upload>
                <el-dialog :visible.sync="dialogVisible">
                  <img width="100%" :src="dialogImageUrl" alt="">
                </el-dialog>
            </el-form-item>
            <!-- 按钮 -->
            <div v-if='isHandle'>
                <el-form-item v-for='(item , index) in searchHandle' :key="index">
                    <el-button :type="item.type" :size="item.size || size" @click='item.handle()'>{{item.label}}</el-button>
                </el-form-item>
            </div>
    </el-form>
    </div>
</template>

<script>
export default {
    props: {
        isHandle:{
            type:Boolean,
            default:true
        },
        labelWidth:{
            type:String,
            default:'80px'
        },
        width:{
            type:String,
            default:'200px'
        },
        size:{
            type:String,
            default:'mini'
        },
        rules:{
            type:Object,
            default:function(){
				return {};
			}
        },
        searchForm:{
            type:Array, 
            default:[]
        },
        searchHandle:{
            type:Array,
            default:()=>[]
        },
        searchData:{
            type:Object,
            default:function(){
				return {};
			}
        },
        limit:{
            type:Number
        },
        action: String,
        imgList: String,
        isShowRequired:{
            type:Boolean,
            default:true
        }
    },
    mounted() {
        console.log(this.imgList)
    },
    watch: {
        imgList: {
            handler(newVal, oldVal) {
                console.log(newVal, oldVal)
                this.fileList = []
                this.fileList.push({url: this.imgList})
            },
            deep: true
        }
    },
    data() {
        return {
            fileList: [],
            dialogImageUrl: "",
            dialogVisible: false
        }
    },
    methods: {
        handleSuccess(file) {
            this.$emit('uploadImg', file)
        },
        onExceedLimit(file) {
            this.$emit('onExceedLimits', file)
        },
        handlePictureCardPreview(file) {
            this.dialogImageUrl = file.url
            this.dialogVisible = true
        },
    }
}
</script>

<style lang="less" scoped>
.form {
  width: 100%;
  padding: 0 20px;  
}
</style>

使用

<template>
  <div class="content-page">
    <div class="tab-content">
      <div class="ces-search">
        <elForm 
          ref="refForm" 
          :action="action"
          labelWidth="130px" 
          :searchForm="searchForm" 
          width="280px" 
          :searchData="searchData" 
          :searchHandle="searchHandle" 
          :isHandle="true" 
          :limit="limit"
          @uploadImg="uploadImg"
          @onExceedLimits="onExceedLimits"
          :imgList="searchData.picture"
          :rules="rules">
        </elForm>
      </div>
    </div>
  </div>
</template>

<script>
import elForm from '@/components/elForm'
import { uploadFile } from "@/api/index"
export default {
  components: {
    elForm
  },
  data() {
    let typeList = [
      { label: "批发", value: 1 },
      { label: "零售", value: 2 },
      { label: "餐饮", value: 3 },
    ]
    let statusList = [
      { label: "上线", value: 1 },
      { label: "待上线", value: 2 },
      { label: "下线", value: 3 },
    ]
    return {
      searchData: {
        projectName: "",
        introduce: "",
        Switch: false,
        type: "",
        status: 1,
        status1: 1,
        status2: [1, 2],
        date: "",
        time: "",
        dateTime: "",
        dateTimes: "",
        slider: 10,
        picture: ""
      },
      limit: 1,
      action: "/ImageServer/YmUpload_image",
      searchForm: [
        { label: '项目名称', prop: "projectName", type: "Input", placeholder:'请输入项目名称...', width: "320px" },
        { label: '项目描述', prop: "introduce", type: "Input", placeholder:'请输入项目描述...', width: "320px" },
        { label: '是否有营业', prop: "state", type: "Switch" },
        { label: '项目类型', prop: "type", type: "Select", placeholder:'请选择项目类型...', width: "320px", options: typeList, change: this.typeChange },
        { label: '项目状态', prop: "status", type: "Radio", radios: statusList},
        { label: '项目状态', prop: "status1", type: "RadioButton", radios: statusList},
        { label: '项目状态', prop: "status2", type: "Checkbox", checkboxs: statusList},
        { label: '日期', prop: "date", type: "Date", placeholder:'请选择日期...', width: "320px" },
        { label: '时间', prop: "time", type: "Time", placeholder:'请选择时间...', width: "320px" },
        { label: '日期时间', prop: "dateTime", type: "DateTime", placeholder:'请选择日期时间...', width: "320px" },
        { label: '日期范围', prop: "dateTimes", type: "datetimerange", placeholder:'请选择日期范围...', width: "320px" },
        { label: '进度', prop: "slider", type: "Slider"},
        { label: '照片', prop: "picture", type: "upload"},
      ],
      searchHandle:[ //查询和重置按钮
        { label:'保存', type:'primary', size: "small", handle:this.save }
      ],
      rules: {
        projectName: [ { required: true, message: "请输入项目名称...", trigger: "blur" } ],
        introduce: [ { required: true, message: "请输入项目描述...", trigger: "blur" } ],
        type: [{ required: true, message: "请选择项目类型...", trigger: "change" }],
        state: [{ required: true, message: "是否有营业...", trigger: "change" }],
        status: [{ required: true, message: "请选择项目状态...", trigger: "change" }],
        status1: [{ required: true, message: "请选择项目状态...", trigger: "change" }],
        status2: [{ required: true, message: "请选择项目状态...", trigger: "change" }],
        date: [{ required: true, message: "请选择日期...", trigger: "change" }],
        time: [{ required: true, message: "请选择时间...", trigger: "change" }],
        dateTime: [{ required: true, message: "请选择日期时间...", trigger: "change" }],
        dateTimes: [{ required: true, message: "请选择日期范围...", trigger: "change" }],
      }
    }
  },
  mounted() {
    
  },
  props: ['imgList'],
  methods: {
    save() {
      console.log(this.searchData, "保存")
      console.log(this.$refs.refForm, "@111")
      this.$refs.refForm.$children[0].validate((valid) => {
        if (valid) {
          console.log('success submit!!');
        } else {
          console.log('error submit!!');
          return false;
        }
      })
    },
    uploadImg(file) {
      console.log(file)
      let imgUploadForm = new FormData();
      imgUploadForm.append("file", file.file);
      uploadFile(imgUploadForm).then((res) => {
        this.searchData.picture = res.fileUrl
      });
    },
    onExceedLimits(file) {
      if (file.length >= 1) {
        this.$notify({
          title: "警告",
          message: "上传失败,一次只能上传1张图片哦~",
          type: "warning",
          duration: 2000,
        });
      }
    },
    typeChange(val) {
      console.log(val)
    }
  }
}
</script>

<style lang="less" scoped>
.content-page {
  .tab-content {
    width: 100%;
    padding: 20px;
  }
}
</style>

vue基于elementUI的form表单进行二次封装_第1张图片

你可能感兴趣的:(vue,element-ui)