diff --git a/src/components/charts/chart-options.js b/src/components/charts/chart-options.js index 45c2d202..1e85a4eb 100644 --- a/src/components/charts/chart-options.js +++ b/src/components/charts/chart-options.js @@ -280,11 +280,37 @@ const singleValueLine = { } ] } +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 typeOptionMappings = [ { value: 11, option: line }, // 常规折线图 { value: 12, option: lineWithStatistics }, // 带统计表格的折线图 { value: 13, option: lineStack }, // 折线堆叠图 { value: 31, option: pieWithTable }, // 常规折线图 + { value: 42, option: relationShip }, // 关系图 { value: 52, option: singleValueLine } ] const typeCategory = { diff --git a/src/views/charts/Chart.vue b/src/views/charts/Chart.vue index 4a2e1f19..67c8e5f9 100644 --- a/src/views/charts/Chart.vue +++ b/src/views/charts/Chart.vue @@ -545,7 +545,7 @@ export default { } }, initECharts (chartParams) { - if(chartParams.showLegend === false ) { + if (chartParams.showLegend === false) { this.chartOption.legend.show = false } const queryParams = { startTime: parseInt(this.timeFilter.startTime / 1000), endTime: parseInt(this.timeFilter.endTime / 1000), ...this.entity } @@ -593,14 +593,73 @@ export default { }) }, initRelationShip (chartParams) { - const queryParams = { ...this.entity } + const queryParams = { ...this.entity, limit: 5 } post(replaceUrlPlaceholder(chartParams.url, queryParams)).then(response => { if (response.code === 200) { + if (!response.data.result) { + this.noData = true + return + } else { + this.noData = false + } + const data = [] + const links = [] + handleData(data, links, response.data.result) + this.chartOption.series[0].data = data + this.chartOption.series[0].links = links } + this.myChart.setOption(this.chartOption) + this.$nextTick(() => { + this.myChart.resize() + }) }).finally(() => { setTimeout(() => { this.loading = false }, 250) }) + + const vm = this + function handleData (data, links, item) { + if (!data.some(d => d.name === item.name)) { + data.push({ name: item.name, ...handleStyle(item) }) + } + if (!vm.$_.isEmpty(item.from) && !vm.$_.isEmpty(item.to)) { + links.push({ target: item.to, source: item.from }) + } + if (!vm.$_.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 + } }, initEchartsWithStatistics (chartParams) { const queryParams = { startTime: parseInt(this.timeFilter.startTime / 1000), endTime: parseInt(this.timeFilter.endTime / 1000), ...this.entity }