Compare commits

..

17 Commits

Author SHA1 Message Date
lijinyang
53c24fe51b Update .gitlab-ci.yml 2023-02-14 15:02:20 +08:00
chenjinsong
2aa7f6edfb fix: 修复ip实体详情右上角饼图请求参数太长导致请求失败的问题 2023-02-10 15:23:19 +08:00
chenjinsong
6ed9c4f5fe fix: 修复detection顶部柱状图数据没有按时间排序的问题,修复app图逻辑问题 2023-02-10 14:20:07 +08:00
chenjinsong
6f8631f947 fix: whois字段问题 2023-02-09 17:15:21 +08:00
chenjinsong
63ab36f4d2 fix: 单位转换方法参数为0时不返回单位 2023-02-08 15:54:32 +08:00
chenjinsong
cccc1f0e6a CN-885 feat: whois字段调整 2023-02-08 15:24:18 +08:00
chenjinsong
4651709529 fix: logo变更、国际化切换按钮隐藏 2023-02-08 11:30:23 +08:00
chenjinsong
6ab98be4c8 fix: 修复加密DNS协议支持情况统计图表数据颠倒的问题 2023-02-08 10:55:11 +08:00
陈劲松
7b96f979a4 Merge branch 'cherry-pick-2b67cb4a' into '6suo'
fix: detection-performanceEvent去除对eventId的格式转换

See merge request cyber-narrator/cn-ui!20
2023-02-07 09:18:19 +00:00
刘洪洪
a59bff2cb7 fix: detection-performanceEvent去除对eventId的格式转换
(cherry picked from commit 2b67cb4a0b)
2023-02-07 17:18:13 +08:00
chenjinsong
04651581fe fix: 更新log外链链接 2023-02-03 18:46:08 +08:00
chenjinsong
84ca05dccc fix: 修复dns仪表盘切换时间不生效的问题 2023-02-03 16:38:24 +08:00
chenjinsong
780de66ddf fix: 隐藏代理和chart入口 2023-02-03 16:28:02 +08:00
chenjinsong
9205d7645d fix: 优化折线图效果 2023-02-03 16:26:46 +08:00
chenjinsong
ec486fe930 fix: 修复地图资源路径拼写错误的问题 2023-02-03 11:08:35 +08:00
chenjinsong
12c31b5bf6 feat: 6所相关内容,增加折线图左侧边距 2023-02-02 18:38:33 +08:00
chenjinsong
96591cb9ef feat: 6所相关内容 2023-02-02 17:55:03 +08:00
52 changed files with 547 additions and 1719 deletions

View File

