+
+
selectValue(value, meta)"
>
+
+
+
+ selectValues(value, meta)"
+ @visible-change="(value) => selectVisibleValues(value, meta)"
+ popper-class="my-select-class"
+ >
+
+ {{ meta.value.value }}
+
+
+
+
+
+
+
0) {
+ let str = ''
+ value.forEach(item => {
+ str += `'${item}',`
+ })
+ str = str.substring(0, str.length - 1)
+ str = `(${str})`
+ meta.value.value = str
+ meta.value.label = str
+ } else {
+ meta.value.value = ''
+ }
+ },
selectConnection (value, meta) {
meta.isEditing = false
},
- columnClick (meta) {
- meta.column.isEditing = true
- this.$nextTick(() => {
- this.$refs.columnSelect[this.$refs.columnSelect.length - 1].focus()
- })
- },
columnBlur (meta, index) {
setTimeout(() => {
const parser = new Parser(this.columnList)
@@ -276,27 +325,60 @@ export default {
this.operatorList = obj ? obj.doc.constraints.operator_functions.split(',') : ['=', 'IN']
if (meta.column && meta.column.type === 'fullText') {
meta.operator.value = '='
- meta.column.show = false
+ meta.column.show = true
meta.column.isFullText = true
- meta.operator.show = false
+ meta.operator.show = true
const label = JSON.parse(JSON.stringify(meta.column.label))
meta.column.label = parser.getEntityTypeByValue(meta.column.label)
meta.value.value = label
meta.value.label = label
- // if (meta.column.label === 'domain') {
- // meta.operator.value = 'like'
- // meta.value.value = `%${this.delSingleQuote(label)}`
- // meta.value.label = `${this.delSingleQuote(label)}`
- // } else if (meta.column.label === 'app') {
- // meta.operator.value = 'like'
- // meta.value.value = `%${this.delSingleQuote(label)}%`
- // meta.value.label = `${this.delSingleQuote(label)}`
- // }
+ if (meta.column.label === 'domain') {
+ meta.operator.value = 'like'
+ meta.value.value = `%${this.delSingleQuote(label)}`
+ meta.value.label = `%${this.delSingleQuote(label)}`
+ } else if (meta.column.label === 'app') {
+ meta.operator.value = 'like'
+ meta.value.value = `%${this.delSingleQuote(label)}%`
+ meta.value.label = `%${this.delSingleQuote(label)}%`
+ }
meta.column.type = 'string'
}
}, 200)
},
+ valueBlur1 (meta) {
+ setTimeout(() => {
+ meta.value.isEditing = false
+ }, 200)
+ },
+ valuesBlur (meta) {
+ this.$nextTick(() => {
+ })
+ },
+ valuesFocus (meta) {
+ this.$nextTick(() => {
+ meta.value.isEditing = true
+ setTimeout(() => {
+ if (meta.value.value && this.myCheckboxList.length === 0) {
+ let valueArr = []
+ if (!_.isArray(meta.value.value)) {
+ let value = meta.value.value
+ if (value.indexOf('(') === 0 && value.indexOf(')') === value.length - 1) {
+ value = value.substring(1, value.length)
+ value = value.substring(0, value.length - 1)
+ }
+ valueArr = value.split(',')
+ valueArr.forEach((item, index) => {
+ if (item[0] === "'" && item[item.length - 1] === "'") {
+ item = item.substring(1, item.length - 1)
+ this.myCheckboxList.push(item)
+ }
+ })
+ }
+ }
+ }, 100)
+ })
+ },
connectionClick (meta) {
meta.isEditing = true
},
@@ -314,7 +396,7 @@ export default {
// 若是in或not in,column的type要改成array,否则是string
if (operator.toLowerCase().indexOf('in') > -1) {
meta.column.type = columnType.array
- meta.value.value = []
+ // meta.value.value = []
} else if (['>', '<', '>=', '<='].indexOf(operator) > -1) {
meta.column.type = columnType.number
} else {
@@ -480,10 +562,26 @@ export default {
}
meta.value.isEditing = !meta.isCompleteCondition()
},
+ columnClick (meta) {
+ meta.column.isEditing = true
+ this.$nextTick(() => {
+ this.$refs.columnSelect[this.$refs.columnSelect.length - 1].focus()
+ })
+ },
valueClick (meta) {
meta.value.isEditing = true
+ const obj = enumerateData.find(d => d.name === meta.column.label)
+ if (obj) {
+ meta.doc = obj
+ }
this.$nextTick(() => {
- this.$refs.valueInput[0].focus()
+ if (this.$refs.valueInput) {
+ this.$refs.valueInput[0].focus()
+ }
+ if (this.$refs.valuesSelect) {
+ // 触发focus后,select弹窗并没有生效
+ this.$refs.valuesSelect[0].focus(meta)
+ }
})
},
// 判断是否是用户自己添加的内容,用于判断是否是全局搜索
@@ -515,7 +613,8 @@ export default {
const str = strObj.str ? strObj.str : strObj
const str2 = strObj.str2 ? strObj.str2 : strObj
// str为将metaList转成字符串的值,str2为地址栏展示的值
- const key = parser.handleEntityTypeByStr(str)
+ let key = parser.handleEntityTypeByStr(str)
+ key = parser.conversionEnum(key)
this.$emit('search', { ...parser.parseStr(key), str: str2, keywordList: keywordList })
} else {
this.$message.error(handleErrorTip(errorList[0]))
diff --git a/src/components/advancedSearch/TextMode.vue b/src/components/advancedSearch/TextMode.vue
index 451acb0d..59bfdc76 100644
--- a/src/components/advancedSearch/TextMode.vue
+++ b/src/components/advancedSearch/TextMode.vue
@@ -178,9 +178,13 @@ export default {
}
})
if (keyInfo.isKey) {
- const errorList = parser.validateStr(keyInfo.key)
+ // 检查是否包含枚举字段,包含的话进行替换
+ const enumKey = parser.conversionEnum(keyInfo.key)
+ const errorList = parser.validateStr(newKey)
if (_.isEmpty(errorList)) {
- this.$emit('search', { ...parser.parseStr(keyInfo.key), str: str, keywordList: keywordList })
+ // 补全模糊搜索
+ toRaw(this.codeMirror).setValue(parser.handleEntityTypeByStr(str))
+ this.$emit('search', { ...parser.parseStr(enumKey), str: parser.handleEntityTypeByStr(str), keywordList: keywordList })
} else {
this.$message.error(handleErrorTip(errorList[0]))
}
diff --git a/src/components/advancedSearch/meta/parser.js b/src/components/advancedSearch/meta/parser.js
index 7650bbb4..16048c06 100644
--- a/src/components/advancedSearch/meta/parser.js
+++ b/src/components/advancedSearch/meta/parser.js
@@ -12,6 +12,7 @@ const strReg = {
value: /^[\da-zA-Z\u4E00-\u9FA5\u3040-\u309F\u0800-\u4e00\u0400-\u04FF\u2000-\u206F\s.'-_%]$/
}
const operatorList = ['=', ' in ', ' IN ', ' like ', ' LIKE ', 'HAS(', 'has(']
+const enumList = ['status', 'eventType', 'severity']
export default class Parser {
constructor (columnList) {
@@ -1476,6 +1477,47 @@ export default class Parser {
return this.columnList.find(t => t.label.toLowerCase() === label.toLowerCase())
}
+
+ /**
+ * 检测str是否包含枚举字段,包含的话,进行替换
+ * @param str
+ * @returns {string|*}
+ */
+ conversionEnum (str) {
+ if (str) {
+ let enumFlag = false // 判断字符串是否包含枚举类型的key,不包含则直接返回
+ enumList.forEach(item => {
+ if (str.toLocaleLowerCase().indexOf(item.toLocaleLowerCase()) > -1) {
+ enumFlag = true
+ }
+ })
+ if (enumFlag) {
+ let key = _.cloneDeep(str)
+ let searchList = [] // 将字符串按AND分割成单独的搜索条件
+ if (key.indexOf(' AND ') > -1) {
+ searchList = key.split(' AND ')
+ } else {
+ searchList = [key]
+ }
+ searchList.forEach((item, index) => {
+ const obj = this.columnList.find(d => item.indexOf(d.label) > -1)
+ if (obj && obj.doc.data) {
+ obj.doc.data.forEach(item1 => {
+ if (item.indexOf(item1.code) > -1) {
+ searchList[index] = searchList[index].replace(new RegExp(item1.code, 'g'), item1.value)
+ }
+ })
+ }
+ })
+ key = searchList.join(' AND ')
+ return key
+ } else {
+ return str
+ }
+ } else {
+ return str
+ }
+ }
}
// 使用单引号包裹
diff --git a/src/views/detections/DetectionFilter.vue b/src/views/detections/DetectionFilter.vue
index 220ba96e..bacce05b 100644
--- a/src/views/detections/DetectionFilter.vue
+++ b/src/views/detections/DetectionFilter.vue
@@ -57,17 +57,17 @@ export default {
filter.showIndex >= (filter.data.length - 1) && (filter.showDisabled = true)
},
clickFilterItem (name, data, index) {
- if (index === 0) {
- let status = 0
- if (name === this.$t('detections.active')) {
- status = '0'
- } else if (name === this.$t('detections.ended')) {
- status = '1'
- }
- this.$emit('filter', status, data)
- } else {
- this.$emit('filter', name, data)
- }
+ // if (index === 0) {
+ // let status = 0
+ // if (name === this.$t('detections.active')) {
+ // status = '0'
+ // } else if (name === this.$t('detections.ended')) {
+ // status = '1'
+ // }
+ // this.$emit('filter', status, data)
+ // } else {
+ // }
+ this.$emit('filter', name, data)
},
handleMouse (id) {
const dom = document.getElementById(id)
diff --git a/src/views/detections/DetectionSearch.vue b/src/views/detections/DetectionSearch.vue
index fb726a23..56c27b0f 100644
--- a/src/views/detections/DetectionSearch.vue
+++ b/src/views/detections/DetectionSearch.vue
@@ -181,7 +181,7 @@ export default {
}
localStorage.setItem(storageKey.detectionSearchHistory, JSON.stringify(arr))
}
- this.$emit('search', { q, metaList })
+ this.$emit('search', { q, metaList, str })
},
changeParams (params) {
this.$refs.search.addParams(params)
diff --git a/src/views/detections/Index.vue b/src/views/detections/Index.vue
index 2d576be2..ac181e4f 100644
--- a/src/views/detections/Index.vue
+++ b/src/views/detections/Index.vue
@@ -140,6 +140,8 @@ import ChartTabs from '@/components/common/ChartTabs'
import { useStore } from 'vuex'
import { tooLongFormatter } from '@/views/charts/charts/tools'
import { format } from 'echarts'
+import Parser from '@/components/advancedSearch/meta/parser'
+import { schemaDetectionSecurity } from '@/utils/static-data'
export default {
name: 'Index',
@@ -763,11 +765,11 @@ export default {
// 参数q,避免切换页码时,地址栏参数q为空
let urlQ = ''
if (param && param.str) {
- // urlQ = encodeURI(param.str)
- urlQ = param.str
+ urlQ = param.str.indexOf('%') > -1 ? encodeURI(param.str) : param.str
+ this.str = param.str
} else if (this.q) {
// urlQ = encodeURI(this.q)
- urlQ = this.q
+ urlQ = this.q.indexOf('%') > -1 ? encodeURI(this.q) : this.q
}
const mode = this.$route.query.mode || 'text'
const newUrl = urlParamsHandler(window.location.href, this.$route.query, {
@@ -778,8 +780,8 @@ export default {
mode: mode
})
overwriteUrl(newUrl)
- this.queryFilter(urlQ)
- this.queryList(urlQ)
+ this.queryFilter(this.q)
+ this.queryList(this.q)
},
resetFilterData () {
this.filterData.securityEvent.forEach(d => {
@@ -921,10 +923,12 @@ export default {
}
// %位置不为0,即内容包含非英文时
const str1 = q.substring(q.indexOf('%'), q.indexOf('%') + 3)
- if (q && q.indexOf('%') > 0 && (str1 !== '%20' || str1 === '%25')) {
+ if (q && q.indexOf('%') > 0 && (str1 === '%20' || str1 === '%25')) {
q = decodeURI(q)
}
}
+ const parser = new Parser(schemaDetectionSecurity)
+ q = parser.conversionEnum(q)
this.queryFilter(q)
if (this.initFlag) {
this.timer = setTimeout(() => {
diff --git a/src/views/entityExplorer/EntityExplorer.vue b/src/views/entityExplorer/EntityExplorer.vue
index 4c956650..3b43ce2f 100644
--- a/src/views/entityExplorer/EntityExplorer.vue
+++ b/src/views/entityExplorer/EntityExplorer.vue
@@ -282,6 +282,7 @@ export default {
],
listData: [],
q: '',
+ str: '',
metaList: [],
listLoading: false,
// 实体详情搜索页面 底部列表
@@ -387,9 +388,12 @@ export default {
// 参数q,避免切换页码时,地址栏参数q为空
let urlQ = ''
if (param.str) {
- urlQ = encodeURI(param.str)
+ // urlQ = encodeURI(param.str)
+ urlQ = param.str.indexOf('%') > -1 ? encodeURI(param.str) : param.str
+ this.str = param.str
} else if (this.q) {
- urlQ = encodeURI(this.q)
+ // urlQ = encodeURI(this.q)
+ urlQ = this.q.indexOf('%') > -1 ? encodeURI(this.q) : this.q
} else if (!this.q) {
this.isHideRelatedEntities = false
}
@@ -444,10 +448,10 @@ export default {
const keywordList = this.getKeywordListByMetaList(this.metaList)
if (this.initFlag) {
if (val !== 20) {
- this.search({ metaList: this.metaList, q: this.q, keywordList: keywordList })
+ this.search({ metaList: this.metaList, q: this.q, str: this.str, keywordList: keywordList })
}
} else {
- this.search({ metaList: this.metaList, q: this.q, keywordList: keywordList })
+ this.search({ metaList: this.metaList, q: this.q, str: this.str, keywordList: keywordList })
}
},
pageNo (val) {
@@ -455,7 +459,7 @@ export default {
this.pageObj.pageNo = val
this.pageObj.resetPageNo = false
const keywordList = this.getKeywordListByMetaList(this.metaList)
- this.search({ metaList: this.metaList, q: this.q, keywordList: keywordList })
+ this.search({ metaList: this.metaList, q: this.q, str: this.str, keywordList: keywordList })
}
},
// 点击上一页箭头
@@ -827,6 +831,8 @@ export default {
if (q && q.indexOf('%') > 0 && (str1 === '%20' || str1 === '%25')) {
q = decodeURI(q)
}
+ const parser = new Parser(columnList)
+ q = parser.conversionEnum(q)
this.initSearch(q)
this.listMode = listMode
// 查询评分基准
@@ -840,7 +846,7 @@ export default {
},
watch: {
timeFilter () {
- this.search({ metaList: this.metaList, q: this.q })
+ this.search({ metaList: this.metaList, q: this.q, str: this.str })
}
},
setup () {