一,需求分析
需求: 实现一个预警功能,需要动态配置一些参数,前端需要根据下拉选中类型实现动态添加表达式的功能;
二,功能实现
1.常用的复合型输入框

官网参考:input输入框
2.项目功能中需要一个可以编辑修改,下拉动态生成的表达式显示配置。
改装后的样子

可以添加多个配置名称的样子

以及实现表达式的查看,修改功能。下面简单介绍下实现过程:
a.新增时选择类型下拉,根据所选中的类型,动态生成表达式的名称和参数:

新增时如何动态生成表达式?
//新增确认
addSignConfig() {
this.editTitle = "新增";
this.addParamsList=[];
this.changeApp(); //动态选中触发方法
this.$refs.editForm.resetFields();
this.showButton = true;
this.signShow = true;
this.getAllwarnType();//类型下拉接口
},
类型下拉:
<FormItem prop="warnTypeId" label="预警类型名称">
<Select
v-model="editForm.warnTypeId"
clearable
filterable
class="search-input"
@on-change="changeApp(editForm.warnTypeId)"
:disabled="this.editTitle == '查看'||this.editTitle == '修改预警规则'" >
<Option
v-for="(item, index) in warnTypeList"
:key="`state-${index}`"
:value="item.code"
>{{ item.name }}</Option
>
</Select>
</FormItem>
b.动态生成新增时的表达式:
<FormItem label="表达式配置新增" prop="setExpression"
:maxlength="100" v-if="this.editTitle == '新增预警规则'&&this.addParamsList!=null">
<Input v-model="item.val" style="width: 320px" ref="setVal"
v-for="(item, index) in addParamsList" :key="`state-${index}`"
@on-blur="handleAddChange(index, item)">
<Select v-model="item.attrName" slot="prepend" style="width: 140px" disabled>
<Option :value="item.attrName">{{ item.attrName }}</Option >
</Select>
<Button slot="append" class='add' v-if="item.attrType==0" style="width: 72px">%</Button>
<Button slot="append" class='add' v-if="item.attrType==1" style="width: 72px">Number</Button>
<Button slot="append" class='add' v-if="item.attrType==2&&index!==1" style="width: 72px">String</Button>
<div slot="append" class='add' v-if="item.attrName=='失败代码'&&index===1" style="width: 58px;background-color:white">
<Icon v-if="item.attrName=='失败代码'&&index===1" custom="iconfont icon-jiahaoyou-lanx" size="22" color="#5173FF" @click="add()"></Icon>
<Icon v-if="item.attrName=='失败代码'&&index===1" custom="iconfont icon-jianshao" size="18" color="#5173FF" @click="del(index,item)"></Icon>
</div>
</Input>
</FormItem>
c.类型下拉接口的范例数据
params: "[{\"attr\":\"successRate\",\"attrName\":\"成功率低于\",\"attrTpe\":0}]"
d.选中类型时的方法
.map获取所需属性到新数组
changeApp(warnTypeId) {
if (warnTypeId == undefined) {
this.addParamsList=null;
return;
} else {
var fun = this.warnTypeList.filter(function (c, i, a) {
if (c.code == warnTypeId) {
return c.params;
}
});
this.downParamsList = JSON.parse(fun[0].params);
let setParamsList =this.downParamsList.map(item => {
return {
attr: item.attr,
attrName: item.attrName,
attrType:item.attrTpe,
val: "",
};
});
//失败代码顺序调换
if(setParamsList){
this.changeIndex(setParamsList);
}
this.addParamsList= setParamsList;
}
},
addParamsList:[]
根据 this.addParamsList生成表达式名称和表达式参数;
如此,就可以根据类型接口动态生成出表达式名称和输入框

e.接下来,输入数据,如何获取并保存数据呢?
使用@on-blur获取数据:
handleAddChange(index, item){
if(!this.$refs.setVal[index].value){
this.editForm.expression=""
}
if(this.$refs.setVal[index].value){
this.editForm.expression=JSON.stringify(this.addParamsList);
}
}
this.$refs.setVal[index].value获取输入框填入的值。
填写完数据后,可通过方法获取到实时填写的数据。这样就可以将新增的数据保存。
f.修改和查看与此功能比较类似,不过不用动态获取表达式配置参数和名称,直接从接口中获取
格式化处理取值即可。
获取参数样例:
expression: "[{\"attr\":\"count\",\"attrName\":\"次数\",\"attrType\":1,\"val\":\"1\"}]"
JSON.parse处理后显示:
修改:
// 获取:
if(this.editForm.expression){
// this.updateParamsList = JSON.parse(this.editForm.expression);
let getParamsList = JSON.parse(this.editForm.expression);
if(getParamsList){
this.changeIndex(getParamsList);
}
this.updateParamsList =getParamsList;
}
显示:
<FormItem label="表达式配置修改" prop="setExpression"
:maxlength="100" v-if="this.editTitle == '修改预警规则'&&this.updateParamsList.length>0">
<Input v-model="item.val" style="width: 320px" ref="setVal"
v-for="(item, index) in updateParamsList" :key="`state-${index}`"
@on-blur="handleUpdateChange(index,item)">
<Select v-model="item.attrName" slot="prepend" style="width: 140px" disabled>
<Option :value="item.attrName">{{ item.attrName }}</Option >
</Select>
<Button slot="append" class='add' v-if="item.attrType==0" style="width: 72px">%</Button>
<Button slot="append" class='add' v-if="item.attrType==1" style="width: 72px">Number</Button>
<Button slot="append" class='add' v-if="item.attrType==2&&index!==1" style="width: 72px">String</Button>
<div slot="append" class='add' v-if="item.attrName=='失败代码'&&index===1" style="width: 58px;background-color:white">
<Icon v-if="item.attrName=='失败代码'&&index===1" custom="iconfont icon-jiahaoyou-lanx" size="22" color="#5173FF" @click="adds()"></Icon>
<Icon v-if="item.attrName=='失败代码'&&index===1" custom="iconfont icon-jianshao" size="18" color="#5173FF" @click="dels(index,item)"></Icon>
</div>
</Input>
</FormItem>
保存: this.editForm.expression
JSON.stringify转换后保存
handleUpdateChange(index, item){
if(!this.$refs.setVal[index].value){
this.editForm.expression=""
}
if(this.$refs.setVal[index].value){
this.editForm.expression=JSON.stringify(this.updateParamsList);
}
}
这样,就可以实现表达式的修改保存
修改样例传参:
expression: "[{\"attr\":\"count\",\"attrName\":\"次数\",\"attrType\":1,\"val\":\"1\"}]"

