middleground_code_v2/src/views/masterDataOptions/compoments/baseNewForm.vue

921 lines
27 KiB
Vue
Raw Normal View History

2024-03-26 11:18:19 +08:00
<!--
* @name: 自定义表单组件
* @author: zhangpengcheng
* @date: 2022-08-24
-->
<template>
<el-form
validate-on-rule-change
:model="ruleForm"
:rules="rules"
:label-position="labelPosition"
:ref="refName"
:label-width="labelWidth"
>
<el-row
:gutter="0"
v-for="(item, index) in formRow"
:key="index"
style="margin-bottom: 18px"
>
<el-col
v-for="(row, indexRow) in item.elCol"
:span="row.row ? row.row * 1 : spanNumber"
:key="row.id"
>
<el-form-item
:prop="row.id"
:style="`display: flex;margin-bottom: ${marginBottom}px;padding:0 20px`"
v-if="row.show != false"
:class="rules[row.id] ? 'ruleFormClass ' : ''"
:rules="
formRule
? [
{
required: row.required,
message: `${row.title}不能为空`,
trigger: row.type === 'input' ? 'change' : 'blur',
},
...(row.pattern && row.message
? [
{
pattern: row.pattern,
message: row.message,
trigger: 'blur',
},
]
: []),
]
: []
"
>
<div
class="single label"
v-if="row.label || row.title"
slot="label"
:style="`` + `justify-content: ${justifyContent};`"
flex
>
<span
class="label"
:style="`font-size:${
row.fontSize ? row.fontSize + 'px' : '13px'
}`"
>
<span v-if="row.required" style="color: red">*</span>
{{ row.title }}:
</span>
</div>
<template v-if="!lookFlag">
<el-checkbox
v-model="ruleForm[row.id]"
v-if="row.type == 'onecheck'"
:disabled="disabled"
2024-03-26 11:18:19 +08:00
>
</el-checkbox>
<el-input
v-model="ruleForm[row.id]"
clearable
:disabled="disabled || (row.disabledOfId?Boolean(ruleForm.id):row.disabled) "
2024-03-26 11:18:19 +08:00
:rows="row.rows ? row.rows : 2"
:type="row.type ? row.type : 'text'"
:maxlength="row.maxlength ? row.maxlength * 1 : '99'"
:placeholder="!row.placeholder ? '请输入' : row.placeholder"
v-if="
row.tag === 'elInput' || (row.type === 'input' && !lookFlag)
"
@blur="searchByStationName(row.id,ruleForm)"
min="1"
@input="row.rules ? integerNumber(row) : ''"
@dblclick.native="row.double?dblclick(ruleForm[row.id]):''"
@change="$emit('onInput')"
>
</el-input>
<el-input
type="number"
v-if="row.type === 'num'"
v-model="ruleForm[row.id]"
style="width: 100%"
:disabled="(row.disabled && !newFlag ? row.disabled : false) || disabled"
2024-03-26 11:18:19 +08:00
:precision="row.precisionNum ? row.precisionNum : 0"
:placeholder="!row.placeholder ? '请输入' : row.placeholder"
:step="row.stepNum ? row.stepNum : 1"
@change="handleChange"
@input="(val) => limitPhoneNum(val, ruleForm, row.id)"
:maxlength="row.maxlength ? row.maxlength * 1 : 50"
:min="1"
:max="row.max ? row.max : 255"
2024-03-26 11:18:19 +08:00
:label="!row.placeholder ? '描述文字' : row.placeholder"
>
<template slot="append" v-if="row.message">{{ row.message }}</template>
</el-input
>
<el-switch
v-if="row.type === 'switch' && !lookFlag"
v-model="ruleForm[row.id]"
: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>
<baseDatePicker
class="w-100"
v-model="ruleForm[row.id]"
v-if="
row.tag === 'elDatePicker' ||
(row.type === 'datepick' && !lookFlag)
"
:disabled="row.disabled && !newFlag"
:datePickerType="formRule ? 'date' : 'daterange'"
>
</baseDatePicker>
<baseDatePicker
class="w-100"
v-model="ruleForm[row.id]"
v-if="row.type === 'datetiempick' && !lookFlag"
:disabled="row.disabled && !newFlag"
datePickerType="datetime"
>
</baseDatePicker>
<el-radio-group
v-model="ruleForm[row.id]"
v-if="
row.tag === 'elRadio' || (row.type === 'radio' && !lookFlag)
"
@input="changeRadio($event, index, indexRow, row)"
:disabled="row.disabled && !newFlag ? row.disabled : false"
>
<el-radio v-for="el in row.options" :label="el.id" :key="el.id">{{
el.label
}}
</el-radio>
</el-radio-group>
<el-input
type="textarea"
v-if="row.type === 'textrea' && !lookFlag"
resize="none"
:rows="4"
placeholder="请输入内容"
show-word-limi
v-model="ruleForm[row.id]"
:disabled="row.disabled && !newFlag"
>
</el-input>
<el-select
class="w-100"
v-model="ruleForm[row.id]"
filterable
:multiple="row.multiple"
@change="selectChange($event, index, indexRow, row)"
:disabled="row.disabled || disabled"
2024-03-26 11:18:19 +08:00
:clearable="row.clearable ? row.clearable : true"
:placeholder="!row.placeholder ? '请选择' : row.placeholder"
v-if="
row.tag === 'select' || (row.type === 'select' && !lookFlag)
"
>
<el-option
v-for="(el, index) in row.options"
:key="!row.optionValue ? el['id'] : el[row.optionValue]"
:label="!row.optionLabel ? el['label'] : el[row.optionLabel]"
:value="!row.optionValue ? el['id'] : el[row.optionValue]"
>
</el-option>
</el-select>
<baseNewSelect
:ref="row.refName"
:apiInfo="row.apiInfo"
:searchApiInfo="row.searchApiInfo"
v-if="row.type === 'newSelect'"
v-model="ruleForm[row.id]"
:itemObj="row"
@showValue="showValueHandle"
:idKey="row.id"
:journalingType="row.journalingType"
:prop="row.prop"
:foucus="row.foucus"
:apiBody="row.apiBody"
:searchKey="row.searchKey"
@selectChange="selectChangeHanlde"
>
</baseNewSelect>
<slot
:name="row.slotName"
v-if="row.type === 'elSlot'"
:row="{row,ruleForm}"
></slot>
</template>
<template v-else>
<div
v-if="
row.type !== 'radio' &&
row.type !== 'newSelect' &&
row.type !== 'select' &&
lookFlag
"
>
{{ ruleForm[row.id] }}
</div>
<baseNewSelect
:disabled="true"
:ref="row.refName"
:apiInfo="row.apiInfo"
:searchApiInfo="row.searchApiInfo"
v-if="row.type === 'newSelect'"
v-model="ruleForm[row.id]"
:itemObj="row"
@showValue="showValueHandle"
:idKey="row.id"
:journalingType="row.journalingType"
:prop="row.prop"
:foucus="row.foucus"
:apiBody="row.apiBody"
:searchKey="row.searchKey"
>
</baseNewSelect>
<el-radio-group
v-model="ruleForm[row.id]"
v-if="row.type === 'radio'"
@input="changeRadio($event, index, indexRow, row)"
:disabled="true"
>
<el-radio v-for="el in row.options" :label="el.id" :key="el.id">{{
el.label
}}
</el-radio>
</el-radio-group>
<el-checkbox-group
class="w-100"
v-if="row.type === 'checkbox'"
v-model="ruleForm[row.id]"
>
{{ 123 }}
<el-checkbox
v-for="(el, index) in row.options"
:key="el.id"
:label="el.id"
>{{ el.label }}
</el-checkbox
>
</el-checkbox-group>
<baseCascader
v-if="row.type === 'treeselect'"
v-model="ruleForm[row.id]"
:disabled="row.disabled && !newFlag"
:itemObj="row"
:ruleForm="ruleForm"
:lookflag="lookFlag"
class="w-100"
></baseCascader>
<el-select
class="w-100"
v-model="ruleForm[row.id]"
filterable
@change="selectChange($event, index, indexRow, row)"
:disabled="true"
:clearable="row.clearable ? row.clearable : true"
:placeholder="!row.placeholder ? '请选择' : row.placeholder"
v-if="row.type === 'select' && lookFlag"
>
<el-option
v-for="(el, index) in row.options"
:key="!row.optionValue ? el['id'] : el[row.optionValue]"
:label="!row.optionLabel ? el['label'] : el[row.optionLabel]"
:value="!row.optionValue ? el['id'] : el[row.optionValue]"
>
</el-option>
</el-select>
</template>
<slot :name="row.slotName" v-if="row.tag === 'elSlot'"></slot>
</el-form-item>
</el-col>
</el-row>
<slot name="main"></slot>
<el-form-item v-if="false" style="margin-top: 20px; padding: 0 20px">
<!-- flex="cross:center main:center" -->
<div flex="main:right">
<el-button
v-if="isFunBtn"
class="saveBtn"
type="primary"
:loading="loading"
@click="submitForm(refName)"
>提交
</el-button
>
<el-button v-if="!lookFlag" @click="resetForm(refName)">重置</el-button>
<el-button v-if="isFunBtn" @click="close()">取消</el-button>
</div>
</el-form-item>
</el-form>
</template>
<script>
import baseCascader from "./baseCascader/index.vue";
import {deepClone} from "@/utils/index.js";
import baseDatePicker from "./baseDatePicker.vue";
import baseNewSelect from "./baseNewSelect";
import {checkMobile} from "@/utils/util";
import {BaseSelect} from "./baseSelect.vue";
export default {
components: {
// uploadFile,
// customCascader
baseNewSelect,
baseDatePicker,
baseCascader,
BaseSelect,
},
props: {
labelWidth: {
type: String,
default: "80px"
},
labelPosition: {
type: String,
default: 'top'
},
// 提交按钮loading
loading: {
type: Boolean,
default: false,
},
// 是否校验正则(搜索模式)
formRule: {
type: Boolean,
default: true,
},
refName: {
type: String,
default: "ruleForm",
},
// 表单新建模式
newFlag: {
type: Boolean,
default: false,
},
// 表单查看模式
lookFlag: {
type: [Boolean, String],
default: false,
},
// 表单显示格式
spanNumber: {
type: Number,
default: 12,
},
spanWidth: {
type: String,
default: "200px",
},
// 表单验证规则
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-end",
},
marginBottom: {
type: String,
default: "0",
},
ruleForm: {
type: Object,
default: () => {
return {};
},
},
tableColumn: {
type: Array,
default: () => {
return [];
},
},
},
data() {
return {
pickerOptionsSearch: {
shortcuts: [
{
text: "本月",
onClick(picker) {
picker.$emit("pick", [new Date(), new Date()]);
},
},
{
text: "今年至今",
onClick(picker) {
const end = new Date();
const start = new Date(new Date().getFullYear(), 0);
picker.$emit("pick", [start, end]);
},
},
{
text: "最近六个月",
onClick(picker) {
const end = new Date();
const start = new Date();
start.setMonth(start.getMonth() - 6);
picker.$emit("pick", [start, end]);
},
},
],
},
// 表单数据
// ruleForm: {},
pickerOptions: {
disabledDate(time) {
return time.getTime() > Date.now();
},
shortcuts: [
{
text: "今天",
onClick(picker) {
picker.$emit("pick", new Date());
},
},
{
text: "昨天",
onClick(picker) {
const date = new Date();
date.setTime(date.getTime() - 3600 * 1000 * 24);
picker.$emit("pick", date);
},
},
{
text: "一周前",
onClick(picker) {
const date = new Date();
date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
picker.$emit("pick", date);
},
},
],
},
tempFormData: {},
};
},
watch: {
ruleForm: {
immediate: true, // 立即执行
deep: true, // 深度监听复杂类型内变化
handler(newVal, oldVal) {
this.$emit("dataChanges");
},
},
},
created() {
this.tempFormData = deepClone(this.ruleForm);
},
mounted() {
// this.ruleForm = this.formdata
},
computed: {},
methods: {
dblclick(val) {
this.$emit('dblclick', val)
},
selectChangeHanlde(val, row) {
console.log(val, row, 111)
this.$emit("selectChange", val, row);
},
showValueHandle() {
},
limitPhoneNum(value, data, id) {
if (value.toString().length > 11) {
data[id] = value.toString().slice(0, 11);
}
},
selectShow(row) {
try {
this.$emit("selectFormSearch", row);
} catch (error) {
console.log(this.ruleForm, row, "23232出错了");
}
},
close() {
this.$emit("closeDialog");
},
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.id] = this.ruleForm[row.id]
.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, form) {
this.$emit("inputBlur", type, form)
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); // 清除表单特定属性
}
},
resetForm() {
this.$refs[this.rulesName].clearValidate(); // 清除表单特定属性
},
resetFields() {
// this.choiceAssignment({});
this.$refs.ruleForm.resetFields();
},
// 下拉框更改,可根据 index 与 indexRow 定位具体位置
selectChange(val, index, indexRow, row) {
this.$emit("onSelect", val, index, indexRow, row);
this.$forceUpdate();
},
switchChange(val, index, indexRow, row) {
this.$emit("switchChange", val, index, indexRow, row);
},
// 自定义级联选择器返回值
getCascader(value, field) {
this.$set(this.ruleForm, field, value);
},
// 表单提交
submitForm() {
this.$refs[this.refName].validate((valid) => {
if (valid) {
this.$emit("onSubmit", this.ruleForm);
} else {
console.log("error submit!!");
return false;
}
});
},
// 表单重置
resetForm() {
// let tempObj = deepClone(this.tempFormData);
// this.tableColumn
// .filter((item) => item.disabled)
// .forEach((item) => {
// tempObj[item.id] = this.ruleForm[item.id];
// });
// this.choiceAssignment({});
// this.$emit("resetForm", tempObj);
this.$refs[this.refName].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(row) {
this.$emit("selectTree");
if (this.$refs.ruleForm) {
this.$nextTick(() => {
this.$refs.ruleForm.validateField(row.id);
});
}
},
treeSelectClear() {
this.$refs.selectTree.clear();
},
},
mounted() {
// this.$refs.ruleForm.resetFields();
},
};
</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'>
.label {
/* @include fontBase(16px, #333333) ; */
color: #999;
font-size: 13px;
display: block;
width: 180px;
// text-align: left;
}
> > > .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;
}
}
::v-deep.stretchNone {
.el-textarea__inner {
resize: none;
}
}
</style>