This commit is contained in:
@changcode
2022-01-20 18:08:08 +08:00
11 changed files with 355 additions and 5 deletions

View File

@@ -119,7 +119,7 @@
border: 1px solid #E7EAED;
box-shadow: 0 2px 4px 0 rgba(51,51,51,0.02);
border-radius: 2px;
height: 100%;
height: calc(100% - 47px);
width: 100%;
.chart-drawing {

View File

@@ -1,5 +1,6 @@
.chart-ip-open-port-bar {
display: flex;
height: 100%;
.el-table--border td{
border: none !important;
}
@@ -19,6 +20,9 @@
font-size: 12px;
font-weight: bold;
}
.chart-drawing{
height: calc(100% - 36px) !important;
}
}
}

View File

@@ -199,7 +199,7 @@
&>.cn-chart {
position: relative;
border-radius: 2px;
height: 100%;
height: calc(100% - 47px);
width: 100%;
.chart-drawing {

View File

@@ -123,6 +123,21 @@
:query-params="queryParams"
></chart-cryptocurrency-event-list>
<chart-relation-ship
v-else-if="isRelationShip"
:chart-info="chartInfo"
:chart-data="chartData"
:query-params="queryParams"
></chart-relation-ship>
<chart-san-key
v-else-if="isSankey"
:chart-info="chartInfo"
:chart-data="chartData"
:query-params="queryParams"
:entity="entity"
></chart-san-key>
</template>
</div>
</template>
@@ -145,6 +160,8 @@ import ChartAppBasicInfo from '@/views/charts/charts/ChartAppBasicInfo'
import ChartDomainWhois from '@/views/charts/charts/ChartDomainWhois'
import ChartDomainDnsRecord from '@/views/charts/charts/ChartDomainDnsRecord'
import ChartCryptocurrencyEventList from '@/views/charts/charts/ChartCryptocurrencyEventList'
import ChartRelationShip from '@/views/charts/charts/ChartRelationShip'
import ChartSanKey from '@/views/charts/charts/ChartSanKey'
import {
isEcharts,
isEchartsLine,
@@ -183,6 +200,7 @@ import _ from 'lodash'
export default {
name: 'chart',
components: {
ChartSanKey,
ChartCryptocurrencyEventList,
ChartDomainDnsRecord,
ChartDomainWhois,
@@ -199,7 +217,8 @@ export default {
ChartBlock,
ChartTimeBar,
ChartCategoryBar,
ChartIpOpenPortBar
ChartIpOpenPortBar,
ChartRelationShip,
},
props: {
chartInfo: Object,

View File

@@ -190,6 +190,10 @@ export default {
response = testData.data2
} else if (this.chartInfo.type === 22 && testData) {
response = testData.data3
} else if (this.chartInfo.type === 43 && testData) {
response = testData.data4
} else if (this.chartInfo.type === 42 && testData) {
response = testData.data5
}
if (response.code === 200) {
this.chartData = response.data.result

View File

@@ -35,6 +35,9 @@
<script>
import lodash from 'lodash'
import { ipOpenPortBar } from '@/views/charts/charts/options/bar'
import { getChartColor } from '@/components/charts/chart-options'
import * as echarts from 'echarts'
export default {
name: 'ChartIpOpenPortBar',
props: {
@@ -71,7 +74,22 @@ export default {
},
methods: {
init (id) {
const dom = document.getElementById(id)
!this.myChart && (this.myChart = echarts.init(dom))
this.tableData = lodash.cloneDeep(this.chartData)
this.chartOption = this.$_.cloneDeep(ipOpenPortBar)
const protocols = []
this.tableData.forEach((d, i) => {
const index = protocols.findIndex(p => p.name === d.protocol.toUpperCase())
if (index === -1) {
protocols.push({ name: d.protocol.toUpperCase(), value: 1, itemStyle: { color: getChartColor(i) } })
} else {
protocols[index].value++
}
})
this.chartOption.series[0].data = protocols
this.chartOption.xAxis.data = protocols.map(p => p.name)
this.myChart.setOption(this.chartOption)
}
},
watch: {

View File

@@ -0,0 +1,92 @@
<template>
<div class="chart-drawing" :id="`chart${chartInfo.id}`"></div>
</template>
<script>
import * as echarts from 'echarts'
import loadsh from 'lodash'
import { relationShip } from './options/sankey'
export default {
name: 'ChartRelationShip',
data () {
return {
myChart: null,
chartOption: null
}
},
props: {
chartInfo: Object,
chartData: [Array, Object],
resultType: Object,
queryParams: Object
},
methods: {
init (id) {
const chartParams = this.chartInfo.params
const dom = document.getElementById(id)
!this.myChart && (this.myChart = echarts.init(dom))
this.chartOption = this.$_.cloneDeep(relationShip)
const data = []
const links = []
handleData(data, links, this.chartData)
this.chartOption.series[0].data = data
this.chartOption.series[0].links = links
this.myChart.setOption(this.chartOption)
function handleData (data, links, item) {
if (!data.some(d => d.name === item.name)) {
data.push({ name: item.name, ...handleStyle(item) })
}
if (!loadsh.isEmpty(item.from) && !loadsh.isEmpty(item.to)) {
links.push({ target: item.to, source: item.from })
}
if (!loadsh.isEmpty(item.leaf)) {
item.leaf.forEach(i => {
handleData(data, links, i)
})
}
}
function handleStyle (item) {
const style = {}
switch (item.type) {
case 'app_id': {
style.itemStyle = { color: '#73DEB3' }
style.symbol = 'circle'
break
}
case 'domain': {
style.itemStyle = { color: '#73A0FA' }
style.symbol = 'circle'
break
}
case 'client_ip': {
style.itemStyle = { color: '#E8F6FF', borderColor: '#C9C9C9' }
style.symbol = 'roundRect'
style.symbolSize = [80, 25]
break
}
case 'server_ip': {
style.itemStyle = { color: '#E2FCEF', borderColor: '#C9C9C9' }
style.symbol = 'roundRect'
style.symbolSize = [80, 25]
break
}
}
return style
}
}
},
watch: {
chartData: {
deep: true,
handler (n) {
this.init(`chart${this.chartInfo.id}`)
}
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,122 @@
<template>
<div class="sankey-box">
<div class="chart-drawing" :id="`chart${chartInfo.id}`"></div>
<div class="sankey__label" style="left: 5%;">{{$t('entities.inboundLinkId')}}</div>
<div class="sankey__label" style="left: 50%;">{{entity.ip || entity.domain || entity.app}}</div>
<div class="sankey__label" style="right: 5%; transform: translateX(50%)">{{$t('entities.outboundLinkId')}}</div>
</div>
</template>
<script>
import unitConvert, { valueToRangeValue } from '@/utils/unit-convert'
import { unitTypes } from '@/utils/constants'
import * as echarts from 'echarts'
import { sankey } from './options/sankey'
export default {
name: 'ChartSanKey',
props: {
chartInfo: Object,
chartData: [Array, Object],
resultType: Object,
queryParams: Object,
entity: {
type: Object,
default: () => {}
}
},
methods: {
init (id) {
const vm = this
const chartParams = this.chartInfo.params
const entityName = this.entity.ip || this.entity.domain || this.entity.app
const dom = document.getElementById(id)
!this.myChart && (this.myChart = echarts.init(dom))
this.chartOption = this.$_.cloneDeep(sankey)
this.chartOption.series[0].tooltip = {
formatter: function (param) {
return `
<div class="sankey__tooltip">
<div class="sankey__tooltip-row">
<div class="sankey__row-label">Via:</div>
<div class="sankey__row-value">${param.data.name}</div>
</div>
<div class="sankey__tooltip-row">
<div style="margin: 6px 0; height: 1px; width: 100%; background-color: #E7EAED;"></div>
</div>
<div class="sankey__tooltip-row">
<div class="sankey__row-label">Traffic:</div>
<div class="sankey__row-value">${param.data.convert[0]}${param.data.convert[1]}&nbsp;(${param.data.percent[0]}%)</div>
</div>
<div class="sankey__tooltip-row">
<div class="sankey__row-label">Performance:</div>
</div>
<div class="sankey__tooltip-table">
<div class="sankey__table-row">
<div class="sankey__table-cell">${vm.$t('networkAppPerformance.tripTime')}:</div>
<div class="sankey__table-cell">${param.data.latency[0]}&nbsp;${param.data.latency[1]}</div>
</div>
<div class="sankey__table-row">
<div class="sankey__table-cell">${vm.$t('overall.packetLoss')}:</div>
<div class="sankey__table-cell">${param.data.lossPercent[0]}&nbsp;%</div>
</div>
<div class="sankey__table-row">
<div class="sankey__table-cell">${vm.$t('overall.packetRetrans')}:</div>
<div class="sankey__table-cell">${param.data.retransPercent[0]}&nbsp;%</div>
</div>
</div>
</div>
`
}
}
let inTotalValue = 0
let outTotalValue = 0
this.chartData.forEach(item => {
if (item.direction === 'in') {
inTotalValue += parseInt(item.bytes)
} else if (item.direction === 'out') {
outTotalValue += parseInt(item.bytes)
}
})
const data = this.chartData.map(item => {
return {
...item,
name: item.linkID,
percent: valueToRangeValue(parseInt(item.bytes) / (item.direction === 'in' ? inTotalValue : outTotalValue) * 100, unitTypes.percent),
convert: unitConvert(item.bytes, unitTypes.byte),
latency: valueToRangeValue(item.latency, unitTypes.time),
lossPercent: valueToRangeValue(item.lossPercent, unitTypes.percent),
retransPercent: valueToRangeValue(item.retransPercent, unitTypes.percent),
bytes: parseFloat(item.bytes)
}
})
data.push({ name: entityName })
const link = data.map(item => {
const source = item.direction === 'in' ? item.linkID : entityName
const target = item.direction === 'in' ? entityName : item.linkID
return {
...item,
source,
target,
value: item.bytes
}
})
this.chartOption.series[0].data = data
this.chartOption.series[0].links = link
this.myChart.setOption(this.chartOption)
}
},
watch: {
chartData: {
deep: true,
handler (n) {
this.init(`chart${this.chartInfo.id}`)
}
}
}
}
</script>
<style scoped>
</style>

View File

@@ -4,7 +4,8 @@ import {
categoryVerticalFormatter,
chartColor,
getCharBartColor,
timeVerticalFormatter, tooLongFormatter
timeVerticalFormatter,
tooLongFormatter
} from '@/views/charts/charts/tools'
export const ipOpenPortBar = {

View File

@@ -41,3 +41,28 @@ export const sankey = {
}
]
}
export 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: []
}
]
}

File diff suppressed because one or more lines are too long