CN-1173: 检测功能UI开发
This commit is contained in:
173
src/views/detectionsNew/DetectionDrawer.vue
Normal file
173
src/views/detectionsNew/DetectionDrawer.vue
Normal file
@@ -0,0 +1,173 @@
|
||||
<template>
|
||||
<div class="detection-drawer" style="height: 100vh;overflow: scroll;padding-bottom: 90px">
|
||||
<div class="drawer-basic">
|
||||
<div class="drawer-basic-header">
|
||||
<div class="drawer-basic-id">ID: {{ drawerInfo.ruleId }}</div>
|
||||
<div :class="`detection-tag-status${detailData.status}`">
|
||||
{{ switchStatus(detailData.status) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="drawer-basic-function">
|
||||
<div class="detection-drawer-title">Name</div>
|
||||
<div class="basic-function-value">{{ detailData.name }}</div>
|
||||
</div>
|
||||
|
||||
<div class="drawer-basic-function">
|
||||
<div class="detection-drawer-title">Type</div>
|
||||
<div class="basic-function-value">{{ detailData.eventType }}</div>
|
||||
</div>
|
||||
|
||||
<div class="drawer-basic-description">
|
||||
<div class="detection-drawer-title">Description</div>
|
||||
<div class="basic-description-value">{{ detailData.description }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detection-drawer-collapse">
|
||||
<el-collapse v-model="activeRule">
|
||||
<el-collapse-item title="Rule Definitcm" name="rule">
|
||||
<div class="drawer-collapse-content">
|
||||
|
||||
<div class="drawer-basic-function">
|
||||
<div class="detection-drawer-title">Source</div>
|
||||
<div class="basic-function-value">{{ detailData.category }}</div>
|
||||
</div>
|
||||
|
||||
<div v-if="detailData.ruleType==='indicator_match'">
|
||||
<div class="drawer-basic-function">
|
||||
<div class="detection-drawer-title">Library</div>
|
||||
<span class="basic-function-value">{{ detailData.library }}</span>
|
||||
</div>
|
||||
|
||||
<div class="drawer-basic-function">
|
||||
<div class="detection-drawer-title">Level</div>
|
||||
<div class="detection-drawer-title">
|
||||
<div class="detection__icon" :style="`background-color: ${eventSeverityColor['critical']}`"></div>
|
||||
<div class="basic-function-value">Critical</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
<div class="drawer-basic-function">
|
||||
<div class="detection-drawer-title">Dimensions</div>
|
||||
<span class="detection-tag-blue">{{ detailData.dimensions }}</span>
|
||||
</div>
|
||||
|
||||
<div class="drawer-basic-function">
|
||||
<div class="detection-drawer-title">Filters</div>
|
||||
<span class="detection-tag-blue">source</span>
|
||||
<span style="margin: 0 6px;">equal</span><span>19890</span>
|
||||
</div>
|
||||
|
||||
<div class="drawer-basic-function" v-for="item in severityList" :key="item.severity"
|
||||
style="padding-bottom: 0">
|
||||
<div class="detection-drawer-title">
|
||||
<div class="detection__icon" :style="`background-color: ${eventSeverityColor[item.severity]}`"></div>
|
||||
<div>{{ toUpperCaseByString(item.severity) }}</div>
|
||||
</div>
|
||||
<div class="detection-drawer-title">Conditions</div>
|
||||
<div>
|
||||
<div class="detection-tag-gray margin-r-10">> 60 Kpackets/s</div>
|
||||
<div class="detection-tag-gray">> 50 Unique Src IPs</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</div>
|
||||
|
||||
<div class="detection-drawer-collapse" style="margin: 20px 0">
|
||||
<el-collapse v-model="activeTrigger">
|
||||
<el-collapse-item title="Trigger" name="trigger">
|
||||
<div class="drawer-collapse-content">
|
||||
<div class="drawer-collapse-trigger">
|
||||
Triggered when conditions occur at least
|
||||
<span style="color: #046ECA" v-if="detailData.trigger">
|
||||
{{ detailData.trigger.atLeast }} time
|
||||
</span> in
|
||||
<span style="color: #046ECA" v-if="detailData.trigger">
|
||||
<!--todo 此处返回的是PT5M,具体时间处理根据后续字段来看-->
|
||||
{{ getNumberFromStr(detailData.trigger.interval) }} minutes
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="drawer-basic-function">
|
||||
<div class="detection-drawer-title">Evaluation Frequency</div>
|
||||
<div class="basic-function-value" v-if="detailData.trigger">{{ getNumberFromStr(detailData.trigger.resetInterval) }} minutes</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { switchStatus, toUpperCaseByString } from '@/utils/tools'
|
||||
import { eventSeverityColor } from '@/utils/constants'
|
||||
import axios from '_axios@0.21.4@axios'
|
||||
import { api } from '@/utils/api'
|
||||
|
||||
export default {
|
||||
name: 'DetectionDrawer',
|
||||
props: {
|
||||
drawerInfo: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
activeRule: 'rule',
|
||||
activeTrigger: 'trigger',
|
||||
detailData: {},
|
||||
eventSeverityColor,
|
||||
severityList: []
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
drawerInfo: {
|
||||
immediate: true,
|
||||
deep: true,
|
||||
handler (n) {
|
||||
if (n) {
|
||||
this.getDetailData()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
switchStatus,
|
||||
toUpperCaseByString,
|
||||
getDetailData () {
|
||||
this.severityList = [
|
||||
{
|
||||
severity: 'critical',
|
||||
list: ['> 60 Kpackets/s', '> 50 Unique Src IPs']
|
||||
},
|
||||
{
|
||||
severity: 'high',
|
||||
list: ['> 20 Kpackets/s', '> 50 Unique Src IPs']
|
||||
}
|
||||
]
|
||||
|
||||
axios.get(`${api.detection.detail}/${this.drawerInfo.ruleId}`).then(res => {
|
||||
if (res.data.code === 200) {
|
||||
this.detailData = res.data.data
|
||||
}
|
||||
}).catch(err => {
|
||||
console.error(err)
|
||||
})
|
||||
},
|
||||
getNumberFromStr (str) {
|
||||
return str.match(/\d+(\.\d+)?/g)[0]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
</style>
|
||||
215
src/views/detectionsNew/DetectionFilter.vue
Normal file
215
src/views/detectionsNew/DetectionFilter.vue
Normal file
@@ -0,0 +1,215 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="detection-filter-title">
|
||||
{{ $t('detections.filters') }}
|
||||
</div>
|
||||
<div class="detection-filter-content">
|
||||
<div>
|
||||
<div class="filter-content-title">{{ $t('overall.status') }}</div>
|
||||
<div class="filter-content-content">
|
||||
<el-checkbox-group v-model="checkStatus" @change="onChangeCategory" style="display: flex;flex-direction: column">
|
||||
<el-checkbox v-for="item in statusList" :key="item.label" class="filter-content-checkbox" :label="item.status">
|
||||
<div>{{ item.label }}</div>
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="filter-content-title">{{ $t('overall.category') }}</div>
|
||||
<div class="filter-content-content">
|
||||
<el-checkbox-group v-model="checkCategory" @change="onChangeCategory">
|
||||
<el-checkbox v-for="item in categoryList" :key="item.value" class="filter-content-checkbox" :label="item.value">
|
||||
{{ item.label }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="filter-content-title">{{ $t('overall.type') }}</div>
|
||||
<div class="filter-content-content">
|
||||
<el-checkbox-group v-model="checkType" @change="onChangeCategory" style="display: flex;flex-direction: column">
|
||||
<el-checkbox v-for="item in typeList" :key="item.value" class="filter-content-checkbox" :label="item.value">
|
||||
{{ item.label }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { get } from '@/utils/http'
|
||||
import { api } from '@/utils/api'
|
||||
|
||||
export default {
|
||||
name: 'DetectionFilter',
|
||||
data () {
|
||||
return {
|
||||
statusList: [],
|
||||
categoryList: [],
|
||||
typeList: [],
|
||||
checkStatus: [],
|
||||
checkCategory: [],
|
||||
checkType: [],
|
||||
url: api.detection.statistics
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
// 开发时删除---start
|
||||
this.statusList = [
|
||||
{ status: 1, label: 'Enabled' },
|
||||
{ status: 0, label: 'Disabled' }
|
||||
]
|
||||
this.checkStatus = [0, 1]
|
||||
this.categoryList = [
|
||||
{ value: 'security', label: 'Security Event' },
|
||||
{ value: 'performance', label: 'Performance Event' },
|
||||
{ value: 'regulatory_risk', label: 'Regulatory Risk Event' }
|
||||
]
|
||||
this.checkCategory = ['security', 'performance', 'regulatory_risk']
|
||||
this.typeList = [
|
||||
{ value: 'c&c', label: 'C&C' },
|
||||
{ value: 'ddos', label: 'DDos' },
|
||||
{ value: 'lateral_movement', label: 'Lateral movement' },
|
||||
{ value: 'brute_force', label: 'Brute force' }
|
||||
]
|
||||
this.checkType = ['c&c', 'ddos', 'lateral_movement', 'brute_force']
|
||||
// 开发时删除---end
|
||||
|
||||
// todo 暂时禁用,后续再开发时解禁
|
||||
// this.getFilterData()
|
||||
},
|
||||
methods: {
|
||||
getFilterData (params) {
|
||||
let searchParams = { pageSize: -1 }
|
||||
if (params) {
|
||||
searchParams = { ...searchParams, ...params }
|
||||
}
|
||||
get(this.url, searchParams).then(response => {
|
||||
if (response.code === 200) {
|
||||
if (response.data.statusList) {
|
||||
this.statusList = []
|
||||
response.data.statusList.forEach(item => {
|
||||
this.statusList.push({ status: item.status, label: this.switchStatus(item.status) })
|
||||
this.checkStatus.push(item.status)
|
||||
})
|
||||
}
|
||||
|
||||
this.categoryList = response.data.categoryList
|
||||
if (response.data.categoryList) {
|
||||
response.data.categoryList.forEach(item => {
|
||||
this.checkCategory.push(item.value)
|
||||
})
|
||||
}
|
||||
|
||||
this.typeList = response.data.typeList
|
||||
if (response.data.typeList) {
|
||||
response.data.typeList.forEach(item => {
|
||||
this.checkType.push(item.value)
|
||||
})
|
||||
}
|
||||
} else {
|
||||
console.error(response)
|
||||
}
|
||||
}).finally(() => {
|
||||
// this.initTypeData()
|
||||
// this.initStatusData()
|
||||
// const self = this
|
||||
// this.$nextTick(() => {
|
||||
// if (self.$refs.knowledgeTreeTypeFilter) {
|
||||
// self.$refs.knowledgeTreeTypeFilter.setCheckedKeys(this.defaultCheckedCategory)
|
||||
// }
|
||||
// if (self.$refs.knowledgeTreeStatusFilter) {
|
||||
// self.$refs.knowledgeTreeStatusFilter.setCheckedKeys(this.defaultCheckedStatus)
|
||||
// }
|
||||
// })
|
||||
})
|
||||
},
|
||||
onChangeCategory (data) {
|
||||
// todo 暂时禁用,后续再开发时解禁
|
||||
// 根据选择的值,构造不同入参,传给列表页,调用查询列表接口
|
||||
},
|
||||
switchStatus (status) {
|
||||
switch (status) {
|
||||
case 0: return 'Disabled'
|
||||
case 1: return 'Enabled'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.detection-filter-title {
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
background: #F7F7F7;
|
||||
padding: 0 20px;
|
||||
box-shadow: 0 1px 0 0 rgba(226, 229, 236, 1);
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
.detection-filter-content {
|
||||
padding: 20px;
|
||||
|
||||
.filter-content-title {
|
||||
font-family: NotoSansHans-Medium;
|
||||
font-size: 14px;
|
||||
line-height: 14px;
|
||||
margin-bottom: 10px;
|
||||
color: #353636;
|
||||
font-weight: 500;
|
||||
}
|
||||
.filter-content-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.filter-content-checkbox {
|
||||
line-height: 16px;
|
||||
margin-bottom: 10px;
|
||||
font-family: NotoSansSChineseRegular;
|
||||
font-size: 14px;
|
||||
color: #353636;
|
||||
font-weight: 400;
|
||||
|
||||
.el-checkbox__inner {
|
||||
width: 16px !important;
|
||||
height: 16px !important;
|
||||
text-align: center !important;
|
||||
line-height: 16px !important;
|
||||
}
|
||||
|
||||
.el-checkbox__input.is-indeterminate .el-checkbox__inner {
|
||||
border-color: #38ACD2;
|
||||
background: #38ACD2;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.el-checkbox__input.is-indeterminate .el-checkbox__inner:before {
|
||||
background: #FFFFFF;
|
||||
border-radius: 1px;
|
||||
}
|
||||
.el-checkbox__input.is-checked {
|
||||
.el-checkbox__inner {
|
||||
border-color: #38ACD2;
|
||||
background: #38ACD2;
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
.el-checkbox__input.is-focus {
|
||||
.el-checkbox__inner {
|
||||
border-color: #38ACD2;
|
||||
}
|
||||
}
|
||||
|
||||
.el-checkbox__label {
|
||||
font-family: NotoSansSChineseRegular;
|
||||
font-size: 14px;
|
||||
color: #353636;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
251
src/views/detectionsNew/DetectionForm.vue
Normal file
251
src/views/detectionsNew/DetectionForm.vue
Normal file
@@ -0,0 +1,251 @@
|
||||
<template>
|
||||
<div class="detection-form">
|
||||
|
||||
<div class="detection-form-header">
|
||||
Create Alert Policies
|
||||
</div>
|
||||
|
||||
<!--第一步:General Settings-->
|
||||
<div class="detection-form-content">
|
||||
<div class="detection-form-collapse">
|
||||
<el-collapse v-model="activeNames">
|
||||
<el-collapse-item name="1">
|
||||
<template #title>
|
||||
<div class="form-collapse-header">
|
||||
<div :class="activeNames[0]==='1' ? 'form-collapse-header-no-active' : 'form-collapse-header-no'">1</div>
|
||||
<div class="form-collapse-header-title">General Settings</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="form-collapse-content">
|
||||
<general-settings ref="form" @setSettingForm="getFormSetting" />
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</div>
|
||||
|
||||
<!--第二步:Rule Definition-->
|
||||
<div class="detection-form-collapse">
|
||||
<el-collapse v-model="activeNames" style="position: relative;">
|
||||
<el-collapse-item name="2">
|
||||
<template #title>
|
||||
<div class="form-collapse-header">
|
||||
<div :class="activeNames[0]==='2' ? 'form-collapse-header-no-active' : 'form-collapse-header-no'">2</div>
|
||||
<div class="form-collapse-header-title">Rule Definition</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="form-collapse-content">
|
||||
<rule-definition :settingObj="settingObj" @setRuleObj="getRuleObj" />
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</div>
|
||||
|
||||
<!--第三步:Trigger-->
|
||||
<div class="detection-form-collapse">
|
||||
<el-collapse v-model="activeNames">
|
||||
<el-collapse-item name="3">
|
||||
<template #title>
|
||||
<div class="form-collapse-header">
|
||||
<div :class="activeNames[0]==='3' ? 'form-collapse-header-no-active' : 'form-collapse-header-no'">3</div>
|
||||
<div class="form-collapse-header-title">Trigger</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="form-collapse-content margin-t-18">
|
||||
<el-form class="trigger-block margin-b-20" ref="form3" :model="triggerObj" :rules="rules">
|
||||
<div class="trigger-block-item margin-b-10">
|
||||
<div>At least</div>
|
||||
<el-form-item prop="atLeast">
|
||||
<el-input size="mini" v-model="triggerObj.atLeast" oninput="value=value.replace(/[^\d]/g,'')"></el-input>
|
||||
</el-form-item>
|
||||
<div>times within</div>
|
||||
|
||||
<el-form-item prop="interval">
|
||||
<el-input size="mini" v-model="triggerObj.interval" oninput="value=value.replace(/[^\d]/g,'')"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item prop="intervalVal">
|
||||
<el-select v-model="triggerObj.intervalVal" class="form-trigger__select" placeholder=" " size="mini">
|
||||
<el-option
|
||||
v-for="item in intervalList"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<div class="trigger-block-item">
|
||||
<div>With the counter resetting after no activity for</div>
|
||||
<el-form-item prop="minute">
|
||||
<el-input size="mini" v-model="triggerObj.minute" oninput="value=value.replace(/[^\d]/g,'')"></el-input>
|
||||
</el-form-item>
|
||||
<div>minutes</div>
|
||||
</div>
|
||||
</el-form>
|
||||
|
||||
<div class="form-setting__btn1">
|
||||
<el-button @click="createPolicy">Create & enable rule</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import GeneralSettings from '@/components/table/detection/GeneralSettings'
|
||||
import RuleDefinition from '@/components/table/detection/RuleDefinition'
|
||||
import { get } from '@/utils/http'
|
||||
import { api } from '@/utils/api'
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'DetectionForm',
|
||||
data () {
|
||||
return {
|
||||
activeNames: ['1'],
|
||||
settingObj: {}, // General Settings,即第一步的form表单信息
|
||||
ruleObj: {}, // 第二步的form表单信息
|
||||
// 第三步的form表单信息
|
||||
triggerObj: {
|
||||
atLeast: '',
|
||||
interval: '',
|
||||
intervalVal: '',
|
||||
minute: '',
|
||||
finishFlag: false
|
||||
},
|
||||
rules: {
|
||||
atLeast: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('validate.required'),
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
interval: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('validate.required'),
|
||||
trigger: 'change'
|
||||
}
|
||||
],
|
||||
intervalVal: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('validate.required'),
|
||||
trigger: 'change'
|
||||
}
|
||||
],
|
||||
minute: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('validate.required'),
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
},
|
||||
intervalList: []
|
||||
}
|
||||
},
|
||||
components: {
|
||||
GeneralSettings,
|
||||
RuleDefinition
|
||||
},
|
||||
mounted () {
|
||||
this.getStatistics()
|
||||
},
|
||||
methods: {
|
||||
/** 获取下拉列表数据 */
|
||||
getStatistics () {
|
||||
get(api.detection.statistics, { pageSize: -1 }).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.intervalList = response.data.intervalList || []
|
||||
} else {
|
||||
console.error(response)
|
||||
}
|
||||
}).finally(() => {
|
||||
})
|
||||
},
|
||||
/** 获取General Settings折叠板form数据 */
|
||||
getFormSetting (data) {
|
||||
this.handleActiveNames('1', this.activeNames)
|
||||
this.settingObj = JSON.parse(JSON.stringify(data))
|
||||
},
|
||||
/** 获取Rule Definition折叠板form数据 */
|
||||
getRuleObj (data) {
|
||||
this.handleActiveNames('2', this.activeNames)
|
||||
this.ruleObj = JSON.parse(JSON.stringify(data))
|
||||
},
|
||||
/** 自动展开收起折叠板 */
|
||||
handleActiveNames (name, arr) {
|
||||
const list = arr
|
||||
list.splice(list.indexOf(name), 1)
|
||||
this.activeNames = []
|
||||
list.forEach(t => {
|
||||
this.activeNames.push(t)
|
||||
})
|
||||
},
|
||||
/** 创建policy */
|
||||
createPolicy () {
|
||||
const self = this
|
||||
const settingLen = Object.keys(this.settingObj).length
|
||||
const ruleLen = Object.keys(this.ruleObj).length
|
||||
|
||||
if (settingLen > 0 && ruleLen > 0) {
|
||||
this.$refs.form3.validate(valid => {
|
||||
if (valid) {
|
||||
// 最终提交form
|
||||
// const formObj = { ...this.settingObj, ...this.ruleObj, ...this.triggerObj }
|
||||
this.$message({
|
||||
duration: 2000,
|
||||
type: 'success',
|
||||
message: this.$t('tip.saveSuccess')
|
||||
})
|
||||
|
||||
// axios.post('api', formObj).then(response => {
|
||||
// if (response.data.code === 200) {
|
||||
// this.$message({
|
||||
// duration: 2000,
|
||||
// type: 'success',
|
||||
// message: this.$t('tip.saveSuccess')
|
||||
// })
|
||||
//
|
||||
// this.$router.push({
|
||||
// path: '/detectionNew',
|
||||
// query: {
|
||||
// t: +new Date()
|
||||
// }
|
||||
// })
|
||||
// } else {
|
||||
// this.$message.error(this.errorMsgHandler(response))
|
||||
// }
|
||||
// }).catch(e => {
|
||||
// console.error(e)
|
||||
// this.$message.error(this.errorMsgHandler(e))
|
||||
// }).finally(() => {
|
||||
// //
|
||||
// })
|
||||
}
|
||||
})
|
||||
} else if (settingLen === 0) {
|
||||
this.handleFormError('1')
|
||||
} else if (ruleLen === 0) {
|
||||
this.handleFormError('2')
|
||||
}
|
||||
},
|
||||
handleFormError (name) {
|
||||
const list = this.activeNames
|
||||
list.push(name)
|
||||
this.activeNames = []
|
||||
list.forEach(t => {
|
||||
this.activeNames.push(t)
|
||||
})
|
||||
this.$message.error('请确保信息填写完整')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
175
src/views/detectionsNew/DetectionTable.vue
Normal file
175
src/views/detectionsNew/DetectionTable.vue
Normal file
@@ -0,0 +1,175 @@
|
||||
<template>
|
||||
<el-table
|
||||
id="detectionTable"
|
||||
class="detection-table"
|
||||
ref="dataTable"
|
||||
:data="tableData"
|
||||
height="100%"
|
||||
border
|
||||
empty-text=" "
|
||||
@header-dragend="dragend"
|
||||
@sort-change="tableDataSort"
|
||||
@selection-change="selectionChange"
|
||||
@row-dblclick="rowDoubleClick"
|
||||
>
|
||||
<el-table-column
|
||||
:resizable="false"
|
||||
align="center"
|
||||
type="selection"
|
||||
:selectable="selectable"
|
||||
width="55">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-for="(item, index) in customTableTitles"
|
||||
:key="`col-${index}`"
|
||||
:fixed="item.fixed"
|
||||
:label="item.label"
|
||||
:min-width="`${item.minWidth}`"
|
||||
:prop="item.prop"
|
||||
:resizable="true"
|
||||
:sort-orders="['ascending', 'descending']"
|
||||
:sortable="item.sortable"
|
||||
:width="`${item.width}`"
|
||||
class="data-column"
|
||||
>
|
||||
<template #header>
|
||||
<span class="data-column__span">{{ item.label }}</span>
|
||||
<div class="col-resize-area"></div>
|
||||
</template>
|
||||
<template #default="scope" :column="item">
|
||||
<template v-if="item.prop === 'name'">
|
||||
<template v-if="scope.row.i18n">
|
||||
<span :title="scope.row[item.prop]">{{ $t(scope.row.i18n) }}</span>
|
||||
</template>
|
||||
<template v-else-if="scope.row.name">
|
||||
<span :title="scope.row[item.prop]">{{ scope.row.name }}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span>-</span>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else-if="item.prop === 'status'">
|
||||
<div :class="`detection-tag-status${scope.row[item.prop]}`">
|
||||
{{ switchStatus(scope.row[item.prop]) }}
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="item.prop === 'description'">
|
||||
<div style="padding-right: 20px">{{ scope.row[item.prop] }}</div>
|
||||
</template>
|
||||
<template v-else-if="item.prop === 'dimensions' && scope.row[item.prop]">
|
||||
<span class="detection-tag-blue">{{ scope.row[item.prop] }}</span>
|
||||
</template>
|
||||
<template v-else-if="item.prop === 'library' && scope.row[item.prop]">
|
||||
<span class="detection-table-library">{{ scope.row[item.prop] }}</span>
|
||||
</template>
|
||||
<span v-else>{{ scope.row[item.prop] || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<template v-slot:empty>
|
||||
<div class="table-no-data" v-if="isNoData">
|
||||
<div class="table-no-data__title">{{ $t('npm.noData') }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import table from '@/mixins/table'
|
||||
import { dateFormatByAppearance } from '@/utils/date-util'
|
||||
import { switchStatus } from '@/utils/tools'
|
||||
|
||||
export default {
|
||||
name: 'DetectionTable',
|
||||
props: {
|
||||
isNoData: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
mixins: [table],
|
||||
data () {
|
||||
return {
|
||||
tableTitle: [
|
||||
{
|
||||
label: this.$t('knowledge.status'),
|
||||
prop: 'status',
|
||||
show: true,
|
||||
minWidth: 70
|
||||
},
|
||||
{
|
||||
label: 'ID',
|
||||
prop: 'ruleId',
|
||||
show: true,
|
||||
minWidth: 65
|
||||
},
|
||||
{
|
||||
label: this.$t('config.roles.name'),
|
||||
prop: 'name',
|
||||
minWidth: 90,
|
||||
show: true
|
||||
},
|
||||
{
|
||||
label: this.$t('overall.category'),
|
||||
prop: 'category',
|
||||
minWidth: 140,
|
||||
show: true
|
||||
},
|
||||
{
|
||||
label: this.$t('overall.type'),
|
||||
prop: 'eventType',
|
||||
minWidth: 145,
|
||||
show: true
|
||||
},
|
||||
{
|
||||
label: this.$t('overall.remark'),
|
||||
prop: 'description',
|
||||
minWidth: 205,
|
||||
show: true
|
||||
},
|
||||
{
|
||||
// label: this.$t('config.user.createTime'),
|
||||
label: 'Dimensions',
|
||||
prop: 'dimensions',
|
||||
minWidth: 204,
|
||||
show: true
|
||||
},
|
||||
{
|
||||
// label: this.$t('config.user.createTime'),
|
||||
label: 'Library',
|
||||
prop: 'library',
|
||||
minWidth: 204,
|
||||
show: true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
tableData: {
|
||||
immediate: true,
|
||||
deep: true,
|
||||
handler (n) {
|
||||
if (n) {
|
||||
n.forEach(t => {
|
||||
if (t.ruleType === 'indicator_match') {
|
||||
t.library = t.ruleConfig.knowledge.name
|
||||
} else if (t.ruleType === 'threshold') {
|
||||
t.dimensions = t.ruleConfig.dimensions
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
dateFormatByAppearance,
|
||||
switchStatus,
|
||||
rowDoubleClick (data) {
|
||||
this.$emit('rowDoubleClick', data)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
</style>
|
||||
77
src/views/detectionsNew/DetectionTools.vue
Normal file
77
src/views/detectionsNew/DetectionTools.vue
Normal file
@@ -0,0 +1,77 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="top-tools__left">
|
||||
<button
|
||||
id="knowledge-base-add"
|
||||
:title="$t('knowledgeBase.createKnowledgeBase')"
|
||||
class="top-tool-btn margin-r-10 top-tool-btn--create"
|
||||
@click="onCreate"
|
||||
style="width:72px;">
|
||||
<i class="cn-icon-xinjian cn-icon"></i>
|
||||
<span>{{ $t('overall.create') }}</span>
|
||||
</button>
|
||||
|
||||
<!-- <button-->
|
||||
<!-- id="knowledge-base-edit"-->
|
||||
<!-- :title="$t('knowledgeBase.editKnowledgeBase')"-->
|
||||
<!-- class="top-tool-btn margin-r-10"-->
|
||||
<!-- style="width:72px;">-->
|
||||
<!-- <i class="cn-icon-edit cn-icon" ></i>-->
|
||||
<!-- <span>{{$t('overall.edit')}}</span>-->
|
||||
<!-- </button>-->
|
||||
|
||||
<button
|
||||
:disabled="disableDelete"
|
||||
id="knowledge-base-delete"
|
||||
:title="$t('knowledgeBase.deleteKnowledgeBase')"
|
||||
class="top-tool-btn margin-r-10"
|
||||
@click="onDelete"
|
||||
style="width:72px;">
|
||||
<i class="cn-icon-delete cn-icon"></i>
|
||||
<span>{{ $t('overall.delete') }}</span>
|
||||
</button>
|
||||
|
||||
<div class="top-tool-search margin-l-10">
|
||||
<el-input v-model="keyWord" size="small" style="height: 28px;" @keyup.enter="onSearch"></el-input>
|
||||
<button
|
||||
class="top-tool-btn top-tool-btn--search"
|
||||
style="border-radius: 0 2px 2px 0 !important;"
|
||||
@click="onSearch">
|
||||
<i class="el-icon-search"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'DetectionTools',
|
||||
props: {
|
||||
disableDelete: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
keyWord: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onSearch () {
|
||||
this.$emit('search', this.keyWord)
|
||||
},
|
||||
onCreate () {
|
||||
this.$emit('create')
|
||||
},
|
||||
onDelete (data) {
|
||||
this.$emit('delete', data)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
||||
301
src/views/detectionsNew/Index.vue
Normal file
301
src/views/detectionsNew/Index.vue
Normal file
@@ -0,0 +1,301 @@
|
||||
<template>
|
||||
<div class="detection">
|
||||
<div class="detection-title">
|
||||
<span>{{ $t('overall.detections') }}</span>
|
||||
<span class="detection-title-label">
|
||||
60 Polices created(200 max) | 32 polices enabled(100 max)
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="detection-content">
|
||||
<div class="detection-filter">
|
||||
<detection-filter></detection-filter>
|
||||
</div>
|
||||
|
||||
<div class="detection-block">
|
||||
<detection-tools
|
||||
@delete="toDelete"
|
||||
@create="onCreate"
|
||||
@search="onSearch"
|
||||
:disableDelete="disableDelete"/>
|
||||
|
||||
<div class="detection-table" style="position: relative">
|
||||
<loading :loading="loading"></loading>
|
||||
<detection-table
|
||||
ref="dataTable"
|
||||
height="100%"
|
||||
:api="url"
|
||||
:isNoData="isNoData"
|
||||
:custom-table-title="tools.customTableTitle"
|
||||
:table-data="tableData"
|
||||
:is-selected-status="isSelectedStatus"
|
||||
:all-count="18"
|
||||
@selectionChange="selectionChange"
|
||||
@reload="reloadRowList"
|
||||
@toggleLoading="toggleLoading"
|
||||
@rowDoubleClick="onRowDoubleClick"
|
||||
></detection-table>
|
||||
</div>
|
||||
|
||||
<div class="knowledge-pagination">
|
||||
<pagination ref="pagination" :page-obj="pageObj" :table-id="tableId" @pageNo='pageNo' @pageSize='pageSize'></pagination>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-dialog
|
||||
v-model="showConfirmDialog"
|
||||
:title="$t('overall.hint')"
|
||||
width="480px"
|
||||
custom-class="del-model-hint"
|
||||
:before-close="handleClose">
|
||||
<div class="dialog-message">{{ $t('knowledge.deleteDataHint') }}</div>
|
||||
<el-table v-model="delItemList"
|
||||
ref="delDataTable"
|
||||
:data="batchDeleteObjs"
|
||||
@selection-change="secondSelectionChange"
|
||||
height="156px"
|
||||
width="100%"
|
||||
class="dialog-table"
|
||||
cell-style="padding:4px 0px;font-size: 12px;color: #353636;font-weight: 400;"
|
||||
header-cell-style="padding:4px 0px;background: #F5F8FA;font-size: 12px;color: #353636;font-weight: 500;">
|
||||
<el-table-column :resizable="false" align="center" type="selection" width="50"></el-table-column>
|
||||
<el-table-column property="ruleId" label="ID" width="70"></el-table-column>
|
||||
<el-table-column property="name" label="Name"></el-table-column>
|
||||
<el-table-column property="category" label="Category" width="100" :formatter="categoryFormat"></el-table-column>
|
||||
<el-table-column property="function" label="Function" width="110" :formatter="sourceFormat"></el-table-column>
|
||||
</el-table>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="showConfirmDialog = false">{{ $t('overall.cancel') }}</el-button>
|
||||
<el-button type="primary" @click="submit">{{ $t('tip.confirm') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<div class="detection-drawer">
|
||||
<el-drawer v-model="showDrawer" :with-header="false">
|
||||
<detection-drawer :drawer-info="drawerInfo"></detection-drawer>
|
||||
</el-drawer>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DetectionFilter from '@/views/detectionsNew/DetectionFilter'
|
||||
import DetectionTools from '@/views/detectionsNew/DetectionTools'
|
||||
import DetectionTable from '@/views/detectionsNew/DetectionTable'
|
||||
import { api } from '@/utils/api'
|
||||
import dataListMixin from '@/mixins/data-list'
|
||||
import DetectionDrawer from '@/views/detectionsNew/DetectionDrawer'
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'Index',
|
||||
components: {
|
||||
DetectionFilter,
|
||||
DetectionTools,
|
||||
DetectionTable,
|
||||
DetectionDrawer
|
||||
},
|
||||
mixins: [dataListMixin],
|
||||
data () {
|
||||
return {
|
||||
// url: api.detection.list,
|
||||
url: api.knowledgeBase,
|
||||
listUrl: api.detection.list,
|
||||
tableId: 'detectionTable',
|
||||
isNoData: false,
|
||||
tableData: [],
|
||||
isSelectedStatus: false,
|
||||
batchDeleteObjs: [], // 待删除列表
|
||||
secondBatchDeleteObjs: [],
|
||||
disableDelete: true,
|
||||
showConfirmDialog: false,
|
||||
delItemList: [],
|
||||
showDrawer: false,
|
||||
drawerInfo: {}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onSearch () {
|
||||
// todo 暂时禁用,后续再开发时解禁
|
||||
// const params = {
|
||||
// ...this.filterParams,
|
||||
// name: this.keyWord
|
||||
// }
|
||||
// this.clearList()
|
||||
// this.search(params)
|
||||
// this.$refs.knowledgeFilter.reloadFilter(this.checkedCategoryIds, this.checkedStatusIds)
|
||||
},
|
||||
toDelete (data) {
|
||||
// todo 暂时禁用,后续再开发时解禁
|
||||
// if (data && data.ruleId) {
|
||||
// this.secondBatchDeleteObjs = []
|
||||
// this.batchDeleteObjs = []
|
||||
// this.secondBatchDeleteObjs.push(data)
|
||||
// this.batchDeleteObjs.push(data)
|
||||
// }
|
||||
// this.showDelDialog()
|
||||
},
|
||||
onCreate () {
|
||||
// todo 暂时禁用,后续再开发时解禁
|
||||
// this.$router.push({
|
||||
// path: '/detection/policies/create',
|
||||
// query: {
|
||||
// t: +new Date()
|
||||
// }
|
||||
// })
|
||||
},
|
||||
selectionChange (objs) {
|
||||
this.batchDeleteObjs = []
|
||||
objs.forEach(obj => {
|
||||
const delObj = this.batchDeleteObjs.find(item => item.ruleId === obj.ruleId)
|
||||
if (delObj === undefined) {
|
||||
this.batchDeleteObjs.push(obj)
|
||||
}
|
||||
})
|
||||
this.disableEdit = this.batchDeleteObjs.length !== 1
|
||||
this.disableDelete = this.batchDeleteObjs.length < 1
|
||||
},
|
||||
reloadRowList () {
|
||||
this.getTableData()
|
||||
},
|
||||
toggleLoading () {
|
||||
},
|
||||
showDelDialog () {
|
||||
this.showConfirmDialog = true
|
||||
this.$nextTick(() => {
|
||||
this.batchDeleteObjs.forEach((item) => {
|
||||
this.$refs.delDataTable.toggleRowSelection(item, true)
|
||||
})
|
||||
})
|
||||
},
|
||||
handleClose () {
|
||||
this.showConfirmDialog = false
|
||||
},
|
||||
secondSelectionChange (objs) {
|
||||
this.secondBatchDeleteObjs = objs
|
||||
},
|
||||
categoryFormat (row, column) {
|
||||
// const category = row.category
|
||||
// const t = knowledgeBaseCategory.find(t => t.value === category)
|
||||
// return t ? t.name : category
|
||||
},
|
||||
sourceFormat (row, column) {
|
||||
// const source = row.source
|
||||
// const t = knowledgeBaseSource.find(t => t.value === source)
|
||||
// return t ? t.name : source
|
||||
},
|
||||
submit () {
|
||||
this.delBatchDetection()
|
||||
this.showConfirmDialog = false
|
||||
},
|
||||
delBatchDetection () {
|
||||
const ids = []
|
||||
if (this.secondBatchDeleteObjs && this.secondBatchDeleteObjs.length > 0) {
|
||||
this.secondBatchDeleteObjs.forEach(item => {
|
||||
ids.push(item.ruleId)
|
||||
})
|
||||
}
|
||||
if (ids.length === 0) {
|
||||
this.$alert(this.$t('tip.pleaseSelect'), {
|
||||
confirmButtonText: this.$t('tip.yes'),
|
||||
type: 'warning'
|
||||
}).catch(() => {
|
||||
})
|
||||
} else {
|
||||
// todo 调用接口删除
|
||||
// this.toggleLoading(true)
|
||||
// axios.delete(api.detection.delete + '?ruleIds=' + ids).then(response => {
|
||||
// if (response.data.code === 200) {
|
||||
// this.delFlag = true
|
||||
// this.$message({ duration: 2000, type: 'success', message: this.$t('tip.deleteSuccess') })
|
||||
// this.secondBatchDeleteObjs.forEach((item) => {
|
||||
// this.$refs.delDataTable.toggleRowSelection(item, false)
|
||||
// })
|
||||
// this.$refs.knowledgeFilter.reloadFilter()
|
||||
// this.secondBatchDeleteObjs = []
|
||||
// this.batchDeleteObjs = []
|
||||
// delete this.searchLabel.category
|
||||
// delete this.searchLabel.source
|
||||
// this.getTableData()
|
||||
// } else {
|
||||
// this.$message.error(response.data.message)
|
||||
// }
|
||||
// }).finally(() => {
|
||||
// this.toggleLoading(false)
|
||||
// if (this.isSelectedStatus != undefined) {
|
||||
// this.isSelectedStatus = false
|
||||
// this.disableDelete = true
|
||||
// this.secondBatchDeleteObjs = []
|
||||
// this.batchDeleteObjs = []
|
||||
// this.showConfirmDialog = false
|
||||
// }
|
||||
// })
|
||||
}
|
||||
},
|
||||
onRowDoubleClick (data) {
|
||||
// todo 暂时禁用,后续再开发时解禁
|
||||
// this.showDrawer = true
|
||||
// this.drawerInfo = data
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.detection {
|
||||
padding: 20px;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
|
||||
.detection-title {
|
||||
font-family: NotoSansHans-Black;
|
||||
line-height: 24px;
|
||||
font-size: 24px;
|
||||
color: #353636;
|
||||
font-weight: 900;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.detection-title-label {
|
||||
font-family: NotoSansSChineseRegular;
|
||||
font-size: 12px;
|
||||
color: #717171;
|
||||
letter-spacing: 0;
|
||||
line-height: 18px;
|
||||
font-weight: 400;
|
||||
margin-top: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.detection-content {
|
||||
margin-top: 15px;
|
||||
width: 100%;
|
||||
height: calc(100% - 96px);
|
||||
display: flex;
|
||||
|
||||
.detection-filter {
|
||||
width: 320px;
|
||||
height: calc(100% + 34px);
|
||||
background: #FFFFFF;
|
||||
border: 1px solid rgba(226, 229, 236, 1);
|
||||
border-radius: 4px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.detection-block {
|
||||
width: calc(100% - 340px);
|
||||
|
||||
.detection-table {
|
||||
width: 100%;
|
||||
height: calc(100% - 44px);
|
||||
border-radius: 4px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
150
src/views/entityExplorer/EntityFilterOld.vue
Normal file
150
src/views/entityExplorer/EntityFilterOld.vue
Normal file
@@ -0,0 +1,150 @@
|
||||
<template >
|
||||
<div class="entity-filter-case">
|
||||
<div class="filter-case__header">{{$t('entities.filter')}}</div>
|
||||
<div
|
||||
class="entity-filter"
|
||||
v-for="(filters, index) in filterData"
|
||||
:key="index"
|
||||
>
|
||||
<div class="filter__header">{{filters.title}}</div>
|
||||
<div class="filter__body">
|
||||
|
||||
<div class="filter__row" v-for="(item, i) in filters.data" :key="i">
|
||||
<el-popover popper-class="filter__row-popover" placement="right-start" :width="440" v-model:visible="item.showTopTen">
|
||||
<template #reference>
|
||||
<div class="filter__row-popover" @click="showTopDialog(i, item, filters)">
|
||||
<div class="row__label">
|
||||
<i :class="item.icon"></i>
|
||||
<span>{{item.label}}</span>
|
||||
</div>
|
||||
<div class="row__value">
|
||||
<loading :loading="loadingLeft" size="small"></loading>
|
||||
<span>{{item.value}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<entity-top
|
||||
ref="entityTopTenPop"
|
||||
:loading="loading"
|
||||
:popover-data="popoverData"
|
||||
:item-data="itemData"
|
||||
:total-count="totalCount"
|
||||
:top-column="item.topColumn"
|
||||
@filter="filter"
|
||||
></entity-top>
|
||||
</el-popover>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import EntityTop from '@/views/entityExplorer/EntityTop'
|
||||
import { get } from '@/utils/http'
|
||||
import { api } from '@/utils/api'
|
||||
import Loading from '@/components/common/Loading'
|
||||
import { getSecond } from '@/utils/date-util'
|
||||
export default {
|
||||
name: 'EntityFilter',
|
||||
components: {
|
||||
Loading,
|
||||
EntityTop
|
||||
},
|
||||
props: {
|
||||
filterData: Array,
|
||||
q: String,
|
||||
timeFilter: Object,
|
||||
loadingLeft: Boolean
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
topList: 'list',
|
||||
topData: [],
|
||||
entityTopTenData: [],
|
||||
currentColumn: {},
|
||||
totalCount: 0,
|
||||
loading: false,
|
||||
popoverData: [],
|
||||
itemData: {}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
currentColumn (n, o) {
|
||||
if (n.column === 'dnsServerOrgCount') {
|
||||
this.totalCount = this.filterData[3].orgTotalCount
|
||||
} else if (n.column === 'dnsServerSoftwareCount') {
|
||||
this.totalCount = this.filterData[3].softwareTotalCount
|
||||
} else if (n.column === 'dnsServerOsCount') {
|
||||
this.totalCount = this.filterData[3].osTotalCount
|
||||
} else if (n.column === 'categoryDistinctCount' && n.type === 'app') {
|
||||
this.totalCount = this.filterData[1].totalCount
|
||||
} else {
|
||||
let count = 0
|
||||
this.filterData.forEach(f => {
|
||||
const filter = f.data.some(d => d.column === n.column)
|
||||
if (filter) {
|
||||
count = f.totalCount
|
||||
}
|
||||
})
|
||||
this.totalCount = count
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
showTopDialog (i, item, filter) {
|
||||
if (this.currentColumn.column === item.column && item.showTopTen) {
|
||||
item.showTopTen = false
|
||||
return
|
||||
}
|
||||
this.filterData.forEach(f => {
|
||||
f.data.forEach(ff => {
|
||||
ff.showTopTen = false
|
||||
})
|
||||
})
|
||||
item.showTopTen = true
|
||||
this.currentColumn = {
|
||||
column: item.column,
|
||||
type: filter.type
|
||||
}
|
||||
const queryParams = {
|
||||
q: this.q,
|
||||
entityType: filter.type,
|
||||
column: item.topColumn,
|
||||
top: 10,
|
||||
startTime: getSecond(this.timeFilter.startTime),
|
||||
endTime: getSecond(this.timeFilter.endTime)
|
||||
}
|
||||
this.loading = true
|
||||
this.popoverData = []
|
||||
this.itemData = {}
|
||||
get(api.filterTop, queryParams).then(response => {
|
||||
if (response.code === 200) {
|
||||
if (this.currentColumn.column === item.column) {
|
||||
if (filter.type === 'dns') {
|
||||
this.popoverData = response.data.result.filter(f => {
|
||||
return f.count > 0
|
||||
})
|
||||
} else {
|
||||
this.popoverData = response.data.result
|
||||
}
|
||||
this.itemData = item
|
||||
}
|
||||
} else {
|
||||
this.popoverData = []
|
||||
this.itemData = item
|
||||
}
|
||||
this.loading = false
|
||||
}).catch(e => {
|
||||
this.popoverData = []
|
||||
this.itemData = item
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
filter (name, topData) {
|
||||
this.showTopDialog('', topData)
|
||||
this.$emit('filter', name, topData)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user