fix: 修复一些问题;entity详情页调整;

This commit is contained in:
chenjinsong
2021-08-09 13:38:32 +08:00
parent a7101b6a2a
commit d5742afe10
13 changed files with 137 additions and 157 deletions

View File

@@ -1,8 +1,8 @@
@font-face {
font-family: "cn-icon"; /* Project id 2614877 */
src: url('iconfont.woff2?t=1625552111572') format('woff2'),
url('iconfont.woff?t=1625552111572') format('woff'),
url('iconfont.ttf?t=1625552111572') format('truetype');
src: url('iconfont.woff2?t=1628479878175') format('woff2'),
url('iconfont.woff?t=1628479878175') format('woff'),
url('iconfont.ttf?t=1628479878175') format('truetype');
}
.cn-icon {
@@ -13,6 +13,14 @@
-moz-osx-font-smoothing: grayscale;
}
.cn-icon-arrow-left-circle:before {
content: "\e741";
}
.cn-icon-credit:before {
content: "\e740";
}
.cn-icon-ip:before {
content: "\e73d";
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,77 +1,33 @@
import i18n from '@/i18n'
export const allTableTitle = {
tableTitles10: [
{
label: i18n.global.t('overall.clientIp'),
prop: 'clientIp'
},
{
label: i18n.global.t('overall.sessions'),
prop: 'sessions'
},
{
label: i18n.global.t('overall.bytes'),
prop: 'bytes'
},
{
label: i18n.global.t('overall.packets'),
prop: 'packets'
}
],
tableTitles13: [
{
label: i18n.global.t('overall.serverIp'),
prop: 'serverIp'
},
{
label: i18n.global.t('overall.sessions'),
prop: 'sessions'
},
{
label: i18n.global.t('overall.bytes'),
prop: 'bytes'
},
{
label: i18n.global.t('overall.packets'),
prop: 'packets'
}
],
tableTitles14: [
{
label: i18n.global.t('overall.domain'),
prop: 'domain'
},
{
label: i18n.global.t('overall.sessions'),
prop: 'sessions'
},
{
label: i18n.global.t('overall.bytes'),
prop: 'bytes'
},
{
label: i18n.global.t('overall.packets'),
prop: 'packets'
}
],
tableTitles15: [
{
label: i18n.global.t('overall.appName'),
prop: 'appName'
},
{
label: i18n.global.t('overall.sessions'),
prop: 'sessions'
},
{
label: i18n.global.t('overall.bytes'),
prop: 'bytes'
},
{
label: i18n.global.t('overall.packets'),
prop: 'packets'
}
]
export const tableTitleMapping = {
clientIp: {
label: i18n.global.t('overall.clientIp'),
prop: 'clientIp'
},
serverIp: {
label: i18n.global.t('overall.serverIp'),
prop: 'serverIp'
},
appName: {
label: i18n.global.t('overall.appName'),
prop: 'appName'
},
sessions: {
label: i18n.global.t('overall.sessions'),
prop: 'sessions'
},
bytes: {
label: i18n.global.t('overall.bytes'),
prop: 'bytes'
},
packets: {
label: i18n.global.t('overall.packets'),
prop: 'packets'
},
domain: {
label: i18n.global.t('overall.domain'),
prop: 'domain'
}
}
export const legendMapping = {
bytes_received_rate: i18n.global.t('trafficSummary.throughputPerSecondC2s'),

View File

@@ -1,3 +1,18 @@
.entity-detail-tool {
display: flex;
justify-content: space-between;
align-items: center;
margin: 10px 20px 10px 0;
padding: 0 20px;
height: 60px;
background-color: #FFFFFF;
box-shadow: 0 1px 2px 0 rgba(0,0,0,0.06);
border-radius: 2px;
.cn-icon-arrow-left-circle {
color: $--color-primary;
}
}
.cn-panel, .cn-panel>.cn-chart__tabs>.el-tabs__content>.el-tab-pane {
display: grid;
grid-template-columns: repeat(30, 1fr);

View File

@@ -25,45 +25,46 @@
</div>
<template v-if="entityType === 'ip'">
<div class="body__row">
<span class="body__row-label cn-icon cn-icon-category tubiao">{{$t('overall.country')}}:</span>
<span class="body__row-label"><i class="cn-icon cn-icon-category"></i>&nbsp;{{$t('overall.country')}}:</span>
<div class="body__row-value" :title="d.country">{{d.country || '-'}}</div>
</div>
<div class="body__row">
<span class="body__row-label cn-icon cn-icon-position tubiao">{{$t('overall.region')}}:</span>
<span class="body__row-label"><i class="cn-icon cn-icon-position"></i>&nbsp;{{$t('overall.region')}}:</span>
<div class="body__row-value" :title="d.region">{{d.region || '-'}}</div>
</div>
<div class="body__row Select">
<span class="body__row-label cn-icon cn-icon-cloud tubiao">{{$t('entities.asn')}}:</span>
<div class="body__row">
<span class="body__row-label"><i class="cn-icon cn-icon-cloud"></i>&nbsp;{{$t('entities.asn')}}:</span>
<div class="body__row-value" :title="d.asn">{{d.asn || '-'}}</div>
</div>
<div class="body__detail" @click="entityDetail">{{$t('overall.detail')}}></div>
<div class="body__detail"
@click="entityDetail({clientIP: d.ip}, [{key: 'clientIP', label: $t('overall.clientIp')}, {key: 'serverIP', label: $t('overall.serverIp')}])">{{$t('overall.detail')}}></div>
</template>
<template v-else-if="entityType === 'domain'">
<div class="body__row">
<span class="body__row-label cn-icon cn-icon-category">{{$t('entities.Group')}}:</span>
<span class="body__row-label"><i class="cn-icon cn-icon-category"></i>&nbsp;{{$t('entities.Group')}}:</span>
<div class="body__row-value" :title="d.categoryGroup">{{d.categoryGroup || '-'}}</div>
</div>
<div class="body__row">
<span class="body__row-label cn-icon cn-icon-sub-category">{{$t('entities.categoryName')}}:</span>
<span class="body__row-label"><i class="cn-icon cn-icon-sub-category"></i>&nbsp;{{$t('entities.categoryName')}}:</span>
<div class="body__row-value" :title="d.categoryName">{{d.categoryName || '-'}}</div>
</div>
<div class="body__row Select">
<span class="body__row-label cn-icon cn-icon-risk">{{$t('entities.credit')}}:</span>
<div class="body__row">
<span class="body__row-label"><i class="cn-icon cn-icon-risk"></i>&nbsp;{{$t('entities.credit')}}:</span>
<div class="body__row-value" :title="d.reputationScore">{{d.reputationScore || '-'}}</div>
</div>
<div class="body__detail" @click="entityDetail({domain: d.domainName})">{{$t('overall.detail')}}></div>
</template>
<template v-else-if="entityType === 'app'">
<div class="body__row">
<span class="body__row-label cn-icon cn-icon-id">APP ID:</span>
<span class="body__row-label"><i class="cn-icon cn-icon-risk"></i>&nbsp;APP ID:</span>
<div class="body__row-value" :title="d.appId">{{d.appId || '-'}}</div>
</div>
<div class="body__row">
<span class="body__row-label cn-icon cn-icon-category">{{$t('entities.category')}}:</span>
<span class="body__row-label"><i class="cn-icon cn-icon-risk"></i>&nbsp;{{$t('entities.category')}}:</span>
<div class="body__row-value" :title="d.appCategory">{{d.appCategory || '-'}}</div>
</div>
<div class="body__row Select">
<span class="body__row-label cn-icon cn-icon-sub-category">{{$t('entities.subcategory')}}:</span>
<div class="body__row">
<span class="body__row-label"><i class="cn-icon cn-icon-risk"></i>&nbsp;{{$t('entities.subcategory')}}:</span>
<div class="body__row-value" :title="d.appSubategory">{{d.appSubategory || '-'}}</div>
</div>
<div class="body__detail" @click="entityDetail({appId: d.appId})">{{$t('overall.detail')}}></div>
@@ -81,7 +82,7 @@
:page-size="pageObj.pageSize"
:total="pageObj.total"
:page-sizes="[30, 50, 100]"
layout="total, prev, pager, next, sizes"
layout="total, prev, pager, next"
></el-pagination>
</div>
</div>
@@ -168,8 +169,8 @@ export default {
})
})
},
entityDetail (params) {
this.$emit('showDetail', params)
entityDetail (params, tabs = []) {
this.$emit('showDetail', params, tabs)
}
}
}

