前端实现Aviator表达式编辑
显示效果

详细代码
<template>
<div class="formula-editor">
<div class="toolbar">
<div class="row">
常用变量
<button v-for="variable in variables" :key="variable.key" @click="appendText(variable, 0)">
{{ variable.desc }}
</button>
</div>
<div class="row">
运算符
<button v-for="operator in operators" :key="operator.key" @click="appendText(operator, 1)">
{{ operator.desc }}
</button>
</div>
<div class="row">
逻辑运算符
<button v-for="logically in logicoperators" :key="logically.key" @click="appendText(logically, 1)">
{{ logically.desc }}
</button>
</div>
<div class="row">
关联
<button v-for="relation in relations" :key="relation.key" @click="appendText(relation, 0)">
{{ relation.desc }}
</button>
</div>
<div class="row">
数字输入
<input type="number" v-model="numberInput" placeholder="输入数字" style="height: 25px;margin-right: 10px;" />
<button @click="appendNumber">插入数字</button>
</div>
<div class="row">
<button @click="reset">重置</button>
</div>
</div>
<draggable tag="div" class="editor" v-model="dynamicElements" @end="updateFormula">
<div v-for="(element, index) in dynamicElements" :key="index" class="dynamic-span">
{{ element.desc }}
<span class="delete-btn" @click="deleteElement(index)">✖</span>
</div>
</draggable>
<div class="result">
<p>公式: {{ formula }}</p>
</div>
</div>
</template>
<script>
import draggable from "vuedraggable";
export default {
components: {
draggable,
},
data() {
return {
variables: [
{ key: 'X', desc: '账单本金' },
{ key: 'Y', desc: '税额' },
{ key: 'Z', desc: '总金额' }
],
logicoperators: [
{ key: '+', desc: '加号' },
{ key: '-', desc: '减号' },
{ key: '*', desc: '乘号' },
{ key: '/', desc: '除号' },
{ key: '(', desc: '(' },
{ key: ')', desc: ')' }
],
operators: [
{ key: '>', desc: '大于' },
{ key: '>=', desc: '大于等于' },
{ key: '<', desc: '小于' },
{ key: '<=', desc: '小于等于' },
{ key: '==', desc: '等于' },
{ key: '!=', desc: '不等于' },
],
relations: [
{ key: '&&', desc: '且' },
{ key: '||', desc: '或' }
],
numberInput: '',
formula: '',
dynamicElements: [],
validationMessage: '',
isValid: true,
validationType: 'condition', // 新增选择框的类型
};
},
methods: {
appendText(text, type) {
const element = {
key: text.key,
desc: type === 0 ? text.desc : text.key,
};
this.dynamicElements.push(element);
this.updateFormula();
},
appendNumber() {
if (this.numberInput !== '') {
const element = {
key: this.numberInput,
desc: this.numberInput,
};
this.dynamicElements.push(element);
this.numberInput = '';
this.updateFormula();
}
},
deleteElement(index) {
this.dynamicElements.splice(index, 1);
this.updateFormula();
},
updateFormula() {
this.formula = this.dynamicElements.map(el => el.key).join(' ');
},
reset() {
this.dynamicElements = []; // 清空动态元素
this.formula = ''; // 重置公式
this.numberInput = ''; // 清空数字输入
},
},
};
</script>
<style>
.formula-editor {
border: 1px solid #dcdfe6;
padding: 20px;
width: 80%;
background-color: #f9f9f9;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
.toolbar {
margin-bottom: 20px;
}
.toolbar button {
margin-right: 10px;
padding: 6px 14px;
background-color: #409eff;
color: #fff;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s;
}
.toolbar button:hover {
background-color: #66b1ff;
}
.toolbar input {
height: 30px;
margin-right: 10px;
padding: 4px 10px;
border: 1px solid #dcdfe6;
border-radius: 4px;
transition: border-color 0.3s;
}
.toolbar input:focus {
border-color: #409eff;
}
.editor {
min-height: 50px;
border: 1px solid #ebeef5;
padding: 10px;
border-radius: 4px;
background-color: #fff;
white-space: pre-wrap;
word-wrap: break-word;
margin-top: 10px;
}
.result {
margin-top: 20px;
font-size: 16px;
color: #606266;
}
.row {
padding-bottom: 15px;
}
.dynamic-span {
position: relative;
background-color: #ecf5ff;
padding: 6px 12px;
margin-right: 5px;
border-radius: 4px;
display: inline-block;
font-size: 14px;
color: #409eff;
}
.delete-btn {
display: none; /* 默认隐藏 */
color: #f56c6c;
cursor: pointer;
position: absolute;
top: 0;
right: -5px;
transform: translateY(-50%);
background-color: white;
border: 1px solid #f56c6c;
border-radius: 50%;
width: 20px;
height: 20px;
text-align: center;
line-height: 18px;
font-size: 12px;
}
.dynamic-span:hover .delete-btn {
display: inline-block; /* 悬浮时显示 */
}
.dynamic-span:hover {
background-color: #c6e2ff;
}
.validation-result {
margin-top: 10px;
padding: 10px;
border-radius: 4px;
}
.error {
background-color: #f5c6cb;
color: #721c24;
}
.success {
background-color: #c3e6cb;
color: #155724;
}
</style>