CN-1258: 实体搜索框支持has函数

This commit is contained in:
刘洪洪
2023-08-25 09:56:29 +08:00
parent 21f32dfdda
commit 7f91d75792
6 changed files with 119 additions and 49 deletions

View File

@@ -18,7 +18,6 @@
v-if="searchMode === 'tag'"
ref="tagMode"
:column-list="columnList"
:operator-list="showOperatorList"
:connection-list="showConnectionList"
:convert-meta-list="metaList"
:show-list="showList"
@@ -31,7 +30,7 @@
<script>
import TagMode from '@/components/advancedSearch/TagMode'
import TextMode from '@/components/advancedSearch/TextMode'
import { defaultOperatorList, defaultConnectionList } from '@/components/advancedSearch/meta/meta'
import { defaultConnectionList } from '@/components/advancedSearch/meta/meta'
import _ from 'lodash'
import { ref } from 'vue'
import Parser from '@/components/advancedSearch/meta/parser'
@@ -64,8 +63,6 @@ export default {
type: Array,
required: true
},
// 操作符列表
operatorList: Array,
// 连接符列表
connectionList: Array
},
@@ -133,12 +130,10 @@ export default {
}
}
}
// 如果参数中的operatorList、connectionList为空使用默认值
const showOperatorList = _.isEmpty(props.operatorList) ? defaultOperatorList : [...props.operatorList]
// 如果参数中的connectionList为空使用默认值
const showConnectionList = _.isEmpty(props.connectionList) ? defaultConnectionList : [...props.connectionList]
return {
searchMode,
showOperatorList,
showConnectionList
}
}

View File