View File

@@ -122,11 +122,10 @@
.body__row {
display: flex;
align-items: center;
width: 200px;
margin: auto;
margin: 0 20px;
border-bottom: 1px solid #EFF2F5;
color: #666666;
padding: 7px 0px;
padding: 7px 0;
justify-content: center;
}
@@ -165,6 +164,12 @@
justify-content: center;
align-items: flex-end;
height: 67px;
.el-pager {
li:last-of-type {
display: none;
}
}
}
}
}
@@ -177,42 +182,3 @@
.app-orange {
color: #FFA200;
}
.Select{
border-bottom: 0px !important;
}
.cn-icon-position:before {
content: "\e72e";
padding: 5.5px;
font-size: 12px;}
.cn-icon-category:before {
content: "\e733";
padding: 5.5px;
font-size: 12px;
}
.cn-icon-cloud:before {
content: "\e73c";
padding: 4.5px;
font-size: 12px;
}
.cn-icon-sub-category:before {
content: "\e730";
padding: 5.5px;
font-size: 12px;
}
.cn-icon-risk:before {
content: "\e731";
padding: 5.5px;
font-size: 12px;
}
.cn-icon-id:before {
content: "\e734";
padding: 5.5px;
font-size: 12px;
}
.cn-entity>ip{
width: 340px;
height: 290px;
}

