最近项目上有一个需求,动态查询组件,要模仿人家Azure Devops的查询功能,我丢,Azure Devops是人家微软开发的个东西,我能模仿他的脸模仿不了他的那个啥。。。尴尬
上图,这是人家 Azure Devops的,确实挺好用挺灵活~~~
先上图,下面是我开发的组件
<template>
<div :class="{'marginClass': onlyOne}" v-if="reDraw">
<div :style="{'width': widthScreen + 'px'}" class="condition-header" v-if="onlyOne">
<div class="group-button">
组
<el-tooltip content="分组">
<svg-icon icon-class="group" class="group-button-icon" @click.stop="_addGroup"></svg-icon>
</el-tooltip>
</div>
<div :style="{'margin-left': (floor * 10 + 15) + 'px' }">且/或</div>
<div style="margin-left: 40px">字段/Path</div>
<div style="margin-left: 150px">运算符</div>
<div style="margin-left: 90px">值</div>
</div>
<div v-for="(item, index) in conditionList" :class="{'group-box':item.groups && item.groups.length > 1}"
:style="{'border-color': borderColor[item.floor],'padding-left': paddingLeft(floor,item),width: widthFunc(floor, item),'display': 'flex','flex-direction': 'column'}">
<div
:style="{'padding-left': paddingInner(floor,item) }"
v-if="!item.groups">
<div>
<i class="el-icon-circle-plus-outline color-success font-title-large" style="cursor: pointer"
@click="_addItem(item)"
></i>
<i class="el-icon-circle-close color-danger font-title-large" style="cursor: pointer;margin-left: 5px"
@click="_delItem(item)"
></i>
<el-checkbox style="padding: 0 5px 0 15px" v-model="item.checked"></el-checkbox>
</div>
<el-tooltip content="点击取消所在分组" v-if="item.pid != -1 && item.btn">
<svg-icon icon-class="group"
style="width: 20px;height: 20px; color: #409e6f; cursor: pointer; margin-left: -20px"
@click="_delGroup(item)"></svg-icon>
</el-tooltip>
<el-select v-model="item.operate" style="width: 60px;padding: 5px 0 5px 0" size="small">
<el-option v-for="ot in [{'key':'且','val':'and'},{'key':'或','val':'or'}]" :key="ot.val" :label="ot.key" :value="ot.val"></el-option>
</el-select>
<el-select v-model="item.field" style="width: 200px; margin-left: 10px" size="small">
<el-option v-for="ot in keyOptions" :key="ot.val" :label="ot.key" :value="ot.val"></el-option>
</el-select>
<el-select v-model="item.condition" style="width: 120px;margin-left: 10px" size="small">
<el-option v-for="ot in conditionSelect" :key="ot.val" :label="ot.key" :value="ot.val"></el-option>
</el-select>
<el-input v-model="item.value" style="width: 700px;margin-left: 10px" placeholder="值" clearable size="small"/>
</div>
<cron-group :conditionList="item.groups" v-if="item.groups && item.groups.length > 0" :only-one="false":floor="floor"></cron-group>
</div>
<el-tag v-if="onlyOne" size="small" style="margin-top: 10px; cursor: pointer" @click="_addChild">添加新的子句</el-tag>
</div>
</template>
addItem(groups, index, conditionList, parentThis) {
var newItem = Object.assign({}, condition, {
id: new Date().getTime(),
index: index + 1,
floor: groups[0].floor,
pid: groups[0].pid
})
groups.splice(index, 0, newItem)
var floorArr = []
this.reIndex(conditionList, 1, floorArr)
parentThis.floor = floorArr.length
},
addChild(conditionList) {
var newItem = Object.assign({}, condition, {
id: new Date().getTime(),
index: conditionList.length + 1,
floor: 1,
pid: -1
})
conditionList.splice(conditionList.length, 0, newItem)
},
delItem(groups, item, conditionList, parentThis) {
var sum = this.countItem(conditionList)
if (sum <= 1) {
return
}
groups.splice(item.index - 1, 1)
var currentGroups = this.findParentGroups(conditionList, groups[0].pid)
if (currentGroups) {
var parentGroups = this.findParentGroups(conditionList, currentGroups.pid)
if (currentGroups.groups.length == 1) {
var ag = JSON.parse(JSON.stringify(currentGroups.groups[0]))
ag.index = currentGroups.index
ag.id = currentGroups.id
ag.pid = parentGroups ? parentGroups.id : -1
ag.floor = currentGroups.floor
if (ag.groups) {
ag.groups.forEach((o, index) => {
o.pid = ag.id
o.floor = ag.floor + 1
o.index = index + 1
})
}
if (parentGroups) {
var _groups = this.findParentGroups(conditionList, parentGroups.id)
_groups.groups.splice(currentGroups.index - 1, 1, ag)
} else {
conditionList.splice(currentGroups.index - 1, 1, ag)
}
}
}
if (conditionList.length == 1 && conditionList[0].groups) {
var newList = JSON.parse(JSON.stringify(conditionList[0].groups))
conditionList.splice(0, 1)
for (var nl of newList) {
nl.pid = -1
nl.floor = 1
conditionList.push(nl)
}
}
var floorArr = []
this.reIndex(conditionList, 1, floorArr)
parentThis.floor = floorArr.length
},
addGroup(allItems, parentThis) {
var checkedList = this.findChecked(allItems)
if (!checkedList || checkedList.length <= 1) {
this.$message({
message: '至少选择2个查询条目',
type: 'warning',
duration: 1000
});
return
}
var checkNodes = []
for (var item of checkedList) {
if (item.pid == -1) {
this.uniquePush(checkNodes, item)
} else {
var pNode = this.getRealParent(allItems, item, checkedList)
if (pNode) {
this.uniquePush(checkNodes, pNode)
}
}
}
var _tmpRoot = []
for (var ck of checkNodes) {
var _tmp = this.findParentGroups(allItems, ck.pid)
if (_tmp) {
this.uniquePush(_tmpRoot, _tmp)
}
}
var allSelectCount = 0
var floorCount = []
for (var cn of checkNodes) {
if (cn.groups) {
allSelectCount += this.countItem(cn.groups)
} else {
allSelectCount++
}
if (floorCount.indexOf(cn.floor) == -1) {
floorCount.push(cn.floor)
}
}
var rootGroup = this.findParentGroups(allItems, checkNodes[0].pid)
if (_tmpRoot.length > 1) {
rootGroup = this.findParentGroups(allItems, rootGroup.pid)
allSelectCount = 0
for (var cn of _tmpRoot) {
if (cn.groups) {
allSelectCount += this.countItem(cn.groups)
} else {
allSelectCount++
}
}
}
var rootArray = allItems
if (rootGroup) {
rootArray = rootGroup.groups
}
var allCount = this.countItem(rootArray)
var currentSelectCount = checkedList.length
if (allSelectCount != currentSelectCount || floorCount.length > 1) {
this.$message({
message: '不能交叉分组',
type: 'warning',
duration: 1000
});
return
}
if (checkNodes.length == 1 || allCount == currentSelectCount) {
this.$message({
message: '无效分组',
type: 'warning',
duration: 1000
});
return
}
var newCheckNode = JSON.parse(JSON.stringify(checkNodes))
newCheckNode.sort(function (a, b) {
return a.index - b.index
})
var groupId = new Date().getTime()
var newGroup = {
groups: newCheckNode,
id: groupId,
index: newCheckNode[0].index,
pid: newCheckNode[0].pid,
floor: newCheckNode[0].floor
}
var waitRemoveNode = []
for (var o of newCheckNode) {
o.floor += 1
o.pid = groupId
if (!o.groups) {
o.checked = false
}
waitRemoveNode.push(o.id)
}
if (!rootGroup) {
this.removeNode(allItems, waitRemoveNode)
allItems.splice(newCheckNode[0].index - 1, 0, newGroup)
} else {
var _groups = this.findParentGroups(allItems, rootGroup.id)
this.removeNode(_groups.groups, waitRemoveNode)
_groups.groups.splice(newCheckNode[0].index - 1, 0, newGroup)
}
var floorArr = []
this.reIndex(allItems, 1, floorArr)
parentThis.floor = floorArr.length
},
delGroup(groups, conditionList, parentThis) {
var parentGroups = this.findParentGroups(conditionList, groups[0].pid)
var rootGroups = this.findParentGroups(conditionList, parentGroups.pid)
var waitRemoveNode = [parentGroups.id]
var newList = JSON.parse(JSON.stringify(groups));
newList.forEach((o, index) => {
o.pid = parentGroups.pid
o.floor = parentGroups.floor
o.checked = false
if (o.btn) {
o.btn = false
}
})
if (!rootGroups) {
this.removeNode(conditionList, waitRemoveNode)
newList.forEach((o, index) => {
conditionList.splice(parentGroups.index - 1 + index, 0, o)
})
} else {
var _groups = this.findParentGroups(conditionList, rootGroups.id)
this.removeNode(_groups.groups, waitRemoveNode)
newList.forEach((o, index) => {
_groups.groups.splice(parentGroups.index - 1 + index, 0, o)
})
}
var floorArr = []
this.reIndex(conditionList, 1, floorArr)
parentThis.floor = floorArr.length
},
??
用起来还不错,比较完美,他有的功能,咱也都有了?
|