This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
cyber-narrator-cn-ui/src/components/advancedSearch/TextMode.vue

239 lines
7.6 KiB
Vue
Raw Normal View History

2022-01-23 23:34:51 +08:00
<template>
<textarea
ref="textSearch"
></textarea>
<div class="search__suffixes search__suffixes--text-mode">
<div class="search__suffix">
<el-popover
popper-class="my-popper-class"
placement="top"
trigger="hover"
:content="$t('entity.switchToAdvancedSearch')"
>
<template #reference>
<i class="cn-icon cn-icon-filter" @click="changeMode"></i>
</template>
</el-popover>
2022-01-23 23:34:51 +08:00
</div>
2023-07-07 17:22:51 +08:00
<div class="search__suffix-close" @click="cleanParams">
<i class="el-icon-error"></i>
</div>
<div class="search__suffix" :class="showList ? 'new-search__suffix' : 'entity-explorer-search'" @click="search">
2022-01-23 23:34:51 +08:00
<i class="el-icon-search"></i>
</div>
</div>
</template>
<script>
import 'codemirror/theme/ambiance.css'
import 'codemirror/addon/hint/show-hint'
import 'codemirror/addon/hint/show-hint.css'
2022-01-25 17:16:56 +08:00
import 'codemirror/addon/display/placeholder'
2022-01-23 23:34:51 +08:00
import 'codemirror/mode/sql/sql'
2022-06-06 17:34:55 +08:00
import Parser, { stringInQuot, handleOperatorSpace } from '@/components/advancedSearch/meta/parser'
2022-01-25 17:16:56 +08:00
import CodeMirror from 'codemirror'
import { toRaw } from 'vue'
2022-06-06 17:34:55 +08:00
import _ from 'lodash'
2022-01-25 17:16:56 +08:00
import { columnType } from '@/components/advancedSearch/meta/meta'
2022-12-08 16:09:46 +08:00
import { handleErrorTip } from '@/components/advancedSearch/meta/error'
import { comparedEntityKey, overwriteUrl, urlParamsHandler } from '@/utils/tools'
2022-01-25 17:16:56 +08:00
2022-01-23 23:34:51 +08:00
export default {
name: 'TextMode',
2022-01-25 17:16:56 +08:00
props: {
columnList: Array,
str: String,
showList: Boolean
2022-01-25 17:16:56 +08:00
},
data () {
return {
codeMirror: null
}
},
emits: ['changeMode', 'search'],
2022-01-23 23:34:51 +08:00
methods: {
2023-07-07 17:22:51 +08:00
cleanParams () {
toRaw(this.codeMirror).setValue('')
const routeQuery = this.$route.query
delete routeQuery.q
this.reloadUrl(routeQuery, 'cleanOldParams')
2023-07-07 17:22:51 +08:00
},
2022-01-23 23:34:51 +08:00
initCodeMirror () {
2022-01-25 17:16:56 +08:00
this.codeMirror = CodeMirror.fromTextArea(this.$refs.textSearch, {
2022-01-23 23:34:51 +08:00
mode: {
name: 'sql'
},
2022-01-25 17:16:56 +08:00
placeholder: 'Enter...',
2022-01-23 23:34:51 +08:00
lineNumbers: false
})
this.codeMirror.setOption('extraKeys', {
2022-04-13 10:14:36 +08:00
Enter: (cm) => {}
})
2022-01-23 23:34:51 +08:00
},
search () {
2022-06-06 17:34:55 +08:00
const str = this.codeMirror.getValue().trim()
if (str) {
const parser = new Parser(this.columnList)
const keyInfo = comparedEntityKey(str)
if (keyInfo.isKey) {
const errorList = parser.validateStr(keyInfo.key)
if (_.isEmpty(errorList)) {
this.$emit('search', { ...parser.parseStr(keyInfo.key), str: str })
} else {
this.$message.error(handleErrorTip(errorList[0]))
}
} else {
this.$message.error(this.$t('tip.invalidQueryField') + keyInfo.key)
}
} else {
2022-06-06 17:34:55 +08:00
this.$emit('search', { q: '', str: '', metaList: [] })
2022-01-25 17:16:56 +08:00
}
2022-01-23 23:34:51 +08:00
},
2022-01-26 18:13:40 +08:00
focus () {
this.codeMirror.focus()
},
2022-01-23 23:34:51 +08:00
changeMode () {
let str = this.codeMirror.getValue().trim()
2022-06-06 17:34:55 +08:00
if (str) {
str = comparedEntityKey(str).key
2022-06-06 17:34:55 +08:00
const parser = new Parser(this.columnList)
const errorList = parser.validateStr(str)
if (_.isEmpty(errorList)) {
2022-06-15 20:41:21 +08:00
const metaList = parser.parseStr(str)
this.reloadUrl({ mode: 'tag' })
2022-06-15 20:41:21 +08:00
this.$emit('changeMode', 'tag', metaList)
2022-06-06 17:34:55 +08:00
} else {
this.reloadUrl({ mode: 'tag' })
2022-06-06 17:34:55 +08:00
this.$emit('changeMode', 'tag', { metaList: [], str: '' })
}
2022-01-25 17:16:56 +08:00
} else {
this.reloadUrl({ mode: 'tag' })
2022-06-06 17:34:55 +08:00
this.$emit('changeMode', 'tag', { str: '', metaList: [] })
2022-01-25 17:16:56 +08:00
}
},
2022-02-18 10:07:43 +08:00
// 处理value例如转换IN的值
handleValue (value, column, operator) {
const isArray = ['IN', 'NOT IN'].indexOf(operator) > -1
if (isArray) {
2022-06-06 17:34:55 +08:00
if (_.isArray(value)) {
2022-02-18 10:07:43 +08:00
value = value.map(v => column.type === columnType.string ? stringInQuot(v) : v)
return `(${value.join(',')})`
} else {
return value
}
} else {
return column.type === columnType.string ? stringInQuot(value) : value
}
},
2022-01-25 17:16:56 +08:00
addParams (params) {
2022-02-18 10:07:43 +08:00
let current = this.codeMirror.getValue()
params.forEach(param => {
const column = this.columnList.find(c => c.label === param.column)
2022-02-18 10:07:43 +08:00
current = `${current ? current + ' AND ' : ''}${param.column}${handleOperatorSpace(param.operator)}${this.handleValue(param.value, column, param.operator)}`
})
toRaw(this.codeMirror).setValue(current.trim())
2022-02-18 10:07:43 +08:00
},
removeParams (params) {
let current = this.codeMirror.getValue()
params.forEach(param => {
const column = this.columnList.find(c => c.label === param.column)
// 将对应内容替换为空串
const sqlPiece = `${param.column}${handleOperatorSpace(param.operator)}${this.handleValue(param.value, column, param.operator)}`.trim()
2022-02-22 22:22:15 +08:00
const sqlPieceWithConnection = [` AND ${sqlPiece}`, ` OR ${sqlPiece}`, `${sqlPiece} AND `, `${sqlPiece} OR `, sqlPiece]
sqlPieceWithConnection.forEach(piece => {
current = current.replace(piece, '')
})
})
toRaw(this.codeMirror).setValue(current.trim())
2022-02-18 10:07:43 +08:00
},
changeParams (params) {
let current = this.codeMirror.getValue()
params.forEach(param => {
const oldColumn = this.columnList.find(c => c.label === param.oldParam.column)
const newColumn = this.columnList.find(c => c.label === param.newParam.column)
// 将oldParam内容替换为newParam
const oldSqlPiece = `${param.oldParam.column}${handleOperatorSpace(param.oldParam.operator)}${this.handleValue(param.oldParam.value, oldColumn, param.oldParam.operator)}`.trim()
const newSqlPiece = `${param.newParam.column}${handleOperatorSpace(param.newParam.operator)}${this.handleValue(param.newParam.value, newColumn, param.newParam.operator)}`.trim()
current = current.replace(oldSqlPiece, newSqlPiece)
2022-01-25 17:16:56 +08:00
})
toRaw(this.codeMirror).setValue(current.trim())
},
/**
* 向地址栏添加/删除参数
*/
reloadUrl (newParam, clean) {
const { query } = this.$route
let newUrl = urlParamsHandler(window.location.href, query, newParam)
if (clean) {
newUrl = urlParamsHandler(window.location.href, query, newParam, clean)
}
overwriteUrl(newUrl)
2022-01-25 17:16:56 +08:00
}
},
watch: {
2022-06-06 17:34:55 +08:00
str: {
2022-01-25 17:16:56 +08:00
immediate: true,
handler (n) {
if (n) {
setTimeout(() => {
toRaw(this.codeMirror).setValue(n)
})
}
}
2022-01-23 23:34:51 +08:00
}
},
mounted () {
// 如果地址栏包含参数q则将参数q回显到搜索栏内
let { q } = this.$route.query
2022-01-23 23:34:51 +08:00
this.initCodeMirror()
if (q) {
// 为避免地址栏任意输入导致全查询的q带QUERY解析时不识别导致的语法错误
// 如地址栏输入116.178.222.171此时的q很长刷新界面时需要把q里的116.178.222.171拿出来进行搜索
if (q.indexOf('QUERY') > -1) {
const strList = q.split(' ')
if (strList.length > 0) {
// 此时strList[1]为ip_addr:116.178.222.171获取116.178.222.171
q = strList[1].slice(8)
}
}
toRaw(this.codeMirror).setValue(q)
}
const vm = this
this.emitter.on('advanced-search', function () {
vm.search()
})
2022-01-23 23:34:51 +08:00
}
}
</script>
2023-07-07 17:22:51 +08:00
<style lang="scss">
.search__suffix-close {
.el-icon-error {
font-size: 17px;
color: #C4C4C4;
margin: 0 12px;
cursor: pointer;
}
}
2023-07-07 17:22:51 +08:00
.new-search__suffix {
width: 41px;
height: 41px;
line-height: 41px;
background: #38ACD2;
text-align: center;
margin-top: -10px;
margin-right: -10px;
2023-07-07 17:22:51 +08:00
.el-icon-search {
color: #fff !important;
margin-top: 9px !important;
}
}
.entity-explorer-search {
color: #3976CB;
margin-top: -2px;
}
2023-07-07 17:22:51 +08:00
</style>