CN-333 feat : Dashboard--dns 实时告警信息图表开发 以及CN-332的一些样式修改
This commit is contained in:
@@ -40,6 +40,7 @@
|
|||||||
@import './views/charts/ChartTwoSituationStatistics';
|
@import './views/charts/ChartTwoSituationStatistics';
|
||||||
@import './views/charts/chartAlarmInfo';
|
@import './views/charts/chartAlarmInfo';
|
||||||
@import './views/chartHeader';
|
@import './views/chartHeader';
|
||||||
|
@import './views/charts/chartMap';
|
||||||
|
|
||||||
|
|
||||||
//@import '../chart';
|
//@import '../chart';
|
||||||
|
|||||||
60
src/assets/css/components/views/charts/chartMap.scss
Normal file
60
src/assets/css/components/views/charts/chartMap.scss
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
.cn-chart__map {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.map-drawing {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.map-chart__legends {
|
||||||
|
flex-basis: 116px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding: 0 30px;
|
||||||
|
|
||||||
|
.map-chart__legend {
|
||||||
|
padding-bottom: 5px;
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
border: 1px solid #E0E6EF;
|
||||||
|
border-left-color: transparent;
|
||||||
|
border-right-color: transparent;;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:first-of-type {
|
||||||
|
border-left-color: #E0E6EF;
|
||||||
|
}
|
||||||
|
&:last-of-type {
|
||||||
|
border-right-color: #E0E6EF;
|
||||||
|
}
|
||||||
|
&.map-chart__legend--active {
|
||||||
|
border-color: #59ABFF;
|
||||||
|
|
||||||
|
.legend__value {
|
||||||
|
color: #1890FF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.legend__circle-marker {
|
||||||
|
flex: 0 0 12px;
|
||||||
|
margin: 12px 0 8px 0;
|
||||||
|
width: 12px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
.legend__value {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
.legend__name {
|
||||||
|
padding: 0 10px;
|
||||||
|
color: #666666;
|
||||||
|
font-size: 12px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -126,7 +126,8 @@
|
|||||||
import { get } from '@/utils/http'
|
import { get } from '@/utils/http'
|
||||||
import { api } from '@/utils/api'
|
import { api } from '@/utils/api'
|
||||||
import * as echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import { getChartColor, entityListLineOption } from '@/views/charts/charts/chart-options'
|
import { entityListLineOption } from '@/views/charts/charts/chart-options'
|
||||||
|
import { getChartColor } from '@/views/charts/charts/tools'
|
||||||
import { legendMapping } from '@/views/charts/charts/chart-table-title'
|
import { legendMapping } from '@/views/charts/charts/chart-table-title'
|
||||||
import unitConvert from '@/utils/unit-convert'
|
import unitConvert from '@/utils/unit-convert'
|
||||||
import { unitTypes } from '@/utils/constants'
|
import { unitTypes } from '@/utils/constants'
|
||||||
|
|||||||
@@ -84,15 +84,17 @@ export const api = {
|
|||||||
victimLocation: '/interface/detection/security/filter/victimLocation',
|
victimLocation: '/interface/detection/security/filter/victimLocation',
|
||||||
eventSeverity: '/interface/detection/security/filter/severity',
|
eventSeverity: '/interface/detection/security/filter/severity',
|
||||||
listBasic: '/interface/detection/security/list/basic',
|
listBasic: '/interface/detection/security/list/basic',
|
||||||
|
listCount: '/interface/detection/security/list/count',
|
||||||
overviewBasic: '/interface/detection/security/detail/overview/basic',
|
overviewBasic: '/interface/detection/security/detail/overview/basic',
|
||||||
overviewEvent: '/interface/detection/security/detail/overview/event'
|
overviewEvent: '/interface/detection/security/detail/overview/event'
|
||||||
},
|
},
|
||||||
performanceEvent: {
|
performanceEvent: {
|
||||||
eventSeverityTrend: '/interface/detection/performance/filter/severityTrend',
|
eventSeverityTrend: '/interface/detection/performance/filter/severityTrend',
|
||||||
securityType: '/interface/detection/performance/filter/eventType',
|
eventType: '/interface/detection/performance/filter/eventType',
|
||||||
eventSeverity: '/interface/detection/performance/filter/severity',
|
eventSeverity: '/interface/detection/performance/filter/severity',
|
||||||
activeEntity: '/interface/detection/performance/filter/activeEntity',
|
activeEntity: '/interface/detection/performance/filter/activeEntity',
|
||||||
listBasic: '/interface/detection/performance/list/basic',
|
listBasic: '/interface/detection/performance/list/basic',
|
||||||
|
listCount: '/interface/detection/performance/list/count',
|
||||||
overviewBasic: '/interface/detection/performance/detail/overview/basic'
|
overviewBasic: '/interface/detection/performance/detail/overview/basic'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -130,7 +130,19 @@ export const unitTypes = {
|
|||||||
export const chartTableDefaultPageSize = 10 // table类型图表默认每页数据量
|
export const chartTableDefaultPageSize = 10 // table类型图表默认每页数据量
|
||||||
export const chartTableTopOptions = [10, 100] // table类型图表的TOP-N选项
|
export const chartTableTopOptions = [10, 100] // table类型图表的TOP-N选项
|
||||||
export const chartActiveIpTableOrderOptions = ['machine'] // active ip table类型图表的order 选项
|
export const chartActiveIpTableOrderOptions = ['machine'] // active ip table类型图表的order 选项
|
||||||
// table类型图表的TOP-N选项
|
// table类型图表column映射
|
||||||
|
export const chartTableColumnMapping = {
|
||||||
|
sessions: 'overall.sessions',
|
||||||
|
packets: 'overall.packets',
|
||||||
|
bytes: 'overall.bytes',
|
||||||
|
clientIp: 'overall.clientIp',
|
||||||
|
serverIp: 'overall.serverIp',
|
||||||
|
domain: 'overall.domain',
|
||||||
|
appName: 'overall.appName',
|
||||||
|
queryRate: 'dns.queryRate',
|
||||||
|
dnsLatency: 'dns.averageResolveLatency',
|
||||||
|
responseFailRate: 'dns.responseFailureRate'
|
||||||
|
}
|
||||||
export const chartPieTableTopOptions = [
|
export const chartPieTableTopOptions = [
|
||||||
{ name: 'Sessions', value: 'sessions' },
|
{ name: 'Sessions', value: 'sessions' },
|
||||||
{ name: 'Packets', value: 'packets' },
|
{ name: 'Packets', value: 'packets' },
|
||||||
@@ -170,6 +182,20 @@ export const detectionPageType = {
|
|||||||
performanceEvent: 'performanceEvent'
|
performanceEvent: 'performanceEvent'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const dnsServerRole = {
|
||||||
|
RTDNS: 'RTDNS',
|
||||||
|
TLDNS: 'TLDNS',
|
||||||
|
OPRDNS: 'OPRDNS',
|
||||||
|
ADNS: 'ADNS',
|
||||||
|
SBDNS: 'SBDNS',
|
||||||
|
RTDNSM: 'RTDNSM'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const chartColor = ['#5370C6', '#90CC74', '#FAC858', '#EE6666',
|
||||||
|
'#73BFDE', '#3BA172', '#FC8452', '#9960B4',
|
||||||
|
'#E97CCC', '#FEA69E', '#0F8AB2', '#57CBAC',
|
||||||
|
'#5888BC', '#63B6AC', '#EDC6B2', '#D5746B']
|
||||||
|
|
||||||
export const iso36112 = {
|
export const iso36112 = {
|
||||||
[storageKey.iso36112Capital]: 'data/countriesWithCapital',
|
[storageKey.iso36112Capital]: 'data/countriesWithCapital',
|
||||||
[storageKey.iso36112WorldLow]: 'worldChinaLow',
|
[storageKey.iso36112WorldLow]: 'worldChinaLow',
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export function getMillisecond (time) {
|
|||||||
ms = Math.floor(time * (10 ** (0 - difference)))
|
ms = Math.floor(time * (10 ** (0 - difference)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ms
|
return ms ? Number(ms) : null
|
||||||
}
|
}
|
||||||
// 初始化日期
|
// 初始化日期
|
||||||
export function getNowTime (interval) {
|
export function getNowTime (interval) {
|
||||||
@@ -40,3 +40,7 @@ export function getNowTime (interval) {
|
|||||||
endTime
|
endTime
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 日期格式转换
|
||||||
|
export function rTime (date) {
|
||||||
|
return window.$dayJs.tz(new Date(date)).format('YYYY-MM-DD HH:mm:ss')
|
||||||
|
}
|
||||||
|
|||||||
@@ -444,12 +444,18 @@ export function lineToHump (name) {
|
|||||||
}
|
}
|
||||||
// 下划线转换空格首位大写
|
// 下划线转换空格首位大写
|
||||||
export function lineToSpace (name) {
|
export function lineToSpace (name) {
|
||||||
|
if (_.isEmpty(name)) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
return _.upperFirst(name.replace(/\_(\w)/g, function (all, letter) {
|
return _.upperFirst(name.replace(/\_(\w)/g, function (all, letter) {
|
||||||
return ` ${letter.toUpperCase()}`
|
return ` ${letter.toUpperCase()}`
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
// 驼峰转换下划线
|
// 驼峰转换下划线
|
||||||
export function humpToLine (name) {
|
export function humpToLine (name) {
|
||||||
|
if (_.isEmpty(name)) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
return name.replace(/([A-Z])/g, '_$1').toLowerCase()
|
return name.replace(/([A-Z])/g, '_$1').toLowerCase()
|
||||||
}
|
}
|
||||||
// 搜索功能:对象转字符串
|
// 搜索功能:对象转字符串
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
:chart-data="chartData"
|
:chart-data="chartData"
|
||||||
:query-params="queryParams"
|
:query-params="queryParams"
|
||||||
:entity="entity"
|
:entity="entity"
|
||||||
|
@query="query"
|
||||||
@showLoading="showLoading"
|
@showLoading="showLoading"
|
||||||
></chart-map>
|
></chart-map>
|
||||||
|
|
||||||
@@ -79,7 +80,7 @@
|
|||||||
></chart-ip-open-port-bar>
|
></chart-ip-open-port-bar>
|
||||||
|
|
||||||
<chart-table
|
<chart-table
|
||||||
v-else-if="isTable && isCurrentTable"
|
v-else-if="isTable && isBasicTable"
|
||||||
:chart-info="chartInfo"
|
:chart-info="chartInfo"
|
||||||
:chart-data="chartData"
|
:chart-data="chartData"
|
||||||
:table="table"
|
:table="table"
|
||||||
@@ -245,7 +246,7 @@ import {
|
|||||||
isEchartsLine,
|
isEchartsLine,
|
||||||
isSingleValue,
|
isSingleValue,
|
||||||
isTable,
|
isTable,
|
||||||
isCurrentTable,
|
isBasicTable,
|
||||||
isActiveIpTable,
|
isActiveIpTable,
|
||||||
isTitle,
|
isTitle,
|
||||||
isMap,
|
isMap,
|
||||||
@@ -371,6 +372,9 @@ export default {
|
|||||||
`chart${this.chartInfo.id}`
|
`chart${this.chartInfo.id}`
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
query (params) {
|
||||||
|
this.$emit('query', params)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
chartData: {
|
chartData: {
|
||||||
@@ -401,7 +405,7 @@ export default {
|
|||||||
),
|
),
|
||||||
isRelationShip: isRelationShip(props.chartInfo.type),
|
isRelationShip: isRelationShip(props.chartInfo.type),
|
||||||
isTable: isTable(props.chartInfo.type),
|
isTable: isTable(props.chartInfo.type),
|
||||||
isCurrentTable: isCurrentTable(props.chartInfo.type),
|
isBasicTable: isBasicTable(props.chartInfo.type),
|
||||||
isActiveIpTable: isActiveIpTable(props.chartInfo.type),
|
isActiveIpTable: isActiveIpTable(props.chartInfo.type),
|
||||||
isMap: isMap(props.chartInfo.type),
|
isMap: isMap(props.chartInfo.type),
|
||||||
isTitle: isTitle(props.chartInfo.type),
|
isTitle: isTitle(props.chartInfo.type),
|
||||||
|
|||||||
@@ -27,6 +27,8 @@
|
|||||||
{{ chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name }}
|
{{ chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name }}
|
||||||
</div>
|
</div>
|
||||||
<template v-if="isCurrentTable">
|
<template v-if="isCurrentTable">
|
||||||
|
<div class="chart-header__title" v-else-if="!isBasicTable" :class="{'chart-header__title--block': isBlock}" :title="chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name">{{chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name}}</div>
|
||||||
|
<template v-if="isBasicTable">
|
||||||
<div class="chart-header__title">
|
<div class="chart-header__title">
|
||||||
<span :title="chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name">{{
|
<span :title="chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name">{{
|
||||||
chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name
|
chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name
|
||||||
@@ -257,6 +259,7 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
chartTableColumnMapping,
|
||||||
dropdownMenuShow: false,
|
dropdownMenuShow: false,
|
||||||
errorText: '',
|
errorText: '',
|
||||||
isFocus:false,
|
isFocus:false,
|
||||||
@@ -369,7 +372,7 @@ export default {
|
|||||||
isBlock: isBlock(props.chartInfo.type),
|
isBlock: isBlock(props.chartInfo.type),
|
||||||
isTabs: isTabs(props.chartInfo.type),
|
isTabs: isTabs(props.chartInfo.type),
|
||||||
isTable: isTable(props.chartInfo.type),
|
isTable: isTable(props.chartInfo.type),
|
||||||
isCurrentTable: isCurrentTable(props.chartInfo.type),
|
isBasicTable: isBasicTable(props.chartInfo.type),
|
||||||
isActiveIpTable: isActiveIpTable(props.chartInfo.type),
|
isActiveIpTable: isActiveIpTable(props.chartInfo.type),
|
||||||
isEchartsWithTable: isEchartsWithTable(props.chartInfo.type),
|
isEchartsWithTable: isEchartsWithTable(props.chartInfo.type),
|
||||||
isGroup: isGroup(props.chartInfo.type),
|
isGroup: isGroup(props.chartInfo.type),
|
||||||
|
|||||||
@@ -48,7 +48,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import ChartHeader from './ChartHeader'
|
import ChartHeader from './ChartHeader'
|
||||||
import Chart from '@/views/charts/Chart'
|
import Chart from '@/views/charts/Chart'
|
||||||
import testData from './charts/testData'
|
import { dnsServerRole, chartPieTableTopOptions, chartTableDefaultPageSize, chartTableTopOptions } from '@/utils/constants'
|
||||||
import {
|
import {
|
||||||
isEcharts,
|
isEcharts,
|
||||||
isSingleValue,
|
isSingleValue,
|
||||||
@@ -81,7 +81,7 @@ import {
|
|||||||
import { tableTitleMapping, legendMapping } from '@/views/charts/charts/chart-table-title'
|
import { tableTitleMapping, legendMapping } from '@/views/charts/charts/chart-table-title'
|
||||||
import { replaceUrlPlaceholder } from '@/utils/tools'
|
import { replaceUrlPlaceholder } from '@/utils/tools'
|
||||||
import { getNowTime, getSecond } from '@/utils/date-util'
|
import { getNowTime, getSecond } from '@/utils/date-util'
|
||||||
import { chartPieTableTopOptions, chartTableDefaultPageSize, chartTableTopOptions } from '@/utils/constants'
|
|
||||||
import { get } from '@/utils/http'
|
import { get } from '@/utils/http'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
@@ -194,6 +194,10 @@ export default {
|
|||||||
...extraParams
|
...extraParams
|
||||||
}
|
}
|
||||||
const requestUrl = url || (chartParams && chartParams.url)
|
const requestUrl = url || (chartParams && chartParams.url)
|
||||||
|
// 默认参数特殊处理
|
||||||
|
if (requestUrl && requestUrl.indexOf('dnsServerRole') > -1) {
|
||||||
|
this.queryParams.dnsServerRole = extraParams.dnsServerRole || dnsServerRole.RTDNS
|
||||||
|
}
|
||||||
if (requestUrl) {
|
if (requestUrl) {
|
||||||
get(replaceUrlPlaceholder(requestUrl, this.queryParams)).then(response => {
|
get(replaceUrlPlaceholder(requestUrl, this.queryParams)).then(response => {
|
||||||
// if (this.chartInfo.type === 23 && testData) {
|
// if (this.chartInfo.type === 23 && testData) {
|
||||||
@@ -201,6 +205,27 @@ export default {
|
|||||||
// } else if (this.chartInfo.type === 24 && testData) {
|
// } else if (this.chartInfo.type === 24 && testData) {
|
||||||
// response = testData.data2
|
// response = testData.data2
|
||||||
// }
|
// }
|
||||||
|
if (this.chartInfo.type === 3) {
|
||||||
|
response = {
|
||||||
|
code: 200,
|
||||||
|
data: {
|
||||||
|
result: [
|
||||||
|
{
|
||||||
|
dnsServerRole: extraParams.dnsServerRole || dnsServerRole.RTDNS,
|
||||||
|
ipLocationCountry: 'China',
|
||||||
|
ipLocationId: 'CN',
|
||||||
|
count: 161
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dnsServerRole: extraParams.dnsServerRole || dnsServerRole.RTDNS,
|
||||||
|
ipLocationCountry: 'Japan',
|
||||||
|
ipLocationId: 'JP',
|
||||||
|
count: 222
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (response.code === 200) {
|
if (response.code === 200) {
|
||||||
if (Array.isArray(response.data.result)) {
|
if (Array.isArray(response.data.result)) {
|
||||||
response.data.result.forEach(item => {
|
response.data.result.forEach(item => {
|
||||||
@@ -210,9 +235,6 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.chartData = response.data.result
|
this.chartData = response.data.result
|
||||||
this.table.tableData = response.data.result
|
|
||||||
this.table.tableColumns = this.getTableTitle(response.data.result)
|
|
||||||
this.table.currentPageData = this.getTargetPageData(1, this.table.pageSize, this.table.tableData)
|
|
||||||
this.resultType = response.data.resultType
|
this.resultType = response.data.resultType
|
||||||
if (this.chartInfo.type === 12) {
|
if (this.chartInfo.type === 12) {
|
||||||
const newArr = []
|
const newArr = []
|
||||||
@@ -231,7 +253,12 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (this.isSingleValue) {
|
if (this.isTable) {
|
||||||
|
this.table.tableData = response.data.result
|
||||||
|
// this.table.tableColumns = chartParams.columns
|
||||||
|
// this.table.tableColumns = this.getTableTitle(response.data.result)
|
||||||
|
this.table.currentPageData = this.getTargetPageData(1, this.table.pageSize, this.table.tableData)
|
||||||
|
} else if (this.isSingleValue) {
|
||||||
if (chartParams && chartParams.dataKey) {
|
if (chartParams && chartParams.dataKey) {
|
||||||
if (response.data.result && (response.data.result[chartParams.dataKey] || response.data.result[chartParams.dataKey] === 0)) {
|
if (response.data.result && (response.data.result[chartParams.dataKey] || response.data.result[chartParams.dataKey] === 0)) {
|
||||||
this.chartData = response.data.result[chartParams.dataKey]
|
this.chartData = response.data.result[chartParams.dataKey]
|
||||||
@@ -377,7 +404,19 @@ export default {
|
|||||||
const dateRangeValue = 60
|
const dateRangeValue = 60
|
||||||
const { startTime, endTime } = getNowTime(dateRangeValue)
|
const { startTime, endTime } = getNowTime(dateRangeValue)
|
||||||
const chartTimeFilter = ref({ startTime, endTime, dateRangeValue })
|
const chartTimeFilter = ref({ startTime, endTime, dateRangeValue })
|
||||||
|
let table = {}
|
||||||
|
if (isTable(props.chartInfo.type)) {
|
||||||
|
table = {
|
||||||
|
pageSize: chartTableDefaultPageSize,
|
||||||
|
limit: chartTableTopOptions[0], // top-n
|
||||||
|
orderBy: props.chartInfo.params.columns.order[0],
|
||||||
|
tableColumns: props.chartInfo.params.columns, // table字段
|
||||||
|
tableData: [], // table的所有数据
|
||||||
|
currentPageData: [] // table当前页的数据
|
||||||
|
}
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
|
table,
|
||||||
chartTimeFilter,
|
chartTimeFilter,
|
||||||
isEcharts: isEcharts(props.chartInfo.type),
|
isEcharts: isEcharts(props.chartInfo.type),
|
||||||
isEchartsTimeBar: isEchartsTimeBar(props.chartInfo.type),
|
isEchartsTimeBar: isEchartsTimeBar(props.chartInfo.type),
|
||||||
|
|||||||
@@ -28,18 +28,18 @@
|
|||||||
v-for="(c, i) in table.tableColumns"
|
v-for="(c, i) in table.tableColumns"
|
||||||
show-overflow-tooltip
|
show-overflow-tooltip
|
||||||
:key="i"
|
:key="i"
|
||||||
:label="c.label"
|
:label="$t(chartTableOrderOptionsMapping[c])"
|
||||||
:prop="c.prop"
|
:prop="c"
|
||||||
>
|
>
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<span v-if="c.prop === 'bytes'">
|
<span v-if="c === 'bytes'">
|
||||||
{{unitConvert(row[c.prop], unitTypes.byte).join(' ')}}
|
{{unitConvert(row[c], unitTypes.byte).join(' ')}}
|
||||||
</span>
|
</span>
|
||||||
<span v-else-if="c.prop === 'packets' || c.prop === 'sessions'">
|
<span v-else-if="c === 'packets' || c === 'sessions'">
|
||||||
{{unitConvert(row[c.prop], unitTypes.number).join(' ')}}
|
{{unitConvert(row[c], unitTypes.number).join(' ')}}
|
||||||
</span>
|
</span>
|
||||||
<span v-else>
|
<span v-else>
|
||||||
{{row[c.prop]}}
|
{{row[c]}}
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { unitTypes } from '@/utils/constants'
|
import { unitTypes, chartTableOrderOptionsMapping } from '@/utils/constants'
|
||||||
import unitConvert from '@/utils/unit-convert'
|
import unitConvert from '@/utils/unit-convert'
|
||||||
export default {
|
export default {
|
||||||
name: 'ChartActiveIpTable',
|
name: 'ChartActiveIpTable',
|
||||||
@@ -61,6 +61,7 @@ export default {
|
|||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
chartTableOrderOptionsMapping,
|
||||||
unitConvert,
|
unitConvert,
|
||||||
unitTypes,
|
unitTypes,
|
||||||
activeIpTable: {
|
activeIpTable: {
|
||||||
|
|||||||
@@ -6,14 +6,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import * as echarts from 'echarts'
|
|
||||||
import StatisticsLegend from '@/views/charts/charts/StatisticsLegend'
|
import StatisticsLegend from '@/views/charts/charts/StatisticsLegend'
|
||||||
import {
|
|
||||||
lineWithStatistics
|
|
||||||
} from '@/views/charts/charts/options/line'
|
|
||||||
import {
|
import {
|
||||||
getChartColor
|
getChartColor
|
||||||
} from '@/views/charts/charts/chart-options'
|
} from '@/views/charts/charts/tools'
|
||||||
import chartEchartMixin from './chart-echart-mixin'
|
import chartEchartMixin from './chart-echart-mixin'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import lodash from 'lodash'
|
import lodash from 'lodash'
|
||||||
import { ipOpenPortBar } from '@/views/charts/charts/options/bar'
|
import { ipOpenPortBar } from '@/views/charts/charts/options/bar'
|
||||||
import { getChartColor } from '@/views/charts/charts/chart-options'
|
import { getChartColor } from '@/views/charts/charts/tools'
|
||||||
import * as echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
export default {
|
export default {
|
||||||
name: 'ChartIpOpenPortBar',
|
name: 'ChartIpOpenPortBar',
|
||||||
|
|||||||
@@ -7,9 +7,8 @@
|
|||||||
import * as am4Core from '@amcharts/amcharts4/core'
|
import * as am4Core from '@amcharts/amcharts4/core'
|
||||||
import * as am4Maps from '@amcharts/amcharts4/maps'
|
import * as am4Maps from '@amcharts/amcharts4/maps'
|
||||||
import { getGeoData, replaceUrlPlaceholder } from '@/utils/tools'
|
import { getGeoData, replaceUrlPlaceholder } from '@/utils/tools'
|
||||||
import { storageKey } from '@/utils/constants'
|
import { storageKey, dnsServerRole } from '@/utils/constants'
|
||||||
|
import { isMapBlock, isMapPoint } from './tools'
|
||||||
import { isMapBlock } from './tools'
|
|
||||||
import unitConvert, { valueToRangeValue } from '@/utils/unit-convert'
|
import unitConvert, { valueToRangeValue } from '@/utils/unit-convert'
|
||||||
import { HeatLegend } from '@/components/amcharts/heatLegend'
|
import { HeatLegend } from '@/components/amcharts/heatLegend'
|
||||||
import { getData } from '@/utils/api'
|
import { getData } from '@/utils/api'
|
||||||
@@ -72,6 +71,7 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
loadAm4ChartMap (polygonSeries, country, chartData) {
|
loadAm4ChartMap (polygonSeries, country, chartData) {
|
||||||
|
// chartData不为空是下钻
|
||||||
if (chartData) {
|
if (chartData) {
|
||||||
this.$emit('showLoading', true)
|
this.$emit('showLoading', true)
|
||||||
}
|
}
|
||||||
@@ -111,8 +111,9 @@ export default {
|
|||||||
showValue: (r.value || r.value === 0) ? valueToRangeValue(r.value, chartParams.unitType).join(' ') : ''
|
showValue: (r.value || r.value === 0) ? valueToRangeValue(r.value, chartParams.unitType).join(' ') : ''
|
||||||
}))
|
}))
|
||||||
!this.$_.isEmpty(seriesData) && (polygonSeries.data = [...seriesData])
|
!this.$_.isEmpty(seriesData) && (polygonSeries.data = [...seriesData])
|
||||||
|
// 数据全为0的情况,legend只显示1个颜色
|
||||||
const sorted = seriesData.sort((a, b) => b.value - a.value)
|
const sorted = seriesData.sort((a, b) => b.value - a.value)
|
||||||
const allZero = this.$_.isEmpty(sorted) || Number(sorted[0].value) === 0 // 数据全为0的情况,legend只显示1个颜色
|
const allZero = this.$_.isEmpty(sorted) || Number(sorted[0].value) === 0
|
||||||
|
|
||||||
polygonSeries.heatRules.push({
|
polygonSeries.heatRules.push({
|
||||||
property: 'fill',
|
property: 'fill',
|
||||||
@@ -142,6 +143,56 @@ export default {
|
|||||||
heatLegend.valueAxis.renderer.labels.template.adapter.add('text', function (labelText) {
|
heatLegend.valueAxis.renderer.labels.template.adapter.add('text', function (labelText) {
|
||||||
return ''
|
return ''
|
||||||
})
|
})
|
||||||
|
} else if (data && this.isMapPoint) {
|
||||||
|
const seriesData = []
|
||||||
|
data.forEach(d => {
|
||||||
|
seriesData.push({
|
||||||
|
id: d.ipLocationId,
|
||||||
|
count: d.count,
|
||||||
|
dnsServerRole: d.dnsServerRole,
|
||||||
|
location: d.ipLocationCity || d.ipLocationProvince || d.ipLocationCountry,
|
||||||
|
desc: this.$t(this.dnsTypeI18n(d.dnsServerRole)),
|
||||||
|
color: this.circleColor[d.dnsServerRole].background,
|
||||||
|
border: this.circleColor[d.dnsServerRole].border
|
||||||
|
})
|
||||||
|
})
|
||||||
|
console.info(seriesData)
|
||||||
|
const imageSeries = this.myChart.series.push(new am4Maps.MapImageSeries())
|
||||||
|
imageSeries.data = seriesData
|
||||||
|
imageSeries.dataFields.value = 'count'
|
||||||
|
|
||||||
|
const imageTemplate = imageSeries.mapImages.template
|
||||||
|
imageTemplate.nonScaling = true
|
||||||
|
|
||||||
|
imageTemplate.adapter.add('latitude', function (latitude, target) {
|
||||||
|
const polygon = polygonSeries.getPolygonById(target.dataItem.dataContext.id)
|
||||||
|
if (polygon) {
|
||||||
|
return polygon.visualLatitude
|
||||||
|
}
|
||||||
|
return latitude
|
||||||
|
})
|
||||||
|
|
||||||
|
imageTemplate.adapter.add('longitude', function (longitude, target) {
|
||||||
|
const polygon = polygonSeries.getPolygonById(target.dataItem.dataContext.id)
|
||||||
|
if (polygon) {
|
||||||
|
return polygon.visualLongitude
|
||||||
|
}
|
||||||
|
return longitude
|
||||||
|
})
|
||||||
|
|
||||||
|
const circle = imageTemplate.createChild(am4Core.Circle)
|
||||||
|
circle.propertyFields.fill = 'color'
|
||||||
|
circle.propertyFields.stroke = 'border'
|
||||||
|
circle.strokeWidth = 1
|
||||||
|
circle.tooltipText = '[bold]{location}[/]\n{desc}: {count}'
|
||||||
|
|
||||||
|
imageSeries.heatRules.push({
|
||||||
|
target: circle,
|
||||||
|
property: 'radius',
|
||||||
|
min: 6,
|
||||||
|
max: 25,
|
||||||
|
dataField: 'value'
|
||||||
|
})
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
@@ -161,6 +212,37 @@ export default {
|
|||||||
this.myChart.goHome()
|
this.myChart.goHome()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
dnsTypeI18n (role) {
|
||||||
|
let i18n = ''
|
||||||
|
switch (role) {
|
||||||
|
case dnsServerRole.RTDNS: {
|
||||||
|
i18n = 'dns.rootDomainServers'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case dnsServerRole.TLDNS: {
|
||||||
|
i18n = 'dns.topLevelDomainServers'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case dnsServerRole.OPRDNS: {
|
||||||
|
i18n = 'dns.publicRecursiveDomainServers'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case dnsServerRole.ADNS: {
|
||||||
|
i18n = 'dns.authoritativeDomainServers'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case dnsServerRole.SBDNS: {
|
||||||
|
i18n = 'dns.selfBuiltDomainServers'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case dnsServerRole.RTDNSM: {
|
||||||
|
i18n = 'RTDNSM'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
default: break
|
||||||
|
}
|
||||||
|
return i18n
|
||||||
|
},
|
||||||
generateTooltipHTML () {
|
generateTooltipHTML () {
|
||||||
return `
|
return `
|
||||||
<div class="map-tooltip" style="padding-bottom: 10px;">
|
<div class="map-tooltip" style="padding-bottom: 10px;">
|
||||||
@@ -206,8 +288,35 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
setup (props) {
|
setup (props) {
|
||||||
|
const circleColor = {}
|
||||||
|
circleColor[dnsServerRole.RTDNS] = {
|
||||||
|
background: '#C0DEFE',
|
||||||
|
border: '#478AD5'
|
||||||
|
}
|
||||||
|
circleColor[dnsServerRole.TLDNS] = {
|
||||||
|
background: '#DBCFFA',
|
||||||
|
border: '#AA8CF2'
|
||||||
|
}
|
||||||
|
circleColor[dnsServerRole.ADNS] = {
|
||||||
|
background: '#A0E8E0',
|
||||||
|
border: '#1CC9B5'
|
||||||
|
}
|
||||||
|
circleColor[dnsServerRole.OPRDNS] = {
|
||||||
|
background: '#FFE1B5',
|
||||||
|
border: '#FFB84E'
|
||||||
|
}
|
||||||
|
circleColor[dnsServerRole.SBDNS] = {
|
||||||
|
background: '#FDC6C6',
|
||||||
|
border: '#FA7777'
|
||||||
|
}
|
||||||
|
circleColor[dnsServerRole.RTDNSM] = {
|
||||||
|
background: '#ECC6F7',
|
||||||
|
border: '#BF49DF'
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
isMapBlock: isMapBlock(props.chartInfo.type)
|
circleColor,
|
||||||
|
isMapBlock: isMapBlock(props.chartInfo.type),
|
||||||
|
isMapPoint: isMapPoint(props.chartInfo.type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ import {
|
|||||||
import { get } from '@/utils/http'
|
import { get } from '@/utils/http'
|
||||||
import { replaceUrlPlaceholder } from '@/utils/tools'
|
import { replaceUrlPlaceholder } from '@/utils/tools'
|
||||||
import * as echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import { getOption, getChartColor } from '@/views/charts/charts/chart-options'
|
import { getOption, getChartColor } from '@/views/charts/charts/tools'
|
||||||
export default {
|
export default {
|
||||||
name: 'chartSingleValue',
|
name: 'chartSingleValue',
|
||||||
props: {
|
props: {
|
||||||
|
|||||||
@@ -9,22 +9,30 @@
|
|||||||
<el-table-column v-if="table.currentPageData.length" type="index" label="#">
|
<el-table-column v-if="table.currentPageData.length" type="index" label="#">
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
v-for="(c, i) in table.tableColumns"
|
v-for="(c, i) in table.tableColumns.common"
|
||||||
show-overflow-tooltip
|
show-overflow-tooltip
|
||||||
:key="i"
|
:key="i"
|
||||||
:label="c.label"
|
:label="$t(chartTableColumnMapping[c])"
|
||||||
:prop="c.prop"
|
:prop="c"
|
||||||
>
|
>
|
||||||
<template #header>{{$t(c.label)}}</template>
|
</el-table-column>
|
||||||
|
<el-table-column
|
||||||
|
v-for="(c, i) in table.tableColumns.order"
|
||||||
|
show-overflow-tooltip
|
||||||
|
:key="i"
|
||||||
|
:label="$t(chartTableColumnMapping[c])"
|
||||||
|
:prop="c"
|
||||||
|
>
|
||||||
|
<template #header>{{$t(chartTableColumnMapping[c])}}</template>
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<span v-if="c.prop === 'bytes'">
|
<span v-if="c === 'bytes'">
|
||||||
{{unitConvert(row[c.prop], unitTypes.byte).join(' ')}}
|
{{unitConvert(row[c], unitTypes.byte).join(' ')}}
|
||||||
</span>
|
</span>
|
||||||
<span v-else-if="c.prop === 'packets' || c.prop === 'sessions'">
|
<span v-else-if="c === 'packets' || c === 'sessions'">
|
||||||
{{unitConvert(row[c.prop], unitTypes.number).join(' ')}}
|
{{unitConvert(row[c], unitTypes.number).join(' ')}}
|
||||||
</span>
|
</span>
|
||||||
<span v-else>
|
<span v-else>
|
||||||
{{row[c.prop]}}
|
{{row[c]}}
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@@ -41,7 +49,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { unitTypes } from '@/utils/constants'
|
import { unitTypes, chartTableColumnMapping } from '@/utils/constants'
|
||||||
import unitConvert from '@/utils/unit-convert'
|
import unitConvert from '@/utils/unit-convert'
|
||||||
import ChartTablePagination from '@/views/charts/charts/ChartTablePagination'
|
import ChartTablePagination from '@/views/charts/charts/ChartTablePagination'
|
||||||
export default {
|
export default {
|
||||||
@@ -57,6 +65,7 @@ export default {
|
|||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
chartTableColumnMapping,
|
||||||
unitConvert,
|
unitConvert,
|
||||||
unitTypes
|
unitTypes
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getChartColor } from '@/views/charts/charts/chart-options'
|
import { getChartColor } from '@/views/charts/charts/tools'
|
||||||
import unitConvert, { valueToRangeValue } from '@/utils/unit-convert'
|
import unitConvert, { valueToRangeValue } from '@/utils/unit-convert'
|
||||||
export default {
|
export default {
|
||||||
name: 'StatisticsLegend',
|
name: 'StatisticsLegend',
|
||||||
|
|||||||
@@ -1,333 +1,6 @@
|
|||||||
/**
|
import { axisFormatter } from '@/views/charts/charts/tools'
|
||||||
* @author 陈劲松
|
import { chartColor } from '@/utils/constants'
|
||||||
* @date 2021/6/16
|
|
||||||
* @description chart option和一些工具
|
|
||||||
*/
|
|
||||||
import { format } from 'echarts'
|
|
||||||
import { unitTypes } from '@/utils/constants'
|
|
||||||
import unitConvert from '@/utils/unit-convert'
|
|
||||||
import _ from 'lodash'
|
|
||||||
export const chartColor = ['#5370C6', '#90CC74', '#FAC858', '#EE6666',
|
|
||||||
'#73BFDE', '#3BA172', '#FC8452', '#9960B4',
|
|
||||||
'#E97CCC', '#FEA69E', '#0F8AB2', '#57CBAC',
|
|
||||||
'#5888BC', '#63B6AC', '#EDC6B2', '#D5746B']
|
|
||||||
export const chartBarColor = ['#0F8AB2', '#57CBAC']
|
|
||||||
export function getChartColor (index) {
|
|
||||||
return chartColor[index % chartColor.length]
|
|
||||||
}
|
|
||||||
export function getCharBartColor (index) {
|
|
||||||
return chartBarColor[index % chartBarColor.length]
|
|
||||||
}
|
|
||||||
const line = {
|
|
||||||
tooltip: {
|
|
||||||
appendToBody: true,
|
|
||||||
trigger: 'axis',
|
|
||||||
textStyle: {
|
|
||||||
width: '20px',
|
|
||||||
overflow: 'truncate'
|
|
||||||
},
|
|
||||||
formatter: axiosFormatter,
|
|
||||||
show: true,
|
|
||||||
className: 'nz-chart-tooltip',
|
|
||||||
extraCssText: 'box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);max-width: 300px !important'
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
type: 'time'
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
type: 'value',
|
|
||||||
axisLabel: {
|
|
||||||
formatter: function (value, index, a, b) {
|
|
||||||
return unitConvert(value, unitTypes.number).join(' ')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
minInterval: 1
|
|
||||||
},
|
|
||||||
animation: false,
|
|
||||||
grid: {
|
|
||||||
left: 55,
|
|
||||||
bottom: 30,
|
|
||||||
top: 100,
|
|
||||||
right: 25
|
|
||||||
},
|
|
||||||
color: chartColor,
|
|
||||||
legend: {
|
|
||||||
tooltip: {
|
|
||||||
show: true,
|
|
||||||
formatter: '{a}'
|
|
||||||
},
|
|
||||||
show: true,
|
|
||||||
right: 23,
|
|
||||||
top: 8,
|
|
||||||
padding: 2,
|
|
||||||
orient: 'horizontal',
|
|
||||||
icon: 'circle',
|
|
||||||
itemGap: 10,
|
|
||||||
itemWidth: 10,
|
|
||||||
textStyle: {
|
|
||||||
padding: [0, 0, 0, 2],
|
|
||||||
fontSize: 14
|
|
||||||
},
|
|
||||||
formatter: tooLongFormatter
|
|
||||||
},
|
|
||||||
axisLabel: {
|
|
||||||
fontSize: 14
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: '',
|
|
||||||
type: 'line',
|
|
||||||
smooth: false,
|
|
||||||
symbol: 'none',
|
|
||||||
data: []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
const lineWithStatistics = {
|
|
||||||
tooltip: {
|
|
||||||
appendToBody: true,
|
|
||||||
trigger: 'axis',
|
|
||||||
textStyle: {
|
|
||||||
width: '20px',
|
|
||||||
overflow: 'truncate'
|
|
||||||
},
|
|
||||||
formatter: axiosFormatter,
|
|
||||||
className: 'nz-chart-tooltip',
|
|
||||||
extraCssText: 'box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);max-width: 300px !important'
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
type: 'time'
|
|
||||||
},
|
|
||||||
animation: false,
|
|
||||||
yAxis: {
|
|
||||||
type: 'value',
|
|
||||||
axisLabel: {
|
|
||||||
formatter: function (value, index) {
|
|
||||||
return unitConvert(value, unitTypes.number).join(' ')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
minInterval: 1
|
|
||||||
},
|
|
||||||
color: chartColor,
|
|
||||||
grid: {
|
|
||||||
left: 55,
|
|
||||||
bottom: 30,
|
|
||||||
top: 20,
|
|
||||||
right: 20
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
axisLabel: {
|
|
||||||
fontSize: 14
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: '',
|
|
||||||
type: 'line',
|
|
||||||
smooth: false,
|
|
||||||
symbol: 'none',
|
|
||||||
data: []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
const lineStack = {
|
|
||||||
tooltip: {
|
|
||||||
appendToBody: true,
|
|
||||||
trigger: 'axis',
|
|
||||||
textStyle: {
|
|
||||||
width: '20px',
|
|
||||||
overflow: 'truncate'
|
|
||||||
},
|
|
||||||
formatter: axiosFormatter,
|
|
||||||
className: 'nz-chart-tooltip',
|
|
||||||
extraCssText: 'box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);max-width: 300px !important'
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
type: 'time'
|
|
||||||
},
|
|
||||||
color: chartColor,
|
|
||||||
yAxis: {
|
|
||||||
type: 'value',
|
|
||||||
axisLabel: {
|
|
||||||
formatter: function (value, index) {
|
|
||||||
return unitConvert(value, unitTypes.number).join(' ')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
minInterval: 1
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
left: 55,
|
|
||||||
bottom: 45,
|
|
||||||
top: 10,
|
|
||||||
right: 180
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
show: true,
|
|
||||||
right: 30,
|
|
||||||
top: 'middle',
|
|
||||||
orient: 'vertical',
|
|
||||||
icon: 'circle',
|
|
||||||
itemGap: 20,
|
|
||||||
itemWidth: 10,
|
|
||||||
formatter: tooLongFormatter,
|
|
||||||
textStyle: {
|
|
||||||
padding: [0, 0, 0, 5],
|
|
||||||
fontSize: 14
|
|
||||||
}
|
|
||||||
},
|
|
||||||
axisLabel: {
|
|
||||||
fontSize: 14
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
name: '',
|
|
||||||
type: 'line',
|
|
||||||
stack: 'value',
|
|
||||||
areaStyle: {},
|
|
||||||
symbol: 'none',
|
|
||||||
data: []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
const pieWithTable = {
|
|
||||||
tooltip: {
|
|
||||||
appendToBody: true
|
|
||||||
},
|
|
||||||
color: chartColor,
|
|
||||||
animation: false,
|
|
||||||
legend: {
|
|
||||||
orient: 'vertical',
|
|
||||||
type: 'plain',
|
|
||||||
left: '60%',
|
|
||||||
top: 'middle',
|
|
||||||
icon: 'circle',
|
|
||||||
itemWidth: 10, // 设置宽度
|
|
||||||
itemHeight: 10, // 设置高度
|
|
||||||
itemGap: 20,
|
|
||||||
formatter: tooLongFormatter,
|
|
||||||
tooltip: {
|
|
||||||
show: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
type: 'pie',
|
|
||||||
selectedMode: 'single',
|
|
||||||
radius: ['42%', '65%'],
|
|
||||||
center: ['30%', '50%'],
|
|
||||||
data: [],
|
|
||||||
label: {
|
|
||||||
formatter: '{d}%'
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
formatter: function (param, index, callback) {
|
|
||||||
return `${param.name}: ${unitConvert(param.value, param.data.unitType).join(' ')}`
|
|
||||||
}
|
|
||||||
},
|
|
||||||
emphasis: {
|
|
||||||
itemStyle: {
|
|
||||||
shadowBlur: 10,
|
|
||||||
shadowOffsetX: 0,
|
|
||||||
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
const ipHostedDomain = {
|
|
||||||
color: chartColor,
|
|
||||||
animation: false,
|
|
||||||
tooltip: {
|
|
||||||
show: true
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
orient: 'vertical',
|
|
||||||
type: 'plain',
|
|
||||||
right: '8%',
|
|
||||||
top: 'middle',
|
|
||||||
icon: 'circle',
|
|
||||||
itemWidth: 10, // 设置宽度
|
|
||||||
itemHeight: 10, // 设置高度
|
|
||||||
itemGap: 20,
|
|
||||||
tooltip: {
|
|
||||||
show: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
type: 'pie',
|
|
||||||
selectedMode: 'single',
|
|
||||||
radius: ['42%', '65%'],
|
|
||||||
center: ['36%', '50%'],
|
|
||||||
data: [],
|
|
||||||
label: {
|
|
||||||
formatter: '{d}%'
|
|
||||||
},
|
|
||||||
tooltip: {
|
|
||||||
formatter: function (param, index, callback) {
|
|
||||||
return `${param.name}: ${unitConvert(param.value, param.data.unitType).join(' ')}`
|
|
||||||
}
|
|
||||||
},
|
|
||||||
emphasis: {
|
|
||||||
itemStyle: {
|
|
||||||
shadowBlur: 10,
|
|
||||||
shadowOffsetX: 0,
|
|
||||||
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
const singleValueLine = {
|
|
||||||
tooltip: {
|
|
||||||
show: true,
|
|
||||||
enterable: true,
|
|
||||||
showContent: true,
|
|
||||||
appendToBody: true,
|
|
||||||
trigger: 'axis',
|
|
||||||
textStyle: {
|
|
||||||
width: '20px',
|
|
||||||
overflow: 'truncate'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
type: 'time',
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
type: 'value',
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
animation: false,
|
|
||||||
grid: {
|
|
||||||
left: 0,
|
|
||||||
bottom: 2,
|
|
||||||
top: 5,
|
|
||||||
right: 0
|
|
||||||
},
|
|
||||||
color: chartColor,
|
|
||||||
legend: {
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
type: 'line',
|
|
||||||
legendHoverLink: false,
|
|
||||||
itemStyle: {
|
|
||||||
normal: {
|
|
||||||
color: '#81C9FF',
|
|
||||||
lineStyle: {
|
|
||||||
width: 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data: [],
|
|
||||||
showSymbol: false,
|
|
||||||
areaStyle: { color: '#C9EAFF' }
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
export const entityListLineOption = {
|
export const entityListLineOption = {
|
||||||
tooltip: {
|
tooltip: {
|
||||||
appendToBody: true,
|
appendToBody: true,
|
||||||
@@ -336,7 +9,7 @@ export const entityListLineOption = {
|
|||||||
width: '20px',
|
width: '20px',
|
||||||
overflow: 'truncate'
|
overflow: 'truncate'
|
||||||
},
|
},
|
||||||
formatter: axiosFormatter,
|
formatter: axisFormatter,
|
||||||
show: true,
|
show: true,
|
||||||
className: 'nz-chart-tooltip',
|
className: 'nz-chart-tooltip',
|
||||||
extraCssText: 'box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);max-width: 300px !important'
|
extraCssText: 'box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);max-width: 300px !important'
|
||||||
@@ -376,461 +49,3 @@ export const entityListLineOption = {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
const relationShip = {
|
|
||||||
grid: {
|
|
||||||
left: 0,
|
|
||||||
bottom: 50,
|
|
||||||
top: 80,
|
|
||||||
right: 0
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
type: 'graph',
|
|
||||||
layout: 'force',
|
|
||||||
symbolSize: 40,
|
|
||||||
roam: true,
|
|
||||||
force: {
|
|
||||||
repulsion: 350
|
|
||||||
},
|
|
||||||
draggable: true,
|
|
||||||
label: { show: true },
|
|
||||||
edgeSymbol: ['none', 'arrow'],
|
|
||||||
edgeSymbolSize: 7,
|
|
||||||
data: [],
|
|
||||||
links: []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
const sankey = {
|
|
||||||
tooltip: {
|
|
||||||
trigger: 'item',
|
|
||||||
triggerOn: 'mousemove'
|
|
||||||
},
|
|
||||||
series: [
|
|
||||||
{
|
|
||||||
type: 'sankey',
|
|
||||||
data: [],
|
|
||||||
links: [],
|
|
||||||
right: '5%',
|
|
||||||
top: 50,
|
|
||||||
bottom: 100,
|
|
||||||
levels: [
|
|
||||||
{
|
|
||||||
depth: 0,
|
|
||||||
itemStyle: {
|
|
||||||
color: '#47D49C'
|
|
||||||
},
|
|
||||||
lineStyle: {
|
|
||||||
color: '#999'
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
depth: 1,
|
|
||||||
itemStyle: {
|
|
||||||
color: '#A69BF5'
|
|
||||||
},
|
|
||||||
lineStyle: {
|
|
||||||
color: '#999'
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
depth: 2,
|
|
||||||
itemStyle: {
|
|
||||||
color: '#73A0FA'
|
|
||||||
},
|
|
||||||
lineStyle: {
|
|
||||||
color: '#999'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
const ipOpenPortBar = {
|
|
||||||
xAxis: {
|
|
||||||
type: 'category',
|
|
||||||
axisTick: { show: false },
|
|
||||||
axisLine: { show: false }
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
top: 30,
|
|
||||||
left: 60,
|
|
||||||
right: 50,
|
|
||||||
bottom: 50
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
type: 'value',
|
|
||||||
show: false
|
|
||||||
},
|
|
||||||
series: [{
|
|
||||||
barWidth: 38,
|
|
||||||
data: [],
|
|
||||||
type: 'bar',
|
|
||||||
label: { show: true, position: 'top' },
|
|
||||||
barCategoryGap: '10%'
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
const categoryBar = {
|
|
||||||
tooltip: {
|
|
||||||
appendToBody: true,
|
|
||||||
trigger: 'axis',
|
|
||||||
textStyle: {
|
|
||||||
width: '20px',
|
|
||||||
overflow: 'truncate'
|
|
||||||
},
|
|
||||||
formatter: categoryVerticalFormatter,
|
|
||||||
show: true,
|
|
||||||
className: 'nz-chart-tooltip',
|
|
||||||
extraCssText: 'box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);max-width: 300px !important'
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
type: 'category',
|
|
||||||
axisTick: { show: false },
|
|
||||||
axisLine: { show: false }
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
top: 20,
|
|
||||||
left: 10,
|
|
||||||
right: 25,
|
|
||||||
bottom: 20,
|
|
||||||
containLabel: true
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
type: 'value',
|
|
||||||
axisTick: { show: false },
|
|
||||||
axisLine: { show: false }
|
|
||||||
},
|
|
||||||
color: chartColor,
|
|
||||||
series: [{
|
|
||||||
barWidth: 15,
|
|
||||||
data: [],
|
|
||||||
type: 'bar',
|
|
||||||
label: { show: false },
|
|
||||||
barCategoryGap: '10%',
|
|
||||||
itemStyle: {
|
|
||||||
color: function (params) {
|
|
||||||
return getCharBartColor([params.dataIndex])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
|
|
||||||
const timeBar = {
|
|
||||||
tooltip: {
|
|
||||||
appendToBody: true,
|
|
||||||
trigger: 'axis',
|
|
||||||
textStyle: {
|
|
||||||
width: '20px',
|
|
||||||
overflow: 'truncate'
|
|
||||||
},
|
|
||||||
formatter: timeVerticalFormatter,
|
|
||||||
show: true,
|
|
||||||
className: 'nz-chart-tooltip',
|
|
||||||
extraCssText: 'box-shadow: 0 0 3px rgba(0, 0, 0, 0.3);max-width: 300px !important'
|
|
||||||
},
|
|
||||||
xAxis: {
|
|
||||||
type: 'time',
|
|
||||||
axisTick: { show: false },
|
|
||||||
axisLine: { show: false },
|
|
||||||
axisLabel: {
|
|
||||||
interval: 0,
|
|
||||||
// rotate: -40, //设置日期显示样式(倾斜度)
|
|
||||||
formatter: function (value) { // 在这里写你需要的时间格式
|
|
||||||
const t_date = new Date(value)
|
|
||||||
return [t_date.getMonth() + 1, t_date.getDate()].join('/') + ' ' + [t_date.getHours(), t_date.getMinutes()].join(':')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
top: 20,
|
|
||||||
left: 25,
|
|
||||||
right: 25,
|
|
||||||
bottom: 20,
|
|
||||||
containLabel: true
|
|
||||||
},
|
|
||||||
yAxis: {
|
|
||||||
type: 'value',
|
|
||||||
axisTick: { show: false },
|
|
||||||
axisLine: { show: false },
|
|
||||||
axisLabel: {
|
|
||||||
formatter: function (value, index, a, b) {
|
|
||||||
return unitConvert(value, unitTypes.number).join(' ')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
minInterval: 1
|
|
||||||
},
|
|
||||||
color: chartColor,
|
|
||||||
series: [{
|
|
||||||
barWidth: 15,
|
|
||||||
data: [],
|
|
||||||
type: 'bar',
|
|
||||||
label: { show: false },
|
|
||||||
barCategoryGap: '10%',
|
|
||||||
itemStyle: {
|
|
||||||
color: function (params) {
|
|
||||||
return getCharBartColor([params.dataIndex])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
const typeOptionMappings = [
|
|
||||||
{ value: 11, option: line }, // 常规折线图
|
|
||||||
{ value: 12, option: lineWithStatistics }, // 带统计表格的折线图
|
|
||||||
{ value: 13, option: lineStack }, // 折线堆叠图
|
|
||||||
{ value: 22, option: ipOpenPortBar }, // ip详情--开放端口的柱状图
|
|
||||||
{ value: 23, option: timeBar }, // 矿机所属单位
|
|
||||||
{ value: 24, option: categoryBar }, // 挖矿事件统计
|
|
||||||
{ value: 31, option: pieWithTable }, // 常规折线图
|
|
||||||
{ value: 33, option: ipHostedDomain }, // ip详情--托管域名
|
|
||||||
{ value: 34, option: ipHostedDomain }, // app详情--相关域名
|
|
||||||
{ value: 42, option: relationShip }, // 关系图
|
|
||||||
{ value: 43, option: sankey }, // 桑基图
|
|
||||||
{ value: 52, option: singleValueLine }
|
|
||||||
]
|
|
||||||
const typeCategory = {
|
|
||||||
MAP: 'map',
|
|
||||||
TABLE: 'table',
|
|
||||||
ECHARTS: 'echarts',
|
|
||||||
TITLE: 'title',
|
|
||||||
SINGLE: 'singleValue',
|
|
||||||
TABS: 'tabs'
|
|
||||||
}
|
|
||||||
export function getTypeCategory (type) {
|
|
||||||
if (isMap(type)) {
|
|
||||||
return typeCategory.MAP
|
|
||||||
} else if (isEcharts(type)) {
|
|
||||||
return typeCategory.ECHARTS
|
|
||||||
} else if (isTable(type)) {
|
|
||||||
return typeCategory.TABLE
|
|
||||||
} else if (isSingleValue(type)) {
|
|
||||||
return typeCategory.SINGLE
|
|
||||||
} else if (isTitle(type)) {
|
|
||||||
return typeCategory.TITLE
|
|
||||||
} else if (isTabs(type)) {
|
|
||||||
return typeCategory.TABS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* 柱状图:挖矿事件统计(time类型柱状图) */
|
|
||||||
export function isEchartsTimeBar (type) {
|
|
||||||
return type == 23
|
|
||||||
}
|
|
||||||
/* 柱状图:矿机所属单位(category类型柱状图) */
|
|
||||||
export function isEchartsCategoryBar (type) {
|
|
||||||
return type == 24
|
|
||||||
}
|
|
||||||
/* 饼图柱状图等 */
|
|
||||||
export function isEcharts (type) {
|
|
||||||
return type >= 11 && type <= 50
|
|
||||||
}
|
|
||||||
/* 折线,饼图 */
|
|
||||||
export function isEchartsLineBar (type) {
|
|
||||||
return type == 11 || type == 12 || type == 31 || type == 32 || type == 33 || type == 34
|
|
||||||
}
|
|
||||||
/* 地图 */
|
|
||||||
export function isMap (type) {
|
|
||||||
return type >= 1 && type <= 10
|
|
||||||
}
|
|
||||||
/* 连线地图 */
|
|
||||||
export function isMapLine (type) {
|
|
||||||
return type === 1
|
|
||||||
}
|
|
||||||
/* 色块地图 */
|
|
||||||
export function isMapBlock (type) {
|
|
||||||
return type === 2
|
|
||||||
}
|
|
||||||
/* 带统计的折线图 */
|
|
||||||
export function isEchartsWithStatistics (type) {
|
|
||||||
return type === 12
|
|
||||||
}
|
|
||||||
/* 关系图 */
|
|
||||||
export function isRelationShip (type) {
|
|
||||||
return type === 42
|
|
||||||
}
|
|
||||||
/* 桑基图 */
|
|
||||||
export function isSankey (type) {
|
|
||||||
return type === 43
|
|
||||||
}
|
|
||||||
/* 单值 */
|
|
||||||
export function isSingleValue (type) {
|
|
||||||
return type >= 51 && type <= 60
|
|
||||||
}
|
|
||||||
/* 带折线图的单值 */
|
|
||||||
export function isSingleValueWithEcharts (type) {
|
|
||||||
return type === 52
|
|
||||||
}
|
|
||||||
/* 带折线图的单值 */
|
|
||||||
export function isSingleValueWithEchartsTemp (type) {
|
|
||||||
return type === 55
|
|
||||||
}
|
|
||||||
/* 带Table的饼图 */
|
|
||||||
export function isEchartsWithTable (type) {
|
|
||||||
return type === 31
|
|
||||||
}
|
|
||||||
/* 普通饼图 */
|
|
||||||
export function isEchartsPie (type) {
|
|
||||||
return type === 32
|
|
||||||
}
|
|
||||||
/* table */
|
|
||||||
export function isTable (type) {
|
|
||||||
return type >= 61 && type <= 70
|
|
||||||
}
|
|
||||||
/* table */
|
|
||||||
export function isActiveIpTable (type) {
|
|
||||||
return type == 63
|
|
||||||
}
|
|
||||||
/* title */
|
|
||||||
export function isTitle (type) {
|
|
||||||
return type === 93
|
|
||||||
}
|
|
||||||
/* tabs */
|
|
||||||
export function isTabs (type) {
|
|
||||||
return type === 91
|
|
||||||
}
|
|
||||||
/* IP实体基本信息 */
|
|
||||||
export function isIpBasicInfo (type) {
|
|
||||||
return type === 4
|
|
||||||
}
|
|
||||||
/* IP实体开放端口 */
|
|
||||||
export function isIpOpenPort (type) {
|
|
||||||
return type === 22
|
|
||||||
}
|
|
||||||
/* IP实体托管域名 */
|
|
||||||
export function isIpHostedDomain (type) {
|
|
||||||
return type === 33
|
|
||||||
}
|
|
||||||
/* APP实体相关域名 */
|
|
||||||
export function isAppRelatedDomain (type) {
|
|
||||||
return type === 34
|
|
||||||
}
|
|
||||||
/* APP实体基本信息 */
|
|
||||||
export function isAppBasicInfo (type) {
|
|
||||||
return type === 82
|
|
||||||
}
|
|
||||||
/* DOMAIN实体Whois */
|
|
||||||
export function isDomainWhois (type) {
|
|
||||||
return type === 83
|
|
||||||
}
|
|
||||||
/* DOMAIN实体DNS记录 */
|
|
||||||
export function isDomainDnsRecord (type) {
|
|
||||||
return type === 84
|
|
||||||
}
|
|
||||||
/* 近期挖矿事件 */
|
|
||||||
export function isCryptocurrencyEventList (type) {
|
|
||||||
return type === 85
|
|
||||||
}
|
|
||||||
/* 组 */
|
|
||||||
export function isGroup (type) {
|
|
||||||
return type === 94
|
|
||||||
}
|
|
||||||
/* 实体详情块 */
|
|
||||||
export function isBlock (type) {
|
|
||||||
return type === 95
|
|
||||||
}
|
|
||||||
export function getOption (type) {
|
|
||||||
const mapping = typeOptionMappings.find(m => m.value === type)
|
|
||||||
return mapping && mapping.option ? _.cloneDeep(mapping.option) : null
|
|
||||||
}
|
|
||||||
export const layoutConstant = {
|
|
||||||
HEADER: 'header',
|
|
||||||
FOOTER: 'footer'
|
|
||||||
}
|
|
||||||
export function getLayout (type) {
|
|
||||||
const layout = []
|
|
||||||
if (!isSingleValue(type) && !isTitle(type)) {
|
|
||||||
layout.push(layoutConstant.HEADER)
|
|
||||||
}
|
|
||||||
if (type === 12 || type === 31) {
|
|
||||||
layout.push(layoutConstant.FOOTER)
|
|
||||||
}
|
|
||||||
return layout
|
|
||||||
}
|
|
||||||
|
|
||||||
function tooLongFormatter (name) {
|
|
||||||
return format.truncateText(name, 110, '12')
|
|
||||||
}
|
|
||||||
function axiosFormatter (params) {
|
|
||||||
let str = '<div>'
|
|
||||||
params.forEach((item, i) => {
|
|
||||||
const tData = item.data[0]
|
|
||||||
if (i === 0) {
|
|
||||||
str += '<div style="margin-bottom: 5px">'
|
|
||||||
str += window.$dayJs.tz(tData).format('YYYY-MM-DD HH:mm:ss')
|
|
||||||
str += '</div>'
|
|
||||||
}
|
|
||||||
str += '<div class="cn-chart-tooltip-box">'
|
|
||||||
str += item.marker
|
|
||||||
str += `<span class="cn-chart-tooltip-content">
|
|
||||||
${item.seriesName}
|
|
||||||
</span>`
|
|
||||||
str += `<span class="cn-chart-tooltip-value">
|
|
||||||
${unitConvert(item.data[1], item.data[2]).join(' ')}
|
|
||||||
</span>`
|
|
||||||
str += '</div>'
|
|
||||||
})
|
|
||||||
str += '</div>'
|
|
||||||
return str
|
|
||||||
}
|
|
||||||
|
|
||||||
export function timeVerticalFormatter (params) {
|
|
||||||
let str = '<div>'
|
|
||||||
params.forEach((item, i) => {
|
|
||||||
const tData = item.data[0]
|
|
||||||
if (i === 0) {
|
|
||||||
str += '<div style="margin-bottom: 5px">'
|
|
||||||
str += window.$dayJs.tz(tData).format('YYYY-MM-DD HH:mm:ss')
|
|
||||||
str += '</div>'
|
|
||||||
}
|
|
||||||
str += '<div class="cn-chart-tooltip-box">'
|
|
||||||
str += item.marker
|
|
||||||
str += `<span class="cn-chart-tooltip-content">
|
|
||||||
${item.seriesName}
|
|
||||||
</span>`
|
|
||||||
str += `<span class="cn-chart-tooltip-value">
|
|
||||||
${unitConvert(item.data[1], item.data[2]).join(' ')}
|
|
||||||
</span>`
|
|
||||||
str += '</div>'
|
|
||||||
})
|
|
||||||
str += '</div>'
|
|
||||||
return str
|
|
||||||
}
|
|
||||||
|
|
||||||
export function timeHorizontalFormatter (params) {
|
|
||||||
let str = '<div>'
|
|
||||||
params.forEach((item, i) => {
|
|
||||||
const tData = item.data[1]
|
|
||||||
if (i === 0) {
|
|
||||||
str += '<div style="margin-bottom: 5px">'
|
|
||||||
str += window.$dayJs.tz(tData).format('YYYY-MM-DD HH:mm:ss')
|
|
||||||
str += '</div>'
|
|
||||||
}
|
|
||||||
str += '<div class="cn-chart-tooltip-box">'
|
|
||||||
str += item.marker
|
|
||||||
str += `<span class="cn-chart-tooltip-content">
|
|
||||||
${item.seriesName}
|
|
||||||
</span>`
|
|
||||||
str += `<span class="cn-chart-tooltip-value">
|
|
||||||
${unitConvert(item.data[0], item.data[2]).join(' ')}
|
|
||||||
</span>`
|
|
||||||
str += '</div>'
|
|
||||||
})
|
|
||||||
str += '</div>'
|
|
||||||
return str
|
|
||||||
}
|
|
||||||
export function categoryHorizontalFormatter (params) {
|
|
||||||
let str = '<div>'
|
|
||||||
params.forEach((item, i) => {
|
|
||||||
str += '<div class="cn-chart-tooltip-box">'
|
|
||||||
str += item.data[1] + ': ' + item.data[0]
|
|
||||||
str += '</div>'
|
|
||||||
})
|
|
||||||
str += '</div>'
|
|
||||||
return str
|
|
||||||
}
|
|
||||||
export function categoryVerticalFormatter (params) {
|
|
||||||
let str = '<div>'
|
|
||||||
params.forEach((item, i) => {
|
|
||||||
str += '<div class="cn-chart-tooltip-box">'
|
|
||||||
str += item.data[0] + ': ' + item.data[1]
|
|
||||||
str += '</div>'
|
|
||||||
})
|
|
||||||
str += '</div>'
|
|
||||||
return str
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import unitConvert from '@/utils/unit-convert'
|
import unitConvert from '@/utils/unit-convert'
|
||||||
import { unitTypes } from '@/utils/constants'
|
import { unitTypes, chartColor } from '@/utils/constants'
|
||||||
import { chartColor } from '@/views/charts/charts/chart-options'
|
import { axisFormatter, tooLongFormatter } from '@/views/charts/charts/tools'
|
||||||
import { axisFormatter, tooLongFormatter } from '../tools'
|
|
||||||
|
|
||||||
export const line = {
|
export const line = {
|
||||||
tooltip: {
|
tooltip: {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import unitConvert from '@/utils/unit-convert'
|
import unitConvert from '@/utils/unit-convert'
|
||||||
import { chartColor } from '@/views/charts/charts/chart-options'
|
|
||||||
import { tooLongFormatter } from '../tools'
|
import { tooLongFormatter } from '../tools'
|
||||||
|
import { chartColor } from '@/utils/constants'
|
||||||
|
|
||||||
export const pieWithTable = {
|
export const pieWithTable = {
|
||||||
tooltip: {
|
tooltip: {
|
||||||
|
|||||||
@@ -6,11 +6,8 @@ import { ipOpenPortBar, timeBar, categoryBar } from './options/bar'
|
|||||||
import { pieWithTable, ipHostedDomain } from './options/pie'
|
import { pieWithTable, ipHostedDomain } from './options/pie'
|
||||||
import { relationShip } from './options/graph'
|
import { relationShip } from './options/graph'
|
||||||
import { sankey } from './options/sankey'
|
import { sankey } from './options/sankey'
|
||||||
|
import { chartColor } from '@/utils/constants'
|
||||||
|
|
||||||
export const chartColor = ['#5370C6', '#90CC74', '#FAC858', '#EE6666',
|
|
||||||
'#73BFDE', '#3BA172', '#FC8452', '#9960B4',
|
|
||||||
'#E97CCC', '#FEA69E', '#0F8AB2', '#57CBAC',
|
|
||||||
'#5888BC', '#63B6AC', '#EDC6B2', '#D5746B']
|
|
||||||
export const chartBarColor = ['#0F8AB2', '#57CBAC']
|
export const chartBarColor = ['#0F8AB2', '#57CBAC']
|
||||||
export function getChartColor (index) {
|
export function getChartColor (index) {
|
||||||
return chartColor[index % chartColor.length]
|
return chartColor[index % chartColor.length]
|
||||||
@@ -66,6 +63,10 @@ export function isMapLine (type) {
|
|||||||
export function isMapBlock (type) {
|
export function isMapBlock (type) {
|
||||||
return type === 2
|
return type === 2
|
||||||
}
|
}
|
||||||
|
/* 散点地图 */
|
||||||
|
export function isMapPoint (type) {
|
||||||
|
return type === 3
|
||||||
|
}
|
||||||
/* 普通折线图 */
|
/* 普通折线图 */
|
||||||
export function isEchartsLine (type) {
|
export function isEchartsLine (type) {
|
||||||
return type === 11
|
return type === 11
|
||||||
@@ -106,8 +107,8 @@ export function isEchartsWithTable (type) {
|
|||||||
export function isTable (type) {
|
export function isTable (type) {
|
||||||
return type >= 61 && type <= 70
|
return type >= 61 && type <= 70
|
||||||
}
|
}
|
||||||
/* current table */
|
/* basic table */
|
||||||
export function isCurrentTable (type) {
|
export function isBasicTable (type) {
|
||||||
return type === 61
|
return type === 61
|
||||||
}
|
}
|
||||||
/* table */
|
/* table */
|
||||||
@@ -158,11 +159,11 @@ export function isAlarmInfo (type) {
|
|||||||
export function isCryptocurrencyEventList (type) {
|
export function isCryptocurrencyEventList (type) {
|
||||||
return type === 85
|
return type === 85
|
||||||
}
|
}
|
||||||
/* 单支持情况统计 */
|
/* 单支持情况统计 */
|
||||||
export function isSingleSupportStatistics (type) {
|
export function isSingleSupportStatistics (type) {
|
||||||
return type === 86
|
return type === 86
|
||||||
}
|
}
|
||||||
/* 两个支持情况统计 */
|
/* 两个支持情况统计 */
|
||||||
export function isTwoSupportStatistics (type) {
|
export function isTwoSupportStatistics (type) {
|
||||||
return type === 87
|
return type === 87
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,9 +14,16 @@
|
|||||||
></detection-search>
|
></detection-search>
|
||||||
<!-- 内容区 -->
|
<!-- 内容区 -->
|
||||||
<div class="explorer-container" style="height: calc(100% - 20px); flex-direction: column">
|
<div class="explorer-container" style="height: calc(100% - 20px); flex-direction: column">
|
||||||
<div class="detection__event-severity-bar" :id="`eventSeverityTrendBar${pageType}`">
|
<div class="entity__loading" style="background: #eff2f5;opacity: .6;" v-show="loading">
|
||||||
<detection-no-data v-if="isEventSeverityNoData"></detection-no-data>
|
<i class="el-icon-loading"></i>
|
||||||
</div>
|
</div>
|
||||||
|
<template v-if="isEventSeverityNoData">
|
||||||
|
<div class="no-data detection__event-severity-bar" >No data</div>
|
||||||
|
</template>
|
||||||
|
<template v-if="!isEventSeverityNoData">
|
||||||
|
<div class="detection__event-severity-bar" :id="`eventSeverityTrendBar${pageType}`">
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
<div style="display: flex; flex-grow: 1">
|
<div style="display: flex; flex-grow: 1">
|
||||||
<detection-filter
|
<detection-filter
|
||||||
:filter-data="filterData[pageType]"
|
:filter-data="filterData[pageType]"
|
||||||
@@ -31,25 +38,38 @@
|
|||||||
<div class="chart-header">
|
<div class="chart-header">
|
||||||
<div class="chart-header__title">{{$t('detection.severity')}}</div>
|
<div class="chart-header__title">{{$t('detection.severity')}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="chart-content" :id="`eventSeverityPie${pageType}`">
|
<template v-if="isStatisticsSeverityNoData">
|
||||||
<detection-no-data v-if="isStatisticsSeverityNoData"></detection-no-data>
|
<div class="no-data chart-content" >No data</div>
|
||||||
</div>
|
</template>
|
||||||
|
<template v-if="!isStatisticsSeverityNoData">
|
||||||
|
<div class="chart-content" :id="`eventSeverityPie${pageType}`">
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="statistics__category">
|
<div class="statistics__category">
|
||||||
<div class="chart-header">
|
<div class="chart-header">
|
||||||
<div class="chart-header__title">{{$t('detection.categoryProportion')}}</div>
|
<div class="chart-header__title">{{$t('detection.categoryProportion')}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="chart-content" :id="`detectionCategoryPer${pageType}`">
|
<template v-if="isStatisticsCategoryNoData">
|
||||||
<detection-no-data v-if="isStatisticsCategoryNoData"></detection-no-data>
|
<div class="no-data chart-content" >No data</div>
|
||||||
</div>
|
</template>
|
||||||
|
<template v-if="!isStatisticsCategoryNoData">
|
||||||
|
<div class="chart-content" :id="`detectionCategoryPer${pageType}`">
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<div class="statistics__active-attack">
|
<div class="statistics__active-attack">
|
||||||
<div class="chart-header">
|
<div class="chart-header">
|
||||||
<div class="chart-header__title">{{pageType === detectionPageType.securityEvent ? $t('detection.activeAttacker') : $t('detections.activeEntity')}}</div>
|
<div class="chart-header__title">{{pageType === detectionPageType.securityEvent ? $t('detection.activeAttacker') : $t('detections.activeEntity')}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="chart-content" style="" :id="`detectionActiveAttacker${pageType}`">
|
<template v-if="isStatisticsActiveAttackNoData">
|
||||||
<detection-no-data v-if="isStatisticsActiveAttackNoData"></detection-no-data>
|
<div class="no-data chart-content" >No data</div>
|
||||||
</div>
|
</template>
|
||||||
|
<template v-if="!isStatisticsActiveAttackNoData">
|
||||||
|
<div class="chart-content" :id="`detectionActiveAttacker${pageType}`">
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<detection-list
|
<detection-list
|
||||||
@@ -87,7 +107,7 @@ import DetectionFilter from '@/views/detections/DetectionFilter'
|
|||||||
import DetectionList from '@/views/detections/DetectionList'
|
import DetectionList from '@/views/detections/DetectionList'
|
||||||
import Pagination from '@/components/common/Pagination'
|
import Pagination from '@/components/common/Pagination'
|
||||||
import { defaultPageSize, detectionPageType } from '@/utils/constants'
|
import { defaultPageSize, detectionPageType } from '@/utils/constants'
|
||||||
import { getNowTime, getSecond } from '@/utils/date-util'
|
import { getNowTime, getSecond, rTime } from '@/utils/date-util'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import * as echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import { multipleBarOption, pieForSeverity, activeAttackBar, getAttackColor, getSeverityColor, getSeriesIndex } from '@/views/detections/options/detectionOptions'
|
import { multipleBarOption, pieForSeverity, activeAttackBar, getAttackColor, getSeverityColor, getSeriesIndex } from '@/views/detections/options/detectionOptions'
|
||||||
@@ -183,8 +203,8 @@ export default {
|
|||||||
data: [] // 从接口动态获取,本项在获得数据后需要特殊处理左边框颜色
|
data: [] // 从接口动态获取,本项在获得数据后需要特殊处理左边框颜色
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: this.$t('detections.securityType'),
|
title: this.$t('detections.eventType'),
|
||||||
column: 'securityType',
|
column: 'eventType',
|
||||||
collapse: false,
|
collapse: false,
|
||||||
value: [],
|
value: [],
|
||||||
data: [] // 从接口动态获取
|
data: [] // 从接口动态获取
|
||||||
@@ -193,24 +213,122 @@ export default {
|
|||||||
},
|
},
|
||||||
listData: [],
|
listData: [],
|
||||||
listLoading: false,
|
listLoading: false,
|
||||||
eventSeverityData: [],
|
|
||||||
severityPerOption: null,
|
severityPerOption: null,
|
||||||
severityPerData: [],
|
severityPerData: [],
|
||||||
categoryPerOption: null,
|
categoryPerOption: null,
|
||||||
categoryPerData: [],
|
categoryPerData: [],
|
||||||
activeAttackOption: null,
|
activeAttackOption: null,
|
||||||
activeAttackData: [],
|
activeAttackData: [],
|
||||||
isEventSeverityNoData: true,
|
eventSeverityData: [],
|
||||||
isStatisticsSeverityNoData: true,
|
statisticsSeverityData: [],
|
||||||
isStatisticsCategoryNoData: true,
|
statisticsCategoryData: [],
|
||||||
isStatisticsActiveAttackNoData: true
|
statisticsActiveAttackData: [],
|
||||||
|
isEventSeverityNoData: false,
|
||||||
|
isStatisticsSeverityNoData: false,
|
||||||
|
isStatisticsCategoryNoData: false,
|
||||||
|
isStatisticsActiveAttackNoData: false,
|
||||||
|
loading: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// 初始化顶部大柱状图
|
// 初始化顶部大柱状图
|
||||||
initEventSeverityTrendData (params) {
|
initEventSeverityTrendData (params) {
|
||||||
|
this.loading = true
|
||||||
getData(api.detection[this.pageType].eventSeverityTrend, params).then(data => {
|
getData(api.detection[this.pageType].eventSeverityTrend, params).then(data => {
|
||||||
/* data = [
|
/* data = [
|
||||||
|
{
|
||||||
|
"stat_time": "2022-01-01T10:07:03.008Z",
|
||||||
|
"event_severity": "critical",
|
||||||
|
"count": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"stat_time": "2022-01-02T10:07:03.008Z",
|
||||||
|
"event_severity": "critical",
|
||||||
|
"count": 15
|
||||||
|
},{
|
||||||
|
"stat_time": "2022-01-03T10:07:03.008Z",
|
||||||
|
"event_severity": "critical",
|
||||||
|
"count": 25
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"stat_time": "2022-01-04T10:07:03.008Z",
|
||||||
|
"event_severity": "critical",
|
||||||
|
"count": 7
|
||||||
|
},{
|
||||||
|
"stat_time": "2022-01-01T10:07:03.008Z",
|
||||||
|
"event_severity": "high",
|
||||||
|
"count": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"stat_time": "2022-01-02T10:07:03.008Z",
|
||||||
|
"event_severity": "high",
|
||||||
|
"count": 2
|
||||||
|
},{
|
||||||
|
"stat_time": "2022-01-03T10:07:03.008Z",
|
||||||
|
"event_severity": "high",
|
||||||
|
"count": 25
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"stat_time": "2022-01-04T10:07:03.008Z",
|
||||||
|
"event_severity": "high",
|
||||||
|
"count": 7
|
||||||
|
},{
|
||||||
|
"stat_time": "2022-01-01T10:07:03.008Z",
|
||||||
|
"event_severity": "medium",
|
||||||
|
"count": 9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"stat_time": "2022-01-02T10:07:03.008Z",
|
||||||
|
"event_severity": "medium",
|
||||||
|
"count": 15
|
||||||
|
},{
|
||||||
|
"stat_time": "2022-01-03T10:07:03.008Z",
|
||||||
|
"event_severity": "medium",
|
||||||
|
"count": 35
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"stat_time": "2022-01-04T10:07:03.008Z",
|
||||||
|
"event_severity": "medium",
|
||||||
|
"count": 7
|
||||||
|
},{
|
||||||
|
"stat_time": "2022-01-01T10:07:03.008Z",
|
||||||
|
"event_severity": "low",
|
||||||
|
"count": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"stat_time": "2022-01-02T10:07:03.008Z",
|
||||||
|
"event_severity": "low",
|
||||||
|
"count": 1
|
||||||
|
},{
|
||||||
|
"stat_time": "2022-01-03T10:07:03.008Z",
|
||||||
|
"event_severity": "low",
|
||||||
|
"count": 25
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"stat_time": "2022-01-04T10:07:03.008Z",
|
||||||
|
"event_severity": "low",
|
||||||
|
"count": 17
|
||||||
|
},{
|
||||||
|
"stat_time": "2022-01-01T10:07:03.008Z",
|
||||||
|
"event_severity": "info",
|
||||||
|
"count": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"stat_time": "2022-01-02T10:07:03.008Z",
|
||||||
|
"event_severity": "info",
|
||||||
|
"count": 15
|
||||||
|
},{
|
||||||
|
"stat_time": "2022-01-03T10:07:03.008Z",
|
||||||
|
"event_severity": "info",
|
||||||
|
"count": 25
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"stat_time": "2022-01-04T10:07:03.008Z",
|
||||||
|
"event_severity": "info",
|
||||||
|
"count": 27
|
||||||
|
},
|
||||||
|
] */
|
||||||
|
/* data2 = [
|
||||||
{
|
{
|
||||||
legend: 'critical',
|
legend: 'critical',
|
||||||
values: [[1435781430781, '999'], [1435781431781, '222'], [1435781432781, '11'], [1435781433781, '3']]
|
values: [[1435781430781, '999'], [1435781431781, '222'], [1435781432781, '11'], [1435781433781, '3']]
|
||||||
@@ -229,23 +347,40 @@ export default {
|
|||||||
values: [[1435781430781, '5'], [1435781431781, '7'], [1435781432781, '5'], [1435781433781, '8']]
|
values: [[1435781430781, '5'], [1435781431781, '7'], [1435781432781, '5'], [1435781433781, '8']]
|
||||||
}
|
}
|
||||||
] */
|
] */
|
||||||
|
this.eventSeverityData = data
|
||||||
if (!this.$_.isEmpty(data)) {
|
if (!this.$_.isEmpty(data)) {
|
||||||
const chartDom = document.getElementById(`eventSeverityTrendBar${this.pageType}`)
|
const dataMap = new Map()
|
||||||
const detectionChart = echarts.init(chartDom)
|
|
||||||
const eventSeverityTrendOption = this.$_.cloneDeep(multipleBarOption)
|
|
||||||
data.forEach(item => {
|
data.forEach(item => {
|
||||||
eventSeverityTrendOption.series[Number(getSeriesIndex(item.legend))].data = item.values.map(v => Number(v[1]))
|
if (item.eventSeverity) {
|
||||||
|
if (!dataMap.has(item.eventSeverity)) {
|
||||||
|
const count = [[item.statTime, item.count]]
|
||||||
|
dataMap.set(item.eventSeverity, count)
|
||||||
|
} else {
|
||||||
|
dataMap.get(item.eventSeverity).push([item.statTime, item.count])
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
eventSeverityTrendOption.xAxis.data = data[0].values.map(v => [window.$dayJs.tz(Number(v[0])).format('YYYY-MM-DD HH:mm:ss')])
|
const chartDom = document.getElementById(`eventSeverityTrendBar${this.pageType}`)
|
||||||
this.$nextTick(() => {
|
const eventSeverityTrendOption = this.$_.cloneDeep(multipleBarOption)
|
||||||
detectionChart.setOption(eventSeverityTrendOption)
|
dataMap.forEach(function (value, key) {
|
||||||
|
eventSeverityTrendOption.series[Number(getSeriesIndex(key))].data = value.map(v => Number(v[1]))
|
||||||
})
|
})
|
||||||
this.isEventSeverityNoData = false
|
eventSeverityTrendOption.xAxis.data = dataMap.get('critical').map(v => rTime(v[0]))
|
||||||
|
const detectionChart = echarts.init(chartDom)
|
||||||
|
detectionChart.setOption(eventSeverityTrendOption)
|
||||||
|
// this.isEventSeverityNoData = false
|
||||||
|
} else {
|
||||||
|
// this.isEventSeverityNoData = true
|
||||||
}
|
}
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
|
|
||||||
|
}).finally(() => {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
// 初始化左侧事件严重等级和小饼图
|
// 初始化左侧事件严重等级和小饼图
|
||||||
initEventSeverityData (params) {
|
initEventSeverityData (params) {
|
||||||
getData(api.detection[this.pageType].eventSeverity, params).then(data => {
|
getData(api.detection[this.pageType].eventSeverity, params).then(data => {
|
||||||
@@ -267,6 +402,8 @@ export default {
|
|||||||
count: 300
|
count: 300
|
||||||
}
|
}
|
||||||
] */
|
] */
|
||||||
|
this.statisticsSeverityData = data
|
||||||
|
// this.isStatisticsSeverityNoData = true
|
||||||
if (!this.$_.isEmpty(data)) {
|
if (!this.$_.isEmpty(data)) {
|
||||||
this.filterData[this.pageType][0].data = data.map(r => ({ label: r.eventSeverity, value: r.eventSeverity, count: r.count }))
|
this.filterData[this.pageType][0].data = data.map(r => ({ label: r.eventSeverity, value: r.eventSeverity, count: r.count }))
|
||||||
const eventSeverityOption = this.$_.cloneDeep(pieForSeverity)
|
const eventSeverityOption = this.$_.cloneDeep(pieForSeverity)
|
||||||
@@ -276,7 +413,28 @@ export default {
|
|||||||
const chartDom = document.getElementById(`eventSeverityPie${this.pageType}`)
|
const chartDom = document.getElementById(`eventSeverityPie${this.pageType}`)
|
||||||
const detectionChart = echarts.init(chartDom)
|
const detectionChart = echarts.init(chartDom)
|
||||||
detectionChart.setOption(eventSeverityOption)
|
detectionChart.setOption(eventSeverityOption)
|
||||||
this.isStatisticsSeverityNoData = false
|
// this.isStatisticsSeverityNoData = false
|
||||||
|
}
|
||||||
|
}).catch(error => {
|
||||||
|
|
||||||
|
})
|
||||||
|
},
|
||||||
|
initEventTypeData (params) {
|
||||||
|
getData(api.detection[this.pageType].eventType, params).then(data => {
|
||||||
|
this.statisticsCategoryData = data
|
||||||
|
if (!this.$_.isEmpty(data)) {
|
||||||
|
this.filterData[this.pageType][1].data = data.map(r => ({
|
||||||
|
label: r.eventType,
|
||||||
|
value: r.eventType,
|
||||||
|
count: r.count
|
||||||
|
}))
|
||||||
|
const chartDom = document.getElementById(`detectionCategoryPer${this.pageType}`)
|
||||||
|
const detectionChart = echarts.init(chartDom)
|
||||||
|
const securityTypeOption = this.$_.cloneDeep(pieForSeverity)
|
||||||
|
securityTypeOption.series[0].data = data.map(d => {
|
||||||
|
return { value: d.count, name: d.eventType }
|
||||||
|
})
|
||||||
|
detectionChart.setOption(securityTypeOption)
|
||||||
}
|
}
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
|
|
||||||
@@ -284,41 +442,20 @@ export default {
|
|||||||
},
|
},
|
||||||
initSecurityTypeData (params) {
|
initSecurityTypeData (params) {
|
||||||
getData(api.detection[this.pageType].securityType, params).then(data => {
|
getData(api.detection[this.pageType].securityType, params).then(data => {
|
||||||
/* data = [
|
this.statisticsCategoryData = data
|
||||||
{
|
|
||||||
attackType: 'command and control',
|
|
||||||
count: 1048
|
|
||||||
}, {
|
|
||||||
attackType: 'payload delivery',
|
|
||||||
count: 735
|
|
||||||
}, {
|
|
||||||
attackType: 'cryptomining',
|
|
||||||
count: 580
|
|
||||||
}, {
|
|
||||||
attackType: 'phishing',
|
|
||||||
count: 484
|
|
||||||
}, {
|
|
||||||
attackType: 'dga',
|
|
||||||
count: 300
|
|
||||||
}, {
|
|
||||||
attackType: 'ddos',
|
|
||||||
count: 50
|
|
||||||
}
|
|
||||||
] */
|
|
||||||
if (!this.$_.isEmpty(data)) {
|
if (!this.$_.isEmpty(data)) {
|
||||||
this.filterData[this.pageType][1].data = data.map(r => ({
|
this.filterData[this.pageType][1].data = data.map(r => ({
|
||||||
label: r.attackType,
|
label: r.securityType,
|
||||||
value: r.attackType,
|
value: r.securityType,
|
||||||
count: r.count
|
count: r.count
|
||||||
}))
|
}))
|
||||||
const chartDom = document.getElementById(`detectionCategoryPer${this.pageType}`)
|
const chartDom = document.getElementById(`detectionCategoryPer${this.pageType}`)
|
||||||
const detectionChart = echarts.init(chartDom)
|
const detectionChart = echarts.init(chartDom)
|
||||||
const securityTypeOption = this.$_.cloneDeep(pieForSeverity)
|
const securityTypeOption = this.$_.cloneDeep(pieForSeverity)
|
||||||
securityTypeOption.series[0].data = data.map(d => {
|
securityTypeOption.series[0].data = data.map(d => {
|
||||||
return { value: d.count, name: d.attackType, itemStyle: { color: getAttackColor(d.attackType) } }
|
return { value: d.count, name: d.securityType, itemStyle: { color: getAttackColor(d.securityType) } }
|
||||||
})
|
})
|
||||||
detectionChart.setOption(securityTypeOption)
|
detectionChart.setOption(securityTypeOption)
|
||||||
this.isStatisticsCategoryNoData = false
|
|
||||||
}
|
}
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
|
|
||||||
@@ -376,6 +513,8 @@ export default {
|
|||||||
count: 55355
|
count: 55355
|
||||||
}
|
}
|
||||||
] */
|
] */
|
||||||
|
|
||||||
|
this.statisticsActiveAttackData = data
|
||||||
if (!this.$_.isEmpty(data)) {
|
if (!this.$_.isEmpty(data)) {
|
||||||
this.filterData[this.pageType][4].data = data.map(r => ({
|
this.filterData[this.pageType][4].data = data.map(r => ({
|
||||||
label: r.offenderIp,
|
label: r.offenderIp,
|
||||||
@@ -395,7 +534,7 @@ export default {
|
|||||||
return [d.count, d.offenderIp]
|
return [d.count, d.offenderIp]
|
||||||
}).reverse()
|
}).reverse()
|
||||||
detectionChart.setOption(offenderIpOption)
|
detectionChart.setOption(offenderIpOption)
|
||||||
this.isStatisticsActiveAttackNoData = false
|
// this.isStatisticsActiveAttackNoData = false
|
||||||
}
|
}
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
|
|
||||||
@@ -550,15 +689,17 @@ export default {
|
|||||||
count: 50
|
count: 50
|
||||||
}
|
}
|
||||||
] */
|
] */
|
||||||
const chartDom = document.getElementById(`detectionActiveAttacker${this.pageType}`)
|
this.statisticsActiveAttackData = data
|
||||||
const detectionChart = echarts.init(chartDom)
|
if (!this.$_.isEmpty(data)) {
|
||||||
const option = this.$_.cloneDeep(activeAttackBar)
|
const chartDom = document.getElementById(`detectionActiveAttacker${this.pageType}`)
|
||||||
option.series[0].data = data.map(d => {
|
const detectionChart = echarts.init(chartDom)
|
||||||
return [d.count, d.name]
|
const option = this.$_.cloneDeep(activeAttackBar)
|
||||||
}).reverse()
|
option.series[0].data = data.map(d => {
|
||||||
detectionChart.setOption(option)
|
return [d.count, d.name]
|
||||||
|
}).reverse()
|
||||||
|
detectionChart.setOption(option)
|
||||||
|
}
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
computeFilterPage (data) {
|
computeFilterPage (data) {
|
||||||
@@ -571,7 +712,9 @@ export default {
|
|||||||
const params = {
|
const params = {
|
||||||
startTime: getSecond(this.timeFilter.startTime),
|
startTime: getSecond(this.timeFilter.startTime),
|
||||||
endTime: getSecond(this.timeFilter.endTime),
|
endTime: getSecond(this.timeFilter.endTime),
|
||||||
q: this.q
|
q: this.q,
|
||||||
|
pageSize: this.pageObj.pageSize,
|
||||||
|
pageNo: this.pageObj.pageNo
|
||||||
}
|
}
|
||||||
getData(api.detection[this.pageType].listBasic, params).then(data => {
|
getData(api.detection[this.pageType].listBasic, params).then(data => {
|
||||||
if (this.pageType === detectionPageType.securityEvent) {
|
if (this.pageType === detectionPageType.securityEvent) {
|
||||||
@@ -873,15 +1016,28 @@ export default {
|
|||||||
this.listData = data
|
this.listData = data
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
|
|
||||||
|
})
|
||||||
|
getData(api.detection[this.pageType].listCount, params).then(data => {
|
||||||
|
this.pageObj.total = data
|
||||||
|
}).catch(error => {
|
||||||
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
timeRefreshChange () {
|
timeRefreshChange () {
|
||||||
|
this.initNoData()
|
||||||
if (!this.$refs.dateTimeRange.isCustom) {
|
if (!this.$refs.dateTimeRange.isCustom) {
|
||||||
const value = this.timeFilter.dateRangeValue
|
const value = this.timeFilter.dateRangeValue
|
||||||
this.$refs.dateTimeRange.quickChange(value)
|
this.$refs.dateTimeRange.quickChange(value)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
initNoData () {
|
||||||
|
this.isEventSeverityNoData = false
|
||||||
|
this.isStatisticsSeverityNoData = false
|
||||||
|
this.isStatisticsCategoryNoData = false
|
||||||
|
this.isStatisticsActiveAttackNoData = false
|
||||||
|
},
|
||||||
reload (s, e, v) {
|
reload (s, e, v) {
|
||||||
|
this.initNoData()
|
||||||
this.dateTimeRangeChange(s, e, v)
|
this.dateTimeRangeChange(s, e, v)
|
||||||
},
|
},
|
||||||
// methods
|
// methods
|
||||||
@@ -889,6 +1045,7 @@ export default {
|
|||||||
this.timeFilter = { startTime: s, endTime: e, dateRangeValue: v }
|
this.timeFilter = { startTime: s, endTime: e, dateRangeValue: v }
|
||||||
},
|
},
|
||||||
search (metaList, formatSql) {
|
search (metaList, formatSql) {
|
||||||
|
this.initNoData()
|
||||||
if (formatSql) {
|
if (formatSql) {
|
||||||
this.q = formatSql
|
this.q = formatSql
|
||||||
this.metaList = metaList
|
this.metaList = metaList
|
||||||
@@ -900,7 +1057,16 @@ export default {
|
|||||||
this.queryList()
|
this.queryList()
|
||||||
this.queryListTotal()
|
this.queryListTotal()
|
||||||
},
|
},
|
||||||
|
resetFilterData () {
|
||||||
|
this.filterData.securityEvent.forEach(d => {
|
||||||
|
d.data = []
|
||||||
|
})
|
||||||
|
this.filterData.performanceEvent.forEach(d => {
|
||||||
|
d.data = []
|
||||||
|
})
|
||||||
|
},
|
||||||
queryFilter () {
|
queryFilter () {
|
||||||
|
this.resetFilterData()
|
||||||
const params = {
|
const params = {
|
||||||
startTime: getSecond(this.timeFilter.startTime),
|
startTime: getSecond(this.timeFilter.startTime),
|
||||||
endTime: getSecond(this.timeFilter.endTime),
|
endTime: getSecond(this.timeFilter.endTime),
|
||||||
@@ -908,14 +1074,15 @@ export default {
|
|||||||
}
|
}
|
||||||
this.initEventSeverityTrendData(params)
|
this.initEventSeverityTrendData(params)
|
||||||
this.initEventSeverityData(params)
|
this.initEventSeverityData(params)
|
||||||
this.initSecurityTypeData(params)
|
|
||||||
if (this.pageType === detectionPageType.securityEvent) {
|
if (this.pageType === detectionPageType.securityEvent) {
|
||||||
this.initOffenderIpData(params)
|
this.initOffenderIpData(params)
|
||||||
this.initOffenderLocationData(params)
|
this.initOffenderLocationData(params)
|
||||||
this.initVictimIpData(params)
|
this.initVictimIpData(params)
|
||||||
this.initVictimLocationData(params)
|
this.initVictimLocationData(params)
|
||||||
|
this.initSecurityTypeData(params)
|
||||||
} else if (this.pageType === detectionPageType.performanceEvent) {
|
} else if (this.pageType === detectionPageType.performanceEvent) {
|
||||||
this.initActiveEntity(params)
|
this.initActiveEntity(params)
|
||||||
|
this.initEventTypeData(params)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
queryListTotal () {
|
queryListTotal () {
|
||||||
@@ -961,6 +1128,68 @@ export default {
|
|||||||
this.queryList()
|
this.queryList()
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
eventSeverityData: {
|
||||||
|
deep: true,
|
||||||
|
handler (n) {
|
||||||
|
if (!n || n.length === 0) {
|
||||||
|
this.timeout = setTimeout(() => {
|
||||||
|
this.isEventSeverityNoData = true
|
||||||
|
// this.$set(this.isEventSeverityNoData ,true)
|
||||||
|
this.loading = false
|
||||||
|
}, 500)
|
||||||
|
} else {
|
||||||
|
clearTimeout(this.timeout)
|
||||||
|
// this.$set(this.isEventSeverityNoData ,false)
|
||||||
|
this.isEventSeverityNoData = false
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
statisticsSeverityData: {
|
||||||
|
deep: true,
|
||||||
|
handler (n) {
|
||||||
|
if (!n || n.length === 0) {
|
||||||
|
this.timeout = setTimeout(() => {
|
||||||
|
// this.$set(this.isStatisticsSeverityNoData ,true)
|
||||||
|
this.isStatisticsSeverityNoData = true
|
||||||
|
}, 500)
|
||||||
|
} else {
|
||||||
|
clearTimeout(this.timeout)
|
||||||
|
// this.$set(this.isStatisticsSeverityNoData ,false)
|
||||||
|
this.isStatisticsSeverityNoData = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
statisticsCategoryData: {
|
||||||
|
deep: true,
|
||||||
|
handler (n) {
|
||||||
|
if (!n || n.length === 0) {
|
||||||
|
this.timeout = setTimeout(() => {
|
||||||
|
this.isStatisticsCategoryNoData = true
|
||||||
|
// this.$set(this.isStatisticsCategoryNoData ,true)
|
||||||
|
}, 500)
|
||||||
|
} else {
|
||||||
|
clearTimeout(this.timeout)
|
||||||
|
// this.$set(this.isStatisticsCategoryNoData ,false)
|
||||||
|
this.isStatisticsCategoryNoData = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
statisticsActiveAttackData: {
|
||||||
|
deep: true,
|
||||||
|
handler (n) {
|
||||||
|
if (!n || n.length === 0) {
|
||||||
|
this.timeout = setTimeout(() => {
|
||||||
|
this.isStatisticsActiveAttackNoData = true
|
||||||
|
// this.$set(this.isStatisticsActiveAttackNoData ,true)
|
||||||
|
}, 500)
|
||||||
|
} else {
|
||||||
|
clearTimeout(this.timeout)
|
||||||
|
// this.$set(this.isStatisticsActiveAttackNoData ,false)
|
||||||
|
this.isStatisticsActiveAttackNoData = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
timeFilter (n) {
|
timeFilter (n) {
|
||||||
this.search(this.metaList, this.q)
|
this.search(this.metaList, this.q)
|
||||||
},
|
},
|
||||||
@@ -1016,7 +1245,6 @@ export default {
|
|||||||
setup () {
|
setup () {
|
||||||
const { params } = useRoute()
|
const { params } = useRoute()
|
||||||
const pageType = params.typeName
|
const pageType = params.typeName
|
||||||
|
|
||||||
const dateRangeValue = 60
|
const dateRangeValue = 60
|
||||||
const { startTime, endTime } = getNowTime(dateRangeValue)
|
const { startTime, endTime } = getNowTime(dateRangeValue)
|
||||||
const timeFilter = ref({ startTime, endTime, dateRangeValue })
|
const timeFilter = ref({ startTime, endTime, dateRangeValue })
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ export function getSeriesIndex (type) {
|
|||||||
return mapping && mapping.index ? _.cloneDeep(mapping.index) : null
|
return mapping && mapping.index ? _.cloneDeep(mapping.index) : null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const activeAttackColor = ['#51a9ee', '#49bcf2', '#4ad7eb', '#4cd4c8',
|
||||||
|
'#7acc7e', '#a7db69']
|
||||||
|
|
||||||
const activeAttackColorMappings = [
|
const activeAttackColorMappings = [
|
||||||
{ value: 'command and control', color: '#51a9ee' },
|
{ value: 'command and control', color: '#51a9ee' },
|
||||||
{ value: 'payload delivery', color: '#49bcf2' },
|
{ value: 'payload delivery', color: '#49bcf2' },
|
||||||
@@ -149,7 +152,7 @@ export const pieForSeverity = {
|
|||||||
tooltip: {
|
tooltip: {
|
||||||
appendToBody: true
|
appendToBody: true
|
||||||
},
|
},
|
||||||
color: chartColor,
|
color: activeAttackColor,
|
||||||
animation: false,
|
animation: false,
|
||||||
legend: {
|
legend: {
|
||||||
orient: 'vertical',
|
orient: 'vertical',
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<div class="overview__title">Fields</div>
|
<div class="overview__title">Fields</div>
|
||||||
<div class="overview__row">
|
<div class="overview__row">
|
||||||
<div class="row__label">{{$t('entities.category')}}</div>
|
<div class="row__label">{{$t('entities.category')}}</div>
|
||||||
<div class="row__content">{{basicInfo.appCategory}}</div>
|
<div class="row__content">{{basicInfo.appCategory || '-'}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="overview__row">
|
<div class="overview__row">
|
||||||
<div class="row__label">{{$t('entities.subcategory')}}</div>
|
<div class="row__label">{{$t('entities.subcategory')}}</div>
|
||||||
@@ -35,8 +35,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { get } from '@/utils/http'
|
import { api, getData } from '@/utils/api'
|
||||||
import { api } from '@/utils/api'
|
|
||||||
import { eventSeverityColor } from '@/utils/constants'
|
import { eventSeverityColor } from '@/utils/constants'
|
||||||
export default {
|
export default {
|
||||||
name: 'DetectionPerformanceEventAppOverview',
|
name: 'DetectionPerformanceEventAppOverview',
|
||||||
@@ -74,35 +73,17 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
query () {
|
query () {
|
||||||
this.basicInfo = {
|
this.queryBasic().then(responses => {
|
||||||
clientLocationCountry: 1212,
|
responses && (this.basicInfo = responses)
|
||||||
clientLocationProvince: '112.2.2.3',
|
})
|
||||||
clientLocationRegion: 'China',
|
|
||||||
clientAsn: 'Hebei',
|
|
||||||
serverLocationCountry: 'Xingtai',
|
|
||||||
serverLocationProvince: 'hehe',
|
|
||||||
serverLocationRegion: '2.2.2.2',
|
|
||||||
serverAsn: 'China',
|
|
||||||
domainCategoryName: 'Hebei',
|
|
||||||
domainCategoryGroup: 'Xingtai',
|
|
||||||
domainReputationScore: 'hehe',
|
|
||||||
domainReputationLevel: 'high',
|
|
||||||
appCategory: 'vpn',
|
|
||||||
appSubcategory: 'foreign vpn',
|
|
||||||
appRisk: 'critical'
|
|
||||||
}
|
|
||||||
/* this.queryBasic().then(responses => {
|
|
||||||
}) */
|
|
||||||
},
|
},
|
||||||
queryBasic () {
|
queryBasic () {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
get(api.detection.performanceEvent.overviewBasic, { serverIp: this.detection.appName }).then(response => {
|
getData(api.detection.performanceEvent.overviewBasic, { domain: this.detection.appName,startTime: this.detection.startTime }).then(data => {
|
||||||
if (response.code === 200) {
|
resolve(data[0])
|
||||||
resolve(response.data.list)
|
}).catch(error => {
|
||||||
} else {
|
reject(error)
|
||||||
reject(response)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
reject(e)
|
reject(e)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<div class="overview__title">Fields</div>
|
<div class="overview__title">Fields</div>
|
||||||
<div class="overview__row">
|
<div class="overview__row">
|
||||||
<div class="row__label">{{$t('entities.category')}}</div>
|
<div class="row__label">{{$t('entities.category')}}</div>
|
||||||
<div class="row__content">{{basicInfo.domainCategoryName}}</div>
|
<div class="row__content">{{basicInfo.domainCategoryName || '-'}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="overview__row">
|
<div class="overview__row">
|
||||||
<div class="row__label">{{$t('entities.group')}}</div>
|
<div class="row__label">{{$t('entities.group')}}</div>
|
||||||
@@ -39,8 +39,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { get } from '@/utils/http'
|
import { api, getData } from '@/utils/api'
|
||||||
import { api } from '@/utils/api'
|
|
||||||
import { eventSeverityColor } from '@/utils/constants'
|
import { eventSeverityColor } from '@/utils/constants'
|
||||||
export default {
|
export default {
|
||||||
name: 'DetectionPerformanceEventDomainOverview',
|
name: 'DetectionPerformanceEventDomainOverview',
|
||||||
@@ -78,35 +77,17 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
query () {
|
query () {
|
||||||
this.basicInfo = {
|
this.queryBasic().then(responses => {
|
||||||
clientLocationCountry: 1212,
|
responses && (this.basicInfo = responses)
|
||||||
clientLocationProvince: '112.2.2.3',
|
})
|
||||||
clientLocationRegion: 'China',
|
|
||||||
clientAsn: 'Hebei',
|
|
||||||
serverLocationCountry: 'Xingtai',
|
|
||||||
serverLocationProvince: 'hehe',
|
|
||||||
serverLocationRegion: '2.2.2.2',
|
|
||||||
serverAsn: 'China',
|
|
||||||
domainCategoryName: 'Hebei',
|
|
||||||
domainCategoryGroup: 'Xingtai',
|
|
||||||
domainReputationScore: 'hehe',
|
|
||||||
domainReputationLevel: 'high',
|
|
||||||
appCategory: 'vpn',
|
|
||||||
appSubcategory: 'foreign vpn',
|
|
||||||
appRisk: 'critical'
|
|
||||||
}
|
|
||||||
/* this.queryBasic().then(responses => {
|
|
||||||
}) */
|
|
||||||
},
|
},
|
||||||
queryBasic () {
|
queryBasic () {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
get(api.detection.performanceEvent.overviewBasic, { serverIp: this.detection.appName }).then(response => {
|
getData(api.detection.performanceEvent.overviewBasic, { appName: this.detection.appName,startTime: this.detection.startTime }).then(data => {
|
||||||
if (response.code === 200) {
|
resolve(data[0])
|
||||||
resolve(response.data.list)
|
}).catch(error => {
|
||||||
} else {
|
reject(error)
|
||||||
reject(response)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
reject(e)
|
reject(e)
|
||||||
|
|||||||
@@ -65,31 +65,15 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
query () {
|
query () {
|
||||||
this.basicInfo = {
|
this.queryBasic().then(responses => {
|
||||||
clientLocationCountry: 1212,
|
responses && (this.basicInfo = responses)
|
||||||
clientLocationProvince: '112.2.2.3',
|
})
|
||||||
clientLocationRegion: 'China',
|
|
||||||
clientAsn: 'Hebei',
|
|
||||||
serverLocationCountry: 'Xingtai',
|
|
||||||
serverLocationProvince: 'hehe',
|
|
||||||
serverLocationRegion: '2.2.2.2',
|
|
||||||
serverAsn: 'China',
|
|
||||||
domainCategoryName: 'Hebei',
|
|
||||||
domainCategoryGroup: 'Xingtai',
|
|
||||||
domainReputationScore: 'hehe',
|
|
||||||
domainReputationLevel: 'high',
|
|
||||||
appCategory: 'vpn',
|
|
||||||
appSubcategory: 'foreign vpn',
|
|
||||||
appRisk: 'critical'
|
|
||||||
}
|
|
||||||
/* this.queryBasic().then(responses => {
|
|
||||||
}) */
|
|
||||||
},
|
},
|
||||||
queryBasic () {
|
queryBasic () {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
getData(api.detection.performanceEvent.overviewBasic, { serverIp: this.detection.serverIp }).then(data => {
|
getData(api.detection.performanceEvent.overviewBasic, { serverIp: this.detection.serverIp,startTime: this.detection.startTime }).then(data => {
|
||||||
resolve(data)
|
resolve(data[0])
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
reject(error)
|
reject(error)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<div class="overview__left">
|
<div class="overview__left">
|
||||||
<div class="overview__title">{{$t('overall.remark')}}</div>
|
<div class="overview__title">{{$t('overall.remark')}}</div>
|
||||||
<div class="overview__row">
|
<div class="overview__row">
|
||||||
<div class="row__content">{{basicInfo.malwareDescription || '-'}}</div>
|
<div class="row__content">Description</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="overview__title">Fields</div>
|
<div class="overview__title">Fields</div>
|
||||||
<div class="overview__row">
|
<div class="overview__row">
|
||||||
@@ -117,7 +117,7 @@
|
|||||||
<div class="overview__title">{{$t('detections.relatedDetections')}}</div>
|
<div class="overview__title">{{$t('detections.relatedDetections')}}</div>
|
||||||
<div class="overview__row-timeline">
|
<div class="overview__row-timeline">
|
||||||
<div class="row-timeline" v-for="event in events" :key="event">
|
<div class="row-timeline" v-for="event in events" :key="event">
|
||||||
<div class="row-timeline__time-info" :style="event.startTime === basicInfo.startTime ? 'color: #333;font-weight: bold;' : ''">{{formatT0(event.startTime)}}</div>
|
<div class="row-timeline__time-info" :style="event.startTime === basicInfo.startTime ? 'color: #333;font-weight: bold;' : ''">{{formatT0(event)}}</div>
|
||||||
<div class="row-timeline__line">
|
<div class="row-timeline__line">
|
||||||
<div class="line-point-larger" v-if="event.startTime === basicInfo.startTime">
|
<div class="line-point-larger" v-if="event.startTime === basicInfo.startTime">
|
||||||
<div class="line-point"></div>
|
<div class="line-point"></div>
|
||||||
@@ -154,7 +154,8 @@
|
|||||||
import { get } from '@/utils/http'
|
import { get } from '@/utils/http'
|
||||||
import { api } from '@/utils/api'
|
import { api } from '@/utils/api'
|
||||||
import { getMillisecond } from '@/utils/date-util'
|
import { getMillisecond } from '@/utils/date-util'
|
||||||
import { eventSeverityColor } from '@/utils/constants'
|
import { eventSeverityColor, unitTypes } from '@/utils/constants'
|
||||||
|
import unitConvert from '@/utils/unit-convert'
|
||||||
export default {
|
export default {
|
||||||
name: 'DetectionOverview',
|
name: 'DetectionOverview',
|
||||||
props: {
|
props: {
|
||||||
@@ -170,126 +171,41 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
formatT0 () {
|
formatT0 () {
|
||||||
return function (startTime) {
|
return function (event) {
|
||||||
return startTime === this.basicInfo.startTime ? 'T0' : 'T0-10m'
|
const diffSeconds = event.diffSeconds
|
||||||
|
if (diffSeconds === 0) {
|
||||||
|
return 'T0'
|
||||||
|
}
|
||||||
|
const eventStartTime = event.startTime
|
||||||
|
const entityStartTime = this.basicInfo ? this.basicInfo.startTime : ''
|
||||||
|
|
||||||
|
if (!this.$_.isEmpty(diffSeconds) && !this.$_.isEmpty(eventStartTime) && !this.$_.isEmpty(entityStartTime)) {
|
||||||
|
const suffix = unitConvert(diffSeconds, unitTypes.time, 's', null, 0).join('')
|
||||||
|
if (eventStartTime > entityStartTime) {
|
||||||
|
return `T0+${suffix}`
|
||||||
|
} else if (eventStartTime < entityStartTime) {
|
||||||
|
return `T0-${suffix}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getMillisecond,
|
getMillisecond,
|
||||||
query () {
|
query () {
|
||||||
this.basicInfo = {
|
|
||||||
eventId: 1212,
|
|
||||||
offenderIp: '112.2.2.3',
|
|
||||||
offenderLocationCountry: 'China',
|
|
||||||
offenderLocationProvince: 'Hebei',
|
|
||||||
offenderLocationRegion: 'Xingtai',
|
|
||||||
offenderAsn: 'hehe',
|
|
||||||
victimIp: '2.2.2.2',
|
|
||||||
victimLocationCountry: 'China',
|
|
||||||
victimLocationProvince: 'Hebei',
|
|
||||||
victimLocationRegion: 'Xingtai',
|
|
||||||
victimAsn: 'hehe',
|
|
||||||
domain: '5aibj.com',
|
|
||||||
domainCategoryName: 'bbs',
|
|
||||||
domainCategoryGroup: 'hehe',
|
|
||||||
domainReputationLevel: 'high',
|
|
||||||
appName: 'express vpn',
|
|
||||||
appCategory: 'vpn',
|
|
||||||
appSubcategory: 'foreign vpn',
|
|
||||||
appRisk: 'critical',
|
|
||||||
cryptominingPool: 'btcP',
|
|
||||||
cryptominingCoinType: 'btc',
|
|
||||||
cryptominingSoftware: 'a',
|
|
||||||
malwareName: 'gtw',
|
|
||||||
malwareAlias: 'gt',
|
|
||||||
malwareDescription: 'this is description,this is description,this is description,this is description,this is description,this is description,this is description,this is description,this is description,this is description,',
|
|
||||||
malwarePlatforms: 'windows',
|
|
||||||
malwareTechniques: 'Audio captures',
|
|
||||||
malwareGroups: 'Silver terrier',
|
|
||||||
startTime: 1645417930
|
|
||||||
}
|
|
||||||
this.events = [
|
|
||||||
{
|
|
||||||
eventSeverity: 'high',
|
|
||||||
securityType: 'command and control',
|
|
||||||
offenderIp: '2.2.2.2',
|
|
||||||
victimIp: '2.2.2.3',
|
|
||||||
startTime: 1645307930
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventSeverity: 'critical',
|
|
||||||
securityType: 'command and control',
|
|
||||||
offenderIp: '2.2.2.2',
|
|
||||||
victimIp: '112.2.2.3',
|
|
||||||
startTime: 1645317930
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventSeverity: 'high',
|
|
||||||
securityType: 'command and control',
|
|
||||||
offenderIp: '2.2.2.2',
|
|
||||||
victimIp: '2.2.2.3',
|
|
||||||
startTime: 1645327930
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventSeverity: 'high',
|
|
||||||
securityType: 'command and control',
|
|
||||||
offenderIp: '2.2.2.2',
|
|
||||||
victimIp: '2.2.2.3',
|
|
||||||
startTime: 1645337930
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventSeverity: 'high',
|
|
||||||
securityType: 'command and control',
|
|
||||||
offenderIp: '2.2.2.2',
|
|
||||||
victimIp: '2.2.2.3',
|
|
||||||
startTime: 1645347930
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventSeverity: 'high',
|
|
||||||
securityType: 'command and control',
|
|
||||||
offenderIp: '2.2.2.2',
|
|
||||||
victimIp: '2.2.2.3',
|
|
||||||
startTime: 1645357930
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventSeverity: 'high',
|
|
||||||
securityType: 'command and control',
|
|
||||||
offenderIp: '2.2.2.2',
|
|
||||||
victimIp: '2.2.2.3',
|
|
||||||
startTime: 1645367930
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventSeverity: 'high',
|
|
||||||
securityType: 'command and control',
|
|
||||||
offenderIp: '2.2.2.2',
|
|
||||||
victimIp: '2.2.2.3',
|
|
||||||
startTime: 1645397930
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventSeverity: 'high',
|
|
||||||
securityType: 'command and control',
|
|
||||||
offenderIp: '2.2.2.2',
|
|
||||||
victimIp: '2.2.2.3',
|
|
||||||
startTime: 1645407930
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventSeverity: 'high',
|
|
||||||
securityType: 'command and control',
|
|
||||||
offenderIp: '2.2.2.2',
|
|
||||||
victimIp: '2.2.2.3',
|
|
||||||
startTime: 1645417930
|
|
||||||
}
|
|
||||||
]
|
|
||||||
Promise.all([this.queryBasic(), this.queryEvent()]).then(responses => {
|
Promise.all([this.queryBasic(), this.queryEvent()]).then(responses => {
|
||||||
|
console.info(responses)
|
||||||
|
responses[0] && (this.basicInfo = responses[0])
|
||||||
|
responses[1] && (this.events = responses[1])
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
queryBasic () {
|
queryBasic () {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
get(api.detectionOverviewBasic, { eventId: this.detection.eventId }).then(response => {
|
get(api.detection.securityEvent.overviewBasic, { eventId: this.detection.eventId,startTime: this.detection.startTime }).then(response => {
|
||||||
if (response.code === 200) {
|
if (response.code === 200) {
|
||||||
resolve(response.data.list)
|
resolve(response.data.result[0])
|
||||||
} else {
|
} else {
|
||||||
reject(response)
|
reject(response)
|
||||||
}
|
}
|
||||||
@@ -302,9 +218,9 @@ export default {
|
|||||||
queryEvent () {
|
queryEvent () {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
get(api.detectionOverviewEvent, { eventId: this.detection.eventId }).then(response => {
|
get(api.detection.securityEvent.overviewEvent, { startTime: this.detection.startTime, offenderIp: this.detection.offenderIp, victimIp: this.detection.victimIp }).then(response => {
|
||||||
if (response.code === 200) {
|
if (response.code === 200) {
|
||||||
resolve(response.data.list)
|
resolve(response.data.result)
|
||||||
} else {
|
} else {
|
||||||
reject(response)
|
reject(response)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -257,8 +257,7 @@ export default {
|
|||||||
const queryParams = {
|
const queryParams = {
|
||||||
startTime: parseInt(this.timeFilter.startTime / 1000),
|
startTime: parseInt(this.timeFilter.startTime / 1000),
|
||||||
endTime: parseInt(this.timeFilter.endTime / 1000),
|
endTime: parseInt(this.timeFilter.endTime / 1000),
|
||||||
ip: this.entityData.ipAddr,
|
ip: this.entityData.ipAddr
|
||||||
country: this.entityData.ipLocationCountry
|
|
||||||
}
|
}
|
||||||
return queryParams
|
return queryParams
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user