View File

@@ -61,7 +61,8 @@ export const entityTypeMappingKey = {
export const unitTypes = {
time: 'time',
number: 'number',
byte: 'byte'
byte: 'byte',
string: 'string'
}
export const chartTableDefaultPageSize = 10 // table类型图表默认每页数据量

View File

@@ -64,6 +64,9 @@ export function timeUnitFormatter (time, sourceUnit = 'ms', targetUnit, dot = 2)
/* 单位转换,返回转换后的[value, unit] */
// unitType = time / number / byte
export default function unitConvert (value, unitType, sourceUnit, targetUnit, dot = 2) {
if (unitType === unitTypes.string) {
return [value, '']
}
if (!Number(value) && Number(value) !== 0) {
return ['-', '']
} else {

View File

@@ -151,7 +151,7 @@ import * as echarts from 'echarts'
import * as am4Core from '@amcharts/amcharts4/core'
import * as am4Maps from '@amcharts/amcharts4/maps'
import { shallowRef } from 'vue'
import { allTableTitle, legendMapping } from '@/components/charts/chart-table-title'
import { tableTitleMapping, legendMapping } from '@/components/charts/chart-table-title'
import {
isEcharts,
isSingleValue,
@@ -187,7 +187,10 @@ export default {
props: {
chart: Object, // 图表对象包括id、name、type等数据
timeFilter: Object,
entity: Object
entity: {
type: Object,
default: () => {}
}
},
components: {
EchartsFrame,
@@ -322,9 +325,9 @@ export default {
},
loadMap (polygonSeries) {
const chartParams = this.chartInfo.params
const queryParams = { startTime: parseInt(this.timeFilter.startTime / 1000), endTime: parseInt(this.timeFilter.endTime / 1000), country: '', region: '' } // 统计数据的查询参数
const queryParams = { startTime: parseInt(this.timeFilter.startTime / 1000), endTime: parseInt(this.timeFilter.endTime / 1000), country: '', region: '', ...this.entity } // 统计数据的查询参数
get(replaceUrlPlaceholder(chartParams.url, queryParams)).then(response => {
if (response.code === 200) {
if (response.code === 200 && !this.$_.isEmpty(response.data.result)) {
const data = response.data.result
data.forEach(r => {
const serverCountryCapital = r.serverId && getCapitalGeo(r.serverId)
@@ -360,7 +363,6 @@ export default {
})
}
]
const imageSeries = this.myChart.series.push(new am4Maps.MapImageSeries())
imageSeries.dataFields.value = 'sessions'
const imageSeriesTemplate = imageSeries.mapImages.template
@@ -429,6 +431,14 @@ export default {
getTargetPageData (pageNum, pageSize, tableData) {
return this.$_.slice(tableData, (pageNum - 1) * pageSize, pageNum * pageSize)
},
getTableTitle (data) {
if (data.length > 0) {
const columns = Object.keys(data[0])
return columns.map(c => tableTitleMapping[c])
} else {
return []
}
},
toggleStatisticsLegend (index) {
this.statisticsData[index].active = !this.statisticsData[index].active
this.statisticsData.forEach((d, i) => {
@@ -452,7 +462,7 @@ export default {
}
},
initECharts (chartParams) {
const queryParams = { startTime: parseInt(this.timeFilter.startTime / 1000), endTime: parseInt(this.timeFilter.endTime / 1000) }
const queryParams = { startTime: parseInt(this.timeFilter.startTime / 1000), endTime: parseInt(this.timeFilter.endTime / 1000), ...this.entity }
get(replaceUrlPlaceholder(chartParams.url, queryParams)).then(response => {
if (response.code === 200) {
const seriesTemplate = this.chartOption.series[0]
@@ -477,7 +487,7 @@ export default {
})
},
initEchartsWithStatistics (chartParams) {
const queryParams = { startTime: parseInt(this.timeFilter.startTime / 1000), endTime: parseInt(this.timeFilter.endTime / 1000) }
const queryParams = { startTime: parseInt(this.timeFilter.startTime / 1000), endTime: parseInt(this.timeFilter.endTime / 1000), ...this.entity }
get(replaceUrlPlaceholder(chartParams.url, queryParams)).then(response => {
if (response.code === 200) {
this.statisticsData = response.data.result.map(d => {
@@ -508,8 +518,8 @@ export default {
const self = this
chartParams.valueColumn = this.orderPieTable
const unitType = getUnitType(chartParams.valueColumn)
const queryParams = { startTime: parseInt(this.timeFilter.startTime / 1000), endTime: parseInt(this.timeFilter.endTime / 1000), limit: 10, order: this.orderPieTable } // 统计数据的查询参数
const tableQueryParams = { startTime: parseInt(this.timeFilter.startTime / 1000), endTime: parseInt(this.timeFilter.endTime / 1000), limit: 10, order: this.orderPieTable } // 统计数据的查询参数
const queryParams = { startTime: parseInt(this.timeFilter.startTime / 1000), endTime: parseInt(this.timeFilter.endTime / 1000), limit: 10, order: this.orderPieTable, ...this.entity } // 统计数据的查询参数
const tableQueryParams = { startTime: parseInt(this.timeFilter.startTime / 1000), endTime: parseInt(this.timeFilter.endTime / 1000), limit: 10, order: this.orderPieTable, ...this.entity } // 统计数据的查询参数
tableQueryParams[chartParams.nameColumn] = [] // 处理两个图表不一样的地方
get(replaceUrlPlaceholder(chartParams.url, queryParams)).then(response => {
if (response.code === 200) {
@@ -531,11 +541,13 @@ export default {
this.$nextTick(() => {
this.myChart.resize()
})
get(replaceUrlPlaceholder(chartParams.urlTable, tableQueryParams)).then(response2 => {
if (response2.code === 200) {
this.pieTableData = response2.data.result
}
})
if (!this.$_.isEmpty(data)) {
get(replaceUrlPlaceholder(chartParams.urlTable, tableQueryParams)).then(response2 => {
if (response2.code === 200) {
this.pieTableData = response2.data.result
}
})
}
}
})
// legend点击事件
@@ -577,7 +589,7 @@ export default {
})
},
loadPieTableData (name = '') {
const childrenParams = { startTime: parseInt(this.timeFilter.startTime / 1000), endTime: parseInt(this.timeFilter.endTime / 1000), limit: 10, order: this.orderPieTable }
const childrenParams = { startTime: parseInt(this.timeFilter.startTime / 1000), endTime: parseInt(this.timeFilter.endTime / 1000), limit: 10, order: this.orderPieTable, ...this.entity }
childrenParams[this.chartInfo.params.nameColumn] = name
get(replaceUrlPlaceholder(this.chartInfo.params.urlTable, childrenParams)).then(response => {
if (response.code === 200) {
@@ -590,11 +602,11 @@ export default {
this.initChartTable(chartParams)
},
initChartTable (chartParams) {
const queryParams = { startTime: parseInt(this.timeFilter.startTime / 1000), endTime: parseInt(this.timeFilter.endTime / 1000), limit: this.table.limit, order: this.table.orderBy }
const queryParams = { startTime: parseInt(this.timeFilter.startTime / 1000), endTime: parseInt(this.timeFilter.endTime / 1000), limit: this.table.limit, order: this.table.orderBy, ...this.entity }
get(replaceUrlPlaceholder(chartParams.url, queryParams)).then(response => {
if (response.code === 200) {
this.table.tableColumns = allTableTitle['tableTitles' + this.chart.id]
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)
}
})

View File

@@ -1,5 +1,14 @@
<template>
<div style="padding: 10px 0 20px 20px;">
<div v-if="!$_.isEmpty(tabs)" class="entity-detail-tool">
<div>
<i class="cn-icon cn-icon-arrow-left-circle"></i>&nbsp;
<span>{{typeName}}&nbsp;{{$t('overall.detail')}}</span>
</div>
<el-radio-group v-model="tab" size="mini">
<el-radio-button v-for="tab in tabs" :key="tab.key" :label="tab.label"></el-radio-button>
</el-radio-group>
</div>
<div class="cn-panel" id="cn-panel">
<div class="panel__time">
<DateTimeRange class="date-time-range" :start-time="timeFilter.startTime" :end-time="timeFilter.endTime" ref="dateTimeRange" @change="reload"/>
@@ -37,12 +46,14 @@ import { getNowTime } from '@/utils/date-util'
import Chart from './Chart'
import DateTimeRange from '@/components/common/TimeRange/DateTimeRange'
import TimeRefresh from '@/components/common/TimeRange/TimeRefresh'
import _ from 'lodash'
export default {
name: 'Panel',
props: {
typeName: String,
entity: Object
entity: Object,
tabs: Array
},
components: {
Chart,
@@ -58,6 +69,10 @@ export default {
await this.init()
},
setup (props, ctx) {
let tab = ''
if (!_.isEmpty(props.tabs)) {
tab = ref(props.tabs[0].key)
}
// data
const dateRangeValue = 60
const { startTime, endTime } = getNowTime(dateRangeValue)
@@ -70,7 +85,8 @@ export default {
panelType,
panel,
timeFilter,
api
api,
tab
}
},
methods: {

View File

@@ -36,7 +36,7 @@
></entity-list>
</div>
</div>
<cn-panel v-else :entity="currentEntity" :type-name="typeName"></cn-panel>
<cn-panel v-else :entity="currentEntity" :type-name="typeName" :tabs="panelTabs"></cn-panel>
</template>
<script>
@@ -70,7 +70,8 @@ export default {
listData: [],
showDetail: false,
typeName: '',
currentEntity: {}
currentEntity: {},
panelTabs: []
}
},
components: {
@@ -239,9 +240,10 @@ export default {
}
}
},
entityDetail (entity) {
entityDetail (entity, tabs) {
this.typeName = `${this.filterType.toLowerCase()}EntityDetail`
this.currentEntity = entity
this.panelTabs = tabs
this.showDetail = true
}
},