#Typora快捷键
#Vue 公用组件使用说明
MyForm表单
对element-ui 中 form表单的二次封装支持如下模块
下面的代码封装支持 栅格布局 -普通常规布局
<!--
* @Author: ruanjiafeng
* @Date: 2020-08-11 09:26:11
* @LastEditTime: 2020-10-13 08:41:08
* @LastEditors: Please set LastEditors
* @Description: form 表单封装
* @FilePath: \tyt-manage-h5\src\components\utils\MyForm.vue
-->
<template>
<el-form
:ref="refName"
:size="size"
:inline="inline"
:label-width="labelWidth"
:model="formData"
:rules="myFormRules"
:label-position="labelPosition"
:class="myFormClass"
>
<!-- --------------------自定义行布局------------------- -->
<!-- (xs <768px) (sm ≥768px) (md ≥992px ) (lg ≥1200px) (xl ≥1920px)-->
<template v-if="customStyle">
<template v-for="(formCfgItem, index) in formCfg">
<el-row :key="index">
<template v-for="(item, index) in formCfgItem">
<el-col
:key="index"
:xs="customCol[0] || null"
:sm="customCol[1] || null"
:md="customCol[2] || null"
:lg="customCol[3] || null"
:xl="customCol[4] || null"
>
<el-form-item
v-if="!item.hide"
:label="item.label"
:style="item.style"
:label-width="item.labelWidth"
:prop="getProp(item, index)"
:key="item.prop"
:class="getFormItemClass(item)"
>
<!-- 如果是myFormDialog自定义-并且设isFormDialog:true-->
<template v-if="item.type === 'custom'">
<slot :name="item.prop" :item="item"></slot>
</template>
<!-- 渲染自定义标题:标签 -->
<!-- 释:
{ customLabel: '销售价:<br/>(最低建议销售价)', type: 'custom', prop: '表单所定义的prop', }
-->
<template v-if="item.customLabel || item.labelFormatter">
<slot slot="label">
<div
class="custom_label"
v-html="getCustomLabel(item)"
></div>
</slot>
</template>
<!-- 如果不是type:title 标题 -->
<template v-if="item.type != 'title' && item.type !== 'custom'">
<!-- 输入框 -->
<el-input
v-if="item.type === 'input' || item.type === 'password'"
v-model="formData[item.prop]"
@change="item.change && item.change(formData[item.prop])"
:disabled="item.disabled"
:type="item.inputType"
:maxlength="item.maxlength"
:style="{ width: item.width }"
:placeholder="getInputPlaceholder(item.placeholder)"
></el-input>
<!-- 文本域 -->
<el-input
v-else-if="item.type === 'textarea'"
type="textarea"
:disabled="item.disabled"
@change="item.change && item.change(formData[item.prop])"
:placeholder="getInputPlaceholder(item.placeholder)"
:maxlength="item.maxlength"
:show-word-limit="item.maxlength ? true : false"
:autosize="getTextareaAutosize(item)"
v-model="formData[item.prop]"
:style="{ width: item.width }"
></el-input>
<!-- 下拉框 -->
<el-select
v-else-if="item.type === 'select'"
v-model="formData[item.prop]"
:style="{ width: item.width ? item.width : '100%' }"
@change="item.change && item.change(formData[item.prop])"
:disabled="item.disabled"
:placeholder="getSelectPlaceholder(item.placeholder)"
>
<!-- 下拉框option选项 -->
<el-option
v-for="(op, opIndex) in item.options"
:label="item.valueMap ? op[item.valueMap[1]] : op.value"
:value="item.valueMap ? op[item.valueMap[0]] : op.key"
:key="
item.valueMap + opIndex
? op[item.valueMap[0]] + opIndex
: op.key + opIndex
"
></el-option>
</el-select>
<!-- 单选 -->
<el-radio-group
v-else-if="item.type === 'radio'"
v-model="formData[item.prop]"
@change="item.change && item.change(formData[item.prop])"
:disabled="item.disabled"
>
<el-radio
v-for="ra in item.radios"
:label="item.valueMap ? ra[item.valueMap[1]] : ra.value"
:key="item.valueMap ? ra[item.valueMap[0]] : ra.key"
>
{{ item.valueMap ? ra[item.valueMap[1]] : ra.value }}
</el-radio>
</el-radio-group>
<!-- 单选按钮 -->
<el-radio-group
v-else-if="item.type === 'radioButton'"
v-model="formData[item.prop]"
@change="item.change && item.change(formData[item.prop])"
:disabled="item.disabled"
>
<el-radio-button
v-for="ra in item.radios"
:label="item.valueMap ? ra[item.valueMap[1]] : ra.value"
:key="item.valueMap ? ra[item.valueMap[0]] : ra.key"
>
{{ item.valueMap ? ra[item.valueMap[1]] : ra.value }}
</el-radio-button>
</el-radio-group>
<!-- 复选框 -->
<el-checkbox-group
v-else-if="item.type === 'checkbox'"
v-model="formData[item.prop]"
@change="item.change && item.change(formData[item.prop])"
:disabled="item.disabled"
>
<el-checkbox
v-for="ch in item.checkboxs"
:label="item.valueMap ? ch[item.valueMap[0]] : ch.key"
:key="item.valueMap ? ch[item.valueMap[0]] : ch.key"
:border="item.border"
>{{
item.valueMap ? ch[item.valueMap[1]] : ch.value
}}</el-checkbox
>
</el-checkbox-group>
<!-- 日期 -->
<el-date-picker
v-else-if="item.type === 'date'"
v-model="formData[item.prop]"
@change="item.change && item.change(formData[item.prop])"
:disabled="item.disabled"
></el-date-picker>
<!-- 时间 -->
<el-time-select
v-else-if="item.type === 'time'"
v-model="formData[item.prop]"
@change="item.change && item.change(formData[item.prop])"
:disabled="item.disabled"
>
</el-time-select>
<!-- 日期时间 -->
<el-date-picker
v-else-if="item.type === 'datetime'"
type="datetime"
v-model="formData[item.prop]"
:prop="item.prop[0]"
@change="item.change && item.change(formData[item.prop])"
:placeholder="
item.placeholder ? item.placeholder[0] : '开始时间'
"
:disabled="item.disabled"
></el-date-picker>
<!-- 日期区间 -格式显示为:2020-02-05 12:20:35 返回时间戳:1598404858000格式-->
<template v-else-if="item.type === 'datetimerange'">
<el-col :span="11">
<el-form-item
class="mr0"
:picker-options="
dateConfig ? dateConfig.pickerOptionsStart : null
"
:prop="item.prop[0]"
>
<el-date-picker
style="width:"
type="datetime"
v-model="formData[item.prop[0]]"
@change="
datetimerangeValue =>
datetimerangeChange(item, datetimerangeValue, 0)
"
:placeholder="
item.placeholder ? item.placeholder[0] : '开始时间'
"
:disabled="item.disabled"
></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="1"
><span class="yzf_telephone_line">-</span></el-col
>
<el-col :span="12">
<el-form-item :prop="item.prop[1]">
<el-date-picker
:picker-options="
dateConfig ? dateConfig.pickerOptionsEnd : null
"
style="width:"
type="datetime"
v-model="formData[item.prop[1]]"
@change="
datetimerangeValue =>
datetimerangeChange(item, datetimerangeValue, 1)
"
:placeholder="
item.placeholder ? item.placeholder[1] : '结束时间'
"
:disabled="item.disabled"
></el-date-picker>
</el-form-item>
</el-col>
</template>
<!-- 日期区间 -格式显示: 2020-02-05 -->
<template v-else-if="item.type === 'ordinaryDate'">
<el-col :span="11">
<el-form-item
class="mr0"
:picker-options="
dateConfig ? dateConfig.pickerOptionsStart : null
"
:prop="item.prop[0]"
>
<el-date-picker
style="width:"
v-model="formData[item.prop[0]]"
@change="
ordinaryValue =>
ordinaryDateChange(item, ordinaryValue, 0)
"
:placeholder="
item.placeholder ? item.placeholder[0] : '开始时间'
"
:disabled="item.disabled"
></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="1"
><span class="yzf_telephone_line">-</span></el-col
>
<el-col :span="12">
<el-form-item :prop="item.prop[1]">
<el-date-picker
:picker-options="
dateConfig ? dateConfig.pickerOptionsEnd : null
"
style="width:"
v-model="formData[item.prop[1]]"
@change="
ordinaryValue =>
ordinaryDateChange(item, ordinaryValue, 1)
"
:placeholder="
item.placeholder ? item.placeholder[1] : '结束时间'
"
:disabled="item.disabled"
></el-date-picker>
</el-form-item>
</el-col>
</template>
<!-- 滑块 -->
<!-- <el-slider v-if="item.type==='Slider'" v-model="editData[item.prop]"></el-slider> -->
<!-- 开关 -->
<el-switch
v-else-if="item.type === 'switch'"
v-model="formData[item.prop]"
@change="item.change && item.change(formData[item.prop])"
:disabled="item.disabled"
>
</el-switch>
<!-- 级联选择器 -->
<el-cascader
v-else-if="item.type === 'cascader'"
v-model="formData[item.prop]"
style="width:"
@change="item.change && item.change(formData[item.prop])"
:disabled="item.disabled"
:props="item.props"
:show-all-levels="item.showAllLevels"
:options="item.options"
>
</el-cascader>
<!-- 自定义插槽 -->
<template v-else-if="item.type === 'custom'">
<slot :name="item.prop" :data="formData"></slot>
</template>
<!-- 图片上传 -->
<template v-else-if="item.type === 'uploadImage'">
<div
class="yzf_image_box"
v-for="(listItem, listIndex) in formData[item.prop[0]]"
:key="listIndex"
>
<el-image
fit="cover"
class="yzf_image_item"
:src="ImageTool.getSmallImg(listItem[item.imageName])"
>
<div slot="error" class="el-image__error">
<i class="el-icon-picture-outline"></i>
</div>
</el-image>
<div
class="yzf_image_item_dlt"
@click="deleteImage(item, listItem, listIndex)"
>
删除
</div>
</div>
<el-upload
v-if="
formData[item.prop[0]].length >= item.limit
? false
: true
"
class="yzf_upload"
:multiple="item.limit > 1 ? true : false"
:limit="item.limit"
:ref="getUploadImageRef(index)"
:headers="uploadImageHead"
:action="item.action"
accept="image/gif, image/jpeg, image/jpg, image/png"
:show-file-list="false"
:file-list="formData[item.prop[0]]"
:on-exceed="
(files, fileList) => {
handleExceed(item, files, fileList);
}
"
:http-request="
file => {
uploadImageHttpRequest(item, file);
}
"
>
<div slot="trigger">
新增图片相册<br />{{ "(暂定最多" + item.limit + "张)" }}
</div>
</el-upload>
</template>
<!-- 电话号码 -->
<template v-else-if="item.type === 'telephone'">
<el-col :span="5">
<el-form-item :prop="item.prop[0]">
<el-input
v-model="formData[item.prop[0]]"
@change="telephoneChange(item)"
maxlength="4"
:disabled="item.disabled"
placeholder="区号"
>
</el-input>
</el-form-item>
</el-col>
<el-col :span="1"
><span class="yzf_telephone_line">-</span></el-col
>
<el-col :span="18">
<el-form-item :prop="item.prop[1]">
<el-input
v-model="formData[item.prop[1]]"
@change="telephoneChange(item)"
:maxlength="8"
:disabled="item.disabled"
placeholder="电话号"
>
</el-input>
</el-form-item>
</el-col>
</template>
<!-- 按钮 -->
<template v-else-if="item.type === 'button'">
<el-row :gutter="20">
<template v-for="(action, index) in formAction">
<el-button
:disabled="btLoading"
v-waves
v-if="!getAtionFormatter(action).hide"
:style="action.style"
:type="action.type || null"
@click="actionButtonClick(action)"
:key="index"
>
<i v-if="action.icon" :class="action.icon"></i>
{{ getAtionFormatter(action).label }}
</el-button>
</template>
</el-row>
</template>
</template>
</el-form-item>
</el-col>
</template>
</el-row>
</template>
</template>
<!-- --------------------普通布局------------------- -->
<template v-if="!customStyle">
<template v-for="(item, index) in formCfg">
<el-form-item
v-if="!item.hide"
:label="item.label"
:style="customStyle ? `${getWidth(item)} ${item.style} ` : item.style"
:label-width="item.labelWidth"
:prop="getProp(item, index)"
:key="item.type + index"
:class="getFormItemClass(item)"
>
<!-- 作用域插槽 -->
<!--
例子:
<template slot-scope="scope" slot='tempMerchantNo'>
<el-input v-model="mySearchFormInfo.searchFormInline.tempMerchantNo" placeholder="请输入内容"></el-input>
</template>
{
label: '临时商商户编号:',
type: 'custom',
prop: 'tempMerchantNo',
placeholder: '请输入临时商商户编号',
},
-->
<!-- 如果是myFormDialog自定义-并且设isFormDialog:true-->
<template v-if="item.type === 'custom'">
<slot :name="item.prop" :item="item"></slot>
</template>
<!-- 渲染自定义标题:标签 -->
<!-- 释:
{ customLabel: '销售价:<br/>(最低建议销售价)', type: 'custom', prop: '表单所定义的prop', }
-->
<template v-if="item.customLabel || item.labelFormatter">
<slot slot="label">
<div class="custom_label" v-html="getCustomLabel(item)"></div>
</slot>
</template>
<!-- 如果不是type:title 标题 -->
<template v-if="item.type != 'title' && item.type !== 'custom'">
<!-- 输入框 -->
<el-input
v-if="item.type === 'input' || item.type === 'password'"
v-model="formData[item.prop]"
@change="item.change && item.change(formData[item.prop])"
:disabled="item.disabled"
:type="item.inputType"
:maxlength="item.maxlength"
:style="{ width: item.width }"
:placeholder="getInputPlaceholder(item.placeholder)"
></el-input>
<!-- 文本域 -->
<el-input
v-else-if="item.type === 'textarea'"
type="textarea"
:disabled="item.disabled"
@change="item.change && item.change(formData[item.prop])"
:placeholder="getInputPlaceholder(item.placeholder)"
:maxlength="item.maxlength"
:show-word-limit="item.maxlength ? true : false"
:autosize="getTextareaAutosize(item)"
v-model="formData[item.prop]"
:style="{ width: item.width }"
></el-input>
<!-- 下拉框 -->
<el-select
v-else-if="item.type === 'select'"
v-model="formData[item.prop]"
:style="{ width: item.width ? item.width : '100%' }"
@change="item.change && item.change(formData[item.prop])"
:disabled="item.disabled"
:placeholder="getSelectPlaceholder(item.placeholder)"
>
<!-- 下拉框option选项 -->
<el-option
v-for="(op, opIndex) in item.options"
:label="item.valueMap ? op[item.valueMap[1]] : op.value"
:value="item.valueMap ? op[item.valueMap[0]] : op.key"
:key="
item.valueMap + opIndex
? op[item.valueMap[0]] + opIndex
: op.key + opIndex
"
></el-option>
</el-select>
<!-- 单选 -->
<el-radio-group
v-else-if="item.type === 'radio'"
v-model="formData[item.prop]"
@change="item.change && item.change(formData[item.prop])"
:disabled="item.disabled"
>
<el-radio
v-for="ra in item.radios"
:label="item.valueMap ? ra[item.valueMap[1]] : ra.value"
:key="item.valueMap ? ra[item.valueMap[0]] : ra.key"
>
{{ item.valueMap ? ra[item.valueMap[1]] : ra.value }}
</el-radio>
</el-radio-group>
<!-- 单选按钮 -->
<el-radio-group
v-else-if="item.type === 'radioButton'"
v-model="formData[item.prop]"
@change="item.change && item.change(formData[item.prop])"
:disabled="item.disabled"
>
<el-radio-button
v-for="ra in item.radios"
:label="item.valueMap ? ra[item.valueMap[1]] : ra.value"
:key="item.valueMap ? ra[item.valueMap[0]] : ra.key"
>
{{ item.valueMap ? ra[item.valueMap[1]] : ra.value }}
</el-radio-button>
</el-radio-group>
<!-- 复选框 -->
<el-checkbox-group
v-else-if="item.type === 'checkbox'"
v-model="formData[item.prop]"
@change="item.change && item.change(formData[item.prop])"
:disabled="item.disabled"
>
<el-checkbox
v-for="ch in item.checkboxs"
:label="item.valueMap ? ch[item.valueMap[0]] : ch.key"
:key="item.valueMap ? ch[item.valueMap[0]] : ch.key"
:border="item.border"
>{{
item.valueMap ? ch[item.valueMap[1]] : ch.value
}}</el-checkbox
>
</el-checkbox-group>
<!-- 日期 -->
<el-date-picker
v-else-if="item.type === 'date'"
v-model="formData[item.prop]"
@change="item.change && item.change(formData[item.prop])"
:disabled="item.disabled"
></el-date-picker>
<!-- 时间 -->
<el-time-select
v-else-if="item.type === 'time'"
v-model="formData[item.prop]"
@change="item.change && item.change(formData[item.prop])"
:disabled="item.disabled"
>
</el-time-select>
<!-- 日期时间 -->
<el-date-picker
v-else-if="item.type === 'datetime'"
type="datetime"
v-model="formData[item.prop]"
:prop="item.prop[0]"
@change="item.change && item.change(formData[item.prop])"
:placeholder="item.placeholder ? item.placeholder[0] : '开始时间'"
:disabled="item.disabled"
></el-date-picker>
<!-- 日期区间 -格式显示为:2020-02-05 12:20:35 返回时间戳:1598404858000格式-->
<template v-else-if="item.type === 'datetimerange'">
<el-col :span="11">
<el-form-item
class="mr0"
:picker-options="
dateConfig ? dateConfig.pickerOptionsStart : null
"
:prop="item.prop[0]"
>
<el-date-picker
style="width:"
type="datetime"
v-model="formData[item.prop[0]]"
@change="
datetimerangeValue =>
datetimerangeChange(item, datetimerangeValue, 0)
"
:placeholder="
item.placeholder ? item.placeholder[0] : '开始时间'
"
:disabled="item.disabled"
></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="1"
><span class="yzf_telephone_line">-</span></el-col
>
<el-col :span="12">
<el-form-item :prop="item.prop[1]">
<el-date-picker
:picker-options="
dateConfig ? dateConfig.pickerOptionsEnd : null
"
style="width:"
type="datetime"
v-model="formData[item.prop[1]]"
@change="
datetimerangeValue =>
datetimerangeChange(item, datetimerangeValue, 1)
"
:placeholder="
item.placeholder ? item.placeholder[1] : '结束时间'
"
:disabled="item.disabled"
></el-date-picker>
</el-form-item>
</el-col>
</template>
<!-- 日期区间 -格式显示: 2020-02-05 -->
<template v-else-if="item.type === 'ordinaryDate'">
<el-col :span="11">
<el-form-item
class="mr0"
:picker-options="
dateConfig ? dateConfig.pickerOptionsStart : null
"
:prop="item.prop[0]"
>
<el-date-picker
style="width:"
v-model="formData[item.prop[0]]"
@change="
ordinaryValue =>
ordinaryDateChange(item, ordinaryValue, 0)
"
:placeholder="
item.placeholder ? item.placeholder[0] : '开始时间'
"
:disabled="item.disabled"
></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="1"
><span class="yzf_telephone_line">-</span></el-col
>
<el-col :span="12">
<el-form-item :prop="item.prop[1]">
<el-date-picker
:picker-options="
dateConfig ? dateConfig.pickerOptionsEnd : null
"
style="width:"
v-model="formData[item.prop[1]]"
@change="
ordinaryValue =>
ordinaryDateChange(item, ordinaryValue, 1)
"
:placeholder="
item.placeholder ? item.placeholder[1] : '结束时间'
"
:disabled="item.disabled"
></el-date-picker>
</el-form-item>
</el-col>
</template>
<!-- 滑块 -->
<!-- <el-slider v-if="item.type==='Slider'" v-model="editData[item.prop]"></el-slider> -->
<!-- 开关 -->
<el-switch
v-else-if="item.type === 'switch'"
v-model="formData[item.prop]"
@change="item.change && item.change(formData[item.prop])"
:disabled="item.disabled"
>
</el-switch>
<!-- 级联选择器 -->
<el-cascader
v-else-if="item.type === 'cascader'"
v-model="formData[item.prop]"
style="width:"
@change="item.change && item.change(formData[item.prop])"
:disabled="item.disabled"
:props="item.props"
:show-all-levels="item.showAllLevels"
:options="item.options"
>
</el-cascader>
<!-- 自定义插槽 -->
<template v-else-if="item.type === 'custom'">
<slot :name="item.prop" :data="formData"></slot>
</template>
<!-- 图片上传 -->
<template v-else-if="item.type === 'uploadImage'">
<div
class="yzf_image_box"
v-for="(listItem, listIndex) in formData[item.prop[0]]"
:key="listIndex"
>
<el-image
fit="cover"
class="yzf_image_item"
:src="ImageTool.getSmallImg(listItem[item.imageName])"
>
<div slot="error" class="el-image__error">
<i class="el-icon-picture-outline"></i>
</div>
</el-image>
<div
class="yzf_image_item_dlt"
@click="deleteImage(item, listItem, listIndex)"
>
删除
</div>
</div>
<el-upload
v-if="
formData[item.prop[0]].length >= item.limit ? false : true
"
class="yzf_upload"
:multiple="item.limit > 1 ? true : false"
:limit="item.limit"
:ref="getUploadImageRef(index)"
:headers="uploadImageHead"
:action="item.action"
accept="image/gif, image/jpeg, image/jpg, image/png"
:show-file-list="false"
:file-list="formData[item.prop[0]]"
:on-exceed="
(files, fileList) => {
handleExceed(item, files, fileList);
}
"
:http-request="
file => {
uploadImageHttpRequest(item, file);
}
"
>
<div slot="trigger">
新增图片相册<br />{{ "(暂定最多" + item.limit + "张)" }}
</div>
</el-upload>
</template>
<!-- 电话号码 -->
<template v-else-if="item.type === 'telephone'">
<el-col :span="5">
<el-form-item :prop="item.prop[0]">
<el-input
v-model="formData[item.prop[0]]"
@change="telephoneChange(item)"
maxlength="4"
:disabled="item.disabled"
placeholder="区号"
>
</el-input>
</el-form-item>
</el-col>
<el-col :span="1"
><span class="yzf_telephone_line">-</span></el-col
>
<el-col :span="18">
<el-form-item :prop="item.prop[1]">
<el-input
v-model="formData[item.prop[1]]"
@change="telephoneChange(item)"
:maxlength="8"
:disabled="item.disabled"
placeholder="电话号"
>
</el-input>
</el-form-item>
</el-col>
</template>
</template>
</el-form-item>
</template>
</template>
<!-- 按钮事件-换行 -->
<div v-if="formAction && actionInline && !customStyle">
<el-form-item>
<template v-for="(action, index) in formAction">
<el-button
:disabled="btLoading"
v-waves
v-if="!getAtionFormatter(action).hide"
:style="action.style"
:type="action.type || null"
@click="actionButtonClick(action)"
:key="index"
>
<i v-if="action.icon" :class="action.icon"></i>
{{ getAtionFormatter(action).label }}
</el-button>
</template>
</el-form-item>
</div>
<!-- 不换行 -->
<el-form-item v-else-if="formAction && !customStyle">
<template v-for="(action, index) in formAction">
<el-button
:disabled="btLoading"
v-waves
v-if="!getAtionFormatter(action).hide"
:style="action.style"
:type="action.type || null"
@click="actionButtonClick(action)"
:key="index"
><i v-if="action.icon" :class="action.icon"></i>
{{ getAtionFormatter(action).label }}</el-button
>
</template>
</el-form-item>
</el-form>
</template>
<script lang="ts">import {
Component,
Vue,
Provide,
Prop,
Watch,
Emit
} from "vue-property-decorator";
import { State, Action, namespace, Getter } from "vuex-class";
// import http from '@/config/http'
@Component
export default class MyForm extends Vue {
/* 按钮加载 */
@Prop(Boolean) btLoading: boolean;
/* 是否为自定义样式-栅格布局 */
@Prop(Boolean) customStyle: boolean;
/* 表单样式 */
@Prop(String) myFormClass: string;
/* 表单ref名称 */
@Prop({ type: String, required: false, default: "editForm" }) refName: string;
/* 日期规则限制 */
@Prop({ type: Object, required: false, default: () => {} })
dateConfig: any;
/* 分行, 参考element */
@Prop({ type: Boolean, required: false, default: false }) inline: boolean;
/* 文本宽度, 参考element */
@Prop({ type: String, required: false, default: "" }) labelWidth: string;
/* 表单内控件的大小, 参考element */
@Prop({ type: String, required: false, default: "medium" }) size: string;
/**
* 栅格配置, 参考 element
* <!-- (xs <768px) (sm ≥768px) (md ≥992px ) (lg ≥1200px) (xl ≥1920px)-->
*
*/
/* */
@Prop({ type: Array, required: false, default: () => [24, 8, 8, 8, 8] })
customCol: any;
/**
* 表单配置, 参考element
* valueMap(Array): [keyName, valueName]
*/
@Prop({ type: Array, required: false, default: () => [] }) formCfg: any;
/* 表单数据, 要与formCfg子项的prop对应 */
@Prop({ type: Object, required: false, default: () => {} }) formData: any;
/* 表单校验, 参考element */
@Prop({ type: Object, required: false, default: null }) formRules: any;
/**
* 表单按钮
* isClear(Boolean): 是否为清除表单
*/
@Prop({ type: Array, required: false, default: () => [] }) formAction: any;
/* 按钮是否换行 */
@Prop({ type: Boolean, required: false, default: false })
actionInline: boolean;
/* 表单文本对齐方式, 参考element */
@Prop({ type: String, required: false, default: "left" })
labelPosition: string;
/* 列数 */
@Prop({ type: Number, required: false, default: 0 })
column: number;
/* data 属性 */
private dyData: object = {}; //存放动态添加的变量
private myFormRules: any; //表单校验规则
/* vuex 中的 getsessionKey */
// @Getter("getsessionKey", { namespace: "app" }) private getSessionKey: any;
/* 计算属性 */
private get uploadImageHead() {
// 上传文件请求头
return { "X-AUTH-TOKEN": this.getSessionKey };
}
created() {
/* 初始化-表单校验 */
this.initRules();
}
/* ------------- methods ------------- */
getWidth(item:) {
/** 获取宽度 **/
// 优先级: width > span > column
// 都不传默认100%
let widthStr = "";
if (item.width) {
widthStr = "width:" + item.width + "px;";
} else if (item.span) {
widthStr = "width:" + 4 * item.span + "%;";
} else if (this.column) {
widthStr = "width:" + 100 / this.column + "%;";
} else {
widthStr = "width:100%;";
}
return widthStr;
}
/** 自定义标题 */
getCustomLabel(item:) {
if (item.labelFormatter) {
let customL = item.labelFormatter(this.formData);
console.log("customL", customL || item.customLabel);
return customL || item.customLabel;
} else {
return item.customLabel;
}
}
/** 过滤prop名称绑定 **/
getProp(item: any, index:) {
if (Object.prototype.toString.call(item.prop) === "[object String]") {
return item.prop;
} else if (item.type === "uploadImage" || item.type === "datetimerange") {
return item.prop[0];
} else {
return "";
}
}
/** 初始化校验规则 **/
initRules() {
/* 如果当前表单没有校验规则 */
if (!this.formRules) {
this.myFormRules = {};
} else {
this.myFormRules = this.formRules;
}
/* 如果表单校验中存在< telephone电话> */
this.formCfg.map((item:) => {
if (item.type === "telephone") {
// 区号
let validateAreaCode = (rule: any, value: any, callback:) => {
if (this.formData[item.prop[1]] && !this.formData[item.prop[0]]) {
callback(new Error("请输入区号"));
} else {
callback();
}
};
/* 地区编码数组校验 */
let areaCodeRuleArr: any = [
{ validator: validateAreaCode, trigger: "blur" }
];
// 电话号
let validateTelephone = (rule: any, value: any, callback:) => {
console.log(
"this.formData[item.prop[0]]",
this.formData[item.prop[0]],
this.formData[item.prop[1]]
);
if (this.formData[item.prop[0]] && !this.formData[item.prop[1]]) {
callback(new Error("请输入电话号"));
} else if (
this.formData[item.prop[0]] &&
this.formData[item.prop[1]]
) {
if (
this.formData[item.prop[0]].length +
this.formData[item.prop[1]].length >
11
) {
callback(new Error("区号与电话号码长度不能超过11"));
} else {
callback();
}
} else {
callback();
}
};
let ruleArr: any = [{ validator: validateTelephone, trigger: "blur" }];
if (item.required) {
areaCodeRuleArr.push({
required: true,
message: "请输入区号",
trigger: "blur"
});
ruleArr.push({
required: true,
message: "请输入电话号",
trigger: "blur"
});
}
this.$set(this.myFormRules, item.prop[0], areaCodeRuleArr);
this.$set(this.myFormRules, item.prop[1], ruleArr);
}
});
}
/** 按钮点击事件 **/
actionButtonClick(data:) {
if (data.isClear) {
// 清空表单
this.resetFields();
this.formCfg.map((item: any, index:) => {
if (item.type === "datetimerange") {
let dateArr = [
this.formData[item.prop[0]],
this.formData[item.prop[1]]
];
this.$set(this.dyData, "datetimerangeArray" + index, dateArr);
}
});
}
if (data.click) {
data.click();
}
}
/** 清空表单数据 **/
resetFields() {
(this.$refs[this.refName] as HTMLElement).resetFields();
}
/** 清空表单数据 **/
validate(cb:) {
(this.$refs[this.refName] as HTMLElement).validate((valid:) => {
cb(valid);
});
}
/** 输入框提示语 **/
getInputPlaceholder(str: string): String {
return str || "请输入";
}
/** 选择列表提示语 **/
getSelectPlaceholder(str: string): String {
return str || "请选择";
}
/** 文本作用域 最大最小行数设置 **/
getTextareaAutosize(data:) {
if (data.minRows && data.maxRows) {
// eslint-disable-next-line standard/object-curly-even-spacing
return { minRows: data.minRows, maxRows: data.maxRows };
} else if (data.minRows && !data.maxRows) {
return { minRows: data.minRows };
} else if (!data.minRows && data.maxRows) {
return { maxRows: data.maxRows };
} else {
return false;
}
}
/** 获取表单栏样式 **/
getFormItemClass(data:) {
if (data.type === "title") {
return "yzf_form_item_title " + (data.class ? data.class : "");
} else {
return data.class ? data.class : "";
}
}
/** 电话号码数据监听 **/
telephoneChange(item:) {
if (item.prop && item.change) {
let data = JSON.parse(
JSON.stringify([
this.formData[item.prop[0]],
this.formData[item.prop[1]]
])
);
item.change(data);
}
}
/** 电话号码输入框最大输入长度 **/
gettelNumberMaxlength(areaCode:) {
if (areaCode.length === 3) {
return 8;
} else {
return 7;
}
}
/** 获取文件上传ref **/
getUploadImageRef(index:) {
return "uploadImage" + this.refName + index;
}
/** 自定义上传图片 */
async uploadImageHttpRequest(item: any, params:) {
console.log("file--", params);
let formData = new FormData();
formData.append("file", params.file);
formData.append("data", JSON.stringify(item.data));
/* 原来封装的http接口 */
// let res = await http.uploadFile(item.action, formData, false)
/* 上传文件自定义接口 */
let res: any = await this.uploadFile(item.action, formData, false);
if (
res.resultCode === 0 &&
res.resultData &&
res.resultData.imageList.length > 0
) {
this.$set(
this.formData[item.prop[0]],
this.formData[item.prop[0]].length,
res.resultData.imageList[0]
);
return true;
}
return false;
}
/* 上传文件接口 */
uploadFile(url: any, data: any, loading:) {
// return axios({
// method: 'post',
// url,
// data,
// params: {loading: loading, isUploadFile: true},
// processData: false,
// contentType: false
// }).then(
// (response:any) => {
// return checkStatus(response)
// }
// ).then(
// (res:any) => {
// return checkCode(res)
// }
// )
}
/** 删除商品图片 **/
deleteImage(item: any, imageItem: any, index:) {
let self = this;
this.$confirm("确定删除此图片", "提示", {
type: "warning",
callback: function(action,) {
if (action === "confirm") {
self.$delete(self.formData[item.prop[0]], index);
self.formData[item.prop[1]].push(imageItem);
}
}
});
}
beforeUploadImage(item: any, file:) {
/** 上传图片前钩子 **/
// var testmsg=file.name.substring(file.name.lastIndexOf('.')+1)
// const extension = testmsg === 'zip'
// if(!extension) {
// this.$message.warning({ message: '上传文件只能是zip格式!' })
// }
// const isLt2M = file.size / 1024 / 1024 < 10
// if(!isLt2M) {
// this.$message({
// message: '上传文件大小不能超过 10MB!',
// type: 'warning'
// });
// }
// return extension || extension2 && isLt2M
return true;
}
/** 文件超出回调 **/
handleExceed(item: any, files: any, fileList:) {
this.$message.warning({
message: "最多只能上传" + item.limit + "张图片"
});
}
/** 多功能-选择时间区间变化回调 **/
datetimerangeChange(item: any, datetimerangeValue: any, index:) {
/* --------- 时间戳格式 (可用)-----------*/
/* 1598404858000 时间戳格式 */
if (datetimerangeValue) {
if (index === 0) {
this.formData[item.prop[0]] = this.$dateParseTime(datetimerangeValue);
} else if (index === 1) {
this.formData[item.prop[1]] = this.$dateParseTime(
datetimerangeValue,
true
);
}
} else {
if (index === 0) {
this.formData[item.prop[0]] = "";
} else if (index === 1) {
this.formData[item.prop[1]] = "";
}
}
}
/** 普通日期-选择时间区间变化回调 **/
ordinaryDateChange(item: any, ordinaryValue: any, index:) {
/* --------- 日期格式 (可用)-----------*/
/* 2020-11-08 12:02:25 格式 */
if (ordinaryValue) {
if (index === 0) {
this.formData[item.prop[0]] = this.$filterDate(ordinaryValue, "start");
} else if (index === 1) {
this.formData[item.prop[1]] = this.$filterDate(ordinaryValue, "end");
}
} else {
if (index === 0) {
this.formData[item.prop[0]] = "";
} else if (index === 1) {
this.formData[item.prop[1]] = "";
}
}
}
/** 按钮渲染更新 **/
getAtionFormatter(action:) {
if (action.formatter) {
let newAction = action.formatter(Object.assign({}, action));
if (newAction) {
action = Object.assign(action, newAction);
}
}
return action;
}
}</script>
<style lang="scss" scoped>/deep/.yzf_form_item_title {
.el-form-item__label {
font-size: 15px;
font-weight: 600;
}
}
/deep/.el-select .el-input__inner {
padding-right: 14px;
}
.el-form--inline .el-form-item {
margin-right: 30px;
}
@media (max-width: 1450px) {
.el-form--inline .el-form-item {
margin-right: 10px;
}
}
/** 图片上传样式 **/
.yzf_image_box {
overflow: hidden;
position: relative;
cursor: pointer;
width: 120px;
height: 120px;
line-height: 116px;
margin: 5px;
padding: 0px;
text-align: center;
float: left;
border: 1px solid #ccc;
margin-top: 15px;
border-radius: 5px;
box-shadow: #e6e6e6 0px 0px 7px 1px;
.yzf_image_item {
width: 100%;
height: 100%;
}
.yzf_image_item_dlt {
width: 100%;
height: 24px;
position: absolute;
background: #e7e7e7;
bottom: 0;
left: 0;
z-index: 20;
text-align: center;
line-height: 24px;
border: 0;
border-top-width: 0px;
}
}
.yzf_upload {
cursor: pointer;
width: 120px;
height: 86px;
background: #ddd;
float: left;
margin: 5px;
margin-top: 15px;
text-align: center;
line-height: 20px;
padding-top: 35px;
border: 1px solid #ccc;
}
.yzf_telephone_line {
width: 100%;
text-align: center;
display: block;
}
.mr0 {
margin-right: 0;
}
.custom_label {
line-height: 20px;
}</style>
MyForm表单传参
参数 | 说明 | 类型 | 可选值 | 默认值 |
refName | 主键的ref名称 | string | - | editForm |
size | 表单组件大小 | string | medium(中) / small (小)/ mini(超小) | medium(中) |
inline | 表单是否换行 | boolean | - | false |
labelWidth | 表头宽度 | string | - | - |
formData | 表单数据 | object | - | - |
formRules | 表单提交数据校验规则 | array | - | null |
labelPosition | 表头位置 | string | right/left/top | left |
formCfg | 表单配置项 | array | - | - |
formAction | 表单操作按钮 | array | - | - |
actionInline | 表单操作按钮是否换行 | boolean | - | false |
MyForm-formCfg 表单配置项
参数 | 说明 | 类型 | 可选值 | 默认值 |
hide | 隐藏显示该配置项 | boolean | true, false | false |
label | 配置项标 题 | string | - | - |
labelWidth | 标题宽度 | string | - | - |
prop | 绑定表单字段名 | string / array | - | - |
class | 表单样式名称 | string | - | - |
type | 表单配置类型 | string | title / input / textarea / select / radio / radioButton / checkbox / date / time / datetime / datetimerange/ switch / cascader / custom / uploadImage / telephone | - |
标题栏 (type = title)
无需绑定prop数据, 只展示标题项
参数 | 说明 | 类型 | 示例 | 可选值 | 默认值 |
customLabel | 标题文本 | string | { customLabel: ‘销售价: (最低建议销售价)’, type: ‘custom’, prop: ‘表单所定义的prop’, } | - | - |
labelFormatter | 标题格式 | function | function(data) data: object 表单数据 return: string 自定义标题 支持 v-html |
###输入框 (type = input)
参数 | 说明 | 类型 | 示例 | 可选值 | 默认值 |
disabled | 禁用 | boolean | - | - | |
inputType | 输入框类型 | string | text,textarea 和其他 原生 input 的 type 值 | - | |
placeholder | 提示 | string | - | - | |
change | 修改回调 | function | change: (data) => { console.log(‘文本域内容’,data) } | - | - |
maxlength | 输入框最大字数 | number |
###文本域 (type = textarea)
参数 | 说明 | 类型 | 示例 | 可选值 | 默认值 |
disabled | 禁用 | boolean | - | - | - |
placeholder | 提示 | string | - | - | - |
maxlength | 最大输入长度 | string | - | - | - |
minRows | 最小行数 | string | - | - | - |
maxRows | 最大行数 | string | - | - | - |
width | 设置文本作用域容器宽度 | string | - | - | - |
change | 修改回调 | function | change: (data) => { console.log(‘文本域内容’,data) } | - | - |
下拉框 (type = select)
参数 | 说明 | 类型 | 可选值 | 默认值 | 示例 |
disabled | 禁用 | boolean | - | - | - |
placeholder | 提示 | string | - | - | - |
options | 选择项数据 | array | - | 默认[{key: “”, value: “"}]数组对象 | [{ key: ‘1’, value: ‘默认’ }] |
valueMap | 下拉列表options数据,所绑定(对应的键值)名称 | array | - | 默认[“”, “"] | valueMap: [‘supplierAccountNumberId’, ‘supplierName’] ,options: [ supplierName: ‘刘备’,supplierAccountNumberId: ‘123’] |
change | 修改回调 | function (data) data: 选中key |
###单选框 (type = radio)
参数 | 说明 | 类型 | 可选值 | 默认值 |
disabled | 禁用 | boolean | - | - |
radios | 选择项 | array | - | 默认[{key: “”, value: “"}]数组 |
change | 修改回调 | function (data) data: 选中key | - | - |
单选按钮 (type = radioButton)
参数 | 说明 | 类型 | 可选值 | 默认值 |
disabled | 禁用 | boolean | - | - |
radios | 选择项 | array | - | 默认[{key: “”, value: “"}]数组 |
change | 修改回调 | function (data) data: 选中key | - | - |
###复选框 (type = checkbox)
参数 | 说明 | 类型 | 可选值 | 默认值 |
disabled | 禁用 | boolean | - | - |
checkboxs | 选择项 | array | - | 默认[{key: “”, value: “"}]数组 |
valueMap | 选择项绑定数据的键值名称 | array | - | 默认[“”, “"] |
change | 修改回调 | function (data) data: 选中key | - | - |
###日期选择器 (type = date)
参数 | 说明 | 类型 | 可选值 | 默认值 |
disabled | 禁用 | boolean | - | - |
change | 修改回调 | function (data) data: 选中key | - | - |
###时间选择器 (type = time)
参数 | 说明 | 类型 | 可选值 | 默认值 |
disabled | 禁用 | boolean | - | - |
change | 修改回调 | function (data) data: 选中key | - | - |
###日期时间选择器 (type = datetime)
参数 | 说明 | 类型 | 可选值 | 默认值 |
disabled | 禁用 | boolean | - | - |
change | 修改回调 | function (data) data: 选中key | - | - |
日期时间区间选择器 (type = datetimerange)
参数 | 说明 | 类型 | 可选值 | 默认值 |
disabled | 禁用 | boolean | - | - |
placeholder | 提示文字 | array | - | 默认[“”, “"] |
###滑动开关 (type = switch)
参数 | 说明 | 类型 | 可选值 | 默认值 |
disabled | 禁用 | boolean | - | - |
change | 修改回调 | function (data) 选种数据 | - | - |
滑动开关 (type = switch)
参数 | 说明 | 类型 | 可选值 | 默认值 |
disabled | 禁用 | boolean | - | - |
change | 修改回调 | function (data) 选种数据 | - | - |
联级选择器 (type = cascader)
参数 | 说明 | 类型 | 可选值 | 默认值 |
disabled | 禁用 | boolean | - | - |
change | 修改回调 | function (data) 选种数据 | - | - |
options | 选择项 | array | - | - |
showAllLevels | 输入框中是否显示选中值的完整路径 | boolean | - | - |
###自定义插槽 (type = custom)
参数 | 说明 | 类型 | 可选值 | 默认值 |
prop | 插槽名称 | string | - | - |
###图片上传 (type = uploadImage)
参数 | 说明 | 类型 | 可选值 | 默认值 |
prop | 绑定数据 | array | - | [“绑定上传图片列表字段名称”,”绑定删除图片列表字段名称"] |
imageName | 图片数据列表展示Url名称 | string | - | - |
limit | 最大上传文件数 | number | - | - |
action | 图片上传地址 | string | - | - |
data | 图片上传参数 | object | - | - |
电话号码 (type = telephone)
参数 | 说明 | 类型 | 可选值 | 默认值 |
prop | 绑定数据 | array | - | [“绑定区号字段名称”,”绑定电话号字段名称"] |
disabled | 禁用 | boolean | - | - |
###表单按钮 formAction
参数 | 说明 | 类型 | 可选值 | 默认值 |
type | 按钮类型 | string | primary / success / warning / danger / info / text | - |
图标类型 | string | 可参考element.ui | - | |
isClear | 是否清空表单 | boolean | - | - |
click | 点击事件 | function () | - | - |
label | 按钮标题 | string | - | - |
formatter | 按钮格式器 | function (action) action: 按钮数据 | - | 可设置按钮标题(label), 是否隐藏(hide) |
表单弹框 MyFormDialog
MyForm添加到弹框的嵌套封装, 具体使用参数参考MyForm说明, 目前不支持 formCfg配置项type = custom类型
参数 | 说明 | 类型 | 可选值 | 默认值 |
title | 弹框标题 | string | - | - |
show | 是否显示弹框 | boolean | - | - |
refName | 表单ref名称 | string | - | editForm |
formData | 表单数据 | object | - | - |
formRules | 表单提交数据校验规则 | array | - | - |
labelPosition | 表头位置 | string | right/left/top | left |
formCfg | 表单配置项 | array | - | - |
formAction | 表单操作按钮 | array | - | - |
#表格 MyTable
参数 | 说明 | 类型 | 可选值 | 默认值 |
refName | 表格ref名称 | string | - | myTable |
select | 是否显示勾选项 | boolean | - | false |
selectionChange | 复选框-勾选回调函数 | function (data) data: 勾选表格项List | - | - |
selectWidth | 复选框-勾选项宽度 | string | - | -null |
tableData | 表格数据 | array | - | - |
tableColumns | 表格配置项 | array | - | - |
spanMethod | 表格合并项 | function | ||
page | 分页配置项 | object | - | - |
表格配置项 tableColumns
参数 | 说明 | 类型 | 可选值 | 默认值 |
type | 配置项类型 | string | options(常规项) / html(动态标签项) / action(按钮项) / custom(自定义-插槽) | - |
fixed | 列是否固定在左侧或者右侧,true 表示固定在左侧 | string / boolean | - | - |
prop | 绑定数据字段名称(后台返回的表格字段) | string | - | - |
label | 表头标题 | string | - | - |
width | 该列宽度 | string / number | - | - |
align | 对齐方式 | string | left / center / right | center |
headerAlign | 表头对齐方式 | string | left / center / right | center |
###常规项 (type = options)
参数 | 说明 | 类型 | 可选值 | 默认值 |
formatter | 格式类 | function (row, column, cellValue, index) | - | 返回内容 |
动态标签项 (type = html)
参数 | 说明 | 类型 | 可选值 | 默认值 |
formatter | 格式类 | function(row) | - | 返回富文本字符串 |
按钮项 (type = action)
参数 | 说明 | 类型 | 可选值 | 默认值 |
actions | 按钮数据 | array | - | - |
-hide | 是否隐藏 | boolean | - | - |
-label | 按钮标题 | string | - | - |
-formatter | 格式类 | function (action, row) action: 按钮数据 row: 列表项数据 | - | 修改action需返回action对象 |
-click | 点击方法 | function (row) row: 列表项数据 | - | - |
-copyFormatter | 拷贝内容格式类 | function (row) row: 列表数据 | - | 需返回拷贝内容数据字符串 |
btnType | 按钮类型 | primary / success / warning / danger / info / text | text |
插槽项 (type = custom)
参数 | 说明 | 类型 | 可选值 | 默认值 |
prop | 插槽名称 | string | - | - |
分页项 page
参数 | 说明 | 类型 | 可选值 | 默认值 |
count | 总页数 | number | - | - |
currentPage | 当前页 | number | - | - |
length | 每页长度 | number | - | - |
tableChange | 页码变化回调 | function () | - | - |
###富文本编辑器
参数 | 说明 | 类型 | 可选值 | 默认值 |
defaultMsg | 富文本内容 | string | - | - |
imageType | 富文本图片类型 | number | - | - |
###上传文件插件 MyUploadFile
参数 | 说明 | 类型 | 可选值 | 默认值 |
limit | 上传文件数量 | number | - | 1 |
uploadType | 上传文件类型 | string | Image(可扩展配置) | image |
action | 上传路由 | string | - | /yhtplus/image/uploadImageList.action |
uploadFileCb | 文件数量修改回调 | function | - | - |
actionParam | 参数 | object | - | - |