@@ -29,10 +29,13 @@
></el-option>
</el-select>
</div>
<span v-show="!meta.column.isEditing" @click="columnClick(meta)">{{meta.column.label}}</span>
<span v-if="!meta.column.isEditing && meta.operator.value !== 'has'" @click="columnClick(meta)">{{meta.column.label}}</span>
<!--操作符是has时has需前置-->
<span v-else class="condition__operator">{{ meta.operator.value.toUpperCase() }}</span>
</div>
<!-- 已选操作符显示 -->
<div class="condition__operator" @click="operatorClick(meta)" v-if="meta.operator.show">{{meta.operator.value}}</div>
<div class="condition__operator" @click="operatorClick(meta)" v-if="meta.operator.show && meta.operator.value !== 'has'">{{meta.operator.value}}</div>
<div v-if="meta.operator.value === 'has'" class="condition__operator" style="color: #000C18">({{meta.column.label}},</div>
<!-- -->
<div class="condition__value">
<div v-if="meta.value.isEditing">
@@ -41,6 +44,8 @@
</div>
<span v-else @click="valueClick(meta)">{{meta.value.label}}</span>
</div>
<div v-if="meta.operator.show && meta.operator.value === 'has'">)</div>
<!-- 操作符选择器 -->
<div class="condition__operation-select" v-if="meta.operator.show && meta.operator.isEditing">
<div
@@ -107,7 +112,6 @@ export default {
name: 'TagMode',
props: {
columnList: Array,
operatorList: Array,
connectionList: Array,
convertMetaList: Array,
showList: Boolean
@@ -116,7 +120,8 @@ export default {
return {
condition,
connection,
metaList: []
metaList: [],
operatorList: [] // 操作符列表根据所选columnList的label来确定一般为=,INtags操作符为has
}
},
emits: ['changeMode', 'search'],
@@ -225,6 +230,9 @@ export default {
this.metaList.splice(index, 1)
}
}
// 根据所选label在columnList中匹配label来确定操作符一般为=,INtags操作符为has
const obj = this.columnList.find(t => t.label === meta.column.label)
this.operatorList = obj ? obj.doc.constraints.operator_functions.split(',') : ['=', 'IN']
}, 200)
},
connectionClick (meta) {

View File

@@ -2,6 +2,7 @@ import Meta, { connection, condition, columnType } from './meta'
import Token, { types } from './token'
import ParserError, { errorTypes, errorDesc } from '@/components/advancedSearch/meta/error'
import _ from 'lodash'
import { columnList } from '@/utils/static-data'
const strReg = {
all: /^[\da-zA-Z\s.'><!=-_(),%]$/,
@@ -94,6 +95,9 @@ export default class Parser {
} else if (meta.column.type === columnType.string) {
if (meta.operator.value.toLowerCase().indexOf('like') > -1 || meta.operator.value.toLowerCase().indexOf('in') > -1) {
str += `${meta.column.label} ${meta.operator.value} '${meta.value.value}' `
} else if (meta.operator.value.toLowerCase().indexOf('has') > -1) {
// 操作符为has时has函数需要提前格式为has(label,value)
str += `${meta.operator.value}(${meta.column.label},'${meta.value.value}') `
} else {
str += `${meta.column.label}${meta.operator.value}'${meta.value.value}' `
}
@@ -141,6 +145,9 @@ export default class Parser {
} else if (meta.column.type === columnType.string) {
if (meta.operator.value.toLowerCase().indexOf('like') > -1 || meta.operator.value.toLowerCase().indexOf('in') > -1) {
str += `${meta.column.label} ${meta.operator.value} '${meta.value.value}' `
} else if (meta.operator.value.toLowerCase().indexOf('has') > -1) {
// 操作符为has时has函数需要提前格式为has(label,value)
str += `${meta.operator.value}(${meta.column.label},'${meta.value.value}') `
} else {
str += `${meta.column.label}${meta.operator.value}'${meta.value.value}' `
}
@@ -582,6 +589,11 @@ export default class Parser {
if (prevToken.type === types.connection && [types.commonOperator, types.letterOperator].indexOf(nextToken.type) > -1) {
meta.column.type = columnType.string
meta.column.label = token.value
} else if (token.value.toLowerCase().indexOf('has(') > -1) {
meta.column.type = columnType.string
// 目前token.value为has(Tag但避免以后使用has函数的实体不限于Tag故截取has(后的内容
meta.column.label = token.value.substring(4)
meta.operator.value = 'has'
} else {
isColumn = false
}
@@ -589,6 +601,11 @@ export default class Parser {
if ([types.commonOperator, types.letterOperator].indexOf(nextToken.type) > -1) {
meta.column.type = columnType.string
meta.column.label = token.value
} else if (token.value.toLowerCase().indexOf('has(') > -1) {
meta.column.type = columnType.string
// 目前token.value为has(Tag但避免以后使用has函数的实体不限于Tag故截取has(后的内容
meta.column.label = token.value.substring(4)
meta.operator.value = 'has'
} else {
isColumn = false
}
@@ -775,7 +792,10 @@ export function handleMetaListToStr (metaList) {
// 长度为1时即模糊搜索例如搜索框值为1.1.1.1则直接返回1.1.1.1
// 如果为IP='1.1.1.1'的情况则从metaList拼接成IP='1.1.1.1'返回出去
if (metaList && metaList.length === 1) {
const arr = ['IP'.toLowerCase(), 'Domain'.toLowerCase(), 'App'.toLowerCase(), 'City'.toLowerCase(), 'Country'.toLowerCase(), 'ASN'.toLowerCase()]
const arr = []
columnList.forEach(item => {
arr.push(item.label.toLowerCase())
})
let label = metaList[0].column.label
let newStr = JSON.parse(JSON.stringify(label.toLowerCase()))
// 将str中的IP、Domain等替换为数组arr中的元素
@@ -785,7 +805,11 @@ export function handleMetaListToStr (metaList) {
// 检查str字段在arr中是否出现,true为出现过
const result = arr.some(item => newStr.includes(item))
if (result) {
return `${metaList[0].column.label} ${metaList[0].operator.value} ${metaList[0].value.label}`
if (metaList[0].operator.value.toLowerCase() === 'has') {
return `${metaList[0].operator.value}(${metaList[0].column.label},'${metaList[0].value.label}')`
} else {
return `${metaList[0].column.label} ${metaList[0].operator.value} ${metaList[0].value.label}`
}
} else {
const regex = /^["']|["']$/
// 去除两侧引号,如'1.1.1.1',避免校验时被当作app
@@ -797,10 +821,15 @@ export function handleMetaListToStr (metaList) {
} else if (metaList && metaList.length > 1) {
// 此为按语法搜索将metaList转为字符串
const newMetaList = []
let hasStr = ''
// 去除metaList的AND项
metaList.forEach(item => {
if (item.value !== 'AND') {
newMetaList.push(item)
if (item.column.label.toLowerCase() === 'tag') {
hasStr += `${item.operator.value}(${item.column.label},'${item.value.value}') AND `
} else {
newMetaList.push(item)
}
}
})
@@ -815,6 +844,9 @@ export function handleMetaListToStr (metaList) {
let str = newObj[i]
str = str.replace(/(\d+\.\d+\.\d+\.\d+),(\d+\.\d+\.\d+\.\d+)/g, "'$1','$2'")
lastObj[i] = `${i} IN (${str})`
} else if (i.toLowerCase() === 'tag') {
// lastObj[i] = `${i} = '${newObj[i]}'`
lastObj[i] = `has(${i},'${newObj[i]}')`
} else {
// 单独存在的,直接保留
lastObj[i] = `${i} = '${newObj[i]}'`
@@ -825,7 +857,7 @@ export function handleMetaListToStr (metaList) {
for (const i in lastObj) {
str += lastObj[i] + ' AND '
}
str = str.slice(0, -5)
str = str.slice(0, -5) + ' ' + hasStr.slice(0, -5)
return str
}