需求:
根据用户选择公式条件,最终生成公式;
后端所需json较大举例IF函数:
{
"name": "技术质量管理",
"remark": "", //备注
"evaluateId": "1656117529237520387",
"previousResult": -1,
"type": "函数", //选择类型
"functionType": "IF", //具体函数类型 MIN、MAX、IF
"functionStr": "IF(H19=0,1,IF(H19<=2,0.9,(IF(H19<=5,0.7,IF(H19<=8,0.5,0.2)))))", //形成的函数表达式
"conditionParams": [
{ //IF条件
"expression": { //表达式参数
"variable": {
"des": "变量", //H31/H30*100<=100 IF(H5/H4>=0.8
"type": "指标值", //指标分值、指标值,带入结果
"previousResult": -1, //具体带入的结果步数 0,-1表示不带入
"indicatorInfo": { //type 为指标分值、指标值、指标内容分值等
"evaluateId": "1656117529237520388",
"name": "质量问题投诉(次)",
"indicatorId": "1655750184467955712",
"indicatorVersionId": "d2d160b1-67ad-4608-9759-d9f3dfea0f9f"
}
},
"condition": {
"des": "条件",
"type": "小于等于" //条件:大于、大于等于、小于、小于等于
},
"constant": {
"des": "常量",
"type": "填值",
"value:": 8 //具体填的值
}
},
"resultParams": { //结果参数
"params1": {
"des": "结果一",
"type": "填值", //填值、指标分值、指标值、带入结果
"value": 0.5, //具体填的值
"previousResult": -1 //具体带入的结果步数 0,-1表示不带入
},
"params2": {
"des": "结果二",
"type": "填值", //填值、指标分值、指标值、带入结果
"value": 0.2,
"previousResult": -1 //具体带入的结果步数 0,-1表示不带入
}
}
},
{
"previousConditionResult": 2, //具体带入的条件步数 0,-1表示不带入
"asResultOne": false, //是否作为结果一,否则作为结果二
"expression": { //表达式参数
"variable": {
"des": "变量", //H31/H30*100<=100 IF(H5/H4>=0.8
"type": "指标值", //指标分值、指标值,带入结果
"previousResult": -1, //具体带入的结果步数 0,-1表示不带入
"indicatorInfo": { //type 为指标分值、指标值、指标内容分值等
"evaluateId": "1656117529237520388",
"name": "质量问题投诉(次)",
"indicatorId": "1655750184467955712",
"indicatorVersionId": "d2d160b1-67ad-4608-9759-d9f3dfea0f9f"
}
},
"condition": {
"des": "条件",
"type": "等于" //条件:大于、大于等于、小于、小于等于
},
"constant": {
"des": "常量",
"type": "填值",
"value:": 0 //具体填的值
}
},
"resultParams": { //结果参数
"params1": {
"des": "结果一",
"type": "填值", //填值、指标分值、指标值、带入结果
"value": 0, //具体填的值
"previousResult": -1 //具体带入的结果步数 0,-1表示不带入
},
"params2": {
"des": "结果二",
"type": "填值", //填值、指标分值、指标值、带入结果
"value": null,
"previousResult": -1 //具体带入的结果步数 0,-1表示不带入
}
}
}
]
},
前端页面样式:
思路1:html代码中取数据,如遇带入步骤/带入条件则进行递归处理
item19,item 两个变量由于在老项目上改动,所以继续用了。
html代码中递归会出现很多问题,不好改动,后改为js写法。无需递归很简单的操作。
<template>
<span>
<span @click="dayin(item19)">
查看
</span>
IF(
<span v-if="item19.expression.variable.type == '指标值' || item19.expression.variable.type == '指标分值'">
{{ item19.expression.variable.indicatorInfo.name }}
</span>
<span v-if="item19.expression.variable.type == '填值'">
{{ item19.expression.variable.value }}
</span>
<span v-if="item19.expression.condition.type == '小于'"> < </span>
<span v-if="item19.expression.condition.type == '大于'"> > </span>
<span v-if="item19.expression.condition.type == '小于等于'"> <= </span>
<span v-if="item19.expression.condition.type == '大于等于'"> >= </span>
<span v-if="item19.expression.condition.type == '等于'"> = </span>
<span v-if="item19.expression.constant.type == '填值'">
{{ item19.expression.constant.value }} ,
</span>
<span v-if="item19.expression.constant.type == '指标值' || item19.expression.constant.type == '指标分值'">
{{ item19.expression.constant.indicatorInfo.name }}
,
</span>
<span v-if="item19.resultParams.params1.type == '带入步骤结果'">
<span v-if="item19.resultParams.params2.previousResult || item19.resultParams.params2.previousResult == 0">
<span v-if="item[item19.resultParams.params1.previousResult]">
<formula :item19="item[item19.resultParams.params1.previousResult].ifFunctionList[0]" :item="item" />
</span>
</span>
</span>
<span v-if="item19.resultParams.params1.type == '填值'">
{{ item19.resultParams.params1.value }} ,
</span>
<span v-if="item19.resultParams.params1.type == '带入条件结果'">
<span
v-if="item19.resultParams.params1.previousConditionResult || item19.resultParams.params1.previousConditionResult == 0">
<formula
:item19="item[item19.resultParams.params1.previousResult].ifFunctionList[item19.resultParams.params1.previousConditionResult]"
:item="item" />
</span>
</span>
<span v-if="item19.resultParams.params2.type == '带入步骤结果'">
<span v-if="item19.resultParams.params2.previousResult || item19.resultParams.params2.previousResult == 0">
<span v-if="item[item19.resultParams.params2.previousResult]">
<formula :item19="item[item19.resultParams.params2.previousResult].ifFunctionList[0]" :item="item" />
</span>
</span>
</span>
<span v-if="item19.resultParams.params2.type == '填值'">
{{ item19.resultParams.params2.value }}
</span>
<span v-if="item19.resultParams.params2.type == '带入条件结果'">
<span
v-if="item19.resultParams.params2.previousConditionResult || item19.resultParams.params2.previousConditionResult == 0">
<formula :item19="item.ifFunctionList[item19.resultParams.params2.previousConditionResult]" :item="item" />
</span>
</span>
)
</span>
</template>
<script>
import formula from './formula.vue';
export default {
name: "formula",
components: {
formula
},
data: function () {
return {
isShow: false,
tableInfo: [],
};
},
created() {
},
watch: {},
props: {
item: {
item: {
type: [Array, Object],
default: () => ({})
}
},
item19: {
type: Object
}
},
computed: {
},
methods: {
dayin(record) {
console.log('record =', record);
}
},
};
</script>
<style></style>
js代码如下:
// 设置 条件结果预览
conditionResultPreview(item19, item) {
let expression = "条件结果预览:IF(";
if(item19.expression.variable.type == '指标值' || item19.expression.variable.type == '指标分值'){
expression += item19.expression.variable.indicatorInfo.name;
}
if(item19.expression.variable.type == '填值'){
expression += item19.expression.variable.value;
}
if(item19.expression.condition.type == '小于') expression += ' < ';
if(item19.expression.condition.type == '大于') expression += ' > ';
if(item19.expression.condition.type == '小于等于') expression += ' <= ';
if(item19.expression.condition.type == '大于等于') expression += ' >= ';
if(item19.expression.condition.type == '等于') expression += ' = ';
if(item19.expression.constant.type == '填值'){
expression += item19.expression.constant.value + ',';
}
if(item19.expression.constant.type == '指标值' || item19.expression.constant.type == '指标分值'){
expression += item19.expression.constant.indicatorInfo.name
}
// 带入步骤结果
try {
if (item19.resultParams.params1.type == '带入步骤结果') {
if (item19.resultParams.params1.previousResult || item19.resultParams.params1.previousResult == 0) {
expression += this.tyPeList[item19.resultParams.params1.previousResult].ifFunctionList[this.tyPeList[item19.resultParams.params1.previousResult].ifFunctionList.length-1].formula + ','
}
}
} catch (error) {
// 处理错误的代码
}
// 带入条件结果
if(item19.resultParams.params1.type == '带入条件结果'){
if(item19.resultParams.params1.previousConditionResult || item19.resultParams.params1.previousConditionResult == 0){
expression += item.ifFunctionList[item19.resultParams.params1.previousConditionResult].formula +','
}
}
if(item19.resultParams.params1.type == '填值'){
expression += item19.resultParams.params1.value + ','
}
// 带入步骤结果
try {
if (item19.resultParams.params2.type == '带入步骤结果') {
if (item19.resultParams.params2.previousResult || item19.resultParams.params2.previousResult == 0) {
expression += this.tyPeList[item19.resultParams.params2.previousResult].ifFunctionList[this.tyPeList[item19.resultParams.params2.previousResult].ifFunctionList.length-1].formula
}
}
} catch (error) {
// 处理错误的代码
}
// 带入条件结果
if(item19.resultParams.params2.type == '带入条件结果'){
if(item19.resultParams.params2.previousConditionResult || item19.resultParams.params2.previousConditionResult == 0){
expression += item.ifFunctionList[item19.resultParams.params2.previousConditionResult].formula
}
}
if(item19.resultParams.params2.type == '填值'){
expression += item19.resultParams.params2.value
}
expression += ')'
item19.formula = expression;
return expression;
}
这边用到了try catch 防止报错导致程序不能运行,我只添加了报错(报错是因为数据没拿到)的条件下,这样能完美解决问题。并且方便拿到每个条件的数据,我认为这个方法比较好。
**
重构后代码:
重构后的代码将逻辑拆分为几个小函数,并且在 conditionResultPreview 函数中调用这些小函数处理相应的任务,并且针对空值和未定义的情况进行了检查。
使代码更加模块化和易于维护,同时可以提高代码的可复用性。
conditionResultPreview(item19, item) {
let expression = "IF(";
const { variable = {}, condition = {}, constant = {} } = item19.expression || {};
expression += this.getIndicatorOrValue(variable);
expression += this.getConditionSymbol(condition.type);
expression += this.getIndicatorOrValue(constant);
expression += this.addStepOrConditionResult(item19.resultParams.params1, this.tyPeList, item);
expression += this.addStepOrConditionResult(item19.resultParams.params2, this.tyPeList, item);
expression += ')';
item19.formula = expression;
return expression;
},
getIndicatorOrValue(obj) {
if (obj.type === '指标值' || obj.type === '指标分值') {
return obj.indicatorInfo?.name ?? '';
} else if (obj.type === '填值') {
return obj.value ?? '';
}
return '';
},
getConditionSymbol(type) {
switch (type) {
case '小于': return ' < ';
case '大于': return ' > ';
case '小于等于': return ' <= ';
case '大于等于': return ' >= ';
case '等于': return ' = ';
default: return '';
}
},
addStepOrConditionResult(params, tyPeList, item) {
if (params.type === '带入步骤结果' && params.previousResult != null && tyPeList && tyPeList[params.previousResult]) {
return `,${tyPeList[params.previousResult].ifFunctionList[tyPeList[params.previousResult].ifFunctionList.length - 1].formula}`;
} else if (params.type === '带入条件结果' && params.previousConditionResult != null && item && item.ifFunctionList) {
return `,${item.ifFunctionList[params.previousConditionResult].formula}`;
} else if (params.type === '填值') {
return `,${params.value ?? ''}`;
}
return '';
}