Compare commits
63 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
53c24fe51b | ||
|
|
2aa7f6edfb | ||
|
|
6ed9c4f5fe | ||
|
|
6f8631f947 | ||
|
|
63ab36f4d2 | ||
|
|
cccc1f0e6a | ||
|
|
4651709529 | ||
|
|
6ab98be4c8 | ||
|
|
7b96f979a4 | ||
|
|
a59bff2cb7 | ||
|
|
04651581fe | ||
|
|
84ca05dccc | ||
|
|
780de66ddf | ||
|
|
9205d7645d | ||
|
|
ec486fe930 | ||
|
|
12c31b5bf6 | ||
|
|
96591cb9ef | ||
|
|
949a8e9d86 | ||
|
|
3604783570 | ||
|
|
f60a6bd778 | ||
|
|
5ece1b6c8e | ||
|
|
86c2c8364d | ||
|
|
1f130a6ac8 | ||
|
|
c8af5fd5a1 | ||
|
|
48b7493b2e | ||
|
|
98ba09b586 | ||
|
|
7d85d332df | ||
|
|
6ee5ea6f6e | ||
|
|
6756812c34 | ||
|
|
d2aa5c9b7a | ||
|
|
049d5f92b4 | ||
|
|
7ce190f3c7 | ||
|
|
e9edd9cf05 | ||
|
|
4655eed55f | ||
|
|
cf625c196e | ||
|
|
55fdd3f0e4 | ||
|
|
8aa96da577 | ||
|
|
22bf16a01d | ||
|
|
04e186e7d8 | ||
|
|
38006bd964 | ||
|
|
05677d5fb6 | ||
|
|
156979e79e | ||
|
|
0f2fcbe9e6 | ||
|
|
089887f05b | ||
|
|
c83f64706f | ||
|
|
c82d33fa39 | ||
|
|
eed1d398d8 | ||
|
|
a8643b8543 | ||
|
|
bd1eeec770 | ||
|
|
8cb3f00aa4 | ||
|
|
4fed5a9b8c | ||
|
|
d54054510b | ||
|
|
27bd8260d2 | ||
|
|
29916f8517 | ||
|
|
2bac72eb5d | ||
|
|
dfcc03f11a | ||
|
|
a608ac72f6 | ||
|
|
b5d897608c | ||
|
|
431821154e | ||
|
|
9f488adcb9 | ||
|
|
a31c408327 | ||
|
|
d84483c0dc | ||
|
|
4804748564 |
@@ -29,7 +29,7 @@ generate_git-log:
|
||||
- public/index.html
|
||||
- public/git-log.html
|
||||
only:
|
||||
- dev
|
||||
- 6suo
|
||||
tags:
|
||||
- galaxy
|
||||
|
||||
@@ -42,7 +42,7 @@ build_project:
|
||||
- echo "npm run build"
|
||||
- cnpm run build
|
||||
only:
|
||||
- dev
|
||||
- 6suo
|
||||
- tags
|
||||
tags:
|
||||
- galaxy
|
||||
@@ -51,14 +51,14 @@ build_image:
|
||||
stage: build_image
|
||||
script:
|
||||
- echo "docker build"
|
||||
- sudo docker build --no-cache -t cn-ui:$CNUI_TAG .
|
||||
- sudo docker build --no-cache -t cn-ui-$CI_COMMIT_REF_NAME:$CNUI_TAG .
|
||||
- echo "docker tag"
|
||||
- sudo docker tag cn-ui:$CNUI_TAG 192.168.40.153:9080/cyber-narrator/cn-ui:$CNUI_TAG
|
||||
- sudo docker tag cn-ui-$CI_COMMIT_REF_NAME:$CNUI_TAG 192.168.40.153:9080/cyber-narrator/cn-ui-$CI_COMMIT_REF_NAME:$CNUI_TAG
|
||||
- echo "docker push"
|
||||
- sudo docker push 192.168.40.153:9080/cyber-narrator/cn-ui:$CNUI_TAG
|
||||
- sudo docker push 192.168.40.153:9080/cyber-narrator/cn-ui-$CI_COMMIT_REF_NAME:$CNUI_TAG
|
||||
when: on_success
|
||||
only:
|
||||
- dev
|
||||
- 6suo
|
||||
tags:
|
||||
- galaxy
|
||||
|
||||
@@ -71,11 +71,11 @@ build_release_image:
|
||||
- echo '提交的版本是'
|
||||
- echo $CI_COMMIT_REF_NAME
|
||||
- echo "docker build"
|
||||
- sudo docker build --no-cache -t cn-ui:$CI_COMMIT_TAG .
|
||||
- sudo docker build --no-cache -t cn-ui-$CI_COMMIT_REF_NAME:$CI_COMMIT_TAG .
|
||||
- echo "docker tag"
|
||||
- sudo docker tag cn-ui:$CI_COMMIT_TAG 192.168.40.153:9080/cyber-narrator/cn-ui:$CI_COMMIT_TAG
|
||||
- sudo docker tag cn-ui-$CI_COMMIT_REF_NAME:$CI_COMMIT_TAG 192.168.40.153:9080/cyber-narrator/cn-ui-$CI_COMMIT_REF_NAME:$CI_COMMIT_TAG
|
||||
- echo "docker push"
|
||||
- sudo docker push 192.168.40.153:9080/cyber-narrator/cn-ui:$CI_COMMIT_TAG
|
||||
- sudo docker push 192.168.40.153:9080/cyber-narrator/cn-ui-$CI_COMMIT_REF_NAME:$CI_COMMIT_TAG
|
||||
only:
|
||||
- tags
|
||||
tags:
|
||||
|
||||
@@ -6,6 +6,8 @@ module.exports = {
|
||||
'<rootDir>/test/**/__tests__/**/*.{vue,js,jsx,ts,tsx}',
|
||||
'<rootDir>/test/**/*.{spec,test}.{vue,js,jsx,ts,tsx}'
|
||||
],
|
||||
setupFilesAfterEnv: ['<rootDir>/test/init.js'],
|
||||
verbose: true,
|
||||
testEnvironment: 'jsdom',
|
||||
transform: {
|
||||
'^.+\\.(vue)$': '<rootDir>/node_modules/vue-jest',
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
"@vue/cli-service": "~4.5.0",
|
||||
"@vue/compiler-sfc": "^3.0.0",
|
||||
"@vue/component-compiler-utils": "^3.2.0",
|
||||
"@vue/test-utils": "^2.0.0-rc.18",
|
||||
"@vue/test-utils": "^2.2.7",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-jest": "^26.0.0",
|
||||
"compression-webpack-plugin": "^8.0.1",
|
||||
|
||||
@@ -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'
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
107
src/Test.vue
107
src/Test.vue
@@ -1,27 +1,120 @@
|
||||
<template>
|
||||
<span data-test="count">{{count}}</span>
|
||||
<button data-test="button" @click="click">click</button>
|
||||
<span test-id="count">{{count}}</span>
|
||||
<span test-id="id">{{obj.id}}</span>
|
||||
<span test-id="title">{{obj.title}}</span>
|
||||
<button test-id="button" @click="click">click</button>
|
||||
<span test-id="tab">{{lineTab}}</span>
|
||||
<el-table
|
||||
:data="tableData"
|
||||
class="test-table"
|
||||
height="100%"
|
||||
empty-text=" "
|
||||
>
|
||||
<template v-for="(item, index) in tableTitles" :key="index">
|
||||
<el-table-column>
|
||||
<template #default="scope" :column="item">
|
||||
<span :test-id="`${item.prop}${scope.$index}`">{{scope.row[item.prop]}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
</el-table>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/* vue-jest的测试示例 */
|
||||
import VueRouter from 'vue-router'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import axios from 'axios'
|
||||
import { ref } from 'vue'
|
||||
import indexedDBUtils from '@/indexedDB'
|
||||
export default {
|
||||
name: 'Test',
|
||||
data () {
|
||||
return {
|
||||
count: 0
|
||||
count: 0,
|
||||
obj: { id: 1, title: 'title' },
|
||||
differentParamData0: null,
|
||||
differentParamData1: null,
|
||||
indexedDBValue: null,
|
||||
tableData: [
|
||||
{
|
||||
name: 'a',
|
||||
age: 10
|
||||
},
|
||||
{
|
||||
name: 'b',
|
||||
age: 11
|
||||
}
|
||||
],
|
||||
tableTitles: [
|
||||
{ label: 'Name', prop: 'name' },
|
||||
{ label: 'Age', prop: 'age' }
|
||||
],
|
||||
mergeRequestData0: null,
|
||||
mergeRequestData1: null,
|
||||
mergeRequestChildData0: null,
|
||||
mergeRequestChildData1: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
click () {
|
||||
this.count++
|
||||
},
|
||||
async getObj () {
|
||||
axios.get('/api/getObjId').then(response => {
|
||||
this.obj.id = response.data
|
||||
})
|
||||
axios.get('/api/getObjTitle').then(response => {
|
||||
this.obj.title = response.data
|
||||
})
|
||||
},
|
||||
async getCount () {
|
||||
axios.get('/api/getCount').then(response => {
|
||||
this.count = response.data
|
||||
})
|
||||
},
|
||||
async differentRequestParam () {
|
||||
axios.get('/api/differentParam', { params: { name: 0 } }).then(response => {
|
||||
this.differentParamData0 = response.data
|
||||
})
|
||||
axios.get('/api/differentParam', { params: { name: 1 } }).then(response => {
|
||||
this.differentParamData1 = response.data
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 同一url,不同入参的axios请求内包含多个不同url请求的demo
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async mergeRequest () {
|
||||
axios.get('/api/differentParam', { params: { name: 0 } }).then(response => {
|
||||
this.mergeRequestData0 = response.data
|
||||
})
|
||||
axios.get('/api/differentParam', { params: { name: 1 } }).then(response => {
|
||||
this.mergeRequestData1 = response.data
|
||||
axios.get('/api/getChildId').then(response1 => {
|
||||
this.mergeRequestChildData0 = response1.data
|
||||
})
|
||||
axios.get('/api/getChildTitle').then(response2 => {
|
||||
this.mergeRequestChildData1 = response2.data
|
||||
})
|
||||
})
|
||||
},
|
||||
async setIndexedDBValue () {
|
||||
await indexedDBUtils.selectTable('test').put({ id: 1, name: 'test' })
|
||||
},
|
||||
async getIndexedDBValue () {
|
||||
this.indexedDBValue = await indexedDBUtils.selectTable('test').get(1)
|
||||
}
|
||||
},
|
||||
created () {
|
||||
const { currentRoute } = VueRouter.useRouter()
|
||||
setup () {
|
||||
const { query } = useRoute()
|
||||
const { currentRoute } = useRouter()
|
||||
const localstorageValue = localStorage.getItem('key')
|
||||
const lineTab = ref(query.lineTab || '')
|
||||
const path = currentRoute.value.path
|
||||
return {
|
||||
currentRoute
|
||||
lineTab,
|
||||
path,
|
||||
localstorageValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
z-index: 999999;
|
||||
box-shadow: 0 0 10px #CCC;
|
||||
box-sizing: border-box;
|
||||
|
||||
.pop-title {
|
||||
margin: 10px 0;
|
||||
}
|
||||
.el-button--mini{
|
||||
padding: 5px 7px;
|
||||
}
|
||||
@@ -23,7 +25,6 @@
|
||||
top: 33px;
|
||||
}
|
||||
.custom-labels {
|
||||
margin-top: 12px;
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
}
|
||||
@@ -41,8 +42,7 @@
|
||||
font-size: 14px;
|
||||
}
|
||||
.custom-label:hover{
|
||||
color: #cccccc;
|
||||
background-color: #DCDFE6;
|
||||
background-color: rgba(220, 223, 230, .5)
|
||||
}
|
||||
.custom-title{
|
||||
padding: 2px 0 2px 2px;
|
||||
@@ -57,6 +57,14 @@
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
.custom-bottom-btns-right {
|
||||
.el-button:nth-of-type(1) {
|
||||
margin-right: 3px;
|
||||
}
|
||||
.el-button .top-tool-btn-save {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.unshow {
|
||||
display: none;
|
||||
|
||||
@@ -98,6 +98,8 @@
|
||||
.domain-detail-list {
|
||||
display: table;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
|
||||
.domain-detail-list__row {
|
||||
display: table-row;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
.cn-chart__whois {
|
||||
overflow: auto;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
padding-right: 20px;
|
||||
|
||||
&.row__label--width130 {
|
||||
flex-basis: 130px;
|
||||
flex-basis: 140px;
|
||||
padding-right: unset;
|
||||
}
|
||||
&.row__label--width160 {
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
import { overwriteUrl, urlParamsHandler } from '@/utils/tools'
|
||||
import { ref } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useStore } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'ChartTabs',
|
||||
@@ -69,8 +70,9 @@ export default {
|
||||
setup (props) {
|
||||
const tabsData = ref([])
|
||||
const router = useRouter()
|
||||
const store = useStore()
|
||||
const routerPath = router.currentRoute.value.path
|
||||
const tabList = window.currentChartTabList
|
||||
const tabList = store.getters.getChartTabList
|
||||
let currentTab = '0'
|
||||
|
||||
if (props.data) {
|
||||
@@ -94,7 +96,7 @@ export default {
|
||||
return item.path === routerPath
|
||||
})
|
||||
currentTab = JSON.stringify(currentTab)
|
||||
window.currentChartTabList = [{ path: routerPath, index: currentTab }]
|
||||
store.dispatch('dispatchChartTabList', [{ path: routerPath, index: currentTab }])
|
||||
} else {
|
||||
// 此处为切换界面,如果window里保存的路径和tabsData里的路径一致,选择window数据并使用
|
||||
// 两个不一致的话,则默认选择tabsData里的第一条
|
||||
@@ -108,10 +110,15 @@ export default {
|
||||
|
||||
if (obj0 && obj1) {
|
||||
currentTab = tabList[1].index
|
||||
// 场景:从遮罩面板进入界面时,重置状态,默认选中第一个tab
|
||||
if (routerPath === tabList[0].path) {
|
||||
currentTab = tabList[0].index
|
||||
store.dispatch('dispatchChartTabList', [{ path: tabsData.value[0].path, index: '0' }])
|
||||
}
|
||||
} else if (obj0) {
|
||||
currentTab = tabList[0].index
|
||||
} else {
|
||||
window.currentChartTabList = [{ path: tabsData.value[0].path, index: '0' }]
|
||||
store.dispatch('dispatchChartTabList', [{ path: tabsData.value[0].path, index: '0' }])
|
||||
currentTab = '0'
|
||||
}
|
||||
}
|
||||
@@ -156,9 +163,10 @@ export default {
|
||||
}
|
||||
}
|
||||
})
|
||||
const tabList = this.$store.getters.getChartTabList
|
||||
|
||||
if (window.currentChartTabList && this.router !== 'noRouter') {
|
||||
window.currentChartTabList.forEach((item) => {
|
||||
if (tabList && this.router !== 'noRouter') {
|
||||
tabList.forEach((item) => {
|
||||
this.$nextTick(() => {
|
||||
this.handleActiveBar(parseFloat(item.index))
|
||||
})
|
||||
@@ -167,7 +175,7 @@ export default {
|
||||
this.$nextTick(() => {
|
||||
this.handleActiveBar(this.currentTab)
|
||||
})
|
||||
window.currentChartTabList = null
|
||||
this.$store.dispatch('dispatchChartTabList', null)
|
||||
}
|
||||
},
|
||||
handleActiveBar (index) {
|
||||
@@ -186,7 +194,7 @@ export default {
|
||||
} else {
|
||||
// 数组长度为1,即代表刚刷新界面,获取active的dom添加样式,避免原模式错位问题
|
||||
// 可添加css样式,也可添加class类名,两个操作选一即可
|
||||
if (window.currentChartTabList.length === 1) {
|
||||
if (this.$store.getters.getChartTabList.length === 1) {
|
||||
// 此处操作是因为初始化时给active加border,导致tab下移,故需要将整体往上移动对应高度
|
||||
const topDom = document.getElementsByClassName('el-tabs__header is-top')
|
||||
topDom[0].style.cssText += 'top: -3px'
|
||||
@@ -201,6 +209,7 @@ export default {
|
||||
},
|
||||
handleClick (item) {
|
||||
this.$emit('click', item)
|
||||
const tabList = this.$store.getters.getChartTabList
|
||||
|
||||
if (this.router === 'noRouter') {
|
||||
const { query } = this.$route
|
||||
@@ -210,14 +219,15 @@ export default {
|
||||
})
|
||||
overwriteUrl(newUrl)
|
||||
} else {
|
||||
window.currentChartTabList.push({
|
||||
tabList.push({
|
||||
path: this.tabsData[item.index].path,
|
||||
index: item.index
|
||||
})
|
||||
|
||||
if (window.currentChartTabList.length > 2) {
|
||||
window.currentChartTabList.splice(0, 1)
|
||||
if (tabList.length > 2) {
|
||||
tabList.splice(0, 1)
|
||||
}
|
||||
this.$store.dispatch('dispatchChartTabList', tabList)
|
||||
|
||||
this.$router.push({
|
||||
path: this.tabsData[item.index].path,
|
||||
@@ -230,6 +240,19 @@ export default {
|
||||
},
|
||||
beforeUnmount () {
|
||||
clearTimeout(this.timer)
|
||||
const path = this.$router.currentRoute.value.path
|
||||
const list = this.$store.getters.getChartTabList
|
||||
if (list && this.router !== 'noRouter') {
|
||||
if (list[1]) {
|
||||
// 去其他界面,清除状态
|
||||
if (path !== list[0].path && path !== list[1].path) {
|
||||
this.$store.dispatch('dispatchChartTabList', null)
|
||||
}
|
||||
} else if (path !== list[0].path) {
|
||||
// 避免刷新页面之后又点击菜单栏进入该界面,还保留上次点击状态
|
||||
this.$store.dispatch('dispatchChartTabList', null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
class="date_style"
|
||||
style="position: absolute;top: -53px;left: -536px;"
|
||||
:clearable="false"
|
||||
:default-time="defaultTime"
|
||||
type="datetimerange"
|
||||
@change="timeArrChange"
|
||||
/>
|
||||
@@ -127,6 +128,11 @@ export default {
|
||||
{ value: 2880, name: 'last 2 days' }
|
||||
]
|
||||
const dropdownFlag = ref(false)
|
||||
// 默认日历选择时间,即开始时间YYYY-MM-DD 00:00:00,结束时间YYYY-MM-DD 59:59:59
|
||||
const defaultTime = ref([
|
||||
new Date(2023, 1, 1, 0, 0, 0),
|
||||
new Date(2023, 1, 2, 23, 59, 59)
|
||||
])
|
||||
|
||||
// computed
|
||||
const utcStr = computed(() => {
|
||||
@@ -274,6 +280,7 @@ export default {
|
||||
rangeEchartsData,
|
||||
address,
|
||||
dateRangeArr,
|
||||
defaultTime,
|
||||
dateRangeValue,
|
||||
isCustom,
|
||||
newDateValue,
|
||||
|
||||
@@ -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--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 }} <i class="cn-icon cn-icon-arrow-down"></i></div>
|
||||
<template #dropdown>
|
||||
@@ -103,32 +103,7 @@
|
||||
<span v-else class="route-menu" @click="jump(route,item,'',3)">{{ $t(item) }}</span>
|
||||
</template>
|
||||
<template v-else-if="index===1">
|
||||
<span class="route-menu" @click="jump(route,'','',2)"
|
||||
v-if="route.indexOf('detection') === -1 && route.indexOf('administration') === -1">{{ item }}</span>
|
||||
<!-- <div class="header__left-breadcrumb-item-select" v-if="route.indexOf('detection') > -1">-->
|
||||
<!-- <el-popover placement="bottom-start"-->
|
||||
<!-- v-if="route.indexOf('detection') > -1"-->
|
||||
<!-- ref="breadcrumbPopover"-->
|
||||
<!-- :show-arrow="false"-->
|
||||
<!-- :append-to-body="false"-->
|
||||
<!-- :hide-after="0"-->
|
||||
<!-- :show-after="0"-->
|
||||
<!-- popper-class="breadcrumb__popper"-->
|
||||
<!-- trigger="click">-->
|
||||
<!-- <template #reference>-->
|
||||
<!-- <div class="breadcrumb-button" id="breadcrumbButton2" :class="showBackground?'breadcrumb-button__active':''" v-if="route.indexOf('detection') > -1">-->
|
||||
<!-- <span id="breadcrumbValue2"> {{item}}</span><i class="cn-icon-xiala cn-icon"></i>-->
|
||||
<!-- </div>-->
|
||||
<!-- </template>-->
|
||||
<!-- <el-row type="flex" justify="center" style="width: fit-content;flex-direction: column;">-->
|
||||
<!-- <ul class="select-dropdown" id="breadcrumbSelectDropdown2">-->
|
||||
<!-- <li v-for="item in detectionMenuList" title='' :key="item.name" :id="item.name" class="select-dropdown__item" @click="jump(item.path,'','',2)">-->
|
||||
<!-- <span>{{$t(item.i18n)}}</span>-->
|
||||
<!-- </li>-->
|
||||
<!-- </ul>-->
|
||||
<!-- </el-row>-->
|
||||
<!-- </el-popover>-->
|
||||
<!-- </div>-->
|
||||
<span class="route-menu" @click="jump(route,'','',2)">{{ item }}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span>{{ item }}</span>
|
||||
@@ -552,7 +527,7 @@ export default {
|
||||
queryCondition.push('common_l7_protocol=\'' + valueGroup[0] + '\'')
|
||||
queryCondition.push('common_server_port=' + valueGroup[1])
|
||||
}
|
||||
console.log(queryCondition.join(' AND '))
|
||||
// console.log(queryCondition.join(' AND '))
|
||||
this.urlChangeParams[this.curTabState.queryCondition] = queryCondition.join(' AND ')
|
||||
} else {
|
||||
searchProps.forEach(item => {
|
||||
@@ -627,9 +602,10 @@ export default {
|
||||
this.urlChangeParams[this.curTabState.tabOperationBeforeType] = this.getUrlParam(this.curTabState.tabOperationType, '', true)
|
||||
this.urlChangeParams[this.curTabState.tabOperationType] = opeType
|
||||
if (opeType === 3) {
|
||||
if (route !== '/panel/networkOverview') {
|
||||
/* if (route !== '/panel/networkOverview') {
|
||||
this.urlChangeParams.queryCondition = ''
|
||||
}
|
||||
} */
|
||||
this.urlChangeParams.queryCondition = ''
|
||||
}
|
||||
} else {
|
||||
this.urlChangeParams[this.curTabState.tabOperationType] = operationType.mainMenu
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
</div>
|
||||
<div class="right-box__container">
|
||||
<div class="container__form">
|
||||
<el-form ref="userForm" :model="editObject" :rules="rules" label-position="top" label-width="120px">
|
||||
<el-form ref="reportForm" :model="editObject" :rules="rules" label-position="top" label-width="120px">
|
||||
<!--name-->
|
||||
<el-form-item :label="$t('report.name')" prop="name">
|
||||
<el-input id="account-input-name" v-model="editObject.name" maxlength="64" placeholder=" " show-word-limit size="small" type="text"></el-input>
|
||||
@@ -76,7 +76,6 @@
|
||||
:disabled="!!editObject.id"
|
||||
:disabled-date="startDisabledDate"
|
||||
@change="startTimeChang"
|
||||
@focus="startFocus"
|
||||
prefix-icon="cn-icon cn-icon-shijian"
|
||||
type="datetime"
|
||||
placeholder=" "
|
||||
@@ -96,7 +95,6 @@
|
||||
:disabled="!!editObject.id"
|
||||
:disabled-date="endDisabledDate"
|
||||
@change="endTimeChange"
|
||||
@focus="endFocus"
|
||||
prefix-icon="cn-icon cn-icon-shijian"
|
||||
type="datetime"
|
||||
placeholder=" "
|
||||
@@ -283,28 +281,8 @@ import { api } from '@/utils/api'
|
||||
import _ from 'lodash'
|
||||
import { get, post, put } from '@/utils/http'
|
||||
import { dateFormat, getMillisecond } from '@/utils/date-util'
|
||||
import { ref } from 'vue'
|
||||
const paramValidator = (rule, value, callback) => {
|
||||
let validate = true
|
||||
if (value && value.length > 0) {
|
||||
const hasEmpty = value.some(v => {
|
||||
return !v.value && v.value !== 0
|
||||
})
|
||||
validate = !hasEmpty
|
||||
}
|
||||
return validate
|
||||
}
|
||||
const nameValidator = (rule, value, callback) => {
|
||||
let validate = true
|
||||
const reg = /^[\u4e00-\u9fa5A-Za-z0-9\-\_]*$/
|
||||
if (reg.test(value)) {
|
||||
validate = true
|
||||
} else {
|
||||
validate = false
|
||||
}
|
||||
return validate
|
||||
}
|
||||
|
||||
import { ref, getCurrentInstance } from 'vue'
|
||||
import i18n from '@/i18n'
|
||||
export default {
|
||||
name: 'ReportBox',
|
||||
mixins: [rightBoxMixin],
|
||||
@@ -313,32 +291,21 @@ export default {
|
||||
currentCategoryId: Number
|
||||
},
|
||||
setup () {
|
||||
const { proxy } = getCurrentInstance()
|
||||
|
||||
const startTime = ref('')
|
||||
const endTime = ref('')
|
||||
const focus = ref('')
|
||||
const focusDate = ref('')
|
||||
function endTimeChange (val) {
|
||||
endTime.value = val
|
||||
}
|
||||
function startTimeChang (val) {
|
||||
startTime.value = val
|
||||
}
|
||||
function startFocus (val) {
|
||||
focus.value = val.target.value
|
||||
}
|
||||
function endFocus (val) {
|
||||
focusDate.value = val.target.value
|
||||
}
|
||||
const endDisabledDate = (time) => {
|
||||
if (time.getTime() > new Date()) {
|
||||
return true
|
||||
}
|
||||
if (startTime.value != '' && startTime.value > time) {
|
||||
return true
|
||||
}
|
||||
if (focusDate.value != '' && endTime.value > time) {
|
||||
return false
|
||||
} else if (endTime.value != '' && endTime.value < time) {
|
||||
if (startTime.value !== '' && startTime.value > time) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -346,22 +313,71 @@ export default {
|
||||
if (time.getTime() > new Date()) {
|
||||
return true
|
||||
}
|
||||
if (focus.value != '' && startTime.value > time) {
|
||||
return false
|
||||
} else if (startTime.value != '' && startTime.value > time) {
|
||||
if (endTime.value !== '' && endTime.value < time) {
|
||||
return true
|
||||
}
|
||||
if (endTime.value != '' && endTime.value < time) {
|
||||
return true
|
||||
}
|
||||
|
||||
const paramValidator = (rule, value, callback) => {
|
||||
let validate = true
|
||||
if (value && value.length > 0) {
|
||||
const hasEmpty = value.some(v => {
|
||||
return !v.value && v.value !== 0
|
||||
})
|
||||
validate = !hasEmpty
|
||||
}
|
||||
return validate
|
||||
}
|
||||
const nameValidator = (rule, value, callback) => {
|
||||
let validate = true
|
||||
const reg = /^[\u4e00-\u9fa5A-Za-z0-9\-\_]*$/
|
||||
validate = reg.test(value)
|
||||
return validate
|
||||
}
|
||||
const startTimeValidator = (rule, value, callback) => {
|
||||
const form = proxy.$refs.reportForm
|
||||
if (form.model.config.endTime) {
|
||||
form.validateField('config.endTime', () => null)
|
||||
}
|
||||
callback()
|
||||
}
|
||||
const endTimeValidator = (rule, value, callback) => {
|
||||
let validate = true
|
||||
if (startTime.value !== '' && value <= startTime.value) {
|
||||
validate = false
|
||||
}
|
||||
return validate
|
||||
}
|
||||
const rules = { // 表单校验规则
|
||||
name: [
|
||||
{ required: true, message: i18n.global.t('validate.required'), trigger: 'blur' },
|
||||
{ validator: nameValidator, message: i18n.global.t('validate.onlyAllowNumberLetterChinese-_'), trigger: 'blur' }
|
||||
],
|
||||
categoryId: [
|
||||
{ required: true, message: i18n.global.t('validate.required'), trigger: 'change' }
|
||||
],
|
||||
schedulerStart: [
|
||||
{ required: true, message: i18n.global.t('validate.required'), trigger: 'change' }
|
||||
],
|
||||
'config.startTime': [
|
||||
{ required: true, message: i18n.global.t('validate.required'), trigger: 'change' },
|
||||
{ validator: startTimeValidator, trigger: 'change' }
|
||||
],
|
||||
'config.endTime': [
|
||||
{ required: true, message: i18n.global.t('validate.required'), trigger: 'change' },
|
||||
{ validator: endTimeValidator, message: i18n.global.t('validate.endTimeGreaterThanStart'), trigger: 'change' }
|
||||
],
|
||||
categoryParams: [
|
||||
{ required: true, message: i18n.global.t('validate.required'), trigger: 'blur' },
|
||||
{ validator: paramValidator, message: i18n.global.t('validate.required'), trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
return {
|
||||
endDisabledDate,
|
||||
startDisabledDate,
|
||||
startTimeChang,
|
||||
endTimeChange,
|
||||
startFocus,
|
||||
endFocus
|
||||
rules
|
||||
}
|
||||
},
|
||||
data () {
|
||||
@@ -391,28 +407,6 @@ export default {
|
||||
monthWeekdayCheckedAll: false,
|
||||
monthWeekdayIsIndeterminate: false,
|
||||
|
||||
rules: { // 表单校验规则
|
||||
name: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' },
|
||||
{ validator: nameValidator, message: this.$t('validate.onlyAllowNumberLetterChinese-_'), trigger: 'blur' }
|
||||
],
|
||||
categoryId: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'change' }
|
||||
],
|
||||
schedulerStart: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'change' }
|
||||
],
|
||||
'config.startTime': [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'change' }
|
||||
],
|
||||
'config.endTime': [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'change' }
|
||||
],
|
||||
categoryParams: [
|
||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' },
|
||||
{ validator: paramValidator, message: this.$t('validate.required'), trigger: 'blur' }
|
||||
]
|
||||
},
|
||||
paramsOptions: []
|
||||
}
|
||||
},
|
||||
@@ -592,7 +586,7 @@ export default {
|
||||
if (this.blockOperation.save) { return }
|
||||
this.blockOperation.save = true
|
||||
|
||||
this.$refs.userForm.validate((valid) => {
|
||||
this.$refs.reportForm.validate((valid) => {
|
||||
if (valid) {
|
||||
let startTime = ''
|
||||
let endTime = ''
|
||||
|
||||
@@ -25,12 +25,12 @@
|
||||
<el-button size="mini" v-if="!isCancel" :id="tableId+'-element-set-all'" class="cn-btn cn-btn-size-small-new cn-btn-style-light-new" type="button" @click="batchHandler(true)">
|
||||
<span class="top-tool-btn-txt">{{$t('overall.all')}}</span>
|
||||
</el-button>
|
||||
<div>
|
||||
<div class="custom-bottom-btns-right">
|
||||
<el-button size="mini" :id="tableId+'-element-set-esc'" class="cn-btn cn-btn-size-small-new cn-btn-style-light-new" type="button" @click="esc">
|
||||
<span class="top-tool-btn-txt">{{$t('overall.cancel')}}</span>
|
||||
</el-button>
|
||||
<el-button size="mini" :id="tableId+'-element-set-save'" class="cn-btn cn-btn-size-small-new cn-btn-style-normal-new" type="button" @click="save" style="background-color: #0091ff;color:#DCDFE6">
|
||||
<span class="top-tool-btn-txt">{{$t('overall.save')}}</span>
|
||||
<span class="top-tool-btn-txt top-tool-btn-save">{{$t('overall.save')}}</span>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,19 @@
|
||||
import { dbName, dbGeoDataTableName, dbDrilldownTableConfig } from '@/utils/constants'
|
||||
import Dexie from 'dexie'
|
||||
/* https://dexie.org/ */
|
||||
|
||||
export const db = new Dexie(dbName)
|
||||
db.version(2).stores({
|
||||
const db = new Dexie(dbName)
|
||||
db.version(3).stores({
|
||||
[dbGeoDataTableName]: '++name, geo',
|
||||
[dbDrilldownTableConfig]: '++id, config'
|
||||
[dbDrilldownTableConfig]: '++id, config',
|
||||
test: '++id, name'
|
||||
})
|
||||
function selectTable (tableName) {
|
||||
return db[tableName]
|
||||
}
|
||||
|
||||
const indexedDBUtils = {
|
||||
db,
|
||||
selectTable
|
||||
}
|
||||
export default indexedDBUtils
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { hasButton } from '@/permission'
|
||||
import { dateFormatByAppearance } from '@/utils/date-util'
|
||||
import { storageKey } from '@/utils/constants'
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
@@ -21,7 +20,9 @@ export default {
|
||||
query: false
|
||||
},
|
||||
timeout: null,
|
||||
debounceFunc: null
|
||||
debounceFunc: null,
|
||||
// 是否正在单元测试
|
||||
isUnitTesting: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -59,7 +59,8 @@ const panel = {
|
||||
rangeEchartsData: {}, // 框选echarts图表
|
||||
routerHistoryList: [], // 路由跳转记录列表
|
||||
dnsQtypeMapData: [],
|
||||
dnsRcodeMapData: []
|
||||
dnsRcodeMapData: [],
|
||||
chartTabList: null // chartTabs组件的tab状态点击列表,初始化为null方便原有逻辑计算
|
||||
},
|
||||
mutations: {
|
||||
setShowRightBox (state, flag) {
|
||||
@@ -151,6 +152,9 @@ const panel = {
|
||||
},
|
||||
setRouterHistoryList (state, list) {
|
||||
state.routerHistoryList = list
|
||||
},
|
||||
setChartTabList (state, list) {
|
||||
state.chartTabList = list
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
@@ -225,6 +229,9 @@ const panel = {
|
||||
},
|
||||
getRouterHistoryList (state) {
|
||||
return state.routerHistoryList
|
||||
},
|
||||
getChartTabList (state) {
|
||||
return state.chartTabList
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
@@ -253,6 +260,9 @@ const panel = {
|
||||
},
|
||||
clearPanel (store) {
|
||||
store.commit('cleanPanel')
|
||||
},
|
||||
dispatchChartTabList (store, list) {
|
||||
store.commit('setChartTabList', list)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { ElMessage } from 'element-plus' // dependent on utc plugin
|
||||
import { storageKey, dbDrilldownTableConfig } from '@/utils/constants'
|
||||
import { getConfigVersion } from '@/utils/tools'
|
||||
import { api } from '@/utils/api'
|
||||
import { db } from '@/indexedDB'
|
||||
import indexedDBUtils from '@/indexedDB'
|
||||
|
||||
const user = {
|
||||
state () {
|
||||
@@ -92,7 +92,7 @@ const user = {
|
||||
if (res.code === 200 && res.page.list && res.page.list.length > 0) {
|
||||
// 从接口返回整体配置,再读取用户缓存,将对应条目覆盖,作为使用的配置
|
||||
const defaultConfigs = JSON.parse(res.page.list[0].cvalue)
|
||||
await db[dbDrilldownTableConfig].put({
|
||||
await indexedDBUtils.selectTable(dbDrilldownTableConfig).put({
|
||||
id: 'default',
|
||||
version: defaultConfigs.version,
|
||||
config: defaultConfigs.config
|
||||
@@ -100,7 +100,7 @@ const user = {
|
||||
const userId = localStorage.getItem(storageKey.userId)
|
||||
const oldVersion = await getConfigVersion(userId)
|
||||
if (oldVersion !== defaultConfigs.version) {
|
||||
db[dbDrilldownTableConfig].delete(userId)
|
||||
indexedDBUtils.selectTable(dbDrilldownTableConfig).delete(userId)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -318,11 +318,12 @@ export async function getI18n () {
|
||||
|
||||
/* 获得原始的3611-2 json字符串数据 */
|
||||
export async function getIso36112JsonData (suffix) {
|
||||
const url = `${window.location.protocol}//${window.location.host}/geojson/${suffix}.json`
|
||||
const request = new Promise(resolve => {
|
||||
axios({
|
||||
url: `${window.location.protocol}//${window.location.host}:${window.location.port}/geojson/${suffix}.json`
|
||||
}).then(response => {
|
||||
axios({ url }).then(response => {
|
||||
resolve(response.data || response || null)
|
||||
}).catch(err => {
|
||||
console.error(err)
|
||||
})
|
||||
})
|
||||
return await request
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
export const defaultPageSize = 20
|
||||
|
||||
// indexedDB库名
|
||||
export const dbName = 'cn-db'
|
||||
// indexedDB表名
|
||||
export const dbGeoDataTableName = 'geodata'
|
||||
export const dbDrilldownTableConfig = 'cn-drilldown-table-config'
|
||||
export const storageKey = {
|
||||
@@ -61,7 +63,8 @@ export const panelTypeAndRouteMapping = {
|
||||
cryptocurrency: 7,
|
||||
ipDrillDownTest: 8,
|
||||
linkMonitor: 14,
|
||||
linkMonitorDrillDown: 15
|
||||
linkMonitorDrillDown: 15,
|
||||
dns6: 18
|
||||
}
|
||||
|
||||
/* operationLog state 执行状态属性 值与名称之间的映射 */
|
||||
@@ -1552,7 +1555,7 @@ export const npmCategoryInfoMapping = [
|
||||
|
||||
// 整屏滚动的路径映射
|
||||
export const wholeScreenRouterMapping = {
|
||||
dns: '/panel/dnsServiceInsights'
|
||||
dns: '/dns6/dns6'
|
||||
}
|
||||
|
||||
export const themeData = [
|
||||
|
||||
@@ -5,8 +5,7 @@ import { storageKey, iso36112, topDomain, echartsFontSize, dbGeoDataTableName, n
|
||||
import { getIso36112JsonData, getDictList } from '@/utils/api'
|
||||
import { format } from 'echarts'
|
||||
import router from '@/router'
|
||||
import { db } from '@/indexedDB'
|
||||
import { useRoute } from 'vue-router'
|
||||
import indexedDBUtils from '@/indexedDB'
|
||||
|
||||
export const tableSort = {
|
||||
// 是否需要排序
|
||||
@@ -488,11 +487,11 @@ export function loadGeoData () {
|
||||
keys.push(storageKey.iso36112Capital)
|
||||
keys.push(storageKey.iso36112WorldLow)
|
||||
keys.forEach(async k => {
|
||||
const queryData = await db[dbGeoDataTableName].get({ name: k })
|
||||
const queryData = await indexedDBUtils.selectTable(dbGeoDataTableName).get({ name: k })
|
||||
if (!queryData) {
|
||||
const data = await getIso36112JsonData(iso36112[k])
|
||||
if (data) {
|
||||
db[dbGeoDataTableName].add({
|
||||
indexedDBUtils.selectTable(dbGeoDataTableName).add({
|
||||
name: k,
|
||||
geo: data
|
||||
})
|
||||
@@ -505,14 +504,14 @@ export function loadGeoData () {
|
||||
* 使用indexedDB缓存地图数据
|
||||
* */
|
||||
export async function getGeoData (key) {
|
||||
const data = await db[dbGeoDataTableName].get({ name: key })
|
||||
const data = await indexedDBUtils.selectTable(dbGeoDataTableName).get({ name: key })
|
||||
if (data) {
|
||||
return data.geo
|
||||
} else {
|
||||
if (iso36112[key]) {
|
||||
const d = await getIso36112JsonData(iso36112[key])
|
||||
if (d) {
|
||||
db[dbGeoDataTableName].add({
|
||||
indexedDBUtils.selectTable(dbGeoDataTableName).add({
|
||||
name: key,
|
||||
geo: d
|
||||
})
|
||||
@@ -937,7 +936,7 @@ export async function getDefaultCurTab (tableType, metric, columnName) {
|
||||
export async function readDrilldownTableConfigByUser () {
|
||||
// 获取用户定制的自定义配置
|
||||
const userId = localStorage.getItem(storageKey.userId)
|
||||
const userLocalConfig = await db[dbDrilldownTableConfig].get({ id: userId })
|
||||
const userLocalConfig = await indexedDBUtils.selectTable(dbDrilldownTableConfig).get({ id: userId })
|
||||
let defaultDrillDownTableConfigs = []
|
||||
if (userLocalConfig) {
|
||||
defaultDrillDownTableConfigs = userLocalConfig.config
|
||||
@@ -946,15 +945,15 @@ export async function readDrilldownTableConfigByUser () {
|
||||
}
|
||||
|
||||
export async function getConfigVersion (id) {
|
||||
let defaultConfigInDb = await db[dbDrilldownTableConfig].get({ id: id })
|
||||
let defaultConfigInDb = await indexedDBUtils.selectTable(dbDrilldownTableConfig).get({ id: id })
|
||||
if (!defaultConfigInDb) {
|
||||
defaultConfigInDb = await db[dbDrilldownTableConfig].get({ id: 'default' })
|
||||
defaultConfigInDb = await indexedDBUtils.selectTable(dbDrilldownTableConfig).get({ id: 'default' })
|
||||
}
|
||||
return defaultConfigInDb.version || ''
|
||||
}
|
||||
|
||||
export async function combineDrilldownTableWithUserConfig () {
|
||||
const defaultConfigInDb = await db[dbDrilldownTableConfig].get({ id: 'default' })
|
||||
const defaultConfigInDb = await indexedDBUtils.selectTable(dbDrilldownTableConfig).get({ id: 'default' })
|
||||
const defaultConfigGroup = defaultConfigInDb ? defaultConfigInDb.config : []
|
||||
const currentUserConfigGroup = await readDrilldownTableConfigByUser()
|
||||
if (defaultConfigGroup && currentUserConfigGroup && currentUserConfigGroup.length > 0) {
|
||||
@@ -1086,3 +1085,64 @@ export function colorGradientCalculation (startColor, endColor, values) {
|
||||
export function colorHexToRgbArr (hex) {
|
||||
return [1, 3, 5].map((h) => parseInt(hex.substring(h, h + 2), 16))
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过事件类型eventType转换对应名称
|
||||
* @param type
|
||||
* @returns {string}
|
||||
*/
|
||||
export function getNameByEventType (type) {
|
||||
switch (type) {
|
||||
case 'http error': {
|
||||
return 'http error ratio'
|
||||
}
|
||||
case 'dns error': {
|
||||
return 'dns error ratio'
|
||||
}
|
||||
case 'high dns response time': {
|
||||
return 'dns response time'
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
折线图通过事件类型 type 转换对应名称
|
||||
*/
|
||||
export function getLineType (type) {
|
||||
switch (type) {
|
||||
case 'bytes': {
|
||||
return 'Bits/s'
|
||||
}
|
||||
case 'packets': {
|
||||
return 'Packets/s'
|
||||
}
|
||||
case 'sessions': {
|
||||
return 'Sessions/s'
|
||||
}
|
||||
case 'queries': {
|
||||
return 'Queries/s'
|
||||
}
|
||||
default: return type
|
||||
}
|
||||
}
|
||||
/**
|
||||
npm折线图通过事件类型 type 转换对应 index 以及 unit
|
||||
*/
|
||||
export function getLineIndexUnit (type, show) {
|
||||
switch (type) {
|
||||
case 'establishLatencyMs': {
|
||||
return show ? '(ms)' : 0
|
||||
}
|
||||
case 'tcpLostlenPercent': {
|
||||
return show ? '(%)' : 3
|
||||
}
|
||||
case 'pktRetransPercent': {
|
||||
return show ? '(%)' : 4
|
||||
}
|
||||
case 'httpResponseLatency': {
|
||||
return show ? '(ms)' : 1
|
||||
}
|
||||
case 'sslConLatency': {
|
||||
return show ? '(ms)' : 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -38,21 +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'
|
||||
},
|
||||
{
|
||||
i18n: 'galaxyProxy.galaxyProxy',
|
||||
path: '/administration/galaxyProxy',
|
||||
icon: 'cn-icon cn-icon-proxy'
|
||||
},
|
||||
{
|
||||
i18n: 'overall.chart',
|
||||
path: '/administration/chart',
|
||||
icon: 'cn-icon cn-icon-chart'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -114,8 +114,8 @@ export default {
|
||||
},
|
||||
reload () {
|
||||
this.copyDataList.forEach(item => {
|
||||
if (this.$refs['chart' + item.id]) {
|
||||
this.$refs['chart' + item.id].reload()
|
||||
if (this.$refs['chart' + item.id] && this.$refs['chart' + item.id][0]) {
|
||||
this.$refs['chart' + item.id][0].reload()
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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]),
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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> <span>{{unitConvert($_.get(chartData, 'bytesPercent'), unitTypes.percent).join('')}}</span></div>
|
||||
<div class="content__data-protocol-percent"><span>{{$t('protocol.proportion')}}</span> <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> <span>{{unitConvert($_.get(chartData, 'countPercent'), unitTypes.percent).join('')}}</span></div>
|
||||
<div class="content__data-protocol-percent"><span>{{$t('protocol.proportion')}}</span> <span>{{unitConvert($_.get(chartData, 'bytesPercent'), unitTypes.percent).join('')}}</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -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'),
|
||||
|
||||
@@ -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: {}
|
||||
|
||||
@@ -32,8 +32,8 @@ export default {
|
||||
methods: {
|
||||
reload () {
|
||||
this.dnsScreenDataList.forEach(item => {
|
||||
if (this.$refs['chart' + item.id]) {
|
||||
this.$refs['chart' + item.id].getChartData()
|
||||
if (this.$refs['chart' + item.id] && this.$refs['chart' + item.id][0]) {
|
||||
this.$refs['chart' + item.id][0].getChartData()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -334,6 +334,8 @@ export default {
|
||||
if (!this.$refs.dateTimeRange.isCustom) {
|
||||
const value = this.timeFilter.dateRangeValue
|
||||
this.$refs.dateTimeRange.quickChange(value)
|
||||
} else {
|
||||
this.timeFilter = JSON.parse(JSON.stringify(this.timeFilter))
|
||||
}
|
||||
} else {
|
||||
this.timeFilter = JSON.parse(JSON.stringify(this.timeFilter))
|
||||
|
||||
@@ -123,11 +123,8 @@ export default {
|
||||
this.toggleLoading(true)
|
||||
get(api.dnsInsight.activeMaliciousDomain, params).then(res => {
|
||||
if (res.code === 200) {
|
||||
const data = res.data.result
|
||||
if (!data || data.length === 0) {
|
||||
this.isNoData = true
|
||||
}
|
||||
this.tableData = data
|
||||
this.isNoData = res.data.result.length === 0
|
||||
this.tableData = res.data.result
|
||||
} else {
|
||||
this.isNoData = true
|
||||
}
|
||||
|
||||
@@ -95,6 +95,9 @@ export default {
|
||||
},
|
||||
beforeUnmount () {
|
||||
window.removeEventListener('resize', this.resize)
|
||||
if (this.myChart) {
|
||||
echarts.dispose(this.myChart)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -147,6 +147,9 @@ export default {
|
||||
},
|
||||
beforeUnmount () {
|
||||
window.removeEventListener('resize', this.resize)
|
||||
if (this.myChart) {
|
||||
echarts.dispose(this.myChart)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -208,9 +208,7 @@ export default {
|
||||
this.toggleLoading(true)
|
||||
get(api.dnsInsight.recentEvents, params).then(res => {
|
||||
if (res.code === 200) {
|
||||
if (!res.data.result || res.data.result.length === 0) {
|
||||
this.isNoData = true
|
||||
}
|
||||
this.isNoData = res.data.result.length === 0
|
||||
this.tableData = res.data.result
|
||||
this.tableData.forEach((t, index) => {
|
||||
if (index > 5) {
|
||||
|
||||
@@ -79,7 +79,7 @@ import { getSecond } from '@/utils/date-util'
|
||||
import ChartNoData from '@/views/charts/charts/ChartNoData'
|
||||
import chartMixin from '@/views/charts2/chart-mixin'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { overwriteUrl, urlParamsHandler } from '@/utils/tools'
|
||||
import { getLineType, overwriteUrl, urlParamsHandler } from '@/utils/tools'
|
||||
export default {
|
||||
name: 'DnsTrafficLine',
|
||||
components: {
|
||||
@@ -207,63 +207,9 @@ export default {
|
||||
{ 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: '' }
|
||||
]
|
||||
} else {
|
||||
this.initData(res.data.result, val, active, show)
|
||||
}
|
||||
res.data.result.forEach((t) => {
|
||||
if (t.type === 'bytes' && val === 'Bits/s') {
|
||||
const mpackets = _.cloneDeep(this.mpackets)
|
||||
mpackets[0].analysis = t.totalBitsRate.analysis
|
||||
mpackets[1].analysis = t.inboundBitsRate.analysis
|
||||
mpackets[2].analysis = t.outboundBitsRate.analysis
|
||||
mpackets[0].data = t.totalBitsRate.values ? t.totalBitsRate.values : []
|
||||
mpackets[1].data = t.inboundBitsRate.values ? t.inboundBitsRate.values : []
|
||||
mpackets[2].data = t.outboundBitsRate.values ? t.outboundBitsRate.values : []
|
||||
let num = 0
|
||||
mpackets.forEach(e => {
|
||||
e.unitType = 'bps'
|
||||
if (e.name !== 'network.total' && parseFloat(e.analysis.avg) === 0) {
|
||||
e.show = false
|
||||
num += 1
|
||||
} else {
|
||||
e.show = true
|
||||
if (!active && show !== this.lineRefer) {
|
||||
this.legendSelectChange(e, 'index')
|
||||
}
|
||||
}
|
||||
if (this.lineTab === e.class) {
|
||||
if (parseFloat(e.analysis.avg) <= 0) {
|
||||
this.lineTab = ''
|
||||
this.lineRefer = ''
|
||||
this.init()
|
||||
}
|
||||
}
|
||||
})
|
||||
this.mpackets = mpackets
|
||||
if (num === 3) {
|
||||
mpackets[0].invertTab = false
|
||||
this.lineTab = 'total'
|
||||
this.legendSelectChange(mpackets[0], 0)
|
||||
this.echartsInit(this.mpackets)
|
||||
} else {
|
||||
this.echartsInit(this.mpackets, show)
|
||||
if (!this.lineRefer) this.lineRefer = 'Average'
|
||||
}
|
||||
} else if (t.type === 'queries' && val === 'Queries/s') {
|
||||
const mpackets = _.cloneDeep(this.mpackets)
|
||||
mpackets[0].analysis = t.totalQueryRate.analysis
|
||||
mpackets[0].data = t.totalQueryRate.values ? t.totalQueryRate.values : []
|
||||
mpackets.forEach((e, i) => {
|
||||
if (i !== 0) {
|
||||
e.show = false
|
||||
}
|
||||
e.unitType = 'queries/s'
|
||||
e.invertTab = false
|
||||
this.lineTab = 'total'
|
||||
this.legendSelectChange(e, 0)
|
||||
})
|
||||
this.mpackets = mpackets
|
||||
this.echartsInit(this.mpackets, true)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.isNoData = false
|
||||
this.showError = true
|
||||
@@ -526,6 +472,79 @@ export default {
|
||||
dataIntegrationArray.sort((a, b) => { return a[1] - b[1] })
|
||||
const sortIndex = dataIntegrationArray.findIndex(a => a[2] === index)
|
||||
return this.sizes[sortIndex]
|
||||
},
|
||||
initData (data, val, active, show) {
|
||||
let lineData = []
|
||||
if (data !== undefined && data.length > 0) {
|
||||
data.forEach((item) => {
|
||||
item.type = getLineType(item.type)
|
||||
if (item.type === val) {
|
||||
lineData = Object.keys(item).map(t => {
|
||||
return {
|
||||
...item[t]
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
lineData.splice(0, 1)
|
||||
const mpackets = _.cloneDeep(this.mpackets)
|
||||
if (val === 'Queries/s') {
|
||||
lineData.forEach((d, i) => {
|
||||
mpackets[i].data = d.values
|
||||
mpackets[i].analysis = d.analysis
|
||||
})
|
||||
mpackets.forEach((e, i) => {
|
||||
if (i !== 0) {
|
||||
e.show = false
|
||||
}
|
||||
e.unitType = 'queries/s'
|
||||
e.invertTab = false
|
||||
this.lineTab = 'total'
|
||||
this.legendSelectChange(e, 0)
|
||||
})
|
||||
this.mpackets = mpackets
|
||||
this.echartsInit(this.mpackets, true)
|
||||
} else {
|
||||
const unit = 'bps'
|
||||
this.legendInit(lineData, active, show, unit, mpackets)
|
||||
}
|
||||
},
|
||||
legendInit (data, active, show, type, dnsData) {
|
||||
data.forEach((d, i) => {
|
||||
dnsData[i].data = d.values
|
||||
dnsData[i].analysis = d.analysis
|
||||
})
|
||||
let num = 0
|
||||
dnsData.forEach(e => {
|
||||
e.unitType = type
|
||||
if (e.name !== 'network.total' && parseFloat(e.analysis.avg) === 0) {
|
||||
e.show = false
|
||||
num += 1
|
||||
} else {
|
||||
e.show = true
|
||||
if (!active && show !== this.lineRefer) {
|
||||
this.legendSelectChange(e, 'index')
|
||||
}
|
||||
}
|
||||
if (this.lineTab === e.class) {
|
||||
if (parseFloat(e.analysis.avg) <= 0) {
|
||||
this.lineTab = ''
|
||||
this.lineRefer = ''
|
||||
this.init()
|
||||
}
|
||||
}
|
||||
})
|
||||
this.mpackets = dnsData
|
||||
if (num === 3) {
|
||||
dnsData[0].invertTab = false
|
||||
this.lineTab = 'total'
|
||||
this.legendSelectChange(dnsData[0], 0)
|
||||
this.echartsInit(this.mpackets)
|
||||
} else {
|
||||
this.echartsInit(this.mpackets, show)
|
||||
if (!this.lineRefer) this.lineRefer = 'Average'
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
@@ -542,7 +561,9 @@ export default {
|
||||
beforeUnmount () {
|
||||
clearTimeout(this.timer)
|
||||
window.removeEventListener('resize', this.resize)
|
||||
this.myChart = null
|
||||
if (this.myChart) {
|
||||
echarts.dispose(this.myChart)
|
||||
}
|
||||
this.chartOption = null
|
||||
this.unitConvert = null
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="link-statistical-dimension" style="position: relative">
|
||||
<div class="dimension-title">{{ $t('linkMonitor.egressLink') }} & {{ $t('linkMonitor.ingressLink') }}
|
||||
</div>
|
||||
<div class="dimension-title" v-if="gridData.length>3">{{ $t('linkMonitor.egressLink') }} & {{ $t('linkMonitor.ingressLink') }}</div>
|
||||
<div class="dimension-title" v-else>{{ $t('linkMonitor.nextHopInternetOfGrid') }}</div>
|
||||
|
||||
<chart-no-data v-if="isNoData"></chart-no-data>
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ import { useRoute } from 'vue-router'
|
||||
import { ref, shallowRef } from 'vue'
|
||||
import unitConvert from '@/utils/unit-convert'
|
||||
import { chartColor3, chartColor4, unitTypes } from '@/utils/constants'
|
||||
import { overwriteUrl, urlParamsHandler } from '@/utils/tools'
|
||||
import { getLineType, overwriteUrl, urlParamsHandler } from '@/utils/tools'
|
||||
import { getSecond } from '@/utils/date-util'
|
||||
import { get } from '@/utils/http'
|
||||
import { api } from '@/utils/api'
|
||||
@@ -187,94 +187,9 @@ export default {
|
||||
{ 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: '' }
|
||||
]
|
||||
} else {
|
||||
this.initData(res.data.result, val, active, show)
|
||||
}
|
||||
res.data.result.forEach((t) => {
|
||||
if (t.type === 'bytes' && val === 'Bits/s') {
|
||||
const mpackets = _.cloneDeep(this.mpackets)
|
||||
mpackets[0].analysis = t.totalBitsRate.analysis
|
||||
mpackets[1].analysis = t.ingressBitsRate.analysis
|
||||
mpackets[2].analysis = t.egressBitsRate.analysis
|
||||
mpackets[0].data = t.totalBitsRate.values ? t.totalBitsRate.values : []
|
||||
mpackets[1].data = t.ingressBitsRate.values ? t.ingressBitsRate.values : []
|
||||
mpackets[2].data = t.egressBitsRate.values ? t.egressBitsRate.values : []
|
||||
let num = 0
|
||||
mpackets.forEach(e => {
|
||||
e.unitType = 'bps'
|
||||
if (e.name !== 'network.total' && parseFloat(e.analysis.avg) === 0) {
|
||||
e.show = false
|
||||
num += 1
|
||||
} else {
|
||||
e.show = true
|
||||
if (!active && !show) {
|
||||
this.legendSelectChange(e, 'index')
|
||||
}
|
||||
}
|
||||
if (this.lineTab === e.class) {
|
||||
if (parseFloat(e.analysis.avg) <= 0) {
|
||||
this.lineTab = ''
|
||||
this.lineRefer = ''
|
||||
this.init()
|
||||
}
|
||||
}
|
||||
})
|
||||
this.mpackets = mpackets
|
||||
if (num === 3) {
|
||||
mpackets[0].invertTab = false
|
||||
this.lineTab = 'total'
|
||||
this.legendSelectChange(mpackets[0], 0)
|
||||
this.$nextTick(() => {
|
||||
this.echartsInit(this.mpackets)
|
||||
})
|
||||
} else {
|
||||
this.$nextTick(() => {
|
||||
this.echartsInit(this.mpackets)
|
||||
if (!this.lineRefer) this.lineRefer = 'Average'
|
||||
})
|
||||
}
|
||||
} else if (t.type === 'packets' && val === 'Packets/s') {
|
||||
const mpackets = _.cloneDeep(this.mpackets)
|
||||
mpackets[0].analysis = t.totalPacketsRate.analysis
|
||||
mpackets[1].analysis = t.ingressPacketsRate.analysis
|
||||
mpackets[2].analysis = t.egressPacketsRate.analysis
|
||||
mpackets[0].data = t.totalPacketsRate.values ? t.totalPacketsRate.values : []
|
||||
mpackets[1].data = t.ingressPacketsRate.values ? t.ingressPacketsRate.values : []
|
||||
mpackets[2].data = t.egressPacketsRate.values ? t.egressPacketsRate.values : []
|
||||
let num = 0
|
||||
mpackets.forEach(e => {
|
||||
e.unitType = 'packets/s'
|
||||
if (e.name !== 'network.total' && parseFloat(e.analysis.avg) === 0) {
|
||||
e.show = false
|
||||
num += 1
|
||||
} else {
|
||||
e.show = true
|
||||
if (!active && !show) {
|
||||
this.legendSelectChange(e, 'index')
|
||||
}
|
||||
}
|
||||
if (this.lineTab === e.class) {
|
||||
if (parseFloat(e.analysis.avg) <= 0) {
|
||||
this.lineTab = ''
|
||||
this.lineRefer = ''
|
||||
this.init()
|
||||
}
|
||||
}
|
||||
})
|
||||
this.mpackets = mpackets
|
||||
if (num === 3) {
|
||||
mpackets[0].invertTab = false
|
||||
this.lineTab = 'total'
|
||||
this.legendSelectChange(mpackets[0], 0)
|
||||
this.$nextTick(() => {
|
||||
this.echartsInit(this.mpackets)
|
||||
})
|
||||
} else {
|
||||
this.$nextTick(() => {
|
||||
this.echartsInit(this.mpackets)
|
||||
if (!this.lineRefer) this.lineRefer = 'Average'
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.showError = true
|
||||
this.errorMsg = res.message
|
||||
@@ -457,6 +372,65 @@ export default {
|
||||
dataIntegrationArray.sort((a, b) => { return a[1] - b[1] })
|
||||
const sortIndex = dataIntegrationArray.findIndex(a => a[2] === index)
|
||||
return this.sizes[sortIndex]
|
||||
},
|
||||
initData (data, val, active, show) {
|
||||
let lineData = []
|
||||
if (data !== undefined && data.length > 0) {
|
||||
data.forEach((item) => {
|
||||
item.type = getLineType(item.type)
|
||||
if (item.type === val) {
|
||||
lineData = Object.keys(item).map(t => {
|
||||
return {
|
||||
...item[t]
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
lineData.splice(0, 1)
|
||||
const mpackets = _.cloneDeep(this.mpackets)
|
||||
const unit = val === 'Bits/s' ? 'bps' : 'packets/s'
|
||||
this.legendInit(lineData, active, show, unit, mpackets)
|
||||
},
|
||||
legendInit (data, active, show, type, linkData) {
|
||||
data.forEach((d, i) => {
|
||||
linkData[i].data = d.values
|
||||
linkData[i].analysis = d.analysis
|
||||
})
|
||||
let num = 0
|
||||
linkData.forEach(e => {
|
||||
e.unitType = type
|
||||
if (e.name !== 'network.total' && parseFloat(e.analysis.avg) === 0) {
|
||||
e.show = false
|
||||
num += 1
|
||||
} else {
|
||||
e.show = true
|
||||
if (!active && !show) {
|
||||
this.legendSelectChange(e, 'index')
|
||||
}
|
||||
}
|
||||
if (this.lineTab === e.class) {
|
||||
if (parseFloat(e.analysis.avg) <= 0) {
|
||||
this.lineTab = ''
|
||||
this.lineRefer = ''
|
||||
this.init()
|
||||
}
|
||||
}
|
||||
})
|
||||
this.mpackets = linkData
|
||||
if (num === 3) {
|
||||
linkData[0].invertTab = false
|
||||
this.lineTab = 'total'
|
||||
this.legendSelectChange(linkData[0], 0)
|
||||
this.$nextTick(() => {
|
||||
this.echartsInit(this.mpackets)
|
||||
})
|
||||
} else {
|
||||
this.$nextTick(() => {
|
||||
this.echartsInit(this.mpackets)
|
||||
if (!this.lineRefer) this.lineRefer = 'Average'
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
@@ -473,7 +447,9 @@ export default {
|
||||
beforeUnmount () {
|
||||
clearTimeout(this.timer)
|
||||
window.removeEventListener('resize', this.resize)
|
||||
this.myChart = null
|
||||
if (this.myChart) {
|
||||
echarts.dispose(this.myChart)
|
||||
}
|
||||
this.chartOption = null
|
||||
this.unitConvert = null
|
||||
}
|
||||
|
||||
@@ -102,15 +102,12 @@ export default {
|
||||
if (condition.length > 1) {
|
||||
if (n === 0) {
|
||||
params.q = condition.find(c => c.indexOf('common_ingress_link_id') > -1 || c.indexOf('ingress_link_direction') > -1)
|
||||
url = api.linkMonitor.drilldownQuadrupleIngressAnalysis // 入口
|
||||
} else {
|
||||
params.q = condition.find(c => c.indexOf('common_egress_link_id') > -1 || c.indexOf('egress_link_direction') > -1)
|
||||
url = api.linkMonitor.drilldownQquadrupleEgressAnalysis // 出口
|
||||
}
|
||||
}
|
||||
if (n === 0) {
|
||||
url = api.linkMonitor.drilldownQuadrupleIngressAnalysis // 入口
|
||||
} else {
|
||||
url = api.linkMonitor.drilldownQquadrupleEgressAnalysis // 出口
|
||||
}
|
||||
} else {
|
||||
if (n === 0) {
|
||||
url = api.linkMonitor.quadrupleIngressAnalysis // 入口
|
||||
|
||||
@@ -152,7 +152,6 @@ export default {
|
||||
searcherApp: '',
|
||||
// 选中的app,不区分app和provider
|
||||
toSaveApp: [],
|
||||
appShowType: 'bytes',
|
||||
pageObj: { // 分页对象
|
||||
pageNo: 1,
|
||||
pageSize: 24,
|
||||
@@ -248,7 +247,7 @@ export default {
|
||||
handleData (prevRequest, request, _t) {
|
||||
this.toggleLoading(true)
|
||||
Promise.all([prevRequest, request]).then(res => {
|
||||
this.isNoData = (res[0].data.result.length && res[1].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 {
|
||||
@@ -298,16 +297,6 @@ export default {
|
||||
this.toggleLoading(false)
|
||||
})
|
||||
},
|
||||
metricChange (value) {
|
||||
if (value === 'Bits/s') {
|
||||
this.appShowType = 'bytes'
|
||||
} else if (value === 'Packets/s') {
|
||||
this.appShowType = 'packets'
|
||||
} else if (value === 'Sessions/s') {
|
||||
this.appShowType = 'sessions'
|
||||
}
|
||||
this.init()
|
||||
},
|
||||
getUrlParam (param, defaultValue, isNumber) {
|
||||
if (isNumber) {
|
||||
return this.$route.query[param] ? Number(this.$route.query[param]) : defaultValue
|
||||
@@ -675,13 +664,6 @@ export default {
|
||||
})
|
||||
}
|
||||
},
|
||||
// moreChange (app) {
|
||||
// this.appData.forEach(t => {
|
||||
// if (t.name === app.name && t.type === app.type) {
|
||||
// t.moreOptions = !t.moreOptions
|
||||
// }
|
||||
// })
|
||||
// },
|
||||
resize () {
|
||||
this.myChart.forEach(t => {
|
||||
t.resize()
|
||||
@@ -734,7 +716,9 @@ export default {
|
||||
window.removeEventListener('resize', this.resize)
|
||||
clearTimeout(this.timerScroll)
|
||||
clearTimeout(this.timerSearch)
|
||||
this.myChart = null
|
||||
if (this.myChart) {
|
||||
echarts.dispose(this.myChart)
|
||||
}
|
||||
this.unitConvert = null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,15 +11,15 @@
|
||||
<div class="ddos-detection-type">
|
||||
<div class="ddos-detection-type-value">
|
||||
<div class="ddos-detection-type-value-name">{{$t('network.numberOfAttacks')}}</div>
|
||||
<div class="ddos-detection-type-value-number">{{$_.get(ddosData, 'attackerCount') || 0}}</div>
|
||||
<div class="ddos-detection-type-value-number" test-id="attackerCount">{{unitConvert($_.get(ddosData, 'attackerCount'), unitTypes.number).join(' ')}}</div>
|
||||
</div>
|
||||
<div class="ddos-detection-type-value">
|
||||
<div class="ddos-detection-type-value-name">{{$t('network.number0fVictims')}}</div>
|
||||
<div class="ddos-detection-type-value-number">{{$_.get(ddosData, 'victimCount') || 0}}</div>
|
||||
<div class="ddos-detection-type-value-number" test-id="victimCount">{{unitConvert($_.get(ddosData, 'victimCount'), unitTypes.number).join(' ')}}</div>
|
||||
</div>
|
||||
<div class="ddos-detection-type-value">
|
||||
<div class="ddos-detection-type-value-name">{{$t('network.number0fDetectedAttackEvents')}}</div>
|
||||
<div class="ddos-detection-type-value-number ddos-event">{{$_.get(ddosData, 'attackEventCount') || 0}}</div>
|
||||
<div class="ddos-detection-type-value-number ddos-event" test-id="attackEventCount">{{unitConvert($_.get(ddosData, 'attackEventCount'), unitTypes.number).join(' ')}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-button size="small">{{$t('network.ddosDetection')}}<i class="cn-icon cn-icon-arrow-right"></i></el-button>
|
||||
@@ -29,11 +29,13 @@
|
||||
|
||||
<script>
|
||||
import { api } from '@/utils/api'
|
||||
import { get } from '@/utils/http'
|
||||
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 unitConvert from '@/utils/unit-convert'
|
||||
import { unitTypes } from '@/utils/constants'
|
||||
import axios from 'axios'
|
||||
export default {
|
||||
name: 'NetworkOverviewDdosDetection',
|
||||
components: {
|
||||
@@ -44,6 +46,8 @@ export default {
|
||||
data () {
|
||||
return {
|
||||
ddosData: {},
|
||||
unitConvert,
|
||||
unitTypes,
|
||||
isNoData: false,
|
||||
showError: false,
|
||||
errorMsg: ''
|
||||
@@ -59,19 +63,16 @@ export default {
|
||||
methods: {
|
||||
ddosDetectDataRequests () {
|
||||
const params = {
|
||||
startTime: getSecond(this.timeFilter.startTime),
|
||||
endTime: getSecond(this.timeFilter.endTime)
|
||||
startTime: this.timeFilter && this.timeFilter.startTime ? getSecond(this.timeFilter.startTime) : '',
|
||||
endTime: this.timeFilter && this.timeFilter.endTime ? getSecond(this.timeFilter.endTime) : ''
|
||||
}
|
||||
this.toggleLoading(true)
|
||||
get(api.netWorkOverview.ddosEventAnalysis, params).then(res => {
|
||||
axios.get(api.netWorkOverview.ddosEventAnalysis, { params: params }).then(res => {
|
||||
res = res.data
|
||||
if (res.code === 200) {
|
||||
this.showError = false
|
||||
if (res.data.result.length === 0) {
|
||||
this.isNoData = true
|
||||
} else {
|
||||
this.ddosData = res.data.result[0]
|
||||
this.isNoData = false
|
||||
}
|
||||
this.isNoData = res.data.result.length === 0
|
||||
this.ddosData = res.data.result[0]
|
||||
} else {
|
||||
this.isNoData = false
|
||||
this.showError = true
|
||||
@@ -87,7 +88,12 @@ export default {
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.ddosDetectDataRequests()
|
||||
this.$nextTick(() => {
|
||||
this.ddosDetectDataRequests()
|
||||
})
|
||||
},
|
||||
beforeUnmount () {
|
||||
this.unitConvert = null
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -12,15 +12,18 @@
|
||||
:key="index"
|
||||
@mouseenter="mouseenter(item)"
|
||||
@mouseleave="mouseleave(item)"
|
||||
@click="activeChange(item, index)">
|
||||
@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">
|
||||
<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>{{unitConvert(item.analysis.avg, unitTypes.number)[1]}}</span>
|
||||
<span v-if="item.unitType">{{item.unitType}}</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -46,7 +49,7 @@
|
||||
</div>
|
||||
<div style="height: calc(100% - 74px); position: relative">
|
||||
<chart-no-data v-if="isNoData && !showError"></chart-no-data>
|
||||
<div class="chart-drawing" v-show="showMarkLine && !isNoData && !showError" id="overviewLineChart"></div>
|
||||
<div class="chart-drawing" v-show="showMarkLine && !isNoData && !showError" ref="overviewLineChart"></div>
|
||||
<!-- todo 后续改动,此处为框选返回-->
|
||||
<!-- <div id="brushBtn" style="position: absolute;left: 0;top: 0;" v-show="mouseDownFlag">-->
|
||||
<!-- <el-button @click.stop="backBrushHistory">返回</el-button>-->
|
||||
@@ -63,13 +66,13 @@ import { unitTypes, chartColor3, chartColor4 } from '@/utils/constants.js'
|
||||
import { ref, shallowRef } from 'vue'
|
||||
import { stackedLineTooltipFormatter } from '@/views/charts/charts/tools'
|
||||
import _ from 'lodash'
|
||||
import { get } from '@/utils/http'
|
||||
import axios from 'axios'
|
||||
import { api } from '@/utils/api'
|
||||
import { getSecond } from '@/utils/date-util'
|
||||
import ChartNoData from '@/views/charts/charts/ChartNoData'
|
||||
import chartMixin from '@/views/charts2/chart-mixin'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { overwriteUrl, urlParamsHandler } from '@/utils/tools'
|
||||
import { getLineType, overwriteUrl, urlParamsHandler } from '@/utils/tools'
|
||||
import ChartError from '@/components/common/Error'
|
||||
export default {
|
||||
name: 'NetworkOverviewLine',
|
||||
@@ -186,32 +189,16 @@ export default {
|
||||
startTime: getSecond(this.timeFilter.startTime),
|
||||
endTime: getSecond(this.timeFilter.endTime)
|
||||
}
|
||||
let condition = ''
|
||||
if (this.queryCondition && this.tabOperationType !== '3') {
|
||||
if (this.queryCondition) {
|
||||
params.q = this.queryCondition
|
||||
} else if (this.tabOperationType == '3' && this.queryCondition) {
|
||||
if (this.queryCondition.indexOf(' OR ') > -1) {
|
||||
if (this.networkOverviewBeforeTab === 'isp') {
|
||||
condition = this.queryCondition.split(/["|'= ](.*?)["|'= ]/)
|
||||
params.q = `notEmpty(${condition[0]}) OR notEmpty(${condition[9]})`
|
||||
} else {
|
||||
condition = this.queryCondition.split(/["|'= ](.*?)["|'= ]/)
|
||||
params.q = `notEmpty(${condition[0]}) OR notEmpty(${condition[5]})`
|
||||
}
|
||||
} else {
|
||||
condition = this.queryCondition.split(/['=](.*?)['=]/)
|
||||
params.q = `notEmpty(${condition[0]})`
|
||||
}
|
||||
}
|
||||
this.toggleLoading(true)
|
||||
|
||||
get(api.netWorkOverview.totalTrafficAnalysis, params).then((res) => {
|
||||
axios.get(api.netWorkOverview.totalTrafficAnalysis, { params: params }).then(response => {
|
||||
const res = response.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.mpackets = [
|
||||
@@ -222,125 +209,9 @@ 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: '' }
|
||||
]
|
||||
} else {
|
||||
this.initData(res.data.result, val, active, show, n)
|
||||
}
|
||||
res.data.result.forEach((t) => {
|
||||
if (t.type === 'bytes' && val === 'Bits/s') {
|
||||
const mpackets = _.cloneDeep(this.mpackets)
|
||||
mpackets[0].analysis = t.totalBitsRate.analysis
|
||||
mpackets[1].analysis = t.inboundBitsRate.analysis
|
||||
mpackets[2].analysis = t.outboundBitsRate.analysis
|
||||
mpackets[3].analysis = t.internalBitsRate.analysis
|
||||
mpackets[4].analysis = t.throughBitsRate.analysis
|
||||
mpackets[5].analysis = t.other.analysis
|
||||
mpackets[0].data = t.totalBitsRate.values ? t.totalBitsRate.values : []
|
||||
mpackets[1].data = t.inboundBitsRate.values ? t.inboundBitsRate.values : []
|
||||
mpackets[2].data = t.outboundBitsRate.values ? t.outboundBitsRate.values : []
|
||||
mpackets[3].data = t.internalBitsRate.values ? t.internalBitsRate.values : []
|
||||
mpackets[4].data = t.throughBitsRate.values ? t.throughBitsRate.values : []
|
||||
mpackets[5].data = t.other.values ? t.other.values : []
|
||||
let num = 0
|
||||
mpackets.forEach(e => {
|
||||
e.unitType = 'bps'
|
||||
if (e.name !== 'network.total' && parseFloat(e.analysis.avg) === 0) {
|
||||
e.show = false
|
||||
num += 1
|
||||
} else {
|
||||
e.show = true
|
||||
if (!active && show !== this.lineRefer) {
|
||||
this.legendSelectChange(e, 'index')
|
||||
}
|
||||
}
|
||||
if (this.lineTab === e.class) {
|
||||
if (parseFloat(e.analysis.avg) <= 0) {
|
||||
this.lineTab = ''
|
||||
this.lineRefer = ''
|
||||
this.init()
|
||||
}
|
||||
}
|
||||
})
|
||||
this.mpackets = mpackets
|
||||
if (num === 5) {
|
||||
mpackets[0].invertTab = false
|
||||
this.lineTab = 'total'
|
||||
this.legendSelectChange(mpackets[0], 0)
|
||||
this.$nextTick(() => {
|
||||
this.echartsInit(this.mpackets, true)
|
||||
})
|
||||
} else {
|
||||
if (n) this.lineTab = ''
|
||||
this.$nextTick(() => {
|
||||
this.echartsInit(this.mpackets, show)
|
||||
if (!this.lineRefer) this.lineRefer = 'Average'
|
||||
})
|
||||
}
|
||||
} else if (t.type === 'packets' && val === 'Packets/s') {
|
||||
const mpackets = _.cloneDeep(this.mpackets)
|
||||
mpackets[0].analysis = t.totalPacketsRate.analysis
|
||||
mpackets[1].analysis = t.inboundPacketsRate.analysis
|
||||
mpackets[2].analysis = t.outboundPacketsRate.analysis
|
||||
mpackets[3].analysis = t.internalPacketsRate.analysis
|
||||
mpackets[4].analysis = t.throughPacketsRate.analysis
|
||||
mpackets[5].analysis = t.other.analysis
|
||||
mpackets[0].data = t.totalPacketsRate.values ? t.totalPacketsRate.values : []
|
||||
mpackets[1].data = t.inboundPacketsRate.values ? t.inboundPacketsRate.values : []
|
||||
mpackets[2].data = t.outboundPacketsRate.values ? t.outboundPacketsRate.values : []
|
||||
mpackets[3].data = t.internalPacketsRate.values ? t.internalPacketsRate.values : []
|
||||
mpackets[4].data = t.throughPacketsRate.values ? t.throughPacketsRate.values : []
|
||||
mpackets[5].data = t.other.values ? t.other.values : []
|
||||
let num = 0
|
||||
mpackets.forEach(e => {
|
||||
e.unitType = 'packets/s'
|
||||
if (e.name !== 'network.total' && parseFloat(e.analysis.avg) === 0) {
|
||||
e.show = false
|
||||
num += 1
|
||||
} else {
|
||||
e.show = true
|
||||
if (!active && show !== this.lineRefer) {
|
||||
this.legendSelectChange(e, 'index')
|
||||
}
|
||||
}
|
||||
if (this.lineTab === e.class) {
|
||||
if (parseFloat(e.analysis.avg) <= 0) {
|
||||
this.lineTab = ''
|
||||
this.lineRefer = ''
|
||||
this.init()
|
||||
}
|
||||
}
|
||||
})
|
||||
this.mpackets = mpackets
|
||||
if (num === 5) {
|
||||
mpackets[0].invertTab = false
|
||||
this.lineTab = 'total'
|
||||
this.legendSelectChange(mpackets[0], 0)
|
||||
this.$nextTick(() => {
|
||||
this.echartsInit(this.mpackets, true)
|
||||
})
|
||||
} else {
|
||||
if (n) this.lineTab = ''
|
||||
this.$nextTick(() => {
|
||||
this.echartsInit(this.mpackets, show)
|
||||
if (!this.lineRefer) this.lineRefer = 'Average'
|
||||
})
|
||||
}
|
||||
} else if (t.type === 'sessions' && val === 'Sessions/s') {
|
||||
const mpackets = _.cloneDeep(this.mpackets)
|
||||
mpackets[0].analysis = t.totalSessionsRate.analysis
|
||||
mpackets[0].data = t.totalSessionsRate.values ? t.totalSessionsRate.values : []
|
||||
mpackets.forEach((e, i) => {
|
||||
if (i !== 0) {
|
||||
e.show = false
|
||||
}
|
||||
e.unitType = 'sessions/s'
|
||||
e.invertTab = false
|
||||
this.lineTab = 'total'
|
||||
this.legendSelectChange(e, 0)
|
||||
})
|
||||
this.mpackets = mpackets
|
||||
this.$nextTick(() => {
|
||||
this.echartsInit(this.mpackets, true)
|
||||
})
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.showError = true
|
||||
this.errorMsg = res.message
|
||||
@@ -377,163 +248,163 @@ export default {
|
||||
}
|
||||
},
|
||||
echartsInit (echartsData, show) {
|
||||
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
|
||||
// !this.myChart && (this.myChart = echarts.init(dom))
|
||||
// 此处为验证是否因dom未销毁,导致图表出错,后续可能会改
|
||||
let dom = null
|
||||
dom = document.getElementById('overviewLineChart')
|
||||
|
||||
this.chartOption = stackedLineChartOption
|
||||
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']),
|
||||
markLine: {
|
||||
silent: true,
|
||||
lineStyle: {
|
||||
color: '#B4B1A8'
|
||||
},
|
||||
symbol: 'none',
|
||||
label: {
|
||||
formatter (params) {
|
||||
const arr = unitConvert(params.value, unitTypes.number).join('')
|
||||
return _this.lineRefer + '(' + arr + echartsData[0].unitType + ')'
|
||||
},
|
||||
position: 'insideStartTop',
|
||||
color: '#717171',
|
||||
fontFamily: 'NotoSansSChineseRegular'
|
||||
}
|
||||
}
|
||||
// echarts内容在单元测试时不执行
|
||||
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)
|
||||
}
|
||||
})
|
||||
if (!show) {
|
||||
this.chartOption.series.forEach((t) => {
|
||||
t.markLine.label.show = false
|
||||
t.markLine = []
|
||||
})
|
||||
}
|
||||
if (this.lineRefer === 'Average' && show) {
|
||||
this.chartOption.series.forEach((t, i) => {
|
||||
t.markLine.label.show = true
|
||||
t.markLine.data = [
|
||||
{
|
||||
yAxis: echartsData[i].analysis.avg
|
||||
}
|
||||
]
|
||||
})
|
||||
} else if (this.lineRefer === '95th Percentile' && show) {
|
||||
this.chartOption.series.forEach((t, i) => {
|
||||
t.markLine.label.show = true
|
||||
t.markLine.data = [
|
||||
{ yAxis: echartsData[i].analysis.p95 }
|
||||
]
|
||||
})
|
||||
} else if (this.lineRefer === 'Maximum' && show) {
|
||||
this.chartOption.series.forEach((t, i) => {
|
||||
t.markLine.label.show = true
|
||||
t.markLine.data = [
|
||||
{ yAxis: echartsData[i].analysis.max }
|
||||
]
|
||||
})
|
||||
}
|
||||
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]
|
||||
}
|
||||
})
|
||||
})
|
||||
return stackedLineTooltipFormatter(params)
|
||||
}
|
||||
this.showMarkLine = true
|
||||
this.$nextTick(() => {
|
||||
this.myChart = echarts.init(dom)
|
||||
this.myChart.setOption(this.chartOption)
|
||||
// 设置参见官网:https://echarts.apache.org/zh/api.html#action.brush.brush
|
||||
this.myChart.dispatchAction({
|
||||
// 刷选模式的开关。使用此 action 可将当前鼠标变为可刷选状态。事实上,点击 toolbox 中的 brush 按钮时,就是通过这个 action,将当前普通鼠标变为刷选器的。
|
||||
type: 'takeGlobalCursor',
|
||||
// 如果想变为“可刷选状态”,必须设置。不设置则会关闭“可刷选状态”。
|
||||
key: 'brush',
|
||||
brushOption: {
|
||||
// 参见 brush 组件的 brushType。如果设置为 false 则关闭“可刷选状态”。
|
||||
brushType: 'lineX',
|
||||
xAxisIndex: 'all',
|
||||
// 单击清除选框
|
||||
brushMode: 'single',
|
||||
// 选择完毕再返回所选数据
|
||||
throttleType: 'debounce'
|
||||
}
|
||||
})
|
||||
|
||||
const self = this
|
||||
|
||||
this.myChart.on('brushEnd', function (params) {
|
||||
self.myChart.dispatchAction({
|
||||
type: 'brush',
|
||||
areas: [] // 删除选框
|
||||
})
|
||||
if (!self.mouseDownFlag) {
|
||||
// 避免点击空白区域报错
|
||||
if (params.areas !== undefined && params.areas.length > 0) {
|
||||
self.brushHistory.unshift({
|
||||
startTime: _.cloneDeep(self.timeFilter.startTime) * 1000,
|
||||
endTime: _.cloneDeep(self.timeFilter.endTime) * 1000
|
||||
})
|
||||
|
||||
const rangeObj = {
|
||||
startTime: Math.ceil(params.areas[0].coordRange[0]),
|
||||
endTime: Math.ceil(params.areas[0].coordRange[1])
|
||||
const _this = this
|
||||
// !this.myChart && (this.myChart = echarts.init(dom))
|
||||
// 此处为验证是否因dom未销毁,导致图表出错,后续可能会改
|
||||
this.chartOption = stackedLineChartOption
|
||||
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
|
||||
}
|
||||
|
||||
// todo 目前暂定框选最小范围为5分钟,后续可能会变动
|
||||
if (rangeObj.endTime - rangeObj.startTime < 5 * 60 * 1000) {
|
||||
rangeObj.startTime = rangeObj.endTime - 5 * 60 * 1000
|
||||
},
|
||||
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']),
|
||||
markLine: {
|
||||
silent: true,
|
||||
lineStyle: {
|
||||
color: '#B4B1A8'
|
||||
},
|
||||
symbol: 'none',
|
||||
label: {
|
||||
formatter (params) {
|
||||
const arr = unitConvert(params.value, unitTypes.number).join('')
|
||||
return _this.lineRefer + '(' + arr + echartsData[0].unitType + ')'
|
||||
},
|
||||
position: 'insideStartTop',
|
||||
color: '#717171',
|
||||
fontFamily: 'NotoSansSChineseRegular'
|
||||
}
|
||||
_this.$store.commit('setRangeEchartsData', rangeObj)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
if (!show) {
|
||||
this.chartOption.series.forEach((t) => {
|
||||
t.markLine.label.show = false
|
||||
t.markLine = []
|
||||
})
|
||||
}
|
||||
if (this.lineRefer === 'Average' && show) {
|
||||
this.chartOption.series.forEach((t, i) => {
|
||||
t.markLine.label.show = true
|
||||
t.markLine.data = [
|
||||
{
|
||||
yAxis: echartsData[i].analysis.avg
|
||||
}
|
||||
]
|
||||
})
|
||||
} else if (this.lineRefer === '95th Percentile' && show) {
|
||||
this.chartOption.series.forEach((t, i) => {
|
||||
t.markLine.label.show = true
|
||||
t.markLine.data = [
|
||||
{ yAxis: echartsData[i].analysis.p95 }
|
||||
]
|
||||
})
|
||||
} else if (this.lineRefer === 'Maximum' && show) {
|
||||
this.chartOption.series.forEach((t, i) => {
|
||||
t.markLine.label.show = true
|
||||
t.markLine.data = [
|
||||
{ yAxis: echartsData[i].analysis.max }
|
||||
]
|
||||
})
|
||||
}
|
||||
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]
|
||||
}
|
||||
})
|
||||
})
|
||||
return stackedLineTooltipFormatter(params)
|
||||
}
|
||||
this.showMarkLine = true
|
||||
this.$nextTick(() => {
|
||||
this.myChart = echarts.init(this.$refs.overviewLineChart)
|
||||
this.myChart.setOption(this.chartOption)
|
||||
// 设置参见官网:https://echarts.apache.org/zh/api.html#action.brush.brush
|
||||
this.myChart.dispatchAction({
|
||||
// 刷选模式的开关。使用此 action 可将当前鼠标变为可刷选状态。事实上,点击 toolbox 中的 brush 按钮时,就是通过这个 action,将当前普通鼠标变为刷选器的。
|
||||
type: 'takeGlobalCursor',
|
||||
// 如果想变为“可刷选状态”,必须设置。不设置则会关闭“可刷选状态”。
|
||||
key: 'brush',
|
||||
brushOption: {
|
||||
// 参见 brush 组件的 brushType。如果设置为 false 则关闭“可刷选状态”。
|
||||
brushType: 'lineX',
|
||||
xAxisIndex: 'all',
|
||||
// 单击清除选框
|
||||
brushMode: 'single',
|
||||
// 选择完毕再返回所选数据
|
||||
throttleType: 'debounce'
|
||||
}
|
||||
})
|
||||
|
||||
const self = this
|
||||
|
||||
this.myChart.on('brushEnd', function (params) {
|
||||
self.myChart.dispatchAction({
|
||||
type: 'brush',
|
||||
areas: [] // 删除选框
|
||||
})
|
||||
if (!self.mouseDownFlag) {
|
||||
// 避免点击空白区域报错
|
||||
if (params.areas !== undefined && params.areas.length > 0) {
|
||||
self.brushHistory.unshift({
|
||||
startTime: _.cloneDeep(self.timeFilter.startTime) * 1000,
|
||||
endTime: _.cloneDeep(self.timeFilter.endTime) * 1000
|
||||
})
|
||||
|
||||
const rangeObj = {
|
||||
startTime: Math.ceil(params.areas[0].coordRange[0]),
|
||||
endTime: Math.ceil(params.areas[0].coordRange[1])
|
||||
}
|
||||
|
||||
// todo 目前暂定框选最小范围为5分钟,后续可能会变动
|
||||
if (rangeObj.endTime - rangeObj.startTime < 5 * 60 * 1000) {
|
||||
rangeObj.startTime = rangeObj.endTime - 5 * 60 * 1000
|
||||
}
|
||||
_this.$store.commit('setRangeEchartsData', rangeObj)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
activeChange (item, index) {
|
||||
if (this.isNoData) return
|
||||
@@ -606,32 +477,34 @@ export default {
|
||||
referenceSelectChange (val) {
|
||||
this.lineRefer = val
|
||||
let echartsData
|
||||
const chartOption = this.myChart.getOption()
|
||||
if (this.lineTab) {
|
||||
echartsData = this.mpackets.filter(t => t.show === true && t.invertTab === false)
|
||||
} else {
|
||||
echartsData = this.mpackets.filter(t => t.show === true)
|
||||
}
|
||||
if (this.lineRefer === 'Average' && this.showMarkLine) {
|
||||
chartOption.series.forEach((t, i) => {
|
||||
if (t.name === echartsData[0].name) {
|
||||
t.markLine.data = [{ yAxis: echartsData[0].analysis.avg }]
|
||||
}
|
||||
})
|
||||
} else if (this.lineRefer === '95th Percentile' && this.showMarkLine) {
|
||||
chartOption.series.forEach((t, i) => {
|
||||
if (t.name === echartsData[0].name) {
|
||||
t.markLine.data = [{ yAxis: echartsData[0].analysis.p95 }]
|
||||
}
|
||||
})
|
||||
} else if (this.lineRefer === 'Maximum' && this.showMarkLine) {
|
||||
chartOption.series.forEach((t, i) => {
|
||||
if (t.name === echartsData[0].name) {
|
||||
t.markLine.data = [{ yAxis: echartsData[0].analysis.max }]
|
||||
}
|
||||
})
|
||||
if (!this.isUnitTesting) {
|
||||
const chartOption = this.myChart.getOption()
|
||||
if (this.lineRefer === 'Average' && this.showMarkLine) {
|
||||
chartOption.series.forEach((t, i) => {
|
||||
if (t.name === echartsData[0].name) {
|
||||
t.markLine.data = [{ yAxis: echartsData[0].analysis.avg }]
|
||||
}
|
||||
})
|
||||
} else if (this.lineRefer === '95th Percentile' && this.showMarkLine) {
|
||||
chartOption.series.forEach((t, i) => {
|
||||
if (t.name === echartsData[0].name) {
|
||||
t.markLine.data = [{ yAxis: echartsData[0].analysis.p95 }]
|
||||
}
|
||||
})
|
||||
} else if (this.lineRefer === 'Maximum' && this.showMarkLine) {
|
||||
chartOption.series.forEach((t, i) => {
|
||||
if (t.name === echartsData[0].name) {
|
||||
t.markLine.data = [{ yAxis: echartsData[0].analysis.max }]
|
||||
}
|
||||
})
|
||||
}
|
||||
this.myChart.setOption(chartOption)
|
||||
}
|
||||
this.myChart.setOption(chartOption)
|
||||
},
|
||||
symbolSizeSortChange (index, time) {
|
||||
const dataIntegrationArray = []
|
||||
@@ -681,6 +554,87 @@ export default {
|
||||
const sortIndex = dataIntegrationArray.findIndex(a => a[2] === index)
|
||||
return this.sizes[sortIndex]
|
||||
},
|
||||
initData (data, val, active, show, n) {
|
||||
let lineData = []
|
||||
if (data !== undefined && data.length > 0) {
|
||||
data.forEach((item) => {
|
||||
item.type = getLineType(item.type)
|
||||
if (item.type === val) {
|
||||
lineData = Object.keys(item).map(t => {
|
||||
return {
|
||||
...item[t]
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
lineData.splice(0, 1)
|
||||
if (val === 'Sessions/s') {
|
||||
const mpackets = _.cloneDeep(this.mpackets)
|
||||
lineData.forEach((d, i) => {
|
||||
mpackets[i].data = d.values
|
||||
mpackets[i].analysis = d.analysis
|
||||
})
|
||||
mpackets.forEach((e, i) => {
|
||||
if (i !== 0) {
|
||||
e.show = false
|
||||
}
|
||||
e.unitType = 'sessions/s'
|
||||
e.invertTab = false
|
||||
this.lineTab = 'total'
|
||||
this.legendSelectChange(e, 0)
|
||||
})
|
||||
this.mpackets = mpackets
|
||||
this.$nextTick(() => {
|
||||
this.echartsInit(this.mpackets, true)
|
||||
})
|
||||
} else {
|
||||
const unit = val === 'Bits/s' ? 'bps' : 'packets/s'
|
||||
this.legendInit(lineData, active, show, unit, n)
|
||||
}
|
||||
},
|
||||
legendInit (data, active, show, type, n) {
|
||||
const mpackets = _.cloneDeep(this.mpackets)
|
||||
data.forEach((d, i) => {
|
||||
mpackets[i].data = d.values
|
||||
mpackets[i].analysis = d.analysis
|
||||
})
|
||||
let num = 0
|
||||
mpackets.forEach(e => {
|
||||
e.unitType = type
|
||||
if (e.name !== 'network.total' && parseFloat(e.analysis.avg) === 0) {
|
||||
e.show = false
|
||||
num += 1
|
||||
} else {
|
||||
e.show = true
|
||||
if (!active && show !== this.lineRefer) {
|
||||
this.legendSelectChange(e, 'index')
|
||||
}
|
||||
}
|
||||
if (this.lineTab === e.class) {
|
||||
if (parseFloat(e.analysis.avg) <= 0) {
|
||||
this.lineTab = ''
|
||||
this.lineRefer = ''
|
||||
this.init()
|
||||
}
|
||||
}
|
||||
})
|
||||
this.mpackets = mpackets
|
||||
if (num === 5) {
|
||||
mpackets[0].invertTab = false
|
||||
this.lineTab = 'total'
|
||||
this.legendSelectChange(mpackets[0], 0)
|
||||
this.$nextTick(() => {
|
||||
this.echartsInit(this.mpackets, true)
|
||||
})
|
||||
} else {
|
||||
if (n) this.lineTab = ''
|
||||
this.$nextTick(() => {
|
||||
this.echartsInit(this.mpackets, show)
|
||||
if (!this.lineRefer) this.lineRefer = 'Average'
|
||||
})
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 鼠标右键返回框选的时间范围
|
||||
*/
|
||||
@@ -702,11 +656,9 @@ export default {
|
||||
this.myChart = null
|
||||
this.chartOption = null
|
||||
this.timer = setTimeout(() => {
|
||||
if (this.lineTab) {
|
||||
if (this.lineTab && this.metric !== 'Sessions/s') {
|
||||
const data = this.mpackets.find(t => t.class === this.lineTab)
|
||||
if (data && data.positioning) {
|
||||
this.activeChange(data, data.positioning)
|
||||
}
|
||||
this.activeChange(data, data.positioning)
|
||||
} else {
|
||||
this.init()
|
||||
}
|
||||
@@ -717,11 +669,13 @@ export default {
|
||||
clearTimeout(this.timer)
|
||||
window.removeEventListener('resize', this.resize)
|
||||
|
||||
let myChart = echarts.getInstanceByDom(document.getElementById('overviewLineChart'))
|
||||
let myChart = echarts.getInstanceByDom(this.$refs.overviewLineChart)
|
||||
if (myChart) {
|
||||
echarts.dispose(myChart)
|
||||
}
|
||||
this.myChart = null
|
||||
if (this.myChart) {
|
||||
echarts.dispose(this.myChart)
|
||||
}
|
||||
// 检测时发现该方法占用较大内存,且未被释放
|
||||
this.unitConvert = null
|
||||
myChart = null
|
||||
|
||||
@@ -61,7 +61,6 @@ export default {
|
||||
methods: {
|
||||
init () {
|
||||
const params = {
|
||||
// startTime: true,
|
||||
startTime: getSecond(this.timeFilter.startTime),
|
||||
endTime: getSecond(this.timeFilter.endTime)
|
||||
}
|
||||
@@ -193,6 +192,14 @@ export default {
|
||||
beforeUnmount () {
|
||||
clearTimeout(this.timer)
|
||||
window.removeEventListener('resize', this.resize)
|
||||
const dom = document.getElementById('chart1')
|
||||
const dom2 = document.getElementById('chart2')
|
||||
if (dom) {
|
||||
echarts.dispose(dom)
|
||||
}
|
||||
if (dom2) {
|
||||
echarts.dispose(dom2)
|
||||
}
|
||||
this.myChart = null
|
||||
this.myChart2 = null
|
||||
}
|
||||
|
||||
@@ -215,8 +215,8 @@ import unitConvert from '@/utils/unit-convert'
|
||||
import { getChainRatio, computeScore, urlParamsHandler, overwriteUrl, readDrilldownTableConfigByUser, combineDrilldownTableWithUserConfig, getDnsMapData, handleSpecialValue, getConfigVersion } from '@/utils/tools'
|
||||
import { getSecond } from '@/utils/date-util'
|
||||
import chartMixin from '@/views/charts2/chart-mixin'
|
||||
import { db } from '@/indexedDB'
|
||||
import _ from 'lodash'
|
||||
import indexedDBUtils from '@/indexedDB'
|
||||
|
||||
export default {
|
||||
name: 'NetworkOverviewTabs',
|
||||
@@ -1729,7 +1729,7 @@ export default {
|
||||
version = await getConfigVersion('default')
|
||||
}
|
||||
// 更新缓存中的配置
|
||||
await db[dbDrilldownTableConfig].put({
|
||||
await indexedDBUtils.selectTable(dbDrilldownTableConfig).put({
|
||||
id: this.userId,
|
||||
version: version,
|
||||
config: this.$_.cloneDeep(curUserConfigGroup)
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
<chart-no-data v-if="isNoData"></chart-no-data>
|
||||
<div class="npm-app-body" v-else>
|
||||
<div class="npm-app-body-patch" v-for="(data, index) in tableData" :key="index">
|
||||
<div class="npm-app-body-icon"><span><i :class="data.icon"></i></span></div>
|
||||
<div class="npm-app-body-color" v-for="(item, index) in 6" :key="index" :class="{'score-color': data.score >= index + 1}"></div>
|
||||
<div class="npm-app-body-icon"><span><i :class="data.icon" :test-id="`iconContent${index}`"></i></span></div>
|
||||
<div class="npm-app-body-color" v-for="index2 in 6" :key="index2" :class="{'score-color': data.score >= index2}"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -48,7 +48,7 @@
|
||||
<div v-else-if="scope.row.bytesRateChainRatio < 0" class="data-total-trend data-total-trend-green">
|
||||
<i class="cn-icon-decline cn-icon"></i>
|
||||
<span v-if="scope.row.bytesRateChainRatio >= -5">
|
||||
{{unitConvert(scope.row.bytesRateChainRatio, unitTypes.percent).join('').replaceAll('-', '')}}
|
||||
{{unitConvert(scope.row.bytesRateChainRatio, unitTypes.percent).join('').replace(/-/g, '')}}
|
||||
</span>
|
||||
<span v-else>>500.00%</span>
|
||||
</div>
|
||||
@@ -71,7 +71,7 @@
|
||||
<div v-else-if="scope.row.outboundBytesRateChainRatio < 0" class="data-total-trend data-total-trend-green">
|
||||
<i class="cn-icon-decline cn-icon"></i>
|
||||
<span v-if="scope.row.outboundBytesRateChainRatio >= -5">
|
||||
{{unitConvert(scope.row.outboundBytesRateChainRatio, unitTypes.percent).join('').replaceAll('-', '')}}
|
||||
{{unitConvert(scope.row.outboundBytesRateChainRatio, unitTypes.percent).join('').replace(/-/g, '')}}
|
||||
</span>
|
||||
<span v-else>>500.00%</span>
|
||||
</div>
|
||||
@@ -86,35 +86,35 @@
|
||||
<div class="data-trend">
|
||||
<div v-if="scope.row.inboundBytesRateChainRatio > 0" class="data-total-trend data-total-trend-red">
|
||||
<i class="cn-icon-rise1 cn-icon"></i>
|
||||
<span v-if="scope.row.inboundBytesRateChainRatio <= 5">
|
||||
<span v-if="scope.row.inboundBytesRateChainRatio <= 5" :test-id="`inbound-${scope.row.appSubcategory}`">
|
||||
{{unitConvert(scope.row.inboundBytesRateChainRatio, unitTypes.percent).join('')}}
|
||||
</span>
|
||||
<span v-else>>500.00%</span>
|
||||
<span v-else :test-id="`inbound-${scope.row.appSubcategory}`">>500.00%</span>
|
||||
</div>
|
||||
<div v-else-if="scope.row.inboundBytesRateChainRatio < 0" class="data-total-trend data-total-trend-green">
|
||||
<i class="cn-icon-decline cn-icon"></i>
|
||||
<span v-if="scope.row.inboundBytesRateChainRatio >= -5">
|
||||
{{unitConvert(scope.row.inboundBytesRateChainRatio, unitTypes.percent).join('').replaceAll('-', '')}}
|
||||
<span v-if="scope.row.inboundBytesRateChainRatio >= -5" :test-id="`inbound-${scope.row.appSubcategory}`">
|
||||
{{unitConvert(scope.row.inboundBytesRateChainRatio, unitTypes.percent).join('').replace(/-/g, '')}}
|
||||
</span>
|
||||
<span v-else>>500.00%</span>
|
||||
<span v-else :test-id="`inbound-${scope.row.appSubcategory}`">>500.00%</span>
|
||||
</div>
|
||||
<div v-else-if="scope.row.inboundBytesRateChainRatio === 0" class="data-total-trend data-total-trend-black">
|
||||
<div v-else-if="scope.row.inboundBytesRateChainRatio === 0" :test-id="`inbound-${scope.row.appSubcategory}`" class="data-total-trend data-total-trend-black">
|
||||
<i class="cn-icon-constant cn-icon"></i>
|
||||
</div>
|
||||
<div v-else></div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="item.prop === 'score'">
|
||||
<div v-if="scope.row.score <= 2" :class="{'data-score-red': scope.row.score <= 2}" class="data-score">
|
||||
<div v-if="scope.row.score <= 2" :test-id="`score-${scope.row.appSubcategory}`" class="data-score data-score-red">
|
||||
{{scope.row.score}}
|
||||
</div>
|
||||
<div v-else-if="scope.row.score <= 4" :class="{'data-score-yellow': scope.row.score <= 4}" class="data-score">
|
||||
<div v-else-if="scope.row.score <= 4" :test-id="`score-${scope.row.appSubcategory}`" class="data-score data-score-yellow">
|
||||
{{scope.row.score}}
|
||||
</div>
|
||||
<div v-else-if="scope.row.score <= 6" :class="{'data-score-green': scope.row.score <= 6}" class="data-score">
|
||||
<div v-else-if="scope.row.score <= 6" :test-id="`score-${scope.row.appSubcategory}`" class="data-score data-score-green">
|
||||
{{scope.row.score}}
|
||||
</div>
|
||||
<div v-else-if="scope.row.score === '-'" class="data-score-no-data">
|
||||
<div v-else-if="scope.row.score === '-'" :test-id="`score-${scope.row.appSubcategory}`" class="data-score-no-data">
|
||||
-
|
||||
</div>
|
||||
</template>
|
||||
@@ -138,17 +138,12 @@ import { unitTypes, npmCategoryInfoMapping, networkTable, operationType, npmCate
|
||||
import unitConvert from '@/utils/unit-convert'
|
||||
import { api } from '@/utils/api'
|
||||
import { getSecond } from '@/utils/date-util'
|
||||
import { get } from '@/utils/http'
|
||||
import {
|
||||
getChainRatio,
|
||||
computeScore,
|
||||
urlParamsHandler,
|
||||
overwriteUrl,
|
||||
getUserDrilldownTableConfig
|
||||
} from '@/utils/tools'
|
||||
import { computeScore, getChainRatio, getUserDrilldownTableConfig, overwriteUrl, urlParamsHandler } from '@/utils/tools'
|
||||
import chartMixin from '@/views/charts2/chart-mixin'
|
||||
import ChartNoData from '@/views/charts/charts/ChartNoData'
|
||||
import ChartError from '@/components/common/Error'
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'NpmAppCategoryScore',
|
||||
data () {
|
||||
@@ -198,15 +193,16 @@ export default {
|
||||
endTime: getSecond(this.timeFilter.endTime)
|
||||
}
|
||||
// 获取table后三列内容
|
||||
const currentTrafficRequest = get(api.npm.overview.appTrafficAnalysis, { ...params, cycle: 0 })
|
||||
const lastCycleTrafficRequest = get(api.npm.overview.appTrafficAnalysis, { ...params, cycle: 1 })
|
||||
const currentTrafficRequest = axios.get(api.npm.overview.appTrafficAnalysis, { params: { ...params, cycle: 0 } })
|
||||
const lastCycleTrafficRequest = axios.get(api.npm.overview.appTrafficAnalysis, { params: { ...params, cycle: 1 } })
|
||||
this.toggleLoading(true)
|
||||
Promise.all([currentTrafficRequest, lastCycleTrafficRequest]).then(res => {
|
||||
if (res[0].code === 200 && res[1].code === 200) {
|
||||
// console.log('打印数据=====', res)
|
||||
if (res[0].data.code === 200 && res[1].data.code === 200) {
|
||||
this.showError = false
|
||||
this.errorMsg = ''
|
||||
const prevData = res[1].data.result
|
||||
const data = res[0].data.result
|
||||
const prevData = res[1].data.data.result
|
||||
const data = res[0].data.data.result
|
||||
if (data && data.length > 0) {
|
||||
this.isNoData = false
|
||||
const tableData = data.map(d => {
|
||||
@@ -228,24 +224,23 @@ export default {
|
||||
return result
|
||||
})
|
||||
// 计算分数
|
||||
const tcpRequest = get(api.npm.overview.appTcpSessionDelay, params)
|
||||
const httpRequest = get(api.npm.overview.appHttpResponseDelay, params)
|
||||
const sslRequest = get(api.npm.overview.appSslConDelay, params)
|
||||
const tcpLostRequest = get(api.npm.overview.appTcpLostlenPercent, params)
|
||||
const packetRetransRequest = get(api.npm.overview.appPacketRetransPercent, params)
|
||||
const tcpRequest = axios.get(api.npm.overview.appTcpSessionDelay, { params: params })
|
||||
const httpRequest = axios.get(api.npm.overview.appHttpResponseDelay, { params: params })
|
||||
const sslRequest = axios.get(api.npm.overview.appSslConDelay, { params: params })
|
||||
const tcpLostRequest = axios.get(api.npm.overview.appTcpLostlenPercent, { params: params })
|
||||
const packetRetransRequest = axios.get(api.npm.overview.appPacketRetransPercent, { params: params })
|
||||
Promise.all([tcpRequest, httpRequest, sslRequest, tcpLostRequest, packetRetransRequest]).then(res => {
|
||||
const keyPre = ['tcp', 'http', 'ssl', 'tcpLost', 'packetRetrans']
|
||||
let msg = ''
|
||||
|
||||
res.forEach((r, i) => {
|
||||
if (r.code === 200) {
|
||||
if (r.data.code === 200) {
|
||||
tableData.forEach(t => {
|
||||
const find = r.data.result.find(d => d.appSubcategory === t.appSubcategory)
|
||||
t[keyPre[i] + 'Score'] = find
|
||||
t[keyPre[i] + 'Score'] = r.data.data.result.find(d => d.appSubcategory === t.appSubcategory)
|
||||
})
|
||||
} else {
|
||||
this.showError = true
|
||||
msg = msg + ',' + r.message
|
||||
msg = msg + ',' + r.data.data.message
|
||||
if (msg.indexOf(',') === 0) {
|
||||
msg = msg.substring(1, msg.length)
|
||||
}
|
||||
@@ -348,7 +343,7 @@ export default {
|
||||
}
|
||||
})
|
||||
let toPanel = null
|
||||
list.forEach((item, index) => {
|
||||
list.forEach(item => {
|
||||
if (item.label === tabType) {
|
||||
item.checked = false
|
||||
toPanel = item.panelId
|
||||
@@ -360,8 +355,7 @@ export default {
|
||||
this.$store.commit('setNetworkOverviewTabList', list)
|
||||
const tabObjGroup = list.filter(item => item.checked)
|
||||
if (tabObjGroup && tabObjGroup.length > 0) {
|
||||
const curTab = tabObjGroup[0]
|
||||
this.urlChangeParams[this.curTabState.curTab] = curTab
|
||||
this.urlChangeParams[this.curTabState.curTab] = tabObjGroup[0]
|
||||
}
|
||||
this.changeUrlTabState()
|
||||
this.$router.push({
|
||||
@@ -384,6 +378,9 @@ export default {
|
||||
},
|
||||
mounted () {
|
||||
this.init()
|
||||
},
|
||||
beforeUnmount () {
|
||||
this.unitConvert = null
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -152,7 +152,9 @@ export default {
|
||||
},
|
||||
beforeUnmount () {
|
||||
window.removeEventListener('resize', this.resize)
|
||||
this.myChart = null
|
||||
if (this.myChart) {
|
||||
echarts.dispose(this.myChart)
|
||||
}
|
||||
this.chartOption = null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,21 +2,21 @@
|
||||
<div class="npm-header">
|
||||
<div class="npm-header-body" v-for="(item, index) in chartData" :key=index>
|
||||
<div class="npm-header-body-severity">
|
||||
<div class="npm-header-body-severity-icon" :class="item.eventSeverity"></div>
|
||||
<div class="npm-header-body-severity-value">{{item.eventSeverity}}</div>
|
||||
<div class="npm-header-body-severity-icon" :class="item.eventSeverity" :test-id="`icon${index}`"></div>
|
||||
<div class="npm-header-body-severity-value" :test-id="`severity${index}`">{{item.eventSeverity}}</div>
|
||||
</div>
|
||||
<chart-error v-if="showError" tooltip :content="errorMsg" />
|
||||
<div v-else class="npm-header-body-total">{{item.count}}</div>
|
||||
<div v-else class="npm-header-body-total" :test-id="`total${index}`">{{item.count}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getSecond } from '@/utils/date-util'
|
||||
import { get } from '@/utils/http'
|
||||
import { api } from '@/utils/api'
|
||||
import chartMixin from '@/views/charts2/chart-mixin'
|
||||
import ChartError from '@/components/common/Error'
|
||||
import axios from 'axios'
|
||||
export default {
|
||||
name: 'NpmEventsHeader',
|
||||
components: { ChartError },
|
||||
@@ -65,12 +65,13 @@ export default {
|
||||
methods: {
|
||||
recentEventsListData () {
|
||||
const params = {
|
||||
startTime: getSecond(this.timeFilter.startTime),
|
||||
endTime: getSecond(this.timeFilter.endTime),
|
||||
startTime: this.timeFilter && this.timeFilter.startTime ? getSecond(this.timeFilter.startTime) : '',
|
||||
endTime: this.timeFilter && this.timeFilter.endTime ? getSecond(this.timeFilter.endTime) : '',
|
||||
type: this.type
|
||||
}
|
||||
this.toggleLoading(true)
|
||||
get(api.npm.events.list, params).then(res => {
|
||||
axios.get(api.npm.events.list, { params: params }).then(res => {
|
||||
res = res.data
|
||||
if (res.code === 200) {
|
||||
this.showError = false
|
||||
if (res.data.result.length === 0) {
|
||||
@@ -96,7 +97,9 @@ export default {
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.recentEventsListData()
|
||||
this.$nextTick(() => {
|
||||
this.recentEventsListData()
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -336,7 +336,9 @@ export default {
|
||||
beforeUnmount () {
|
||||
clearTimeout(this.timer)
|
||||
window.removeEventListener('resize', this.resize)
|
||||
this.myChart = null
|
||||
if (this.myChart) {
|
||||
echarts.dispose(this.myChart)
|
||||
}
|
||||
this.chartOption = null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,60 @@
|
||||
<template>
|
||||
<div class="npm-network-quantity">
|
||||
<single-value
|
||||
v-if="npmNetworkData.length>0"
|
||||
:npm-network-name="npmNetworkName"
|
||||
:npm-network-data="npmNetworkData"
|
||||
></single-value>
|
||||
<div class="single-value" v-for="(npm, index) in newNpmNetworkData" :key="index">
|
||||
<div class="single-value__title" style="display: flex">
|
||||
{{ $t(npmNetworkName[index].name) }}
|
||||
<chart-error v-if="npm.message" tooltip :content="npm.message"></chart-error>
|
||||
</div>
|
||||
|
||||
<div class="single-value__content" >
|
||||
<div class="single-value__content-number" v-if="index ===0 || index ===1 || index ===2" :test-id="`singleValueContent${index}`">
|
||||
{{ unitConvert(npm.Avg, unitTypes.time).join(' ') }}
|
||||
</div>
|
||||
<div class="single-value__content-number" v-else :test-id="`singleValueContent${index}`">
|
||||
{{unitConvert(npm.Avg, unitTypes.percent).join(' ')}}
|
||||
</div>
|
||||
<div v-if="npm.value > 0" class="single-value__content-trend single-value__content-trend-red" >
|
||||
<i class="cn-icon-rise1 cn-icon" :test-id="`singleValueTrendIcon${index}`"></i>
|
||||
<span v-if="npm.value <= 5" :test-id="`singleValueTrendValue${index}`">
|
||||
{{ unitConvert(npm.value, unitTypes.percent).join('') }}
|
||||
</span>
|
||||
<span v-else :test-id="`singleValueTrendValue${index}`">>500.00%</span>
|
||||
</div>
|
||||
<div v-else-if="npm.value < 0" class="single-value__content-trend single-value__content-trend-green" >
|
||||
<i class="cn-icon-decline cn-icon" :test-id="`singleValueTrendIcon${index}`"></i>
|
||||
<span v-if="npm.value >= -5" :test-id="`singleValueTrendValue${index}`">
|
||||
{{ unitConvert(npm.value, unitTypes.percent).join('') }}
|
||||
</span>
|
||||
<span v-else :test-id="`singleValueTrendValue${index}`">>500.00%</span>
|
||||
</div>
|
||||
<div v-else-if="npm.value === 0" class="single-value__content-trend single-value__content-trend-black">
|
||||
<i class="cn-icon-constant cn-icon" :test-id="`singleValueTrendIcon${index}`"></i>
|
||||
</div>
|
||||
<div v-else></div>
|
||||
</div>
|
||||
|
||||
<div class="single-value__circle">
|
||||
<div class="single-value__circle-p95" :test-id="`singleValueP95${index}`">
|
||||
<span v-if="index ===0 || index ===1 || index ===2">
|
||||
P95:{{ unitConvert(npm.P95, unitTypes.time).join(' ') }}</span>
|
||||
<span v-else>
|
||||
P95:{{ unitConvert(npm.P95, unitTypes.percent).join(' ') }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="single-value__circle-p99" :test-id="`singleValueP99${index}`">
|
||||
<span v-if="index ===0 || index ===1 || index ===2">
|
||||
P99:{{ unitConvert(npm.P99, unitTypes.time).join(' ') }}
|
||||
</span>
|
||||
<span v-else>
|
||||
P99:{{ unitConvert(npm.P99, unitTypes.percent).join(' ') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SingleValue from '@/views/charts2/charts/npm/localComponents/SingleValue'
|
||||
import { get } from '@/utils/http'
|
||||
import { getSecond } from '@/utils/date-util'
|
||||
import { api } from '@/utils/api'
|
||||
import chartMixin from '@/views/charts2/chart-mixin'
|
||||
@@ -18,9 +62,11 @@ import _ from 'lodash'
|
||||
import { getChainRatio } from '@/utils/tools'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { ref } from 'vue'
|
||||
import { unitTypes } from '@/utils/constants'
|
||||
import unitConvert from '@/utils/unit-convert'
|
||||
import axios from 'axios'
|
||||
export default {
|
||||
name: 'NpmNetworkQuantity',
|
||||
components: { SingleValue },
|
||||
mixins: [chartMixin],
|
||||
setup () {
|
||||
const { query } = useRoute()
|
||||
@@ -39,6 +85,8 @@ export default {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
unitTypes,
|
||||
unitConvert,
|
||||
npmNetworkName: [
|
||||
{ name: 'networkAppPerformance.tcpConnectionEstablishLatency' },
|
||||
{ name: 'networkAppPerformance.httpResponse' },
|
||||
@@ -48,6 +96,7 @@ export default {
|
||||
],
|
||||
npmNetworkCycleData: [],
|
||||
npmNetworkLastCycleData: [],
|
||||
newNpmNetworkData: [],
|
||||
npmNetworkData: [],
|
||||
side: '',
|
||||
chartData: {},
|
||||
@@ -68,7 +117,7 @@ export default {
|
||||
npmNetworkCycleQuery () {
|
||||
let condition = ''
|
||||
let url = ''
|
||||
if (this.queryCondition.indexOf(' OR ') > -1) {
|
||||
if (this.queryCondition && this.queryCondition.indexOf(' OR ') > -1) {
|
||||
condition = this.queryCondition.split(/["|'](.*?)["|']/)
|
||||
} else {
|
||||
condition = this.queryCondition
|
||||
@@ -84,37 +133,38 @@ export default {
|
||||
} else if (parseFloat(this.tabIndex) === 1) {
|
||||
this.side = 'server'
|
||||
}
|
||||
if (condition && (typeof condition !== 'object') && type) {
|
||||
if (type === 'clientIp' || type === 'serverIp') {
|
||||
if (parseFloat(this.tabIndex) === 0) {
|
||||
if (condition && (typeof condition !== 'object') && type) { // 判断 condition 不为空并且不为对象 type 不为空
|
||||
if (type === 'clientIp' || type === 'serverIp') { // type = clientIp || serverIp
|
||||
if (parseFloat(this.tabIndex) === 0) { // npm 下钻 tabIndex 为 0
|
||||
type = 'clientIp'
|
||||
} else if (parseFloat(this.tabIndex) === 1) {
|
||||
} else if (parseFloat(this.tabIndex) === 1) { // npm 下钻 tabIndex 为 1
|
||||
type = 'serverIp'
|
||||
}
|
||||
params.q = `ip='${condition.split(/'(.*?)'/)[1]}'`
|
||||
params.q = `ip='${condition.split(/'(.*?)'/)[1]}'` // 拼接字段作为参数
|
||||
} else if (type === 'clientCity') {
|
||||
params.q = `client_city='${condition.split(/'(.*?)'/)[1]}'`
|
||||
params.q = `client_city='${condition.split(/'(.*?)'/)[1]}'` // 拼接字段作为参数
|
||||
} else if (type === 'serverCity') {
|
||||
params.q = `server_city='${condition.split(/'(.*?)'/)[1]}'`
|
||||
params.q = `server_city='${condition.split(/'(.*?)'/)[1]}'` // 拼接字段作为参数
|
||||
} else {
|
||||
params.q = condition
|
||||
params.q = condition // 默认参数
|
||||
}
|
||||
params.type = type
|
||||
} else if (condition.length > 1 && type && type === 'ip') {
|
||||
params.q = `${type}='${condition[1]}' and side='${this.side}'`
|
||||
} else if (condition.length > 1 && type && type === 'ip') { // condition 为数组时数组长度不为 0 | type 不为空 | type为ip
|
||||
params.q = `${type}='${condition[1]}' and side='${this.side}'` // 拼接字段作为参数
|
||||
params.type = type
|
||||
} else if (condition.length > 1 && type && type !== 'ip') {
|
||||
if (type === 'country' || type === 'asn' || type === 'province' || type === 'city' || type === 'isp') {
|
||||
params.q = `${type}='${condition[1]}'`
|
||||
} else if (condition.length > 1 && type && type !== 'ip') { // condition 为数组时数组长度不为 0 | type 不为空 | type不为ip
|
||||
if (type === 'country' || type === 'asn' || type === 'province' || type === 'city' || type === 'isp') { // 根据接口所需,调整参数
|
||||
params.q = `${type}='${condition[1]}'` // 拼接字段作为参数
|
||||
params.type = type
|
||||
} else if (type === 'idcRenter') {
|
||||
params.q = `idc_renter='${condition[1]}'`
|
||||
params.q = `idc_renter='${condition[1]}'` // 拼接字段作为参数
|
||||
params.type = type
|
||||
} else {
|
||||
params.q = `${condition[0]}'${condition[1]}'`
|
||||
params.q = `${condition[0]}'${condition[1]}'` // 拼接字段作为参数
|
||||
params.type = type
|
||||
}
|
||||
}
|
||||
// 区分 3 级菜单和 2 级菜单使用不同的 url
|
||||
if (parseFloat(this.tabOperationType) === 3) {
|
||||
url = api.npm.overview.allNetworkAnalysis
|
||||
} else {
|
||||
@@ -123,7 +173,8 @@ export default {
|
||||
if ((type && condition) || type) {
|
||||
params.type = params.type || type
|
||||
this.toggleLoading(true)
|
||||
get(url, params).then(res => {
|
||||
axios.get(url, { params: params }).then(res => {
|
||||
res = res.data
|
||||
if (res.code === 200) {
|
||||
this.npmNetworkCycleData = res.data.result
|
||||
}
|
||||
@@ -133,21 +184,21 @@ export default {
|
||||
this.toggleLoading(false)
|
||||
})
|
||||
} else {
|
||||
const tcp = get(api.npm.overview.tcpSessionDelay, params)
|
||||
const http = get(api.npm.overview.httpResponseDelay, params)
|
||||
const ssl = get(api.npm.overview.sslConDelay, params)
|
||||
const tcpPercent = get(api.npm.overview.tcpLostlenPercent, params)
|
||||
const packetPercent = get(api.npm.overview.packetRetransPercent, params)
|
||||
const tcp = axios.get(api.npm.overview.tcpSessionDelay, { params: params })
|
||||
const http = axios.get(api.npm.overview.httpResponseDelay, { params: params })
|
||||
const ssl = axios.get(api.npm.overview.sslConDelay, { params: params })
|
||||
const tcpPercent = axios.get(api.npm.overview.tcpLostlenPercent, { params: params })
|
||||
const packetPercent = axios.get(api.npm.overview.packetRetransPercent, { params: params })
|
||||
this.toggleLoading(true)
|
||||
Promise.all([tcp, http, ssl, tcpPercent, packetPercent]).then(res => {
|
||||
// 状态为200的,赋值接口数据,不为200的传入报错提示message,
|
||||
// 传给子组件SingleValue,再进行error处理,注:error处理不在此处处理
|
||||
this.npmNetworkCycleData = []
|
||||
res.forEach(t => {
|
||||
if (t.code === 200) {
|
||||
this.npmNetworkCycleData.push(t.data.result)
|
||||
if (t.data.code === 200) {
|
||||
this.npmNetworkCycleData.push(t.data.data.result)
|
||||
} else {
|
||||
this.npmNetworkCycleData.push(t)
|
||||
this.npmNetworkCycleData.push(t.data)
|
||||
}
|
||||
})
|
||||
this.npmNetworkLastCycleQuery()
|
||||
@@ -177,7 +228,8 @@ export default {
|
||||
if ((params.type && params.q) || (param && param.type)) {
|
||||
params.type = params.type || param.type
|
||||
this.toggleLoading(true)
|
||||
get(url, params).then(res => {
|
||||
axios.get(url, { params: params }).then(res => {
|
||||
res = res.data
|
||||
if (res.code === 200) {
|
||||
this.npmNetworkLastCycleData = res.data.result
|
||||
} else {
|
||||
@@ -195,20 +247,20 @@ export default {
|
||||
this.toggleLoading(false)
|
||||
})
|
||||
} else {
|
||||
const tcp = get(api.npm.overview.tcpSessionDelay, params)
|
||||
const http = get(api.npm.overview.httpResponseDelay, params)
|
||||
const ssl = get(api.npm.overview.sslConDelay, params)
|
||||
const tcpPercent = get(api.npm.overview.tcpLostlenPercent, params)
|
||||
const packetPercent = get(api.npm.overview.packetRetransPercent, params)
|
||||
const tcp = axios.get(api.npm.overview.tcpSessionDelay, { params: params })
|
||||
const http = axios.get(api.npm.overview.httpResponseDelay, { params: params })
|
||||
const ssl = axios.get(api.npm.overview.sslConDelay, { params: params })
|
||||
const tcpPercent = axios.get(api.npm.overview.tcpLostlenPercent, { params: params })
|
||||
const packetPercent = axios.get(api.npm.overview.packetRetransPercent, { params: params })
|
||||
this.toggleLoading(true)
|
||||
Promise.all([tcp, http, ssl, tcpPercent, packetPercent]).then(res => {
|
||||
// 状态为200的,赋值接口数据,不为200的保留报错提示message,
|
||||
// 传给子组件SingleValue,再进行error处理,注:error处理不在此处处理
|
||||
res.forEach(t => {
|
||||
if (t.code === 200) {
|
||||
this.npmNetworkLastCycleData.push(t.data.result)
|
||||
if (t.data.code === 200) {
|
||||
this.npmNetworkLastCycleData.push(t.data.data.result)
|
||||
} else {
|
||||
this.npmNetworkLastCycleData.push(t)
|
||||
this.npmNetworkLastCycleData.push(t.data)
|
||||
}
|
||||
this.npmNetworkQuantity(this.npmNetworkCycleData, this.npmNetworkLastCycleData, 1)
|
||||
})
|
||||
@@ -271,6 +323,39 @@ export default {
|
||||
})
|
||||
this.npmNetworkData = cycle
|
||||
}
|
||||
this.initData(this.npmNetworkData)
|
||||
},
|
||||
initData (data) {
|
||||
// 处理数据后的数组
|
||||
const dealList = []
|
||||
|
||||
if (data !== undefined && data.length > 0) {
|
||||
data.forEach((item) => {
|
||||
const tempObj = {}
|
||||
for (const i in item) {
|
||||
if (item.msg || item.message) {
|
||||
// 为了兼容字段为msg的情况
|
||||
tempObj.message = item.msg ? item.msg : item.message
|
||||
} else {
|
||||
// 将含有avg、p90等关键字使用avg、p90来代替,形成统一属性
|
||||
if (i.indexOf('Avg') > -1) {
|
||||
tempObj.Avg = item[i]
|
||||
} else if (i.indexOf('P50') > -1) {
|
||||
tempObj.P50 = item[i]
|
||||
} else if (i.indexOf('P90') > -1) {
|
||||
tempObj.P90 = item[i]
|
||||
} else if (i.indexOf('P95') > -1) {
|
||||
tempObj.P95 = item[i]
|
||||
} else if (i.indexOf('P99') > -1) {
|
||||
tempObj.P99 = item[i]
|
||||
}
|
||||
tempObj.value = item.value
|
||||
}
|
||||
}
|
||||
dealList.push(tempObj)
|
||||
})
|
||||
this.newNpmNetworkData = dealList
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
@@ -282,6 +367,7 @@ export default {
|
||||
beforeUnmount () {
|
||||
clearTimeout(this.timer1)
|
||||
clearTimeout(this.timer2)
|
||||
this.unitConvert = null
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -21,15 +21,15 @@
|
||||
<template #default="scope" :column="item">
|
||||
<div class="data-recent-table">
|
||||
<template v-if="item.prop === 'eventSeverity'">
|
||||
<span class="data-recent-table-severity" :class="scope.row[item.prop]">{{scope.row[item.prop]}}</span>
|
||||
<span class="data-recent-table-severity" :class="scope.row[item.prop]" :test-id="`eventSeverity-${scope.row.eventSeverity}-${scope.$index}`">{{scope.row[item.prop]}}</span>
|
||||
</template>
|
||||
<template v-else-if="item.prop === 'eventKey'">
|
||||
<span class="data-recent-table-entity click-active" @click="jumpPage(scope.row)">{{splitEventKey(scope.row[item.prop])}}</span>
|
||||
<span class="data-recent-table-entity click-active" @click="jumpPage(scope.row)" :test-id="`eventKey-${splitEventKey(scope.row.eventKey)}-${scope.$index}`">{{splitEventKey(scope.row[item.prop])}}</span>
|
||||
</template>
|
||||
<template v-else-if="item.prop === 'eventType'">
|
||||
<span class="data-recent-table-eventType">{{scope.row[item.prop]}}</span>
|
||||
<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]">{{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>
|
||||
@@ -48,13 +48,13 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { get } from '@/utils/http'
|
||||
import { api } from '@/utils/api'
|
||||
import { getSecond, dateFormatByAppearance } from '@/utils/date-util'
|
||||
import chartMixin from '@/views/charts2/chart-mixin'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { ref } from 'vue'
|
||||
import ChartError from '@/components/common/Error'
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'NpmRecentEvents',
|
||||
@@ -99,7 +99,7 @@ export default {
|
||||
endTime: getSecond(this.timeFilter.endTime),
|
||||
limit: 8
|
||||
}
|
||||
if (condition.length > 1 && this.dimensionType) {
|
||||
if (condition && condition.length > 1 && this.dimensionType) {
|
||||
params.param = condition[1]
|
||||
params.type = this.dimensionType
|
||||
if (params.type === 'serverIp' || params.type === 'clientIp') params.type = 'ip'
|
||||
@@ -114,7 +114,8 @@ export default {
|
||||
url = api.npm.events.recentEvents
|
||||
}
|
||||
this.toggleLoading(true)
|
||||
get(url, params).then(res => {
|
||||
axios.get(url, { params: params }).then(res => {
|
||||
res = res.data
|
||||
if (res.code === 200) {
|
||||
this.showError = false
|
||||
this.isNoData = res.data.result.length === 0
|
||||
@@ -151,6 +152,7 @@ export default {
|
||||
return name
|
||||
},
|
||||
jumpPage (item) {
|
||||
this.beforeRouterPush()
|
||||
this.$router.push({
|
||||
path: '/detection/performanceEvent',
|
||||
query: {
|
||||
@@ -158,6 +160,36 @@ export default {
|
||||
eventId: item.eventId
|
||||
}
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 在路由跳转前,即下钻前将路由数据保存起来,确保回退和前进保留当时状态
|
||||
*/
|
||||
beforeRouterPush () {
|
||||
const currentRouter = this.$_.cloneDeep(this.$route.query)
|
||||
const historyList = this.$_.cloneDeep(this.$store.getters.getRouterHistoryList)
|
||||
|
||||
const tempObj = {
|
||||
t: currentRouter.t,
|
||||
query: currentRouter,
|
||||
path: this.$_.cloneDeep(this.$route.path),
|
||||
params: this.$_.cloneDeep(this.$route.params)
|
||||
}
|
||||
if (historyList.length > 0) {
|
||||
let flag = true
|
||||
historyList.forEach((item, index) => {
|
||||
if (item.t === currentRouter.t) {
|
||||
historyList[index] = tempObj
|
||||
flag = false
|
||||
}
|
||||
if (!flag) {
|
||||
return true
|
||||
}
|
||||
})
|
||||
if (flag) historyList.push(tempObj)
|
||||
} else {
|
||||
historyList.push(tempObj)
|
||||
}
|
||||
this.$store.commit('setRouterHistoryList', historyList)
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
|
||||
@@ -22,7 +22,6 @@ import { get } from '@/utils/http'
|
||||
import { api } from '@/utils/api'
|
||||
import { drillDownPanelTypeMapping } from '@/utils/constants'
|
||||
import { overwriteUrl, urlParamsHandler } from '@/utils/tools'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { ref } from 'vue'
|
||||
export default {
|
||||
name: 'NpmTabs',
|
||||
|
||||
@@ -42,7 +42,7 @@ import ChartNoData from '@/views/charts/charts/ChartNoData'
|
||||
import _ from 'lodash'
|
||||
import chartMixin from '@/views/charts2/chart-mixin'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { overwriteUrl, urlParamsHandler } from '@/utils/tools'
|
||||
import { getLineType, getLineIndexUnit, overwriteUrl, urlParamsHandler } from '@/utils/tools'
|
||||
import ChartError from '@/components/common/Error'
|
||||
|
||||
export default {
|
||||
@@ -80,11 +80,11 @@ export default {
|
||||
{ name: this.$t('network.other'), show: true, positioning: 5, data: [], unitType: 'number' }
|
||||
],
|
||||
npmQuantity: [
|
||||
{ name: this.$t('networkAppPerformance.tcpConnectionEstablishLatency'), show: true, positioning: 0, data: [], unitType: unitTypes.time },
|
||||
{ name: this.$t('networkAppPerformance.httpResponse'), show: true, positioning: 0, data: [], unitType: unitTypes.time },
|
||||
{ name: this.$t('networkAppPerformance.sslResponseLatency'), show: true, positioning: 0, data: [], unitType: unitTypes.time },
|
||||
{ name: this.$t('networkAppPerformance.packetLoss'), show: true, positioning: 0, data: [], unitType: unitTypes.percent },
|
||||
{ name: this.$t('overall.packetRetrans'), show: true, positioning: 0, data: [], unitType: unitTypes.percent }
|
||||
{ name: this.$t('networkAppPerformance.tcpConnectionEstablishLatency'), show: true, positioning: 0, data: [], unitType: unitTypes.time, index: 0 },
|
||||
{ name: this.$t('networkAppPerformance.httpResponse'), show: true, positioning: 0, data: [], unitType: unitTypes.time, index: 1 },
|
||||
{ name: this.$t('networkAppPerformance.sslResponseLatency'), show: true, positioning: 0, data: [], unitType: unitTypes.time, index: 2 },
|
||||
{ name: this.$t('networkAppPerformance.packetLoss'), show: true, positioning: 0, data: [], unitType: unitTypes.percent, index: 3 },
|
||||
{ name: this.$t('overall.packetRetrans'), show: true, positioning: 0, data: [], unitType: unitTypes.percent, index: 4 }
|
||||
],
|
||||
chartData: {},
|
||||
metricOptions: [
|
||||
@@ -144,7 +144,6 @@ export default {
|
||||
if (!val) {
|
||||
val = this.metricFilter
|
||||
}
|
||||
// const conditionStr = this.$route.query.queryCondition ? this.$route.query.queryCondition : ''
|
||||
let condition = ''
|
||||
let type = this.dimensionType
|
||||
if (this.queryCondition.indexOf(' OR ') > -1) {
|
||||
@@ -209,92 +208,15 @@ export default {
|
||||
{ name: this.$t('network.other'), show: true, positioning: 5, data: [], unitType: 'number' }
|
||||
]
|
||||
this.npmQuantity = [
|
||||
{ name: this.$t('networkAppPerformance.tcpConnectionEstablishLatency'), show: true, positioning: 0, data: [], unitType: unitTypes.time },
|
||||
{ name: this.$t('networkAppPerformance.httpResponse'), show: true, positioning: 0, data: [], unitType: unitTypes.time },
|
||||
{ name: this.$t('networkAppPerformance.sslResponseLatency'), show: true, positioning: 0, data: [], unitType: unitTypes.time },
|
||||
{ name: this.$t('networkAppPerformance.packetLoss'), show: true, positioning: 0, data: [], unitType: unitTypes.percent },
|
||||
{ name: this.$t('overall.packetRetrans'), show: true, positioning: 0, data: [], unitType: unitTypes.percent }
|
||||
{ name: this.$t('networkAppPerformance.tcpConnectionEstablishLatency'), show: true, positioning: 0, data: [], unitType: unitTypes.time, index: 0 },
|
||||
{ name: this.$t('networkAppPerformance.httpResponse'), show: true, positioning: 0, data: [], unitType: unitTypes.time, index: 1 },
|
||||
{ name: this.$t('networkAppPerformance.sslResponseLatency'), show: true, positioning: 0, data: [], unitType: unitTypes.time, index: 2 },
|
||||
{ name: this.$t('networkAppPerformance.packetLoss'), show: true, positioning: 0, data: [], unitType: unitTypes.percent, index: 3 },
|
||||
{ name: this.$t('overall.packetRetrans'), show: true, positioning: 0, data: [], unitType: unitTypes.percent, index: 4 }
|
||||
]
|
||||
} else {
|
||||
this.initData(res.data.result, val)
|
||||
}
|
||||
res.data.result.forEach((t) => {
|
||||
if (t.type === 'bytes' && val === 'Bits/s') {
|
||||
const mpackets = _.cloneDeep(this.mpackets)
|
||||
mpackets[0].data = t.totalBitsRate.values ? t.totalBitsRate.values : []
|
||||
mpackets[1].data = t.inboundBitsRate.values ? t.inboundBitsRate.values : []
|
||||
mpackets[2].data = t.outboundBitsRate.values ? t.outboundBitsRate.values : []
|
||||
mpackets[3].data = t.internalBitsRate.values ? t.internalBitsRate.values : []
|
||||
mpackets[4].data = t.throughBitsRate.values ? t.throughBitsRate.values : []
|
||||
mpackets[5].data = t.other.values ? t.other.values : []
|
||||
mpackets.forEach((e) => {
|
||||
e.show = true
|
||||
})
|
||||
this.mpackets = mpackets
|
||||
this.echartsInit(this.mpackets)
|
||||
} else if (t.type === 'packets' && val === 'Packets/s') {
|
||||
const mpackets = _.cloneDeep(this.mpackets)
|
||||
mpackets[0].data = t.totalPacketsRate.values ? t.totalPacketsRate.values : []
|
||||
mpackets[1].data = t.inboundPacketsRate.values ? t.inboundPacketsRate.values : []
|
||||
mpackets[2].data = t.outboundPacketsRate.values ? t.outboundPacketsRate.values : []
|
||||
mpackets[3].data = t.internalPacketsRate.values ? t.internalPacketsRate.values : []
|
||||
mpackets[4].data = t.throughPacketsRate.values ? t.throughPacketsRate.values : []
|
||||
mpackets[5].data = t.other.values ? t.other.values : []
|
||||
mpackets.forEach((e) => {
|
||||
e.show = true
|
||||
})
|
||||
this.mpackets = mpackets
|
||||
this.echartsInit(this.mpackets)
|
||||
} else if (t.type === 'sessions' && val === 'Sessions/s') {
|
||||
const mpackets = _.cloneDeep(this.mpackets)
|
||||
mpackets[0].data = t.totalSessionsRate.values ? t.totalSessionsRate.values : []
|
||||
mpackets.forEach((e, i) => {
|
||||
if (i !== 0) {
|
||||
e.show = false
|
||||
}
|
||||
})
|
||||
this.mpackets = mpackets
|
||||
this.echartsInit(this.mpackets)
|
||||
} else if (t.type === 'establishLatencyMs' && val === 'establishLatencyMs') {
|
||||
const npmQuantity = _.cloneDeep(this.npmQuantity)
|
||||
npmQuantity[0].data = t.establishLatencyMsAvg.values ? t.establishLatencyMsAvg.values : []
|
||||
npmQuantity.forEach((e, i) => {
|
||||
e.show = i === 0
|
||||
})
|
||||
this.npmQuantity = npmQuantity
|
||||
this.echartsInit(this.npmQuantity, '(ms)')
|
||||
} else if (t.type === 'httpResponseLatency' && val === 'httpResponseLatency') {
|
||||
const npmQuantity = _.cloneDeep(this.npmQuantity)
|
||||
npmQuantity[1].data = t.httpResponseLatencyAvg.values ? t.httpResponseLatencyAvg.values : []
|
||||
npmQuantity.forEach((e, i) => {
|
||||
e.show = i === 1
|
||||
})
|
||||
this.npmQuantity = npmQuantity
|
||||
this.echartsInit(this.npmQuantity, '(ms)')
|
||||
} else if (t.type === 'sslConLatency' && val === 'sslConLatency') {
|
||||
const npmQuantity = _.cloneDeep(this.npmQuantity)
|
||||
npmQuantity[2].data = t.sslConLatencyAvg.values ? t.sslConLatencyAvg.values : []
|
||||
npmQuantity.forEach((e, i) => {
|
||||
e.show = i === 2
|
||||
})
|
||||
this.npmQuantity = npmQuantity
|
||||
this.echartsInit(this.npmQuantity, '(ms)')
|
||||
} else if (t.type === 'tcpLostlenPercent' && val === 'tcpLostlenPercent') {
|
||||
const npmQuantity = _.cloneDeep(this.npmQuantity)
|
||||
npmQuantity[3].data = t.tcpLostlenPercentAvg.values ? t.tcpLostlenPercentAvg.values : []
|
||||
npmQuantity.forEach((e, i) => {
|
||||
e.show = i === 3
|
||||
})
|
||||
this.npmQuantity = npmQuantity
|
||||
this.echartsInit(this.npmQuantity, '(%)')
|
||||
} else if (t.type === 'pktRetransPercent' && val === 'pktRetransPercent') {
|
||||
const npmQuantity = _.cloneDeep(this.npmQuantity)
|
||||
npmQuantity[4].data = t.pktRetransPercentAvg.values ? t.pktRetransPercentAvg.values : []
|
||||
npmQuantity.forEach((e, i) => {
|
||||
e.show = i === 4
|
||||
})
|
||||
this.npmQuantity = npmQuantity
|
||||
this.echartsInit(this.npmQuantity, '(%)')
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.isNoData = false
|
||||
this.showError = true
|
||||
@@ -308,204 +230,50 @@ export default {
|
||||
this.toggleLoading(false)
|
||||
})
|
||||
} else {
|
||||
if (val === 'Bits/s' || val === 'Packets/s' || val === 'Sessions/s') {
|
||||
this.toggleLoading(true)
|
||||
get(api.npm.overview.totalTrafficAnalysis, params).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.showError = false
|
||||
this.isNoData = res.data.result.length === 0
|
||||
if (this.isNoData) {
|
||||
this.mpackets = [
|
||||
{ name: 'network.total', show: true, positioning: 0, data: [], unitType: 'number' },
|
||||
{ name: 'network.inbound', show: true, positioning: 1, data: [], unitType: 'number' },
|
||||
{ name: 'network.outbound', show: true, positioning: 2, data: [], unitType: 'number' },
|
||||
{ name: 'network.internal', show: true, positioning: 3, data: [], unitType: 'number' },
|
||||
{ name: 'network.through', show: true, positioning: 4, data: [], unitType: 'number' },
|
||||
{ name: 'network.other', show: true, positioning: 5, data: [], unitType: 'number' }
|
||||
]
|
||||
}
|
||||
res.data.result.forEach((t) => {
|
||||
if (t.type === 'bytes' && val === 'Bits/s') {
|
||||
const mpackets = _.cloneDeep(this.mpackets)
|
||||
mpackets[0].data = t.totalBitsRate.values ? t.totalBitsRate.values : []
|
||||
mpackets[1].data = t.inboundBitsRate.values ? t.inboundBitsRate.values : []
|
||||
mpackets[2].data = t.outboundBitsRate.values ? t.outboundBitsRate.values : []
|
||||
mpackets[3].data = t.internalBitsRate.values ? t.internalBitsRate.values : []
|
||||
mpackets[4].data = t.throughBitsRate.values ? t.throughBitsRate.values : []
|
||||
mpackets[5].data = t.other.values ? t.other.values : []
|
||||
mpackets.forEach((e) => {
|
||||
e.show = true
|
||||
})
|
||||
this.mpackets = mpackets
|
||||
this.echartsInit(this.mpackets)
|
||||
} else if (t.type === 'packets' && val === 'Packets/s') {
|
||||
const mpackets = _.cloneDeep(this.mpackets)
|
||||
mpackets[0].data = t.totalPacketsRate.values ? t.totalPacketsRate.values : []
|
||||
mpackets[1].data = t.inboundPacketsRate.values ? t.inboundPacketsRate.values : []
|
||||
mpackets[2].data = t.outboundPacketsRate.values ? t.outboundPacketsRate.values : []
|
||||
mpackets[3].data = t.internalPacketsRate.values ? t.internalPacketsRate.values : []
|
||||
mpackets[4].data = t.throughPacketsRate.values ? t.throughPacketsRate.values : []
|
||||
mpackets[5].data = t.other.values ? t.other.values : []
|
||||
mpackets.forEach((e) => {
|
||||
e.show = true
|
||||
})
|
||||
this.mpackets = mpackets
|
||||
this.echartsInit(this.mpackets)
|
||||
} else if (t.type === 'sessions' && val === 'Sessions/s') {
|
||||
const mpackets = _.cloneDeep(this.mpackets)
|
||||
mpackets[0].data = t.totalSessionsRate.values ? t.totalSessionsRate.values : []
|
||||
mpackets.forEach((e, i) => {
|
||||
if (i !== 0) {
|
||||
e.show = false
|
||||
}
|
||||
})
|
||||
this.mpackets = mpackets
|
||||
this.echartsInit(this.mpackets)
|
||||
}
|
||||
})
|
||||
this.toggleLoading(true)
|
||||
const totalTrafficAnalysis = get(api.npm.overview.totalTrafficAnalysis, params)
|
||||
const totalNetworkAnalysis = get(api.npm.overview.totalNetworkAnalysis, params)
|
||||
const totalHttpResponseDelay = get(api.npm.overview.totalHttpResponseDelay, params)
|
||||
const totalSslConDelay = get(api.npm.overview.totalSslConDelay, params)
|
||||
const npmLineData = []
|
||||
Promise.all([totalNetworkAnalysis, totalTrafficAnalysis, totalHttpResponseDelay, totalSslConDelay]).then(res => {
|
||||
res.forEach(item => {
|
||||
if (item.code === 200) {
|
||||
npmLineData.push(...item.data.result)
|
||||
} else {
|
||||
this.isNoData = false
|
||||
this.showError = true
|
||||
this.errorMsg = res.message
|
||||
}
|
||||
}).catch(e => {
|
||||
this.isNoData = false
|
||||
this.showError = true
|
||||
this.errorMsg = e.message
|
||||
}).finally(() => {
|
||||
this.toggleLoading(false)
|
||||
})
|
||||
} else if (val === 'establishLatencyMs' || val === 'tcpLostlenPercent' || val === 'pktRetransPercent') {
|
||||
this.toggleLoading(true)
|
||||
get(api.npm.overview.totalNetworkAnalysis, params).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.showError = false
|
||||
this.isNoData = res.data.result.length === 0
|
||||
if (this.isNoData) {
|
||||
this.npmQuantity = [
|
||||
{ name: 'networkAppPerformance.tcpConnectionEstablishLatency', show: true, positioning: 0, data: [], unitType: unitTypes.time },
|
||||
{ name: 'networkAppPerformance.httpResponse', show: true, positioning: 0, data: [], unitType: unitTypes.time },
|
||||
{ name: 'networkAppPerformance.sslResponseLatency', show: true, positioning: 0, data: [], unitType: unitTypes.time },
|
||||
{ name: 'networkAppPerformance.packetLoss', show: true, positioning: 0, data: [], unitType: unitTypes.percent },
|
||||
{ name: 'overall.packetRetrans', show: true, positioning: 0, data: [], unitType: unitTypes.percent }
|
||||
]
|
||||
}
|
||||
res.data.result.forEach((t) => {
|
||||
if (t.type === 'establishLatencyMs' && val === 'establishLatencyMs') {
|
||||
const npmQuantity = _.cloneDeep(this.npmQuantity)
|
||||
npmQuantity[0].data = t.establishLatencyMs.values ? t.establishLatencyMs.values : []
|
||||
npmQuantity.forEach((e, i) => {
|
||||
e.show = i === 0
|
||||
})
|
||||
this.npmQuantity = npmQuantity
|
||||
this.echartsInit(this.npmQuantity, '(ms)')
|
||||
} else if (t.type === 'tcpLostlenPercent' && val === 'tcpLostlenPercent') {
|
||||
const npmQuantity = _.cloneDeep(this.npmQuantity)
|
||||
npmQuantity[3].data = t.tcpLostlenPercent.values ? t.tcpLostlenPercent.values : []
|
||||
npmQuantity.forEach((e, i) => {
|
||||
e.show = i === 3
|
||||
})
|
||||
this.npmQuantity = npmQuantity
|
||||
this.echartsInit(this.npmQuantity, '(%)')
|
||||
} else if (t.type === 'pktRetransPercent' && val === 'pktRetransPercent') {
|
||||
const npmQuantity = _.cloneDeep(this.npmQuantity)
|
||||
npmQuantity[4].data = t.pktRetransPercent.values ? t.pktRetransPercent.values : []
|
||||
npmQuantity.forEach((e, i) => {
|
||||
e.show = i === 4
|
||||
})
|
||||
this.npmQuantity = npmQuantity
|
||||
this.echartsInit(this.npmQuantity, '(%)')
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.isNoData = false
|
||||
this.showError = true
|
||||
this.errorMsg = res.message
|
||||
}
|
||||
}).catch(e => {
|
||||
this.isNoData = false
|
||||
this.showError = true
|
||||
this.errorMsg = e.message
|
||||
}).finally(() => {
|
||||
this.toggleLoading(false)
|
||||
})
|
||||
} else if (val === 'httpResponseLatency') {
|
||||
this.toggleLoading(true)
|
||||
get(api.npm.overview.totalHttpResponseDelay, params).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.showError = false
|
||||
this.isNoData = res.data.result.length === 0
|
||||
if (this.isNoData) {
|
||||
this.npmQuantity = [
|
||||
{ name: 'networkAppPerformance.tcpConnectionEstablishLatency', show: true, positioning: 0, data: [], unitType: unitTypes.time },
|
||||
{ name: 'networkAppPerformance.httpResponse', show: true, positioning: 0, data: [], unitType: unitTypes.time },
|
||||
{ name: 'networkAppPerformance.sslResponseLatency', show: true, positioning: 0, data: [], unitType: unitTypes.time },
|
||||
{ name: 'networkAppPerformance.packetLoss', show: true, positioning: 0, data: [], unitType: unitTypes.percent },
|
||||
{ name: 'overall.packetRetrans', show: true, positioning: 0, data: [], unitType: unitTypes.percent }
|
||||
]
|
||||
}
|
||||
res.data.result.forEach(t => {
|
||||
if (t.type === 'httpResponseLatency' && val === 'httpResponseLatency') {
|
||||
const npmQuantity = _.cloneDeep(this.npmQuantity)
|
||||
npmQuantity[1].data = t.httpResponseLatency.values ? t.httpResponseLatency.values : []
|
||||
npmQuantity.forEach((e, i) => {
|
||||
e.show = i === 1
|
||||
})
|
||||
this.npmQuantity = npmQuantity
|
||||
this.echartsInit(this.npmQuantity, '(ms)')
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.isNoData = false
|
||||
this.showError = true
|
||||
this.errorMsg = res.message
|
||||
}
|
||||
}).catch(e => {
|
||||
this.isNoData = false
|
||||
this.showError = true
|
||||
this.errorMsg = e.message
|
||||
}).finally(() => {
|
||||
this.toggleLoading(false)
|
||||
})
|
||||
} else if (val === 'sslConLatency') {
|
||||
this.toggleLoading(true)
|
||||
get(api.npm.overview.totalSslConDelay, params).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.showError = false
|
||||
this.isNoData = res.data.result.length === 0
|
||||
if (this.isNoData) {
|
||||
this.npmQuantity = [
|
||||
{ name: 'networkAppPerformance.tcpConnectionEstablishLatency', show: true, positioning: 0, data: [], unitType: unitTypes.time },
|
||||
{ name: 'networkAppPerformance.httpResponse', show: true, positioning: 0, data: [], unitType: unitTypes.time },
|
||||
{ name: 'networkAppPerformance.sslResponseLatency', show: true, positioning: 0, data: [], unitType: unitTypes.time },
|
||||
{ name: 'networkAppPerformance.packetLoss', show: true, positioning: 0, data: [], unitType: unitTypes.percent },
|
||||
{ name: 'overall.packetRetrans', show: true, positioning: 0, data: [], unitType: unitTypes.percent }
|
||||
]
|
||||
}
|
||||
res.data.result.forEach(t => {
|
||||
if (t.type === 'sslConLatency' && val === 'sslConLatency') {
|
||||
const npmQuantity = _.cloneDeep(this.npmQuantity)
|
||||
npmQuantity[2].data = t.sslConLatency.values ? t.sslConLatency.values : []
|
||||
npmQuantity.forEach((e, i) => {
|
||||
e.show = i === 2
|
||||
})
|
||||
this.npmQuantity = npmQuantity
|
||||
this.echartsInit(this.npmQuantity, '(ms)')
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.isNoData = false
|
||||
this.showError = true
|
||||
this.errorMsg = res.message
|
||||
}
|
||||
}).catch(e => {
|
||||
this.isNoData = false
|
||||
this.showError = true
|
||||
this.errorMsg = e.message
|
||||
}).finally(() => {
|
||||
this.toggleLoading(false)
|
||||
})
|
||||
}
|
||||
this.showError = false
|
||||
this.isNoData = npmLineData.length === 0
|
||||
if (this.isNoData) {
|
||||
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' },
|
||||
{ name: this.$t('network.internal'), show: true, positioning: 3, data: [], unitType: 'number' },
|
||||
{ name: this.$t('network.through'), show: true, positioning: 4, data: [], unitType: 'number' },
|
||||
{ name: this.$t('network.other'), show: true, positioning: 5, data: [], unitType: 'number' }
|
||||
]
|
||||
this.npmQuantity = [
|
||||
{ name: this.$t('networkAppPerformance.tcpConnectionEstablishLatency'), show: true, positioning: 0, data: [], unitType: unitTypes.time, index: 0 },
|
||||
{ name: this.$t('networkAppPerformance.httpResponse'), show: true, positioning: 0, data: [], unitType: unitTypes.time, index: 1 },
|
||||
{ name: this.$t('networkAppPerformance.sslResponseLatency'), show: true, positioning: 0, data: [], unitType: unitTypes.time, index: 2 },
|
||||
{ name: this.$t('networkAppPerformance.packetLoss'), show: true, positioning: 0, data: [], unitType: unitTypes.percent, index: 3 },
|
||||
{ name: this.$t('overall.packetRetrans'), show: true, positioning: 0, data: [], unitType: unitTypes.percent, index: 4 }
|
||||
]
|
||||
} else {
|
||||
this.initData(npmLineData, val)
|
||||
}
|
||||
}).catch(e => {
|
||||
this.isNoData = false
|
||||
this.showError = true
|
||||
this.errorMsg = e.message
|
||||
}).finally(() => {
|
||||
this.toggleLoading(false)
|
||||
})
|
||||
}
|
||||
},
|
||||
echartsInit (echartsData, legendUnit) {
|
||||
@@ -619,6 +387,67 @@ export default {
|
||||
},
|
||||
resize () {
|
||||
this.myChart.resize()
|
||||
},
|
||||
initData (data, val) {
|
||||
let lineData = []
|
||||
if (data !== undefined && data.length > 0) {
|
||||
data.forEach(item => {
|
||||
item.type = getLineType(item.type)
|
||||
if (item.type === val) {
|
||||
lineData = Object.keys((item)).map(t => {
|
||||
return {
|
||||
...item[t],
|
||||
index: getLineIndexUnit(item.type, false),
|
||||
unit: getLineIndexUnit(item.type, true)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
lineData.splice(0, 1)
|
||||
const mpackets = _.cloneDeep(this.mpackets)
|
||||
const npmQuantity = _.cloneDeep(this.npmQuantity)
|
||||
if (val === 'Sessions/s') {
|
||||
lineData.forEach((d, i) => {
|
||||
mpackets[i].data = d.values
|
||||
mpackets[i].analysis = d.analysis
|
||||
})
|
||||
mpackets.forEach((e, i) => {
|
||||
if (i !== 0) {
|
||||
e.show = false
|
||||
}
|
||||
})
|
||||
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, mpackets, false)
|
||||
}
|
||||
},
|
||||
legendInit (data, npmData, show) {
|
||||
data.forEach((d, i) => {
|
||||
if (show) {
|
||||
npmData[d.index].data = d.values
|
||||
npmData[d.index].analysis = d.analysis
|
||||
} else {
|
||||
npmData[i].data = d.values
|
||||
npmData[i].analysis = d.analysis
|
||||
}
|
||||
})
|
||||
if (show) {
|
||||
npmData.forEach((e, i) => {
|
||||
e.show = i === data[0].index
|
||||
})
|
||||
this.npmQuantity = npmData
|
||||
this.echartsInit(this.npmQuantity, data[0].unit)
|
||||
} else {
|
||||
npmData.forEach((e) => {
|
||||
e.show = true
|
||||
})
|
||||
this.mpackets = npmData
|
||||
this.echartsInit(this.mpackets)
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
@@ -633,8 +462,9 @@ export default {
|
||||
beforeUnmount () {
|
||||
clearTimeout(this.timer)
|
||||
window.removeEventListener('resize', this.resize)
|
||||
this.myChart = null
|
||||
this.myChart = null
|
||||
if (this.myChart) {
|
||||
echarts.dispose(this.myChart)
|
||||
}
|
||||
this.unitConvert = null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
<template>
|
||||
<div class="single-value" v-for="(npm, index) in newNpmNetworkData" :key="index">
|
||||
<div class="single-value__title" style="display: flex">
|
||||
{{ $t(npmNetworkName[index].name) }}
|
||||
<chart-error v-if="npm.message" tooltip :content="npm.message"></chart-error>
|
||||
</div>
|
||||
|
||||
<div class="single-value__content">
|
||||
<div class="single-value__content-number" v-if="index ===0 || index ===1 || index ===2">
|
||||
{{ unitConvert(npm.Avg, unitTypes.time).join(' ') }}
|
||||
</div>
|
||||
<div class="single-value__content-number" v-else>
|
||||
{{unitConvert(npm.Avg, unitTypes.percent).join(' ')}}
|
||||
</div>
|
||||
<div v-if="npm.value > 0" class="single-value__content-trend single-value__content-trend-red">
|
||||
<i class="cn-icon-rise1 cn-icon"></i>
|
||||
<span v-if="npm.value <= 5">
|
||||
{{ unitConvert(npm.value, unitTypes.percent).join('') }}
|
||||
</span>
|
||||
<span v-else>>500.00%</span>
|
||||
</div>
|
||||
<div v-else-if="npm.value < 0" class="single-value__content-trend single-value__content-trend-green">
|
||||
<i class="cn-icon-decline cn-icon"></i>
|
||||
<span v-if="npm.value >= -5">
|
||||
{{ unitConvert(npm.value, unitTypes.percent).join('').replaceAll('-', '') }}
|
||||
</span>
|
||||
<span v-else>>500.00%</span>
|
||||
</div>
|
||||
<div v-else-if="npm.value === 0" class="single-value__content-trend single-value__content-trend-black">
|
||||
<i class="cn-icon-constant cn-icon"></i>
|
||||
</div>
|
||||
<div v-else></div>
|
||||
</div>
|
||||
|
||||
<div class="single-value__circle">
|
||||
<div class="single-value__circle-p95">
|
||||
<span v-if="index ===0 || index ===1 || index ===2">
|
||||
P95:{{ unitConvert(npm.P95, unitTypes.time).join(' ') }}</span>
|
||||
<span v-else>
|
||||
P95:{{ unitConvert(npm.P95, unitTypes.percent).join(' ') }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="single-value__circle-p99">
|
||||
<span v-if="index ===0 || index ===1 || index ===2">
|
||||
P99:{{ unitConvert(npm.P99, unitTypes.time).join(' ') }}
|
||||
</span>
|
||||
<span v-else>
|
||||
P99:{{ unitConvert(npm.P99, unitTypes.percent).join(' ') }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { unitTypes } from '@/utils/constants'
|
||||
import unitConvert from '@/utils/unit-convert'
|
||||
import ChartError from '@/components/common/Error'
|
||||
|
||||
export default {
|
||||
name: 'SingleValue',
|
||||
components: { ChartError },
|
||||
props: {
|
||||
npmNetworkName: Array,
|
||||
npmNetworkData: Array
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
unitTypes,
|
||||
unitConvert,
|
||||
newNpmNetworkData: [] // 整合处理传过来的数据列表
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
npmNetworkData: {
|
||||
deep: true,
|
||||
handler () {
|
||||
this.initData()
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.initData()
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 初始化数据
|
||||
*/
|
||||
initData () {
|
||||
// 传过来的数据
|
||||
const npmNetworkData = this.npmNetworkData
|
||||
// 处理数据后的数组
|
||||
const dealList = []
|
||||
|
||||
if (npmNetworkData !== undefined && npmNetworkData.length > 0) {
|
||||
npmNetworkData.forEach((item) => {
|
||||
const tempObj = {}
|
||||
for (const i in item) {
|
||||
if (item.msg || item.message) {
|
||||
// 为了兼容字段为msg的情况
|
||||
tempObj.message = item.msg ? item.msg : item.message
|
||||
} else {
|
||||
// 将含有avg、p90等关键字使用avg、p90来代替,形成统一属性
|
||||
if (i.indexOf('Avg') > -1) {
|
||||
tempObj.Avg = item[i]
|
||||
} else if (i.indexOf('P50') > -1) {
|
||||
tempObj.P50 = item[i]
|
||||
} else if (i.indexOf('P90') > -1) {
|
||||
tempObj.P90 = item[i]
|
||||
} else if (i.indexOf('P95') > -1) {
|
||||
tempObj.P95 = item[i]
|
||||
} else if (i.indexOf('P99') > -1) {
|
||||
tempObj.P99 = item[i]
|
||||
}
|
||||
tempObj.value = item.value
|
||||
}
|
||||
}
|
||||
dealList.push(tempObj)
|
||||
})
|
||||
this.newNpmNetworkData = dealList
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -134,15 +134,7 @@ export default {
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
if (this.$route.query.eventId) {
|
||||
if (parseFloat(this.$route.query.eventId) === this.detection.eventId) {
|
||||
const container = document.getElementById('cnContainer')
|
||||
container.scrollTop = 555 + this.index * 97
|
||||
|
||||
this.isCollapse = false
|
||||
this.$emit('switchCollapse', this.isCollapse, this.index)
|
||||
}
|
||||
}
|
||||
this.initExpendTab()
|
||||
},
|
||||
computed: {
|
||||
iconClass () {
|
||||
@@ -186,7 +178,7 @@ export default {
|
||||
this.$emit('switchCollapse', this.isCollapse, this.index)
|
||||
|
||||
if (this.isCollapse) {
|
||||
const newQuery = this.$route.query // 深拷贝路由数据
|
||||
const newQuery = this.$route.query
|
||||
delete newQuery.eventId
|
||||
this.reloadUrl(newQuery, 'cleanOldParams')
|
||||
} else {
|
||||
@@ -207,6 +199,33 @@ export default {
|
||||
newUrl = urlParamsHandler(window.location.href, query, newParam, clean)
|
||||
}
|
||||
overwriteUrl(newUrl)
|
||||
},
|
||||
/**
|
||||
* 初始化从npm跳转过来的id,并展开tab
|
||||
*/
|
||||
initExpendTab () {
|
||||
if (this.$route.query.eventId) {
|
||||
if (this.$route.query.eventId === this.detection.eventId) {
|
||||
const container = document.getElementById('cnContainer')
|
||||
const dom = document.getElementsByClassName('cn-detection__case')
|
||||
// 未展开的item折叠块,高度67+下边距10+底部线高度1,兼容不同分辨率下的tab高度
|
||||
let itemHeight = 78
|
||||
if (dom && this.index > 0) {
|
||||
itemHeight = dom[0].clientHeight + 11
|
||||
}
|
||||
|
||||
let topHeight = 554 + this.index * itemHeight
|
||||
// 经过测试对比,第7个以后的tab会往上移动,但是手动展开和自动展开tab的滚动条高度一致,为解决该问题,自动加上误差值
|
||||
if (this.index > 6) {
|
||||
topHeight = topHeight + 6
|
||||
}
|
||||
|
||||
container.scrollTop = topHeight
|
||||
|
||||
this.isCollapse = false
|
||||
this.$emit('switchCollapse', this.isCollapse, this.index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
<div class="metric__column">
|
||||
<div class="overview__title">{{$t('detections.metric')}}</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__content--metric ">{{detection.eventType || '-'}}</div>
|
||||
<div class="row__content--metric ">{{getNameByEventType(detection.eventType) || '-'}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="metric__column">
|
||||
@@ -95,7 +95,7 @@ import { get } from '@/utils/http'
|
||||
import * as echarts from 'echarts'
|
||||
import { markRaw } from 'vue'
|
||||
import { metricOption } from '@/views/detections/options/detectionOptions'
|
||||
import { sortBy, reverseSortBy } from '@/utils/tools'
|
||||
import { sortBy, reverseSortBy, getNameByEventType } from '@/utils/tools'
|
||||
import _ from 'lodash'
|
||||
export default {
|
||||
name: 'DetectionPerformanceEventAppOverview',
|
||||
@@ -134,6 +134,7 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getNameByEventType,
|
||||
query () {
|
||||
this.queryBasic().then(responses => {
|
||||
responses && (this.basicInfo = responses)
|
||||
@@ -180,6 +181,10 @@ export default {
|
||||
this.chartOptionMetric.series[2].data = this.metricList.slice(endIndex - 1, this.metricList.length).map(v => [Number(v[0]) * 1000, Number(v[1]), unitTypes.number])
|
||||
}
|
||||
|
||||
this.chartOptionMetric.series.forEach(item => {
|
||||
item.name = this.getNameByEventType(this.detection.eventType)
|
||||
})
|
||||
|
||||
this.chartOptionMetric && this.metricChart.setOption(this.chartOptionMetric)
|
||||
},
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
<div class="metric__column">
|
||||
<div class="overview__title">{{$t('detections.metric')}}</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__content--metric ">{{detection.eventType || '-'}}</div>
|
||||
<div class="row__content--metric ">{{getNameByEventType(detection.eventType) || '-'}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="metric__column">
|
||||
@@ -98,7 +98,7 @@ import { get } from '@/utils/http'
|
||||
import * as echarts from 'echarts'
|
||||
import { markRaw } from 'vue'
|
||||
import { metricOption } from '@/views/detections/options/detectionOptions'
|
||||
import { sortBy, reverseSortBy } from '@/utils/tools'
|
||||
import { sortBy, reverseSortBy, getNameByEventType } from '@/utils/tools'
|
||||
import _ from 'lodash'
|
||||
export default {
|
||||
name: 'DetectionPerformanceEventDomainOverview',
|
||||
@@ -165,6 +165,7 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getNameByEventType,
|
||||
query () {
|
||||
this.queryBasic().then(responses => {
|
||||
responses && (this.basicInfo = responses)
|
||||
@@ -212,6 +213,10 @@ export default {
|
||||
this.chartOptionMetric.series[2].data = this.metricList.slice(endIndex - 1, this.metricList.length).map(v => [Number(v[0]) * 1000, Number(v[1]), unitTypes.number])
|
||||
}
|
||||
|
||||
this.chartOptionMetric.series.forEach(item => {
|
||||
item.name = this.getNameByEventType(this.detection.eventType)
|
||||
})
|
||||
|
||||
this.chartOptionMetric && this.metricChart.setOption(this.chartOptionMetric)
|
||||
},
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
<div class="metric__column">
|
||||
<div class="overview__title">{{$t('detections.metric')}}</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__content--metric ">{{getNameByType(detection.eventType) || '-'}}</div>
|
||||
<div class="row__content--metric ">{{getNameByEventType(detection.eventType) || '-'}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="metric__column">
|
||||
@@ -88,7 +88,7 @@ import { get } from '@/utils/http'
|
||||
import * as echarts from 'echarts'
|
||||
import { markRaw } from 'vue'
|
||||
import { metricOption } from '@/views/detections/options/detectionOptions'
|
||||
import { sortBy, reverseSortBy } from '@/utils/tools'
|
||||
import { sortBy, reverseSortBy, getNameByEventType } from '@/utils/tools'
|
||||
import _ from 'lodash'
|
||||
|
||||
export default {
|
||||
@@ -129,6 +129,7 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getNameByEventType,
|
||||
query () {
|
||||
this.queryBasic().then(responses => {
|
||||
responses && (this.basicInfo = responses)
|
||||
@@ -173,9 +174,11 @@ export default {
|
||||
this.chartOptionMetric.series[1].data = this.metricList.slice(startIndex - 1, endIndex).map(v => [Number(v[0]) * 1000, Number(v[1]), unitTypes.number])
|
||||
this.chartOptionMetric.series[2].data = this.metricList.slice(endIndex - 1, this.metricList.length).map(v => [Number(v[0]) * 1000, Number(v[1]), unitTypes.number])
|
||||
}
|
||||
|
||||
this.chartOptionMetric.series.forEach(item => {
|
||||
item.name = this.getNameByType(this.detection.eventType)
|
||||
item.name = this.getNameByEventType(this.detection.eventType)
|
||||
})
|
||||
|
||||
this.chartOptionMetric && this.metricChart.setOption(this.chartOptionMetric)
|
||||
},
|
||||
queryMetric () {
|
||||
@@ -236,29 +239,6 @@ export default {
|
||||
}
|
||||
})
|
||||
window.open(href, '_blank')
|
||||
},
|
||||
/**
|
||||
* 通过事件类型转换对应名称
|
||||
* @param type
|
||||
* @returns {string}
|
||||
*/
|
||||
getNameByType (type) {
|
||||
switch (type) {
|
||||
case 'http error': {
|
||||
return 'http error ratio'
|
||||
}
|
||||
case 'dns error': {
|
||||
return 'dns error ratio'
|
||||
}
|
||||
case 'high dns response time': {
|
||||
return 'dns response time'
|
||||
}
|
||||
// 目前ui并未找到此类型,添加以防不测
|
||||
case 'high http resopnse time':
|
||||
default: {
|
||||
return 'http response time'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
|
||||
@@ -324,8 +324,8 @@ export default {
|
||||
getMillisecond,
|
||||
query () {
|
||||
Promise.all([this.queryBasic(), this.queryEvent()]).then((responses) => {
|
||||
responses[0].malwareTechniques = responses[0].malwareTechniques.length > 2 ? responses[0].malwareTechniques.replace('[', '').split(',', 5).join(', ') : ''
|
||||
responses[0].malwareGroups = responses[0].malwareGroups.length > 2 ? responses[0].malwareGroups.replace('[', '').split(',', 5).join(', ') : ''
|
||||
responses[0].malwareTechniques = responses[0].malwareTechniques.length > 2 ? responses[0].malwareTechniques.replace('[', '').replace(']', '').split(',', 5).join(', ') : ''
|
||||
responses[0].malwareGroups = responses[0].malwareGroups.length > 2 ? responses[0].malwareGroups.replace('[', '').replace(']', '').split(',', 5).join(', ') : ''
|
||||
responses[0].malwarePlatforms = responses[0].malwarePlatforms.length > 1 ? responses[0].malwarePlatforms : ''
|
||||
responses[0].malwareDescription = responses[0].malwareDescription.length > 1 ? responses[0].malwareDescription : ''
|
||||
responses[0] && (this.basicInfo = responses[0])
|
||||
|
||||
@@ -22,6 +22,14 @@
|
||||
<div class="row__label row__label--width130">{{$t('entities.org')}}</div>
|
||||
<div class="row__content">{{entityData.domainWhoisOrg || '-'}}</div>
|
||||
</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('entities.icpCompanyName')}}</div>
|
||||
<div class="row__content">{{entityData.domainIcpCompanyName || '-'}}</div>
|
||||
</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('entities.icpLicense')}}</div>
|
||||
<div class="row__content">{{entityData.domainIcpSiteLicense || '-'}}</div>
|
||||
</div>
|
||||
<!-- <div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('overall.remark')}}</div>
|
||||
<div class="row__content">{{entityData.domainDescription || '-'}}</div>
|
||||
@@ -352,7 +360,9 @@ export default {
|
||||
domainDescription: response.data.result.domainDescription,
|
||||
domainReputationScore: response.data.result.domainReputationScore,
|
||||
domainWhoisAddress: response.data.result.domainWhoisAddress,
|
||||
domainWhoisOrg: response.data.result.domainWhoisOrg
|
||||
domainWhoisOrg: response.data.result.domainWhoisOrg,
|
||||
domainIcpCompanyName: response.data.result.domainIcpCompanyName,
|
||||
domainIcpSiteLicense: response.data.result.domainIcpSiteLicense
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,34 +1,215 @@
|
||||
/**
|
||||
* jest: https://jestjs.io/docs/getting-started
|
||||
* vue-jest: https://test-utils.vuejs.org/guide/
|
||||
* */
|
||||
|
||||
import Test from '../src/Test'
|
||||
import { mount } from '@vue/test-utils'
|
||||
import { getNameByEventType } from '@/utils/tools'
|
||||
import axios from 'axios'
|
||||
import indexedDBUtils from '@/indexedDB'
|
||||
import ElementPlus from 'element-plus'
|
||||
|
||||
// 模拟vue-router库,否则组件中引用vue-router的代码报错
|
||||
jest.mock('vue-router', () => {
|
||||
return {
|
||||
useRouter: function () { return { currentRoute: '/' } }
|
||||
}
|
||||
})
|
||||
test('点击按钮后count的值+1', async () => {
|
||||
// 加载vue组件,获得实例
|
||||
const wrapper = mount(Test)
|
||||
|
||||
// 取到文本和按钮的dom
|
||||
const textNode = await wrapper.get('[data-test="count"]')
|
||||
const button = await wrapper.get('[data-test="button"]')
|
||||
// 断言文本dom的内容是否是'0'
|
||||
expect(textNode.text()).toContain('0')
|
||||
// 模拟按钮dom点击,执行click()方法
|
||||
await button.trigger('click')
|
||||
// 断言点击按钮后文本dom的内容是否是'1'
|
||||
expect(textNode.text()).toContain('1')
|
||||
// 再次点击
|
||||
await button.trigger('click')
|
||||
// 断言点击按钮后文本dom的内容是否是'2'
|
||||
expect(textNode.text()).toContain('2')
|
||||
|
||||
// 通过wrapper.vm.xxx直接执行click方法、获取data的数据
|
||||
expect(wrapper.vm.count).toEqual(2)
|
||||
await wrapper.vm.click()
|
||||
expect(wrapper.vm.count).toEqual(3)
|
||||
|
||||
// 更多断言类型:https://jestjs.io/zh-Hans/docs/expect
|
||||
// 模拟的axios返回数据
|
||||
const mockId = { data: 2 }
|
||||
const mockTitle = { data: 'title2' }
|
||||
const mockCount = { data: 999 }
|
||||
const mockDifferentParam0 = { data: 0 }
|
||||
const mockDifferentParam1 = { data: 1 }
|
||||
const mergeRequestParam0 = { data: 0 }
|
||||
const mergeRequestParam1 = { data: 1 }
|
||||
const mergeRequestChildParam0 = { data: 0 }
|
||||
const mergeRequestChildParam1 = { data: 1 }
|
||||
|
||||
describe('单元测试demo', () => {
|
||||
test('Vue组件--点击按钮后count的值+1', async () => {
|
||||
// 若组件中使用了vue-router,需要细化模拟相关内容
|
||||
require('vue-router').useRoute.mockReturnValue({ query: {} })
|
||||
require('vue-router').useRouter.mockReturnValue({ currentRoute: { value: { path: '/' } } })
|
||||
// 加载vue组件,获得实例
|
||||
const wrapper = mount(Test, {
|
||||
global: {
|
||||
plugins: [ElementPlus]
|
||||
}
|
||||
})
|
||||
// 取到文本和按钮的dom
|
||||
const textNode = await wrapper.get('[test-id="count"]')
|
||||
const button = await wrapper.get('[test-id="button"]')
|
||||
// 断言文本dom的内容是否是'0'
|
||||
expect(textNode.text()).toBe('0')
|
||||
// 模拟按钮dom点击,执行click()方法
|
||||
await button.trigger('click')
|
||||
// 断言点击按钮后文本dom的内容是否是'1'
|
||||
expect(textNode.text()).toBe('1')
|
||||
// 再次点击
|
||||
await button.trigger('click')
|
||||
// 断言点击按钮后文本dom的内容是否是'2'
|
||||
expect(textNode.text()).toBe('2')
|
||||
/* 更多断言类型:https://jestjs.io/docs/expect */
|
||||
})
|
||||
test('Vue组件--获取路由中的参数', async () => {
|
||||
// query中带上lineTab参数
|
||||
require('vue-router').useRoute.mockReturnValue({ query: { lineTab: 'total' } })
|
||||
require('vue-router').useRouter.mockReturnValue({ currentRoute: { value: { path: '/' } } })
|
||||
// 加载vue组件,获得实例
|
||||
const wrapper = mount(Test, {
|
||||
global: {
|
||||
plugins: [ElementPlus]
|
||||
}
|
||||
})
|
||||
// 取到文本和按钮的dom
|
||||
const textNode = await wrapper.get('[test-id="tab"]')
|
||||
expect(textNode.text()).toBe('total')
|
||||
})
|
||||
test('Vue组件--模拟获取localstorage/sessionStorage的内容', async () => {
|
||||
require('vue-router').useRoute.mockReturnValue({ query: {} })
|
||||
require('vue-router').useRouter.mockReturnValue({ currentRoute: { value: { path: '/' } } })
|
||||
// 模拟localStorage的getItem
|
||||
jest.spyOn(localStorage.__proto__, 'getItem').mockImplementation(key => key)
|
||||
// 加载vue组件,获得实例
|
||||
const wrapper = mount(Test, {
|
||||
global: {
|
||||
plugins: [ElementPlus]
|
||||
}
|
||||
})
|
||||
expect(wrapper.vm.localstorageValue).toBe('key')
|
||||
})
|
||||
test('Vue组件--直接获取vue实例中的data和method', async () => {
|
||||
require('vue-router').useRoute.mockReturnValue({ query: {} })
|
||||
require('vue-router').useRouter.mockReturnValue({ currentRoute: { value: { path: '/' } } })
|
||||
// 模拟axios返回数据
|
||||
// 测试内容只有一个axios请求的时候
|
||||
axios.get.mockResolvedValue(mockCount)
|
||||
// 加载vue组件,获得实例
|
||||
const wrapper = mount(Test, {
|
||||
global: {
|
||||
mocks: {
|
||||
$t: key => key
|
||||
},
|
||||
plugins: [ElementPlus]
|
||||
}
|
||||
})
|
||||
const textNode = await wrapper.get('[test-id="count"]')
|
||||
// 通过wrapper.vm.xxx直接执行click方法、获取data的数据
|
||||
expect(wrapper.vm.count).toBe(0)
|
||||
await wrapper.vm.click()
|
||||
expect(wrapper.vm.count).toBe(1)
|
||||
await wrapper.vm.getCount()
|
||||
await wrapper.vm.$nextTick(() => {
|
||||
expect(textNode.text()).toBe('999')
|
||||
})
|
||||
})
|
||||
test('Vue组件--多个axios请求', async () => {
|
||||
require('vue-router').useRoute.mockReturnValue({ query: {} })
|
||||
require('vue-router').useRouter.mockReturnValue({ currentRoute: { value: { path: '/' } } })
|
||||
// 模拟axios返回数据
|
||||
// 测试内容有多个url不同的axios请求的话,需分开写
|
||||
axios.get.mockImplementation(url => {
|
||||
switch (url) {
|
||||
case '/api/getObjId':
|
||||
return Promise.resolve(mockId)
|
||||
case '/api/getObjTitle':
|
||||
return Promise.resolve(mockTitle)
|
||||
}
|
||||
})
|
||||
// 加载vue组件,获得实例
|
||||
const wrapper = mount(Test, {
|
||||
global: {
|
||||
plugins: [ElementPlus]
|
||||
}
|
||||
})
|
||||
const textNode = await wrapper.get('[test-id="id"]')
|
||||
const textNode2 = await wrapper.get('[test-id="title"]')
|
||||
expect(textNode2.text()).toBe('title')
|
||||
await wrapper.vm.getObj()
|
||||
await wrapper.vm.$nextTick(() => {
|
||||
expect(textNode.text()).toBe('2')
|
||||
expect(textNode2.text()).toBe('title2')
|
||||
// 匹配整个对象
|
||||
expect(wrapper.vm.obj).toEqual({ id: 2, title: 'title2' })
|
||||
})
|
||||
})
|
||||
test('Vue组件--多个同url不同参数的axios请求', async () => {
|
||||
require('vue-router').useRoute.mockReturnValue({ query: {} })
|
||||
require('vue-router').useRouter.mockReturnValue({ currentRoute: { value: { path: '/' } } })
|
||||
// 模拟axios返回数据
|
||||
axios.get.mockResolvedValueOnce(mockDifferentParam0)
|
||||
axios.get.mockResolvedValueOnce(mockDifferentParam1)
|
||||
// 加载vue组件,获得实例
|
||||
const wrapper = mount(Test, {
|
||||
global: {
|
||||
plugins: [ElementPlus]
|
||||
}
|
||||
})
|
||||
await wrapper.vm.differentRequestParam()
|
||||
expect(wrapper.vm.differentParamData0).toBe(0)
|
||||
expect(wrapper.vm.differentParamData1).toBe(1)
|
||||
})
|
||||
test('Vue组件--axios请求内包含多个不同url的组合请求', async () => {
|
||||
require('vue-router').useRoute.mockReturnValue({ query: {} })
|
||||
require('vue-router').useRouter.mockReturnValue({ currentRoute: { value: { path: '/' } } })
|
||||
// 模拟axios返回数据
|
||||
axios.get.mockResolvedValueOnce(mergeRequestParam0)
|
||||
axios.get.mockResolvedValueOnce(mergeRequestParam1)
|
||||
|
||||
axios.get.mockImplementation(url => {
|
||||
switch (url) {
|
||||
case '/api/getChildId':
|
||||
return Promise.resolve(mergeRequestChildParam0)
|
||||
case '/api/getChildTitle':
|
||||
return Promise.resolve(mergeRequestChildParam1)
|
||||
}
|
||||
})
|
||||
|
||||
// 加载vue组件,获得实例
|
||||
const wrapper = mount(Test, {
|
||||
global: {
|
||||
plugins: [ElementPlus]
|
||||
}
|
||||
})
|
||||
await wrapper.vm.mergeRequest()
|
||||
await wrapper.vm.$nextTick(() => {
|
||||
expect(wrapper.vm.mergeRequestData0).toBe(0)
|
||||
expect(wrapper.vm.mergeRequestData1).toBe(1)
|
||||
expect(wrapper.vm.mergeRequestChildData0).toBe(0)
|
||||
expect(wrapper.vm.mergeRequestChildData1).toBe(1)
|
||||
})
|
||||
})
|
||||
test('Vue组件--模拟indexedDB操作', async () => {
|
||||
require('vue-router').useRoute.mockReturnValue({ query: {} })
|
||||
require('vue-router').useRouter.mockReturnValue({ currentRoute: { value: { path: '/' } } })
|
||||
// 加载vue组件,获得实例
|
||||
const wrapper = mount(Test, {
|
||||
global: {
|
||||
plugins: [ElementPlus]
|
||||
}
|
||||
})
|
||||
// 模拟indexedDB的内容
|
||||
indexedDBUtils.selectTable.mockReturnValue({
|
||||
put: jest.fn(),
|
||||
get: jest.fn().mockResolvedValue({ a: 1 })
|
||||
})
|
||||
await wrapper.vm.setIndexedDBValue()
|
||||
await wrapper.vm.getIndexedDBValue()
|
||||
expect(wrapper.vm.indexedDBValue).toEqual({ a: 1 })
|
||||
})
|
||||
test('Vue组件--使用第三方组件的情况(以el-table为例)', async () => {
|
||||
require('vue-router').useRoute.mockReturnValue({ query: {} })
|
||||
require('vue-router').useRouter.mockReturnValue({ currentRoute: { value: { path: '/' } } })
|
||||
// 加载vue组件,获得实例
|
||||
const wrapper = mount(Test, {
|
||||
global: {
|
||||
plugins: [ElementPlus]
|
||||
}
|
||||
})
|
||||
// 执行nextTick等待el-table渲染完成
|
||||
await wrapper.vm.$nextTick()
|
||||
const textNode = await wrapper.get('[test-id="name0"]')
|
||||
const textNode2 = await wrapper.get('[test-id="age1"]')
|
||||
expect(textNode.text()).toBe('a')
|
||||
expect(textNode2.text()).toBe('11')
|
||||
})
|
||||
test('js方法--getNameByEventType', async () => {
|
||||
expect(getNameByEventType('http error')).toBe('http error ratio')
|
||||
})
|
||||
})
|
||||
|
||||
41
test/init.js
Normal file
41
test/init.js
Normal file
@@ -0,0 +1,41 @@
|
||||
import { config } from '@vue/test-utils'
|
||||
|
||||
/* 开启测试 */
|
||||
config.global.mocks.isUnitTesting = true
|
||||
/* 初始化dayjs */
|
||||
const dayjs = require('dayjs')
|
||||
const utc = require('dayjs/plugin/utc')
|
||||
const timezone = require('dayjs/plugin/timezone')
|
||||
const advancedFormat = require('dayjs/plugin/advancedFormat')
|
||||
const weekday = require('dayjs/plugin/weekday')
|
||||
dayjs.extend(utc)
|
||||
dayjs.extend(timezone)
|
||||
dayjs.extend(advancedFormat)
|
||||
dayjs.extend(weekday)
|
||||
window.$dayJs = dayjs
|
||||
// 引入 lodash 工具 模拟 lodash
|
||||
const _ = require('lodash') // lodash工具
|
||||
|
||||
/* 模拟vue-router库,否则组件中引用vue-router的代码报错 */
|
||||
jest.mock('vue-router', () => {
|
||||
return {
|
||||
useRouter: jest.fn(),
|
||||
useRoute: jest.fn(),
|
||||
createWebHashHistory: jest.fn(),
|
||||
createRouter: jest.fn().mockReturnValue({
|
||||
beforeEach: jest.fn()
|
||||
})
|
||||
}
|
||||
})
|
||||
/* 模拟axios */
|
||||
jest.mock('axios')
|
||||
/* 模拟indexedDB工具 */
|
||||
jest.mock('@/indexedDB')
|
||||
/* 模拟$t */
|
||||
config.global.mocks.$t = key => key
|
||||
/* 模拟$route,具体用例中需要不同值时重写覆盖即可 */
|
||||
config.global.mocks.$route = { query: '' }
|
||||
/* 模拟 lodash */
|
||||
config.global.mocks.$_ = _
|
||||
/* 消除warn */
|
||||
jest.spyOn(console, 'warn').mockImplementation(() => {})
|
||||
@@ -0,0 +1,37 @@
|
||||
import NetworkOverviewDdosDetection from '@/views/charts2/charts/networkOverview/NetworkOverviewDdosDetection'
|
||||
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"}
|
||||
}
|
||||
|
||||
const timeFilter = {
|
||||
dateRangeValue: -1,
|
||||
startTime: 1675043912,
|
||||
endTime: 1675047512
|
||||
}
|
||||
|
||||
describe('views/charts2/charts/networkOverview/NetworkOverviewDdosDetection.vue测试', () => {
|
||||
test('攻击、受害、攻击数事件:ddos检测图', async () => {
|
||||
require('vue-router').useRoute.mockReturnValue({ query: {} })
|
||||
// 模拟 axios 返回数据
|
||||
axios.get.mockResolvedValue(mockGet)
|
||||
// 加载vue组件,获得实例
|
||||
const wrapper = mount(NetworkOverviewDdosDetection, {
|
||||
propsData: {
|
||||
timeFilter
|
||||
}
|
||||
})
|
||||
const attackEventCount = wrapper.get('[test-id="attackEventCount"]')
|
||||
const attackerCount = wrapper.get('[test-id="attackerCount"]')
|
||||
const victimCount = wrapper.get('[test-id="victimCount"]')
|
||||
|
||||
await new Promise(resolve => setTimeout(() => {
|
||||
expect(attackEventCount.text()).toEqual('1.20 M')
|
||||
expect(attackerCount.text()).toEqual('2.69 M')
|
||||
expect(victimCount.text()).toEqual('36.68 M')
|
||||
resolve()
|
||||
}, 200))
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,83 @@
|
||||
import NetworkOverviewLine from '@/views/charts2/charts/networkOverview/NetworkOverviewLine'
|
||||
import { mount } from '@vue/test-utils'
|
||||
import axios from 'axios'
|
||||
|
||||
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,"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,点击第三个tab', async () => {
|
||||
require('vue-router').useRoute.mockReturnValue({ query: {} })
|
||||
// 模拟axios返回数据
|
||||
axios.get.mockResolvedValue(mockGet)
|
||||
// 加载vue组件,获得实例
|
||||
const wrapper = mount(NetworkOverviewLine, {
|
||||
propsData: {
|
||||
timeFilter,
|
||||
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(() => {
|
||||
expect(textNode0.text()).toEqual('112.04Mbps')
|
||||
expect(textNode1.text()).toEqual('18.59Mbps')
|
||||
expect(textNode2.text()).toEqual('87.56Mbps')
|
||||
resolve()
|
||||
}, 200))
|
||||
|
||||
// 点击tab后,是否切换高亮状态
|
||||
const textNode3 = await wrapper.get('[test-id="tab2"]')
|
||||
await textNode3.trigger('click')
|
||||
expect(textNode3.classes()).toContain('is-active')
|
||||
})
|
||||
test('Metric=Packets/s', async () => {
|
||||
require('vue-router').useRoute.mockReturnValue({ query: {} })
|
||||
// 模拟axios返回数据
|
||||
axios.get.mockResolvedValue(mockGet)
|
||||
// 加载vue组件,获得实例
|
||||
const wrapper = mount(NetworkOverviewLine, {
|
||||
propsData: {
|
||||
timeFilter,
|
||||
chart,
|
||||
metric: 'Packets/s'
|
||||
}
|
||||
})
|
||||
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')
|
||||
resolve()
|
||||
}, 200))
|
||||
})
|
||||
test('Metric=Sessions/s', async () => {
|
||||
require('vue-router').useRoute.mockReturnValue({ query: {} })
|
||||
// 模拟axios返回数据
|
||||
axios.get.mockResolvedValue(mockGet)
|
||||
// 加载vue组件,获得实例
|
||||
const wrapper = mount(NetworkOverviewLine, {
|
||||
propsData: {
|
||||
timeFilter,
|
||||
chart,
|
||||
metric: 'Sessions/s'
|
||||
}
|
||||
})
|
||||
const textNode0 = await wrapper.get('[test-id="tabContent0"]')
|
||||
await new Promise(resolve => setTimeout(() => {
|
||||
expect(textNode0.text()).toEqual('29.89sessions/s')
|
||||
resolve()
|
||||
}, 200))
|
||||
})
|
||||
})
|
||||
148
test/views/charts2/charts/npm/NpmAppCategoryScore.test.js
Normal file
148
test/views/charts2/charts/npm/NpmAppCategoryScore.test.js
Normal file
File diff suppressed because one or more lines are too long
54
test/views/charts2/charts/npm/NpmEventsHeader.test.js
Normal file
54
test/views/charts2/charts/npm/NpmEventsHeader.test.js
Normal file
@@ -0,0 +1,54 @@
|
||||
import NpmEventsHeader from '@/views/charts2/charts/npm/NpmEventsHeader'
|
||||
import { mount } from '@vue/test-utils'
|
||||
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"}
|
||||
}
|
||||
// type
|
||||
const type = 'severity'
|
||||
|
||||
describe('views/charts2/charts/npm/NpmEventsHeader.vue测试', () => {
|
||||
test('严重等级各等级个数:npm event 严重等级单值', async () => {
|
||||
require('vue-router').useRoute.mockReturnValue({ query: {} })
|
||||
// 模拟 axios 返回数据
|
||||
axios.get.mockResolvedValue(chartData)
|
||||
// 加载vue组件,获得实例
|
||||
const wrapper = mount(NpmEventsHeader, {
|
||||
propsData: {
|
||||
type
|
||||
}
|
||||
})
|
||||
// 严重等级
|
||||
const severity0 = wrapper.get('[test-id="severity0"]')
|
||||
const severity1 = wrapper.get('[test-id="severity1"]')
|
||||
const severity2 = wrapper.get('[test-id="severity2"]')
|
||||
const severity3 = wrapper.get('[test-id="severity3"]')
|
||||
const severity4 = wrapper.get('[test-id="severity4"]')
|
||||
// 各等级个数
|
||||
const total0 = wrapper.get('[test-id="total0"]')
|
||||
const total1 = wrapper.get('[test-id="total1"]')
|
||||
const total2 = wrapper.get('[test-id="total2"]')
|
||||
const total3 = wrapper.get('[test-id="total3"]')
|
||||
const total4 = wrapper.get('[test-id="total4"]')
|
||||
|
||||
// type
|
||||
expect(wrapper.vm.type).toEqual('severity')
|
||||
|
||||
expect(severity0.text()).toEqual('critical')
|
||||
expect(severity1.text()).toEqual('high')
|
||||
expect(severity2.text()).toEqual('medium')
|
||||
expect(severity3.text()).toEqual('low')
|
||||
expect(severity4.text()).toEqual('info')
|
||||
|
||||
await new Promise(resolve => setTimeout(() => {
|
||||
expect(total0.text()).toEqual('322,334')
|
||||
expect(total1.text()).toEqual('1,111')
|
||||
expect(total2.text()).toEqual('2,000,000')
|
||||
expect(total3.text()).toEqual('14,456,678')
|
||||
expect(total4.text()).toEqual('122,222')
|
||||
resolve()
|
||||
}, 200))
|
||||
})
|
||||
})
|
||||
248
test/views/charts2/charts/npm/NpmNetworkQuantity.test.js
Normal file
248
test/views/charts2/charts/npm/NpmNetworkQuantity.test.js
Normal file
File diff suppressed because one or more lines are too long
162
test/views/charts2/charts/npm/NpmRecentEvents.test.js
Normal file
162
test/views/charts2/charts/npm/NpmRecentEvents.test.js
Normal file
@@ -0,0 +1,162 @@
|
||||
import NpmRecentEvents from '@/views/charts2/charts/npm/NpmRecentEvents'
|
||||
import { mount } from '@vue/test-utils'
|
||||
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":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":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",
|
||||
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"
|
||||
}
|
||||
|
||||
const timeFilter = {
|
||||
dateRangeValue: -1,
|
||||
startTime: 1675043912,
|
||||
endTime: 1675047512
|
||||
}
|
||||
|
||||
describe('views/charts2/charts/npm/NpmRecentEvents.vue测试', () => {
|
||||
test('npm events 近期事件表格 未下钻', async () => {
|
||||
require('vue-router').useRoute.mockReturnValue({ query: {} })
|
||||
// 模拟 axios 返回数据
|
||||
axios.get.mockResolvedValue(mockGet)
|
||||
|
||||
const wrapper = mount(NpmRecentEvents, {
|
||||
propsData: {
|
||||
timeFilter
|
||||
},
|
||||
global: {
|
||||
plugins: [ElementPlus]
|
||||
}
|
||||
})
|
||||
await new Promise(resolve => setTimeout(() => {
|
||||
const severity0 = wrapper.get('[test-id="eventSeverity-critical-0"]')
|
||||
const severity1 = wrapper.get('[test-id="eventSeverity-high-1"]')
|
||||
const severity2 = wrapper.get('[test-id="eventSeverity-medium-2"]')
|
||||
const severity3 = wrapper.get('[test-id="eventSeverity-low-3"]')
|
||||
const severity4 = wrapper.get('[test-id="eventSeverity-info-4"]')
|
||||
const severity5 = wrapper.get('[test-id="eventSeverity-critical-5"]')
|
||||
|
||||
expect(severity0.text()).toEqual('critical')
|
||||
expect(severity1.text()).toEqual('high')
|
||||
expect(severity2.text()).toEqual('medium')
|
||||
expect(severity3.text()).toEqual('low')
|
||||
expect(severity4.text()).toEqual('info')
|
||||
expect(severity5.text()).toEqual('critical')
|
||||
|
||||
expect(severity0.classes()).toContain('critical')
|
||||
expect(severity1.classes()).toContain('high')
|
||||
expect(severity2.classes()).toContain('medium')
|
||||
expect(severity3.classes()).toContain('low')
|
||||
expect(severity4.classes()).toContain('info')
|
||||
expect(severity5.classes()).toContain('critical')
|
||||
|
||||
const eventKey0 = wrapper.get('[test-id="eventKey-114.114.114.114-0"]')
|
||||
const eventKey1 = wrapper.get('[test-id="eventKey-116.178.78.241-1"]')
|
||||
const eventKey2 = wrapper.get('[test-id="eventKey-223.6.6.6-2"]')
|
||||
const eventKey3 = wrapper.get('[test-id="eventKey-114.114.114.114-3"]')
|
||||
const eventKey4 = wrapper.get('[test-id="eventKey-1.1.1.2-4"]')
|
||||
|
||||
expect(eventKey0.text()).toEqual('114.114.114.114')
|
||||
expect(eventKey1.text()).toEqual('116.178.78.241')
|
||||
expect(eventKey2.text()).toEqual('223.6.6.6')
|
||||
expect(eventKey3.text()).toEqual('114.114.114.114')
|
||||
expect(eventKey4.text()).toEqual('1.1.1.2')
|
||||
|
||||
const eventType0 = wrapper.get('[test-id="eventType-dns error-0"]')
|
||||
const eventType1 = wrapper.get('[test-id="eventType-http error-1"]')
|
||||
const eventType2 = wrapper.get('[test-id="eventType-dns error-2"]')
|
||||
const eventType3 = wrapper.get('[test-id="eventType-dns error-3"]')
|
||||
const eventType4 = wrapper.get('[test-id="eventType-http error-4"]')
|
||||
|
||||
expect(eventType0.text()).toEqual('dns error')
|
||||
expect(eventType1.text()).toEqual('http error')
|
||||
expect(eventType2.text()).toEqual('dns error')
|
||||
expect(eventType3.text()).toEqual('dns error')
|
||||
expect(eventType4.text()).toEqual('http error')
|
||||
|
||||
resolve()
|
||||
}, 200))
|
||||
})
|
||||
test('npm events 近期事件表格 下钻', async () => {
|
||||
require('vue-router').useRoute.mockReturnValue({ query: query })
|
||||
// 模拟 axios 返回数据
|
||||
axios.get.mockResolvedValue(mockGet1)
|
||||
|
||||
const wrapper = mount(NpmRecentEvents, {
|
||||
propsData: {
|
||||
timeFilter
|
||||
},
|
||||
global: {
|
||||
plugins: [ElementPlus]
|
||||
}
|
||||
})
|
||||
await new Promise(resolve => setTimeout(() => {
|
||||
const severity0 = wrapper.get('[test-id="eventSeverity-critical-0"]')
|
||||
const severity1 = wrapper.get('[test-id="eventSeverity-high-1"]')
|
||||
const severity2 = wrapper.get('[test-id="eventSeverity-low-2"]')
|
||||
const severity3 = wrapper.get('[test-id="eventSeverity-medium-3"]')
|
||||
const severity4 = wrapper.get('[test-id="eventSeverity-info-4"]')
|
||||
const severity5 = wrapper.get('[test-id="eventSeverity-critical-5"]')
|
||||
|
||||
expect(severity0.text()).toEqual('critical')
|
||||
expect(severity1.text()).toEqual('high')
|
||||
expect(severity2.text()).toEqual('low')
|
||||
expect(severity3.text()).toEqual('medium')
|
||||
expect(severity4.text()).toEqual('info')
|
||||
expect(severity5.text()).toEqual('critical')
|
||||
|
||||
expect(severity0.classes()).toContain('critical')
|
||||
expect(severity1.classes()).toContain('high')
|
||||
expect(severity2.classes()).toContain('low')
|
||||
expect(severity3.classes()).toContain('medium')
|
||||
expect(severity4.classes()).toContain('info')
|
||||
expect(severity5.classes()).toContain('critical')
|
||||
|
||||
const eventType0 = wrapper.get('[test-id="eventType-http error-0"]')
|
||||
const eventType1 = wrapper.get('[test-id="eventType-dns error-1"]')
|
||||
const eventType2 = wrapper.get('[test-id="eventType-dns error-2"]')
|
||||
const eventType3 = wrapper.get('[test-id="eventType-http error-3"]')
|
||||
const eventType4 = wrapper.get('[test-id="eventType-dns error-4"]')
|
||||
|
||||
expect(eventType0.text()).toEqual('http error')
|
||||
expect(eventType1.text()).toEqual('dns error')
|
||||
expect(eventType2.text()).toEqual('dns error')
|
||||
expect(eventType3.text()).toEqual('http error')
|
||||
expect(eventType4.text()).toEqual('dns error')
|
||||
|
||||
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')
|
||||
expect(startTime2.text()).toEqual('2023-01-03T13:05:00+08:00')
|
||||
expect(startTime3.text()).toEqual('2023-01-03T12:35:00+08:00')
|
||||
expect(startTime4.text()).toEqual('2023-01-03T12:15:00+08:00')
|
||||
|
||||
resolve()
|
||||
}, 300))
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user