|
@@ -0,0 +1,239 @@
|
|
|
+<template>
|
|
|
+ <div class="condition-box">
|
|
|
+ <div :class="{'parent': showParentBorder}">
|
|
|
+ <div v-for="(val, i) in list" :key="i" class="item">
|
|
|
+ <el-row :gutter="10" v-if="!val.children.length">
|
|
|
+ <el-col :span="6">
|
|
|
+ <el-select v-model="val.key" filterable placeholder="请选择事件指标">
|
|
|
+ <el-option v-for="item in eventIndicator" :key="item.value" :label="item.name" :value="item.value"/>
|
|
|
+ </el-select>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="6">
|
|
|
+ <el-select v-model="val.operation" filterable placeholder="请选择运算规则">
|
|
|
+ <el-option v-for="item in operator" :key="item.value" :label="item.remark" :value="item.operation"/>
|
|
|
+ </el-select>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="6">
|
|
|
+ <el-input v-model="val.value" clearable placeholder="请输入数值" />
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="6">
|
|
|
+ <el-button text circle @click="handleDelete(i)">
|
|
|
+ <Icon icon="ep:close" />
|
|
|
+ </el-button>
|
|
|
+ <el-button v-if="list.length >= 2" @click="handleItemAdd(i)" text><Icon class="mr-5px" icon="ep:plus" />并且满足</el-button>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <template v-else>
|
|
|
+ <div class="parent">
|
|
|
+ <div v-for="(_val, index) in val.children" :key="index" class="item">
|
|
|
+ <el-row :gutter="10">
|
|
|
+ <el-col :span="6">
|
|
|
+ <el-select v-model="_val.key" filterable placeholder="请选择事件指标">
|
|
|
+ <el-option v-for="item in eventIndicator" :key="item.value" :label="item.name" :value="item.value"/>
|
|
|
+ </el-select>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="6">
|
|
|
+ <el-select v-model="_val.operation" filterable placeholder="请选择运算规则">
|
|
|
+ <el-option v-for="item in operator" :key="item.value" :label="item.remark" :value="item.operation"/>
|
|
|
+ </el-select>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="6">
|
|
|
+ <el-input v-model="_val.value" clearable placeholder="请输入数值" />
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="6">
|
|
|
+ <el-button text circle @click="handleDelete(index, val.children, i)">
|
|
|
+ <Icon icon="ep:close" />
|
|
|
+ </el-button>
|
|
|
+ <el-button v-if="index === 0" @click="handleItemAdd(index, val.children)" text><Icon class="mr-5px" icon="ep:plus" />并且满足</el-button>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <div class="relation">
|
|
|
+ <div :class="['relation-item', {'active': k.active}]" v-for="k in val.relationList" :key="k.value" @click="handleActive(k, val.relationList, val)">{{ k.text }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
+ <div v-if="list.length >= 2" class="relation">
|
|
|
+ <div :class="['relation-item', {'active': k.active}]" v-for="k in relationList" :key="k.value" @click="handleActive(k)">{{ k.text }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <el-button text type="primary" @click="handleAdd"><Icon class="mr-5px" icon="ep:plus" />筛选条件</el-button>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+defineOptions({ name: 'Condition'})
|
|
|
+import { cloneDeep } from 'lodash-es'
|
|
|
+import { checkObjectValues } from './check'
|
|
|
+import { getOperationList, getEventIndicatorList } from '@/api/menduner/system/integral'
|
|
|
+
|
|
|
+const emit = defineEmits(['submit'])
|
|
|
+const props = defineProps({
|
|
|
+ itemData: Object
|
|
|
+})
|
|
|
+
|
|
|
+const message = useMessage() // 消息弹窗
|
|
|
+const query = ref({
|
|
|
+ operation: 'AND',
|
|
|
+ type: 'RELATION',
|
|
|
+ children: []
|
|
|
+})
|
|
|
+
|
|
|
+const list = ref([
|
|
|
+ { key: '', operation: '', value: '', type: 'EXPRESSION', children: [] }
|
|
|
+])
|
|
|
+
|
|
|
+const showParentBorder = computed(() => {
|
|
|
+ return (list.value && list.value.length === 1 && list.value[0].children.length) ? false : true
|
|
|
+})
|
|
|
+
|
|
|
+const relationList = ref([
|
|
|
+ { text: '且', active: true, value: 'AND' },
|
|
|
+ { text: '或', active: false, value: 'OR' }
|
|
|
+])
|
|
|
+
|
|
|
+
|
|
|
+// 获取运算符列表、事件指标列表
|
|
|
+const operator = ref([])
|
|
|
+const eventIndicator = ref([])
|
|
|
+const getData = async () => {
|
|
|
+ operator.value = await getOperationList()
|
|
|
+ eventIndicator.value = await getEventIndicatorList()
|
|
|
+}
|
|
|
+getData()
|
|
|
+
|
|
|
+// 添加筛选条件
|
|
|
+const handleAdd = () => {
|
|
|
+ list.value.push({ key: '', operation: '', type: 'EXPRESSION', value: '', children: [] })
|
|
|
+}
|
|
|
+
|
|
|
+// 删除筛选条件
|
|
|
+const handleDelete = (index, arr, parentIndex) => {
|
|
|
+ if (arr && arr.length) {
|
|
|
+ // 当children长度为2时变回一级
|
|
|
+ if (arr.length === 2) {
|
|
|
+ list.value[parentIndex] = { key: '', operation: '', value: '', type: 'EXPRESSION', children: [] }
|
|
|
+ return
|
|
|
+ }
|
|
|
+ arr.splice(index, 1)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (list.value.length === 1) return message.warning('最少保留一个触发条件')
|
|
|
+ list.value.splice(index, 1)
|
|
|
+}
|
|
|
+
|
|
|
+// 选择且或关系
|
|
|
+const handleActive = (k, arr, parentVal) => {
|
|
|
+ if (arr && arr.length) {
|
|
|
+ arr.forEach(e => e.active = false)
|
|
|
+ k.active = true
|
|
|
+ parentVal.operation = k.value
|
|
|
+ return
|
|
|
+ }
|
|
|
+ relationList.value.forEach(e => e.active = false)
|
|
|
+ k.active = true
|
|
|
+ query.value.operation = k.value
|
|
|
+}
|
|
|
+
|
|
|
+// 并且满足
|
|
|
+const handleItemAdd = (i, arr) => {
|
|
|
+ const obj = { key: '', operation: '', value: '', type: 'EXPRESSION', children: [] }
|
|
|
+ const item = {
|
|
|
+ type: 'RELATION',
|
|
|
+ operation: 'AND',
|
|
|
+ relationList: cloneDeep(relationList.value),
|
|
|
+ children: [cloneDeep(obj), cloneDeep(obj)]
|
|
|
+ }
|
|
|
+ if (arr && arr.length) return arr.push(cloneDeep(obj))
|
|
|
+ list.value.splice(i, 1, item)
|
|
|
+}
|
|
|
+
|
|
|
+// 编辑回显
|
|
|
+watch(
|
|
|
+ () => props.itemData,
|
|
|
+ (newVal) => {
|
|
|
+ if (!newVal) return
|
|
|
+ const data = cloneDeep(newVal)
|
|
|
+ if (data.children && !data.children.length) {
|
|
|
+ list.value = [data]
|
|
|
+ } else {
|
|
|
+ list.value = data.children.map(e => {
|
|
|
+ if (e.type === 'RELATION') {
|
|
|
+ e.relationList = cloneDeep(relationList.value)
|
|
|
+ e.relationList.forEach(e => e.active = false)
|
|
|
+ const obj = e.relationList.find(j => j.value === e.operation)
|
|
|
+ if (obj) obj.active = true
|
|
|
+ }
|
|
|
+ return e
|
|
|
+ })
|
|
|
+ query.value = data
|
|
|
+ relationList.value.forEach(e => {
|
|
|
+ e.active = false
|
|
|
+ if (e.value === data.operation) e.active = true
|
|
|
+ })
|
|
|
+ }
|
|
|
+ },
|
|
|
+ { deep: true }
|
|
|
+)
|
|
|
+
|
|
|
+const result = {}
|
|
|
+const getQuery = () => {
|
|
|
+ // const check = list.value.every(e => checkObjectValues(e))
|
|
|
+ // if (!check) return message.warning('请将条件中的项填写完整')
|
|
|
+
|
|
|
+ if (list.value.length === 1) result.value = list.value[0]
|
|
|
+ else result.value = { ...query.value, children: list.value }
|
|
|
+ return result.value
|
|
|
+}
|
|
|
+
|
|
|
+defineExpose({
|
|
|
+ getQuery
|
|
|
+})
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+.el-row {
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.condition-box {
|
|
|
+ padding: 20px;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ // margin-left: 120px !important;
|
|
|
+ border: 1px solid #ccc;
|
|
|
+}
|
|
|
+
|
|
|
+.text-end {
|
|
|
+ text-align: end;
|
|
|
+}
|
|
|
+
|
|
|
+.parent {
|
|
|
+ position: relative;
|
|
|
+ padding-left: 50px;
|
|
|
+ border-left: 1px solid #ccc;
|
|
|
+
|
|
|
+ .relation {
|
|
|
+ position: absolute;
|
|
|
+ top: 50%;
|
|
|
+ left: -12px;
|
|
|
+ font-size: 14px;
|
|
|
+ color: #666;
|
|
|
+ background-color: #eee;
|
|
|
+ transform: translateY(-50%);
|
|
|
+
|
|
|
+ .relation-item {
|
|
|
+ padding: 3px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .active {
|
|
|
+ color: #fff;
|
|
|
+ background-color: #409eff;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.item {
|
|
|
+ margin-bottom: 20px;
|
|
|
+}
|
|
|
+</style>
|