https://github.com/bigbigbo/rule-editor.git
demo
<template>
<div>
<UniteCondition class="ftms-condition"
:rootCondition="rootCondition"
:variables="variables"
@changeData="changeData"
>
</UniteCondition>
</div>
</template>
<script>
import UniteCondition from './UniteCondition.vue'
// import Condition from './Condition.vue'/
export default {
name: 'ConditionView',
props: [],
data:()=>{
return{
rootCondition: {
id: 'ROOT',
type: 'and',
subConditions: [
{
id: '95fe42f0b1f395f9e20529b825e5599d',
type: 'normal',
expression: {
left: {
id: 'fb842a8d3730e7cd5a919fc8a0014214',
type: 'variable',
value: {
groupCode: ['kehu'],
groupLabel: '客户',
propCode: 'hunfou',
propLabel: '婚否'
}
},
operator: {
label: '等于',
charator: '=='
},
right: {
id: '769dfa8a8013d8987735d542df188021',
type: 'input',
value: '未婚'
}
}
},
{
id: '638b12ff1d67d0e61a3aace0f1e6a11c',
type: 'normal',
expression: {
left: {
id: 'f0c01555924010e52f9cc918c5a55d7d',
type: 'variable',
value: {
groupCode: ['kehu'],
groupLabel: '客户',
propCode: 'nianling',
propLabel: '年龄'
}
},
operator: {
label: '等于',
charator: '=='
},
right: {
id: '5a30eaec8e0ed46f49dcb25ebd51bc7c',
type: 'func',
value: {
actionName: 'date.action',
methodName: 'format',
methodLabel: '格式化日期',
parameters: [
{
name: '目标日期',
type: 'Date',
value: {
id: 'dfc3cd60659f125bcd5766905260b20c',
type: 'func',
value: {
actionName: 'date.action',
methodName: 'getDate',
methodLabel: '当前日期',
parameters: []
}
}
},
{
name: '格式',
type: 'String',
value: {
id: '150fea2a440d4a251c8e62982d7ef054',
type: 'input',
value: 'YYYYMMDD'
}
}
]
}
}
}
},
{
id: '9ee37340f10e30a944f23860f7b06afd',
type: 'normal',
expression: {
left: {
id: 'b83129403fcaaf3c70b330d4d53ae60b',
type: 'variable',
value: {
dicts: {
label: '性别',
value: 'sex',
children: [
{
label: '男',
value: '1'
},
{
label: '女',
value: '0'
}
]
},
groupCode: ['kehu'],
groupLabel: '客户',
propCode: 'xingbie',
propLabel: '性别'
}
},
operator: {
label: '等于',
charator: '=='
},
right: {
id: 'e12a208596c5525130399c43d507a3aa',
type: 'constant',
value: {
dicts: {
label: '性别',
value: 'sex',
children: [
{
label: '男',
value: '1'
},
{
label: '女',
value: '0'
}
]
},
dictType: 'sex',
dictTypeLabel: '性别',
code: '1',
label: '男'
}
}
}
},
{
id: '57d2401cb7b49f4643bd4ba775886fc5',
type: 'normal',
expression: {
left: {
id: 'a201a2e363defe1868233f469705437d',
type: 'variable',
value: {
dicts: {
label: '性别',
value: 'sex',
children: [
{
label: '男',
value: '1'
},
{
label: '女',
value: '0'
}
]
},
groupCode: ['kehu'],
groupLabel: '客户',
propCode: 'xingbie',
propLabel: '性别'
}
},
operator: {
label: '在集合中',
charator: 'in'
},
right: {
id: '911fb641ab283eccc1a17fd78601c551',
type: 'constant',
value: {
dicts: {
label: '性别',
value: 'sex',
children: [
{
label: '男',
value: '1'
},
{
label: '女',
value: '0'
}
]
},
dictType: 'sex',
dictTypeLabel: '性别',
code: '',
label: ''
}
}
}
},
{
id: '50757e83994e09379b35c4132e4415bb',
type: 'or',
subConditions: [
{
id: '0a2d8a7d952e124159226a69ed21fb15',
type: 'normal',
expression: {
left: {
id: '2956e9cc421afbb073f3fc537d2a7d49',
type: 'variable',
value: {
groupCode: ['kehu'],
groupLabel: '客户',
propCode: 'nianling',
propLabel: '年龄'
}
},
operator: {
label: '大于等于',
charator: '>='
},
right: {
id: 'aaee47dcbcd8b775ad98baf0be3171f8',
type: 'input',
value: '99'
}
}
},
{
id: '0a2d8a7d952e124159226a69ed21fb17',
type: 'normal',
expression: {
left: {
id: '2956e9cc421afbb073f3fc537d2a7d49',
type: 'variable',
value: {
groupCode: ['kehu'],
groupLabel: '客户',
propCode: 'nianling',
propLabel: '年龄'
}
},
operator: {
label: '大于等于',
charator: '>='
},
right: {
id: 'aaee47dcbcd8b775ad98baf0be3171f8',
type: 'input',
value: '99'
}
}
}
]
},
{
id: 'bbc7b9132e24deff907386b6c511fec2',
type: 'or',
subConditions: [
{
id: '1d1c6a532ac8222b8f45e05e59983688',
type: 'normal',
expression: {
left: {
id: '3a0dd38fea59adc86ba3bc3a86cee3c2',
type: 'variable',
value: {
groupCode: ['dingdan'],
groupLabel: '订单',
propCode: 'shuliang',
propLabel: '数量'
}
},
operator: {
label: '大于等于',
charator: '>='
},
right: {
id: 'f3e8f1bd1baf90153cabf5a7c3d119a0',
type: 'input',
value: '1000000'
}
}
},
{
id: '1d1c6a532ac8222b8f45e05e59983678',
type: 'normal',
expression: {
left: {
id: '3a0dd38fea59adc86ba3bc3a86cee3c2',
type: 'variable',
value: {
groupCode: ['dingdan'],
groupLabel: '订单',
propCode: 'shuliang',
propLabel: '数量'
}
},
operator: {
label: '大于等于',
charator: '>='
},
right: {
id: 'f3e8f1bd1baf90153cabf5a7c3d119a0',
type: 'input',
value: '1000000'
}
}
},
{
id: '1d1c6a532ac8222b8f45e05e59983668',
type: 'normal',
expression: {
left: {
id: '3a0dd38fea59adc86ba3bc3a86cee3c2',
type: 'variable',
value: {
groupCode: ['dingdan'],
groupLabel: '订单',
propCode: 'shuliang',
propLabel: '数量'
}
},
operator: {
label: '大于等于',
charator: '>='
},
right: {
id: 'f3e8f1bd1baf90153cabf5a7c3d119a0',
type: 'input',
value: '1000000'
}
}
},
{
id: 'bbc7b9132e24deff907286b6c511fec2',
type: 'or',
subConditions: [
{
id: '1d1c6a532ac8222b8f45e05e49983688',
type: 'normal',
expression: {
left: {
id: '3a0dd38fea59adc86ba3bc3a86cee3c2',
type: 'variable',
value: {
groupCode: ['dingdan'],
groupLabel: '订单',
propCode: 'shuliang',
propLabel: '数量'
}
},
operator: {
label: '大于等于',
charator: '>='
},
right: {
id: 'f3e8f1bd1baf90153cabf5a7c3d119a0',
type: 'input',
value: '1000000'
}
}
},
]
}
]
},
{
id: '1d1c6a532ac8222b8f35e05e59983468',
type: 'normal',
expression: {
left: {
id: '3a0dd38fea59adc86ba3bc3a86cee3c2',
type: 'variable',
value: {
groupCode: ['dingdan'],
groupLabel: '订单',
propCode: 'shuliang',
propLabel: '数量'
}
},
operator: {
label: '大于等于',
charator: '>='
},
right: {
id: 'f3e8f1bd1baf90153cabf5a7c3d119a0',
type: 'input',
value: '1000000'
}
}
}
]
},
variables:[
{
label: '客户',
value: 'kehu',
desc: '描述客户的一些信息',
children: [
{ label: '年龄', value: 'nianling', dictType: '' },
{ label: '性别', value: 'xingbie', dictType: 'sex' },
{ label: '婚否', value: 'hunfou', dictType: '' },
{
label: '订单',
value: '_dingdan',
children: [
{ label: '数量', value: '_shuliang' },
{ label: '名称', value: '_mingcheng' },
{ label: '价格', value: '_jiage' }
]
}
]
},
{
label: '订单',
value: 'dingdan',
desc: '描述订单的一些信息',
children: [
{ label: '数量', value: 'shuliang' },
{ label: '名称', value: 'mingcheng' },
{ label: '价格', value: 'jiage' }
]
}
],
}
},
components:{
UniteCondition,
// Condition
},
methods:{
changeData(){
alert(1);
console.log(this.rootCondition);
// this.rootCondition.subConditions[5].type = 'And';
this.getTreeName(this.rootCondition.subConditions,'1d1c6a532ac8222b8f45e05e59983688');
},
getTreeName(list,id){
let _this=this
for (let i = 0; i < list.length; i++) {
let a=list[i];
if(a.id === 'bbc7b9132e24deff907386b6c511fec2'){
let temp = {
id: '1d1c6a532ac8222b8f45e05e59983689',
type: 'normal',
expression: {
left: {
id: '3a0dd38fea59adc86ba3bc3a86cee3c2',
type: 'variable',
value: {
groupCode: ['dingdan'],
groupLabel: '订单',
propCode: 'shuliang',
propLabel: '数量'
}
},
operator: {
label: '大于等于',
charator: '>='
},
right: {
id: 'f3e8f1bd1baf90153cabf5a7c3d119a0',
type: 'input',
value: '1000000'
}
}
};
// a.subConditions.push(temp);
this.$set(a.subConditions,a.subConditions.length,temp)
}
if(a.id===id){
console.log(a);
// a.type = 'Andnd'
// a.expression.operator.label = 'Andnd'
this.$set(a.expression.operator,'label','Andnd');
// return a.type
alert(123);
}else{
if(a.subConditions && a.subConditions.length>0){
let res=_this.getTreeName(a.subConditions,id)
if(res){
// return res
}
}
}
}
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="less">
.ftms-condition:after{
content: '';
position: absolute;
width: 16px;
height: 1px;
background-color: #fff;
top: 20px;
left: -16px;
}
</style>
单项条件 condition
<template>
<div class="condition-wrap condition-wrap-before">
<el-cascader
style="margin-right:20px;"
:options="options"
v-model="selectedOptions">
</el-cascader>
<el-select style="margin-right:20px;width:80px;" v-model="Svalue" placeholder="请选择">
<el-option
v-for="item in Selectoptions"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
<el-input style="margin-right:20px;width: 120px;" v-model="input" placeholder="请输入内容"></el-input>
</div>
</template>
<script>
export default {
name: 'Condition',
props: [
'rootCondition'
],
data:()=>{
return {
input:'',
Svalue:'',
Selectoptions:[
{
value: '选项1',
label: '+'
}, {
value: '选项2',
label: '-'
}, {
value: '选项3',
label: '*'
}, {
value: '选项4',
label: '/'
}, {
value: '选项5',
label: '%'
}
],
selectedOptions:[],
options:[{
value: 'zhinan',
label: '指南',
children: [{
value: 'shejiyuanze',
label: '设计原则',
children: [{
value: 'yizhi',
label: '一致'
}]
}, {
value: 'daohang',
label: '导航',
children: [{
value: 'cexiangdaohang',
label: '侧向导航'
}, {
value: 'dingbudaohang',
label: '顶部导航'
}]
}]
}, {
value: 'zujian',
label: '组件',
children: [{
value: 'basic',
label: 'Basic',
children: [{
value: 'layout',
label: 'Layout 布局'
}]
}, {
value: 'form',
label: 'Form',
children: [{
value: 'radio',
label: 'Radio 单选框'
}, {
value: 'checkbox',
label: 'Checkbox 多选框'
}]
}, {
value: 'data',
label: 'Data',
children: [{
value: 'table',
label: 'Table 表格'
}]
}, {
value: 'notice',
label: 'Notice',
children: [{
value: 'alert',
label: 'Alert 警告'
}]
}, {
value: 'navigation',
label: 'Navigation',
children: [{
value: 'menu',
label: 'NavMenu 导航菜单'
}]
}, {
value: 'others',
label: 'Others',
children: [{
value: 'dialog',
label: 'Dialog 对话框'
}]
}]
}, {
value: 'ziyuan',
label: '资源',
children: [{
value: 'axure',
label: 'Axure Components'
}]
}]
}
},
created(){
// this.Svalue = this.rootCondition.expression.operator.label
},
watch:{
'rootCondition.expression':{
handler(newValue,oldValue){
console.log(newValue);
console.log(oldValue);
this.Svalue = newValue.operator.label
},
immediate:true,
deep:true
},
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="less">
.condition-wrap{
text-align: left;
margin-bottom: 10px;
position: relative;
}
.condition-wrap:before{
content: '';
position: absolute;
width: 16px;
height: 1px;
background-color: #c9c9c9;
top: 20px;
left: -16px;
}
</style>
联合条件 unitecondition
<template>
<div class="unite-condition">
<el-dropdown class="dropdown-wrap" split-button type="primary" @click="handleClick">
{{rootCondition.type}}
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>并且</el-dropdown-item>
<el-dropdown-item>或者</el-dropdown-item>
<el-dropdown-item divided>添加条件</el-dropdown-item>
<el-dropdown-item>添加联合条件</el-dropdown-item>
<el-dropdown-item divided v-if="rootCondition.id != 'ROOT'">删除</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<div :class="rootCondition.subConditions.length > 1? 'sub-condition border-sub-condition':'sub-condition'" v-if="rootCondition.subConditions">
<div v-for="item in rootCondition.subConditions" :key="item.id" class="sub-condition-wrap">
<!-- <UniteCondition v-bind="$attrs" v-on="$listeners" v-if="item.type != 'normal'" :rootCondition="item"></UniteCondition> -->
<UniteCondition v-if="item.type != 'normal'" :rootCondition="item"></UniteCondition>
<Condition v-bind="$attrs" v-on="$listeners" v-else :rootCondition="item"></Condition>
</div>
</div>
<el-button @click="changeData">修改数据+{{rootCondition.type}}</el-button>
</div>
</template>
<script>
import Condition from './Condition.vue'
export default {
name: 'UniteCondition',
props: [
'rootCondition',
'variables'
],
components:{
Condition
},
data:()=>{
return{
}
},
created(){
},
watch:{
rootCondition:{
handler(newValue,oldValue){
console.log('unite***********8');
console.log(newValue);
console.log(oldValue);
},
deep:true
},
},
methods:{
handleClick(){
},
changeData(){
this.$emit('changeData');
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped type="text/css" lang="less">
.unite-condition{
display: flex;
position: relative;
.dropdown-wrap{
margin-right: 16px;
height: 40px;
}
.dropdown-wrap:after{
content: '';
position: absolute;
width: 16px;
height: 1px;
background-color: #c9c9c9;
top: 20px;
right: -16px;
}
.sub-condition{
padding-left: 16px;
position: relative;
}
.sub-condition:before{
content: '';
position: absolute;
width: 1px;
height: 20px;
background-color: #fff;
top: 0;
left: -1px;
}
.sub-condition:after{
content: '';
position: absolute;
width: 1px;
height: 29px;
background-color: #fff;
bottom: 0;
left: -1px;
}
.border-sub-condition{
border-left: 1px solid #ddd;
}
.sub-condition-wrap{
position: relative;
}
}
.unite-condition:before{
content: '';
position: absolute;
width: 16px;
height: 1px;
background-color: #c9c9c9;
top: 20px;
left: -16px;
}
.sub-condition-wrap:before{
content: '';
position: absolute;
width: 1px;
height: 50px;
background-color: #fff;
top: 20px;
left: -132px;
}
</style>
app中调用
<template>
<div id="app">
<ConditionView
disabled={disabled}
ruleId={id}
rootCondition={rootCondition}
dispatch={dispatch}
constants={constants}
variables={variables}
funcs={funcs}
/>
</div>
</template>
<script>
import ConditionView from './components/ConditionView.vue'
export default {
name: 'App',
components: {
ConditionView
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>