middleground_code_v2/src/components/base/baseNewForm/index.vue

545 lines
20 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!--
* @name: 自定义表单组件
* @author: zhangpengcheng
* @date: 2022-08-24
-->
<template>
<el-form validate-on-rule-change :model="ruleForm" :rules="rules" label-position="top" ref="ruleForm"
label-width="100px">
<el-row :gutter="24" v-for="(item, index) in formRow" :key="index" style="margin-bottom: 17px;">
<el-col v-for="(row, indexRow) in item.elCol" :span="row.span ? row.span : spanNumber" :key="indexRow">
<el-form-item :prop="row.prop" :style="`display: flex;margin-bottom: ${marginBottom}px;`"
v-if="row.show != false" :class="(rules[row.prop] ? 'ruleFormClass ' : '')">
<!-- <span class="label" slot="label" style="width: 25%;">{{row.label}}</span> -->
<div class="single label" v-if="row.label" slot="label"
:style="`width: ${spanWidth};` + `justify-content: ${justifyContent};`" flex>
<span class="label">{{ row.label }}</span>
</div>
<el-input v-model="ruleForm[row.prop]" v-if="row.tag === 'password'" type="password" show-password clearable auto-complete="off" placeholder="密码" @keyup.enter.native="handleLogin" :disabled="row.disabled ? row.disabled : false">
<svg-icon
slot="prefix"
icon-class="password"
class="el-input__icon input-icon"
/>
</el-input>
<el-input v-model="ruleForm[row.prop]" clearable :disabled="row.disabled ? row.disabled : false"
:rows="row.rows ? row.rows : 2" :type="row.type ? row.type : 'text'" :maxlength="row.maxlength ? row.maxlength : ''"
:placeholder="!row.placeholder ? '请输入' : row.placeholder" v-if="row.tag === 'elInput'"
@blur="searchByStationName(row.prop)" min="1" @input="row.rules ? integerNumber(row) : ''">
</el-input>
<el-input-number v-if="row.tag === 'elInputNumber'" v-model="ruleForm[row.prop]"style="width: 100%;"
:disabled="row.disabled ? row.disabled : false" :precision="row.precisionNum ? row.precisionNum : 0"
:step="row.stepNum ? row.stepNum : 1" @change="handleChange" :min="0"
:max="row.maxNum ? row.maxNum : 99999"
:label="!row.placeholder ? '描述文字' : row.placeholder"></el-input-number>
<!-- <div v-if="row.prop=='address'" id="container"
style="display:none;margin-top:30px;width: 730px;margin:0 auto;height: 590px;border: 1px solid gray;overflow:hidden;">
</div> -->
<el-switch v-if="row.tag === 'elSwitch'" v-model="ruleForm[row.prop]" :active-text="row.activeText"
@change="switchChange($event, index, indexRow, row)" :inactive-text="row.inactiveText"
:active-value="row.activeValue ? row.activeValue : true"
:inactive-value="row.inactiveValue || row.inactiveValue == 0 ? row.inactiveValue : false">
</el-switch>
<el-date-picker v-model="ruleForm[row.prop]" v-if="row.tag === 'elDatePicker'" class="w-100"
:class="{ one: row.type ? 'date' : row.type }" :disabled="row.disabled ? row.disabled : false"
:value-format="!row.valueFormat ? 'yyyy-MM-dd' : row.valueFormat" range-separator="至"
start-placeholder="开始日期" end-placeholder="结束日期" :type="!row.type ? 'date' : row.type"
:placeholder="!row.placeholder ? '请选择' : row.placeholder">
</el-date-picker>
<el-radio-group v-model="ruleForm[row.prop]" v-if="row.tag === 'elRadio'" @input="changeRadio($event,index,indexRow,row)"
:disabled="row.disabled ? row.disabled : false">
<el-radio v-for="el in row.options" :label="el.value" :key="el.value">{{ el.label }}</el-radio>
</el-radio-group>
<div @click="elDialogClick(row, index, indexRow)" @mouseover="elDialogHover(row)"
@mouseleave="elDialogLeave(row)" v-if="row.tag === 'elDialog'" class="elDialog"
:style="{ 'background-color': row.disabled ? '#F5FAF7' : '#fff', 'curpur': row.disabled ? 'pointer' : 'default' }">
<!-- ,background-color:row.disabled?'#c0c4cc':'#fff' -->
<p :style="{ color: ruleForm[row.prop] ? '#000' : '#c0c4cc' }" class="showText"
@click="elDialogClick(row, index, indexRow)">{{ ruleForm[row.prop] ? ruleForm[row.prop] :
'请点击选择' }}
<!-- <el-input v-model="ruleForm[row.prop]"></el-input> -->
</p>
<!-- <i class="el-icon-more " v-if="row.elDialogHoverType"></i> -->
<i class="el-icon-more " @click="elDialogClick(row, index, indexRow)"
v-if="!row.disabled && !ruleForm[row.prop]"></i>
<i class="el-icon-circle-close " v-if="!row.disabled && ruleForm[row.prop] && row.elDialogHoverType"
@click.stop="resetField(row.prop)" style="margin-left: 10px;"></i>
</div>
<div v-if="row.tag === 'elLook'">
{{ ruleForm[row.prop] }}
</div>
<el-select class="w-100" v-model="ruleForm[row.prop]" filterable
@change="selectChange($event, index, indexRow, row.options)" :disabled="row.disabled?row.disabled:false"
:clearable="row.clearable ? row.clearable : true"
:placeholder="!row.placeholder ? '请选择' : row.placeholder" v-if="row.tag === 'elSelect'">
<el-option v-for="(el, index) in row.options"
:key="!row.optionValue ? el['value'] : el[row.optionValue]"
:label="!row.optionLabel ? el['label'] : el[row.optionLabel]"
:value="!row.optionValue ? el['value'] : el[row.optionValue]">
</el-option>
</el-select>
<el-select class="w-100" v-model="ruleForm[row.prop]" multiple :disabled="row.disabled?row.disabled:false"
:clearable="row.clearable" :placeholder="!row.placeholder ? '请选择' : row.placeholder"
v-if="row.tag === 'elMultiple'">
<el-option v-for="el in row.options" :key="!row.optionValue ? el['value'] : el[row.optionValue]"
:label="!row.optionLabel ? el['label'] : el[row.optionLabel]"
:value="!row.optionValue ? el['value'] : el[row.optionValue]">
</el-option>
</el-select>
<treeselect v-if="row.tag === 'elTreeSelect'" v-model="ruleForm[row.prop]" :normalizer="normalizer"
:options="delTreeChildren(row.options)" :multiple="row.multiple?row.multiple:false"
:disabled="row.disabled?row.disabled:false" @clear="treeSelectClear" ref="selectTree"
:placeholder="!row.placeholder?'请选择':row.placeholder" @select="selectTree" />
<slot :name="row.slotName" v-if="row.tag === 'elSlot'" :row="ruleForm"></slot>
<!-- <upload-file v-if="row.tag === 'uploadFile'" :showImgPath="ruleForm[row.prop]" ref="imgFile"
@onImage="row.prop == 'beforeImgList'? getbeforeImgList:row.prop == 'materialsList'? getmaterialsList:row.prop == 'getmaterialsListAfter'?getmaterialsListAfter:getImage "></upload-file> -->
<!-- <custom-cascader :name="row.prop" :field="row.prop" :ref="row.prop" class="w-100"
v-if="row.tag === 'customCascader'" @onChange="getCascader"></custom-cascader> -->
</el-form-item>
</el-col>
</el-row>
<slot name="main"></slot>
<el-form-item v-if="isFunBtn" style="margin-top: 12px;">
<!-- flex="cross:center main:center" -->
<div flex="main:right">
<el-button class="saveBtn" type="primary" @click="submitForm('ruleForm')">提交</el-button>
<el-button @click="resetForm('ruleForm')">重置</el-button>
</div>
</el-form-item>
</el-form>
</template>
<script>
// import uploadFile from "@/components/uploadFile";
// import customCascader from "@/components/customCascader";
import {
checkMobile
} from '@/utils/util'
export default {
components: {
// uploadFile,
// customCascader
},
props: {
// 表单显示格式
spanNumber: {
type: Number,
default: 12
},
spanWidth: {
type: String,
default: '90px'
},
// 表单验证规则
rules: {
type: Object,
default: () => {
return {}
}
},
// 表单页面结构数据
formRow: {
type: Array,
default: () => {
return []
}
},
// 是否禁用
disabled: {
type: Boolean,
default: false
},
// 是否显示操作按钮
isFunBtn: {
type: Boolean,
default: true
},
formdata: {
type: Object,
},
justifyContent: {
type: String,
default: 'flex-start'
},
marginBottom: {
type: String,
default: '0'
},
},
data() {
return {
// 表单数据
ruleForm: {},
}
},
watch: {
ruleForm: {
immediate: true, // 立即执行
deep: true, // 深度监听复杂类型内变化
handler(newVal, oldVal) {
this.$emit('dataChanges')
}
}
},
created() { },
mounted() {
// this.ruleForm = this.formdata
},
computed: {},
methods: {
integerNumber(row) {
// row.rules?(v)=>()):''
// @input="(v)=>(row.row.number=v.replace(/[^\d]/g,''))"
// if(this.ruleForm[row.prop].replace(/[^\d]/g,'')){
// return this.ruleForm[row.prop].replace(/[^\d]/g,'')
//
// integer整数
if (row.rulesName == 'integer') {
this.ruleForm[row.prop] = this.ruleForm[row.prop].replace(/[^\d]/g, '')
}
// decimal小数
if (row.rulesName == 'decimal') {
this.ruleForm[row.prop] = this.ruleForm[row.prop].replace(/[^\d.]/g, '').replace(/\.{2,}/g, '.')
.replace('.', '$#$')
.replace(/\./g, '').replace('$#$', '.').replace(/^(\-)*(\d+)\.(\d\d).*$/, '$1$2.$3').replace(
/^\./g, '')
}
// 身份证
if (row.rulesName == 'identity') {
this.ruleForm[row.prop] = this.ruleForm[row.prop].replace(
/^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/,
'')
}
// 手机号
if (row.rulesName == 'phone') {
this.ruleForm[row.prop] = this.ruleForm[row.prop].replace(/^1(3|4|5|7|8|9)\\d{9}$/, '')
// this.ruleForm[row.prop] = this.ruleForm[row.prop].replace(/^1[3,4,5,6,7,8,9][0-9]{9}$/, '')
// this.ruleForm[row.prop] = this.ruleForm[row.prop].replace(/1(\d{2})\d{4}(\d{4})/g,'').replace(/[^\d]/g, '')
// this.ruleForm[row.prop] = this.ruleForm[row.prop].replace(/\.{11,}/g, '')
// /^1[3|4|5|6|7|8|9][0-9]\d{8}$/
}
// 邮箱
if (row.rulesName == 'eMail') {
this.ruleForm[row.prop] = this.ruleForm[row.prop].replace(
/^([0-9a-zA-Z_\.\-\])+\@([0-9a-zA-Z_\.\-\])+\.([a-zA-Z]+)$/, '')
}
// this.ruleForm[row.prop] = this.ruleForm[row.prop].replace(/[^\d]/g,'')
},
//根据地址获取经纬度
searchByStationName(type) {
if (type == 'address') {
let address = this.ruleForm[type]
let that = this
var map = new BMap.Map("container");
map.centerAndZoom(address, 18);
map.enableScrollWheelZoom(); //启用滚轮放大缩小,默认禁用
map.enableContinuousZoom(); //启用地图惯性拖拽,默认禁用
map.addControl(new BMap.NavigationControl()); //添加默认缩放平移控件
map.addControl(new BMap.OverviewMapControl()); //添加默认缩略地图控件
map.addControl(new BMap.OverviewMapControl({
isOpen: true,
anchor: BMAP_ANCHOR_BOTTOM_RIGHT
})); //右下角,打开
var localSearch = new BMap.LocalSearch(map);
localSearch.enableAutoViewport(); //允许自动调节窗体大小
map.clearOverlays(); //清空原来的标注
var keyword = address
localSearch.setSearchCompleteCallback(function (searchResult) {
var poi = searchResult.getPoi(0);
map.centerAndZoom(poi.point, 13);
var marker = new BMap.Marker(new BMap.Point(poi.point.lng, poi.point
.lat)); // 创建标注,为要查询的地方对应的经纬度
map.addOverlay(marker);
var content = keyword + "<br/><br/>经度:" + poi.point.lng + "<br/>纬度:" + poi.point.lat;
that.ruleForm['lng'] = poi.point.lng
that.ruleForm['lat'] = poi.point.lat
var infoWindow = new BMap.InfoWindow("<p style='font-size:14px;'>" + content + "</p>");
marker.addEventListener("click", function () {
this.openInfoWindow(infoWindow);
});
// marker.setAnimation(BMAP_ANIMATION_BOUNCE); //跳动的动画
});
localSearch.search(keyword);
}
},
//计步器
handleChange(val) {
this.$emit('handleChange', val)
},
// 获取图片
getImage(imagePath) {
let licenseImg = imagePath.join(",")
},
// 处置前照片
getbeforeImgList(imagePath) {
let licenseImg = imagePath.join(",")
this.$set(this.ruleForm, 'beforeImgList', licenseImg)
},
// 处置材料
getmaterialsList(imagePath) {
let licenseImg = imagePath.join(",")
this.$set(this.ruleForm, 'materialsList', licenseImg)
},
// 处置后材料
getmaterialsListAfter(imagePath) {
let licenseImg = imagePath.join(",")
this.$set(this.ruleForm, 'materialsListAfter', licenseImg)
},
revealPhoto(licenseImg) {
this.$refs.imgFile.revealImg(licenseImg)
},
// 回显数据
echoFromData(echoData, otherField) {
let jsonData = []
this.formRow.forEach(item => {
jsonData.push(item.elCol)
})
let newJson = [].concat.apply([], jsonData)
newJson.forEach(item => {
if (this.ruleForm.factoryInFlag == 1) {
for (let i = 0; i < this.formRow[8].elCol.length; i++) { }
}
if (this.ruleForm.factoryInFlag == 0) {
for (let i = 0; i < this.formRow[8].elCol.length; i++) { }
}
this.$set(this.ruleForm, item.prop, echoData[item.prop])
})
// 回显自定义多级选择组件
if (typeof otherField == 'object') {
this.$refs[otherField.props][0].setEchoData(echoData[otherField.field])
}
},
// 获取指定字段参数
//参数propLabel 值value
getField(propLabel, value) {
this.$set(this.ruleForm, propLabel, value)
},
//弹窗赋值
choiceAssignment(value) {
this.ruleForm = Object.assign({}, value)
// this.$forceUpdate()
},
incomingParameters(vale) {
let ruleLength = 0
let valeLength = 0
for (let i in vale) {
valeLength = valeLength + 1
}
for (let i in this.ruleForm) {
ruleLength = ruleLength + 1
}
// if(ruleLength == valeLength){
// this.choiceAssignment(vale)
// }else{
// for(let i in vale){
// this.getField(i,vale[i])
// }
// }
for (let i in vale) {
this.getField(i, vale[i])
}
},
resetFormPlus(formName) {
for (let i in this.$refs[formName]) {
this.getField(i, '')
}
},
// 重置表单字段
resetField(field) {
if (this.ruleForm[field]) {
this.$set(this.ruleForm, field, '')
this.$refs['ruleForm'].clearValidate(field); // 清除表单特定属性
}
},
resetFields() {
this.choiceAssignment({})
this.$refs.ruleForm.resetFields();
},
// 下拉框更改,可根据 index 与 indexRow 定位具体位置
selectChange(val, index, indexRow, options) {
let obj = {}
options.forEach((item) => {
if (item.value == val) {
obj = item
}
})
this.$emit('onSelect', val, index, indexRow, obj)
this.$forceUpdate();
},
switchChange(val, index, indexRow, row) {
this.$emit('switchChange', val, index, indexRow, row)
},
// 自定义级联选择器返回值
getCascader(value, field) {
this.$set(this.ruleForm, field, value)
},
// 表单提交
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
this.$emit('onSubmit', this.ruleForm)
} else {
console.log('error submit!!');
return false;
}
});
},
// 表单重置
resetForm(formName) {
this.choiceAssignment({})
this.$emit('resetForm')
// this.$refs[formName].resetFields();
},
clearCheck(propName) {
this.ruleForm[propName] = ''
},
elDialogClick(row, index, indexRow) {
if (row.disabled) {
return
}
// row.prop
this.$emit('elDialogClick', row, index)
},
elDialogHover(row) {
row.elDialogHoverType = true
},
elDialogLeave(row) {
// row.elDialogHoverType = false
},
// 单选按钮组input事件
changeRadio(val, index, indexRow, row){
this.$emit('onChangeRadio', val, index, indexRow, row)
},
normalizer(node,row) {
//去掉children=null的属性
if (node.children == null || node.children == 'null') {
delete node.children
}
// return{
// ...node,
// label:nodeLabel
// }
},
selectTree(node, instanceId) {
this.$emit('selectTree', node)
},
treeSelectClear(){
this.$refs.selectTree.clear()
}
},
}
</script>
<style>
.el-form-item__label {
/* width: 25%; */
line-height: 1.2;
}
.el-form-item--medium .el-form-item__content {
/* line-height: 36px; */
flex: 1
}
.el-form-item.is-required:not(.is-no-asterisk)>.el-form-item__label:before {
margin-right: 0;
content: ''
}
</style>
<style scoped lang='scss'>
::v-deep textarea.el-textarea__inner{
min-height: 100px !important;
}
.label {
/* @include fontBase(16px, #333333) ; */
color: #333;
font-size: 13px;
/* width: 90px; */
text-align: right;
padding-right: 5px;
}
>>>.el-form-item__label {
width: 100px;
text-align: right !important;
margin-right: 10px !important;
padding: 0 !important;
}
::v-deep .el-form-item__label:before {
display: none;
}
::v-deep .el-form-item__content {
margin-left: 10px;
width: calc(100% - 100px);
}
.w-100 {
width: 100%;
}
.saveBtn {
/* width: 410px; */
}
.one {
width: calc(100% - 15px) !important;
}
.elDialog {
display: flex;
width: 100%;
/* width: calc(100% - 14px);1 */
align-items: center;
justify-content: space-between;
border: 1px solid #DCDFE6;
border-radius: 8px;
padding: 0 15px;
cursor: pointer;
i {
color: #c0c4cc
}
}
.showText {
/* width: 100%; */
/* width: calc(100% - 110px); */
/*让长段文本不换行*/
white-space: nowrap;
/*设置文本超出元素宽度部分隐藏*/
overflow-x: hidden;
/*设置文本超出部分用省略号显示*/
text-overflow: ellipsis;
}
.ruleFormClass {
::v-deep .el-input__inner {
border-color: #E6A23C !important
}
.elDialog {
border-color: #E6A23C !important
}
::v-deep .el-radio__inner {
border-color: #E6A23C !important
}
.el-radio.is-bordered {
border-color: #E6A23C !important
}
::v-deep .vue-treeselect__control {
border-color: #E6A23C !important
}
::v-deep .el-textarea__inner {
border-color: #E6A23C !important
}
}
</style>