查看的方法比较类似,直接将输入框禁用掉即可
3.校验表达式输入:顺序,重复,类型及动态添加删除
a,校验顺序
配置多个名称时,将失败代码次数放到顶部,便于查看。
changeIndex(failList){
if(failList&&failList[0].attrName=="失败代码"){
let tempFirst = failList[0];
let tempSecond = failList[1];
failList[0] = tempSecond;
failList[1] = tempFirst;
}
return failList
},
b,配置多个失败代码的重复校验
new Set去重比较长度判断是否重复
.filter剔除多余的undefined值
let arr=this.addParamsList.map(item =>{
if(item.attrType==2||item.attrType==3){
return item.val;
}
}).filter(iten => iten!=undefined);
let cutRepeat = Array.from(new Set(arr));
if (cutRepeat.length < arr.length) {
this.$Message.error('失败代码不能重复')
return
}
c,其它类型范围校验
.some非空校验
if (this.updateParamsList.some((item) => item.val=== "")) {
this.$Message.error('表达式配置参数不能为空!!!');
return;
}
其它类型校验
表达式:
非数字 isNaN
次数或特殊字段检测 search
正整数正则: !(/(^[1-9]\d*$)/.test(item.val))
//表达式校验
if (this.updateParamsList.some((item) => item.attrType===0&&isNaN(item.val)===true)){
this.$Message.error('表达式配置参数百分比必须为数字!!!');
return;
}
if (this.updateParamsList.some((item) => item.attrType===0&&item.val<0)) {
this.$Message.error('表达式配置参数百分比范围为0~100 !!!');
return;
}
if (this.updateParamsList.some((item) => item.attrType===0&&item.val>100)) {
this.$Message.error('表达式配置参数百分比范围为0~100 !!!');
return;
}
//次数校验
if (this.updateParamsList.some((item) =>(item.attrType===1&&item.attrName.search("次数")!=-1)&&!(/(^[1-9]\d*$)/.test(item.val))) ) {
this.$Message.error('表达式配置参数次数必须为正整数!!!');
return;
}
//余额校验
if (this.updateParamsList.some((item) => item.attrType===1&&item.attrName=="余额小于"&&isNaN(item.val)===true)){
this.$Message.error('表达式配置参数余额必须为数字!!!');
return;
}
if (this.updateParamsList.some((item) => item.attrType===1&&item.attrName=="余额小于"&& item.val<-10)) {
this.$Message.error('表达式配置参数余额负数最大为-10!!!');
return;
}
//失败代码校验
if (this.updateParamsList.some((item) => item.attrType===2)&&this.updateParamsList.length>21) {
this.$Message.error('表达式配置参数失败代码最大为20条!!!');
return;
}
d.新增多个失败代码时新增,删除的方法
新增
add(){
if (this.addParamsList[0].attrName=="失败代码"&&this.addParamsList[0].val=="") {
this.$Message.warning('请先填写前一个失败代码')
return
}
//失败代码条数校验
if (this.addParamsList.length>20) {
this.$Message.warning('失败代码最多添加20个')
return
}
//失败代码重复校验
let arr=this.addParamsList.map(item =>{
if(item.attrType==2||item.attrType==3){
return item.val;
}
}).filter(iten => iten!=undefined);
let cutRepeat = Array.from(new Set(arr));
if (cutRepeat.length < arr.length) {
this.$Message.warning('失败代码重复或存在多个空值')
return
}
let obj = this.addParamsList[this.addParamsList.length-1]
if (!obj.val&&obj.attrName=="失败代码") {
this.$Message.warning('请先填写前一个失败代码')
}else{
this.addParamsList.push({
attr:"code",
attrName:"失败代码",
val:"",
attrType:"2"
})
}
},
删除
del(index,item){
if(this.addParamsList.length ===2){
this.$Message.warning('至少有一个失败代码,不可删除!!')
return
}if(this.addParamsList.length >2){
this.addParamsList.splice(this.addParamsList.length-1, 1)
}
this.handleAddChange(index, item);
},
这样就用复合型input实现了动态生成表达式,修改查看,动态添加删除校验功能!!!。

此文仅input功能小小使用,简单总结,便于交流学习改进,喜欢就多点点关注评论,一起学习进步。