@@ -1,8 +1,7 @@
module.exports = {
env: {
browser: true,
es2021: true,
jest: true
es2021: true
},
extends: [
'plugin:vue/vue3-essential',

View File

@@ -2,7 +2,6 @@
stages:
- gen_git-log
- build_project
- test
- build_image
cache:
@@ -11,7 +10,7 @@ cache:
- package.json
paths:
- node_modules
# - dist/
- dist/
before_script:
- export CNUI_TAG=$(date +%Y%m%d%H%M%S)
@@ -30,7 +29,7 @@ generate_git-log:
- public/index.html
- public/git-log.html
only:
- dev-test
- 6suo
tags:
- galaxy
@@ -42,30 +41,13 @@ build_project:
- cnpm install --save-dev --unsafe-perm
- echo "npm run build"
- cnpm run build
artifacts:
name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME"
when: on_success
paths:
- dist/
only:
- dev-test
- 6suo
- tags
tags:
- galaxy
test:
stage: test
script:
- cnpm run test
when: on_success
only:
- dev-test
tags:
- galaxy
build_image:
dependencies:
- build_project
stage: build_image
script:
- echo "docker build"
@@ -76,14 +58,12 @@ build_image:
- sudo docker push 192.168.40.153:9080/cyber-narrator/cn-ui-$CI_COMMIT_REF_NAME:$CNUI_TAG
when: on_success
only:
- dev-test
- 6suo
tags:
- galaxy
build_release_image:
dependencies:
- build_project
stage: build_image
script:
- echo 'tag名称是'

View File

@@ -1,4 +1,5 @@
var BASE_CONFIG = {
baseUrl: 'http://192.168.44.54:8090/',
version: '2.0.2021.05.11.19.43'
baseUrl: 'http://192.168.44.54:8093/',
version: '23.02.08',
logUrl: 'http://192.168.44.114:8088/superset/explore/?r=12&standalone=1'
}

View File

@@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>images/logo.svg">
<script src="config.js"></script>
<title>Cyber Narrator</title>
<title>域名解析服务监测系统</title>
</head>
<body class="theme-light">
<noscript>

View File

@@ -1,9 +1,7 @@
<template>
<div class="logins">
<div class="inside">
<div class="title">
<img src="../public/images/logo-title.svg" />
</div>
<div class="title">域名解析服务监测系统</div>
<el-form class="login__box">
<el-form-item>
<el-input
@@ -193,12 +191,12 @@ export default {
}
.title {
margin-top: 65px;
margin-top: 90px;
padding: 0 70px;
color: white;
font-size: 40px;
text-align: center;
}
.title > img {
height: 135px;
}
.login__box {
display: flex;
justify-content: center;

View File

@@ -98,6 +98,8 @@
.domain-detail-list {
display: table;
width: 100%;
height: 100%;
overflow: auto;
.domain-detail-list__row {
display: table-row;

View File

@@ -1,4 +1,5 @@
.cn-chart__whois {
overflow: auto;
height: 100%;
}

View File

@@ -7,7 +7,7 @@
display: flex;
&.panel__time--scrolled-out {
position: fixed;
top: 70px;
top: 120px;
padding-right: 10px;
}
&>div {
@@ -18,7 +18,7 @@
.chart-list {
&.chart-list--screen {
display: grid;
height: calc(100vh - 90px);
height: calc(100vh - 130px);
width: 100%;
grid-template-columns: repeat(30,1fr);
grid-template-rows: repeat(19,1fr);

View File

@@ -98,11 +98,11 @@
//top: 0;
//left: 0;
display: flex;
.line-value-tabs.mousemove-cursor {
.line-value-mpackets.mousemove-cursor {
border-top: 4px solid #D3D0D8;
z-index: 0;
}
.line-value-tabs {
.line-value-mpackets {
cursor: pointer;
padding: 16px 0 0 20px;
border-top: 4px solid transparent;
@@ -122,10 +122,10 @@
}
}
}
.line-value-tabs-name {
.line-value-mpackets-name {
position: relative;
display: flex;
.tabs-name {
.mpackets-name {
flex: 1;
padding-left: 19px;
}

View File

@@ -141,6 +141,7 @@ export default {
hoverError (e) {
// const dom = document.getElementById('error-content')
// if (dom) {
// console.log('---', dom.clientHeight)
// }
}
}

View File

@@ -98,6 +98,7 @@ export default {
if (val && val.value !== -1) {
// 切换轮询请求时间频率时,发现有未结束的请求,终止请求
const cancelList = this.$store.state.panel.httpCancel
// console.log('timeRefresh.vue------setRefresh------查看终止数量', cancelList, cancelList.length)
if (cancelList.length > 0) {
cancelList.forEach((cancel, index) => {
cancel()

View File

@@ -4,12 +4,12 @@
<div class="banner__left">
<span @click="shrink" class="shrink-button" :class="{'shrink-button--collapse': showMenu}"><i
class="cn-icon cn-icon-navigation"></i></span>
<img alt="loading..." height="26" :src="logo?logo:require('../../assets/img/logo-header.svg')" @click="jump('/panel/networkOverview', '', '', 0)" style="cursor: pointer"/>
<span style="color: white; font-size: 20px;">域名解析服务监测系统</span>
</div>
<!--个人操作-->
<div class="personal">
<el-dropdown>
<div class="header-menu--item"><i class="cn-icon cn-icon-language"></i></div>
<!-- <el-dropdown>
<div class="header-menu&#45;&#45;item"><i class="cn-icon cn-icon-language"></i></div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item>
@@ -24,7 +24,7 @@
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-dropdown>-->
<el-dropdown>
<div class='login-user header-menu--item'>{{ username }}&nbsp;<i class="cn-icon cn-icon-arrow-down"></i></div>
<template #dropdown>

View File

@@ -19,6 +19,7 @@
v-model="editObject.config.timeConfig.type"
class="right-box__select"
collapse-tags
:disabled="!!editObject.id"
placeholder=" "
popper-class="right-box-select-dropdown right-box-select-report "
size="small"
@@ -30,6 +31,7 @@
</el-select>
<template v-if="editObject.config.timeConfig.type === 'this'">
<el-select id="reportBoxTimeUnitSelect"
:disabled="!!editObject.id"
v-model="editObject.config.timeConfig.unit"
class="right-box__select"
collapse-tags
@@ -43,7 +45,7 @@
</el-select>
</template>
<div v-else-if="editObject.config.timeConfig.type === 'last' || editObject.config.timeConfig.type === 'previous'" style="display: flex;">
<el-input v-model.number="editObject.config.timeConfig.offset" size="small" class="el-input-single" placeholder=" ">
<el-input v-model.number="editObject.config.timeConfig.offset" size="small" class="el-input-single" placeholder=" " :disabled="!!editObject.id">
<template #prepend><i @click="timeOffsetHandle('m')" class="cn-icon cn-icon-a-"></i></template>
<template #append><i @click="timeOffsetHandle('p')" class="cn-icon cn-icon-a-1"></i></template>
</el-input>
@@ -51,6 +53,7 @@
v-model="editObject.config.timeConfig.unit"
class="right-box__select right-box__select-single"
collapse-tags
:disabled="!!editObject.id"
placeholder=" "
popper-class="right-box-select-dropdown el-select-last"
size="small"
@@ -70,6 +73,7 @@
v-model="editObject.config.startTime"
size="small"
:format="dateFormat"
:disabled="!!editObject.id"
:disabled-date="startDisabledDate"
@change="startTimeChang"
prefix-icon="cn-icon cn-icon-shijian"
@@ -88,6 +92,7 @@
v-model="editObject.config.endTime"
size="small"
:format="dateFormat"
:disabled="!!editObject.id"
:disabled-date="endDisabledDate"
@change="endTimeChange"
prefix-icon="cn-icon cn-icon-shijian"
@@ -98,41 +103,41 @@
</div>
</el-form-item >
<el-form-item class="el-height">
<el-checkbox v-model="scheduleChecked" :disabled="editObject.config.timeConfig.type === 'customize'" :label="$t('report.enableTimeSchedule')" size="large" />
<el-checkbox v-model="scheduleChecked" :disabled="editObject.config.timeConfig.type === 'customize' || !!editObject.id" :label="$t('report.enableTimeSchedule')" size="large" />
</el-form-item>
<!--Enable time schedule-->
<el-form-item prop="enableTimeSchedule" v-if="scheduleChecked">
<div class="enable-tab">
<div class="enable-tabs" @click="scheduleTypeChange(type.value)" v-for="type in scheduleTypeList" :key="type.value" :class="{'active': scheduleType === type.value}">{{$t(type.name)}}</div>
<div class="enable-tabs" @click="editObject.id ? null : (scheduleType = type.value)" v-for="type in scheduleTypeList" :key="type.value" :class="{'active': scheduleType === type.value, 'disable': editObject.id}">{{$t(type.name)}}</div>
</div>
<div class="enable-tabs-daily" v-if="scheduleType === scheduleTypeList[0].value">
<div class="enable-tabs-custom">{{$t('report.customEvery')}}</div>
<el-input v-model.number="editObject.config.schedulerConfig.interval" size="small" placeholder=" " style="margin-top: 0.3125rem;">
<el-input v-model.number="editObject.config.schedulerConfig.interval" size="small" placeholder=" " style="margin-top: 0.3125rem;" :disabled="!!editObject.id">
<template #append>{{$t('report.day')}}</template>
</el-input>
</div>
<div class="enable-tabs-weekly" v-else-if="scheduleType === scheduleTypeList[1].value">
<div class="enable-tabs-weekly" v-else-if="scheduleType === scheduleTypeList[1].value" :disabled="!!editObject.id">
<!-- 每隔几周暂时隐藏 -->
<!-- <div class="enable-tabs-custom">{{$t('report.customEvery')}}</div>
<el-input v-model="editObject.config.schedulerConfig.interval" size="small" placeholder="Please input">
<template #append>{{$t('report.week')}}</template>
</el-input>-->
<el-checkbox-group v-model="editObject.config.schedulerConfig.weekDates" style="margin-top: 0.3125rem">
<el-checkbox-group v-model="editObject.config.schedulerConfig.weekDates" style="margin-top: 0.3125rem" :disabled="!!editObject.id">
<el-checkbox v-for="(item, index) in weekdayList" :key="index" :label="item.value">{{$t(item.name)}}</el-checkbox>
</el-checkbox-group>
</div>
<!-- -->
<div class="enable-tabs-per-month" v-else-if="scheduleType === scheduleTypeList[2].value">
<div class="enable-month-tab">
<div class="enable-month-tabs" @click="monthScheduleType = 'daily'" :class="{'active': monthScheduleType === 'daily'}">{{$t('report.date')}}</div>
<div class="enable-month-tabs" @click="monthScheduleType = 'weekly'" :class="{'active': monthScheduleType === 'weekly'}">{{$t('report.week')}}</div>
<el-checkbox v-model="monthIsCycle" :label="$t('report.cycle')" size="large"/>
<div class="enable-month-tabs" @click="editObject.id ? null : (monthScheduleType = 'daily')" :class="{'active': monthScheduleType === 'daily', 'disable': editObject.id}">{{$t('report.date')}}</div>
<div class="enable-month-tabs" @click="editObject.id ? null : (monthScheduleType = 'weekly')" :class="{'active': monthScheduleType === 'weekly', 'disable': editObject.id}">{{$t('report.week')}}</div>
<el-checkbox v-model="monthIsCycle" :label="$t('report.cycle')" size="large" :disabled="!!editObject.id"/>
</div>
<div class="enable-month-data-tab">
<!-- 自定义月循环 -->
<template v-if="monthIsCycle">
<div class="enable-tabs-custom">{{$t('report.customEvery')}}</div>
<el-input v-model="editObject.config.schedulerConfig.interval" size="small" placeholder=" " style="margin-top: 0.3125rem;">
<el-input v-model="editObject.config.schedulerConfig.interval" size="small" placeholder=" " style="margin-top: 0.3125rem;" :disabled="!!editObject.id">
<template #append>{{$t('report.month')}}</template>
</el-input>
</template>
@@ -140,8 +145,8 @@
<template v-else>
<div class="enable-month-moon-custom">{{$t('report.custom')}}</div>
<div class="enable-month-all">
<el-checkbox v-model="monthCheckedAll" class="enable-month-all-months" :indeterminate="monthIsIndeterminate" @change="monthCheckAllChange" :label="$t('report.allMonths')"/>
<el-checkbox-group v-model="editObject.config.schedulerConfig.months" @change="monthCheckChange">
<el-checkbox v-model="monthCheckedAll" class="enable-month-all-months" :indeterminate="monthIsIndeterminate" @change="monthCheckAllChange" :label="$t('report.allMonths')" :disabled="!!editObject.id"/>
<el-checkbox-group v-model="editObject.config.schedulerConfig.months" @change="monthCheckChange" :disabled="!!editObject.id">
<el-checkbox v-for="(item, index) in monthList" :key="index" :label="item.value">{{$t(item.name)}}</el-checkbox>
</el-checkbox-group>
</div>
@@ -149,8 +154,8 @@
<!-- 按日期 -->
<template v-if="monthScheduleType === 'daily'">
<div class="enable-month-data-tabs">
<el-checkbox v-model="dateCheckedAll" :indeterminate="dateIsIndeterminate" @change="dateCheckAllChange" :label="$t('report.all')" size="large"/>
<el-checkbox-group v-model="editObject.config.schedulerConfig.monthDates" @change="dateCheckChange">
<el-checkbox v-model="dateCheckedAll" :indeterminate="dateIsIndeterminate" @change="dateCheckAllChange" :label="$t('report.all')" size="large" :disabled="!!editObject.id"/>
<el-checkbox-group v-model="editObject.config.schedulerConfig.monthDates" @change="dateCheckChange" :disabled="!!editObject.id">
<el-checkbox v-for="item in dateList" :key="item" :label="item"/>
</el-checkbox-group>
</div>
@@ -163,6 +168,7 @@
class="right-box__select"
multiple
placeholder=" "
:disabled="!!editObject.id"
popper-class="right-box-select-dropdown right-box-select-report"
size="small"
@change="()=>{ this.$forceUpdate() }">
@@ -171,8 +177,8 @@
</template>
</el-select>
<div class="enable-month-week">
<el-checkbox v-model="monthWeekdayCheckedAll" class="enable-month-week-all" :label="$t('report.all')" :indeterminate="monthWeekdayIsIndeterminate" @change="monthWeekdayCheckAllChange" size="large"/>
<el-checkbox-group v-model="editObject.config.schedulerConfig.weekDates" @change="monthWeekdayCheckChange">
<el-checkbox v-model="monthWeekdayCheckedAll" class="enable-month-week-all" :label="$t('report.all')" :indeterminate="monthWeekdayIsIndeterminate" @change="monthWeekdayCheckAllChange" size="large" :disabled="!!editObject.id"/>
<el-checkbox-group v-model="editObject.config.schedulerConfig.weekDates" @change="monthWeekdayCheckChange" :disabled="!!editObject.id">
<el-checkbox v-for="(item, index) in weekdayList" :key="index" :label="item.value">{{$t(item.name)}}</el-checkbox>
</el-checkbox-group>
</div>
@@ -222,7 +228,7 @@
:disabled="!!editObject.id"
popper-class="right-box-select-dropdown right-box-select-report"
size="small"
>
@change="typeChange">
<template v-for="category in categoryList" :key="category.id">
<el-option :label="category.name" :value="category.id"></el-option>
</template>
@@ -407,14 +413,20 @@ export default {
watch: {
scheduleType (n, o) {
this.editObject.config.schedulerConfig.type = n
this.cleanScheduleConfig()
if (!this.editObject.id) {
this.cleanScheduleConfig()
}
},
scheduleChecked (n) {
this.editObject.config.isScheduler = n ? 1 : 0
this.cleanScheduleConfig()
if (!this.editObject.id) {
this.cleanScheduleConfig()
}
},
monthScheduleType (n) {
this.cleanScheduleConfig()
if (!this.editObject.id) {
this.cleanScheduleConfig()
}
},
monthIsCycle (n) {
if (!this.editObject.id) {
@@ -548,13 +560,15 @@ export default {
this.editObject.config.timeConfig.offset--
}
}
},
typeChange (id) {
},
cleanScheduleConfig () {
this.editObject.config.schedulerConfig.monthDates = []
this.editObject.config.schedulerConfig.weekDates = []
this.editObject.config.schedulerConfig.months = []
this.editObject.config.schedulerConfig.monthWeekDates = []
this.editObject.config.schedulerConfig.interval = 1
this.monthIsCycle = true
this.dateCheckedAll = false
this.dateIsIndeterminate = false
@@ -568,9 +582,6 @@ export default {
this.scheduleChecked = false
}
},
scheduleTypeChange (val) {
this.scheduleType = val
},
save () {
if (this.blockOperation.save) { return }
this.blockOperation.save = true

View File

@@ -19,6 +19,11 @@ const routes = [
path: '/panel/:typeName',
component: () => import('@/views/charts2/Panel')
},
{
name: 'dns6',
path: '/dns6/:typeName',
component: () => import('@/views/charts/Panel')
},
{
path: '/report/builtIn',
component: () => import('@/views/report/reportTest')

View File

@@ -63,7 +63,8 @@ export const panelTypeAndRouteMapping = {
cryptocurrency: 7,
ipDrillDownTest: 8,
linkMonitor: 14,
linkMonitorDrillDown: 15
linkMonitorDrillDown: 15,
dns6: 18
}
/* operationLog state 执行状态属性 值与名称之间的映射 */
@@ -1554,7 +1555,7 @@ export const npmCategoryInfoMapping = [
// 整屏滚动的路径映射
export const wholeScreenRouterMapping = {
dns: '/panel/dnsServiceInsights'
dns: '/dns6/dns6'
}
export const themeData = [

View File

@@ -17,6 +17,9 @@ function asciiCompute (num, ascii = 1000, units, dot = 2) {
return ['', '']
}
num = Number(num)
if (num === 0) {
return [0, '']
}
let carry = 0
if (num > 1) {
const log = Math.log(num) / Math.log(ascii)

View File

@@ -38,11 +38,6 @@ export default {
i18n: 'overall.operationLog',
path: '/administration/operationLog',
icon: 'cn-icon cn-icon-operation-log'
},
{
i18n: 'I18n',
path: '/administration/i18n',
icon: 'cn-icon cn-icon-i18n'
}
]
}

View File

@@ -23,7 +23,7 @@ export default {
const boxDom = document.getElementById('frame-box')
const dom = document.getElementById('frame')
const height = boxDom.offsetHeight
dom.src = `http://192.168.44.114:8088/superset/explore/?r=15&standalone=1&height=${height || 800}`
dom.src = BASE_CONFIG.logUrl + '&height=' + (height + 100)
}
}
</script>

View File

@@ -150,12 +150,14 @@ export default {
if (panels && panels.length > 0) {
this.panel = panels[0]
}
// console.log(this.panel)
if (this.panel.id) {
if (this.panel.params) {
this.panel.params = JSON.parse(this.panel.params)
} else {
this.panel.params = {}
}
// console.log(this.panel)
const allCharts = (await getChartList({ panelId: this.panel.id, pageSize: -1 })).map(chart => {
chart.i = chart.id
this.recursionParamsConvert(chart)

View File

@@ -11,20 +11,40 @@
<div class="domain-detail-list__content">{{ $_.get(chartData, "org") || '-'}}</div>
</div>
<div class="domain-detail-list__row">
<div class="domain-detail-list__label">Email</div>
<div class="domain-detail-list__label">注册机构邮箱</div>
<div class="domain-detail-list__content">{{ $_.get(chartData, "email") || '-'}}</div>
</div>
<div class="domain-detail-list__row">
<div class="domain-detail-list__label">{{$t('overall.country')}}</div>
<div class="domain-detail-list__label">注册机构电话</div>
<div class="domain-detail-list__content">{{ $_.get(chartData, "domainWhoisPhone") || '-'}}</div>
</div>
<div class="domain-detail-list__row">
<div class="domain-detail-list__label">注册国家</div>
<div class="domain-detail-list__content">{{ $_.get(chartData, "country") || '-'}}</div>
</div>
<div class="domain-detail-list__row">
<div class="domain-detail-list__label">{{$t('entities.creationDate')}}</div>
<div class="domain-detail-list__content">{{ dateFormatByAppearance($_.get(chartData, "createTime") * 1) || '-'}}</div>
<div class="domain-detail-list__label">注册地邮编</div>
<div class="domain-detail-list__content">{{ $_.get(chartData, "domainWhoisPostcode") || '-'}}</div>
</div>
<div class="domain-detail-list__row">
<div class="domain-detail-list__label">{{$t('entities.expirationDate')}}</div>
<div class="domain-detail-list__content">{{ dateFormatByAppearance($_.get(chartData, "expirationTime") * 1) || '-'}}</div>
<div class="domain-detail-list__label">{{$t('entities.creationDate')}}</div>
<div class="domain-detail-list__content">{{ $_.get(chartData, "createTime") ? dateFormatByAppearance($_.get(chartData, "createTime") * 1) : '-'}}</div>
</div>
<div class="domain-detail-list__row">
<div class="domain-detail-list__label">过期时间</div>
<div class="domain-detail-list__content">{{ $_.get(chartData, "expirationTime") ? dateFormatByAppearance($_.get(chartData, "expirationTime") * 1) : '-'}}</div>
</div>
<div class="domain-detail-list__row">
<div class="domain-detail-list__label">主办单位名称</div>
<div class="domain-detail-list__content">{{ $_.get(chartData, "domainIcpCompanyName") || '-'}}</div>
</div>
<div class="domain-detail-list__row">
<div class="domain-detail-list__label">主办单位性质</div>
<div class="domain-detail-list__content">{{ $_.get(chartData, "domainIcpCompanyType") || '-'}}</div>
</div>
<div class="domain-detail-list__row">
<div class="domain-detail-list__label">网站备案号</div>
<div class="domain-detail-list__content">{{ $_.get(chartData, "domainIcpSiteLicense") || '-'}}</div>
</div>
</div>
</div>

View File

@@ -126,7 +126,7 @@ export default {
? legendMapping[
`${this.entity && this.entity.ip ? 'ip_' : ''}${r.legend}`
]
: (legendMapping[r.legend] ? legendMapping[r.legend] : humpToSpace(r.legend)),
: (legendMapping[r.legend] ? legendMapping[r.legend] : r.legend),
data: r.values.map((v) => [
Number(v[0]) * 1000,
Number(v[1]),

View File

@@ -35,10 +35,12 @@ export default {
initEcharts (id) {
this.initDom(id, 2)
const chartParams = this.chartInfo.params
const domains = this.chartData.map(function (item, i) {
let domains = this.chartData.map(function (item, i) {
return item.domain
}).join(',')
// 参数字符串限制长度在4300以内。经测试超过4600左右会报错
domains = domains.substring(0, 4300)
domains = domains.substring(0, domains.lastIndexOf(','))
const byType = new Promise(resolve => {
get(replaceUrlPlaceholder(chartParams.byCategoryUrl, { domains: domains })).then(response => {
if (response.code === 200) {
@@ -47,7 +49,7 @@ export default {
} else {
// this.noData0 = false
// chartOption = this.$_.cloneDeep(this.chartOption)
const data = response.data.result.sort(reverseSortBy('uniqDomains')).map(d => {
const originalData = response.data.result.sort(reverseSortBy('uniqDomains')).map(d => {
return {
data: d,
name: d.categoryName,
@@ -55,6 +57,22 @@ export default {
unitType: chartParams.unitType
}
})
const data = originalData.filter((d, i) => i < 5)
let otherValue = 0
originalData.forEach((d, i) => {
if (i > 4) {
otherValue += parseInt(d.uniqDomains)
}
})
data.push({
data: {
uniqDomains: otherValue,
categoryName: 'other'
},
name: 'other',
value: otherValue,
unitType: chartParams.unitType
})
this.chartOption.series[0].data = data
}
}

View File

@@ -202,10 +202,10 @@
</div>
</div>
<div class="content__data-protocol-value">
<div class="content__data-protocol-value-title">{{$t('protocol.requestVolume')}}</div>
<div class="content__data-protocol-value-num">{{unitConvert($_.get(chartData, 'bytes'), chartInfo.params.unitType).join('')}}</div>
<div class="content__data-protocol-value-title">{{$t('protocol.totalFlow')}}</div>
<div class="content__data-protocol-value-num">{{unitConvert($_.get(chartData, 'count'), chartInfo.params.unitType).join('')}}</div>
</div>
<div class="content__data-protocol-percent"><span>{{$t('protocol.proportion')}}</span>&nbsp;<span>{{unitConvert($_.get(chartData, 'bytesPercent'), unitTypes.percent).join('')}}</span></div>
<div class="content__data-protocol-percent"><span>{{$t('protocol.proportion')}}</span>&nbsp;<span>{{unitConvert($_.get(chartData, 'countPercent'), unitTypes.percent).join('')}}</span></div>
</div>
<div class="content__data-protocol">
<div class="content__data-protocol-all">
@@ -214,10 +214,10 @@
</div>
</div>
<div class="content__data-protocol-value">
<div class="content__data-protocol-value-title">{{$t('protocol.totalFlow')}}</div>
<div class="content__data-protocol-value-num">{{unitConvert($_.get(chartData, 'count'), chartInfo.params.unitType).join('')}}</div>
<div class="content__data-protocol-value-title">{{$t('protocol.requestVolume')}}</div>
<div class="content__data-protocol-value-num">{{unitConvert($_.get(chartData, 'bytes'), unitTypes.byte).join('')}}</div>
</div>
<div class="content__data-protocol-percent"><span>{{$t('protocol.proportion')}}</span>&nbsp;<span>{{unitConvert($_.get(chartData, 'countPercent'), unitTypes.percent).join('')}}</span></div>
<div class="content__data-protocol-percent"><span>{{$t('protocol.proportion')}}</span>&nbsp;<span>{{unitConvert($_.get(chartData, 'bytesPercent'), unitTypes.percent).join('')}}</span></div>
</div>
</div>
</div>

View File

@@ -64,11 +64,11 @@ export const legendMapping = {
ip_packets_sent_rate: i18n.global.t('trafficSummary.packetsPerSecondS2c'),
dnsLatency: i18n.global.t('dns.latency'),
queryRate: i18n.global.t('dns.query.rate'),
formatErrorRate: i18n.global.t('dns.formatErrorRate'),
serverFailureRate: i18n.global.t('dns.serverFailureRate'),
nonExistentDomainRate: i18n.global.t('dns.nonExistentDomainRate'),
notImplementedRate: i18n.global.t('dns.notImplementedRate'),
queryRefusedRate: i18n.global.t('dns.queryRefusedRate'),
formatErrorRate: 'FormErr',
serverFailureRate: 'ServFail',
nonExistentDomainRate: 'NXDomain',
notImplementedRate: 'NotImp',
queryRefusedRate: 'Refused',
sequenceGapLossPercent: i18n.global.t('entity.ip.sequenceGapLossPercent'),
establishLatency: i18n.global.t('entity.ip.establishLatency'),
httpResponseLatency: i18n.global.t('entity.ip.httpResponseLatency'),

View File

@@ -22,6 +22,9 @@ export const line = {
},
yAxis: {
type: 'value',
splitLine: {
show: false
},
axisLabel: {
formatter: function (value) {
return unitConvert(value, unitTypes.number, null, null, 0).join(' ')
@@ -30,7 +33,7 @@ export const line = {
},
animation: false,
grid: {
left: 55,
left: 60,
bottom: 30,
top: 20,
right: 25
@@ -62,7 +65,7 @@ export const line = {
{
name: '',
type: 'line',
smooth: false,
smooth: true,
symbol: 'none',
data: [],
markLine: {}

View File

@@ -5,17 +5,17 @@
<div class="line-header-left">
<div class="line-value-active" v-if="lineTab"></div>
<div class="line-value">
<div class="line-value-tabs"
<div class="line-value-mpackets"
v-show="item.show"
:class=" {'is-active': lineTab === item.class, 'mousemove-cursor': mousemoveCursor === item.class}"
v-for="(item, index) in tabs"
v-for="(item, index) in mpackets"
:key="index"
@mouseenter="mouseenter(item)"
@mouseleave="mouseleave(item)"
@click="activeChange(item, index)">
<div class="line-value-tabs-name">
<div class="line-value-mpackets-name">
<div :class="item.class"></div>
<div class="tabs-name">{{$t(item.name)}}</div>
<div class="mpackets-name">{{$t(item.name)}}</div>
</div>
<div class="line-value-unit">
<span class="line-value-unit-number">{{unitConvert(item.analysis.avg, unitTypes.number)[0]}}</span>
@@ -126,7 +126,7 @@ export default {
label: 'Maximum'
}
],
tabs: [
mpackets: [
{ analysis: {}, name: 'network.total', class: 'total', show: true, invertTab: true, positioning: 0, data: [], unitType: '' },
{ analysis: {}, name: 'network.inbound', class: 'inbound', show: true, invertTab: true, positioning: 1, data: [], unitType: '' },
{ analysis: {}, name: 'network.outbound', class: 'outbound', show: true, invertTab: true, positioning: 2, data: [], unitType: '' }
@@ -202,7 +202,7 @@ export default {
this.isNoData = res.data.result.length === 0
if (this.isNoData) {
this.lineTab = ''
this.tabs = [
this.mpackets = [
{ analysis: {}, name: 'network.total', class: 'total', show: true, invertTab: true, positioning: 0, data: [], unitType: '' },
{ analysis: {}, name: 'network.inbound', class: 'inbound', show: true, invertTab: true, positioning: 1, data: [], unitType: '' },
{ analysis: {}, name: 'network.outbound', class: 'outbound', show: true, invertTab: true, positioning: 2, data: [], unitType: '' }
@@ -323,7 +323,7 @@ export default {
this.chartOption.tooltip.formatter = (params) => {
params.forEach(t => {
t.seriesName = this.$t(t.seriesName)
this.tabs.forEach(e => {
this.mpackets.forEach(e => {
if (this.$t(e.name) === t.seriesName) {
t.borderColor = chartColor3[e.positioning]
}
@@ -366,16 +366,16 @@ export default {
legendSelectChange (item, index, val) {
if (index === 'index') {
this.dispatchLegendSelectAction(item.name)
} else if (this.tabs[index] && this.tabs[index].name === item.name) {
} else if (this.mpackets[index] && this.mpackets[index].name === item.name) {
this.dispatchLegendSelectAction(item.name)
this.tabs.forEach((t) => {
this.mpackets.forEach((t) => {
if (t.name !== item.name) {
this.dispatchLegendUnSelectAction(t.name)
}
})
}
if (val === 'active') {
this.tabs.forEach(t => {
this.mpackets.forEach(t => {
if (item.name === t.name) {
t.invertTab = !t.invertTab
} else {
@@ -387,7 +387,7 @@ export default {
} else {
this.lineTab = t.class
}
this.tabs.forEach((e) => {
this.mpackets.forEach((e) => {
this.dispatchLegendSelectAction(e.name)
})
}
@@ -395,8 +395,8 @@ export default {
}
},
handleActiveBar () {
if (document.querySelector('.network .line-value-tabs.is-active')) {
const { offsetLeft, clientWidth, clientLeft } = document.querySelector('.network .line-value-tabs.is-active')
if (document.querySelector('.network .line-value-mpackets.is-active')) {
const { offsetLeft, clientWidth, clientLeft } = document.querySelector('.network .line-value-mpackets.is-active')
const activeBar = document.querySelector('.network .line-value-active')
activeBar.style.cssText += `width: ${clientWidth}px; left: ${offsetLeft + this.leftOffset + clientLeft}px;`
}
@@ -409,7 +409,7 @@ export default {
this.lineTab = ''
this.handleActiveBar()
this.showMarkLine = !this.showMarkLine
this.tabs.forEach((e) => {
this.mpackets.forEach((e) => {
if (!e.invertTab) {
e.invertTab = true
}
@@ -421,9 +421,9 @@ export default {
let echartsData
const chartOption = this.myChart.getOption()
if (this.lineTab) {
echartsData = this.tabs.filter(t => t.show === true && t.invertTab === false)
echartsData = this.mpackets.filter(t => t.show === true && t.invertTab === false)
} else {
echartsData = this.tabs.filter(t => t.show === true)
echartsData = this.mpackets.filter(t => t.show === true)
}
if (this.lineRefer === 'Average' && this.showMarkLine) {
chartOption.series.forEach((t, i) => {
@@ -488,13 +488,13 @@ export default {
})
}
lineData.splice(0, 1)
const tabs = _.cloneDeep(this.tabs)
const mpackets = _.cloneDeep(this.mpackets)
if (val === 'Queries/s') {
lineData.forEach((d, i) => {
tabs[i].data = d.values
tabs[i].analysis = d.analysis
mpackets[i].data = d.values
mpackets[i].analysis = d.analysis
})
tabs.forEach((e, i) => {
mpackets.forEach((e, i) => {
if (i !== 0) {
e.show = false
}
@@ -503,11 +503,11 @@ export default {
this.lineTab = 'total'
this.legendSelectChange(e, 0)
})
this.tabs = tabs
this.echartsInit(this.tabs, true)
this.mpackets = mpackets
this.echartsInit(this.mpackets, true)
} else {
const unit = 'bps'
this.legendInit(lineData, active, show, unit, tabs)
this.legendInit(lineData, active, show, unit, mpackets)
}
},
legendInit (data, active, show, type, dnsData) {
@@ -535,14 +535,14 @@ export default {
}
}
})
this.tabs = dnsData
this.mpackets = dnsData
if (num === 3) {
dnsData[0].invertTab = false
this.lineTab = 'total'
this.legendSelectChange(dnsData[0], 0)
this.echartsInit(this.tabs)
this.echartsInit(this.mpackets)
} else {
this.echartsInit(this.tabs, show)
this.echartsInit(this.mpackets, show)
if (!this.lineRefer) this.lineRefer = 'Average'
}
}
@@ -550,7 +550,7 @@ export default {
mounted () {
this.timer = setTimeout(() => {
if (this.lineTab) {
const data = this.tabs.find(t => t.class === this.lineTab)
const data = this.mpackets.find(t => t.class === this.lineTab)
this.activeChange(data, data.positioning)
} else {
this.init()

View File

@@ -29,20 +29,20 @@
<div class="popper-content__link-id">Link ID: {{ item.linkId }}</div>
<div class="popper-content__link-info">
<div class="info__label">{{ $t('linkMonitor.linkBlock.total') }}</div>
<div class="info__value" :test-id="`linkBlockTotal${index}`" style="margin-left: 8px">
<div class="info__value" style="margin-left: 8px">
{{ unitConvert(item.totalBitsRate, unitTypes.bps).join(' ') }}
</div>
</div>
<div class="popper-content__link-info">
<div class="info__label">{{ $t('linkMonitor.linkBlock.bandwidthUsage') }}</div>
<div class="info__value" style="display: flex">
<div :test-id="`linkBlockEgressUsage${index}`">
<div>
<svg class="icon item-popover-up" aria-hidden="true">
<use xlink:href="#cn-icon-egress"></use>
</svg>
{{ convertValue(item.egressUsage) }}
</div>
<div :test-id="`linkBlockIngressUsage${index}`">
<div>
<svg class="icon item-popover-down" aria-hidden="true">
<use xlink:href="#cn-icon-ingress"></use>
</svg>
@@ -84,7 +84,7 @@
<div class="popper-content__link-id">Next-Hop Internet: {{ item.linkDirection }}</div>
<div class="popper-content__link-info">
<div class="info__label">{{ $t('linkMonitor.linkBlock.total') }}</div>
<div class="info__value" :test-id="`nextHopTotal${index}`" style="margin-left: 8px">
<div class="info__value" style="margin-left: 8px">
{{ unitConvert(item.totalBitsRate, unitTypes.bps).join(' ') }}
</div>
</div>
@@ -118,13 +118,13 @@ import ChartNoData from '@/views/charts/charts/ChartNoData'
import chartMixin from '@/views/charts2/chart-mixin'
import { useRoute } from 'vue-router'
import { ref } from 'vue'
import { get } from '@/utils/http'
import { api } from '@/utils/api'
import { colorGradientCalculation } from '@/utils/tools'
import unitConvert from '@/utils/unit-convert'
import { drillDownPanelTypeMapping, storageKey, unitTypes } from '@/utils/constants'
import { getSecond } from '@/utils/date-util'
import ChartError from '@/components/common/Error'
import axios from 'axios'
export default {
name: 'LinkBlock',
@@ -175,13 +175,10 @@ export default {
endTime: getSecond(this.timeFilter.endTime)
}
const dataRequest = axios.get(api.linkMonitor.analysis, { params: params })
const nextHopRequest = axios.get(api.linkMonitor.nextHopAnalysis, { params: params })
const dataRequest = get(api.linkMonitor.analysis, params)
const nextHopRequest = get(api.linkMonitor.nextHopAnalysis, params)
Promise.all([dataRequest, nextHopRequest]).then(response => {
const res = []
res[0] = response[0].data
res[1] = response[1].data
Promise.all([dataRequest, nextHopRequest]).then(res => {
if (res[0].code === 200 && res[1].code === 200) {
this.showError = false

View File

@@ -12,10 +12,10 @@
import chartMixin from '@/views/charts2/chart-mixin'
import { getSecond } from '@/utils/date-util'
import { api } from '@/utils/api'
import { get } from '@/utils/http'
import { storageKey } from '@/utils/constants'
import PopoverContent from './LinkDirectionGrid/PopoverContent'
import { computeScore } from '@/utils/tools'
import axios from 'axios'
export default {
name: 'LinkDirectionGrid',
@@ -56,14 +56,11 @@ export default {
endTime: getSecond(this.timeFilter.endTime)
}
const dataRequest = axios.get(api.linkMonitor.bigramAnalysis, { params: params })
const nextHopRequest = axios.get(api.linkMonitor.bigramNextHopAnalysis, { params: params })
const dataRequest = get(api.linkMonitor.bigramAnalysis, params)
const nextHopRequest = get(api.linkMonitor.bigramNextHopAnalysis, params)
this.toggleLoading(true)
Promise.all([dataRequest, nextHopRequest]).then(response => {
const res = []
res[0] = response[0].data
res[1] = response[1].data
Promise.all([dataRequest, nextHopRequest]).then(res => {
if (res[0].code === 200) {
this.isLinkShowError = false
// 链路流量数据
@@ -98,7 +95,7 @@ export default {
// 分数低于3分赋红点
d.score = this.localComputeScore(d)
d.scoreLow3 = d.score < 3 || d.score === '-'
d.scoreLow3 = d.score < 3
if (data) {
const existedEgressLink = data.egress.find(e => e.linkId === egressLink.linkId)
@@ -146,9 +143,9 @@ export default {
// 接口数据乱序,根据出方向排序,再根据同个出方向下的入进行排序
nextLinkData.sort((a, b) => {
if (a.ingressLinkDirection !== b.ingressLinkDirection) {
return a.ingressLinkDirection.localeCompare(b.ingressLinkDirection, 'zh')
return a.ingressLinkDirection.localeCompare(b.ingressLinkDirection)
}
return a.egressLinkDirection.localeCompare(b.egressLinkDirection, 'zh')
return a.egressLinkDirection.localeCompare(b.egressLinkDirection)
})
this.isNextNoData = nextLinkData.length === 0
@@ -185,7 +182,7 @@ export default {
// 分数低于3分赋红点
d.score = this.localComputeScore(d)
d.scoreLow3 = d.score < 3 || d.score === '-'
d.scoreLow3 = d.score < 3
if (data) {
const existedEgressLink = data.egress.find(e => e.linkId === egressLink.linkId)
@@ -228,11 +225,13 @@ export default {
this.nextErrorMsg = res[1].message
}
}).catch(e => {
console.error(e)
this.isLinkShowError = true
this.linkErrorMsg = e.message
this.linkErrorMsg = e[0].message
this.isNextShowError = true
this.nextErrorMsg = e.message
this.nextErrorMsg = e[1].message
}).finally(() => {
this.toggleLoading(false)
})

View File

@@ -21,13 +21,13 @@
<span v-if="row.nextHop">{{ row.nextHop }}</span>
<span v-else>{{ row.linkId }}</span>
</div>
<div v-for="(item, index3) in row.egress" :key="index3">
<div v-for="(item, index2) in row.egress" :key="index2">
<el-popover :width="item.popoverWidth" placement="right" trigger="hover">
<template #reference>
<div class="data-item data-item__hover">
<div :test-id="`usagePoint${gridData.length}-${index2+1}-${index3+1}`" :class="item.usageMore90 ? 'data-item__point-red':'data-item__point'"></div>
<div :test-id="`scorePoint${gridData.length}-${index2+1}-${index3+1}`" :class="item.scoreLow3 ? 'data-item__point-red':'data-item__point'"></div>
<div :class="row.egress[index2].usageMore90 ? 'data-item__point-red':'data-item__point'"></div>
<div :class="row.egress[index2].scoreLow3 ? 'data-item__point-red':'data-item__point'"></div>
</div>
</template>
@@ -35,13 +35,13 @@
<template #default>
<div class="item-popover-header">
<!--兼容下一跳情况-->
<span v-if="row.nextHop" :test-id="`toNextHop${index2+1}`">{{ row.nextHop }}</span>
<span v-else :test-id="`fromLinkId${index2+1}`">{{ row.linkId }}</span>
<span v-if="row.nextHop">{{ row.nextHop }}</span>
<span v-else>{{ row.linkId }}</span>
<svg class="icon item-popover-header-icon" aria-hidden="true">
<use xlink:href="#cn-icon-arrow-right2"></use>
</svg>
<span v-if="row.nextHop" :test-id="`toNextHop${index3+1}`">{{ item.egressLinkDirection }}</span>
<span v-else :test-id="`toLinkId${index3+1}`">{{ item.linkId }}</span>
<span v-if="row.nextHop">{{ row.egress[index2].egressLinkDirection }}</span>
<span v-else>{{ row.egress[index2].linkId }}</span>
</div>
<div class="item-popover-block">
@@ -49,24 +49,24 @@
<div style="display: flex">
<div class="row-dot">
<div :class="item.usageMore90 ? 'red-dot':'green-dot'"></div>
<div :class="row.egress[index2].usageMore90 ? 'red-dot':'green-dot'"></div>
</div>
<div class="item-popover-block-content">
<div class="block-content-item">
<div class="block-content-item-name">{{ $t('linkMonitor.bandwidthUsage') }}</div>
<div class="block-content-item-value" :style="{width: item.valueWidth + 'px'}">
<div :test-id="`egressUsage${gridData.length}-${index2+1}-${index3+1}`" style="margin-left: -10px">
<div class="block-content-item-value" :style="{width: row.egress[index2].valueWidth + 'px'}">
<div style="margin-left: -10px">
<svg class="icon item-popover-up" aria-hidden="true">
<use xlink:href="#cn-icon-egress"></use>
</svg>
{{ convertValue(item.egressUsage) }}
{{ convertValue(row.egress[index2].egressUsage) }}
</div>
<div :test-id="`ingressUsage${gridData.length}-${index2+1}-${index3+1}`">
<div>
<svg class="icon item-popover-down" aria-hidden="true">
<use xlink:href="#cn-icon-ingress"></use>
</svg>
{{ convertValue(item.ingressUsage) }}
{{ convertValue(row.egress[index2].ingressUsage) }}
</div>
</div>
</div>
@@ -74,8 +74,8 @@
<div class="block-content-item">
<div class="block-content-item-name">{{ $t('linkMonitor.linkBlock.total') }}</div>
<div :test-id="`totalBitsRate${gridData.length}-${index2+1}-${index3+1}`" class="block-content-item-value" :style="{width: item.valueWidth + 'px'}">
{{ unitConvert(item.totalBitsRate, unitTypes.bps).join('') }}
<div class="block-content-item-value" :style="{width: row.egress[index2].valueWidth + 'px'}">
{{ unitConvert(row.egress[index2].totalBitsRate, unitTypes.bps).join('') }}
</div>
</div>
</div>
@@ -87,48 +87,48 @@
<div style="display: flex">
<div class="row-dot">
<div :class="item.scoreLow3 ? 'red-dot':'green-dot'"></div>
<div :class="row.egress[index2].scoreLow3 ? 'red-dot':'green-dot'"></div>
</div>
<div class="item-popover-block-content">
<div class="block-content-item">
<div class="block-content-item-name">{{ $t('linkMonitor.npmScore1') }}</div>
<div :test-id="`score${gridData.length}-${index2+1}-${index3+1}`" class="block-content-item-value" :style="{width: item.valueWidth + 'px'}">
{{ item.score }}
<div class="block-content-item-value" :style="{width: row.egress[index2].valueWidth + 'px'}">
{{ row.egress[index2].score }}
</div>
</div>
<div class="block-content-item">
<div class="block-content-item-name">{{ $t(npmNetworkName[0].name) }}</div>
<div :test-id="`tcp${gridData.length}-${index2+1}-${index3+1}`" class="block-content-item-value" :style="{width: item.valueWidth + 'px'}">
{{ unitConvert(item.establishLatencyMs, unitTypes.time).join('') }}
<div class="block-content-item-value" :style="{width: row.egress[index2].valueWidth + 'px'}">
{{ unitConvert(row.egress[index2].establishLatencyMs, unitTypes.time).join('') }}
</div>
</div>
<div class="block-content-item">
<div class="block-content-item-name">{{ $t(npmNetworkName[1].name) }}</div>
<div :test-id="`http${gridData.length}-${index2+1}-${index3+1}`" class="block-content-item-value" :style="{'width': item.valueWidth + 'px'}">
{{ unitConvert(item.httpResponseLatency, unitTypes.time).join('') }}
<div class="block-content-item-value" :style="{'width': row.egress[index2].valueWidth + 'px'}">
{{ unitConvert(row.egress[index2].httpResponseLatency, unitTypes.time).join('') }}
</div>
</div>
<div class="block-content-item">
<div class="block-content-item-name">{{ $t(npmNetworkName[2].name) }}</div>
<div :test-id="`ssl${gridData.length}-${index2+1}-${index3+1}`" class="block-content-item-value" :style="{width: item.valueWidth + 'px'}">
{{ unitConvert(item.sslConLatency, unitTypes.time).join('') }}
<div class="block-content-item-value" :style="{width: row.egress[index2].valueWidth + 'px'}">
{{ unitConvert(row.egress[index2].sslConLatency, unitTypes.time).join('') }}
</div>
</div>
<div class="block-content-item">
<div class="block-content-item-name">{{ $t(npmNetworkName[3].name) }}</div>
<div :test-id="`packetLoss${gridData.length}-${index2+1}-${index3+1}`" class="block-content-item-value" :style="{width: item.valueWidth + 'px'}">
{{ unitConvert(item.tcpLostlenPercent, unitTypes.percent).join('') }}
<div class="block-content-item-value" :style="{width: row.egress[index2].valueWidth + 'px'}">
{{ unitConvert(row.egress[index2].tcpLostlenPercent, unitTypes.percent).join('') }}
</div>
</div>
<div class="block-content-item">
<div class="block-content-item-name">{{ $t(npmNetworkName[4].name) }}</div>
<div :test-id="`packetRetrans${gridData.length}-${index2+1}-${index3+1}`" class="block-content-item-value" :style="{width: item.valueWidth + 'px'}">
{{ unitConvert(item.pktRetransPercent, unitTypes.percent).join('') }}
<div class="block-content-item-value" :style="{width: row.egress[index2].valueWidth + 'px'}">
{{ unitConvert(row.egress[index2].pktRetransPercent, unitTypes.percent).join('') }}
</div>
</div>
</div>

View File

@@ -2,7 +2,7 @@
<div class="link-traffic-line">
<link-traffic-drill-down-list
:chart="chart"
:line-data="tabs[0]"
:line-data="mpackets"
:time-filter="timeFilter">
</link-traffic-drill-down-list>
<div class="line network link-traffic">
@@ -12,25 +12,23 @@
<div class="line-header-left">
<div class="line-value-active" v-if="lineTab"></div>
<div class="line-value">
<div class="line-value-tabs"
<div class="line-value-mpackets"
v-show="item.show"
:class=" {'is-active': lineTab === item.class, 'mousemove-cursor': mousemoveCursor === item.class}"
v-for="(item, index) in tabs"
v-for="(item, index) in mpackets"
:key="index"
@mouseenter="mouseenter(item)"
@mouseleave="mouseleave(item)"
@click="activeChange(item, index)"
:test-id="`tab-${index}`">
<div class="line-value-tabs-name">
@click="activeChange(item, index)">
<div class="line-value-mpackets-name">
<div :class="item.class"></div>
<div class="tabs-name">{{$t(item.name)}}</div>
<div class="mpackets-name">{{$t(item.name)}}</div>
</div>
<div class="line-value-unit" :test-id="`tabContent${index}`">
<div class="line-value-unit">
<span class="line-value-unit-number">{{unitConvert(item.analysis.avg, unitTypes.number)[0]}}</span>
<span class="line-value-unit-number2">
<span>{{unitConvert(item.analysis.avg, unitTypes.number)[1]}}</span>
<span v-if="item.unitType">{{item.unitType}}</span>
</span>
<span>{{unitConvert(item.analysis.avg, unitTypes.number)[1]}}</span><span v-if="item.unitType">{{item.unitType}}</span>
</span>
</div>
</div>
</div>
@@ -71,12 +69,12 @@ import unitConvert from '@/utils/unit-convert'
import { chartColor3, chartColor4, unitTypes } from '@/utils/constants'
import { getLineType, overwriteUrl, urlParamsHandler } from '@/utils/tools'
import { getSecond } from '@/utils/date-util'
import { get } from '@/utils/http'
import { api } from '@/utils/api'
import _ from 'lodash'
import * as echarts from 'echarts'
import { linkTrafficLineChartOption } from '@/views/charts2/charts/options/echartOption'
import { stackedLineTooltipFormatter } from '@/views/charts/charts/tools'
import axios from 'axios'
export default {
name: 'LinkTrafficLine',
@@ -114,7 +112,7 @@ export default {
label: 'Packets/s'
}
],
tabs: [
mpackets: [
{ analysis: {}, name: 'network.total', class: 'total', show: true, invertTab: true, positioning: 0, data: [], unitType: '' },
{ analysis: {}, name: 'linkMonitor.ingress', class: 'ingress', show: true, invertTab: true, positioning: 1, data: [], unitType: '' },
{ analysis: {}, name: 'linkMonitor.egress', class: 'egress', show: true, invertTab: true, positioning: 2, data: [], unitType: '' }
@@ -178,14 +176,13 @@ export default {
}
}
this.loading = true
axios.get(api.linkMonitor.totalTrafficAnalysis, { params: params }).then((res) => {
res = res.data
get(api.linkMonitor.totalTrafficAnalysis, params).then((res) => {
if (res.code === 200) {
this.showError = false
this.isNoData = res.data.result.length === 0
if (this.isNoData) {
this.lineTab = ''
this.tabs = [
this.mpackets = [
{ analysis: {}, name: 'network.total', class: 'total', show: true, invertTab: true, positioning: 0, data: [], unitType: '' },
{ analysis: {}, name: 'linkMonitor.ingress', class: 'ingress', show: true, invertTab: true, positioning: 1, data: [], unitType: '' },
{ analysis: {}, name: 'linkMonitor.egress', class: 'egress', show: true, invertTab: true, positioning: 2, data: [], unitType: '' }
@@ -207,69 +204,67 @@ export default {
})
},
echartsInit (echartsData) {
if (!this.isUnitTesting) {
if (this.lineTab) {
this.handleActiveBar()
echartsData = echartsData.filter(t => t.show === true && t.invertTab === false)
} else {
echartsData = echartsData.filter(t => t.show === true)
}
const _this = this
const dom = document.getElementById('linkTrafficLineChart')
!this.myChart && (this.myChart = echarts.init(dom))
this.chartOption = linkTrafficLineChartOption
const chartOption = this.chartOption.series[0]
this.chartOption.series = echartsData.map((t, i) => {
return {
...chartOption,
name: t.name,
lineStyle: {
color: chartColor3[t.positioning],
width: 1
},
stack: t.name !== 'network.total' ? 'network.total' : '',
symbolSize: function (value) {
return _this.symbolSizeSortChange(i, value[0])
},
emphasis: {
itemStyle: {
borderColor: chartColor4[t.positioning],
borderWidth: 2,
shadowColor: chartColor4[t.positioning],
shadowBlur: this.sizes[t.positioning] + 2
}
},
areaStyle: {
opacity: 0.1,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: chartColor3[t.positioning]
},
{
offset: 1,
color: chartColor3[t.positioning]
}
])
},
data: t.data.map(v => [Number(v[0]) * 1000, Number(v[1]), 'number'])
}
})
this.chartOption.tooltip.formatter = (params) => {
params.forEach(t => {
t.seriesName = this.$t(t.seriesName)
this.tabs.forEach(e => {
if (this.$t(e.name) === t.seriesName) {
t.borderColor = chartColor3[e.positioning]
}
})
})
// const str = stackedLineTooltipFormatter(params)
return stackedLineTooltipFormatter(params)
}
this.showMarkLine = true
this.myChart.setOption(this.chartOption)
if (this.lineTab) {
this.handleActiveBar()
echartsData = echartsData.filter(t => t.show === true && t.invertTab === false)
} else {
echartsData = echartsData.filter(t => t.show === true)
}
const _this = this
const dom = document.getElementById('linkTrafficLineChart')
!this.myChart && (this.myChart = echarts.init(dom))
this.chartOption = linkTrafficLineChartOption
const chartOption = this.chartOption.series[0]
this.chartOption.series = echartsData.map((t, i) => {
return {
...chartOption,
name: t.name,
lineStyle: {
color: chartColor3[t.positioning],
width: 1
},
stack: t.name !== 'network.total' ? 'network.total' : '',
symbolSize: function (value) {
return _this.symbolSizeSortChange(i, value[0])
},
emphasis: {
itemStyle: {
borderColor: chartColor4[t.positioning],
borderWidth: 2,
shadowColor: chartColor4[t.positioning],
shadowBlur: this.sizes[t.positioning] + 2
}
},
areaStyle: {
opacity: 0.1,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: chartColor3[t.positioning]
},
{
offset: 1,
color: chartColor3[t.positioning]
}
])
},
data: t.data.map(v => [Number(v[0]) * 1000, Number(v[1]), 'number'])
}
})
this.chartOption.tooltip.formatter = (params) => {
params.forEach(t => {
t.seriesName = this.$t(t.seriesName)
this.mpackets.forEach(e => {
if (this.$t(e.name) === t.seriesName) {
t.borderColor = chartColor3[e.positioning]
}
})
})
// const str = stackedLineTooltipFormatter(params)
return stackedLineTooltipFormatter(params)
}
this.showMarkLine = true
this.myChart.setOption(this.chartOption)
},
activeChange (item, index) {
if (this.isNoData) return
@@ -301,16 +296,16 @@ export default {
legendSelectChange (item, index, val) {
if (index === 'index') {
this.dispatchLegendSelectAction(item.name)
} else if (this.tabs[index] && this.tabs[index].name === item.name) {
} else if (this.mpackets[index] && this.mpackets[index].name === item.name) {
this.dispatchLegendSelectAction(item.name)
this.tabs.forEach((t) => {
this.mpackets.forEach((t) => {
if (t.name !== item.name) {
this.dispatchLegendUnSelectAction(t.name)
}
})
}
if (val === 'active') {
this.tabs.forEach(t => {
this.mpackets.forEach(t => {
if (item.name === t.name) {
t.invertTab = !t.invertTab
} else {
@@ -322,7 +317,7 @@ export default {
} else {
this.lineTab = t.class
}
this.tabs.forEach((e) => {
this.mpackets.forEach((e) => {
this.dispatchLegendSelectAction(e.name)
})
}
@@ -330,8 +325,8 @@ export default {
}
},
handleActiveBar () {
if (document.querySelector('.network .line-value-tabs.is-active')) {
const { offsetLeft, clientWidth, clientLeft } = document.querySelector('.network .line-value-tabs.is-active')
if (document.querySelector('.network .line-value-mpackets.is-active')) {
const { offsetLeft, clientWidth, clientLeft } = document.querySelector('.network .line-value-mpackets.is-active')
const activeBar = document.querySelector('.network .line-value-active')
activeBar.style.cssText += `width: ${clientWidth}px; left: ${offsetLeft + this.leftOffset + clientLeft}px;`
}
@@ -344,7 +339,7 @@ export default {
this.lineTab = ''
this.handleActiveBar()
this.showMarkLine = !this.showMarkLine
this.tabs.forEach((e) => {
this.mpackets.forEach((e) => {
if (!e.invertTab) {
e.invertTab = true
}
@@ -393,9 +388,9 @@ export default {
})
}
lineData.splice(0, 1)
const tabs = _.cloneDeep(this.tabs)
const mpackets = _.cloneDeep(this.mpackets)
const unit = val === 'Bits/s' ? 'bps' : 'packets/s'
this.legendInit(lineData, active, show, unit, tabs)
this.legendInit(lineData, active, show, unit, mpackets)
},
legendInit (data, active, show, type, linkData) {
data.forEach((d, i) => {
@@ -422,17 +417,17 @@ export default {
}
}
})
this.tabs = linkData
this.mpackets = linkData
if (num === 3) {
linkData[0].invertTab = false
this.lineTab = 'total'
this.legendSelectChange(linkData[0], 0)
this.$nextTick(() => {
this.echartsInit(this.tabs)
this.echartsInit(this.mpackets)
})
} else {
this.$nextTick(() => {
this.echartsInit(this.tabs)
this.echartsInit(this.mpackets)
if (!this.lineRefer) this.lineRefer = 'Average'
})
}
@@ -441,7 +436,7 @@ export default {
mounted () {
this.timer = setTimeout(() => {
if (this.lineTab) {
const data = this.tabs.find(t => t.class === this.lineTab)
const data = this.mpackets.find(t => t.class === this.lineTab)
this.activeChange(data, data.positioning)
} else {
this.init()

View File

@@ -6,42 +6,36 @@
<div v-else>
<div class="link-traffic-list-center">
<div class="link-traffic-list-center-label">{{$t('network.total')}}</div>
<div class="link-traffic-list-center-value" v-if="lineData && lineData.analysis" test-id="line-tabContent">
<span>{{unitConvert(lineData.analysis.avg, unitTypes.number)[0]}}</span>
<span>
<span>{{unitConvert(lineData.analysis.avg, unitTypes.number)[1]}}</span>
<span v-if="lineData.unitType">{{lineData.unitType}}</span>
</span>
</div>
<div class="link-traffic-list-center-value" v-if="lineData[0] && lineData[0].analysis">{{unitConvert(lineData[0].analysis.avg, unitTypes.bps).join('')}}</div>
</div>
<div class="link-traffic-list-center">
<div class="link-traffic-list-center-label">{{$t('linkMonitor.bandwidthUsage')}}</div>
<div class="link-traffic-list-center-value" v-if="lineData && lineData.analysis && bandWidth" test-id="line-percent">{{unitConvert(lineData.analysis.avg / bandWidth, unitTypes.percent).join('')}}</div>
<div class="link-traffic-list-center-value" v-if="bandWidth && lineData[0] && lineData[0].analysis">{{unitConvert(lineData[0].analysis.avg / bandWidth, unitTypes.percent).join('')}}</div>
<div class="link-traffic-list-center-value" v-else>-</div>
</div>
<div class="link-traffic-list-center">
<div class="link-traffic-list-center-label">{{$t('linkMonitor.npmScore')}}</div>
<div class="link-traffic-list-center-value" test-id="line-score">{{linkTrafficListData.npmScore || '-'}}</div>
<div class="link-traffic-list-center-value">{{linkTrafficListData.npmScore || '-'}}</div>
</div>
<div class="link-traffic-list-center">
<div class="link-traffic-list-center-label">{{$t('networkAppPerformance.tcpConnectionEstablishLatency')}}</div>
<div class="link-traffic-list-center-value" test-id="line-tcp">{{unitConvert(Math.floor(linkTrafficListData.establishLatencyMs), unitTypes.time).join('')}}</div>
<div class="link-traffic-list-center-value">{{unitConvert(Math.floor(linkTrafficListData.establishLatencyMs), unitTypes.time).join('')}}</div>
</div>
<div class="link-traffic-list-center">
<div class="link-traffic-list-center-label">{{$t('networkAppPerformance.httpResponse')}}</div>
<div class="link-traffic-list-center-value" test-id="line-http">{{unitConvert(Math.floor(linkTrafficListData.httpResponseLatency), unitTypes.time).join('')}}</div>
<div class="link-traffic-list-center-value">{{unitConvert(Math.floor(linkTrafficListData.httpResponseLatency), unitTypes.time).join('')}}</div>
</div>
<div class="link-traffic-list-center">
<div class="link-traffic-list-center-label">{{$t('networkAppPerformance.sslResponseLatency')}}</div>
<div class="link-traffic-list-center-value" test-id="line-ssl">{{unitConvert(Math.floor(linkTrafficListData.sslConLatency), unitTypes.time).join('')}}</div>
<div class="link-traffic-list-center-value">{{unitConvert(Math.floor(linkTrafficListData.sslConLatency), unitTypes.time).join('')}}</div>
</div>
<div class="link-traffic-list-center">
<div class="link-traffic-list-center-label">{{$t('networkAppPerformance.packetLoss')}}</div>
<div class="link-traffic-list-center-value" test-id="line-packetLoss">{{unitConvert(linkTrafficListData.tcpLostlenPercent, unitTypes.percent).join('')}}</div>
<div class="link-traffic-list-center-value">{{unitConvert(linkTrafficListData.tcpLostlenPercent, unitTypes.percent).join('')}}</div>
</div>
<div class="link-traffic-list-center">
<div class="link-traffic-list-center-label">{{$t('overall.packetRetrans')}}</div>
<div class="link-traffic-list-center-value" test-id="line-packetRetrans">{{unitConvert(linkTrafficListData.pktRetransPercent, unitTypes.percent).join('')}}</div>
<div class="link-traffic-list-center-value">{{unitConvert(linkTrafficListData.pktRetransPercent, unitTypes.percent).join('')}}</div>
</div>
</div>
</div>
@@ -51,6 +45,7 @@
import chartMixin from '@/views/charts2/chart-mixin'
import { storageKey, unitTypes } from '@/utils/constants'
import unitConvert from '@/utils/unit-convert'
import { get } from '@/utils/http'
import { api } from '@/utils/api'
import { ref } from 'vue'
import { useRoute } from 'vue-router'
@@ -58,7 +53,6 @@ import { getSecond } from '@/utils/date-util'
import { computeScore } from '@/utils/tools'
import Loading from '@/components/common/Loading'
import ChartError from '@/components/common/Error'
import axios from 'axios'
export default {
name: 'linkTrafficList',
mixins: [chartMixin],
@@ -142,8 +136,7 @@ export default {
}
}
this.loading = true
axios.get(api.linkMonitor.networkAnalysis, { params: params }).then(res => {
res = res.data
get(api.linkMonitor.networkAnalysis, params).then(res => {
if (res.code === 200) {
this.showError = false
this.isNoData = res.data.result.length === 0
@@ -172,9 +165,6 @@ export default {
},
mounted () {
this.linkTrafficData()
},
beforeUnmount () {
this.unitConvert = null
}
}
</script>

View File

@@ -6,31 +6,31 @@
</div>
<div class="app-cards">
<div class="app-card" @mouseenter="mouseenter(app)" @mouseleave="mouseleave(app)" v-for="(app, index) in appData" :key="app.type + app.name" test-id="app-data-card">
<div class="app-card" @mouseenter="mouseenter(app)" @mouseleave="mouseleave(app)" v-for="(app, index) in appData" :key="app.type + app.name">
<div class="app-card-title">
<div class="app-card-title-name">
<i class="cn-icon" :class="app.type === 'provider' ? 'cn-icon-entity' : 'cn-icon-app2'" :test-id="`icon${index}`"></i>
<span @click="drillDownData(app.type, app.name)" :test-id="`name${index}`">{{app.name}}</span>
<i class="cn-icon" :class="app.type === 'provider' ? 'cn-icon-entity' : 'cn-icon-app2'"></i>
<span @click="drillDownData(app.type, app.name)">{{app.name}}</span>
</div>
<div class="app-card-title-more">
<span v-show="app.showMore"><i class="cn-icon cn-icon-more-dark" @mouseenter="mouseenterMore(app)" test-id="mouseenter-dark"></i></span>
<span class="app-card-title-more-delete" @click="del(app, index)" v-show="app.moreOptions" @mouseleave="mouseleaveMore(app)" test-id="mouseleave-more"><i class="cn-icon cn-icon-delete"></i>{{$t('overall.delete')}}</span>
<span v-show="app.showMore"><i class="cn-icon cn-icon-more-dark" @mouseenter="mouseenterMore(app)"></i></span>
<span class="app-card-title-more-delete" @click="del(app, index)" v-show="app.moreOptions" @mouseleave="mouseleaveMore(app)"><i class="cn-icon cn-icon-delete"></i>{{$t('overall.delete')}}</span>
</div>
</div>
<div class="app-card__bodys">
<div class="app-card__body">
<div class="app-card__body-content">
<div class="app-card__body-content-value">
<div class="app-card__body-content-number" :test-id="`rate${index}`">{{unitConvert(app.rate, unitTypes.number).join(' ')}}</div>
<div class="app-card__body-content-percent red" v-if="app.value > 0" :test-id="`percent${index}`">
<div class="app-card__body-content-number">{{unitConvert(app.rate, unitTypes.number).join(' ')}}</div>
<div class="app-card__body-content-percent red" v-if="app.value > 0">
<span v-if="app.value <= 5">
+{{unitConvert(app.value, unitTypes.percent).join('')}}
</span>
<span v-else>>500.00%</span>
</div>
<div class="app-card__body-content-percent green" v-else-if="app.value < 0" :test-id="`percent${index}`">
<div class="app-card__body-content-percent green" v-else-if="app.value < 0">
<span v-if="app.value >= -5">
-{{unitConvert(app.value, unitTypes.percent).join('').replace(/-/g, '')}}
-{{unitConvert(app.value, unitTypes.percent).join('').replaceAll('-', '')}}
</span>
<span v-else>>500.00%</span>
</div>
@@ -39,8 +39,8 @@
</div>
<div class="app-card__body-previous">
<div>Total</div>
<div v-if="metric === 'Bits/s'" :test-id="`total${index}`">{{unitConvert(app.total, unitTypes.byte).join(' ')}}</div>
<div v-else :test-id="`total${index}`">{{unitConvert(app.total, unitTypes.number).join(' ')}}</div>
<div v-if="metric === 'Bits/s'">{{unitConvert(app.total, unitTypes.byte).join(' ')}}</div>
<div v-else>{{unitConvert(app.total, unitTypes.number).join(' ')}}</div>
</div>
</div>
<div class="chart__drawing" v-show="!isNoData" :id="`chart-${app.name}-${app.type}`"></div>
@@ -48,7 +48,7 @@
</div>
<div class="app-card app-card--create">
<i class="cn-icon cn-icon-add1" @click="addApp"></i>
<span @click="addApp" test-id="add">{{$t('overall.add')}}</span>
<span @click="addApp">{{$t('overall.add')}}</span>
</div>
</div>
<el-drawer
@@ -62,7 +62,7 @@
<div class="add-app__header">
<div class="header__title">{{$t('overall.add')}}</div>
<div class="header__operations">
<div class="header__operation header__operation--cancel" @click="cancelApp" test-id="cancel-app">{{$t('overall.cancel')}}</div>
<div class="header__operation header__operation--cancel" @click="cancelApp">{{$t('overall.cancel')}}</div>
<div class="header__operation header__operation--save" @click="save">{{$t('overall.save')}}</div>
</div>
</div>
@@ -72,15 +72,15 @@
<div class="body__apps" :class="{'body__apps-no-grid': providerOptions.length === 0}">
<loading :loading="loadingBody"></loading>
<chart-no-data v-if="providerOptions.length === 0 && !loadingBody"></chart-no-data>
<div class="body__app" v-else :class="{'provide-show': app.provideShow}" v-for="(app, index) in providerOptions" :key="index" @click="appCheckedChange(app, 0)" :test-id="`provide${index}`">
<div class="body__app" v-else :class="{'provide-show': app.provideShow}" v-for="(app, index) in providerOptions" :key="index" @click="appCheckedChange(app, 0)">
<div class="body__app-content">
<div class="body__app-left">
<span><i class="cn-icon" :class="app.icon" :test-id="`provide-icon${index}`"></i></span>
<span class="body__app-left-title" :test-id="`provide-title${index}`">{{app.value}}</span>
<span><i class="cn-icon" :class="app.icon"></i></span>
<span class="body__app-left-title">{{app.value}}</span>
</div>
<div class="body__app-content-right" v-if="app.provideShow"><span><i class="cn-icon cn-icon-a-allclear"></i></span></div>
</div>
<div class="body__app-value" v-if="app.remark" :title="app.remark" :test-id="`provide-remark${index}`">{{app.remark}}</div>
<div class="body__app-value" v-if="app.remark" :title="app.remark">{{app.remark}}</div>
<div v-else>-</div>
</div>
</div>
@@ -89,22 +89,22 @@
<div class="body__apps" :class="{'body__apps-no-grid': appOptions.length === 0}">
<loading :loading="loadingBody"></loading>
<chart-no-data v-if="appOptions.length === 0 && !loadingBody"></chart-no-data>
<div class="body__app" v-else :class="{'app-show': app.appShow}" v-for="(app, index) in appOptions" :key="index" @click="appCheckedChange(app, 1)" :test-id="`app${index}`">
<div class="body__app" v-else :class="{'app-show': app.appShow}" v-for="(app, index) in appOptions" :key="index" @click="appCheckedChange(app, 1)">
<div class="body__app-content">
<div class="body__app-left">
<span><i class="cn-icon" :class="app.icon" :test-id="`app-icon${index}`"></i></span>
<span class="body__app-left-title" :test-id="`app-title${index}`">{{app.value}}</span>
<span><i class="cn-icon" :class="app.icon"></i></span>
<span class="body__app-left-title">{{app.value}}</span>
</div>
<div class="body__app-content-right" v-if="app.appShow"><span><i class="cn-icon cn-icon-a-allclear"></i></span></div>
</div>
<div class="body__app-value" v-if="app.remark" :title="app.remark" :test-id="`app-remark${index}`">{{app.remark}}</div>
<div class="body__app-value" v-if="app.remark" :title="app.remark">{{app.remark}}</div>
<div v-else>-</div>
</div>
</div>
</el-tab-pane>
</el-tabs>
<div class="body__searcher">
<el-input v-model="searcherApp" @input="searcherAppChange" size="mini" :placeholder="$t('networkOverview.search')" prefix-icon="el-icon-search" test-id="search-input"></el-input>
<el-input v-model="searcherApp" @input="searcherAppChange" size="mini" :placeholder="$t('networkOverview.search')" prefix-icon="el-icon-search"></el-input>
</div>
<div class="body__loading"><loading :loading="loading"></loading></div>
</div>
@@ -119,7 +119,7 @@ import { storageKey, unitTypes, networkTable, operationType, curTabState } from
import * as echarts from 'echarts'
import { appListChartOption } from '@/views/charts2/charts/options/echartOption'
import { shallowRef } from 'vue'
import { put } from '@/utils/http'
import { get, put } from '@/utils/http'
import { api } from '@/utils/api'
import _ from 'lodash'
import { getSecond } from '@/utils/date-util'
@@ -128,7 +128,6 @@ import loading from '@/components/common/Loading'
import ChartNoData from '@/views/charts/charts/ChartNoData'
import { appStackedLineTooltipFormatter } from '@/views/charts/charts/tools'
import chartMixin from '@/views/charts2/chart-mixin'
import axios from 'axios'
export default {
name: 'NetworkOverviewApps',
@@ -228,8 +227,8 @@ export default {
return `'${item.name}'`
}).join(',')
}
prevRequest = axios.get(api.netWorkOverview.applicationCycleTrafficTotal, { params: params })
request = axios.get(api.netWorkOverview.applicationTrafficAnalysis, { params: params })
prevRequest = get(api.netWorkOverview.applicationCycleTrafficTotal, params)
request = get(api.netWorkOverview.applicationTrafficAnalysis, params)
this.handleData(prevRequest, request, 'app')
}
if (providerCards.length > 0) {
@@ -240,15 +239,15 @@ export default {
return `'${item.name}'`
}).join(',')
}
prevRequest = axios.get(api.netWorkOverview.appCompanyCycleTrafficTotal, { params: params })
request = axios.get(api.netWorkOverview.appCompanyTrafficAnalysis, { params: params })
prevRequest = get(api.netWorkOverview.appCompanyCycleTrafficTotal, params)
request = get(api.netWorkOverview.appCompanyTrafficAnalysis, params)
this.handleData(prevRequest, request, 'provider')
}
},
handleData (prevRequest, request, _t) {
this.toggleLoading(true)
Promise.all([prevRequest, request]).then(res => {
this.isNoData = (res[0].data.data.result.length && res[1].data.data.result.length) === 0
this.isNoData = res[0].data.result.length === 0 && res[1].data.result.length === 0
if (this.isNoData) {
this.appData = this.appData.map(t => {
return {
@@ -257,10 +256,10 @@ export default {
}
})
}
if (res[0].data.code === 200 && res[1].data.code === 200) {
if (res[0].code === 200 && res[1].code === 200) {
this.showError = false
const prevData = res[0].data.data.result
const data = res[1].data.data.result
const prevData = res[0].data.result
const data = res[1].data.result
let toCompareType = 'bytes'
if (this.metric === 'Sessions/s') {
toCompareType = 'sessions'
@@ -391,40 +390,38 @@ export default {
this.urlChangeParams = {}
},
initChart (obj) {
if (!this.isUnitTesting) {
let chart = this.myChart.find(m => m.name === obj.name && m.type === obj.type)
if (!chart) {
chart = echarts.init(document.getElementById(`chart-${obj.name}-${obj.type}`))
const chartOption = _.cloneDeep(appListChartOption)
chartOption.series = [{
...chartOption.series[0],
data: obj.lineData.map(v => [Number(v[0]) * 1000, Number(v[1]), 'number']),
lineStyle: {
color: '#35ADDA'
},
areaStyle: {
opacity: 0.1,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: '#35ADDA'
},
{
offset: 1,
color: '#35ADDA'
}
])
}
}]
chartOption.tooltip.formatter = (params) => {
return appStackedLineTooltipFormatter(params)
let chart = this.myChart.find(m => m.name === obj.name && m.type === obj.type)
if (!chart) {
chart = echarts.init(document.getElementById(`chart-${obj.name}-${obj.type}`))
const chartOption = _.cloneDeep(appListChartOption)
chartOption.series = [{
...chartOption.series[0],
data: obj.lineData.map(v => [Number(v[0]) * 1000, Number(v[1]), 'number']),
lineStyle: {
color: '#35ADDA'
},
areaStyle: {
opacity: 0.1,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: '#35ADDA'
},
{
offset: 1,
color: '#35ADDA'
}
])
}
chart.setOption(chartOption)
this.myChart.push(chart)
this.$nextTick(() => {
chart.resize()
})
}]
chartOption.tooltip.formatter = (params) => {
return appStackedLineTooltipFormatter(params)
}
chart.setOption(chartOption)
this.myChart.push(chart)
this.$nextTick(() => {
chart.resize()
})
}
},
handleScroll (e) {
@@ -461,8 +458,7 @@ export default {
}
if (parseFloat(this.appTypeTab) === 0) {
params.type = 'overviewProvide'
axios.get(api.dict, { params: params }).then(res => {
res = res.data
get(api.dict, params).then(res => {
if (res.code === 200) {
res.data.list = res.data.list.filter(l => !this.appData.some(pd => pd.type === 'provider' && pd.name === l.value))
this.pageObj.pages = res.data.pages
@@ -487,10 +483,9 @@ export default {
})
} else if (parseFloat(this.appTypeTab) === 1) {
params.type = 'overviewApp'
axios.get(api.dict, { params: params }).then(res => {
res = res.data
get(api.dict, params).then(res => {
res.data.list = res.data.list.filter(l => !this.appData.some(pd => pd.type === 'app' && pd.name === l.value))
if (res.code === 200) {
res.data.list = res.data.list.filter(l => !this.appData.some(pd => pd.type === 'app' && pd.name === l.value))
this.pageObj.pages = res.data.pages
res.data.list.forEach(t => {
this.toSaveApp.forEach(e => {
@@ -705,7 +700,7 @@ export default {
}
},
mounted () {
if (this.chart && this.chart.params && this.chart.params.app) {
if (this.chart.params && this.chart.params.app) {
const userId = parseInt(localStorage.getItem(storageKey.userId))
const apps = _.cloneDeep(this.chart.params.app)
let app = apps.find(p => p.user === userId)

View File

@@ -5,29 +5,28 @@
<div class="line-header-left">
<div class="line-value-active" v-if="lineTab"></div>
<div class="line-value">
<template v-for="(item, index) in tabs">
<div class="line-value-tabs"
:class=" {'is-active': lineTab === item.class, 'mousemove-cursor': mousemoveCursor === item.class}"
v-if="item.show"
:key="index"
@mouseenter="mouseenter(item)"
@mouseleave="mouseleave(item)"
@click="activeChange(item, index)"
:test-id="`tab${index}`"
>
<div class="line-value-tabs-name">
<div :class="item.class"></div>
<div class="tabs-name" :test-id="`tabTitle${index}`">{{$t(item.name)}}</div>
</div>
<div class="line-value-unit" :test-id="`tabContent${index}`">
<span class="line-value-unit-number">{{unitConvert(item.analysis.avg, unitTypes.number)[0]}}</span>
<span class="line-value-unit-number2">
<div class="line-value-mpackets"
v-show="item.show"
:class=" {'is-active': lineTab === item.class, 'mousemove-cursor': mousemoveCursor === item.class}"
v-for="(item, index) in mpackets"
:key="index"
@mouseenter="mouseenter(item)"
@mouseleave="mouseleave(item)"
@click="activeChange(item, index)"
:test-id="`tab${index}`"
>
<div class="line-value-mpackets-name">
<div :class="item.class"></div>
<div class="mpackets-name">{{$t(item.name)}}</div>
</div>
<div class="line-value-unit" :test-id="`tabContent${index}`">
<span class="line-value-unit-number">{{unitConvert(item.analysis.avg, unitTypes.number)[0]}}</span>
<span class="line-value-unit-number2">
<span>{{unitConvert(item.analysis.avg, unitTypes.number)[1]}}</span>
<span v-if="item.unitType">{{item.unitType}}</span>
</span>
</div>
</div>
</template>
</div>
</div>
</div>
<div class="line-select line-header-right">
@@ -75,8 +74,6 @@ import chartMixin from '@/views/charts2/chart-mixin'
import { useRoute } from 'vue-router'
import { getLineType, overwriteUrl, urlParamsHandler } from '@/utils/tools'
import ChartError from '@/components/common/Error'
import mockData from '../../../../../test/views/charts2/charts/networkOverview/NetworkOverviewLineMockData'
export default {
name: 'NetworkOverviewLine',
components: {
@@ -122,7 +119,7 @@ export default {
label: 'Maximum'
}
],
tabsTemplate: [
mpackets: [
{ analysis: {}, name: 'network.total', class: 'total', show: true, invertTab: true, positioning: 0, data: [], unitType: '' },
{ analysis: {}, name: 'network.inbound', class: 'inbound', show: true, invertTab: true, positioning: 1, data: [], unitType: '' },
{ analysis: {}, name: 'network.outbound', class: 'outbound', show: true, invertTab: true, positioning: 2, data: [], unitType: '' },
@@ -130,7 +127,6 @@ export default {
{ analysis: {}, name: 'network.through', class: 'through', show: true, invertTab: true, positioning: 4, data: [], unitType: '' },
{ analysis: {}, name: 'network.other', class: 'other', show: true, invertTab: true, positioning: 5, data: [], unitType: '' }
],
tabs: [],
unitConvert,
unitTypes,
chartDateObject: [],
@@ -176,7 +172,7 @@ export default {
metric (n) {
this.handleActiveBar()
this.showMarkLine = !this.showMarkLine
this.tabs.forEach((e) => {
this.mpackets.forEach((e) => {
if (!e.invertTab) {
e.invertTab = true
}
@@ -199,14 +195,20 @@ export default {
this.toggleLoading(true)
axios.get(api.netWorkOverview.totalTrafficAnalysis, { params: params }).then(response => {
const res = response.data
// const res = mockData.bytes.boundary.data
this.errorMsg = res.message
if (res.code === 200) {
this.isNoData = res.data.result.length === 0
this.showError = false
if (this.isNoData) {
this.lineTab = ''
this.tabs = _.cloneDeep(this.tabsTemplate)
this.mpackets = [
{ analysis: {}, name: 'network.total', class: 'total', show: true, invertTab: true, positioning: 0, data: [], unitType: '' },
{ analysis: {}, name: 'network.inbound', class: 'inbound', show: true, invertTab: true, positioning: 1, data: [], unitType: '' },
{ analysis: {}, name: 'network.outbound', class: 'outbound', show: true, invertTab: true, positioning: 2, data: [], unitType: '' },
{ analysis: {}, name: 'network.internal', class: 'internal', show: true, invertTab: true, positioning: 3, data: [], unitType: '' },
{ analysis: {}, name: 'network.through', class: 'through', show: true, invertTab: true, positioning: 4, data: [], unitType: '' },
{ analysis: {}, name: 'network.other', class: 'other', show: true, invertTab: true, positioning: 5, data: [], unitType: '' }
]
} else {
this.initData(res.data.result, val, active, show, n)
}
@@ -344,7 +346,7 @@ export default {
this.chartOption.tooltip.formatter = (params) => {
params.forEach(t => {
t.seriesName = this.$t(t.seriesName)
this.tabs.forEach(e => {
this.mpackets.forEach(e => {
if (this.$t(e.name) === t.seriesName) {
t.borderColor = chartColor3[e.positioning]
}
@@ -434,16 +436,16 @@ export default {
legendSelectChange (item, index, val) {
if (index === 'index') {
this.dispatchLegendSelectAction(item.name)
} else if (this.tabs[index] && this.tabs[index].name === item.name) {
} else if (this.mpackets[index] && this.mpackets[index].name === item.name) {
this.dispatchLegendSelectAction(item.name)
this.tabs.forEach((t) => {
this.mpackets.forEach((t) => {
if (t.name !== item.name) {
this.dispatchLegendUnSelectAction(t.name)
}
})
}
if (val === 'active') {
this.tabs.forEach(t => {
this.mpackets.forEach(t => {
if (item.name === t.name) {
t.invertTab = !t.invertTab
} else {
@@ -455,7 +457,7 @@ export default {
} else {
this.lineTab = t.class
}
this.tabs.forEach((e) => {
this.mpackets.forEach((e) => {
this.dispatchLegendSelectAction(e.name)
})
}
@@ -463,8 +465,8 @@ export default {
}
},
handleActiveBar () {
if (document.querySelector('.network .line-value-tabs.is-active')) {
const { offsetLeft, clientWidth, clientLeft } = document.querySelector('.network .line-value-tabs.is-active')
if (document.querySelector('.network .line-value-mpackets.is-active')) {
const { offsetLeft, clientWidth, clientLeft } = document.querySelector('.network .line-value-mpackets.is-active')
const activeBar = document.querySelector('.network .line-value-active')
activeBar.style.cssText += `width: ${clientWidth}px; left: ${offsetLeft + this.leftOffset + clientLeft}px;`
}
@@ -476,9 +478,9 @@ export default {
this.lineRefer = val
let echartsData
if (this.lineTab) {
echartsData = this.tabs.filter(t => t.show === true && t.invertTab === false)
echartsData = this.mpackets.filter(t => t.show === true && t.invertTab === false)
} else {
echartsData = this.tabs.filter(t => t.show === true)
echartsData = this.mpackets.filter(t => t.show === true)
}
if (!this.isUnitTesting) {
const chartOption = this.myChart.getOption()
@@ -568,12 +570,12 @@ export default {
}
lineData.splice(0, 1)
if (val === 'Sessions/s') {
const tabs = _.cloneDeep(this.tabsTemplate)
const mpackets = _.cloneDeep(this.mpackets)
lineData.forEach((d, i) => {
tabs[i].data = d.values
tabs[i].analysis = d.analysis
mpackets[i].data = d.values
mpackets[i].analysis = d.analysis
})
tabs.forEach((e, i) => {
mpackets.forEach((e, i) => {
if (i !== 0) {
e.show = false
}
@@ -582,9 +584,9 @@ export default {
this.lineTab = 'total'
this.legendSelectChange(e, 0)
})
this.tabs = tabs
this.mpackets = mpackets
this.$nextTick(() => {
this.echartsInit(this.tabs, true)
this.echartsInit(this.mpackets, true)
})
} else {
const unit = val === 'Bits/s' ? 'bps' : 'packets/s'
@@ -592,15 +594,15 @@ export default {
}
},
legendInit (data, active, show, type, n) {
const tabs = _.cloneDeep(this.tabsTemplate)
const mpackets = _.cloneDeep(this.mpackets)
data.forEach((d, i) => {
tabs[i].data = d.values
tabs[i].analysis = d.analysis
mpackets[i].data = d.values
mpackets[i].analysis = d.analysis
})
let num = 0
tabs.forEach(e => {
mpackets.forEach(e => {
e.unitType = type
if (e.name !== 'network.total' && parseFloat(e.analysis.avg) == 0) {
if (e.name !== 'network.total' && parseFloat(e.analysis.avg) === 0) {
e.show = false
num += 1
} else {
@@ -617,18 +619,18 @@ export default {
}
}
})
this.tabs = tabs
this.mpackets = mpackets
if (num === 5) {
tabs[0].invertTab = false
mpackets[0].invertTab = false
this.lineTab = 'total'
this.legendSelectChange(tabs[0], 0)
this.legendSelectChange(mpackets[0], 0)
this.$nextTick(() => {
this.echartsInit(this.tabs, true)
this.echartsInit(this.mpackets, true)
})
} else {
if (n) this.lineTab = ''
this.$nextTick(() => {
this.echartsInit(this.tabs, show)
this.echartsInit(this.mpackets, show)
if (!this.lineRefer) this.lineRefer = 'Average'
})
}
@@ -655,7 +657,7 @@ export default {
this.chartOption = null
this.timer = setTimeout(() => {
if (this.lineTab && this.metric !== 'Sessions/s') {
const data = this.tabsTemplate.find(t => t.class === this.lineTab)
const data = this.mpackets.find(t => t.class === this.lineTab)
this.activeChange(data, data.positioning)
} else {
this.init()

View File

@@ -197,6 +197,7 @@ export default {
const lastCycleTrafficRequest = axios.get(api.npm.overview.appTrafficAnalysis, { params: { ...params, cycle: 1 } })
this.toggleLoading(true)
Promise.all([currentTrafficRequest, lastCycleTrafficRequest]).then(res => {
// console.log('打印数据=====', res)
if (res[0].data.code === 200 && res[1].data.code === 200) {
this.showError = false
this.errorMsg = ''

View File

@@ -1,11 +1,29 @@
<template>
<div class="npm-app-event">
<!-- <div class="metric-select">
<el-select
v-model="metric"
class="option__select select-column"
popper-class="option-popper common-select"
:popper-append-to-body="false"
key="tabMetric"
@change="changeMetric"
size="mini"
width="100">
<el-option
v-for="item in options"
:key="item.label"
:label="item.label"
:value="item.value"
/>
</el-select>
<span>{{ $t('network.metric') }}</span>
</div>-->
<el-table
id="tabTable"
ref="dataTable"
:data="tableData"
class="npm-app-event-table"
:row-class-name="rowClassName"
height="100%"
empty-text=""
>
@@ -15,33 +33,34 @@
<span class="data-column__span">{{ $t(item.label) }}</span>
</template>
<template #default="scope" :column="item">
<div class="data-app-event-table" :test-id="`${item.prop}${scope.row.index}`">
<div class="data-app-event-table">
<template v-if="item.prop === 'domain' ||item.prop === 'appName' ||item.prop === 'serverIp' ">
<span class="data-applications">{{ scope.row[item.prop] }}</span>
</template>
<template v-else-if="item.prop === 'eventSeverity'" >
<template v-else-if="item.prop === 'eventSeverity'">
<template v-if="scope.row[item.prop]==='critical'">
<div v-for="item in 5" class="red-dot" :key="item" :test-id="`eventSeverityValue${scope.row.index}${item}`"></div>
<div v-for="item in 5" class="red-dot" :key="item"></div>
</template>
<template v-else-if="scope.row[item.prop]==='high'">
<div v-for="item in 4" class="red-dot" :key="item" :test-id="`eventSeverityValue${scope.row.index}${item}`"></div>
<div v-for="item in 1" class="grey-dot" :key="item" :test-id="`eventSeverityValue${scope.row.index}${4+item}`"></div>
<div v-for="item in 4" class="red-dot" :key="item"></div>
<div class="grey-dot"></div>
</template>
<template v-else-if="scope.row[item.prop]==='medium'">
<div v-for="item in 3" class="red-dot" :key="item" :test-id="`eventSeverityValue${scope.row.index}${item}`"></div>
<div v-for="item in 2" class="grey-dot" :key="item" :test-id="`eventSeverityValue${scope.row.index}${3+item}`"></div>
<div v-for="item in 3" class="red-dot" :key="item"></div>
<div v-for="item in 2" class="grey-dot" :key="item"></div>
</template>
<template v-else-if="scope.row[item.prop]==='low'">
<div v-for="item in 2" class="red-dot" :key="item" :test-id="`eventSeverityValue${scope.row.index}${item}`"></div>
<div v-for="item in 3" class="grey-dot" :key="item" :test-id="`eventSeverityValue${scope.row.index}${2+item}`"></div>
<div v-for="item in 2" class="red-dot" :key="item"></div>
<div v-for="item in 3" class="grey-dot" :key="item"></div>
</template>
<template v-else-if="scope.row[item.prop]==='info'">
<div v-for="item in 1" class="red-dot" :key="item" :test-id="`eventSeverityValue${scope.row.index}${item}`"></div>
<div v-for="item in 4" class="grey-dot" :key="item" :test-id="`eventSeverityValue${scope.row.index}${1+item}`"></div>
<div v-for="item in 1" class="red-dot" :key="item"></div>
<div v-for="item in 4" class="grey-dot" :key="item"></div>
</template>
<span class="data-severity">{{ scope.row[item.prop] }}</span>
</template>
<template v-else-if="item.prop === 'eventType'">
<!-- <span class="data-eventType" v-for="type in scope.row[item.prop]">{{type}}</span>-->
<span class="data-eventType">{{ scope.row[item.prop] }}</span>
</template>
<template v-else-if="item.prop === 'count'">
@@ -134,10 +153,6 @@ export default {
this.init()
},
methods: {
rowClassName ({ row, rowIndex }) {
// 把每一行的索引放进row
row.index = rowIndex
},
init () {
this.toggleLoading(true)
this.isNoData = false

View File

@@ -13,14 +13,14 @@
<div class="npm-event-pie-legend-title" v-if="chartData.length > 0">{{ $t('overall.type') }}</div>
<template v-for="(legend, index) in chartData" :key="index">
<div class="npm-event-pie-legend-type">
<div class="npm-event-pie-legend-type-severity" :test-id="`testNode${index}`">{{legend.name}}</div>
<div class="npm-event-pie-legend-type-severity">{{legend.name}}</div>
</div>
</template>
</div>
<div class="npm-event-pie-legend">
<div class="npm-event-pie-legend-title" v-if="chartData.length > 0">{{ $t('network.total') }}</div>
<template v-for="(legend, index) in chartData" :key="index">
<div class="npm-event-pie-legend-total" :test-id="`total${index}`">{{legend.value}}</div>
<div class="npm-event-pie-legend-total">{{legend.value}}</div>
</template>
</div>
</div>
@@ -31,6 +31,7 @@
<script>
import { shallowRef } from 'vue'
import { get } from '@/utils/http'
import { api } from '@/utils/api'
import * as echarts from 'echarts'
import { pieChartOption3 } from '@/views/charts2/charts/options/echartOption'
@@ -38,7 +39,6 @@ import { getSecond } from '@/utils/date-util'
import ChartNoData from '@/views/charts/charts/ChartNoData'
import chartMixin from '@/views/charts2/chart-mixin'
import ChartError from '@/components/common/Error'
import axios from 'axios'
export default {
name: 'NpmEventsByType',
@@ -108,8 +108,7 @@ export default {
type: 'severity'
}
this.toggleLoading(true)
axios.get(api.npm.events.recentEvents, { params: params }).then(res => {
res = res.data
get(api.npm.events.recentEvents, params).then(res => {
if (res.code === 200) {
this.showError = false
this.isNoData = res.data.result.length === 0
@@ -127,9 +126,7 @@ export default {
this.chartData = arrData.sort((a, b) => { return b.value - a.value })
this.$nextTick(() => {
if (this.chartData.length > 0) {
if (!this.isUnitTesting) {
this.init()
}
this.init()
}
})
} else {

View File

@@ -29,7 +29,7 @@
<template v-else-if="item.prop === 'eventType'">
<span class="data-recent-table-eventType" :test-id="`eventType-${scope.row.eventType}-${scope.$index}`">{{scope.row[item.prop]}}</span>
</template>
<span v-else-if="scope.row[item.prop]" :test-id="`startTime-${scope.$index}`">{{scope.row[item.prop]}}</span>
<span v-else-if="scope.row[item.prop]" :test-id="`startTime-${scope.row.startTime}-${scope.$index}`">{{scope.row[item.prop]}}</span>
<span v-else>-</span>
</div>
</template>

View File

@@ -71,7 +71,7 @@ export default {
unitConvert,
unitTypes,
side: '',
tabs: [
mpackets: [
{ name: this.$t('network.total'), show: true, positioning: 0, data: [], unitType: 'number' },
{ name: this.$t('network.inbound'), show: true, positioning: 1, data: [], unitType: 'number' },
{ name: this.$t('network.outbound'), show: true, positioning: 2, data: [], unitType: 'number' },
@@ -199,7 +199,7 @@ export default {
this.showError = false
this.isNoData = res.data.result.length === 0
if (this.isNoData) {
this.tabs = [
this.mpackets = [
{ name: this.$t('network.total'), show: true, positioning: 0, data: [], unitType: 'number' },
{ name: this.$t('network.inbound'), show: true, positioning: 1, data: [], unitType: 'number' },
{ name: this.$t('network.outbound'), show: true, positioning: 2, data: [], unitType: 'number' },
@@ -249,7 +249,7 @@ export default {
this.showError = false
this.isNoData = npmLineData.length === 0
if (this.isNoData) {
this.tabs = [
this.mpackets = [
{ name: this.$t('network.total'), show: true, positioning: 0, data: [], unitType: 'number' },
{ name: this.$t('network.inbound'), show: true, positioning: 1, data: [], unitType: 'number' },
{ name: this.$t('network.outbound'), show: true, positioning: 2, data: [], unitType: 'number' },
@@ -320,7 +320,7 @@ export default {
})
this.chartOption.tooltip.formatter = (params) => {
params.forEach(t => {
this.tabs.forEach(e => {
this.mpackets.forEach(e => {
if (e.name === t.seriesName) {
t.borderColor = chartColor3[e.positioning]
}
@@ -405,24 +405,24 @@ export default {
})
}
lineData.splice(0, 1)
const tabs = _.cloneDeep(this.tabs)
const mpackets = _.cloneDeep(this.mpackets)
const npmQuantity = _.cloneDeep(this.npmQuantity)
if (val === 'Sessions/s') {
lineData.forEach((d, i) => {
tabs[i].data = d.values
tabs[i].analysis = d.analysis
mpackets[i].data = d.values
mpackets[i].analysis = d.analysis
})
tabs.forEach((e, i) => {
mpackets.forEach((e, i) => {
if (i !== 0) {
e.show = false
}
})
this.tabs = tabs
this.echartsInit(this.tabs)
this.mpackets = mpackets
this.echartsInit(this.mpackets)
} else if (val !== 'Bits/s' && val !== 'Packets/s' && val !== 'Sessions/s') {
this.legendInit(lineData, npmQuantity, true)
} else {
this.legendInit(lineData, tabs, false)
this.legendInit(lineData, mpackets, false)
}
},
legendInit (data, npmData, show) {
@@ -445,8 +445,8 @@ export default {
npmData.forEach((e) => {
e.show = true
})
this.tabs = npmData
this.echartsInit(this.tabs)
this.mpackets = npmData
this.echartsInit(this.mpackets)
}
}
},

View File

@@ -294,7 +294,7 @@ export default {
const chartDom = document.getElementById(`eventSeverityTrendBar${this.pageType}`)
const eventSeverityTrendOption = this.$_.cloneDeep(multipleBarOption)
const xData = []
let xData = []
dataMap.forEach(function (value) {
// eventSeverityTrendOption.series[Number(getSeriesIndex(key))].data = value.map(v => Number(v[1]))
value.forEach(item => {
@@ -303,6 +303,9 @@ export default {
}
})
})
xData = xData.sort((a, b) => {
return new Date(a) - new Date(b)
})
eventSeverityTrendOption.series.forEach(serie => {
const seriesData = []
xData.forEach(item => {

View File

@@ -1,130 +0,0 @@
import linkBlock from '@/views/charts2/charts/linkMonitor/LinkBlock'
import { mount } from '@vue/test-utils'
import axios from 'axios'
const mockGet1 = {
data: { status: 200, code: 200, queryKey: '549b4c3bcabf0feee193b834671879de', success: true, message: null, statistics: { elapsed: 3, rows_read: 11480, bytes_read: 459200, result_size: 1214, result_rows: 21 }, job: null, formatType: 'json', meta: [{ name: 'link_id', type: 'string', category: 'Dimension' }, { name: 'egress_bytes', type: 'long', category: 'Metric' }, { name: 'ingress_bytes', type: 'long', category: 'Metric' }], data: { resultType: 'table', result: [{ linkId: '257', egressBytes: '0', egressBitsRate: 0, ingressBytes: '493739879', ingressBitsRate: 1097199.76 }, { linkId: '256', egressBytes: '4147998874', egressBitsRate: 9217775.28, ingressBytes: '0', ingressBitsRate: 0 }, { linkId: '1024', egressBytes: '4229808296', egressBitsRate: 9399574, ingressBytes: '0', ingressBitsRate: 0 }, { linkId: '1793', egressBytes: '0', egressBitsRate: 0, ingressBytes: '604840505', ingressBitsRate: 1344090 }, { linkId: '2817', egressBytes: '0', egressBitsRate: 0, ingressBytes: '430811638', ingressBitsRate: 957359.2 }, { linkId: '0', egressBytes: '819878366014', egressBitsRate: 1821951924.48, ingressBytes: '140774357362', ingressBitsRate: 312831905.28 }, { linkId: '1281', egressBytes: '0', egressBitsRate: 0, ingressBytes: '544675122', ingressBitsRate: 1210389.12 }, { linkId: '2049', egressBytes: '0', egressBitsRate: 0, ingressBytes: '711346274', ingressBitsRate: 1580769.52 }, { linkId: '1536', egressBytes: '4195896971', egressBitsRate: 9324215.52, ingressBytes: '0', ingressBitsRate: 0 }, { linkId: '2305', egressBytes: '0', egressBitsRate: 0, ingressBytes: '524865003', ingressBitsRate: 1166366.64 }, { linkId: '1792', egressBytes: '4145790227', egressBitsRate: 9212867.2, ingressBytes: '0', ingressBitsRate: 0 }, { linkId: '1025', egressBytes: '0', egressBitsRate: 0, ingressBytes: '492227445', ingressBitsRate: 1093838.8 }, { linkId: '2816', egressBytes: '4000074817', egressBitsRate: 8889055.12, ingressBytes: '0', ingressBitsRate: 0 }, { linkId: '513', egressBytes: '0', egressBitsRate: 0, ingressBytes: '1444814826', ingressBitsRate: 3210699.6 }, { linkId: '768', egressBytes: '4370006099', egressBitsRate: 9711124.64, ingressBytes: '0', ingressBitsRate: 0 }, { linkId: '512', egressBytes: '3894190397', egressBitsRate: 8653756.4, ingressBytes: '0', ingressBitsRate: 0 }, { linkId: '769', egressBytes: '0', egressBitsRate: 0, ingressBytes: '1877580759', ingressBitsRate: 4172401.68 }, { linkId: '2304', egressBytes: '3767761711', egressBitsRate: 8372803.84, ingressBytes: '0', ingressBitsRate: 0 }, { linkId: '1537', egressBytes: '0', egressBitsRate: 0, ingressBytes: '367986916', ingressBitsRate: 817748.72 }, { linkId: '1280', egressBytes: '4040444894', egressBitsRate: 8978766.4, ingressBytes: '0', ingressBitsRate: 0 }, { linkId: '2048', egressBytes: '4682050724', egressBitsRate: 10404557.2, ingressBytes: '0', ingressBitsRate: 0 }] }, originalUrl: 'http://192.168.44.55:9999?query=SELECT%20arrayJoin%28splitByChar%28%27_%27%2C%20concat%28toString%28common_egress_link_id%29%2C%20%27_%27%2C%20toString%28common_ingress_link_id%29%29%29%29%20AS%20link_id%2CSUM%28IF%28toString%28common_egress_link_id%29%20%3D%20link_id%2C%20traffic_outbound_byte%2C%200%29%29%20AS%20egress_bytes%2CSUM%28IF%28toString%28common_ingress_link_id%29%20%3D%20link_id%2C%20traffic_inbound_byte%2C%200%29%29%20AS%20ingress_bytes%20FROM%20metric_link%20WHERE%20stat_time%20%3E%3D%201675303793%20AND%20stat_time%20%3C%201675307393%20GROUP%20BY%20link_id&format=json&option=real-time', msg: 'OK' }
}
const mockGet2 = {
data: { status: 200, code: 200, queryKey: 'ee2e820b1275748167cdee82b2b4ea40', success: true, message: null, statistics: { elapsed: 3, rows_read: 11480, bytes_read: 618564, result_size: 1053, result_rows: 10 }, job: null, formatType: 'json', meta: [{ name: 'egress_link_direction', type: 'string', category: 'Dimension' }, { name: 'ingress_link_direction', type: 'string', category: 'Dimension' }, { name: 'egress_bytes', type: 'long', category: 'Metric' }, { name: 'ingress_bytes', type: 'long', category: 'Metric' }], data: { resultType: 'table', result: [{ egressLinkDirection: '太原', ingressLinkDirection: '西宁', egressBytes: '2407509269', egressBitsRate: 5350020.56, ingressBytes: '193368911', ingressBitsRate: 429708.72 }, { egressLinkDirection: '西安', ingressLinkDirection: '西安', egressBytes: '3609358392', egressBitsRate: 8020796.4, ingressBytes: '345009143', ingressBitsRate: 766686.96 }, { egressLinkDirection: '西宁', ingressLinkDirection: '西安', egressBytes: '1273508499', egressBitsRate: 2830018.88, ingressBytes: '122646511', ingressBitsRate: 272547.84 }, { egressLinkDirection: '太原', ingressLinkDirection: '太原', egressBytes: '14840136119', egressBitsRate: 32978080.24, ingressBytes: '3386427658', ingressBitsRate: 7525394.8 }, { egressLinkDirection: '西安', ingressLinkDirection: '太原', egressBytes: '7070361369', egressBitsRate: 15711914.16, ingressBytes: '1853445429', ingressBitsRate: 4118767.6 }, { egressLinkDirection: '西宁', ingressLinkDirection: '太原', egressBytes: '2619231460', egressBitsRate: 5820514.32, ingressBytes: '291561196', ingressBitsRate: 647913.76 }, { egressLinkDirection: '', ingressLinkDirection: '', egressBytes: '409939183007', egressBitsRate: 910975962.24, ingressBytes: '70387178681', ingressBitsRate: 156415952.64 }, { egressLinkDirection: '太原', ingressLinkDirection: '西安', egressBytes: '7808050741', egressBitsRate: 17351223.84, ingressBytes: '1001570985', ingressBitsRate: 2225713.28 }, { egressLinkDirection: '西宁', ingressLinkDirection: '西宁', egressBytes: '337068337', egressBitsRate: 749040.72, ingressBytes: '165230290', ingressBitsRate: 367178.4 }, { egressLinkDirection: '西安', ingressLinkDirection: '西宁', egressBytes: '1508798824', egressBitsRate: 3352886.24, ingressBytes: '133628244', ingressBitsRate: 296951.68 }] }, originalUrl: 'http://192.168.44.55:9999?query=SELECT%20egress_link_direction%20AS%20egress_link_direction%2C%20ingress_link_direction%20AS%20ingress_link_direction%2C%20SUM%28traffic_outbound_byte%29%20AS%20egress_bytes%2C%20SUM%28traffic_inbound_byte%29%20AS%20ingress_bytes%20FROM%20metric_link%20WHERE%20stat_time%20%3E%3D%201675303793%20AND%20stat_time%20%3C%201675307393%20GROUP%20BY%20egress_link_direction%2C%20ingress_link_direction&format=json&option=real-time', msg: 'OK' }
}
const linkInfoData = [{ originalLinkId: '256', linkId: 'Hundredgige1', direction: 'egress', nextHop: '西安', bandwidth: 100000000000 }, { originalLinkId: '257', linkId: 'Hundredgige1', direction: 'ingress', nextHop: '西安', bandwidth: 100000000000 }, { originalLinkId: '512', linkId: 'Hundredgige2', direction: 'egress', nextHop: '太原', bandwidth: 100000000000 }, { originalLinkId: '513', linkId: 'Hundredgige2', direction: 'ingress', nextHop: '太原', bandwidth: 100000000000 }, { originalLinkId: '768', linkId: 'Hundredgige3', direction: 'egress', nextHop: '太原', bandwidth: 100000000000 }, { originalLinkId: '769', linkId: 'Hundredgige3', direction: 'ingress', nextHop: '太原', bandwidth: 100000000000 }, { originalLinkId: '1024', linkId: 'Hundredgige4', direction: 'egress', nextHop: '西宁', bandwidth: 100000000000 }, { originalLinkId: '1025', linkId: 'Hundredgige4', direction: 'ingress', nextHop: '西宁', bandwidth: 100000000000 }, { originalLinkId: '1280', linkId: 'Hundredgige5', direction: 'egress', nextHop: '西安', bandwidth: 100000000000 }, { originalLinkId: '1281', linkId: 'Hundredgige5', direction: 'ingress', nextHop: '西安', bandwidth: 100000000000 }, { originalLinkId: '1536', linkId: 'Hundredgige6', direction: 'egress', nextHop: '太原', bandwidth: 100000000000 }, { originalLinkId: '1537', linkId: 'Hundredgige6', direction: 'ingress', nextHop: '太原', bandwidth: 100000000000 }, { originalLinkId: '1792', linkId: 'Hundredgige7', direction: 'egress', nextHop: '太原', bandwidth: 100000000000 }, { originalLinkId: '1793', linkId: 'Hundredgige7', direction: 'ingress', nextHop: '太原', bandwidth: 100000000000 }, { originalLinkId: '2048', linkId: 'Hundredgige8', direction: 'egress', nextHop: '太原', bandwidth: 100000000000 }, { originalLinkId: '2049', linkId: 'Hundredgige8', direction: 'ingress', nextHop: '太原', bandwidth: 100000000000 }, { originalLinkId: '2304', linkId: 'Hundredgige9', direction: 'egress', nextHop: '太原', bandwidth: 100000000000 }, { originalLinkId: '2305', linkId: 'Hundredgige9', direction: 'ingress', nextHop: '太原', bandwidth: 100000000000 }, { originalLinkId: '2816', linkId: 'Hundredgige10', direction: 'egress', nextHop: '西安', bandwidth: 100000000000 }, { originalLinkId: '2817', linkId: 'Hundredgige10', direction: 'ingress', nextHop: '西安', bandwidth: 100000000000 }]
const linkInfo = JSON.stringify(linkInfoData)
const timeFilter = {
dateRangeValue: -1,
startTime: 1673244000000,
endTime: 1673247600000
}
var wrapper = null
/**
* 进行axios请求并挂载vue实例
* @param list
*/
function axiosPostAndMounted (list) {
require('vue-router').useRoute.mockReturnValue({ query: {} })
const data = list || mockGet1
// 模拟axios返回数据
axios.get.mockImplementation(url => {
switch (url) {
case '/interface/link/overview/analysis':
return Promise.resolve(data)
case '/interface/link/overview/nextHopAnalysis':
return Promise.resolve(mockGet2)
}
})
// 模拟localStorage获取数据
// eslint-disable-next-line no-proto
jest.spyOn(localStorage.__proto__, 'getItem').mockImplementation(key => linkInfo)
// 加载vue组件获得实例
wrapper = mount(linkBlock, {
propsData: {
timeFilter
}
})
}
describe('views/charts2/charts/linkMonitor/LinkBlock.vue测试', () => {
test('测试链路蜂窝图和下一跳蜂窝图从大到小排列', async () => {
axiosPostAndMounted()
// 延迟等待渲染。使用wrapper.vm.$nextTick有时不管用例如组件中使用了setTimeout的时候
await new Promise(resolve => setTimeout(() => {
const linkBlockTotal0 = wrapper.get('[test-id="linkBlockTotal0"]')
const linkBlockTotal1 = wrapper.get('[test-id="linkBlockTotal1"]')
const linkBlockTotal2 = wrapper.get('[test-id="linkBlockTotal2"]')
const linkBlockTotal3 = wrapper.get('[test-id="linkBlockTotal3"]')
const linkBlockTotal4 = wrapper.get('[test-id="linkBlockTotal4"]')
const linkBlockTotal5 = wrapper.get('[test-id="linkBlockTotal5"]')
const linkBlockTotal6 = wrapper.get('[test-id="linkBlockTotal6"]')
const linkBlockTotal7 = wrapper.get('[test-id="linkBlockTotal7"]')
const linkBlockTotal8 = wrapper.get('[test-id="linkBlockTotal8"]')
const linkBlockTotal9 = wrapper.get('[test-id="linkBlockTotal9"]')
expect(linkBlockTotal0.text()).toBe('13.88 Mbps')
expect(linkBlockTotal1.text()).toBe('11.99 Mbps')
expect(linkBlockTotal2.text()).toBe('11.86 Mbps')
expect(linkBlockTotal3.text()).toBe('10.56 Mbps')
expect(linkBlockTotal4.text()).toBe('10.49 Mbps')
expect(linkBlockTotal5.text()).toBe('10.31 Mbps')
expect(linkBlockTotal6.text()).toBe('10.19 Mbps')
expect(linkBlockTotal7.text()).toBe('10.14 Mbps')
expect(linkBlockTotal8.text()).toBe('9.85 Mbps')
expect(linkBlockTotal9.text()).toBe('9.54 Mbps')
const nextHopTotal0 = wrapper.get('[test-id="nextHopTotal0"]')
const nextHopTotal1 = wrapper.get('[test-id="nextHopTotal1"]')
const nextHopTotal2 = wrapper.get('[test-id="nextHopTotal2"]')
expect(nextHopTotal0.text()).toBe('67.97 Mbps')
expect(nextHopTotal1.text()).toBe('30.35 Mbps')
expect(nextHopTotal2.text()).toBe('10.49 Mbps')
resolve()
}, 200))
})
test('鼠标移动到链路蜂窝图第一个测试total显示', async () => {
// 以"Hundredgige3"为例对应出方向linkId为768对应出方向流量为9711124.64
// 对应入方向linkId为769对应入方向流量为4172401.68修改流量测试total
const list = JSON.parse(JSON.stringify(mockGet1))
list.data.data.result[14].egressBitsRate = 9000000.00
list.data.data.result[16].ingressBitsRate = 4000000.00
axiosPostAndMounted(list)
// 延迟等待渲染。使用wrapper.vm.$nextTick有时不管用例如组件中使用了setTimeout的时候
await new Promise(resolve => setTimeout(() => {
const linkBlockTotal0 = wrapper.get('[test-id="linkBlockTotal0"]')
const linkBlockEgressUsage0 = wrapper.get('[test-id="linkBlockEgressUsage0"]')
const linkBlockIngressUsage0 = wrapper.get('[test-id="linkBlockIngressUsage0"]')
expect(linkBlockTotal0.text()).toBe('13 Mbps')
expect(linkBlockEgressUsage0.text()).toBe('< 0.01%')
expect(linkBlockIngressUsage0.text()).toBe('< 0.01%')
resolve()
}, 200))
})
test('鼠标移动到链路蜂窝图第一个,测试出入流量占比', async () => {
// 以"Hundredgige3"为例修改其出入流量为100000000000测试上行流量占比为100%下行占比为0%的情况
const list = JSON.parse(JSON.stringify(mockGet1))
list.data.data.result[14].egressBitsRate = 100000000000.00
list.data.data.result[16].ingressBitsRate = 0
axiosPostAndMounted(list)
// 延迟等待渲染。使用wrapper.vm.$nextTick有时不管用例如组件中使用了setTimeout的时候
await new Promise(resolve => setTimeout(() => {
const linkBlockTotal0 = wrapper.get('[test-id="linkBlockTotal0"]')
const linkBlockEgressUsage0 = wrapper.get('[test-id="linkBlockEgressUsage0"]')
const linkBlockIngressUsage0 = wrapper.get('[test-id="linkBlockIngressUsage0"]')
expect(linkBlockTotal0.text()).toBe('100 Gbps')
expect(linkBlockEgressUsage0.text()).toBe('100.00%')
expect(linkBlockIngressUsage0.text()).toBe('0%')
resolve()
}, 200))
})
})

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -3,7 +3,7 @@ import { mount } from '@vue/test-utils'
import axios from 'axios'
const mockGet = {
data: { status: 200, code: 200, queryKey: 'dec6723e173e8fa2b00917dc597bfb27', success: true, message: null, statistics: { elapsed: 0, rows_read: 2, result_size: 58, result_rows: 1 }, job: null, formatType: 'json', meta: [{ name: 'attack_event_count', type: 'long', category: 'Metric' }, { name: 'attacker_count', type: 'long', category: 'Metric' }, { name: 'victim_count', type: 'long', category: 'Metric' }], data: { resultType: 'object', result: [{ attackEventCount: 1200000, attackerCount: 2687878, victimCount: 36676767 }] }, originalUrl: 'http://192.168.44.55:9999?query=SELECT%20COUNT%28*%29%20AS%20attack_event_count%2C%20COUNT%28DISTINCT%28offender_ip%29%29%20AS%20attacker_count%2C%20COUNT%28DISTINCT%28victim_ip%29%29%20AS%20victim_count%20FROM%20security_event%20WHERE%20start_time%20%3E%3D%201675043912%20AND%20start_time%20%3C%201675047512%20AND%20security_type%20%3D%20%27ddos%27&format=json&option=real-time', msg: 'OK' }
data: {"status":200,"code":200,"queryKey":"dec6723e173e8fa2b00917dc597bfb27","success":true,"message":null,"statistics":{"elapsed":0,"rows_read":2,"result_size":58,"result_rows":1},"job":null,"formatType":"json","meta":[{"name":"attack_event_count","type":"long","category":"Metric"},{"name":"attacker_count","type":"long","category":"Metric"},{"name":"victim_count","type":"long","category":"Metric"}],"data":{"resultType":"object","result":[{"attackEventCount":1200000,"attackerCount":2687878,"victimCount":36676767}]},"originalUrl":"http://192.168.44.55:9999?query=SELECT%20COUNT%28*%29%20AS%20attack_event_count%2C%20COUNT%28DISTINCT%28offender_ip%29%29%20AS%20attacker_count%2C%20COUNT%28DISTINCT%28victim_ip%29%29%20AS%20victim_count%20FROM%20security_event%20WHERE%20start_time%20%3E%3D%201675043912%20AND%20start_time%20%3C%201675047512%20AND%20security_type%20%3D%20%27ddos%27&format=json&option=real-time","msg":"OK"}
}
const timeFilter = {

View File

@@ -1,77 +1,22 @@
import NetworkOverviewLine from '@/views/charts2/charts/networkOverview/NetworkOverviewLine'
import { mount } from '@vue/test-utils'
import axios from 'axios'
import mockData from './NetworkOverviewLineMockData'
const mockGet = {
data: {"status":200,"code":200,"success":true,"message":null,"formatType":"json","data":{"resultType":"object","result":[{"type":"bytes","totalBitsRate":{"values":[[1673247564,"96801019.52"]],"analysis":{"avg":"112042808.24","max":"301842105.76","min":"52096324","p95":"168089003.35199997"}},"inboundBitsRate":{"values":[[1673247564,"11814508.48"]],"analysis":{"avg":"18587597.36","max":"137528138.88","min":"3181142.88","p95":"49561521.447999954"}},"outboundBitsRate":{"values":[[1673247564,"84282965.52"]],"analysis":{"avg":"87557861.44","max":"290402258","min":"45337684.48","p95":"121041718.81199999"}},"internalBitsRate":{"values":[[1673247564,"9125.12"]],"analysis":{"avg":"278114.32","max":"2215460.48","min":"0","p95":"923494.5719999998"}},"throughBitsRate":{"values":[[1673247564,"694420.48"]],"analysis":{"avg":"5619235.12","max":"42455480.24","min":"262607.76","p95":"13559588.195999999"}},"other":{"values":[[1673247564,"0.00"]],"analysis":{"avg":"0.01","max":"0.08","min":"0.00","p95":"0.08"}}},{"type":"packets","totalPacketsRate":{"values":[[1673247564,"12077.53"]],"analysis":{"avg":"14062.37","max":"32840.42","min":"6564.17","p95":"20923.167999999987"}},"inboundPacketsRate":{"values":[[1673247564,"3865.58"]],"analysis":{"avg":"4241.61","max":"15460.03","min":"1918.22","p95":"8549.799999999997"}},"outboundPacketsRate":{"values":[[1673247564,"8118.89"]],"analysis":{"avg":"9170.98","max":"27134.58","min":"4510.25","p95":"13690.540999999996"}},"internalPacketsRate":{"values":[[1673247564,"15.89"]],"analysis":{"avg":"35.95","max":"276.47","min":"0.00","p95":"122.49749999999999"}},"throughPacketsRate":{"values":[[1673247564,"77.17"]],"analysis":{"avg":"613.82","max":"3768.56","min":"42.92","p95":"1279.757499999999"}},"other":{"values":[[1673247564,"0.00"]],"analysis":{"avg":"0","max":"0.01","min":"0.00","p95":"0.01"}}},{"type":"sessions","totalSessionsRate":{"values":[[1673247564,"29.92"]],"analysis":{"avg":"29.89","max":"29.92","min":"29.67","p95":"29.92"}}}]},"msg":"OK"}
}
const timeFilter = {
dateRangeValue: -1,
startTime: 1673244000000,
endTime: 1673247600000
}
const chart = {"id":1,"name":"network overview line","i18n":"","panelId":1,"pid":0,"type":102,"x":0,"y":0,"w":19,"h":6,"children":[],"panel":{"id":1,"name":"Network Overview"},"i":1,"category":"echarts","firstShow":false,"moved":false}
function init () {
require('vue-router').useRoute.mockReturnValue({ query: {} })
}
const chart = {"id":1,"name":"network overview line","i18n":"","panelId":1,"pid":0,"type":102,"x":0,"y":0,"w":19,"h":6,"params":{},"cby":1,"ctime":"2022-07-06 16:59:22","uby":1,"utime":"2022-07-06 16:59:22","remark":"","state":1,"system":0,"buildIn":0,"uuser":{"id":1,"name":null,"username":"admin","salt":null,"lang":null,"theme":null,"lastLoginIp":null,"lastLoginTime":null,"ctime":null,"cby":null,"email":null,"mobile":null,"status":null,"source":null,"buildIn":null,"roleIds":null,"usergroupIds":null,"roles":null,"apiKeyId":null},"cuser":{"id":1,"name":null,"username":"admin","salt":null,"lang":null,"theme":null,"lastLoginIp":null,"lastLoginTime":null,"ctime":null,"cby":null,"email":null,"mobile":null,"status":null,"source":null,"buildIn":null,"roleIds":null,"usergroupIds":null,"roles":null,"apiKeyId":null},"children":[],"parent":null,"panel":{"id":1,"name":"Network Overview","i18n":null,"type":null,"params":null,"cby":null,"ctime":null,"uby":null,"utime":null,"remark":null,"state":null,"buildIn":null,"uuser":null,"cuser":null},"i":1,"category":"echarts","firstShow":false,"moved":false}
describe('views/charts2/charts/networkOverview/NetworkOverviewLine.vue测试', () => {
test('Metric=Bits/s无数据空数组', async () => {
init()
axios.get.mockResolvedValue(mockData.empty)
const wrapper = mount(NetworkOverviewLine, {
propsData: {
timeFilter,
chart
}
})
// 延迟等待渲染。使用wrapper.vm.$nextTick有时不管用例如组件中使用了setTimeout的时候
await new Promise(resolve => setTimeout(async () => {
const textNode0 = await wrapper.get('[test-id="tabContent0"]')
const textNode1 = await wrapper.get('[test-id="tabContent1"]')
const textNode2 = await wrapper.get('[test-id="tabContent2"]')
const textNode3 = await wrapper.get('[test-id="tabContent3"]')
const textNode4 = await wrapper.get('[test-id="tabContent4"]')
const textNode5 = await wrapper.get('[test-id="tabContent5"]')
expect(textNode0.text()).toEqual('-')
expect(textNode1.text()).toEqual('-')
expect(textNode2.text()).toEqual('-')
expect(textNode3.text()).toEqual('-')
expect(textNode4.text()).toEqual('-')
expect(textNode5.text()).toEqual('-')
resolve()
}, 200))
})
test('Metric=Bits/s0和大数值', async () => {
init()
axios.get.mockResolvedValue(mockData.bytes.boundary)
const wrapper = mount(NetworkOverviewLine, {
propsData: {
timeFilter,
chart
}
})
// 延迟等待渲染。使用wrapper.vm.$nextTick有时不管用例如组件中使用了setTimeout的时候
await new Promise(resolve => setTimeout(async () => {
// total页签固定显示数据是0也一样
const titleNode0 = await wrapper.get('[test-id="tabTitle0"]')
const titleNode1 = await wrapper.get('[test-id="tabTitle2"]')
const titleNode2 = await wrapper.get('[test-id="tabTitle5"]')
const textNode0 = await wrapper.get('[test-id="tabContent0"]')
const textNode1 = await wrapper.get('[test-id="tabContent2"]')
const textNode2 = await wrapper.get('[test-id="tabContent5"]')
expect(titleNode0.text()).toEqual('network.total')
expect(titleNode1.text()).toEqual('network.outbound')
expect(titleNode2.text()).toEqual('network.other')
expect(textNode0.text()).toEqual('0bps')
expect(textNode1.text()).toEqual('95.23Ebps')
expect(textNode2.text()).toEqual('0.01bps')
resolve()
}, 200))
})
test('Metric=Bits/s点击第三个tab', async () => {
init()
require('vue-router').useRoute.mockReturnValue({ query: {} })
// 模拟axios返回数据
axios.get.mockResolvedValue(mockData.common)
axios.get.mockResolvedValue(mockGet)
// 加载vue组件获得实例
const wrapper = mount(NetworkOverviewLine, {
propsData: {
@@ -79,12 +24,11 @@ describe('views/charts2/charts/networkOverview/NetworkOverviewLine.vue测试', (
chart
}
})
const textNode0 = await wrapper.get('[test-id="tabContent0"]')
const textNode1 = await wrapper.get('[test-id="tabContent1"]')
const textNode2 = await wrapper.get('[test-id="tabContent2"]')
// 延迟等待渲染。使用wrapper.vm.$nextTick有时不管用例如组件中使用了setTimeout的时候
await new Promise(resolve => setTimeout(async () => {
const textNode0 = await wrapper.get('[test-id="tabContent0"]')
const textNode1 = await wrapper.get('[test-id="tabContent1"]')
const textNode2 = await wrapper.get('[test-id="tabContent2"]')
await new Promise(resolve => setTimeout(() => {
expect(textNode0.text()).toEqual('112.04Mbps')
expect(textNode1.text()).toEqual('18.59Mbps')
expect(textNode2.text()).toEqual('87.56Mbps')
@@ -97,9 +41,9 @@ describe('views/charts2/charts/networkOverview/NetworkOverviewLine.vue测试', (
expect(textNode3.classes()).toContain('is-active')
})
test('Metric=Packets/s', async () => {
init()
require('vue-router').useRoute.mockReturnValue({ query: {} })
// 模拟axios返回数据
axios.get.mockResolvedValue(mockData.common)
axios.get.mockResolvedValue(mockGet)
// 加载vue组件获得实例
const wrapper = mount(NetworkOverviewLine, {
propsData: {
@@ -108,11 +52,10 @@ describe('views/charts2/charts/networkOverview/NetworkOverviewLine.vue测试', (
metric: 'Packets/s'
}
})
await new Promise(resolve => setTimeout(async () => {
const textNode0 = await wrapper.get('[test-id="tabContent0"]')
const textNode1 = await wrapper.get('[test-id="tabContent1"]')
const textNode2 = await wrapper.get('[test-id="tabContent2"]')
const textNode0 = await wrapper.get('[test-id="tabContent0"]')
const textNode1 = await wrapper.get('[test-id="tabContent1"]')
const textNode2 = await wrapper.get('[test-id="tabContent2"]')
await new Promise(resolve => setTimeout(() => {
expect(textNode0.text()).toEqual('14.06Kpackets/s')
expect(textNode1.text()).toEqual('4.24Kpackets/s')
expect(textNode2.text()).toEqual('9.17Kpackets/s')
@@ -120,9 +63,9 @@ describe('views/charts2/charts/networkOverview/NetworkOverviewLine.vue测试', (
}, 200))
})
test('Metric=Sessions/s', async () => {
init()
require('vue-router').useRoute.mockReturnValue({ query: {} })
// 模拟axios返回数据
axios.get.mockResolvedValue(mockData.common)
axios.get.mockResolvedValue(mockGet)
// 加载vue组件获得实例
const wrapper = mount(NetworkOverviewLine, {
propsData: {
@@ -131,9 +74,8 @@ describe('views/charts2/charts/networkOverview/NetworkOverviewLine.vue测试', (
metric: 'Sessions/s'
}
})
await new Promise(resolve => setTimeout(async () => {
const textNode0 = await wrapper.get('[test-id="tabContent0"]')
const textNode0 = await wrapper.get('[test-id="tabContent0"]')
await new Promise(resolve => setTimeout(() => {
expect(textNode0.text()).toEqual('29.89sessions/s')
resolve()
}, 200))

View File

@@ -1,73 +0,0 @@
const mockData = {
// 空
empty: {
data: {
"status": 200,
"code": 200,
"data": {
"resultType": "object",
"result" : []
}
}
},
bytes: {
// 边界
boundary: {
data: {
"status": 200,
"code": 200,
"data": {
"resultType": "object",
"result": [
{
"type": "bytes",
"totalBitsRate": {
"analysis": {
"avg": "0"
}
},
"inboundBitsRate": {
"analysis": {
"avg": "0"
}
},
"outboundBitsRate": {
"analysis": {
"avg": "95229000000000000000"
}
},
"internalBitsRate": {
"analysis": {
"avg": "0"
}
},
"throughBitsRate": {
"analysis": {
"avg": "0"
}
},
"other": {
"analysis": {
"avg": "0.01"
}
}
},
{
"type": "packets"
},
{
"type": "sessions"
}
]
},
"msg": "OK"
}
}
},
// 正常数据
common: {
data: {"status":200,"code":200,"data":{"resultType":"object","result":[{"type":"bytes","totalBitsRate":{"values":[[1673247564,"96801019.52"]],"analysis":{"avg":"112042808.24","max":"301842105.76","min":"52096324","p95":"168089003.35199997"}},"inboundBitsRate":{"values":[[1673247564,"11814508.48"]],"analysis":{"avg":"18587597.36","max":"137528138.88","min":"3181142.88","p95":"49561521.447999954"}},"outboundBitsRate":{"values":[[1673247564,"84282965.52"]],"analysis":{"avg":"87557861.44","max":"290402258","min":"45337684.48","p95":"121041718.81199999"}},"internalBitsRate":{"values":[[1673247564,"9125.12"]],"analysis":{"avg":"278114.32","max":"2215460.48","min":"0","p95":"923494.5719999998"}},"throughBitsRate":{"values":[[1673247564,"694420.48"]],"analysis":{"avg":"5619235.12","max":"42455480.24","min":"262607.76","p95":"13559588.195999999"}},"other":{"values":[[1673247564,"0.00"]],"analysis":{"avg":"0.01","max":"0.08","min":"0.00","p95":"0.08"}}},{"type":"packets","totalPacketsRate":{"values":[[1673247564,"12077.53"]],"analysis":{"avg":"14062.37","max":"32840.42","min":"6564.17","p95":"20923.167999999987"}},"inboundPacketsRate":{"values":[[1673247564,"3865.58"]],"analysis":{"avg":"4241.61","max":"15460.03","min":"1918.22","p95":"8549.799999999997"}},"outboundPacketsRate":{"values":[[1673247564,"8118.89"]],"analysis":{"avg":"9170.98","max":"27134.58","min":"4510.25","p95":"13690.540999999996"}},"internalPacketsRate":{"values":[[1673247564,"15.89"]],"analysis":{"avg":"35.95","max":"276.47","min":"0.00","p95":"122.49749999999999"}},"throughPacketsRate":{"values":[[1673247564,"77.17"]],"analysis":{"avg":"613.82","max":"3768.56","min":"42.92","p95":"1279.757499999999"}},"other":{"values":[[1673247564,"0.00"]],"analysis":{"avg":"0","max":"0.01","min":"0.00","p95":"0.01"}}},{"type":"sessions","totalSessionsRate":{"values":[[1673247564,"29.92"]],"analysis":{"avg":"29.89","max":"29.92","min":"29.67","p95":"29.92"}}}]},"msg":"OK"}
}
}
export default mockData

File diff suppressed because one or more lines are too long

View File

@@ -1,258 +0,0 @@
import NpmAppEventTable from '@/views/charts2/charts/npm/NpmAppEventTable'
import { mount } from '@vue/test-utils'
import axios from 'axios'
import ElementPlus from 'element-plus'
const timeFilter = {
dateRangeValue: -1,
startTime: 1675558657,
endTime: 1675731457
}
const mockGet = { data: { status: 200, code: 200, queryKey: '88eeb92e0ddb40c0327db494cfe5c74c', success: true, message: null, statistics: { elapsed: 0, rows_read: 2, result_size: 752, result_rows: 10 }, job: null, formatType: 'json', meta: [{ name: 'app_name', type: 'string', category: 'Dimension' }, { name: 'event_severity', type: 'string', category: 'Dimension' }, { name: 'event_type', type: 'string', category: 'Dimension' }, { name: 'count', type: 'long', category: 'Metric' }], data: { resultType: 'table', result: [{ appName: 'youku', eventSeverity: 'info', eventType: 'http error', count: 6 }, { appName: 'uplive', eventSeverity: 'critical', eventType: 'http error', count: 5 }, { appName: 'youku', eventSeverity: 'low', eventType: 'http error', count: 4 }, { appName: 'apple_hls', eventSeverity: 'info', eventType: 'http error', count: 3 }, { appName: 'apple_hls', eventSeverity: 'low', eventType: 'http error', count: 3 }, { appName: 'apple_hls', eventSeverity: 'medium', eventType: 'http error', count: 2 }, { appName: 'uplive', eventSeverity: 'high', eventType: 'http error', count: 2 }, { appName: 'windows_update', eventSeverity: 'medium', eventType: 'http error', count: 2 }, { appName: 'apple_hls', eventSeverity: 'critical', eventType: 'http error', count: 1 }, { appName: 'cloudflare', eventSeverity: 'info', eventType: 'http error', count: 1 }] }, originalUrl: 'http://192.168.44.55:9999?query=SELECT%20app_name%20AS%20app_name%2C%20event_severity%20AS%20event_severity%2C%20event_type%20AS%20event_type%2C%20COUNT%28*%29%20AS%20count%20FROM%20performance_event%20WHERE%20start_time%20%3E%3D%201675580110%20AND%20end_time%20%3C%201675752910%20AND%20entity_type%20%3D%20%27app%27%20GROUP%20BY%20app_name%2Cevent_severity%2Cevent_type%20ORDER%20BY%20count%20DESC%20%20LIMIT%2010%20&format=json&option=real-time', msg: 'OK' } }
describe('views/charts2/charts/npm/NpmAppEventTable.vue测试', () => {
test('Npm 事件APP事件信息表格 严重程度色块验证', async () => {
require('vue-router').useRoute.mockReturnValue({ query: {} })
// 模拟 axios 数据
axios.get.mockResolvedValue(mockGet)
// 加载vue组件获得实例
const wrapper = mount(NpmAppEventTable, {
global: {
plugins: [ElementPlus]
},
propsData: {
timeFilter
}
})
await new Promise(resolve => setTimeout(() => {
// critical
const criticalArray = [1, 8]
for (let index = 0; index < criticalArray.length; index++) {
const rowIndex = criticalArray[index]
for (let i = 1; i <= 5; i++) {
const eventSeverityRedValue = wrapper.find('[test-id="eventSeverityValue' + rowIndex + i + '"]')
expect(eventSeverityRedValue.classes()).toContain('red-dot')
}
}
// high
const highArray = [6]
for (let index = 0; index < highArray.length; index++) {
const rowIndex = highArray[index]
for (let i = 1; i <= 4; i++) {
const eventSeverityRedValue = wrapper.find('[test-id="eventSeverityValue' + rowIndex + i + '"]')
expect(eventSeverityRedValue.classes()).toContain('red-dot')
}
for (let i = 5; i <= 5; i++) {
const eventSeverityGreyValue = wrapper.find('[test-id="eventSeverityValue' + rowIndex + i + '"]')
expect(eventSeverityGreyValue.classes()).toContain('grey-dot')
}
}
// medium
const mediumArray = [5, 7]
for (let index = 0; index < mediumArray.length; index++) {
const rowIndex = mediumArray[index]
for (let i = 1; i <= 3; i++) {
const eventSeverityRedValue = wrapper.find('[test-id="eventSeverityValue' + rowIndex + i + '"]')
expect(eventSeverityRedValue.classes()).toContain('red-dot')
}
for (let i = 4; i <= 5; i++) {
const eventSeverityGreyValue = wrapper.find('[test-id="eventSeverityValue' + rowIndex + i + '"]')
expect(eventSeverityGreyValue.classes()).toContain('grey-dot')
}
}
// low
const lowArray = [2, 4]
for (let index = 0; index < lowArray.length; index++) {
const rowIndex = lowArray[index]
for (let i = 1; i <= 2; i++) {
const eventSeverityRedValue = wrapper.find('[test-id="eventSeverityValue' + rowIndex + i + '"]')
expect(eventSeverityRedValue.classes()).toContain('red-dot')
}
for (let i = 3; i <= 5; i++) {
const eventSeverityGreyValue = wrapper.find('[test-id="eventSeverityValue' + rowIndex + i + '"]')
expect(eventSeverityGreyValue.classes()).toContain('grey-dot')
}
}
// info
const infoArray = [0, 3, 9]
for (let index = 0; index < infoArray.length; index++) {
const rowIndex = infoArray[index]
for (let i = 1; i <= 1; i++) {
const eventSeverityRedValue = wrapper.find('[test-id="eventSeverityValue' + rowIndex + i + '"]')
expect(eventSeverityRedValue.classes()).toContain('red-dot')
}
for (let i = 2; i <= 5; i++) {
const eventSeverityGreyValue = wrapper.find('[test-id="eventSeverityValue' + rowIndex + i + '"]')
expect(eventSeverityGreyValue.classes()).toContain('grey-dot')
}
}
resolve()
}, 200))
})
test('Npm 事件APP事件信息表格 数据验证(应用数据列)', async () => {
require('vue-router').useRoute.mockReturnValue({ query: {} })
// 模拟 axios 数据
axios.get.mockResolvedValue(mockGet)
// 加载vue组件获得实例
const wrapper = mount(NpmAppEventTable, {
global: {
plugins: [ElementPlus]
},
propsData: {
timeFilter
}
})
await new Promise(resolve => setTimeout(() => {
const textNode0 = wrapper.find('[test-id="appName0"]')
const textNode1 = wrapper.find('[test-id="appName1"]')
const textNode2 = wrapper.find('[test-id="appName2"]')
const textNode3 = wrapper.find('[test-id="appName3"]')
const textNode4 = wrapper.find('[test-id="appName4"]')
const textNode5 = wrapper.find('[test-id="appName5"]')
const textNode6 = wrapper.find('[test-id="appName6"]')
const textNode7 = wrapper.find('[test-id="appName7"]')
const textNode8 = wrapper.find('[test-id="appName8"]')
const textNode9 = wrapper.find('[test-id="appName9"]')
expect(textNode0.text()).toEqual('youku')
expect(textNode1.text()).toEqual('uplive')
expect(textNode2.text()).toEqual('youku')
expect(textNode3.text()).toEqual('apple_hls')
expect(textNode4.text()).toEqual('apple_hls')
expect(textNode5.text()).toEqual('apple_hls')
expect(textNode6.text()).toEqual('uplive')
expect(textNode7.text()).toEqual('windows_update')
expect(textNode8.text()).toEqual('apple_hls')
expect(textNode9.text()).toEqual('cloudflare')
resolve()
}, 200))
})
test('Npm 事件APP事件信息表格 数据验证(严重程度数据列)', async () => {
require('vue-router').useRoute.mockReturnValue({ query: {} })
// 模拟 axios 数据
axios.get.mockResolvedValue(mockGet)
// 加载vue组件获得实例
const wrapper = mount(NpmAppEventTable, {
global: {
plugins: [ElementPlus]
},
propsData: {
timeFilter
}
})
await new Promise(resolve => setTimeout(() => {
const textNode0 = wrapper.find('[test-id="eventSeverity0"]')
const textNode1 = wrapper.find('[test-id="eventSeverity1"]')
const textNode2 = wrapper.find('[test-id="eventSeverity2"]')
const textNode3 = wrapper.find('[test-id="eventSeverity3"]')
const textNode4 = wrapper.find('[test-id="eventSeverity4"]')
const textNode5 = wrapper.find('[test-id="eventSeverity5"]')
const textNode6 = wrapper.find('[test-id="eventSeverity6"]')
const textNode7 = wrapper.find('[test-id="eventSeverity7"]')
const textNode8 = wrapper.find('[test-id="eventSeverity8"]')
const textNode9 = wrapper.find('[test-id="eventSeverity9"]')
expect(textNode0.text()).toEqual('info')
expect(textNode1.text()).toEqual('critical')
expect(textNode2.text()).toEqual('low')
expect(textNode3.text()).toEqual('info')
expect(textNode4.text()).toEqual('low')
expect(textNode5.text()).toEqual('medium')
expect(textNode6.text()).toEqual('high')
expect(textNode7.text()).toEqual('medium')
expect(textNode8.text()).toEqual('critical')
expect(textNode9.text()).toEqual('info')
resolve()
}, 200))
})
test('Npm 事件APP事件信息表格 数据验证(事件类型数据列)', async () => {
require('vue-router').useRoute.mockReturnValue({ query: {} })
// 模拟 axios 数据
axios.get.mockResolvedValue(mockGet)
// 加载vue组件获得实例
const wrapper = mount(NpmAppEventTable, {
global: {
plugins: [ElementPlus]
},
propsData: {
timeFilter
}
})
await new Promise(resolve => setTimeout(() => {
const textNode0 = wrapper.find('[test-id="eventType0"]')
const textNode1 = wrapper.find('[test-id="eventType1"]')
const textNode2 = wrapper.find('[test-id="eventType2"]')
const textNode3 = wrapper.find('[test-id="eventType3"]')
const textNode4 = wrapper.find('[test-id="eventType4"]')
const textNode5 = wrapper.find('[test-id="eventType5"]')
const textNode6 = wrapper.find('[test-id="eventType6"]')
const textNode7 = wrapper.find('[test-id="eventType7"]')
const textNode8 = wrapper.find('[test-id="eventType8"]')
const textNode9 = wrapper.find('[test-id="eventType9"]')
expect(textNode0.text()).toEqual('http error')
expect(textNode1.text()).toEqual('http error')
expect(textNode2.text()).toEqual('http error')
expect(textNode3.text()).toEqual('http error')
expect(textNode4.text()).toEqual('http error')
expect(textNode5.text()).toEqual('http error')
expect(textNode6.text()).toEqual('http error')
expect(textNode7.text()).toEqual('http error')
expect(textNode8.text()).toEqual('http error')
expect(textNode9.text()).toEqual('http error')
resolve()
}, 200))
})
test('Npm 事件APP事件信息表格 数据验证(事件数量数据列)', async () => {
require('vue-router').useRoute.mockReturnValue({ query: {} })
// 模拟 axios 数据
axios.get.mockResolvedValue(mockGet)
// 加载vue组件获得实例
const wrapper = mount(NpmAppEventTable, {
global: {
plugins: [ElementPlus]
},
propsData: {
timeFilter
}
})
await new Promise(resolve => setTimeout(() => {
const textNode0 = wrapper.find('[test-id="count0"]')
const textNode1 = wrapper.find('[test-id="count1"]')
const textNode2 = wrapper.find('[test-id="count2"]')
const textNode3 = wrapper.find('[test-id="count3"]')
const textNode4 = wrapper.find('[test-id="count4"]')
const textNode5 = wrapper.find('[test-id="count5"]')
const textNode6 = wrapper.find('[test-id="count6"]')
const textNode7 = wrapper.find('[test-id="count7"]')
const textNode8 = wrapper.find('[test-id="count8"]')
const textNode9 = wrapper.find('[test-id="count9"]')
expect(textNode0.text()).toEqual('6')
expect(textNode1.text()).toEqual('5')
expect(textNode2.text()).toEqual('4')
expect(textNode3.text()).toEqual('3')
expect(textNode4.text()).toEqual('3')
expect(textNode5.text()).toEqual('2')
expect(textNode6.text()).toEqual('2')
expect(textNode7.text()).toEqual('2')
expect(textNode8.text()).toEqual('1')
expect(textNode9.text()).toEqual('1')
resolve()
}, 200))
})
})

File diff suppressed because one or more lines are too long

View File

@@ -4,7 +4,7 @@ import axios from 'axios'
// 模拟数据
const chartData = {
data: { status: 200, code: 200, queryKey: '6480498979f7501d822572ebeb9e9665', success: true, message: null, statistics: { elapsed: 0, rows_read: 3, result_size: 167, result_rows: 5 }, job: null, formatType: 'json', meta: [{ name: 'event_severity', type: 'string', category: 'Dimension' }, { name: 'count', type: 'long', category: 'Metric' }], data: { resultType: 'table', result: [{ eventSeverity: 'critical', count: 322334 }, { eventSeverity: 'high', count: 1111 }, { eventSeverity: 'info', count: 122222 }, { eventSeverity: 'low', count: 14456678 }, { eventSeverity: 'medium', count: 2000000 }] }, originalUrl: 'http://192.168.44.55:9999?query=SELECT%20event_severity%20AS%20event_severity%2C%20COUNT%28*%29%20AS%20count%20FROM%20performance_event%20WHERE%20start_time%20%3E%3D%201675026686%20AND%20end_time%20%3C%201675048286%20GROUP%20BY%20event_severity&format=json&option=real-time', msg: 'OK' }
data: {"status":200,"code":200,"queryKey":"6480498979f7501d822572ebeb9e9665","success":true,"message":null,"statistics":{"elapsed":0,"rows_read":3,"result_size":167,"result_rows":5},"job":null,"formatType":"json","meta":[{"name":"event_severity","type":"string","category":"Dimension"},{"name":"count","type":"long","category":"Metric"}],"data":{"resultType":"table","result":[{"eventSeverity":"critical","count":322334},{"eventSeverity":"high","count":1111},{"eventSeverity":"info","count":122222},{"eventSeverity":"low","count":14456678},{"eventSeverity":"medium","count":2000000}]},"originalUrl":"http://192.168.44.55:9999?query=SELECT%20event_severity%20AS%20event_severity%2C%20COUNT%28*%29%20AS%20count%20FROM%20performance_event%20WHERE%20start_time%20%3E%3D%201675026686%20AND%20end_time%20%3C%201675048286%20GROUP%20BY%20event_severity&format=json&option=real-time","msg":"OK"}
}
// type
const type = 'severity'

File diff suppressed because one or more lines are too long

View File

@@ -4,28 +4,28 @@ import axios from 'axios'
import ElementPlus from 'element-plus'
// 未下钻
const mockGet = {
data: { status: 200, code: 200, queryKey: '68d8aa5867b08b926b5bd38c36add9e5', success: true, message: null, statistics: { elapsed: 0, rows_read: 2, result_size: 550, result_rows: 5 }, job: null, formatType: 'json', meta: [{ name: 'event_id', type: 'long', category: 'Metric' }, { name: 'event_severity', type: 'string', category: 'Metric' }, { name: 'event_key', type: 'string', category: 'Metric' }, { name: 'event_type', type: 'string', category: 'Metric' }], data: { resultType: 'table', result: [{ eventId: 1173511643475208200, eventSeverity: 'critical', eventKey: '114.114.114.114 dns error', eventType: 'dns error' }, { eventId: 1173504415263352800, eventSeverity: 'high', eventKey: '116.178.78.241 http error', eventType: 'http error' }, { eventId: 1173492761289025500, eventSeverity: 'medium', eventKey: '223.6.6.6 dns error', eventType: 'dns error' }, { eventId: 1173489002890651600, eventSeverity: 'low', eventKey: '114.114.114.114 dns error', eventType: 'dns error' }, { eventId: 1173482380537620500, eventSeverity: 'info', eventKey: '1.1.1.2 dns error', eventType: 'http error' }, { eventId: 1173482380537620500, eventSeverity: 'critical', eventKey: '1.1.1.2 dns error', eventType: 'dns error' }] }, originalUrl: 'http://192.168.44.55:9999?query=SELECT%20event_id%20AS%20event_id%2Cevent_severity%20AS%20event_severity%2C%20event_key%20AS%20event_key%2C%20event_type%20AS%20event_type%20FROM%20performance_event%20WHERE%20start_time%20%3E%3D%201675227528%20AND%20end_time%20%3C%201675231128%20ORDER%20BY%20start_time%20DESC%20%20LIMIT%208%20&format=json&option=real-time', msg: 'OK' }
data: {"status":200,"code":200,"queryKey":"68d8aa5867b08b926b5bd38c36add9e5","success":true,"message":null,"statistics":{"elapsed":0,"rows_read":2,"result_size":550,"result_rows":5},"job":null,"formatType":"json","meta":[{"name":"event_id","type":"long","category":"Metric"},{"name":"event_severity","type":"string","category":"Metric"},{"name":"event_key","type":"string","category":"Metric"},{"name":"event_type","type":"string","category":"Metric"}],"data":{"resultType":"table","result":[{"eventId":1173511643475208192,"eventSeverity":"critical","eventKey":"114.114.114.114 dns error","eventType":"dns error"},{"eventId":1173504415263352832,"eventSeverity":"high","eventKey":"116.178.78.241 http error","eventType":"http error"},{"eventId":1173492761289025537,"eventSeverity":"medium","eventKey":"223.6.6.6 dns error","eventType":"dns error"},{"eventId":1173489002890651648,"eventSeverity":"low","eventKey":"114.114.114.114 dns error","eventType":"dns error"},{"eventId":1173482380537620480,"eventSeverity":"info","eventKey":"1.1.1.2 dns error","eventType":"http error"},{"eventId":1173482380537620481,"eventSeverity":"critical","eventKey":"1.1.1.2 dns error","eventType":"dns error"}]},"originalUrl":"http://192.168.44.55:9999?query=SELECT%20event_id%20AS%20event_id%2Cevent_severity%20AS%20event_severity%2C%20event_key%20AS%20event_key%2C%20event_type%20AS%20event_type%20FROM%20performance_event%20WHERE%20start_time%20%3E%3D%201675227528%20AND%20end_time%20%3C%201675231128%20ORDER%20BY%20start_time%20DESC%20%20LIMIT%208%20&format=json&option=real-time","msg":"OK"}
}
// 下钻
const mockGet1 = {
data: { status: 200, code: 200, queryKey: 'fc0bd92bf3b48a37310d5c004d8b7a7b', success: true, message: null, statistics: { elapsed: 0, rows_read: 2, result_size: 689, result_rows: 7 }, job: null, formatType: 'json', meta: [{ name: 'event_id', type: 'long', category: 'Metric' }, { name: 'event_severity', type: 'string', category: 'Metric' }, { name: 'event_type', type: 'string', category: 'Metric' }, { name: 'start_time', type: 'long', category: 'Metric' }], data: { resultType: 'table', result: [{ eventId: 1132790825086844900, eventSeverity: 'critical', eventType: 'http error', startTime: 1672802700 }, { eventId: 1132132403379142700, eventSeverity: 'high', eventType: 'dns error', startTime: 1672763400 }, { eventId: 1131441760155689000, eventSeverity: 'low', eventType: 'dns error', startTime: 1672722300 }, { eventId: 1131411523384598500, eventSeverity: 'medium', eventType: 'http error', startTime: 1672720500 }, { eventId: 1131390214323789800, eventSeverity: 'info', eventType: 'dns error', startTime: 1672719300 }, { eventId: 1131306200132968400, eventSeverity: 'critical', eventType: 'http error', startTime: 1672714200 }] }, originalUrl: 'http://192.168.44.55:9999?query=SELECT%20event_id%20AS%20event_id%2Cevent_severity%20AS%20event_severity%2C%20event_type%20AS%20event_type%2C%20start_time%20AS%20start_time%20FROM%20performance_event%20WHERE%20start_time%20%3E%3D%201672675200%20AND%20start_time%20%3C%201677513600%20AND%20server_ip%20%3D%20%27116.178.236.216%27%20ORDER%20BY%20start_time%20DESC&format=json&option=real-time', msg: 'OK' }
data: {"status":200,"code":200,"queryKey":"fc0bd92bf3b48a37310d5c004d8b7a7b","success":true,"message":null,"statistics":{"elapsed":0,"rows_read":2,"result_size":689,"result_rows":7},"job":null,"formatType":"json","meta":[{"name":"event_id","type":"long","category":"Metric"},{"name":"event_severity","type":"string","category":"Metric"},{"name":"event_type","type":"string","category":"Metric"},{"name":"start_time","type":"long","category":"Metric"}],"data":{"resultType":"table","result":[{"eventId":1132790825086844928,"eventSeverity":"critical","eventType":"http error","startTime":1672802700},{"eventId":1132132403379142657,"eventSeverity":"high","eventType":"dns error","startTime":1672763400},{"eventId":1131441760155688960,"eventSeverity":"low","eventType":"dns error","startTime":1672722300},{"eventId":1131411523384598528,"eventSeverity":"medium","eventType":"http error","startTime":1672720500},{"eventId":1131390214323789824,"eventSeverity":"info","eventType":"dns error","startTime":1672719300},{"eventId":1131306200132968450,"eventSeverity":"critical","eventType":"http error","startTime":1672714200}]},"originalUrl":"http://192.168.44.55:9999?query=SELECT%20event_id%20AS%20event_id%2Cevent_severity%20AS%20event_severity%2C%20event_type%20AS%20event_type%2C%20start_time%20AS%20start_time%20FROM%20performance_event%20WHERE%20start_time%20%3E%3D%201672675200%20AND%20start_time%20%3C%201677513600%20AND%20server_ip%20%3D%20%27116.178.236.216%27%20ORDER%20BY%20start_time%20DESC&format=json&option=real-time","msg":"OK"}
}
const query = {
curTab: 'country',
dimensionType: 'ip',
fourthMenu: '116.178.214.84',
fourthPanel: '8',
networkOverviewBeforeTab: 'ip',
panelName: '116.178.214.84',
curTab: "country",
dimensionType: "ip",
fourthMenu: "116.178.214.84",
fourthPanel: "8",
networkOverviewBeforeTab: "ip",
panelName: "116.178.214.84",
queryCondition: "common_client_ip='116.178.214.84' OR common_server_ip='116.178.214.84'",
t: '1675236779453',
tabIndex: '1',
tabOperationBeforeType: '',
tabOperationType: '4',
thirdMenu: 'network.ips',
thirdPanel: '12'
t: "1675236779453",
tabIndex: "1",
tabOperationBeforeType: "",
tabOperationType: "4",
thirdMenu: "network.ips",
thirdPanel: "12"
}
const timeFilter = {
@@ -144,11 +144,11 @@ describe('views/charts2/charts/npm/NpmRecentEvents.vue测试', () => {
expect(eventType3.text()).toEqual('http error')
expect(eventType4.text()).toEqual('dns error')
const startTime0 = wrapper.get('[test-id="startTime-0"]')
const startTime1 = wrapper.get('[test-id="startTime-1"]')
const startTime2 = wrapper.get('[test-id="startTime-2"]')
const startTime3 = wrapper.get('[test-id="startTime-3"]')
const startTime4 = wrapper.get('[test-id="startTime-4"]')
const startTime0 = wrapper.get('[test-id="startTime-2023-01-04T11:25:00+08:00-0"]')
const startTime1 = wrapper.get('[test-id="startTime-2023-01-04T00:30:00+08:00-1"]')
const startTime2 = wrapper.get('[test-id="startTime-2023-01-03T13:05:00+08:00-2"]')
const startTime3 = wrapper.get('[test-id="startTime-2023-01-03T12:35:00+08:00-3"]')
const startTime4 = wrapper.get('[test-id="startTime-2023-01-03T12:15:00+08:00-4"]')
expect(startTime0.text()).toEqual('2023-01-04T11:25:00+08:00')
expect(startTime1.text()).toEqual('2023-01-04T00:30:00+08:00')