diff --git a/src/components/advancedSearch/Index.vue b/src/components/advancedSearch/Index.vue
index b72b2720..0b166ff5 100644
--- a/src/components/advancedSearch/Index.vue
+++ b/src/components/advancedSearch/Index.vue
@@ -115,11 +115,11 @@ export default {
},
setup (props) {
// 默认为文本模式
- let searchMode = ref('text')
+ const searchMode = ref('text')
if (props.defaultMode) {
switch (props.defaultMode) {
case 'tag': {
- searchMode = 'tag'
+ searchMode.value = 'tag'
break
}
}
diff --git a/src/components/advancedSearch/TagMode.vue b/src/components/advancedSearch/TagMode.vue
index 534bd662..94e15c1e 100644
--- a/src/components/advancedSearch/TagMode.vue
+++ b/src/components/advancedSearch/TagMode.vue
@@ -93,6 +93,7 @@ import Meta, { connection, condition, columnType } from './meta/meta'
import _ from 'lodash'
import { handleErrorTip } from '@/components/advancedSearch/meta/error'
import Parser, { stringInQuot } from '@/components/advancedSearch/meta/parser'
+import { overwriteUrl, urlParamsHandler } from '@/utils/tools'
export default {
name: 'TagMode',
props: {
@@ -320,8 +321,10 @@ export default {
const parser = new Parser(this.columnList)
const errorList = parser.validateMeta(this.metaList)
if (_.isEmpty(errorList)) {
+ this.reloadUrl({ mode: 'text' })
this.$emit('changeMode', 'text', parser.parseMeta(this.metaList))
} else {
+ this.reloadUrl({ mode: 'text' })
this.$emit('changeMode', 'text', { metaList: [], str: '' })
}
},
@@ -397,10 +400,28 @@ export default {
this.metaList.splice(metaIndex, 2)
}
})
+ },
+ /**
+ * 向地址栏添加/删除参数
+ */
+ 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)
}
},
mounted () {
const vm = this
+ // 如果地址栏包含参数q,则匹配出metaList到搜索栏回显使用
+ const { q } = this.$route.query
+ if (q) {
+ const parser = new Parser(this.columnList)
+ this.metaList = parser.parseStr(q).metaList
+ }
+
this.emitter.on('advanced-search', function () {
vm.search()
})
diff --git a/src/components/advancedSearch/TextMode.vue b/src/components/advancedSearch/TextMode.vue
index 1a98deb9..700fd165 100644
--- a/src/components/advancedSearch/TextMode.vue
+++ b/src/components/advancedSearch/TextMode.vue
@@ -28,6 +28,7 @@ import { toRaw } from 'vue'
import _ from 'lodash'
import { columnType } from '@/components/advancedSearch/meta/meta'
import { handleErrorTip } from '@/components/advancedSearch/meta/error'
+import { overwriteUrl, urlParamsHandler } from '@/utils/tools'
export default {
name: 'TextMode',
@@ -81,11 +82,14 @@ export default {
const errorList = parser.validateStr(str)
if (_.isEmpty(errorList)) {
const metaList = parser.parseStr(str)
+ this.reloadUrl({ mode: 'tag' })
this.$emit('changeMode', 'tag', metaList)
} else {
+ this.reloadUrl({ mode: 'tag' })
this.$emit('changeMode', 'tag', { metaList: [], str: '' })
}
} else {
+ this.reloadUrl({ mode: 'tag' })
this.$emit('changeMode', 'tag', { str: '', metaList: [] })
}
},
@@ -135,6 +139,17 @@ export default {
current = current.replace(oldSqlPiece, newSqlPiece)
})
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)
}
},
watch: {
@@ -150,7 +165,13 @@ export default {
}
},
mounted () {
+ // 如果地址栏包含参数q,则将参数q回显到搜索栏内
+ const { q } = this.$route.query
this.initCodeMirror()
+ if (q) {
+ toRaw(this.codeMirror).setValue(q)
+ }
+
const vm = this
this.emitter.on('advanced-search', function () {
vm.search()
diff --git a/src/utils/static-data.js b/src/utils/static-data.js
index 83b779d1..a390ecc2 100644
--- a/src/utils/static-data.js
+++ b/src/utils/static-data.js
@@ -270,3 +270,191 @@ export const dataForNpmNetworkQuantity = {
{ name: 'overall.packetRetrans' }
]
}
+export const columnList = [
+ {
+ name: 'entity_type',
+ type: 'string',
+ label: 'Entity type'
+ },
+ {
+ name: 'ip_addr',
+ type: 'string',
+ label: 'IP.Address'
+ },
+ {
+ name: 'ip_location_country',
+ type: 'string',
+ label: 'IP.Country'
+ },
+ {
+ name: 'ip_location_province',
+ type: 'string',
+ label: 'IP.Province'
+ },
+ {
+ name: 'ip_location_city',
+ type: 'string',
+ label: 'IP.City'
+ },
+ {
+ name: 'ip_asn',
+ type: 'string',
+ label: 'IP.ASN'
+ },
+ {
+ name: 'dns_server_role',
+ type: 'string',
+ label: 'IP.DNS server role'
+ },
+ {
+ name: 'dns_server_org',
+ type: 'string',
+ label: 'IP.DNS server organization'
+ },
+ {
+ name: 'dns_server_os',
+ type: 'string',
+ label: 'IP.Operating system'
+ },
+ {
+ name: 'dns_server_software',
+ type: 'string',
+ label: 'IP.DNS server software'
+ },
+ {
+ name: 'domain_name',
+ type: 'string',
+ label: 'Domain.Name'
+ },
+ {
+ name: 'domain_category',
+ type: 'string',
+ label: 'Domain.Category'
+ },
+ {
+ name: 'domain_category_group',
+ type: 'string',
+ label: 'Domain.Category group'
+ },
+ {
+ name: 'domain_reputation_level',
+ type: 'string',
+ label: 'Domain.Reputation'
+ },
+ {
+ name: 'domain_whois_email',
+ type: 'string',
+ label: 'Domain.Whois email'
+ },
+ {
+ name: 'domain_whois_name_servers',
+ type: 'string',
+ label: 'Domain.Whois nameserver'
+ },
+ {
+ name: 'domain_whois_registrar',
+ type: 'string',
+ label: 'Domain.Whois registrar'
+ },
+ {
+ name: 'domain_whois_org',
+ type: 'string',
+ label: 'Domain.Whois organization'
+ },
+ {
+ name: 'domain_whois_address',
+ type: 'string',
+ label: 'Domain.Whois address'
+ },
+ {
+ name: 'domain_whois_city',
+ type: 'string',
+ label: 'Domain.Whois city'
+ },
+ {
+ name: 'domain_whois_state',
+ type: 'string',
+ label: 'Domain.Whois state'
+ },
+ {
+ name: 'domain_whois_country',
+ type: 'string',
+ label: 'Domain.Whois country'
+ },
+ {
+ name: 'domain_icp_owner',
+ type: 'string',
+ label: 'Domain.ICP owner'
+ },
+ {
+ name: 'domain_icp_company_name',
+ type: 'string',
+ label: 'Domain.ICP company'
+ },
+ {
+ name: 'domain_icp_company_type',
+ type: 'string',
+ label: 'Domain.ICP company type'
+ },
+ {
+ name: 'domain_icp_site_license',
+ type: 'string',
+ label: 'Domain.ICP site license'
+ },
+ {
+ name: 'domain_icp_site_name',
+ type: 'string',
+ label: 'Domain.ICP site'
+ },
+ {
+ name: 'app_name',
+ type: 'string',
+ label: 'APP.Name'
+ },
+ {
+ name: 'app_id',
+ type: 'string',
+ label: 'APP.ID'
+ },
+ {
+ name: 'app_category',
+ type: 'string',
+ label: 'APP.Category'
+ },
+ {
+ name: 'app_subcategory',
+ type: 'string',
+ label: 'APP.Subcategory'
+ },
+ {
+ name: 'app_risk',
+ type: 'string',
+ label: 'APP.Risk'
+ },
+ {
+ name: 'app_description',
+ type: 'string',
+ label: 'APP.Description'
+ },
+ {
+ name: 'app_longname',
+ type: 'string',
+ label: 'APP.Long name'
+ },
+ {
+ name: 'app_technology',
+ type: 'string',
+ label: 'APP.Technology'
+ }
+]
+export const operatorList = ['=', '!=', /* '>', '<', '>=', '<=', */'IN', 'NOT IN', 'LIKE', 'NOT LIKE']
+export const connectionList = [
+ {
+ value: 'AND',
+ label: 'AND'
+ },
+ {
+ value: 'OR',
+ label: 'OR'
+ }
+]
diff --git a/src/views/entityExplorer/EntityExplorer.vue b/src/views/entityExplorer/EntityExplorer.vue
index b83bdd68..8eda8dec 100644
--- a/src/views/entityExplorer/EntityExplorer.vue
+++ b/src/views/entityExplorer/EntityExplorer.vue
@@ -18,8 +18,8 @@
-
-
+
+
@@ -161,6 +161,11 @@ import { getNowTime, getSecond } from '@/utils/date-util'
import { ref } from 'vue'
import _ from 'lodash'
import Loading from '@/components/common/Loading'
+import { overwriteUrl, urlParamsHandler } from '@/utils/tools'
+import Parser from '@/components/advancedSearch/meta/parser'
+import { handleErrorTip } from '@/components/advancedSearch/meta/error'
+import { columnList } from '@/utils/static-data'
+import { useRoute } from 'vue-router'
export default {
name: 'entity-explorer',
@@ -428,8 +433,32 @@ export default {
this.metaList = []
}
+ // 在非列表模式下选择tag模式,在地址栏输入内容时将mode添加到地址栏
+ const mode = this.$route.query.mode || 'text'
+
+ this.reloadUrl({
+ listMode: this.listMode,
+ q: q,
+ mode: mode,
+ startTime: getSecond(this.timeFilter.startTime),
+ endTime: getSecond(this.timeFilter.endTime)
+ })
+
if (!this.showList) {
+ // 首页进入搜索时重载页面,视觉上进入列表页面
+ this.$router.push({
+ path: '/entityExplorer',
+ query: {
+ listMode: this.listMode,
+ q: q,
+ mode: mode,
+ startTime: getSecond(this.timeFilter.startTime),
+ endTime: getSecond(this.timeFilter.endTime)
+ }
+ })
this.showList = true
+ // 跳转页面,则不执行搜索功能
+ return true
}
if (this.pageObj.resetPageNo) {
this.pageObj.pageNo = 1
@@ -725,20 +754,80 @@ export default {
d.value = 0
})
this.filterData[index].totalCount = 0
+ },
+ setListMode (mode) {
+ this.listMode = mode
+ const newParam = {
+ listMode: mode
+ }
+ this.reloadUrl(newParam)
+ },
+ /**
+ * 向地址栏添加/删除参数
+ */
+ 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)
+ },
+ /**
+ * 初始化搜索,分享url或者刷新界面,保留本次搜索结果
+ * @param q
+ */
+ initSearch (q) {
+ const str = q
+ // 此处的mode不做text和tag区分,是因为text和tag构造搜索参数过程不一样,但结果的参数一致
+ // 故采用text的参数形式进行搜索,tag形式在tagMode.vue的mounted里根据地址栏的参数q构造metaList
+ if (str) {
+ const parser = new Parser(columnList)
+ const errorList = parser.validateStr(str)
+ if (_.isEmpty(errorList)) {
+ this.search(parser.parseStr(str))
+ } else {
+ this.$message.error(handleErrorTip(errorList[0]))
+ }
+ } else {
+ this.search({ q: '', str: '', metaList: [] })
+ }
}
},
mounted () {
this.getEntityIndexData()
+ const { q, listMode } = this.$route.query
+
+ // 如果地址栏有listMode,即列表页,并非首页,则开始搜索
+ if (listMode) {
+ this.showList = true
+ this.initSearch(q)
+ this.listMode = listMode
+ }
},
watch: {
- timeFilter (n) {
+ timeFilter () {
this.search({ metaList: this.metaList, q: this.q })
}
},
setup () {
- const dateRangeValue = 60
- const { startTime, endTime } = getNowTime(dateRangeValue)
- const timeFilter = ref({ startTime, endTime, dateRangeValue })
+ const { query } = useRoute()
+ // 获取url携带的range、startTime、endTime
+ const rangeParam = query.range
+ const startTimeParam = query.startTime
+ const endTimeParam = query.endTime
+ // 若url携带了,使用携带的值,否则使用默认值。
+ const dateRangeValue = rangeParam ? parseInt(query.range) : 60
+ const timeFilter = ref({ dateRangeValue })
+ if (!startTimeParam || !endTimeParam) {
+ const { startTime, endTime } = getNowTime(60)
+ timeFilter.value.startTime = startTime
+ timeFilter.value.endTime = endTime
+ } else {
+ timeFilter.value.startTime = parseInt(startTimeParam)
+ timeFilter.value.endTime = parseInt(endTimeParam)
+ }
+ timeFilter.value.dateRangeValue = 60
return {
timeFilter
}
diff --git a/src/views/entityExplorer/search/ExplorerSearch.vue b/src/views/entityExplorer/search/ExplorerSearch.vue
index df2aa6b9..b9d2a583 100644
--- a/src/views/entityExplorer/search/ExplorerSearch.vue
+++ b/src/views/entityExplorer/search/ExplorerSearch.vue
@@ -10,6 +10,7 @@
:column-list="columnList"
:operator-list="operatorList"
:connection-list="connectionList"
+ :default-mode="defaultMode"
:full-text="true"
:class="{'advanced-search--show-list': showList}"
@search="search"
@@ -51,6 +52,9 @@
import AdvancedSearch from '@/components/advancedSearch/Index'
import _ from 'lodash'
import { storageKey } from '@/utils/constants'
+import { useRoute } from 'vue-router'
+import { ref } from 'vue'
+import { columnList } from '@/utils/static-data'
export default {
name: 'CnSearch',
components: {
@@ -64,183 +68,7 @@ export default {
},
data () {
return {
- columnList: [
- {
- name: 'entity_type',
- type: 'string',
- label: 'Entity type'
- },
- {
- name: 'ip_addr',
- type: 'string',
- label: 'IP.Address'
- },
- {
- name: 'ip_location_country',
- type: 'string',
- label: 'IP.Country'
- },
- {
- name: 'ip_location_province',
- type: 'string',
- label: 'IP.Province'
- },
- {
- name: 'ip_location_city',
- type: 'string',
- label: 'IP.City'
- },
- {
- name: 'ip_asn',
- type: 'string',
- label: 'IP.ASN'
- },
- {
- name: 'dns_server_role',
- type: 'string',
- label: 'IP.DNS server role'
- },
- {
- name: 'dns_server_org',
- type: 'string',
- label: 'IP.DNS server organization'
- },
- {
- name: 'dns_server_os',
- type: 'string',
- label: 'IP.Operating system'
- },
- {
- name: 'dns_server_software',
- type: 'string',
- label: 'IP.DNS server software'
- },
- {
- name: 'domain_name',
- type: 'string',
- label: 'Domain.Name'
- },
- {
- name: 'domain_category',
- type: 'string',
- label: 'Domain.Category'
- },
- {
- name: 'domain_category_group',
- type: 'string',
- label: 'Domain.Category group'
- },
- {
- name: 'domain_reputation_level',
- type: 'string',
- label: 'Domain.Reputation'
- },
- {
- name: 'domain_whois_email',
- type: 'string',
- label: 'Domain.Whois email'
- },
- {
- name: 'domain_whois_name_servers',
- type: 'string',
- label: 'Domain.Whois nameserver'
- },
- {
- name: 'domain_whois_registrar',
- type: 'string',
- label: 'Domain.Whois registrar'
- },
- {
- name: 'domain_whois_org',
- type: 'string',
- label: 'Domain.Whois organization'
- },
- {
- name: 'domain_whois_address',
- type: 'string',
- label: 'Domain.Whois address'
- },
- {
- name: 'domain_whois_city',
- type: 'string',
- label: 'Domain.Whois city'
- },
- {
- name: 'domain_whois_state',
- type: 'string',
- label: 'Domain.Whois state'
- },
- {
- name: 'domain_whois_country',
- type: 'string',
- label: 'Domain.Whois country'
- },
- {
- name: 'domain_icp_owner',
- type: 'string',
- label: 'Domain.ICP owner'
- },
- {
- name: 'domain_icp_company_name',
- type: 'string',
- label: 'Domain.ICP company'
- },
- {
- name: 'domain_icp_company_type',
- type: 'string',
- label: 'Domain.ICP company type'
- },
- {
- name: 'domain_icp_site_license',
- type: 'string',
- label: 'Domain.ICP site license'
- },
- {
- name: 'domain_icp_site_name',
- type: 'string',
- label: 'Domain.ICP site'
- },
- {
- name: 'app_name',
- type: 'string',
- label: 'APP.Name'
- },
- {
- name: 'app_id',
- type: 'string',
- label: 'APP.ID'
- },
- {
- name: 'app_category',
- type: 'string',
- label: 'APP.Category'
- },
- {
- name: 'app_subcategory',
- type: 'string',
- label: 'APP.Subcategory'
- },
- {
- name: 'app_risk',
- type: 'string',
- label: 'APP.Risk'
- },
- {
- name: 'app_description',
- type: 'string',
- label: 'APP.Description'
- },
- {
- name: 'app_longname',
- type: 'string',
- label: 'APP.Long name'
- },
- {
- name: 'app_technology',
- type: 'string',
- label: 'APP.Technology'
- }
- ],
+ columnList: columnList,
operatorList: ['=', '!=', /* '>', '<', '>=', '<=', */'IN', 'NOT IN', 'LIKE', 'NOT LIKE'],
connectionList: [
{
@@ -256,6 +84,14 @@ export default {
history: []
}
},
+ setup () {
+ // 根据地址栏添加mode,即text和tag模式,默认text
+ const { query } = useRoute()
+ const defaultMode = ref(query.mode || 'text')
+ return {
+ defaultMode
+ }
+ },
methods: {
search ({ str, q, metaList }) {
if (str) {