Compare commits
88 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c7366ef745 | ||
|
|
064001c4ab | ||
|
|
eb92ef9ea8 | ||
|
|
cb0546ebb2 | ||
|
|
9ca2950d68 | ||
|
|
533f7d357d | ||
|
|
efa899da2c | ||
|
|
c35965061f | ||
|
|
19677ba521 | ||
|
|
7c1729ca63 | ||
|
|
1c6e28a200 | ||
|
|
fa746fd95b | ||
|
|
0a5fe3029c | ||
|
|
61357f2720 | ||
|
|
9bc9103925 | ||
|
|
f0ea7e28fc | ||
|
|
cf5bfb4136 | ||
|
|
ef6c95e536 | ||
|
|
29fe3bc3ef | ||
|
|
85830dc7ca | ||
|
|
f1423b6b62 | ||
|
|
8b2e1e95db | ||
|
|
a1b7527496 | ||
|
|
e93345ea2a | ||
|
|
2b3e5ca360 | ||
|
|
8f045125ea | ||
|
|
aa06553b17 | ||
|
|
9e2aa20303 | ||
|
|
1e77c69460 | ||
|
|
d25912b2ce | ||
|
|
c7eacdd6f6 | ||
|
|
09edc8961c | ||
|
|
8e698f3b78 | ||
|
|
e2d6707249 | ||
|
|
a381f5a01b | ||
|
|
1ac910fc54 | ||
|
|
7d9829ae27 | ||
|
|
16a255be50 | ||
|
|
ae4ce44eff | ||
|
|
bf008fe944 | ||
|
|
2cae53e83a | ||
|
|
fa8ea9dce0 | ||
|
|
d5298347d8 | ||
|
|
248075cd81 | ||
|
|
c3ffd01363 | ||
|
|
69735e438f | ||
|
|
8e221414b8 | ||
|
|
8d461ef200 | ||
|
|
0f5bd8a7a7 | ||
|
|
ebf1228c68 | ||
|
|
cdd48102a5 | ||
|
|
6ba21507f7 | ||
|
|
90ee54c3ad | ||
|
|
5e03847a42 | ||
|
|
4c107704e7 | ||
|
|
4975f2425d | ||
|
|
2b34f8bc26 | ||
|
|
7c4b16d443 | ||
|
|
57b607fca5 | ||
|
|
c30f6e642a | ||
|
|
8416060fc4 | ||
|
|
45c318b391 | ||
|
|
3ec3873860 | ||
|
|
5a1f177ae1 | ||
|
|
820c86a3d3 | ||
|
|
b4b7edb18f | ||
|
|
0a3cf92ce9 | ||
|
|
5ecf096e40 | ||
|
|
aee521d5bc | ||
|
|
35fcbab852 | ||
|
|
9f6a98779b | ||
|
|
d44b406222 | ||
|
|
37ce944dc1 | ||
|
|
c322059c97 | ||
|
|
323ccae196 | ||
|
|
d1beba7782 | ||
|
|
0fb496c349 | ||
|
|
ef069e7fbc | ||
|
|
40e1e5da16 | ||
|
|
e996963635 | ||
|
|
aa6d5f1598 | ||
|
|
39edceb0dd | ||
|
|
e355eb31cd | ||
|
|
3e4cc199a6 | ||
|
|
faabc949c0 | ||
|
|
809a6b5562 | ||
|
|
21e0f94d19 | ||
|
|
ec98178d45 |
@@ -18,7 +18,7 @@ before_script:
|
||||
generate_git-log:
|
||||
stage: gen_git-log
|
||||
script:
|
||||
- if (( `grep git-log.html ./public/index.html | wc -l` == 0 )); then sed -i 's+</body>+<a style="position:fixed;top:0;left:0;z-index:999;font-size:12px;color:darkblue;text-decoration:none;" target="_blank" href="./git-log.html">R</a>\n</body>+g' ./public/index.html; echo "添加更新记录链接"; fi;
|
||||
- if (( `grep git-log.html ./public/index.html | wc -l` == 0 )); then sed -i 's+</body>+<a style="position:fixed;top:0;left:0;z-index:999;font-size:12px;color:transparent;text-decoration:none;display:none;" target="_blank" href="./git-log.html">R</a>\n</body>+g' ./public/index.html; echo "添加更新记录链接"; fi;
|
||||
- echo "最近的100个提交记录"
|
||||
- echo "<!DOCTYPE html><html><head><meta charset='utf-8'></head><body><pre>" > ./public/git-log.html
|
||||
- "git log -100 --pretty=format:'%ad : %s' >> ./public/git-log.html"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
display: none !important;
|
||||
}
|
||||
* {
|
||||
font-family: NotoSansSChineseRegular;
|
||||
font-family: NotoSansSChineseRegular, serif;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
html, body, #app {
|
||||
@@ -43,3 +43,20 @@ body {
|
||||
.el-form-item__error {
|
||||
padding-top: 0 !important;
|
||||
}
|
||||
|
||||
/* 请求报错样式关于popover的修改 */
|
||||
.error-popover {
|
||||
//min-width: 30px !important;
|
||||
display: inline-block;
|
||||
background: #FFE7E6 !important;
|
||||
border: 1px solid rgba(226,97,84,0.42) !important;
|
||||
padding: 6.6px 12px !important;
|
||||
border-radius: 4px !important;
|
||||
font-size: 14px !important;
|
||||
color: #F53A19 !important;
|
||||
font-weight: 400 !important;
|
||||
line-height: 1.2 !important;
|
||||
.el-popper__arrow {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
80
src/assets/css/components/components/common/chart-error.scss
Normal file
80
src/assets/css/components/components/common/chart-error.scss
Normal file
@@ -0,0 +1,80 @@
|
||||
.error-component {
|
||||
position: absolute;
|
||||
//width: 100%;
|
||||
//height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
.error-block {
|
||||
display: inline-block;
|
||||
//width: 100%;
|
||||
//max-width: calc(100% - 24px);
|
||||
//max-height: calc(100% - 24px);
|
||||
//line-height: 24px;
|
||||
background: #FFE7E6;
|
||||
font-size: 14px;
|
||||
color: #F53A19;
|
||||
font-weight: 400;
|
||||
padding: 7.6px 12px;
|
||||
margin: 12px;
|
||||
z-index: 3;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
//white-space: nowrap;
|
||||
word-break: break-all;
|
||||
border: 1px solid rgba(226,97,84,0.42);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.error-block-info {
|
||||
position: absolute;
|
||||
width: calc(100% - 20px);
|
||||
height: calc(100% - 20px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 10px;
|
||||
font-size: 14px;
|
||||
color: #575757;
|
||||
line-height: 24px;
|
||||
font-weight: 400;
|
||||
font-family: NotoSansSChineseRegular, serif;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.new-error-icon {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.new-error-icon .error-content {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
top: -42px;
|
||||
left: 0;
|
||||
visibility: hidden;
|
||||
max-width: 220px;
|
||||
overflow: scroll;
|
||||
height: auto;
|
||||
background: #FFE7E6;
|
||||
border: 1px solid rgba(226,97,84,0.42);
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
color: #F53A19;
|
||||
font-weight: 400;
|
||||
padding: 5px 12px;
|
||||
}
|
||||
|
||||
.error-icon-default {
|
||||
font-size: 16px;
|
||||
margin-left: -2px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.error-icon-tooltip {
|
||||
font-size: 16px !important;
|
||||
margin-bottom: -1px;
|
||||
margin-left: 6px;
|
||||
}
|
||||
@@ -72,3 +72,4 @@
|
||||
@import 'views/charts2/dnsEventChart';
|
||||
@import './views/charts2/dnsEventChartByPie';
|
||||
//@import '../chart';
|
||||
@import './components/common/chart-error';
|
||||
|
||||
@@ -13,6 +13,13 @@
|
||||
font-size: 14px;
|
||||
color: #046ECA;
|
||||
}
|
||||
.link-block-error {
|
||||
position: absolute;
|
||||
width: calc(100% - 20px);
|
||||
height: calc(100% - 60px);
|
||||
margin-left: -12px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.data-grid {
|
||||
height: 100px;
|
||||
.egress-row {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
.network-overview-apps-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
//justify-content: space-between;
|
||||
|
||||
.network-overview-apps-title {
|
||||
font-size: 14px;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
height:calc(100% - 64px);
|
||||
font-size:12px;
|
||||
.tab-hide{
|
||||
margin-top:40px;
|
||||
margin-top:42px;
|
||||
}
|
||||
.cn-chart__tabs {
|
||||
height:100%;
|
||||
@@ -32,13 +32,11 @@
|
||||
.div-yellow {
|
||||
height: 12px;
|
||||
background: #e5a219;
|
||||
border: 1px solid #e5a219;
|
||||
border-left: none;
|
||||
}
|
||||
.div-green {
|
||||
height: 12px;
|
||||
background: #749f4d;
|
||||
border: 1px solid #749f4d;
|
||||
border-right: none;
|
||||
}
|
||||
}
|
||||
@@ -115,6 +113,18 @@
|
||||
.el-table thead {
|
||||
color: $grey;
|
||||
}
|
||||
.el-table__empty-text{
|
||||
line-height:20px !important;
|
||||
}
|
||||
.el-table__header th .cell {
|
||||
display:flex;
|
||||
flex-direction:row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.el-table__header tr th:nth-of-type(1) .cell {
|
||||
justify-content: start;
|
||||
}
|
||||
.score-cell {
|
||||
display: flex !important;
|
||||
justify-content: center;
|
||||
|
||||
@@ -179,3 +179,6 @@
|
||||
color: $grey;
|
||||
}
|
||||
}
|
||||
.npm-app-border {
|
||||
border: 1px solid #E2E5EC;
|
||||
}
|
||||
|
||||
@@ -110,4 +110,10 @@
|
||||
.el-table--group::after,.el-table--border::after,.el-table::before {
|
||||
height: 0px;
|
||||
}
|
||||
.table-error {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 68px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.npm-event-title {
|
||||
display: flex;
|
||||
font-size: 14px;
|
||||
color: #353636;
|
||||
font-weight: 600;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
width: 100%;
|
||||
border: 1px solid #f0f0f0;
|
||||
.npm-line-title {
|
||||
display: flex;
|
||||
font-size: 14px;
|
||||
color: #353636;
|
||||
font-weight: 500;
|
||||
@@ -14,6 +15,7 @@
|
||||
margin: 20px 20px 0 20px;
|
||||
justify-content: space-between;
|
||||
.npm-line-header-title {
|
||||
display: flex;
|
||||
font-size: 14px;
|
||||
color: #353636;
|
||||
font-weight: 500;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
.cn-chart__map-title {
|
||||
display: flex;
|
||||
font-size: 14px;
|
||||
color: #353636;
|
||||
font-weight: 600;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
.npm-recent-title {
|
||||
display: flex;
|
||||
font-size: 14px;
|
||||
color: #353636;
|
||||
font-weight: 600;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
.npm-sessions-title {
|
||||
display: flex;
|
||||
font-size: 14px;
|
||||
color: #353636;
|
||||
font-weight: 500;
|
||||
@@ -27,6 +28,14 @@
|
||||
border-bottom-left-radius: 4px;
|
||||
border-right: none;
|
||||
}
|
||||
.npm-sessions-div-gray {
|
||||
height: 100%;
|
||||
background: rgba(113,113,113,0.30);
|
||||
border: 1px solid rgba(113,113,113,0.30);
|
||||
border-top-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-right: none;
|
||||
}
|
||||
}
|
||||
|
||||
.npm-sessions-body {
|
||||
@@ -45,15 +54,10 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.npm-sessions-as-client-i18n {
|
||||
ont-size: 12px;
|
||||
font-size: 12px;
|
||||
color: #717171;
|
||||
font-weight: 400;
|
||||
}
|
||||
.npm-sessions-as-client-percent {
|
||||
font-size: 18px;
|
||||
color: #353636;
|
||||
font-weight: 700;
|
||||
}
|
||||
.npm-sessions-as-client-green,.npm-sessions-as-client-red {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
@@ -66,6 +70,11 @@
|
||||
background: red;
|
||||
}
|
||||
}
|
||||
.npm-sessions-as-client-percent {
|
||||
font-size: 18px;
|
||||
color: #353636;
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
}
|
||||
.npm-sessions-body-right {
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
align-items: center;
|
||||
padding-left: 10px;
|
||||
color: #666;
|
||||
background-color: #F3F7FA;
|
||||
//background-color: #F3F7FA;
|
||||
cursor: pointer;
|
||||
|
||||
span {
|
||||
@@ -33,7 +33,18 @@
|
||||
i.arrow-rotate {
|
||||
transform: rotate(90deg) translate(2px, 3px);
|
||||
}
|
||||
.new-detection-filter-header-title {
|
||||
font-size: 14px;
|
||||
color: #353636;
|
||||
font-weight: 600;
|
||||
}
|
||||
.new-detection-filter-icon {
|
||||
margin-left: 8px;
|
||||
margin-bottom: 2px;
|
||||
font-weight: bold !important;
|
||||
}
|
||||
}
|
||||
|
||||
.filter__body {
|
||||
padding: 5px 0 0 15px;
|
||||
|
||||
@@ -69,4 +80,17 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.new-detection-filter-title {
|
||||
display: flex;
|
||||
flex: 0 0 32px;
|
||||
align-items: center;
|
||||
padding-left: 27px;
|
||||
background-color: #EFF2F5;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
color: #353636;
|
||||
font-weight: 600;
|
||||
margin: -10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
|
||||
.cn-detection__shadow {
|
||||
.cn-detection__shadow, .new-cn-detection__shadow {
|
||||
position: fixed;
|
||||
height: 100vh;
|
||||
width:100vw;
|
||||
@@ -49,6 +49,10 @@
|
||||
z-index: 1;
|
||||
background-color: rgba(0, 0, 0, .2);
|
||||
}
|
||||
|
||||
.new-cn-detection__shadow {
|
||||
z-index: 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,13 +2,22 @@
|
||||
display: flex;
|
||||
|
||||
.cn-detection__collapse {
|
||||
margin-bottom: 1px;
|
||||
padding-top: 18px;
|
||||
width: 24px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
background-color: #F3F7FA;
|
||||
margin-bottom: 1px;
|
||||
//padding-top: 18px;
|
||||
background-color: #EFF2F5;
|
||||
|
||||
.cn-detection__collapse-block {
|
||||
min-height: 66px;
|
||||
height: 100%;
|
||||
max-height: 88px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
span {
|
||||
transform: rotate(0);
|
||||
@@ -99,6 +108,25 @@
|
||||
line-height: 14px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
.detection-event-severity-color-block {
|
||||
width: 5px;
|
||||
height: 20px;
|
||||
border-radius: 2.5px;
|
||||
margin-left: -16px;
|
||||
margin-right: 12px;
|
||||
}
|
||||
.detection-event-severity-block {
|
||||
font-family: NotoSansHans-Medium;
|
||||
font-size: 12px;
|
||||
color: #046EC9;
|
||||
font-weight: 500;
|
||||
padding: 2px 10px;
|
||||
background: rgba(56,172,210,0.10);
|
||||
border: 1px solid #ADC7DB;
|
||||
box-shadow: 0 2px 4px 0 rgba(51,51,51,0.02);
|
||||
border-radius: 3px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.cn-detection__body {
|
||||
|
||||
@@ -62,8 +62,11 @@
|
||||
|
||||
.row__content {
|
||||
display: flex;
|
||||
color: #3976CB;
|
||||
|
||||
//color: #3976CB;
|
||||
color: #046ECA;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
|
||||
&.row__content--link {
|
||||
font-style: italic;
|
||||
text-decoration: underline;
|
||||
@@ -77,6 +80,10 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
span{
|
||||
font-style: italic;
|
||||
color: #046ECA;
|
||||
}
|
||||
.row__content--span {
|
||||
font-style: italic;
|
||||
color: #1890FF;
|
||||
}
|
||||
@@ -169,13 +176,16 @@
|
||||
span {
|
||||
padding-left: 5px;
|
||||
font-size: 14px;
|
||||
color: #3976CB;
|
||||
//color: #3976CB;
|
||||
color: #046ECA;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
}
|
||||
.timeline__security-type {
|
||||
font-size: 12px;
|
||||
color: #3976CB;
|
||||
color: #046ECA;
|
||||
margin-bottom: 10px;
|
||||
font-weight: 500;
|
||||
}
|
||||
.timeline__start-time {
|
||||
font-size: 12px;
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.explorer-top-tools {
|
||||
.explorer-top-tools, .explorer-detection-top-tools {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
@@ -46,6 +46,38 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.explorer-detection-top-tools {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.explorer-top-tools-title {
|
||||
font-size: 24px;
|
||||
line-height: 24px;
|
||||
font-weight: 900;
|
||||
color: #353636;
|
||||
}
|
||||
.explorer-top-tools-block {
|
||||
font-family: NotoSansHans-Medium;
|
||||
height: 28px;
|
||||
line-height: 28px;
|
||||
background: #F5F8FA;
|
||||
font-size: 14px;
|
||||
color: #353636;
|
||||
font-weight: 500;
|
||||
padding: 0 10px;
|
||||
margin-right: 10px;
|
||||
border: 1px solid #E2E5EC;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.detection-icon-setting {
|
||||
margin-right: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.detection-border {
|
||||
border: 1px solid #E2E5EC;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.explorer-container {
|
||||
display: flex;
|
||||
overflow: visible; /*overflow: hidden;*/
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
@font-face {
|
||||
font-family: "cn-icon"; /* Project id 2614877 */
|
||||
src: url('iconfont.woff2?t=1663570533591') format('woff2'),
|
||||
url('iconfont.woff?t=1663570533591') format('woff'),
|
||||
url('iconfont.ttf?t=1663570533591') format('truetype');
|
||||
src: url('iconfont.woff2?t=1668593055875') format('woff2'),
|
||||
url('iconfont.woff?t=1668593055875') format('woff'),
|
||||
url('iconfont.ttf?t=1668593055875') format('truetype');
|
||||
}
|
||||
|
||||
.cn-icon {
|
||||
@@ -13,6 +13,46 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.cn-icon-baocuo:before {
|
||||
content: "\e7b7";
|
||||
}
|
||||
|
||||
.cn-icon-a-SecurityEvent:before {
|
||||
content: "\e7ae";
|
||||
}
|
||||
|
||||
.cn-icon-bianji1:before {
|
||||
content: "\e7af";
|
||||
}
|
||||
|
||||
.cn-icon-a-PerformanceEvent:before {
|
||||
content: "\e7b0";
|
||||
}
|
||||
|
||||
.cn-icon-xinjian:before {
|
||||
content: "\e7b1";
|
||||
}
|
||||
|
||||
.cn-icon-a-RegulatoryRiskEvent:before {
|
||||
content: "\e7b2";
|
||||
}
|
||||
|
||||
.cn-icon-Delete1:before {
|
||||
content: "\e7b3";
|
||||
}
|
||||
|
||||
.cn-icon-a-EvaluatedTarget:before {
|
||||
content: "\e7b4";
|
||||
}
|
||||
|
||||
.cn-icon-a-GeneralSettings:before {
|
||||
content: "\e7b5";
|
||||
}
|
||||
|
||||
.cn-icon-Thresholds:before {
|
||||
content: "\e7b6";
|
||||
}
|
||||
|
||||
.cn-icon-good:before {
|
||||
content: "\e7ad";
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
149
src/components/common/Error.vue
Normal file
149
src/components/common/Error.vue
Normal file
@@ -0,0 +1,149 @@
|
||||
<template>
|
||||
<div v-if="showDefault" class="error-component">
|
||||
<div class="error-block" :style="{'max-width': localMaxWidth, 'width': localWidth}">
|
||||
<svg class="icon error-icon-default" aria-hidden="true">
|
||||
<use xlink:href="#cn-icon-baocuo"></use>
|
||||
</svg>
|
||||
{{ content }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="error-com">
|
||||
<div v-if="tooltip !== undefined">
|
||||
<el-popover
|
||||
:width="localPopoverWidth"
|
||||
placement="top-start"
|
||||
trigger="hover"
|
||||
:visible-arrow="false"
|
||||
popper-class="error-popover"
|
||||
:content="content">
|
||||
<template #reference>
|
||||
<span>
|
||||
<svg class="icon error-icon-tooltip" aria-hidden="true">
|
||||
<use xlink:href="#cn-icon-baocuo"></use>
|
||||
</svg>
|
||||
<!-- 为后续自定义icon插槽做预备-->
|
||||
<!-- <i v-if="icon" :class="`icon cn-icon-${icon}`"></i>-->
|
||||
</span>
|
||||
</template>
|
||||
</el-popover>
|
||||
<!-- 不使用popover实现hover,后续考虑替换为该方案-->
|
||||
<!-- <span class="new-error-icon" @mouseenter="hoverError">-->
|
||||
<!-- <svg class="icon item-popover-up" aria-hidden="true">-->
|
||||
<!-- <use xlink:href="#cn-icon-baocuo"></use>-->
|
||||
<!-- </svg>-->
|
||||
<!-- <div id="error-content" class="error-content">-->
|
||||
<!-- rview/appCompanyCyclrview/appCompanyCycleTrafficTotal?startTime=getSecond(this.timeFilter.startTime)&endTime=getSecond(this.timeFilter.endTime)&appCompanies=%27Tencent%27,%27Jingdong%27,%27Akamai%27,%27Bytedance%27,%27Baidu%27,%27Huawei%27,%27Beike%27,%27Aiqiyi%27,%27Ctrip%27,%27Meituan%27-->
|
||||
<!-- </div>-->
|
||||
<!-- </span>-->
|
||||
</div>
|
||||
|
||||
<div class="error-block-info" v-if="info !== undefined">
|
||||
<div>
|
||||
<svg class="icon error-icon-default" aria-hidden="true">
|
||||
<use xlink:href="#cn-icon-baocuo"></use>
|
||||
</svg>
|
||||
{{ content }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- start----------------调用方式----------------start -->
|
||||
<!--
|
||||
组件在全局注册了,调用时: <chart-error :content="content"></chart-error>
|
||||
-->
|
||||
<!--
|
||||
目前有三种形式,分别是default、tooltip、info
|
||||
默认,即红框展示:<chart-error :content="content" />
|
||||
在标题之后显示,需要鼠标移动到图标上显示弹窗:<chart-error tooltip :content="content" />
|
||||
文字提示:<chart-error info :content="content" />
|
||||
-->
|
||||
<!--
|
||||
自定义宽度:<chart-error width="300" :content="content" />
|
||||
自定义弹窗宽度:<chart-error tooltip width="300" :content="content" />
|
||||
注意:info模式不支持宽度设置
|
||||
-->
|
||||
<!--
|
||||
自定义icon图标:<chart-error tooltip icon="baocuo" :content="content" />,此时icon全称为'cn-icon-baocuo'
|
||||
-->
|
||||
<!-- end----------------调用方式----------------end -->
|
||||
<script>
|
||||
export default {
|
||||
name: 'Error',
|
||||
props: {
|
||||
// 工具栏提示类型
|
||||
tooltip: {
|
||||
type: String
|
||||
},
|
||||
// 文字提示类型
|
||||
info: {
|
||||
type: String
|
||||
},
|
||||
// 报错信息内容,如果不传,默认为"Error"
|
||||
content: {
|
||||
type: String,
|
||||
default: 'Error!'
|
||||
},
|
||||
// 报错信息模块宽度,如果类型选择tooltip,则为弹窗宽度,info模式没有宽度设置
|
||||
width: {
|
||||
type: String
|
||||
},
|
||||
// 报错信息模块最大宽度
|
||||
maxWidth: {
|
||||
type: String
|
||||
// default: '350'
|
||||
},
|
||||
// 自定义icon图标
|
||||
icon: {
|
||||
type: String
|
||||
},
|
||||
// 自定义svg图标
|
||||
svg: {
|
||||
type: String
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
showDefault: false, // 是否显示default,分别是default、tooltip、info
|
||||
showSmall: false, // 显示错误的类型,true为图表模块内显示报错,false为标题后显示报错
|
||||
localWidth: '',
|
||||
localMaxWidth: '',
|
||||
localPopoverWidth: ''
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.initData()
|
||||
},
|
||||
methods: {
|
||||
initData () {
|
||||
if (this.tooltip !== undefined) {
|
||||
this.showDefault = false
|
||||
this.localPopoverWidth = this.width !== undefined
|
||||
}
|
||||
|
||||
// 默认default模式
|
||||
this.showDefault = this.tooltip === undefined && this.info === undefined
|
||||
|
||||
if (this.width) {
|
||||
// 避免宽度出现负数的情况
|
||||
this.localWidth = Math.abs(parseFloat(this.width)) + 'px'
|
||||
}
|
||||
|
||||
if (this.maxWidth) {
|
||||
// 避免宽度出现负数的情况
|
||||
this.localMaxWidth = Math.abs(parseFloat(this.maxWidth)) + 'px'
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 鼠标移入事件,用于获取弹窗dom,修改距离父元素的top
|
||||
*/
|
||||
hoverError (e) {
|
||||
// const dom = document.getElementById('error-content')
|
||||
// if (dom) {
|
||||
// console.log('---', dom.clientHeight)
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div v-ele-click-outside="changeDropdown" style="position: relative;z-index: 99" class="date-range-box">
|
||||
<div v-ele-click-outside="changeDropdown" style="position: relative;z-index: 2" class="date-range-box">
|
||||
<div @click="showDropdown" class="date-range-text">
|
||||
<div class="calendar-popover-text"><i class="cn-icon cn-icon-Data"></i></div>
|
||||
<div class="calendar-popover-text" style="display: flex" v-if="isCustom">
|
||||
@@ -76,7 +76,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ref, computed } from 'vue'
|
||||
import { ref, computed, watch, reactive } from 'vue'
|
||||
import { storageKey } from '@/utils/constants'
|
||||
import { getMillisecond, timestampToList } from '@/utils/date-util'
|
||||
import { useStore } from 'vuex'
|
||||
@@ -157,6 +157,21 @@ export default {
|
||||
// refs
|
||||
const newDatePicker = ref(null)
|
||||
|
||||
// echarts框选时间范围
|
||||
const rangeEchartsData = reactive({
|
||||
value: computed(() => store.state.panel.rangeEchartsData)
|
||||
})
|
||||
|
||||
watch(() => rangeEchartsData.value, (newVal, oldVal) => {
|
||||
if (newVal) {
|
||||
myStartTime.value = getMillisecond(newVal.startTime)
|
||||
myEndTime.value = getMillisecond(newVal.endTime)
|
||||
isCustom.value = true
|
||||
dateRangeValue.value = -1
|
||||
returnValue()
|
||||
}
|
||||
})
|
||||
|
||||
// methods
|
||||
/**
|
||||
* 打开/关闭时间面板
|
||||
@@ -256,6 +271,7 @@ export default {
|
||||
myEndTime,
|
||||
dropdownFlag,
|
||||
utcStr,
|
||||
rangeEchartsData,
|
||||
address,
|
||||
dateRangeArr,
|
||||
dateRangeValue,
|
||||
|
||||
@@ -20,7 +20,8 @@ export default {
|
||||
entityDetectionStyle () {
|
||||
const route = this.$route.name !== undefined ? this.$route.name : this.$route
|
||||
if (listScrollPath.indexOf(route.path) > -1) {
|
||||
return 'overflow:auto;background-color: #EFF2F5;'
|
||||
const style = route.path === listScrollPath[0] ? 'overflow:auto;background-color: #EFF2F5;' : 'overflow:auto;'
|
||||
return style
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
<div class="cn-header">
|
||||
<div class="cn-header__banner">
|
||||
<div class="banner__left">
|
||||
<span @click="shrink" class="shrink-button" :class="{'shrink-button--collapse': showMenu}"><i class="cn-icon cn-icon-navigation"></i></span>
|
||||
<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')"/>
|
||||
</div>
|
||||
<!--个人操作-->
|
||||
@@ -12,23 +13,27 @@
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item>
|
||||
<div id="header-to-english" :style="language === 'en'?'color:#0091ff':''" @click="changeLocal('en')">English</div>
|
||||
<div id="header-to-english" :style="language === 'en'?'color:#0091ff':''" @click="changeLocal('en')">
|
||||
English
|
||||
</div>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item>
|
||||
<div id="header-to-chinese" :style="language === 'cn'?'color:#0091ff':''" @click="changeLocal('cn')">中文</div>
|
||||
<div id="header-to-chinese" :style="language === 'cn'?'color:#0091ff':''" @click="changeLocal('cn')">
|
||||
中文
|
||||
</div>
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<el-dropdown>
|
||||
<div class='login-user header-menu--item'>{{username}} <i class="cn-icon cn-icon-arrow-down"></i></div>
|
||||
<div class='login-user header-menu--item'>{{ username }} <i class="cn-icon cn-icon-arrow-down"></i></div>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item>
|
||||
<div id="header-to-changepin" @click="showPinDialog">{{$t('overall.changePassword')}}</div>
|
||||
<div id="header-to-changepin" @click="showPinDialog">{{ $t('overall.changePassword') }}</div>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item>
|
||||
<div id="header-to-logout" @click="logout">{{$t('overall.logout')}}</div>
|
||||
<div id="header-to-logout" @click="logout">{{ $t('overall.logout') }}</div>
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
@@ -37,8 +42,9 @@
|
||||
</div>
|
||||
<div class="cn-header__nav">
|
||||
<i class="cn-icon cn-icon-a-NetworkAnalytics"></i>
|
||||
<el-breadcrumb class="header__left-breadcrumb" separator=">">
|
||||
<el-breadcrumb-item class="header__left-breadcrumb-item" :id="`breadcrumb${item}`" :title="item" v-for="(item,index) in breadcrumb" :key="item">
|
||||
<el-breadcrumb class="header__left-breadcrumb" :separator="route.indexOf('detection') === -1 ? '>' : ''">
|
||||
<el-breadcrumb-item class="header__left-breadcrumb-item" :id="`breadcrumb${item}`" :title="item"
|
||||
v-for="(item,index) in breadcrumb" :key="item">
|
||||
<template v-if="index===3">
|
||||
<div class="header__left-breadcrumb-item-select">
|
||||
<el-popover placement="bottom-start"
|
||||
@@ -52,16 +58,17 @@
|
||||
@hide="hideBreadcrumbPopover()"
|
||||
trigger="click">
|
||||
<template #reference>
|
||||
<div class="breadcrumb-button" id="breadcrumbButton" :class="showBackground?'breadcrumb-button__active':''" >
|
||||
<span id="breadcrumbValue">
|
||||
<div class="breadcrumb-button" id="breadcrumbButton"
|
||||
:class="showBackground?'breadcrumb-button__active':''">
|
||||
<span id="breadcrumbValue">
|
||||
<template v-if="curTabProp === 'qtype'">
|
||||
<span>{{dnsQtypeMapData.get(item) ? dnsQtypeMapData.get(item):item}}</span>
|
||||
<span>{{ dnsQtypeMapData.get(item)}}</span>
|
||||
</template>
|
||||
<template v-else-if="curTabProp === 'rcode'">
|
||||
<span>{{dnsRcodeMapData.get(item) ? dnsRcodeMapData.get(item):item}}</span>
|
||||
<span>{{ dnsRcodeMapData.get(item)}}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span>{{item}}</span>
|
||||
<span>{{ item }}</span>
|
||||
</template>
|
||||
</span><i class="cn-icon-xiala cn-icon"></i>
|
||||
</div>
|
||||
@@ -73,16 +80,17 @@
|
||||
v-model="dropDownValue"
|
||||
@input="dropDownSearch"></el-input>
|
||||
</div>
|
||||
<ul class="select-dropdown" id="breadcrumbSelectDropdown" @scroll="scrollList()">
|
||||
<li v-for="item in breadcrumbColumnValueListShow" title='' :key="item" :id="item" class="select-dropdown__item" @click="changeValue(item)" :class="selected?'':''">
|
||||
<ul class="select-dropdown" id="breadcrumbSelectDropdown" @scroll="scrollList()">
|
||||
<li v-for="item in breadcrumbColumnValueListShow" title='' :key="item" :id="item"
|
||||
class="select-dropdown__item" @click="changeValue(item)" :class="selected?'':''">
|
||||
<template v-if="curTabProp === 'qtype'">
|
||||
<span>{{dnsQtypeMapData.get(item) ? dnsQtypeMapData.get(item):item}}</span>
|
||||
<span>{{ dnsQtypeMapData.get(item) }}</span>
|
||||
</template>
|
||||
<template v-else-if="curTabProp === 'rcode'">
|
||||
<span>{{dnsRcodeMapData.get(item) ? dnsRcodeMapData.get(item):item}}</span>
|
||||
<span>{{ dnsRcodeMapData.get(item) }}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<span>{{item}}</span>
|
||||
<span>{{ item }}</span>
|
||||
</template>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -91,38 +99,39 @@
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="index===2">
|
||||
<span v-if="route===wholeScreenRouterMapping.dns" >{{$t(item)}}</span>
|
||||
<span v-else class="route-menu" @click="jump(route,item,'',3)">{{$t(item)}}</span>
|
||||
<span v-if="route===wholeScreenRouterMapping.dns">{{ $t(item) }}</span>
|
||||
<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">{{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)"
|
||||
v-if="route.indexOf('detection') === -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>-->
|
||||
</template>
|
||||
<template v-else>
|
||||
<span>{{item}}</span>
|
||||
<span>{{ item }}</span>
|
||||
</template>
|
||||
</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
@@ -140,22 +149,26 @@
|
||||
<div class="cn-menu__left">
|
||||
<div class="left-menu" v-for="menu in otherMenu" :key="menu.id" @click="jump(menu.route,'','',0)">
|
||||
<i :class="menu.icon"></i>
|
||||
<span>{{$t(menu.i18n || menu.name)}}</span>
|
||||
<span>{{ $t(menu.i18n || menu.name) }}</span>
|
||||
<i class="cn-icon cn-icon-right"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cn-menu__middle">
|
||||
<div class="middle-menus middle-menus--network-analytics">
|
||||
<div class="middle-menus__header">{{$t('overall.networkAnalytics')}}</div>
|
||||
<div class="middle-menus__header">{{ $t('overall.networkAnalytics') }}</div>
|
||||
<div class="middle-menus__body">
|
||||
<div style="width: 260px;">
|
||||
<template v-for="(menu, index) in networkAnalyticsMenu.children" :key="index">
|
||||
<div class="middle-menu" v-if="index < 5" @click="jump(menu.route,'','',2)">{{$t(menu.i18n || menu.name)}}</div>
|
||||
<div class="middle-menu" v-if="index < 5" @click="jump(menu.route,'','',2)">
|
||||
{{ $t(menu.i18n || menu.name) }}
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div>
|
||||
<template v-for="(menu, index) in networkAnalyticsMenu.children" :key="index">
|
||||
<div class="middle-menu" v-if="index >= 5 && index < 10" @click="jump(menu.route,'','',2)">{{$t(menu.i18n || menu.name)}}</div>
|
||||
<div class="middle-menu" v-if="index >= 5 && index < 10" @click="jump(menu.route,'','',2)">
|
||||
{{ $t(menu.i18n || menu.name) }}
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
@@ -167,12 +180,12 @@
|
||||
<el-dialog v-model="showChangePin"
|
||||
width="30%"
|
||||
:before-close="handleClose">
|
||||
<el-form :rules="changePassFormRules" :model="changePassForm" ref="changePassForm">
|
||||
<el-form :rules="changePassFormRules" :model="changePassForm" ref="changePassForm">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item :label="$t('overall.currentPassword')" prop="oldPwd">
|
||||
<el-input v-model="changePassForm.oldPwd" type="password"></el-input>
|
||||
</el-form-item>
|
||||
<el-col :span="24">
|
||||
<el-form-item :label="$t('overall.currentPassword')" prop="oldPwd">
|
||||
<el-input v-model="changePassForm.oldPwd" type="password"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item :label="$t('overall.newPassword')" prop="newPwd">
|
||||
@@ -188,8 +201,8 @@
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="showChangePin = false">{{$t('overall.cancel')}}</el-button>
|
||||
<el-button type="primary" @click="submit">{{$t('overall.update')}}</el-button>
|
||||
<el-button @click="showChangePin = false">{{ $t('overall.cancel') }}</el-button>
|
||||
<el-button type="primary" @click="submit">{{ $t('overall.update') }}</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
@@ -197,14 +210,10 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { useRoute } from 'vue-router'
|
||||
import { get, put } from '@/utils/http'
|
||||
import {
|
||||
curTabState,
|
||||
dbDrilldownTableConfig,
|
||||
entityType,
|
||||
networkOverviewSearchUrl,
|
||||
networkOverviewTabList,
|
||||
networkTable,
|
||||
operationType,
|
||||
storageKey,
|
||||
@@ -213,9 +222,17 @@ import {
|
||||
} from '@/utils/constants'
|
||||
import { api } from '@/utils/api'
|
||||
import { ref } from 'vue'
|
||||
import { combineTabList, getDefaultCurTab, getTabList, overwriteUrl, urlParamsHandler, combinDrilldownTableWithUserConfig,getDnsMapData } from '@/utils/tools'
|
||||
import {
|
||||
combineTabList,
|
||||
getDefaultCurTab,
|
||||
getTabList,
|
||||
overwriteUrl,
|
||||
urlParamsHandler,
|
||||
combinDrilldownTableWithUserConfig,
|
||||
getDnsMapData,
|
||||
handleSpecialValue
|
||||
} from '@/utils/tools'
|
||||
import { getNowTime, getSecond } from '@/utils/date-util'
|
||||
import { db } from '@/indexedDB'
|
||||
|
||||
export default {
|
||||
name: 'Header',
|
||||
@@ -238,17 +255,32 @@ export default {
|
||||
newPwd2: ''
|
||||
},
|
||||
changePassFormRules: {
|
||||
oldPwd: [{ required: true, message: this.$t('validate.required'), trigger: 'blur' }],
|
||||
newPwd: [{ required: true, message: this.$t('validate.required'), trigger: 'blur' }],
|
||||
newPwd2: [{ required: true, message: this.$t('validate.required'), trigger: 'blur' }, { validator: passwordComparison, trigger: 'blur' }]
|
||||
oldPwd: [{
|
||||
required: true,
|
||||
message: this.$t('validate.required'),
|
||||
trigger: 'blur'
|
||||
}],
|
||||
newPwd: [{
|
||||
required: true,
|
||||
message: this.$t('validate.required'),
|
||||
trigger: 'blur'
|
||||
}],
|
||||
newPwd2: [{
|
||||
required: true,
|
||||
message: this.$t('validate.required'),
|
||||
trigger: 'blur'
|
||||
}, {
|
||||
validator: passwordComparison,
|
||||
trigger: 'blur'
|
||||
}]
|
||||
},
|
||||
showMenu: false,
|
||||
dropDownValue: '',
|
||||
breadcrumbColumnValueListShow: [],
|
||||
curTabProp:'',
|
||||
dnsRcodeMapData:[],
|
||||
dnsQtypeMapData:[],
|
||||
isDnsMapType:false,
|
||||
curTabProp: '',
|
||||
dnsRcodeMapData: new Map(),
|
||||
dnsQtypeMapData: new Map(),
|
||||
isDnsMapType: false,
|
||||
valueMeta: [],
|
||||
showBackground: false,
|
||||
selected: false,
|
||||
@@ -297,10 +329,21 @@ export default {
|
||||
this.curTabProp = this.$route.query.dimensionType ? this.$route.query.dimensionType : null
|
||||
this.$store.getters.menuList.forEach(menu => {
|
||||
if (this.$_.isEmpty(menu.children) && menu.route) {
|
||||
breadcrumbMap.push({ name: this.$t(menu.i18n), path: menu.route, columnName: menu.columnName, columnValue: menu.columnValue })
|
||||
breadcrumbMap.push({
|
||||
name: this.$t(menu.i18n),
|
||||
path: menu.route,
|
||||
columnName: menu.columnName,
|
||||
columnValue: menu.columnValue
|
||||
})
|
||||
} else if (!this.$_.isEmpty(menu.children)) {
|
||||
menu.children.forEach(child => {
|
||||
breadcrumbMap.push({ name: child.i18n ? this.$t(child.i18n) : child.name, parentName: menu.i18n ? this.$t(menu.i18n) : menu.name, path: child.route, columnName: child.columnName, columnValue: child.columnValue })
|
||||
breadcrumbMap.push({
|
||||
name: child.i18n ? this.$t(child.i18n) : child.name,
|
||||
parentName: menu.i18n ? this.$t(menu.i18n) : menu.name,
|
||||
path: child.route,
|
||||
columnName: child.columnName,
|
||||
columnValue: child.columnValue
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -339,14 +382,24 @@ export default {
|
||||
},
|
||||
async mounted () {
|
||||
this.from = Object.keys(this.entityType)[0]
|
||||
this.dnsQtypeMapData = await getDnsMapData('dnsQtype')
|
||||
this.dnsRcodeMapData = await getDnsMapData('dnsRcode')
|
||||
// 是否需要dns的qtype和rcode的数据字典
|
||||
if(this.$route.params.typeName === fromRoute.dnsServiceInsights) {
|
||||
this.dnsQtypeMapData = await getDnsMapData('dnsQtype')
|
||||
this.dnsRcodeMapData = await getDnsMapData('dnsRcode')
|
||||
}
|
||||
this.initDropdownList()
|
||||
},
|
||||
setup () {
|
||||
const dateRangeValue = 60
|
||||
const { startTime, endTime } = getNowTime(dateRangeValue)
|
||||
const chartTimeFilter = ref({ startTime, endTime, dateRangeValue })
|
||||
const {
|
||||
startTime,
|
||||
endTime
|
||||
} = getNowTime(dateRangeValue)
|
||||
const chartTimeFilter = ref({
|
||||
startTime,
|
||||
endTime,
|
||||
dateRangeValue
|
||||
})
|
||||
return {
|
||||
chartTimeFilter,
|
||||
entityType // 所有entity类型,用于header下拉框选择
|
||||
@@ -377,25 +430,25 @@ export default {
|
||||
window.location.reload()
|
||||
})
|
||||
},
|
||||
getCurTabByLabel(label){
|
||||
getCurTabByLabel (label) {
|
||||
let curTab = null
|
||||
let tableType = this.$route.params ? this.$route.params.typeName : 'networkOverview'
|
||||
let curTableInCode = networkTable[tableType] ? networkTable[tableType] : networkTable.networkOverview
|
||||
const tableType = this.$route.params ? this.$route.params.typeName : 'networkOverview'
|
||||
const curTableInCode = networkTable[tableType] ? networkTable[tableType] : networkTable.networkOverview
|
||||
if (curTableInCode && curTableInCode.tabList) {
|
||||
curTab = curTableInCode.tabList.find(item => item.label == label)
|
||||
}
|
||||
return curTab
|
||||
},
|
||||
async initDropdownList () {
|
||||
//是否需要dns的qtype和rcode的数据字典
|
||||
// 是否需要dns的qtype和rcode的数据字典
|
||||
this.curTabProp = this.$route.query.dimensionType ? this.$route.query.dimensionType : null
|
||||
let currentValue = document.getElementById('breadcrumbValue') ? document.getElementById('breadcrumbValue').innerText : ''
|
||||
let columnName = this.getUrlParam(this.curTabState.thirdMenu, '')
|
||||
const currentValue = document.getElementById('breadcrumbValue') ? document.getElementById('breadcrumbValue').innerText : ''
|
||||
const columnName = this.getUrlParam(this.curTabState.thirdMenu, '')
|
||||
let type = 'ip'
|
||||
let tableType = this.$route.params ? this.$route.params.typeName : 'networkOverview'
|
||||
let curTableInCode = networkTable[tableType] ? networkTable[tableType] : networkTable.networkOverview
|
||||
const tableType = this.$route.params ? this.$route.params.typeName : 'networkOverview'
|
||||
const curTableInCode = networkTable[tableType] ? networkTable[tableType] : networkTable.networkOverview
|
||||
if (curTableInCode && curTableInCode.tabList) {
|
||||
let curTab = curTableInCode.tabList.find(item => item.label == columnName)
|
||||
const curTab = curTableInCode.tabList.find(item => item.label == columnName)
|
||||
if (curTab) {
|
||||
type = curTab.prop
|
||||
}
|
||||
@@ -410,16 +463,18 @@ export default {
|
||||
get(curTableInCode.url.drilldownList, params).then(async response => {
|
||||
if (response.code === 200) {
|
||||
this.breadcrumbColumnValueListShow = response.data.result
|
||||
this.dnsQtypeMapData = await getDnsMapData('dnsQtype')
|
||||
this.dnsRcodeMapData = await getDnsMapData('dnsRcode')
|
||||
if(this.from === fromRoute.dnsServiceInsights) {
|
||||
this.dnsQtypeMapData = await getDnsMapData('dnsQtype')
|
||||
this.dnsRcodeMapData = await getDnsMapData('dnsRcode')
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
this.breadcrumbColumnValueListShow.forEach(item => {
|
||||
const selectedDom = document.getElementById(item)
|
||||
if (selectedDom) {
|
||||
let itemName = item
|
||||
if(this.curTabProp === 'qtype'){
|
||||
if (this.curTabProp === 'qtype') {
|
||||
itemName = this.dnsQtypeMapData.get(item)
|
||||
}else if(this.curTabProp === 'rcode'){
|
||||
} else if (this.curTabProp === 'rcode') {
|
||||
itemName = this.dnsRcodeMapData.get(item)
|
||||
}
|
||||
if (itemName === currentValue) {
|
||||
@@ -454,34 +509,31 @@ export default {
|
||||
changeValue (value) {
|
||||
// 设置面包屑显示的内容及hover时的title
|
||||
let valName = value
|
||||
if(this.tab === 'qtype'){
|
||||
valName =this.dnsQtypeMapData.get(value)
|
||||
}else if(this.tab === 'rcode'){
|
||||
valName =this.dnsRcodeMapData.get(value)
|
||||
if (this.tab === 'qtype') {
|
||||
valName = this.dnsQtypeMapData.get(value)
|
||||
} else if (this.tab === 'rcode') {
|
||||
valName = this.dnsRcodeMapData.get(value)
|
||||
}
|
||||
this.curTabProp = this.$route.query.dimensionType ? this.$route.query.dimensionType : null
|
||||
document.getElementById('breadcrumbValue').innerText = value
|
||||
//document.getElementById('breadcrumbButton').setAttribute('title', valName)
|
||||
document.getElementById(this.valueMenuId).setAttribute('title', valName)
|
||||
document.getElementById('breadcrumbButton').click()
|
||||
// const columnName = this.$store.getters.getBreadcrumbColumnName
|
||||
const columnName = this.getUrlParam(this.curTabState.thirdMenu, '')
|
||||
//const tabObjGroup = networkOverviewTabList.filter(item => item.label == columnName)
|
||||
let curTab = this.getCurTabByLabel()
|
||||
const curTab = this.getCurTabByLabel(columnName)
|
||||
if (curTab) {
|
||||
const queryCondition = []
|
||||
const searchProps = curTab.dillDownProp
|
||||
if (curTab.prop === 'protocolPort') {
|
||||
const valueGroup = value.split(':')
|
||||
if (valueGroup) {
|
||||
queryCondition.push("common_l7_protocol='" + valueGroup[0] + "'")
|
||||
queryCondition.push('common_l7_protocol=\'' + valueGroup[0] + '\'')
|
||||
queryCondition.push('common_server_port=' + valueGroup[1])
|
||||
}
|
||||
console.log(queryCondition.join(' AND '))
|
||||
this.urlChangeParams[this.curTabState.queryCondition] = queryCondition.join(' AND ')
|
||||
} else {
|
||||
searchProps.forEach(item => {
|
||||
queryCondition.push(item + "='" + value.replaceAll("'", "\\\\'") + "'")
|
||||
queryCondition.push(item + '=\'' + handleSpecialValue(value) + '\'')
|
||||
})
|
||||
this.urlChangeParams[this.curTabState.queryCondition] = queryCondition.join(' OR ')
|
||||
}
|
||||
@@ -495,7 +547,10 @@ export default {
|
||||
submit () {
|
||||
this.$refs.changePassForm.validate((valid) => {
|
||||
if (valid) {
|
||||
put(api.pin, { oldPin: this.changePassForm.oldPwd, newPin: this.changePassForm.newPwd }).then(res => {
|
||||
put(api.pin, {
|
||||
oldPin: this.changePassForm.oldPwd,
|
||||
newPin: this.changePassForm.newPwd
|
||||
}).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.$message.success('Success')
|
||||
this.showChangePin = false
|
||||
@@ -517,7 +572,7 @@ export default {
|
||||
this.urlChangeParams = {}
|
||||
},
|
||||
async handleCurDrilldownTableConfig (thirdMenu, fourthMenu) {
|
||||
const userId = localStorage.getItem(storageKey.userId)
|
||||
// const userId = localStorage.getItem(storageKey.userId)
|
||||
const tableType = this.$route.params ? this.$route.params.typeName : 'networkOverview'
|
||||
const drillDownTableConfigs = await combinDrilldownTableWithUserConfig()
|
||||
const currentTableConfig = drillDownTableConfigs.find(config => config.route === tableType)
|
||||
@@ -546,7 +601,9 @@ export default {
|
||||
this.urlChangeParams[this.curTabState.tabOperationBeforeType] = this.getUrlParam(this.curTabState.tabOperationType, '', true)
|
||||
this.urlChangeParams[this.curTabState.tabOperationType] = opeType
|
||||
if (opeType === 3) {
|
||||
this.urlChangeParams.queryCondition = ''
|
||||
if (route !== '/panel/networkOverview') {
|
||||
this.urlChangeParams.queryCondition = ''
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.urlChangeParams[this.curTabState.tabOperationType] = operationType.mainMenu
|
||||
@@ -564,18 +621,18 @@ export default {
|
||||
child.columnName = columnName
|
||||
this.urlChangeParams[this.curTabState.thirdMenu] = columnName
|
||||
this.urlChangeParams[this.curTabState.fourthMenu] = columnValue
|
||||
//const tabObjGroup = networkOverviewTabList.filter(item => item.label == columnName)
|
||||
//let curTab = this.getCurTabByLabel()
|
||||
//const type = curTab ? curTab.prop : ''
|
||||
//this.curTabProp = this.$route.query.dimensionType ? this.$route.query.dimensionType : null
|
||||
//this.urlChangeParams[this.curTabState.dimensionType] = type
|
||||
// const tabObjGroup = networkOverviewTabList.filter(item => item.label == columnName)
|
||||
// let curTab = this.getCurTabByLabel()
|
||||
// const type = curTab ? curTab.prop : ''
|
||||
// this.curTabProp = this.$route.query.dimensionType ? this.$route.query.dimensionType : null
|
||||
// this.urlChangeParams[this.curTabState.dimensionType] = type
|
||||
this.urlChangeParams[this.curTabState.panelName] = columnValue
|
||||
} else if (columnName) { // 点击的为列名
|
||||
child.columnValue = ''
|
||||
child.columnName = columnName
|
||||
this.urlChangeParams[this.curTabState.thirdMenu] = columnName
|
||||
this.urlChangeParams[this.curTabState.fourthMenu] = ''
|
||||
this.urlChangeParams[this.curTabState.panelName] = columnValue
|
||||
this.urlChangeParams[this.curTabState.panelName] = columnName
|
||||
const tableType = this.$route.params ? this.$route.params.typeName : 'networkOverview'
|
||||
const metric = this.getUrlParam(this.curTabState.tableMetric, 'Bits/s')
|
||||
const curTab = getDefaultCurTab(tableType, metric, columnName)
|
||||
@@ -605,11 +662,20 @@ export default {
|
||||
})
|
||||
} else if (opeType === 3) {
|
||||
this.$router.push({
|
||||
query: { ...this.$route.query, fourthPanel: '', t: +new Date() }
|
||||
query: {
|
||||
...this.$route.query,
|
||||
fourthPanel: '',
|
||||
t: +new Date()
|
||||
}
|
||||
})
|
||||
} else if (opeType != 4) {
|
||||
this.$router.push({
|
||||
query: { ...this.$route.query, fourthPanel: '', thirdPanel: '', t: +new Date() }
|
||||
query: {
|
||||
...this.$route.query,
|
||||
fourthPanel: '',
|
||||
thirdPanel: '',
|
||||
t: +new Date()
|
||||
}
|
||||
})
|
||||
}
|
||||
if (route === this.route) {
|
||||
|
||||
@@ -20,6 +20,7 @@ import bus from 'tiny-emitter'
|
||||
import DateTimeRange from '@/components/common/TimeRange/DateTimeRange'
|
||||
import TimeRefresh from '@/components/common/TimeRange/TimeRefresh'
|
||||
import PanelChartList from '@/views/charts/PanelChartList'
|
||||
import Error from '@/components/common/Error'
|
||||
import 'lib-flexible'
|
||||
|
||||
const emitter = new bus()
|
||||
@@ -46,6 +47,7 @@ app.mixin(commonMixin)
|
||||
app.component('date-time-range', DateTimeRange)
|
||||
app.component('time-refresh', TimeRefresh)
|
||||
app.component('panel-chart-list', PanelChartList)
|
||||
app.component('chart-error', Error)
|
||||
|
||||
app.mount('#app')
|
||||
|
||||
|
||||
@@ -55,7 +55,11 @@ const panel = {
|
||||
timeRangeArray: [], // 时间范围列表:开始/结束时间
|
||||
timeRangeFlag: null, // 时间范围标志,默认60即一小时,-1为手动选择的时间范围
|
||||
routerPath: '', // 当前路由路径
|
||||
httpCancel: null // 终止http请求
|
||||
httpCancel: null, // 终止http请求
|
||||
rangeEchartsData: {}, // 框选echarts图表
|
||||
routerHistoryList: [], // 路由跳转记录列表
|
||||
dnsQtypeMapData:[],
|
||||
dnsRcodeMapData:[]
|
||||
},
|
||||
mutations: {
|
||||
setShowRightBox (state, flag) {
|
||||
@@ -106,36 +110,15 @@ const panel = {
|
||||
setCurrentMap (state, currentMap) {
|
||||
state.currentMap = currentMap
|
||||
},
|
||||
// setPanelName (state, panelName) {
|
||||
// state.panelName = panelName
|
||||
// },
|
||||
// setBreadcrumbColumnName (state, breadcrumbColumnName) {
|
||||
// state.breadcrumbColumnName = breadcrumbColumnName
|
||||
// },
|
||||
// setDimensionType (state, dimensionType) {
|
||||
// state.dimensionType = dimensionType
|
||||
// },
|
||||
// setBreadcrumbColumnValue (state, breadcrumbColumnValue) {
|
||||
// state.breadcrumbColumnValue = breadcrumbColumnValue
|
||||
// },
|
||||
// setNetworkOverviewCurrentTab (state, networkOverviewCurrentTab) {
|
||||
// state.networkOverviewCurrentTab = networkOverviewCurrentTab
|
||||
// },
|
||||
// setQueryCondition (state, queryCondition) {
|
||||
// state.queryCondition = queryCondition
|
||||
// },
|
||||
setDnsQtypeMapData (state, dnsQtypeMapData) {
|
||||
state.dnsQtypeMapData = dnsQtypeMapData
|
||||
},
|
||||
setDnsRcodeMapData (state, dnsRcodeMapData) {
|
||||
state.dnsRcodeMapData = dnsRcodeMapData
|
||||
},
|
||||
setNetworkOverviewTabList (state, networkOverviewTabList) {
|
||||
state.networkOverviewTabList = networkOverviewTabList
|
||||
},
|
||||
// setTabOperationType (state, tabOperationType) {
|
||||
// state.tabOperationType = tabOperationType
|
||||
// },
|
||||
// setNetworkOverviewBeforeTab (state, networkOverviewBeforeTab) {
|
||||
// state.networkOverviewBeforeTab = networkOverviewBeforeTab
|
||||
// },
|
||||
// setTabOperationBeforeType (state, tabOperationBeforeType) {
|
||||
// state.tabOperationBeforeType = tabOperationBeforeType
|
||||
// },
|
||||
setNpmLocationCountry (state, country) {
|
||||
state.npmLocationCountry = country
|
||||
},
|
||||
@@ -162,6 +145,12 @@ const panel = {
|
||||
},
|
||||
setHttpCancel (state, cancel) {
|
||||
state.httpCancel = cancel
|
||||
},
|
||||
setRangeEchartsData (state, data) {
|
||||
state.rangeEchartsData = data
|
||||
},
|
||||
setRouterHistoryList (state, list) {
|
||||
state.routerHistoryList = list
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
@@ -207,36 +196,15 @@ const panel = {
|
||||
getCurrentMap (state) {
|
||||
return state.currentMap
|
||||
},
|
||||
// getPanelName (state) {
|
||||
// return state.panelName
|
||||
// },
|
||||
// getBreadcrumbColumnName (state) {
|
||||
// return state.breadcrumbColumnName
|
||||
// },
|
||||
// getDimensionType (state) {
|
||||
// return state.dimensionType
|
||||
// },
|
||||
// getBreadcrumbColumnValue (state) {
|
||||
// return state.breadcrumbColumnValue
|
||||
// },
|
||||
// getNetworkOverviewCurrentTab (state) {
|
||||
// return state.networkOverviewCurrentTab
|
||||
// },
|
||||
// getQueryCondition (state) {
|
||||
// return state.queryCondition
|
||||
// },
|
||||
getDnsQtypeMapData (state) {
|
||||
return state.dnsQtypeMapData
|
||||
},
|
||||
getDnsRcodeMapData (state) {
|
||||
return state.dnsRcodeMapData
|
||||
},
|
||||
getNetworkOverviewTabList (state) {
|
||||
return state.networkOverviewTabList
|
||||
},
|
||||
// getTabOperationType (state) {
|
||||
// return state.tabOperationType
|
||||
// },
|
||||
// getNetworkOverviewBeforeTab (state) {
|
||||
// return state.networkOverviewBeforeTab
|
||||
// },
|
||||
// getTabOperationBeforeType (state) {
|
||||
// return state.tabOperationBeforeType
|
||||
// },
|
||||
getNpmLocationCountry (state) {
|
||||
return state.npmLocationCountry
|
||||
},
|
||||
@@ -254,6 +222,9 @@ const panel = {
|
||||
},
|
||||
getRouterPath (state) {
|
||||
return state.routerPath
|
||||
},
|
||||
getRouterHistoryList (state) {
|
||||
return state.routerHistoryList
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
|
||||
@@ -3,7 +3,7 @@ import router from '@/router'
|
||||
import { sortByOrderNum, getWelcomeMenu } from '@/permission'
|
||||
import { ElMessage } from 'element-plus' // dependent on utc plugin
|
||||
import { storageKey, dbDrilldownTableConfig } from '@/utils/constants'
|
||||
import { readDrilldownTableConfigByUser } from '@/utils/tools'
|
||||
import { getConfigVersion } from '@/utils/tools'
|
||||
import { api } from '@/utils/api'
|
||||
import { db } from '@/indexedDB'
|
||||
|
||||
@@ -94,8 +94,14 @@ const user = {
|
||||
const defaultConfigs = JSON.parse(res.page.list[0].cvalue)
|
||||
await db[dbDrilldownTableConfig].put({
|
||||
id: 'default',
|
||||
config: defaultConfigs
|
||||
version: defaultConfigs.version,
|
||||
config: defaultConfigs.config
|
||||
})
|
||||
let userId = localStorage.getItem(storageKey.userId)
|
||||
let oldVersion = await getConfigVersion(userId)
|
||||
if(oldVersion !== defaultConfigs.version ){
|
||||
db[dbDrilldownTableConfig].delete(userId)
|
||||
}
|
||||
}
|
||||
})
|
||||
get(api.config, { ckey: 'link_info' }).then(res => {
|
||||
|
||||
@@ -172,6 +172,8 @@ export const api = {
|
||||
trafficGraph: '/interface/application/performance/overview/drilldown/drilldown/dimension/trafficGraph',
|
||||
// 各维度下钻网络性能
|
||||
networkAnalysis: '/interface/application/performance/overview/drilldown/dimension/networkAnalysis',
|
||||
// 各维度下钻网络性能 三级菜单
|
||||
allNetworkAnalysis: '/interface/application/performance/overview/drilldown/dimension/allNetworkAnalysis',
|
||||
// 下钻地图
|
||||
map: '/interface/application/performance/overview/drilldown/dimension/clientLocations/world/trafficAnalysis',
|
||||
mapTcp: '/interface/application/performance/overview/drilldown/dimension/clientLocations/world/tcpSessionDelay',
|
||||
|
||||
@@ -291,7 +291,8 @@ export const curTabState = {
|
||||
fourthPanel: 'fourthPanel',
|
||||
networkOverviewBeforeTab: 'networkOverviewBeforeTab',
|
||||
tabOperationType: 'tabOperationType',
|
||||
tabOperationBeforeType: 'tabOperationBeforeType'
|
||||
tabOperationBeforeType: 'tabOperationBeforeType',
|
||||
tabIndex: 'tabIndex'
|
||||
}
|
||||
|
||||
export const scoreUrl = [
|
||||
@@ -652,6 +653,118 @@ export const networkOverviewTabList = [
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.networkOverview
|
||||
}, {
|
||||
label: 'network.clientIps',
|
||||
prop: 'clientIp',
|
||||
queryCycleTotalProp: 'clientIps',
|
||||
dillDownProp: ['common_client_ip'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.networkOverview
|
||||
}, {
|
||||
label: 'network.serverIps',
|
||||
prop: 'serverIp',
|
||||
queryCycleTotalProp: 'serverIps',
|
||||
dillDownProp: ['common_server_ip'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.networkOverview
|
||||
}, {
|
||||
label: 'network.clientCountries',
|
||||
prop: 'clientCountry',
|
||||
queryCycleTotalProp: 'clientCountries',
|
||||
dillDownProp: ['client_country'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.networkOverview
|
||||
}, {
|
||||
label: 'network.serverCountries',
|
||||
prop: 'serverCountry',
|
||||
queryCycleTotalProp: 'serverCountries',
|
||||
dillDownProp: ['server_country'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.networkOverview
|
||||
}, {
|
||||
label: 'network.clientProvinces',
|
||||
prop: 'clientProvince',
|
||||
queryCycleTotalProp: 'clientProvinces',
|
||||
dillDownProp: ['client_province'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.networkOverview
|
||||
}, {
|
||||
label: 'network.serverProvinces',
|
||||
prop: 'serverProvince',
|
||||
queryCycleTotalProp: 'serverProvinces',
|
||||
dillDownProp: ['server_province'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.networkOverview
|
||||
}, {
|
||||
label: 'network.clientCities',
|
||||
prop: 'clientCity',
|
||||
queryCycleTotalProp: 'clientCities',
|
||||
dillDownProp: ['client_region'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.networkOverview
|
||||
}, {
|
||||
label: 'network.serverCities',
|
||||
prop: 'serverCity',
|
||||
queryCycleTotalProp: 'serverCities',
|
||||
dillDownProp: ['server_region'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.networkOverview
|
||||
}, {
|
||||
label: 'network.clientIsps',
|
||||
prop: 'clientIsp',
|
||||
queryCycleTotalProp: 'clientIsps',
|
||||
dillDownProp: ['client_isp'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.networkOverview
|
||||
}, {
|
||||
label: 'network.serverIsps',
|
||||
prop: 'serverIsp',
|
||||
queryCycleTotalProp: 'serverIsps',
|
||||
dillDownProp: ['server_isp'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.networkOverview
|
||||
}, {
|
||||
label: 'network.clientIdcRenters',
|
||||
prop: 'clientIdcRenter',
|
||||
queryCycleTotalProp: 'clientIdcRenters',
|
||||
dillDownProp: ['client_idc_renter'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.networkOverview
|
||||
}, {
|
||||
label: 'network.serverIdcRenters',
|
||||
prop: 'serverIdcRenter',
|
||||
queryCycleTotalProp: 'serverIdcRenters',
|
||||
dillDownProp: ['server_idc_renter'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.networkOverview
|
||||
}, {
|
||||
label: 'network.clientAsns',
|
||||
prop: 'clientAsn',
|
||||
queryCycleTotalProp: 'clientAsns',
|
||||
dillDownProp: ['client_asn'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.networkOverview
|
||||
}, {
|
||||
label: 'network.serverAsns',
|
||||
prop: 'serverAsn',
|
||||
queryCycleTotalProp: 'serverAsns',
|
||||
dillDownProp: ['server_asn'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.networkOverview
|
||||
}
|
||||
]
|
||||
|
||||
@@ -784,6 +897,118 @@ export const networkAppPerformanceTabList = [
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.npmOverviewCommon
|
||||
}, {
|
||||
label: 'network.clientIps',
|
||||
prop: 'clientIp',
|
||||
queryCycleTotalProp: 'clientIps',
|
||||
dillDownProp: ['common_client_ip'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.npmOverviewCommon
|
||||
}, {
|
||||
label: 'network.serverIps',
|
||||
prop: 'serverIp',
|
||||
queryCycleTotalProp: 'serverIps',
|
||||
dillDownProp: ['common_server_ip'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.npmOverviewCommon
|
||||
}, {
|
||||
label: 'network.clientCountries',
|
||||
prop: 'clientCountry',
|
||||
queryCycleTotalProp: 'clientCountries',
|
||||
dillDownProp: ['client_country'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.npmOverviewCommon
|
||||
}, {
|
||||
label: 'network.serverCountries',
|
||||
prop: 'serverCountry',
|
||||
queryCycleTotalProp: 'serverCountries',
|
||||
dillDownProp: ['server_country'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.npmOverviewCommon
|
||||
}, {
|
||||
label: 'network.clientProvinces',
|
||||
prop: 'clientProvince',
|
||||
queryCycleTotalProp: 'clientProvinces',
|
||||
dillDownProp: ['client_province'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.npmOverviewCommon
|
||||
}, {
|
||||
label: 'network.serverProvinces',
|
||||
prop: 'serverProvince',
|
||||
queryCycleTotalProp: 'serverProvinces',
|
||||
dillDownProp: ['server_province'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.npmOverviewCommon
|
||||
}, {
|
||||
label: 'network.clientCities',
|
||||
prop: 'clientCity',
|
||||
queryCycleTotalProp: 'clientCities',
|
||||
dillDownProp: ['client_region'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.npmOverviewCommon
|
||||
}, {
|
||||
label: 'network.serverCities',
|
||||
prop: 'serverCity',
|
||||
queryCycleTotalProp: 'serverCities',
|
||||
dillDownProp: ['server_region'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.npmOverviewCommon
|
||||
}, {
|
||||
label: 'network.clientIsps',
|
||||
prop: 'clientIsp',
|
||||
queryCycleTotalProp: 'clientIsps',
|
||||
dillDownProp: ['client_isp'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.npmOverviewCommon
|
||||
}, {
|
||||
label: 'network.serverIsps',
|
||||
prop: 'serverIsp',
|
||||
queryCycleTotalProp: 'serverIsps',
|
||||
dillDownProp: ['server_isp'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.npmOverviewCommon
|
||||
}, {
|
||||
label: 'network.clientIdcRenters',
|
||||
prop: 'clientIdcRenter',
|
||||
queryCycleTotalProp: 'clientIdcRenters',
|
||||
dillDownProp: ['client_idc_renter'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.npmOverviewCommon
|
||||
}, {
|
||||
label: 'network.serverIdcRenters',
|
||||
prop: 'serverIdcRenter',
|
||||
queryCycleTotalProp: 'serverIdcRenters',
|
||||
dillDownProp: ['server_idc_renter'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.npmOverviewCommon
|
||||
}, {
|
||||
label: 'network.clientAsns',
|
||||
prop: 'clientAsn',
|
||||
queryCycleTotalProp: 'clientAsns',
|
||||
dillDownProp: ['client_asn'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.npmOverviewCommon
|
||||
}, {
|
||||
label: 'network.serverAsns',
|
||||
prop: 'serverAsn',
|
||||
queryCycleTotalProp: 'serverAsns',
|
||||
dillDownProp: ['server_asn'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.npmOverviewCommon
|
||||
}
|
||||
]
|
||||
export const linkMonitorTabList = [
|
||||
@@ -915,6 +1140,118 @@ export const linkMonitorTabList = [
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.linkMonitor
|
||||
}, {
|
||||
label: 'network.clientIps',
|
||||
prop: 'clientIp',
|
||||
queryCycleTotalProp: 'clientIps',
|
||||
dillDownProp: ['common_client_ip'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.linkMonitor
|
||||
}, {
|
||||
label: 'network.serverIps',
|
||||
prop: 'serverIp',
|
||||
queryCycleTotalProp: 'serverIps',
|
||||
dillDownProp: ['common_server_ip'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.linkMonitor
|
||||
}, {
|
||||
label: 'network.clientCountries',
|
||||
prop: 'clientCountry',
|
||||
queryCycleTotalProp: 'clientCountries',
|
||||
dillDownProp: ['client_country'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.linkMonitor
|
||||
}, {
|
||||
label: 'network.serverCountries',
|
||||
prop: 'serverCountry',
|
||||
queryCycleTotalProp: 'serverCountries',
|
||||
dillDownProp: ['server_country'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.linkMonitor
|
||||
}, {
|
||||
label: 'network.clientProvinces',
|
||||
prop: 'clientProvince',
|
||||
queryCycleTotalProp: 'clientProvinces',
|
||||
dillDownProp: ['client_province'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.linkMonitor
|
||||
}, {
|
||||
label: 'network.serverProvinces',
|
||||
prop: 'serverProvince',
|
||||
queryCycleTotalProp: 'serverProvinces',
|
||||
dillDownProp: ['server_province'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.linkMonitor
|
||||
}, {
|
||||
label: 'network.clientCities',
|
||||
prop: 'clientCity',
|
||||
queryCycleTotalProp: 'clientCities',
|
||||
dillDownProp: ['client_region'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.linkMonitor
|
||||
}, {
|
||||
label: 'network.serverCities',
|
||||
prop: 'serverCity',
|
||||
queryCycleTotalProp: 'serverCities',
|
||||
dillDownProp: ['server_region'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.linkMonitor
|
||||
}, {
|
||||
label: 'network.clientIsps',
|
||||
prop: 'clientIsp',
|
||||
queryCycleTotalProp: 'clientIsps',
|
||||
dillDownProp: ['client_isp'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.linkMonitor
|
||||
}, {
|
||||
label: 'network.serverIsps',
|
||||
prop: 'serverIsp',
|
||||
queryCycleTotalProp: 'serverIsps',
|
||||
dillDownProp: ['server_isp'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.linkMonitor
|
||||
}, {
|
||||
label: 'network.clientIdcRenters',
|
||||
prop: 'clientIdcRenter',
|
||||
queryCycleTotalProp: 'clientIdcRenters',
|
||||
dillDownProp: ['client_idc_renter'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.linkMonitor
|
||||
}, {
|
||||
label: 'network.serverIdcRenters',
|
||||
prop: 'serverIdcRenter',
|
||||
queryCycleTotalProp: 'serverIdcRenters',
|
||||
dillDownProp: ['server_idc_renter'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.linkMonitor
|
||||
}, {
|
||||
label: 'network.clientAsns',
|
||||
prop: 'clientAsn',
|
||||
queryCycleTotalProp: 'clientAsns',
|
||||
dillDownProp: ['client_asn'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.linkMonitor
|
||||
}, {
|
||||
label: 'network.serverAsns',
|
||||
prop: 'serverAsn',
|
||||
queryCycleTotalProp: 'serverAsns',
|
||||
dillDownProp: ['server_asn'],
|
||||
checked: false,
|
||||
disabled: false,
|
||||
panelId: drillDownPanelTypeMapping.linkMonitor
|
||||
}
|
||||
]
|
||||
export const dnsServiceInsightsTabList = [
|
||||
|
||||
@@ -2,7 +2,7 @@ import { ElMessageBox, ElMessage } from 'element-plus'
|
||||
import i18n from '@/i18n'
|
||||
import _ from 'lodash'
|
||||
import { storageKey, iso36112, topDomain, echartsFontSize, dbGeoDataTableName, networkTable, dbDrilldownTableConfig } from '@/utils/constants'
|
||||
import { getIso36112JsonData,getDictList } from '@/utils/api'
|
||||
import { getIso36112JsonData, getDictList } from '@/utils/api'
|
||||
import { format } from 'echarts'
|
||||
import router from '@/router'
|
||||
import { db } from '@/indexedDB'
|
||||
@@ -840,7 +840,6 @@ export function changeTabState (param, value) {
|
||||
})
|
||||
}
|
||||
export function getTabList (curTable, curMetric) {
|
||||
console.log('getTabList--------------')
|
||||
let tabs = []
|
||||
if (curTable.hasMetricSearch) { // 有metric
|
||||
const metricsList = curTable ? curTable.metrics : []
|
||||
@@ -855,29 +854,35 @@ export function getTabList (curTable, curMetric) {
|
||||
}
|
||||
return tabs
|
||||
}
|
||||
export async function getDnsMapData(type){
|
||||
let codeValueMap = new Map()
|
||||
const dnsData = await getDictList({ type:type,pageSize: -1 })
|
||||
if(dnsData && dnsData.length>0) {
|
||||
export async function getDnsMapData (type) {
|
||||
const codeValueMap = new Map()
|
||||
const dnsData = await getDictList({ type: type, pageSize: -1 })
|
||||
if (dnsData && dnsData.length > 0) {
|
||||
dnsData.forEach(mapData => {
|
||||
let code = mapData.code
|
||||
if(code.indexOf('-')>-1){
|
||||
let range = mapData.code.split('-')
|
||||
if(range && range.length >= 2){
|
||||
let start = range[0].trim()
|
||||
let eEnd = range[1].trim()
|
||||
const code = mapData.code
|
||||
if (code.indexOf('-') > -1) {
|
||||
const range = mapData.code.split('-')
|
||||
if (range && range.length >= 2) {
|
||||
const start = range[0].trim()
|
||||
const eEnd = range[1].trim()
|
||||
mapData.value = (start <= code && code <= eEnd) ? mapData.value : code
|
||||
for (let i = start; i <= eEnd; i++) {
|
||||
codeValueMap.set(i,mapData.value)
|
||||
codeValueMap.set(i, mapData.value)
|
||||
}
|
||||
}
|
||||
}else {
|
||||
codeValueMap.set(code,mapData.value)
|
||||
} else {
|
||||
codeValueMap.set(code, mapData.value)
|
||||
}
|
||||
})
|
||||
}
|
||||
return codeValueMap
|
||||
}
|
||||
export function handleSpecialValue(value){
|
||||
value = value.replaceAll("'", "\\\\'")
|
||||
.replaceAll('"','\\"')
|
||||
.replaceAll('&','%26')
|
||||
return value
|
||||
}
|
||||
export function combineTabList (tableType, list, commonTabList) {
|
||||
const curTableInCode = networkTable[tableType] ? networkTable[tableType] : networkTable.networkOverview
|
||||
const listInCode = curTableInCode ? curTableInCode.tabList : []
|
||||
@@ -927,7 +932,7 @@ export async function getDefaultCurTab (tableType, metric, columnName) {
|
||||
return curTab
|
||||
}
|
||||
|
||||
export async function readDrilldownTableConfigByUser (tableType, curMetric) {
|
||||
export async function readDrilldownTableConfigByUser () {
|
||||
// 获取用户定制的自定义配置
|
||||
const userId = localStorage.getItem(storageKey.userId)
|
||||
const userLocalCongfig = await db[dbDrilldownTableConfig].get({ id: userId })
|
||||
@@ -938,6 +943,17 @@ export async function readDrilldownTableConfigByUser (tableType, curMetric) {
|
||||
return defaultDrillDownTableConfigs
|
||||
}
|
||||
|
||||
export async function getConfigVersion (id) {
|
||||
let defaultCongfigInDb = await db[dbDrilldownTableConfig].get({ id: id })
|
||||
let version
|
||||
if(defaultCongfigInDb) {
|
||||
version = defaultCongfigInDb ? defaultCongfigInDb.version : ''
|
||||
}else {
|
||||
defaultCongfigInDb = await db[dbDrilldownTableConfig].get({ id: 'default' })
|
||||
}
|
||||
return version
|
||||
}
|
||||
|
||||
export async function combinDrilldownTableWithUserConfig () {
|
||||
const defaultCongfigInDb = await db[dbDrilldownTableConfig].get({ id: 'default' })
|
||||
const defaultConfigs = defaultCongfigInDb ? defaultCongfigInDb.config : []
|
||||
@@ -951,8 +967,10 @@ export async function combinDrilldownTableWithUserConfig () {
|
||||
tableConfig.hiddenColumns = newTableConfig.hiddenColumns
|
||||
tableConfig.tabs.forEach(tab => {
|
||||
const newTab = newTableConfig.tabs.find(newTab => newTab.name === tab.name)
|
||||
tab.hiddenDrilldownTabs = newTab.hiddenDrilldownTabs
|
||||
tab.checked = newTab.checked
|
||||
if (newTab) {
|
||||
tab.hiddenDrilldownTabs = newTab.hiddenDrilldownTabs
|
||||
tab.checked = newTab.checked
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -960,40 +978,6 @@ export async function combinDrilldownTableWithUserConfig () {
|
||||
return defaultConfigs
|
||||
}
|
||||
|
||||
/*
|
||||
export async function readDrilldownTableConfigByUser2 (tableType, curMetric) {
|
||||
let list = []
|
||||
// 获取用户定制的自定义配置,如果没有,则使用默认的自定义配置
|
||||
const userId = localStorage.getItem(storageKey.userId)
|
||||
const userLocalCongfig = await db[dbDrilldownTableConfig].get({ id: userId })
|
||||
let defaultDrillDownTableConfigs = []
|
||||
if (userLocalCongfig) {
|
||||
defaultDrillDownTableConfigs = userLocalCongfig.config
|
||||
if(defaultDrillDownTableConfigs && defaultDrillDownTableConfigs.length > 0){
|
||||
const currentTableConfig = defaultDrillDownTableConfigs.find(config => config.route === tableType)
|
||||
const commonTabList = currentTableConfig ? currentTableConfig.tabs : []
|
||||
const tables = currentTableConfig ? currentTableConfig.tables : []
|
||||
if (tables && tables.length > 0) {
|
||||
const curTableOldConfig = tables.find(table => table.id === tableType)
|
||||
const curTable = curTableOldConfig || null
|
||||
if (curTable) {
|
||||
if (curTable.hasMetricSearch) { // 有metric
|
||||
const metricsList = curTable ? curTable.metrics : []
|
||||
if (metricsList && metricsList.length > 0) {
|
||||
const metricTab = metricsList.find(metric => metric.name === curMetric)
|
||||
list = metricTab ? metricTab.tabs : []
|
||||
}
|
||||
} else { // 无metric
|
||||
list = curTable ? curTable.tabs : []
|
||||
}
|
||||
//combineTabList(tableType, list, commonTabList)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
*/
|
||||
export async function getUserDrilldownTableConfig (tableType, curMetric) {
|
||||
let list = []
|
||||
// 获取用户定制的自定义配置,如果没有,则使用默认的自定义配置
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<div class="panel__header">
|
||||
<div class="panel__title">{{panelName?panelName:(panel.i18n ? $t(panel.i18n) : panel.name)}}
|
||||
<div v-if="showScore" class="score">
|
||||
<div class="circle-icon" v-if="score <= 2" :class="{'data-score-red': score <= 2}" ></div>
|
||||
<div class="circle-icon" v-if="score <= 2 || score === '-'" :class="{'data-score-red': score <= 2 || score === '-'}" ></div>
|
||||
<div class="circle-icon" v-else-if="score <= 4" :class="{'data-score-yellow': score <= 4}" ></div>
|
||||
<div class="circle-icon" v-else-if="score <= 6" :class="{'data-score-green': score <= 6}" ></div>
|
||||
Score:{{score}}
|
||||
@@ -61,14 +61,16 @@ import {
|
||||
panelTypeAndRouteMapping,
|
||||
curTabState,
|
||||
drillDownPanelTypeMapping,
|
||||
metricOptions
|
||||
metricOptions,
|
||||
fromRoute
|
||||
} from '@/utils/constants'
|
||||
import { getPanelList, getChartList } from '@/utils/api'
|
||||
import { getPanelList, getChartList, api } from '@/utils/api'
|
||||
import { getNowTime, getSecond } from '@/utils/date-util'
|
||||
import { getTypeCategory } from '@/views/charts/charts/tools'
|
||||
import { urlParamsHandler, overwriteUrl,getDnsMapData } from '@/utils/tools'
|
||||
import { urlParamsHandler, overwriteUrl, getDnsMapData, computeScore } from '@/utils/tools'
|
||||
import ChartList from '@/views/charts2/ChartList'
|
||||
import { useStore } from 'vuex'
|
||||
import { get } from '@/utils/http'
|
||||
|
||||
export default {
|
||||
name: 'Panel',
|
||||
@@ -94,30 +96,41 @@ export default {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
npmThirdLevelMenuScore () {
|
||||
return this.$store.getters.getNpmThirdLevelMenuScore
|
||||
}
|
||||
// npmThirdLevelMenuScore () {
|
||||
// return this.$store.getters.getNpmThirdLevelMenuScore
|
||||
// }
|
||||
},
|
||||
watch: {
|
||||
npmThirdLevelMenuScore: {
|
||||
deep: true,
|
||||
immediate: true,
|
||||
handler (n) {
|
||||
this.score = n
|
||||
// npmThirdLevelMenuScore: {
|
||||
// deep: true,
|
||||
// immediate: true,
|
||||
// handler (n) {
|
||||
// this.score = n
|
||||
// }
|
||||
// }
|
||||
timeFilter: {
|
||||
handler () {
|
||||
if (this.$route.path === '/panel/networkAppPerformance' && (this.queryCondition || this.networkOverviewBeforeTab)) {
|
||||
this.scoreCalculation()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
async mounted () {
|
||||
// this.panelName = this.$store.getters.getPanelName
|
||||
let pName = this.$route.query.panelName ? this.$t(this.$route.query.panelName) : ''
|
||||
let curTabProp = this.$route.query.dimensionType ? this.$route.query.dimensionType : null
|
||||
this.dnsQtypeMapData = await getDnsMapData('dnsQtype')
|
||||
this.dnsRcodeMapData = await getDnsMapData('dnsRcode')
|
||||
if(curTabProp === 'qtype'){
|
||||
const pName = this.$route.query.panelName ? this.$t(this.$route.query.panelName) : ''
|
||||
const curTabProp = this.$route.query.dimensionType ? this.$route.query.dimensionType : null
|
||||
if (this.$route.params.typeName === fromRoute.dnsServiceInsights) {
|
||||
this.dnsQtypeMapData = await getDnsMapData('dnsQtype')
|
||||
this.dnsRcodeMapData = await getDnsMapData('dnsRcode')
|
||||
this.$store.commit('setDnsQtypeMapData', this.dnsQtypeMapData)
|
||||
this.$store.commit('setDnsRcodeMapData', this.dnsRcodeMapData)
|
||||
}
|
||||
if (curTabProp === 'qtype') {
|
||||
this.panelName = this.dnsQtypeMapData.get(pName)
|
||||
}else if(curTabProp === 'rcode'){
|
||||
} else if (curTabProp === 'rcode') {
|
||||
this.panelName = this.dnsRcodeMapData.get(pName)
|
||||
}else {
|
||||
} else {
|
||||
this.panelName = pName
|
||||
}
|
||||
|
||||
@@ -183,14 +196,16 @@ export default {
|
||||
return chart
|
||||
})
|
||||
})
|
||||
if (this.$route.path === '/panel/networkAppPerformance' && (this.queryCondition || this.networkOverviewBeforeTab)) {
|
||||
this.scoreCalculation()
|
||||
}
|
||||
},
|
||||
setup (props, ctx) {
|
||||
setup (props) {
|
||||
// todo 目前在panel页面测试,后续会挪到router里
|
||||
const store = useStore()
|
||||
const cancelList = store.state.panel.httpCancel
|
||||
|
||||
// 进入页面时,发现有未结束的请求,终止请求
|
||||
// console.log('panel.vue------setup------查看http终止情况', cancelList, cancelList.length)
|
||||
if (cancelList.length > 0) {
|
||||
cancelList.forEach((cancel, index) => {
|
||||
cancel()
|
||||
@@ -200,19 +215,20 @@ export default {
|
||||
|
||||
const panel = ref({})
|
||||
let panelType = 1 // 取得panel的type
|
||||
const { params, query, path } = useRoute()
|
||||
// 只要当前路由和vuex里的路由一致,且vuex存储的range有值,即代表已经下钻后返回,此时直接使用vuex里存储的时间范围
|
||||
if (path === store.getters.getRouterPath && store.getters.getTimeRangeFlag !== null) {
|
||||
const newUrl = urlParamsHandler(window.location.href, query, {
|
||||
startTime: store.getters.getTimeRangeArray[0],
|
||||
endTime: store.getters.getTimeRangeArray[1],
|
||||
range: store.getters.getTimeRangeFlag
|
||||
})
|
||||
let { params, query, path } = useRoute()
|
||||
|
||||
// 获取路由跳转过的历史状态,赋值给当前界面,起到保留状态的作用,如浏览器的回退前进等
|
||||
const routerObj = store.getters.getRouterHistoryList.find(item => item.t === query.t)
|
||||
if (routerObj) {
|
||||
params = routerObj.params
|
||||
query = routerObj.query
|
||||
path = routerObj.path
|
||||
|
||||
// 如果当前界面之前载入过,获取状态后更新地址栏,以便后续的赋值操作
|
||||
const newUrl = urlParamsHandler(window.location.href, useRoute().query, query)
|
||||
overwriteUrl(newUrl)
|
||||
} else {
|
||||
store.commit('setTimeRangeArray', [])
|
||||
store.commit('setTimeRangeFlag', null)
|
||||
}
|
||||
|
||||
const thirdPanel = query.thirdPanel
|
||||
const fourthPanel = query.fourthPanel
|
||||
if (fourthPanel) {
|
||||
@@ -231,6 +247,7 @@ export default {
|
||||
const startTimeParam = query.startTime
|
||||
const endTimeParam = query.endTime
|
||||
// 若url携带了,使用携带的值,否则使用默认值。
|
||||
|
||||
const dateRangeValue = rangeParam ? parseInt(query.range) : (isEntityDetail(panelType) ? 60 * 24 : 60)
|
||||
const timeFilter = ref({ dateRangeValue })
|
||||
if (!startTimeParam || !endTimeParam) {
|
||||
@@ -241,19 +258,29 @@ export default {
|
||||
timeFilter.value.startTime = parseInt(startTimeParam)
|
||||
timeFilter.value.endTime = parseInt(endTimeParam)
|
||||
}
|
||||
store.commit('setRouterPath', path)
|
||||
|
||||
// npm是否展示分数
|
||||
const showScorePanel = [drillDownPanelTypeMapping.npmOverviewIp, drillDownPanelTypeMapping.npmOverviewDomain, drillDownPanelTypeMapping.npmOverviewApp, drillDownPanelTypeMapping.npmOverviewCommon, drillDownPanelTypeMapping.npmThirdMenu]
|
||||
const showScore = showScorePanel.indexOf(panelType) > -1
|
||||
|
||||
const metric = ref(query.metric || 'Bits/s')
|
||||
|
||||
const queryCondition = ref(query.queryCondition || '')
|
||||
const dimensionType = ref(query.dimensionType || '')
|
||||
// 三级菜单判断
|
||||
const tabOperationType = ref(query.tabOperationType)
|
||||
const networkOverviewBeforeTab = ref(query.networkOverviewBeforeTab || '')
|
||||
return {
|
||||
panelType,
|
||||
panel,
|
||||
timeFilter,
|
||||
showScore,
|
||||
metric
|
||||
metric,
|
||||
path,
|
||||
queryCondition,
|
||||
dimensionType,
|
||||
tabOperationType,
|
||||
networkOverviewBeforeTab
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -323,7 +350,88 @@ export default {
|
||||
metric: value
|
||||
})
|
||||
overwriteUrl(newUrl)
|
||||
},
|
||||
scoreCalculation () {
|
||||
let condition = ''
|
||||
let url = ''
|
||||
if (this.queryCondition.indexOf(' OR ') > -1) {
|
||||
condition = this.queryCondition.split(/["|'](.*?)["|']/)
|
||||
} else {
|
||||
condition = this.queryCondition
|
||||
}
|
||||
const type = this.dimensionType || this.networkOverviewBeforeTab
|
||||
const params = {
|
||||
startTime: getSecond(this.timeFilter.startTime),
|
||||
endTime: getSecond(this.timeFilter.endTime),
|
||||
cycle: 0
|
||||
}
|
||||
if (condition && (typeof condition !== 'object') && type) {
|
||||
if (type === 'clientIp') {
|
||||
params.q = `ip='${condition.split(/'(.*?)'/)[1]}' and side='client'`
|
||||
} else if (type === 'serverIp') {
|
||||
params.q = `ip='${condition.split(/'(.*?)'/)[1]}' and side='server'`
|
||||
} else if (type === 'clientCity') {
|
||||
params.q = `client_city='${condition.split(/'(.*?)'/)[1]}'`
|
||||
} else if (type === 'serverCity') {
|
||||
params.q = `server_city='${condition.split(/'(.*?)'/)[1]}'`
|
||||
} else {
|
||||
params.q = condition
|
||||
}
|
||||
params.type = type
|
||||
} else if (condition.length > 1 && type && type === 'ip') {
|
||||
params.q = `${type}='${condition[1]}'`
|
||||
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]}'`
|
||||
params.type = type
|
||||
} else if (type === 'idcRenter') {
|
||||
params.q = `idc_renter='${condition[1]}'`
|
||||
params.type = type
|
||||
} else {
|
||||
params.q = `${condition[0]}'${condition[1]}'`
|
||||
params.type = type
|
||||
}
|
||||
}
|
||||
if (parseFloat(this.tabOperationType) === 3) {
|
||||
url = api.npm.overview.allNetworkAnalysis
|
||||
} else {
|
||||
url = api.npm.overview.networkAnalysis
|
||||
}
|
||||
if ((type && condition) || type) {
|
||||
params.type = params.type || type
|
||||
get(url, params).then(res => {
|
||||
if (res.code === 200) {
|
||||
const data = {
|
||||
establishLatencyMs: res.data.result.establishLatencyMsAvg || null,
|
||||
httpResponseLatency: res.data.result.httpResponseLatencyAvg || null,
|
||||
sslConLatency: res.data.result.sslConLatencyAvg || null,
|
||||
tcpLostlenPercent: res.data.result.tcpLostlenPercentAvg || null,
|
||||
pktRetransPercent: res.data.result.pktRetransPercentAvg || null
|
||||
}
|
||||
this.score = computeScore(data)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 页面销毁前,更新历史中已保存的状态
|
||||
* 之所以会在下钻时、销毁前保存状态,是因为panel第一次下钻时,beforeUnmount获取不到下钻前参数
|
||||
*/
|
||||
beforeUnmount () {
|
||||
const query = this.$_.cloneDeep(this.$route.query)
|
||||
const routerObj = this.$store.getters.getRouterHistoryList.find(item => item.t === query.t)
|
||||
// const routerObj = window.localRouterHistoryList.find(item => item.t === query.t)
|
||||
if (routerObj !== undefined) {
|
||||
if (Object.getOwnPropertyNames(query).length >= Object.getOwnPropertyNames(routerObj.query).length) {
|
||||
routerObj.query = query
|
||||
}
|
||||
}
|
||||
|
||||
this.emitter.off('reloadChartList')
|
||||
this.$store = null
|
||||
this.emitter = null
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<div class="line network dns-traffic-line">
|
||||
<div class="line-header">
|
||||
<chart-error v-if="showError" :content="errorMsg" />
|
||||
<div class="line-header" v-if="!showError">
|
||||
<div class="line-header-left">
|
||||
<div class="line-value-active" v-if="lineTab"></div>
|
||||
<div class="line-value">
|
||||
@@ -138,7 +139,9 @@ export default {
|
||||
leftOffset: 0,
|
||||
sizes: [3, 4, 6, 8, 9, 10],
|
||||
dynamicVariable: '',
|
||||
showMarkLine: true
|
||||
showMarkLine: true,
|
||||
showError: false,
|
||||
errorMsg: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -167,7 +170,7 @@ export default {
|
||||
overwriteUrl(newUrl)
|
||||
},
|
||||
timeFilter: {
|
||||
handler (n) {
|
||||
handler () {
|
||||
if (this.lineTab) {
|
||||
this.init(this.lineMetric, this.showMarkLine, 'active')
|
||||
} else {
|
||||
@@ -195,15 +198,17 @@ export default {
|
||||
}
|
||||
get(url, params).then((res) => {
|
||||
if (res.code === 200) {
|
||||
this.showError = false
|
||||
this.isNoData = res.data.result.length === 0
|
||||
if (this.isNoData) {
|
||||
this.lineTab = ''
|
||||
this.mpackets = [
|
||||
{ analysis: {}, name: 'network.total', class: 'total', show: true, invertTab: true, positioning: 0, data: [], unitType: '' },
|
||||
{ analysis: {}, name: 'network.inbound', class: 'inbound', show: true, invertTab: true, positioning: 1, data: [], unitType: '' },
|
||||
{ analysis: {}, name: 'network.outbound', class: 'outbound', show: true, invertTab: true, positioning: 2, data: [], unitType: '' }
|
||||
]
|
||||
}
|
||||
res.data.result.forEach((t, i) => {
|
||||
res.data.result.forEach((t) => {
|
||||
if (t.type === 'bytes' && val === 'Bits/s') {
|
||||
const mpackets = _.cloneDeep(this.mpackets)
|
||||
mpackets[0].analysis = t.totalBitsRate.analysis
|
||||
@@ -215,7 +220,7 @@ export default {
|
||||
let num = 0
|
||||
mpackets.forEach(e => {
|
||||
e.unitType = 'bps'
|
||||
if (e.name !== 'network.total' && e.analysis.avg == 0) {
|
||||
if (e.name !== 'network.total' && parseFloat(e.analysis.avg) === 0) {
|
||||
e.show = false
|
||||
num += 1
|
||||
} else {
|
||||
@@ -225,7 +230,7 @@ export default {
|
||||
}
|
||||
}
|
||||
if (this.lineTab === e.class) {
|
||||
if (e.analysis.avg <= 0) {
|
||||
if (parseFloat(e.analysis.avg) <= 0) {
|
||||
this.lineTab = ''
|
||||
this.lineRefer = ''
|
||||
this.init()
|
||||
@@ -243,6 +248,7 @@ export default {
|
||||
} else {
|
||||
this.$nextTick(() => {
|
||||
this.echartsInit(this.mpackets, show)
|
||||
if (!this.lineRefer) this.lineRefer = 'Average'
|
||||
})
|
||||
}
|
||||
} else if (t.type === 'queries' && val === 'Queries/s') {
|
||||
@@ -264,10 +270,16 @@ export default {
|
||||
})
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.isNoData = false
|
||||
this.showError = true
|
||||
this.errorMsg = res.message
|
||||
}
|
||||
}).catch(e => {
|
||||
console.error(e)
|
||||
this.isNoData = true
|
||||
this.isNoData = false
|
||||
this.showError = true
|
||||
this.errorMsg = e.message
|
||||
}).finally(() => {
|
||||
this.toggleLoading(false)
|
||||
})
|
||||
@@ -293,7 +305,7 @@ export default {
|
||||
width: 1
|
||||
},
|
||||
stack: t.name !== 'network.total' ? 'network.total' : '',
|
||||
symbolSize: function (value, params) {
|
||||
symbolSize: function (value) {
|
||||
return _this.symbolSizeSortChange(i, value[0])
|
||||
},
|
||||
itemStyle: {
|
||||
@@ -337,7 +349,7 @@ export default {
|
||||
}
|
||||
})
|
||||
if (!show) {
|
||||
this.chartOption.series.forEach((t, i) => {
|
||||
this.chartOption.series.forEach((t) => {
|
||||
t.markLine.label.show = false
|
||||
t.markLine = []
|
||||
})
|
||||
@@ -375,19 +387,20 @@ export default {
|
||||
}
|
||||
})
|
||||
})
|
||||
const str = stackedLineTooltipFormatter(params)
|
||||
return str
|
||||
return stackedLineTooltipFormatter(params)
|
||||
}
|
||||
this.showMarkLine = true
|
||||
this.myChart.setOption(this.chartOption)
|
||||
},
|
||||
activeChange (item, index) {
|
||||
if (this.isNoData) return
|
||||
this.lineTab = item.class
|
||||
this.legendSelectChange(item, index, 'active')
|
||||
this.showMarkLine = !item.invertTab
|
||||
this.init(this.lineMetric, this.showMarkLine, 'active')
|
||||
},
|
||||
mouseenter (item) {
|
||||
if (this.isNoData) return
|
||||
this.mousemoveCursor = item.class
|
||||
this.handleActiveBar(item.class)
|
||||
},
|
||||
@@ -437,7 +450,7 @@ export default {
|
||||
})
|
||||
}
|
||||
},
|
||||
handleActiveBar (value) {
|
||||
handleActiveBar () {
|
||||
if (document.querySelector('.network .line-value-mpackets.is-active')) {
|
||||
const { offsetLeft, clientWidth, clientLeft } = document.querySelector('.network .line-value-mpackets.is-active')
|
||||
const activeBar = document.querySelector('.network .line-value-active')
|
||||
@@ -452,7 +465,7 @@ export default {
|
||||
this.lineTab = ''
|
||||
this.handleActiveBar()
|
||||
this.showMarkLine = !this.showMarkLine
|
||||
this.mpackets.forEach((e, i) => {
|
||||
this.mpackets.forEach((e) => {
|
||||
if (!e.invertTab) {
|
||||
e.invertTab = true
|
||||
}
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
<template>
|
||||
<div class="link-blocks">
|
||||
<div class="block-list" style="position: relative">
|
||||
<div class="block-list__title">{{ $t('linkMonitor.links') }}</div>
|
||||
<div class="block-list__title" v-if="!showError">{{ $t('linkMonitor.links') }}</div>
|
||||
|
||||
<!--无数据noData-->
|
||||
<chart-no-data v-if="isNoData"></chart-no-data>
|
||||
|
||||
<div class="block-list__list" v-show="!isNoData">
|
||||
<chart-error v-if="showError" :content="errorMsg1" />
|
||||
<el-popover
|
||||
v-else
|
||||
placement="bottom"
|
||||
trigger="hover"
|
||||
popper-class="link-block__popper"
|
||||
@@ -54,13 +56,15 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="block-list" style="position: relative">
|
||||
<div class="block-list__title">{{ $t('linkMonitor.nextHopInternet') }}</div>
|
||||
<div class="block-list" >
|
||||
<div class="block-list__title" v-if="!showError">{{ $t('linkMonitor.nextHopInternet') }}</div>
|
||||
|
||||
<chart-no-data v-if="isNoData"></chart-no-data>
|
||||
|
||||
<div class="block-list__list" v-show="!isNoData">
|
||||
<chart-error v-if="showError" :content="errorMsg2" />
|
||||
<el-popover
|
||||
v-else
|
||||
placement="bottom"
|
||||
trigger="hover"
|
||||
popper-class="link-block__popper"
|
||||
@@ -120,11 +124,13 @@ import { colorGradientCalculation } from '@/utils/tools'
|
||||
import unitConvert from '@/utils/unit-convert'
|
||||
import { drillDownPanelTypeMapping, storageKey, unitTypes } from '@/utils/constants'
|
||||
import { getSecond } from '@/utils/date-util'
|
||||
import ChartError from '@/components/common/Error'
|
||||
|
||||
export default {
|
||||
name: 'LinkBlock',
|
||||
mixins: [chartMixin],
|
||||
components: {
|
||||
ChartError,
|
||||
ChartNoData
|
||||
},
|
||||
data () {
|
||||
@@ -133,7 +139,10 @@ export default {
|
||||
unitTypes,
|
||||
linkData: [],
|
||||
nextHopData: [],
|
||||
gradientColor: ['#FF005C', '#40537E'] // [start, end]
|
||||
gradientColor: ['#FF005C', '#40537E'], // [start, end]
|
||||
showError: false,
|
||||
errorMsg1: '',
|
||||
errorMsg2: ''
|
||||
}
|
||||
},
|
||||
setup () {
|
||||
@@ -145,7 +154,7 @@ export default {
|
||||
},
|
||||
watch: {
|
||||
timeFilter: {
|
||||
handler (n) {
|
||||
handler () {
|
||||
this.init()
|
||||
}
|
||||
}
|
||||
@@ -158,7 +167,8 @@ export default {
|
||||
init () {
|
||||
this.toggleLoading(true)
|
||||
// 链路基本信息
|
||||
let linkInfo = localStorage.getItem(storageKey.linkInfo)
|
||||
let linkInfo = null
|
||||
linkInfo = localStorage.getItem(storageKey.linkInfo)
|
||||
linkInfo = JSON.parse(linkInfo)
|
||||
const params = {
|
||||
startTime: getSecond(this.timeFilter.startTime),
|
||||
@@ -170,6 +180,8 @@ export default {
|
||||
|
||||
Promise.all([dataRequest, nextHopRequest]).then(res => {
|
||||
if (res[0].code === 200 && res[1].code === 200) {
|
||||
this.showError = false
|
||||
|
||||
const linkData = res[0].data.result
|
||||
const nextHopData = res[1].data.result
|
||||
|
||||
@@ -230,7 +242,7 @@ export default {
|
||||
directionArr.push(item.ingressLinkDirection)
|
||||
}
|
||||
})
|
||||
directionArr = [...new Set(directionArr)]
|
||||
directionArr = Array.from(new Set(directionArr))
|
||||
|
||||
const newNextHopData = []
|
||||
|
||||
@@ -274,11 +286,18 @@ export default {
|
||||
|
||||
this.nextHopData = nextHopSorted
|
||||
} else {
|
||||
this.isNoData = true
|
||||
this.isNoData = false
|
||||
this.showError = true
|
||||
this.errorMsg1 = res[0].message
|
||||
this.errorMsg2 = res[1].message
|
||||
}
|
||||
}).catch(e => {
|
||||
console.error(e)
|
||||
this.isNoData = true
|
||||
this.isNoData = false
|
||||
this.showError = true
|
||||
// todo 此处数据还待验证
|
||||
this.errorMsg1 = e.message
|
||||
this.errorMsg2 = e.message
|
||||
}).finally(() => {
|
||||
this.toggleLoading(false)
|
||||
})
|
||||
@@ -365,6 +384,9 @@ export default {
|
||||
|
||||
return newValue
|
||||
}
|
||||
},
|
||||
beforeUnmount () {
|
||||
this.unitConvert = null
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<div class="link-direction-grid">
|
||||
<!--左侧链路出入口-->
|
||||
<popover-content :isNoData="isNoData" :gridData="gridData" style="width: 900px;"/>
|
||||
<popover-content :isNoData="isLinkNoData" :gridData="linkGridData" :showError="isLinkShowError" :content="linkErrorMsg" style="width: 900px;"/>
|
||||
|
||||
<!--右侧链路下一跳-->
|
||||
<popover-content :isNoData="isNoData" :gridData="gridData2"/>
|
||||
<popover-content :isNoData="isNextNoData" :gridData="nextGridData" :showError="isNextShowError" :content="nextErrorMsg" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -22,9 +22,14 @@ export default {
|
||||
mixins: [chartMixin],
|
||||
data () {
|
||||
return {
|
||||
gridData: [],
|
||||
gridData2: [],
|
||||
isNoData: false
|
||||
linkGridData: [],
|
||||
nextGridData: [],
|
||||
isLinkNoData: false,
|
||||
isNextNoData: false,
|
||||
isLinkShowError: false, // 显示左侧链路报错标识
|
||||
linkErrorMsg: '', // 左侧链路的报错信息
|
||||
isNextShowError: false, // 显示右侧下一跳报错标识
|
||||
nextErrorMsg: '' // 右侧下一跳的报错信息
|
||||
}
|
||||
},
|
||||
components: {
|
||||
@@ -32,7 +37,7 @@ export default {
|
||||
},
|
||||
watch: {
|
||||
timeFilter: {
|
||||
handler (n) {
|
||||
handler () {
|
||||
this.init()
|
||||
}
|
||||
}
|
||||
@@ -45,7 +50,6 @@ export default {
|
||||
// 链路基本信息
|
||||
let linkInfo = localStorage.getItem(storageKey.linkInfo)
|
||||
linkInfo = JSON.parse(linkInfo)
|
||||
// console.log('LinkDirectionGrid.vue---init--获取链路基本信息缓存', linkInfo)
|
||||
|
||||
const params = {
|
||||
startTime: getSecond(this.timeFilter.startTime),
|
||||
@@ -57,7 +61,8 @@ export default {
|
||||
this.toggleLoading(true)
|
||||
|
||||
Promise.all([dataRequest, nextHopRequest]).then(res => {
|
||||
if (res[0].code === 200 && res[1].code === 200) {
|
||||
if (res[0].code === 200) {
|
||||
this.isLinkShowError = false
|
||||
// 链路流量数据
|
||||
const linkData = res[0].data.result
|
||||
// 接口数据乱序,根据入链路id(ingressLinkId)大小排序之后,
|
||||
@@ -69,6 +74,70 @@ export default {
|
||||
return a.egressLinkId - b.egressLinkId
|
||||
})
|
||||
|
||||
this.isLinkNoData = linkData.length === 0
|
||||
if (!this.isLinkNoData) {
|
||||
// 链路流量数据
|
||||
const linkGridData = []
|
||||
linkData.forEach(d => {
|
||||
const ingressLink = linkInfo.find(l => l.originalLinkId === d.ingressLinkId)
|
||||
const egressLink = linkInfo.find(l => l.originalLinkId === d.egressLinkId)
|
||||
if (ingressLink && egressLink) {
|
||||
const data = linkGridData.find(g => g.linkId === ingressLink.linkId)
|
||||
|
||||
// 上行使用情况计算
|
||||
const egressUsage = this.computeUsage(d.egressBitsRate, egressLink.bandwidth)
|
||||
// 下行使用情况计算
|
||||
const ingressUsage = this.computeUsage(d.ingressBitsRate, ingressLink.bandwidth)
|
||||
// 宽带使用超过90%,赋红点
|
||||
|
||||
d.usageMore90 = egressUsage >= 0.9 || ingressUsage >= 0.9
|
||||
// 计算npm分数
|
||||
// 分数低于3分,赋红点
|
||||
d.score = this.localComputeScore(d)
|
||||
|
||||
d.scoreLow3 = d.score < 3
|
||||
|
||||
if (data) {
|
||||
const existedEgressLink = data.egress.find(e => e.linkId === egressLink.linkId)
|
||||
if (!existedEgressLink) {
|
||||
data.egress.push({
|
||||
linkId: egressLink.linkId,
|
||||
egressUsage: egressUsage,
|
||||
ingressUsage: ingressUsage,
|
||||
popoverWidth: this.computeWidth(egressUsage, ingressUsage, 'popover'),
|
||||
valueWidth: this.computeWidth(egressUsage, ingressUsage, 'value'),
|
||||
totalBitsRate: d.totalBitsRate,
|
||||
...d
|
||||
})
|
||||
}
|
||||
} else {
|
||||
linkGridData.push({
|
||||
linkId: ingressLink.linkId,
|
||||
egress: [{
|
||||
linkId: egressLink.linkId,
|
||||
egressUsage: egressUsage,
|
||||
ingressUsage: ingressUsage,
|
||||
popoverWidth: this.computeWidth(egressUsage, ingressUsage, 'popover'),
|
||||
valueWidth: this.computeWidth(egressUsage, ingressUsage, 'value'),
|
||||
totalBitsRate: d.totalBitsRate,
|
||||
...d
|
||||
}]
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
this.linkGridData = linkGridData
|
||||
}
|
||||
} else {
|
||||
this.isLinkNoData = false
|
||||
this.isLinkShowError = true
|
||||
this.linkErrorMsg = res[0].message
|
||||
}
|
||||
|
||||
if (res[1].code === 200) {
|
||||
this.isNextShowError = false
|
||||
|
||||
// 链路下一跳信息
|
||||
const nextLinkData = res[1].data.result
|
||||
// 接口数据乱序,根据出方向排序,再根据同个出方向下的入进行排序
|
||||
@@ -79,145 +148,92 @@ export default {
|
||||
return a.egressLinkDirection.localeCompare(b.egressLinkDirection)
|
||||
})
|
||||
|
||||
this.isNoData = linkData.length === 0 && nextLinkData.length === 0
|
||||
if (this.isNoData) {
|
||||
return
|
||||
}
|
||||
this.isNextNoData = nextLinkData.length === 0
|
||||
if (!this.isNextNoData) {
|
||||
// 链路下一跳数据
|
||||
const nextGridData = []
|
||||
|
||||
// 链路流量数据
|
||||
const gridData = []
|
||||
// 链路下一跳数据
|
||||
const gridData2 = []
|
||||
linkData.forEach(d => {
|
||||
const ingressLink = linkInfo.find(l => l.originalLinkId === d.ingressLinkId)
|
||||
const egressLink = linkInfo.find(l => l.originalLinkId === d.egressLinkId)
|
||||
if (ingressLink && egressLink) {
|
||||
const data = gridData.find(g => g.linkId === ingressLink.linkId)
|
||||
nextLinkData.forEach(d => {
|
||||
const ingressLink = linkInfo.find(l => l.nextHop === d.ingressLinkDirection && l.direction === 'ingress')
|
||||
const egressLink = linkInfo.find(l => l.nextHop === d.egressLinkDirection && l.direction === 'egress')
|
||||
|
||||
// 上行使用情况计算
|
||||
const egressUsage = this.computeUsage(d.egressBitsRate, egressLink.bandwidth)
|
||||
// 下行使用情况计算
|
||||
const ingressUsage = this.computeUsage(d.ingressBitsRate, ingressLink.bandwidth)
|
||||
// 宽带使用超过90%,赋红点
|
||||
d.usageMore90 = false
|
||||
if (egressUsage >= 0.9 || ingressUsage >= 0.9) {
|
||||
d.usageMore90 = true
|
||||
}
|
||||
// 计算npm分数
|
||||
// 分数低于3分,赋红点
|
||||
d.score = this.localComputeScore(d)
|
||||
d.scoreLow3 = false
|
||||
if (d.score < 3) {
|
||||
d.scoreLow3 = true
|
||||
}
|
||||
if (ingressLink && egressLink) {
|
||||
const data = nextGridData.find(g => g.linkId === ingressLink.linkId)
|
||||
|
||||
if (data) {
|
||||
const existedEgressLink = data.egress.find(e => e.linkId === egressLink.linkId)
|
||||
if (!existedEgressLink) {
|
||||
data.egress.push({
|
||||
linkId: egressLink.linkId,
|
||||
egressUsage: egressUsage,
|
||||
ingressUsage: ingressUsage,
|
||||
popoverWidth: this.computeWidth(egressUsage, ingressUsage, 'popover'),
|
||||
valueWidth: this.computeWidth(egressUsage, ingressUsage, 'value'),
|
||||
totalBitsRate: d.totalBitsRate,
|
||||
...d
|
||||
})
|
||||
}
|
||||
} else {
|
||||
gridData.push({
|
||||
linkId: ingressLink.linkId,
|
||||
egress: [{
|
||||
linkId: egressLink.linkId,
|
||||
egressUsage: egressUsage,
|
||||
ingressUsage: ingressUsage,
|
||||
popoverWidth: this.computeWidth(egressUsage, ingressUsage, 'popover'),
|
||||
valueWidth: this.computeWidth(egressUsage, ingressUsage, 'value'),
|
||||
totalBitsRate: d.totalBitsRate,
|
||||
...d
|
||||
}]
|
||||
let egressBanwidth = 0
|
||||
let ingressBanwidth = 0
|
||||
linkInfo.forEach((item) => {
|
||||
if (item.nextHop === d.egressLinkDirection && item.direction === 'egress') {
|
||||
egressBanwidth += item.bandwidth
|
||||
}
|
||||
if (item.nextHop === d.ingressLinkDirection && item.direction === 'ingress') {
|
||||
ingressBanwidth += item.bandwidth
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
this.gridData = gridData
|
||||
// 上行使用情况计算
|
||||
const egressUsage = this.computeUsage(d.egressBitsRate, egressBanwidth)
|
||||
// 下行使用情况计算
|
||||
const ingressUsage = this.computeUsage(d.ingressBitsRate, ingressBanwidth)
|
||||
// 宽带使用超过90%,赋红点
|
||||
|
||||
nextLinkData.forEach(d => {
|
||||
const ingressLink = linkInfo.find(l => l.nextHop === d.ingressLinkDirection && l.direction === 'ingress')
|
||||
const egressLink = linkInfo.find(l => l.nextHop === d.egressLinkDirection && l.direction === 'egress')
|
||||
d.usageMore90 = egressUsage >= 0.9 || ingressUsage >= 0.9
|
||||
// 计算npm分数
|
||||
// 分数低于3分,赋红点
|
||||
d.score = this.localComputeScore(d)
|
||||
|
||||
if (ingressLink && egressLink) {
|
||||
const data = gridData2.find(g => g.linkId === ingressLink.linkId)
|
||||
d.scoreLow3 = d.score < 3
|
||||
|
||||
let egressBanwidth = 0
|
||||
let ingressBanwidth = 0
|
||||
linkInfo.forEach((item) => {
|
||||
if (item.nextHop === d.egressLinkDirection && item.direction === 'egress') {
|
||||
egressBanwidth += item.bandwidth
|
||||
}
|
||||
if (item.nextHop === d.ingressLinkDirection && item.direction === 'ingress') {
|
||||
ingressBanwidth += item.bandwidth
|
||||
}
|
||||
})
|
||||
|
||||
// 上行使用情况计算
|
||||
const egressUsage = this.computeUsage(d.egressBitsRate, egressBanwidth)
|
||||
// 下行使用情况计算
|
||||
const ingressUsage = this.computeUsage(d.ingressBitsRate, ingressBanwidth)
|
||||
// 宽带使用超过90%,赋红点
|
||||
d.usageMore90 = false
|
||||
if (egressUsage >= 0.9 || ingressUsage >= 0.9) {
|
||||
d.usageMore90 = true
|
||||
}
|
||||
// 计算npm分数
|
||||
// 分数低于3分,赋红点
|
||||
d.score = this.localComputeScore(d)
|
||||
d.scoreLow3 = false
|
||||
if (d.score < 3) {
|
||||
d.scoreLow3 = true
|
||||
}
|
||||
|
||||
if (data) {
|
||||
const existedEgressLink = data.egress.find(e => e.linkId === egressLink.linkId)
|
||||
if (!existedEgressLink) {
|
||||
data.egress.push({
|
||||
linkId: egressLink.linkId,
|
||||
nextHop: egressLink.nextHop,
|
||||
egressUsage: egressUsage,
|
||||
ingressUsage: ingressUsage,
|
||||
popoverWidth: this.computeWidth(egressUsage, ingressUsage, 'popover'),
|
||||
valueWidth: this.computeWidth(egressUsage, ingressUsage, 'value'),
|
||||
totalBitsRate: d.totalBitsRate,
|
||||
...d
|
||||
})
|
||||
}
|
||||
} else {
|
||||
gridData2.push({
|
||||
linkId: ingressLink.linkId,
|
||||
nextHop: ingressLink.nextHop,
|
||||
egress: [{
|
||||
linkId: egressLink.linkId,
|
||||
if (data) {
|
||||
const existedEgressLink = data.egress.find(e => e.linkId === egressLink.linkId)
|
||||
if (!existedEgressLink) {
|
||||
data.egress.push({
|
||||
linkId: egressLink.linkId,
|
||||
nextHop: egressLink.nextHop,
|
||||
egressUsage: egressUsage,
|
||||
ingressUsage: ingressUsage,
|
||||
popoverWidth: this.computeWidth(egressUsage, ingressUsage, 'popover'),
|
||||
valueWidth: this.computeWidth(egressUsage, ingressUsage, 'value'),
|
||||
totalBitsRate: d.totalBitsRate,
|
||||
...d
|
||||
})
|
||||
}
|
||||
} else {
|
||||
nextGridData.push({
|
||||
linkId: ingressLink.linkId,
|
||||
nextHop: ingressLink.nextHop,
|
||||
egressUsage: egressUsage,
|
||||
ingressUsage: ingressUsage,
|
||||
popoverWidth: this.computeWidth(egressUsage, ingressUsage, 'popover'),
|
||||
valueWidth: this.computeWidth(egressUsage, ingressUsage, 'value'),
|
||||
totalBitsRate: d.totalBitsRate,
|
||||
...d
|
||||
}]
|
||||
})
|
||||
egress: [{
|
||||
linkId: egressLink.linkId,
|
||||
nextHop: ingressLink.nextHop,
|
||||
egressUsage: egressUsage,
|
||||
ingressUsage: ingressUsage,
|
||||
popoverWidth: this.computeWidth(egressUsage, ingressUsage, 'popover'),
|
||||
valueWidth: this.computeWidth(egressUsage, ingressUsage, 'value'),
|
||||
totalBitsRate: d.totalBitsRate,
|
||||
...d
|
||||
}]
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
this.gridData2 = gridData2
|
||||
this.nextGridData = nextGridData
|
||||
}
|
||||
} else {
|
||||
this.isNoData = true
|
||||
this.isNextNoData = false
|
||||
this.isNextShowError = true
|
||||
// todo 此时返回的是msg,后期记得改为message
|
||||
this.nextErrorMsg = res[1].msg
|
||||
}
|
||||
}).catch(e => {
|
||||
console.error(e)
|
||||
this.isNoData = true
|
||||
|
||||
this.isLinkShowError = true
|
||||
// todo 此时返回的是msg,后期记得改为message
|
||||
this.linkErrorMsg = e[0].msg
|
||||
|
||||
this.isNextShowError = true
|
||||
this.nextErrorMsg = e[1].msg
|
||||
}).finally(() => {
|
||||
this.toggleLoading(false)
|
||||
})
|
||||
@@ -235,7 +251,7 @@ export default {
|
||||
/**
|
||||
* 本地计算npm分数
|
||||
*/
|
||||
localComputeScore (data, bandwidth) {
|
||||
localComputeScore (data) {
|
||||
let score = 0
|
||||
const dataScore = {
|
||||
establishLatencyMs: data.establishLatencyMs || null,
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
|
||||
<chart-no-data v-if="isNoData"></chart-no-data>
|
||||
|
||||
<div class="data-grid" v-show="!isNoData">
|
||||
<chart-error class="link-block-error" v-if="showError" :content="content"/>
|
||||
|
||||
<div class="data-grid" v-show="!isNoData && !showError">
|
||||
<div class="egress-row">
|
||||
<div class="egress-id" v-for="(item, index) in gridData" :key="index">
|
||||
<!--兼容下一跳情况-->
|
||||
@@ -73,7 +75,7 @@
|
||||
<div class="block-content-item-name">{{ $t('linkMonitor.linkBlock.total') }}</div>
|
||||
|
||||
<div class="block-content-item-value" :style="{width: row.egress[index2].valueWidth + 'px'}">
|
||||
{{unitConvert(row.egress[index2].totalBitsRate, unitTypes.bps).join('')}}
|
||||
{{ unitConvert(row.egress[index2].totalBitsRate, unitTypes.bps).join('') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -146,13 +148,18 @@
|
||||
import unitConvert from '@/utils/unit-convert'
|
||||
import { unitTypes } from '@/utils/constants'
|
||||
import ChartNoData from '@/views/charts/charts/ChartNoData'
|
||||
import ChartError from '@/components/common/Error'
|
||||
|
||||
export default {
|
||||
name: 'PopoverContent',
|
||||
props: {
|
||||
gridData: Array,
|
||||
isNoData: Boolean
|
||||
isNoData: Boolean,
|
||||
showError: Boolean,
|
||||
content: String
|
||||
},
|
||||
components: {
|
||||
ChartError,
|
||||
ChartNoData
|
||||
},
|
||||
data () {
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
</link-traffic-drill-down-list>
|
||||
<div class="line network link-traffic">
|
||||
<loading :loading="loading"></loading>
|
||||
<div class="line-header">
|
||||
<chart-error v-if="showError" :content="errorMsg" />
|
||||
<div class="line-header" v-if="!showError">
|
||||
<div class="line-header-left">
|
||||
<div class="line-value-active" v-if="lineTab"></div>
|
||||
<div class="line-value">
|
||||
@@ -59,22 +60,21 @@
|
||||
|
||||
<script>
|
||||
import chartMixin from '@/views/charts2/chart-mixin'
|
||||
import linkTrafficDrillDownLine from '@/views/charts2/charts/linkMonitor/localComponents/LinkTrafficDrillDownLine'
|
||||
import LinkTrafficDrillDownList from '@/views/charts2/charts/linkMonitor/localComponents/LinkTrafficDrillDownList'
|
||||
import ChartNoData from '@/views/charts/charts/ChartNoData'
|
||||
import Loading from '@/components/common/Loading'
|
||||
import {useRoute} from 'vue-router'
|
||||
import {ref, shallowRef} from 'vue'
|
||||
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 {getSecond} from '@/utils/date-util'
|
||||
import {get} from '@/utils/http'
|
||||
import {api} from '@/utils/api'
|
||||
import { chartColor3, chartColor4, unitTypes } from '@/utils/constants'
|
||||
import { overwriteUrl, urlParamsHandler } from '@/utils/tools'
|
||||
import { getSecond } from '@/utils/date-util'
|
||||
import { get } from '@/utils/http'
|
||||
import { api } from '@/utils/api'
|
||||
import _ from 'lodash'
|
||||
import * as echarts from 'echarts'
|
||||
import {linkTrafficLineChartOption} from '@/views/charts2/charts/options/echartOption'
|
||||
import {stackedLineTooltipFormatter} from '@/views/charts/charts/tools'
|
||||
import { linkTrafficLineChartOption } from '@/views/charts2/charts/options/echartOption'
|
||||
import { stackedLineTooltipFormatter } from '@/views/charts/charts/tools'
|
||||
|
||||
export default {
|
||||
name: 'LinkTrafficLine',
|
||||
@@ -126,7 +126,9 @@ export default {
|
||||
sizes: [3, 4, 6, 8, 9, 10],
|
||||
dynamicVariable: '',
|
||||
showMarkLine: true,
|
||||
loading: false
|
||||
loading: false,
|
||||
showError: false,
|
||||
errorMsg: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -148,7 +150,7 @@ export default {
|
||||
overwriteUrl(newUrl)
|
||||
},
|
||||
timeFilter: {
|
||||
handler (n) {
|
||||
handler () {
|
||||
if (this.lineTab) {
|
||||
this.init(this.lineMetric, this.showMarkLine, 'active')
|
||||
} else {
|
||||
@@ -176,15 +178,17 @@ export default {
|
||||
this.loading = true
|
||||
get(api.linkMonitor.totalTrafficAnalysis, params).then((res) => {
|
||||
if (res.code === 200) {
|
||||
this.showError = false
|
||||
this.isNoData = res.data.result.length === 0
|
||||
if (this.isNoData) {
|
||||
this.lineTab = ''
|
||||
this.mpackets = [
|
||||
{ analysis: {}, name: 'network.total', class: 'total', show: true, invertTab: true, positioning: 0, data: [], unitType: '' },
|
||||
{ analysis: {}, name: 'linkMonitor.ingress', class: 'ingress', show: true, invertTab: true, positioning: 1, data: [], unitType: '' },
|
||||
{ analysis: {}, name: 'linkMonitor.egress', class: 'egress', show: true, invertTab: true, positioning: 2, data: [], unitType: '' }
|
||||
]
|
||||
}
|
||||
res.data.result.forEach((t, i) => {
|
||||
res.data.result.forEach((t) => {
|
||||
if (t.type === 'bytes' && val === 'Bits/s') {
|
||||
const mpackets = _.cloneDeep(this.mpackets)
|
||||
mpackets[0].analysis = t.totalBitsRate.analysis
|
||||
@@ -196,7 +200,7 @@ export default {
|
||||
let num = 0
|
||||
mpackets.forEach(e => {
|
||||
e.unitType = 'bps'
|
||||
if (e.name !== 'network.total' && e.analysis.avg == 0) {
|
||||
if (e.name !== 'network.total' && parseFloat(e.analysis.avg) === 0) {
|
||||
e.show = false
|
||||
num += 1
|
||||
} else {
|
||||
@@ -206,7 +210,7 @@ export default {
|
||||
}
|
||||
}
|
||||
if (this.lineTab === e.class) {
|
||||
if (e.analysis.avg <= 0) {
|
||||
if (parseFloat(e.analysis.avg) <= 0) {
|
||||
this.lineTab = ''
|
||||
this.lineRefer = ''
|
||||
this.init()
|
||||
@@ -224,6 +228,7 @@ export default {
|
||||
} else {
|
||||
this.$nextTick(() => {
|
||||
this.echartsInit(this.mpackets)
|
||||
if (!this.lineRefer) this.lineRefer = 'Average'
|
||||
})
|
||||
}
|
||||
} else if (t.type === 'packets' && val === 'Packets/s') {
|
||||
@@ -237,7 +242,7 @@ export default {
|
||||
let num = 0
|
||||
mpackets.forEach(e => {
|
||||
e.unitType = 'packets/s'
|
||||
if (e.name !== 'network.total' && e.analysis.avg == 0) {
|
||||
if (e.name !== 'network.total' && parseFloat(e.analysis.avg) === 0) {
|
||||
e.show = false
|
||||
num += 1
|
||||
} else {
|
||||
@@ -247,7 +252,7 @@ export default {
|
||||
}
|
||||
}
|
||||
if (this.lineTab === e.class) {
|
||||
if (e.analysis.avg <= 0) {
|
||||
if (parseFloat(e.analysis.avg) <= 0) {
|
||||
this.lineTab = ''
|
||||
this.lineRefer = ''
|
||||
this.init()
|
||||
@@ -265,14 +270,22 @@ export default {
|
||||
} else {
|
||||
this.$nextTick(() => {
|
||||
this.echartsInit(this.mpackets)
|
||||
if (!this.lineRefer) this.lineRefer = 'Average'
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.showError = true
|
||||
// todo 此时返回的是msg,后期记得改
|
||||
this.errorMsg = res.msg
|
||||
// this.errorMsg = res.message
|
||||
}
|
||||
}).catch(e => {
|
||||
console.error(e)
|
||||
this.isNoData = true
|
||||
this.showError = true
|
||||
this.errorMsg = e.message
|
||||
// this.isNoData = true
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
@@ -298,7 +311,7 @@ export default {
|
||||
width: 1
|
||||
},
|
||||
stack: t.name !== 'network.total' ? 'network.total' : '',
|
||||
symbolSize: function (value, params) {
|
||||
symbolSize: function (value) {
|
||||
return _this.symbolSizeSortChange(i, value[0])
|
||||
},
|
||||
itemStyle: {
|
||||
@@ -334,19 +347,21 @@ export default {
|
||||
}
|
||||
})
|
||||
})
|
||||
const str = stackedLineTooltipFormatter(params)
|
||||
return str
|
||||
// const str = stackedLineTooltipFormatter(params)
|
||||
return stackedLineTooltipFormatter(params)
|
||||
}
|
||||
this.showMarkLine = true
|
||||
this.myChart.setOption(this.chartOption)
|
||||
},
|
||||
activeChange (item, index) {
|
||||
if (this.isNoData) return
|
||||
this.lineTab = item.class
|
||||
this.legendSelectChange(item, index, 'active')
|
||||
this.showMarkLine = !item.invertTab
|
||||
this.init(this.lineMetric, this.showMarkLine, 'active')
|
||||
},
|
||||
mouseenter (item) {
|
||||
if (this.isNoData) return
|
||||
this.mousemoveCursor = item.class
|
||||
this.handleActiveBar(item.class)
|
||||
},
|
||||
@@ -396,7 +411,7 @@ export default {
|
||||
})
|
||||
}
|
||||
},
|
||||
handleActiveBar (value) {
|
||||
handleActiveBar () {
|
||||
if (document.querySelector('.network .line-value-mpackets.is-active')) {
|
||||
const { offsetLeft, clientWidth, clientLeft } = document.querySelector('.network .line-value-mpackets.is-active')
|
||||
const activeBar = document.querySelector('.network .line-value-active')
|
||||
@@ -411,7 +426,7 @@ export default {
|
||||
this.lineTab = ''
|
||||
this.handleActiveBar()
|
||||
this.showMarkLine = !this.showMarkLine
|
||||
this.mpackets.forEach((e, i) => {
|
||||
this.mpackets.forEach((e) => {
|
||||
if (!e.invertTab) {
|
||||
e.invertTab = true
|
||||
}
|
||||
|
||||
@@ -2,21 +2,23 @@
|
||||
<div class="link-traffic-sankey">
|
||||
<el-tabs v-model="tab">
|
||||
<el-tab-pane :label="$t('linkMonitor.ingress')" name="0">
|
||||
<chart-error v-if="showError" :content="errorMsg"></chart-error>
|
||||
<chart-no-data v-if="ingress"></chart-no-data>
|
||||
<div v-if="tab == 0" class="chart-drawing" id="link-traffic-sankey-0"></div>
|
||||
<div v-if="parseInt(tab) === 0 && !showError" class="chart-drawing" id="link-traffic-sankey-0"></div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('linkMonitor.egress')" name="1">
|
||||
<chart-error v-if="showError" :content="errorMsg"></chart-error>
|
||||
<chart-no-data v-if="egress"></chart-no-data>
|
||||
<div v-if="tab == 1" class="chart-drawing" id="link-traffic-sankey-1"></div>
|
||||
<div v-if="parseInt(tab) === 1 && !showError" class="chart-drawing" id="link-traffic-sankey-1"></div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<template v-if="tab == 0 && !ingress">
|
||||
<template v-if="parseInt(tab) === 0 && !ingress">
|
||||
<div class="sankey__label" style="left: 5%;">External Locations</div>
|
||||
<div class="sankey__label" style="left: 35%;">Next-Hop Internets</div>
|
||||
<div class="sankey__label" style="left: 63%;">Links</div>
|
||||
<div class="sankey__label" style="right: 9%; transform: translateX(50%)">Internal Locations</div>
|
||||
</template>
|
||||
<template v-else-if="tab == 1 && !egress">
|
||||
<template v-else-if="parseInt(tab) === 1 && !egress">
|
||||
<div class="sankey__label" style="left: 5%;">Internal Locations</div>
|
||||
<div class="sankey__label" style="left: 33.2%;">Links</div>
|
||||
<div class="sankey__label" style="left: 64.5%;">Next-Hop Internets</div>
|
||||
@@ -38,11 +40,13 @@ import { useRoute } from 'vue-router'
|
||||
import { overwriteUrl, urlParamsHandler } from '@/utils/tools'
|
||||
import unitConvert from '@/utils/unit-convert'
|
||||
import { storageKey, unitTypes } from '@/utils/constants'
|
||||
import ChartError from '@/components/common/Error'
|
||||
|
||||
export default {
|
||||
name: 'LinksTrafficSankey',
|
||||
mixins: [chartMixin],
|
||||
components: {
|
||||
ChartError,
|
||||
ChartNoData
|
||||
},
|
||||
setup () {
|
||||
@@ -63,7 +67,9 @@ export default {
|
||||
egress: false,
|
||||
unitConvert,
|
||||
unitTypes,
|
||||
cnLinkInfo: JSON.parse(localStorage.getItem(storageKey.linkInfo))
|
||||
cnLinkInfo: JSON.parse(localStorage.getItem(storageKey.linkInfo)),
|
||||
showError: false,
|
||||
errorMsg: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -78,13 +84,14 @@ export default {
|
||||
overwriteUrl(newUrl)
|
||||
},
|
||||
timeFilter: {
|
||||
handler (n) {
|
||||
handler () {
|
||||
this.linkTrafficSankeyDataRequest(this.tab)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
linkTrafficSankeyDataRequest (n) {
|
||||
n = parseInt(n)
|
||||
const params = {
|
||||
startTime: getSecond(this.timeFilter.startTime),
|
||||
endTime: getSecond(this.timeFilter.endTime)
|
||||
@@ -93,19 +100,19 @@ export default {
|
||||
if (this.queryCondition) {
|
||||
const condition = this.queryCondition.toLowerCase().split(' or ')
|
||||
if (condition.length > 1) {
|
||||
if (n == 0) {
|
||||
if (n === 0) {
|
||||
params.q = condition.find(c => c.indexOf('common_ingress_link_id') > -1 || c.indexOf('ingress_link_direction') > -1)
|
||||
} else {
|
||||
params.q = condition.find(c => c.indexOf('common_egress_link_id') > -1 || c.indexOf('egress_link_direction') > -1)
|
||||
}
|
||||
}
|
||||
if (n == 0) {
|
||||
if (n === 0) {
|
||||
url = api.linkMonitor.drilldownQuadrupleIngressAnalysis // 入口
|
||||
} else {
|
||||
url = api.linkMonitor.drilldownQquadrupleEgressAnalysis // 出口
|
||||
}
|
||||
} else {
|
||||
if (n == 0) {
|
||||
if (n === 0) {
|
||||
url = api.linkMonitor.quadrupleIngressAnalysis // 入口
|
||||
} else {
|
||||
url = api.linkMonitor.quadrupleEgressAnalysis // 出口
|
||||
@@ -114,26 +121,32 @@ export default {
|
||||
this.toggleLoading(true)
|
||||
get(url, params).then(res => {
|
||||
if (res.code === 200) {
|
||||
if (n == 0) {
|
||||
this.showError = false
|
||||
if (n === 0) {
|
||||
this.ingress = res.data.result.length === 0
|
||||
} else {
|
||||
this.egress = res.data.result.length === 0
|
||||
}
|
||||
this.dataProcessing(res.data.result, n)
|
||||
this.dataProcessing(res.data.result, parseInt(n))
|
||||
} else {
|
||||
this.showError = true
|
||||
this.errorMsg = res.message
|
||||
}
|
||||
}).catch(e => {
|
||||
console.error(e)
|
||||
this.egress = true
|
||||
this.ingress = true
|
||||
this.showError = true
|
||||
this.errorMsg = e.message
|
||||
}).finally(() => {
|
||||
this.toggleLoading(false)
|
||||
})
|
||||
},
|
||||
dataProcessing (result, tab) {
|
||||
if (tab == 0) {
|
||||
if (tab === 0) {
|
||||
result.forEach(t => {
|
||||
this.cnLinkInfo.forEach(e => {
|
||||
if (t.commonIngressLinkId == e.originalLinkId) {
|
||||
if (t.commonIngressLinkId === e.originalLinkId) {
|
||||
t.linkId = e.linkId
|
||||
t.linkDirection = e.nextHop
|
||||
t.bandwidth = e.bandwidth
|
||||
@@ -146,7 +159,7 @@ export default {
|
||||
} else {
|
||||
result.forEach(t => {
|
||||
this.cnLinkInfo.forEach(e => {
|
||||
if (t.commonEgressLinkId == e.originalLinkId) {
|
||||
if (t.commonEgressLinkId === e.originalLinkId) {
|
||||
t.linkId = e.linkId
|
||||
t.bandwidth = e.bandwidth
|
||||
t.linkDirection = e.nextHop
|
||||
@@ -170,7 +183,7 @@ export default {
|
||||
const links1 = []
|
||||
const links2 = []
|
||||
const linksAnalyze2 = []
|
||||
if (tab == 1) {
|
||||
if (tab === 1) {
|
||||
result.forEach(r => {
|
||||
// 第一列
|
||||
if (!data0.some(d => d.name === r.client)) {
|
||||
@@ -357,18 +370,16 @@ export default {
|
||||
echartsInit (tab, data, links) {
|
||||
const _this = this
|
||||
let dom = ''
|
||||
if (tab == 0) {
|
||||
if (tab === 0) {
|
||||
dom = document.getElementById('link-traffic-sankey-0')
|
||||
if (this.myChart) {
|
||||
this.myChart.dispose()
|
||||
}
|
||||
this.myChart = echarts.init(dom)
|
||||
} else {
|
||||
dom = document.getElementById('link-traffic-sankey-1')
|
||||
if (this.myChart2) {
|
||||
this.myChart2.dispose()
|
||||
}
|
||||
this.myChart2 = echarts.init(dom)
|
||||
}
|
||||
this.chartOption = this.$_.cloneDeep(linksTrafficSankeyOption)
|
||||
this.chartOption.tooltip.formatter = function (param) {
|
||||
@@ -400,14 +411,18 @@ export default {
|
||||
}
|
||||
this.chartOption.series[0].data = data
|
||||
this.chartOption.series[0].links = links
|
||||
if (tab == 0) {
|
||||
this.myChart.setOption(this.chartOption)
|
||||
} else {
|
||||
this.myChart2.setOption(this.chartOption)
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
if (tab === 0) {
|
||||
this.myChart = echarts.init(dom)
|
||||
this.myChart.setOption(this.chartOption)
|
||||
} else {
|
||||
this.myChart2 = echarts.init(dom)
|
||||
this.myChart2.setOption(this.chartOption)
|
||||
}
|
||||
})
|
||||
},
|
||||
resize () {
|
||||
if (this.tab == 0) {
|
||||
if (this.tab === 0) {
|
||||
this.myChart.resize()
|
||||
} else {
|
||||
this.myChart2.resize()
|
||||
@@ -415,6 +430,9 @@ export default {
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.myChart = null
|
||||
this.myChart2 = null
|
||||
this.chartOption = null
|
||||
this.timer = setTimeout(() => {
|
||||
this.linkTrafficSankeyDataRequest(this.tab)
|
||||
}, 100)
|
||||
@@ -423,6 +441,19 @@ export default {
|
||||
beforeUnmount () {
|
||||
clearTimeout(this.timer)
|
||||
window.removeEventListener('resize', this.resize)
|
||||
if (this.myChart) {
|
||||
this.myChart.dispose()
|
||||
// 避免不能生效
|
||||
this.myChart = null
|
||||
}
|
||||
if (this.myChart2) {
|
||||
this.myChart2.dispose()
|
||||
this.myChart2 = null
|
||||
}
|
||||
this.chartOption = null
|
||||
|
||||
this.cnLinkInfo = null
|
||||
this.unitConvert = null
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,38 +1,42 @@
|
||||
<template>
|
||||
<div class="link-traffic-list">
|
||||
<loading :loading="loading"></loading>
|
||||
<div class="link-traffic-list-center">
|
||||
<div class="link-traffic-list-center-label">{{$t('network.total')}}</div>
|
||||
<div class="link-traffic-list-center-value" v-if="lineData[0] && lineData[0].analysis">{{unitConvert(lineData[0].analysis.avg, unitTypes.bps).join('')}}</div>
|
||||
</div>
|
||||
<div class="link-traffic-list-center">
|
||||
<div class="link-traffic-list-center-label">{{$t('linkMonitor.bandwidthUsage')}}</div>
|
||||
<div class="link-traffic-list-center-value" v-if="bandWidth && lineData[0] && lineData[0].analysis">{{unitConvert(lineData[0].analysis.avg / bandWidth, unitTypes.percent).join('')}}</div>
|
||||
<div class="link-traffic-list-center-value" v-else>-</div>
|
||||
</div>
|
||||
<div class="link-traffic-list-center">
|
||||
<div class="link-traffic-list-center-label">{{$t('linkMonitor.npmScore')}}</div>
|
||||
<div class="link-traffic-list-center-value">{{linkTrafficListData.npmScore || '-'}}</div>
|
||||
</div>
|
||||
<div class="link-traffic-list-center">
|
||||
<div class="link-traffic-list-center-label">{{$t('networkAppPerformance.tcpConnectionEstablishLatency')}}</div>
|
||||
<div class="link-traffic-list-center-value">{{unitConvert(Math.floor(linkTrafficListData.establishLatencyMs), unitTypes.time).join('')}}</div>
|
||||
</div>
|
||||
<div class="link-traffic-list-center">
|
||||
<div class="link-traffic-list-center-label">{{$t('networkAppPerformance.httpResponse')}}</div>
|
||||
<div class="link-traffic-list-center-value">{{unitConvert(Math.floor(linkTrafficListData.httpResponseLatency), unitTypes.time).join('')}}</div>
|
||||
</div>
|
||||
<div class="link-traffic-list-center">
|
||||
<div class="link-traffic-list-center-label">{{$t('networkAppPerformance.sslResponseLatency')}}</div>
|
||||
<div class="link-traffic-list-center-value">{{unitConvert(Math.floor(linkTrafficListData.sslConLatency), unitTypes.time).join('')}}</div>
|
||||
</div>
|
||||
<div class="link-traffic-list-center">
|
||||
<div class="link-traffic-list-center-label">{{$t('networkAppPerformance.packetLoss')}}</div>
|
||||
<div class="link-traffic-list-center-value">{{unitConvert(linkTrafficListData.tcpLostlenPercent, unitTypes.percent).join('')}}</div>
|
||||
</div>
|
||||
<div class="link-traffic-list-center">
|
||||
<div class="link-traffic-list-center-label">{{$t('overall.packetRetrans')}}</div>
|
||||
<div class="link-traffic-list-center-value">{{unitConvert(linkTrafficListData.pktRetransPercent, unitTypes.percent).join('')}}</div>
|
||||
|
||||
<chart-error v-if="showError" :content="errorMsg" />
|
||||
<div v-else>
|
||||
<div class="link-traffic-list-center">
|
||||
<div class="link-traffic-list-center-label">{{$t('network.total')}}</div>
|
||||
<div class="link-traffic-list-center-value" v-if="lineData[0] && lineData[0].analysis">{{unitConvert(lineData[0].analysis.avg, unitTypes.bps).join('')}}</div>
|
||||
</div>
|
||||
<div class="link-traffic-list-center">
|
||||
<div class="link-traffic-list-center-label">{{$t('linkMonitor.bandwidthUsage')}}</div>
|
||||
<div class="link-traffic-list-center-value" v-if="bandWidth && lineData[0] && lineData[0].analysis">{{unitConvert(lineData[0].analysis.avg / bandWidth, unitTypes.percent).join('')}}</div>
|
||||
<div class="link-traffic-list-center-value" v-else>-</div>
|
||||
</div>
|
||||
<div class="link-traffic-list-center">
|
||||
<div class="link-traffic-list-center-label">{{$t('linkMonitor.npmScore')}}</div>
|
||||
<div class="link-traffic-list-center-value">{{linkTrafficListData.npmScore || '-'}}</div>
|
||||
</div>
|
||||
<div class="link-traffic-list-center">
|
||||
<div class="link-traffic-list-center-label">{{$t('networkAppPerformance.tcpConnectionEstablishLatency')}}</div>
|
||||
<div class="link-traffic-list-center-value">{{unitConvert(Math.floor(linkTrafficListData.establishLatencyMs), unitTypes.time).join('')}}</div>
|
||||
</div>
|
||||
<div class="link-traffic-list-center">
|
||||
<div class="link-traffic-list-center-label">{{$t('networkAppPerformance.httpResponse')}}</div>
|
||||
<div class="link-traffic-list-center-value">{{unitConvert(Math.floor(linkTrafficListData.httpResponseLatency), unitTypes.time).join('')}}</div>
|
||||
</div>
|
||||
<div class="link-traffic-list-center">
|
||||
<div class="link-traffic-list-center-label">{{$t('networkAppPerformance.sslResponseLatency')}}</div>
|
||||
<div class="link-traffic-list-center-value">{{unitConvert(Math.floor(linkTrafficListData.sslConLatency), unitTypes.time).join('')}}</div>
|
||||
</div>
|
||||
<div class="link-traffic-list-center">
|
||||
<div class="link-traffic-list-center-label">{{$t('networkAppPerformance.packetLoss')}}</div>
|
||||
<div class="link-traffic-list-center-value">{{unitConvert(linkTrafficListData.tcpLostlenPercent, unitTypes.percent).join('')}}</div>
|
||||
</div>
|
||||
<div class="link-traffic-list-center">
|
||||
<div class="link-traffic-list-center-label">{{$t('overall.packetRetrans')}}</div>
|
||||
<div class="link-traffic-list-center-value">{{unitConvert(linkTrafficListData.pktRetransPercent, unitTypes.percent).join('')}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -48,6 +52,7 @@ import { useRoute } from 'vue-router'
|
||||
import { getSecond } from '@/utils/date-util'
|
||||
import { computeScore } from '@/utils/tools'
|
||||
import Loading from '@/components/common/Loading'
|
||||
import ChartError from '@/components/common/Error'
|
||||
export default {
|
||||
name: 'linkTrafficList',
|
||||
mixins: [chartMixin],
|
||||
@@ -62,6 +67,7 @@ export default {
|
||||
}
|
||||
},
|
||||
components: {
|
||||
ChartError,
|
||||
Loading
|
||||
},
|
||||
data () {
|
||||
@@ -72,7 +78,9 @@ export default {
|
||||
linkTrafficListData: {},
|
||||
cnLinkInfo: JSON.parse(localStorage.getItem(storageKey.linkInfo)),
|
||||
bandWidth: 0,
|
||||
loading: false
|
||||
loading: false,
|
||||
showError: false,
|
||||
errorMsg: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -91,6 +99,7 @@ export default {
|
||||
if (this.queryCondition) {
|
||||
const condition = this.queryCondition.toLowerCase().split(' or ')
|
||||
if (condition.length > 1) {
|
||||
// params.egressParam = true
|
||||
params.egressParam = condition.find(c => c.indexOf('common_egress_link_id') > -1 || c.indexOf('egress_link_direction') > -1)
|
||||
params.ingressParam = condition.find(c => c.indexOf('common_ingress_link_id') > -1 || c.indexOf('ingress_link_direction') > -1)
|
||||
let bandwidthAll = 0
|
||||
@@ -109,10 +118,10 @@ export default {
|
||||
}
|
||||
if (egressLinkId && ingressLinkId) {
|
||||
this.cnLinkInfo.forEach(e => {
|
||||
if (ingressLinkId == e.originalLinkId) {
|
||||
if (ingressLinkId === e.originalLinkId) {
|
||||
bandwidthAll += e.bandwidth
|
||||
}
|
||||
if (egressLinkId == e.originalLinkId) {
|
||||
if (egressLinkId === e.originalLinkId) {
|
||||
bandwidthAll += e.bandwidth
|
||||
}
|
||||
})
|
||||
@@ -129,6 +138,7 @@ export default {
|
||||
this.loading = true
|
||||
get(api.linkMonitor.networkAnalysis, params).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.showError = false
|
||||
this.isNoData = res.data.result.length === 0
|
||||
const data = {
|
||||
establishLatencyMs: res.data.result[0].establishLatencyMs || null,
|
||||
@@ -139,10 +149,17 @@ export default {
|
||||
}
|
||||
this.linkTrafficListData = res.data.result[0]
|
||||
this.linkTrafficListData.npmScore = computeScore(data)
|
||||
} else {
|
||||
this.showError = true
|
||||
// todo 此时返回的是msg,后期记得改
|
||||
this.errorMsg = res.msg
|
||||
// this.errorMsg = res.message
|
||||
}
|
||||
}).catch(e => {
|
||||
console.error(e)
|
||||
this.isNoData = true
|
||||
this.showError = true
|
||||
this.errorMsg = e.message
|
||||
// this.isNoData = true
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
<div class="network-overview-apps">
|
||||
<div class="network-overview-apps-header">
|
||||
<div class="network-overview-apps-title">{{$t('networkOverview.appType.providerAndApp')}}</div>
|
||||
<chart-error v-if="showError" tooltip :content="errorMsg" max-width="350" width="280" />
|
||||
</div>
|
||||
|
||||
<div class="app-cards">
|
||||
<div class="app-card" @mouseenter="mouseenter(app)" @mouseleave="mouseleave(app)" v-for="(app, index) in appData" :key="index">
|
||||
<div class="app-card" @mouseenter="mouseenter(app)" @mouseleave="mouseleave(app)" v-for="(app, index) in appData" :key="app.type + app.name">
|
||||
<div class="app-card-title">
|
||||
<div class="app-card-title-name">
|
||||
<i class="cn-icon" :class="app.type === 'provider' ? 'cn-icon-entity' : 'cn-icon-app2'"></i>
|
||||
@@ -137,6 +138,7 @@ export default {
|
||||
mixins: [chartMixin],
|
||||
data () {
|
||||
return {
|
||||
testData: '测试值',
|
||||
appData: [],
|
||||
// 假数据
|
||||
appTempData: [],
|
||||
@@ -163,7 +165,9 @@ export default {
|
||||
timerSearch: null,
|
||||
loadingBody: false,
|
||||
curTabState: curTabState,
|
||||
urlChangeParams: {}
|
||||
urlChangeParams: {},
|
||||
showError: false,
|
||||
errorMsg: ''
|
||||
}
|
||||
},
|
||||
props: {
|
||||
@@ -221,7 +225,7 @@ export default {
|
||||
startTime: getSecond(this.timeFilter.startTime),
|
||||
endTime: getSecond(this.timeFilter.endTime),
|
||||
appLabels: appCards.map(item => {
|
||||
return item.name
|
||||
return `'${item.name}'`
|
||||
}).join(',')
|
||||
}
|
||||
prevRequest = get(api.netWorkOverview.applicationCycleTrafficTotal, params)
|
||||
@@ -233,7 +237,7 @@ export default {
|
||||
startTime: getSecond(this.timeFilter.startTime),
|
||||
endTime: getSecond(this.timeFilter.endTime),
|
||||
appCompanies: providerCards.map(item => {
|
||||
return item.name
|
||||
return `'${item.name}'`
|
||||
}).join(',')
|
||||
}
|
||||
prevRequest = get(api.netWorkOverview.appCompanyCycleTrafficTotal, params)
|
||||
@@ -254,6 +258,7 @@ export default {
|
||||
})
|
||||
}
|
||||
if (res[0].code === 200 && res[1].code === 200) {
|
||||
this.showError = false
|
||||
const prevData = res[0].data.result
|
||||
const data = res[1].data.result
|
||||
let toCompareType = 'bytes'
|
||||
@@ -281,9 +286,13 @@ export default {
|
||||
})
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.showError = true
|
||||
this.errorMsg = res[0].message
|
||||
}
|
||||
}).catch(e => {
|
||||
console.error(e)
|
||||
this.showError = true
|
||||
this.errorMsg = e.message
|
||||
this.isNoData = true
|
||||
}).finally(() => {
|
||||
this.toggleLoading(false)
|
||||
@@ -400,18 +409,18 @@ export default {
|
||||
...chartOption.series[0],
|
||||
data: obj.lineData.map(v => [Number(v[0]) * 1000, Number(v[1]), 'number']),
|
||||
lineStyle: {
|
||||
color: obj.trend === 'up' ? '#7FA054' : '#35ADDA'
|
||||
color: '#35ADDA'
|
||||
},
|
||||
areaStyle: {
|
||||
opacity: 0.1,
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{
|
||||
offset: 0,
|
||||
color: obj.trend === 'up' ? '#7FA054' : '#35ADDA'
|
||||
color: '#35ADDA'
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: obj.trend === 'up' ? '#7FA054' : '#35ADDA'
|
||||
color: '#35ADDA'
|
||||
}
|
||||
])
|
||||
}
|
||||
@@ -461,7 +470,7 @@ export default {
|
||||
} else {
|
||||
params.pageNo = 1
|
||||
}
|
||||
if (this.appTypeTab === 0) {
|
||||
if (parseFloat(this.appTypeTab) === 0) {
|
||||
params.type = 'overviewProvide'
|
||||
get(api.dict, params).then(res => {
|
||||
if (res.code === 200) {
|
||||
@@ -486,7 +495,7 @@ export default {
|
||||
this.loading = false
|
||||
this.loadingBody = false
|
||||
})
|
||||
} else if (this.appTypeTab === 1) {
|
||||
} else if (parseFloat(this.appTypeTab) === 1) {
|
||||
params.type = 'overviewApp'
|
||||
get(api.dict, params).then(res => {
|
||||
res.data.list = res.data.list.filter(l => !this.appData.some(pd => pd.type === 'app' && pd.name === l.value))
|
||||
@@ -728,6 +737,8 @@ export default {
|
||||
window.removeEventListener('resize', this.resize)
|
||||
clearTimeout(this.timerScroll)
|
||||
clearTimeout(this.timerSearch)
|
||||
this.myChart = null
|
||||
this.unitConvert = null
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
<template>
|
||||
<div class="ddos-detection">
|
||||
<chart-no-data v-if="isNoData"></chart-no-data>
|
||||
<div class="ddos-detection-title"><i class="cn-icon cn-icon-a-DDosDetection"></i>{{$t('network.ddosDetection')}}</div>
|
||||
<div class="ddos-detection-value" v-if="!isNoData">
|
||||
<chart-error info v-if="showError" :content="errorMsg" />
|
||||
|
||||
<div class="ddos-detection-title">
|
||||
<i class="cn-icon cn-icon-a-DDosDetection"></i>
|
||||
{{$t('network.ddosDetection')}}
|
||||
</div>
|
||||
<div class="ddos-detection-value" v-if="!isNoData && !showError">
|
||||
<div class="ddos-detection-type">
|
||||
<div class="ddos-detection-type-value">
|
||||
<div class="ddos-detection-type-value-name">{{$t('network.numberOfAttacks')}}</div>
|
||||
@@ -28,21 +33,25 @@ 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'
|
||||
export default {
|
||||
name: 'NetworkOverviewDdosDetection',
|
||||
components: {
|
||||
ChartError,
|
||||
ChartNoData
|
||||
},
|
||||
mixins: [chartMixin],
|
||||
data () {
|
||||
return {
|
||||
ddosData: {},
|
||||
isNoData: false
|
||||
isNoData: false,
|
||||
showError: false,
|
||||
errorMsg: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
timeFilter: {
|
||||
handler (n) {
|
||||
handler () {
|
||||
this.ddosDetectDataRequests()
|
||||
}
|
||||
}
|
||||
@@ -56,13 +65,22 @@ export default {
|
||||
this.toggleLoading(true)
|
||||
get(api.netWorkOverview.ddosEventAnalysis, params).then(res => {
|
||||
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
|
||||
}
|
||||
} 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)
|
||||
})
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<div class="line network">
|
||||
<div class="line-header">
|
||||
<chart-error v-if="showError" :content="errorMsg" />
|
||||
<div class="line-header" v-if="!showError">
|
||||
<div class="line-header-left">
|
||||
<div class="line-value-active" v-if="lineTab"></div>
|
||||
<div class="line-value">
|
||||
@@ -44,8 +45,12 @@
|
||||
</div>
|
||||
</div>
|
||||
<div style="height: calc(100% - 74px); position: relative">
|
||||
<chart-no-data v-if="isNoData"></chart-no-data>
|
||||
<div class="chart-drawing" v-show="showMarkLine && !isNoData" id="overviewLineChart"></div>
|
||||
<chart-no-data v-if="isNoData && !showError"></chart-no-data>
|
||||
<div class="chart-drawing" v-show="showMarkLine && !isNoData && !showError" id="overviewLineChart"></div>
|
||||
<!-- todo 后续改动,此处为框选返回-->
|
||||
<!-- <div id="brushBtn" style="position: absolute;left: 0;top: 0;" v-show="mouseDownFlag">-->
|
||||
<!-- <el-button @click.stop="backBrushHistory">返回</el-button>-->
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -65,9 +70,11 @@ 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 ChartError from '@/components/common/Error'
|
||||
export default {
|
||||
name: 'NetworkOverviewLine',
|
||||
components: {
|
||||
ChartError,
|
||||
ChartNoData
|
||||
},
|
||||
props: {
|
||||
@@ -81,10 +88,14 @@ export default {
|
||||
const lineRefer = ref(query.lineRefer || 'Average')
|
||||
const lineTab = ref(query.lineTab || '')
|
||||
const queryCondition = ref(query.queryCondition || '')
|
||||
const tabOperationType = ref(query.tabOperationType)
|
||||
const networkOverviewBeforeTab = ref(query.networkOverviewBeforeTab)
|
||||
return {
|
||||
lineRefer,
|
||||
lineTab,
|
||||
queryCondition,
|
||||
tabOperationType,
|
||||
networkOverviewBeforeTab,
|
||||
myChart: shallowRef(null)
|
||||
}
|
||||
},
|
||||
@@ -121,7 +132,11 @@ export default {
|
||||
leftOffset: 0,
|
||||
sizes: [3, 4, 6, 8, 9, 10],
|
||||
dynamicVariable: '',
|
||||
showMarkLine: true
|
||||
showMarkLine: true,
|
||||
mouseDownFlag: false,
|
||||
brushHistory: [],
|
||||
showError: false,
|
||||
errorMsg: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -143,7 +158,7 @@ export default {
|
||||
overwriteUrl(newUrl)
|
||||
},
|
||||
timeFilter: {
|
||||
handler (n) {
|
||||
handler () {
|
||||
if (this.lineTab) {
|
||||
this.init(this.metric, this.showMarkLine, 'active')
|
||||
} else {
|
||||
@@ -154,7 +169,7 @@ export default {
|
||||
metric (n) {
|
||||
this.handleActiveBar()
|
||||
this.showMarkLine = !this.showMarkLine
|
||||
this.mpackets.forEach((e, i) => {
|
||||
this.mpackets.forEach((e) => {
|
||||
if (!e.invertTab) {
|
||||
e.invertTab = true
|
||||
}
|
||||
@@ -171,16 +186,34 @@ export default {
|
||||
startTime: getSecond(this.timeFilter.startTime),
|
||||
endTime: getSecond(this.timeFilter.endTime)
|
||||
}
|
||||
// const condition = this.$store.getters.getQueryCondition
|
||||
// const condition = this.$route.query.queryCondition ? this.$route.query.queryCondition : ''
|
||||
if (this.queryCondition) {
|
||||
let condition = ''
|
||||
if (this.queryCondition && this.tabOperationType !== '3') {
|
||||
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) => {
|
||||
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 = [
|
||||
{ analysis: {}, name: 'network.total', class: 'total', show: true, invertTab: true, positioning: 0, data: [], unitType: '' },
|
||||
{ analysis: {}, name: 'network.inbound', class: 'inbound', show: true, invertTab: true, positioning: 1, data: [], unitType: '' },
|
||||
@@ -190,7 +223,7 @@ export default {
|
||||
{ analysis: {}, name: 'network.other', class: 'other', show: true, invertTab: true, positioning: 5, data: [], unitType: '' }
|
||||
]
|
||||
}
|
||||
res.data.result.forEach((t, i) => {
|
||||
res.data.result.forEach((t) => {
|
||||
if (t.type === 'bytes' && val === 'Bits/s') {
|
||||
const mpackets = _.cloneDeep(this.mpackets)
|
||||
mpackets[0].analysis = t.totalBitsRate.analysis
|
||||
@@ -208,7 +241,7 @@ export default {
|
||||
let num = 0
|
||||
mpackets.forEach(e => {
|
||||
e.unitType = 'bps'
|
||||
if (e.name !== 'network.total' && e.analysis.avg == 0) {
|
||||
if (e.name !== 'network.total' && parseFloat(e.analysis.avg) === 0) {
|
||||
e.show = false
|
||||
num += 1
|
||||
} else {
|
||||
@@ -218,7 +251,7 @@ export default {
|
||||
}
|
||||
}
|
||||
if (this.lineTab === e.class) {
|
||||
if (e.analysis.avg <= 0) {
|
||||
if (parseFloat(e.analysis.avg) <= 0) {
|
||||
this.lineTab = ''
|
||||
this.lineRefer = ''
|
||||
this.init()
|
||||
@@ -237,6 +270,7 @@ export default {
|
||||
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') {
|
||||
@@ -256,7 +290,7 @@ export default {
|
||||
let num = 0
|
||||
mpackets.forEach(e => {
|
||||
e.unitType = 'packets/s'
|
||||
if (e.name !== 'network.total' && e.analysis.avg == 0) {
|
||||
if (e.name !== 'network.total' && parseFloat(e.analysis.avg) === 0) {
|
||||
e.show = false
|
||||
num += 1
|
||||
} else {
|
||||
@@ -266,7 +300,7 @@ export default {
|
||||
}
|
||||
}
|
||||
if (this.lineTab === e.class) {
|
||||
if (e.analysis.avg <= 0) {
|
||||
if (parseFloat(e.analysis.avg) <= 0) {
|
||||
this.lineTab = ''
|
||||
this.lineRefer = ''
|
||||
this.init()
|
||||
@@ -285,6 +319,7 @@ export default {
|
||||
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') {
|
||||
@@ -306,14 +341,41 @@ export default {
|
||||
})
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.showError = true
|
||||
this.errorMsg = res.message
|
||||
}
|
||||
}).catch(e => {
|
||||
console.error(e)
|
||||
this.isNoData = true
|
||||
this.showError = true
|
||||
this.errorMsg = e.message
|
||||
this.isNoData = false
|
||||
}).finally(() => {
|
||||
this.toggleLoading(false)
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 初始化echartsdom,用于右键点击返回框选
|
||||
*/
|
||||
domInit () {
|
||||
const self = this
|
||||
// 去掉默认的contextmenu事件,否则会和右键事件同时出现。
|
||||
document.oncontextmenu = function (e) {
|
||||
e.preventDefault()
|
||||
}
|
||||
document.getElementById('overviewLineChart').onmousedown = function (e) {
|
||||
// e.button: 0左键,1滚轮,2右键
|
||||
if (e.button === 2) {
|
||||
self.myChart.dispatchAction({
|
||||
type: 'brush',
|
||||
areas: [] // 删除选框
|
||||
})
|
||||
self.mouseDownFlag = true
|
||||
document.getElementById('brushBtn').style.left = e.layerX + 'px'
|
||||
document.getElementById('brushBtn').style.top = e.layerY + 74 + 'px'
|
||||
}
|
||||
}
|
||||
},
|
||||
echartsInit (echartsData, show) {
|
||||
if (this.lineTab) {
|
||||
this.handleActiveBar()
|
||||
@@ -322,8 +384,13 @@ export default {
|
||||
echartsData = echartsData.filter(t => t.show === true)
|
||||
}
|
||||
const _this = this
|
||||
const dom = document.getElementById('overviewLineChart')
|
||||
!this.myChart && (this.myChart = echarts.init(dom))
|
||||
// !this.myChart && (this.myChart = echarts.init(dom))
|
||||
// 此处为验证是否因dom未销毁,导致图表出错,后续可能会改
|
||||
let dom = null
|
||||
dom = document.getElementById('overviewLineChart')
|
||||
if (this.myChart) {
|
||||
this.myChart.dispose()
|
||||
}
|
||||
this.chartOption = stackedLineChartOption
|
||||
const chartOption = this.chartOption.series[0]
|
||||
this.chartOption.series = echartsData.map((t, i) => {
|
||||
@@ -335,7 +402,7 @@ export default {
|
||||
width: 1
|
||||
},
|
||||
stack: t.name !== 'network.total' ? 'network.total' : '',
|
||||
symbolSize: function (value, params) {
|
||||
symbolSize: function (value) {
|
||||
return _this.symbolSizeSortChange(i, value[0])
|
||||
},
|
||||
itemStyle: {
|
||||
@@ -379,7 +446,7 @@ export default {
|
||||
}
|
||||
})
|
||||
if (!show) {
|
||||
this.chartOption.series.forEach((t, i) => {
|
||||
this.chartOption.series.forEach((t) => {
|
||||
t.markLine.label.show = false
|
||||
t.markLine = []
|
||||
})
|
||||
@@ -421,15 +488,65 @@ export default {
|
||||
return str
|
||||
}
|
||||
this.showMarkLine = true
|
||||
this.myChart.setOption(this.chartOption)
|
||||
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])
|
||||
}
|
||||
|
||||
// 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
|
||||
this.lineTab = item.class
|
||||
this.legendSelectChange(item, index, 'active')
|
||||
this.showMarkLine = !item.invertTab
|
||||
this.init(this.metric, this.showMarkLine, 'active')
|
||||
},
|
||||
mouseenter (item) {
|
||||
if (this.isNoData) return
|
||||
this.mousemoveCursor = item.class
|
||||
this.handleActiveBar(item.class)
|
||||
},
|
||||
@@ -479,7 +596,7 @@ export default {
|
||||
})
|
||||
}
|
||||
},
|
||||
handleActiveBar (value) {
|
||||
handleActiveBar () {
|
||||
if (document.querySelector('.network .line-value-mpackets.is-active')) {
|
||||
const { offsetLeft, clientWidth, clientLeft } = document.querySelector('.network .line-value-mpackets.is-active')
|
||||
const activeBar = document.querySelector('.network .line-value-active')
|
||||
@@ -540,9 +657,27 @@ export default {
|
||||
dataIntegrationArray.sort((a, b) => { return a[1] - b[1] })
|
||||
const sortIndex = dataIntegrationArray.findIndex(a => a[2] === index)
|
||||
return this.sizes[sortIndex]
|
||||
},
|
||||
/**
|
||||
* 鼠标右键返回框选的时间范围
|
||||
*/
|
||||
backBrushHistory () {
|
||||
this.myChart.dispatchAction({
|
||||
type: 'brush',
|
||||
areas: [] // 删除选框
|
||||
})
|
||||
if (this.brushHistory.length > 0) {
|
||||
this.$store.commit('setRangeEchartsData', _.cloneDeep(this.brushHistory[0]))
|
||||
this.brushHistory.shift()
|
||||
}
|
||||
this.mouseDownFlag = false
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
// todo 初始化鼠标事件,开启右键返回
|
||||
// this.domInit()
|
||||
this.myChart = null
|
||||
this.chartOption = null
|
||||
this.timer = setTimeout(() => {
|
||||
if (this.lineTab) {
|
||||
const data = this.mpackets.find(t => t.class === this.lineTab)
|
||||
@@ -558,6 +693,15 @@ export default {
|
||||
beforeUnmount () {
|
||||
clearTimeout(this.timer)
|
||||
window.removeEventListener('resize', this.resize)
|
||||
|
||||
let myChart = echarts.getInstanceByDom(document.getElementById('overviewLineChart'))
|
||||
if (myChart) {
|
||||
echarts.dispose(myChart)
|
||||
}
|
||||
this.myChart = null
|
||||
// 检测时发现该方法占用较大内存,且未被释放
|
||||
this.unitConvert = null
|
||||
myChart = null
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,18 +1,24 @@
|
||||
<template>
|
||||
<div class="performance-event">
|
||||
<div class="performance-event-title"><i class="cn-icon cn-icon-a-NetworkPerformanceEvent"></i>{{$t('network.networkPerEvent')}}</div>
|
||||
<div class="performance-event-title">
|
||||
<i class="cn-icon cn-icon-a-NetworkPerformanceEvent"></i>{{$t('network.networkPerEvent')}}
|
||||
</div>
|
||||
<div class="performance-event-value">
|
||||
<div class="performance-event-pie">
|
||||
<chart-no-data v-if="isNoData"></chart-no-data>
|
||||
<chart-error v-if="showError1" info :content="errorMsg1" />
|
||||
<div class="chart-drawing" id="chart1" v-show="!isNoData"></div>
|
||||
</div>
|
||||
<div class="performance-event-pie-hr"></div>
|
||||
<div class="performance-event-pie">
|
||||
<chart-no-data v-if="isNoData2"></chart-no-data>
|
||||
<chart-error v-if="showError1" info :content="errorMsg1" />
|
||||
<div class="chart-drawing" id="chart2" v-show="!isNoData2"></div>
|
||||
</div>
|
||||
</div>
|
||||
<el-button class="pie-button" size="small" @click="routerJump">{{$t('network.dashboards')}}<i class="cn-icon cn-icon-arrow-right"></i></el-button>
|
||||
<el-button class="pie-button" size="small" @click="routerJump">
|
||||
{{$t('network.dashboards')}}<i class="cn-icon cn-icon-arrow-right"></i>
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -25,6 +31,7 @@ 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 ChartError from '@/components/common/Error'
|
||||
export default {
|
||||
name: 'NetworkOverviewPerformanceEvent',
|
||||
setup () {
|
||||
@@ -35,6 +42,7 @@ export default {
|
||||
},
|
||||
mixins: [chartMixin],
|
||||
components: {
|
||||
ChartError,
|
||||
ChartNoData
|
||||
},
|
||||
data () {
|
||||
@@ -43,12 +51,17 @@ export default {
|
||||
isNoData: false,
|
||||
isNoData2: false,
|
||||
loading1: false,
|
||||
loading2: false
|
||||
loading2: false,
|
||||
showError1: false,
|
||||
showError2: false,
|
||||
errorMsg1: '',
|
||||
errorMsg2: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
init () {
|
||||
const params = {
|
||||
// startTime: true,
|
||||
startTime: getSecond(this.timeFilter.startTime),
|
||||
endTime: getSecond(this.timeFilter.endTime)
|
||||
}
|
||||
@@ -60,6 +73,7 @@ export default {
|
||||
this.loading1 = true
|
||||
get(api.netWorkOverview.eventSeverity, params).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.showError1 = false
|
||||
if (res.data.result.length === 0) {
|
||||
this.isNoData = true
|
||||
return
|
||||
@@ -88,8 +102,14 @@ export default {
|
||||
this.chartOption.series[0].data = res.data.result.sort((a, b) => { return a.index - b.index })
|
||||
this.myChart.setOption(this.chartOption)
|
||||
} else {
|
||||
this.isNoData = true
|
||||
this.isNoData = false
|
||||
this.showError1 = true
|
||||
this.errorMsg1 = res.message
|
||||
}
|
||||
}).catch((e) => {
|
||||
this.isNoData = false
|
||||
this.showError1 = true
|
||||
this.errorMsg1 = e.message
|
||||
}).finally(() => {
|
||||
this.loading1 = false
|
||||
})
|
||||
@@ -100,6 +120,8 @@ export default {
|
||||
this.loading2 = true
|
||||
get(api.netWorkOverview.eventType, params).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.showError2 = false
|
||||
|
||||
if (res.data.result.length === 0) {
|
||||
this.isNoData2 = true
|
||||
return
|
||||
@@ -119,7 +141,15 @@ export default {
|
||||
}
|
||||
this.chartOption2.series[0].data = res.data.result
|
||||
this.myChart2.setOption(this.chartOption2)
|
||||
} else {
|
||||
this.isNoData2 = false
|
||||
this.showError2 = true
|
||||
this.errorMsg2 = res.message
|
||||
}
|
||||
}).catch((e) => {
|
||||
this.isNoData2 = false
|
||||
this.showError2 = true
|
||||
this.errorMsg2 = e.message
|
||||
}).finally(() => {
|
||||
this.loading2 = false
|
||||
})
|
||||
@@ -163,6 +193,8 @@ export default {
|
||||
beforeUnmount () {
|
||||
clearTimeout(this.timer)
|
||||
window.removeEventListener('resize', this.resize)
|
||||
this.myChart = null
|
||||
this.myChart2 = null
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="tabs" :style="showCustomizeTabs ? (tableData.length > 10 && showRecordNum === 10 ? 'height: calc(100% - 40px);'
|
||||
<div class="tabs" :style="showCustomizeTabs ? (tableData.length > 10 && showRecordNum === 10 ? 'height: calc(100% - 36px);'
|
||||
: 'height: calc(100% - 2px)')
|
||||
: (tableData.length > 10 && showRecordNum === 10 ? 'height: calc(100% - 64px);'
|
||||
: (tableData.length > 10 && showRecordNum === 10 ? 'height: calc(100% - 77px);'
|
||||
: 'height: calc(100% - 26px);')">
|
||||
<el-tabs v-model="activeTab"
|
||||
:class="showCustomizeTabs?'cn-chart__tabs':'tab-hide cn-chart__tabs cn-chart__tabs-hide-tab'"
|
||||
@@ -33,7 +33,7 @@
|
||||
<template v-for="(item, index) in customTableTitles">
|
||||
<el-table-column
|
||||
v-if="item.checked"
|
||||
:sortable="sortable(item)"
|
||||
:sortable="item.showError ? false : sortable(item)"
|
||||
align="center"
|
||||
:prop="item.prop"
|
||||
class="data-column"
|
||||
@@ -42,6 +42,7 @@
|
||||
>
|
||||
<template #header >
|
||||
<span class="data-column__span" >{{$t(item.label)}}</span>
|
||||
<chart-error v-if="item.showError" tooltip :content="item.errorMsg" width="300" />
|
||||
</template>
|
||||
<template #default="scope" :column="item">
|
||||
<template v-if="item.columnType === tableColumnType.chainRatio" >
|
||||
@@ -82,7 +83,7 @@
|
||||
</template>
|
||||
</div>
|
||||
<div v-else class="data-click" @click="handleTabValue(item.name,scope.row['tab'])">
|
||||
<template v-if="isDnsMapType">
|
||||
<template v-if="tableType === fromRoute.dnsServiceInsights && isDnsMapType">
|
||||
{{dnsMapData.get(scope.row['tab'])}}
|
||||
</template>
|
||||
<template v-else>
|
||||
@@ -123,8 +124,9 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
<template v-slot:empty>
|
||||
<div class="table-no-data" v-if="isNoData">
|
||||
<template v-slot:empty >
|
||||
<chart-error v-if="showError" :content="errorMsg" />
|
||||
<div class="table-no-data" v-else-if="isNoData">
|
||||
<div class="table-no-data__title">{{ $t('npm.noData') }}</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -169,7 +171,7 @@
|
||||
</li>
|
||||
</transition-group>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('network.direction')" name="metrics" width="50%" >
|
||||
<el-tab-pane :label="tableType==='networkOverview'?$t('network.direction'):$t('network.metrics')" name="metrics" width="50%" >
|
||||
<transition-group name="dragMetric" class="list" tag="ul" ref="metric">
|
||||
<template v-for="(item, index) in customTableTitles" :key="item.label">
|
||||
<li v-if="index>0"
|
||||
@@ -196,15 +198,15 @@
|
||||
</template>
|
||||
<script>
|
||||
import { ref } from 'vue'
|
||||
import { operationType, unitTypes, networkTable, tableColumnType, networkDefaultLimit, curTabState, storageKey, dbDrilldownTableConfig,fromRoute } from '@/utils/constants'
|
||||
import { operationType, unitTypes, networkTable, tableColumnType, networkDefaultLimit, curTabState, storageKey, dbDrilldownTableConfig, fromRoute } from '@/utils/constants'
|
||||
import { get } from '@/utils/http'
|
||||
import unitConvert from '@/utils/unit-convert'
|
||||
import { getChainRatio, computeScore, urlParamsHandler, overwriteUrl, getUserDrilldownTableGeo, readDrilldownTableConfigByUser, combinDrilldownTableWithUserConfig,getDnsMapData } from '@/utils/tools'
|
||||
import { getChainRatio, computeScore, urlParamsHandler, overwriteUrl, getUserDrilldownTableGeo, readDrilldownTableConfigByUser, combinDrilldownTableWithUserConfig, getDnsMapData,handleSpecialValue,getConfigVersion } from '@/utils/tools'
|
||||
import { getSecond } from '@/utils/date-util'
|
||||
import chartMixin from '@/views/charts2/chart-mixin'
|
||||
import ChartNoData from '@/views/charts/charts/ChartNoData'
|
||||
import { db } from '@/indexedDB'
|
||||
import { api,getDictList } from '@/utils/api'
|
||||
import { api, getDictList } from '@/utils/api'
|
||||
|
||||
export default {
|
||||
name: 'NetworkOverviewTabs',
|
||||
@@ -250,16 +252,18 @@ export default {
|
||||
column: {},
|
||||
index: 0,
|
||||
chartData: [],
|
||||
dnsMapData:[],
|
||||
dnsQtypeMapData:[],
|
||||
dnsRcodeMapData:[],
|
||||
isDnsMapType:false,
|
||||
dnsMapData: new Map(),
|
||||
dnsQtypeMapData: new Map(),
|
||||
dnsRcodeMapData: new Map(),
|
||||
isDnsMapType: false,
|
||||
tableSortColumn: '',
|
||||
tableSortType: '',
|
||||
tableSortTab: '',
|
||||
urlChangeParams: {},
|
||||
showUnit: false,
|
||||
fromRoute: fromRoute,
|
||||
showError: false,
|
||||
errorMsg: ''
|
||||
}
|
||||
},
|
||||
props: {
|
||||
@@ -327,14 +331,20 @@ export default {
|
||||
const requestUrl = this.getCurUrl()
|
||||
get(requestUrl, queryParams).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.showError = false
|
||||
this.errorMsg = ''
|
||||
this.chartData = response.data.result
|
||||
this.initData()
|
||||
} else {
|
||||
this.showError = true
|
||||
this.errorMsg = response.message || 'Unknown'
|
||||
this.isNoData = true
|
||||
this.toggleLoading(false)
|
||||
}
|
||||
}).catch(e => {
|
||||
console.error(e)
|
||||
this.showError = true
|
||||
this.errorMsg = e.message || 'Unknown'
|
||||
}).finally(() => {
|
||||
this.changeUrlTabState()
|
||||
this.toggleLoading(false)
|
||||
@@ -613,8 +623,14 @@ export default {
|
||||
endTime: getSecond(this.timeFilter.endTime)
|
||||
}
|
||||
if (tabList.length > 0) {
|
||||
const conditionStr = tabList.filter(item => item != '')
|
||||
queryParams.params = conditionStr.toString().replaceAll("'", "\\\\'")
|
||||
let conditionGroup = tabList.filter(item => item != '')
|
||||
let conditionHandleRlt = []
|
||||
conditionGroup.forEach(condition => {
|
||||
condition = handleSpecialValue(condition)//condition.replaceAll("'", "\\\\'")
|
||||
condition = "'"+condition+ "'"
|
||||
conditionHandleRlt.push(condition)
|
||||
})
|
||||
queryParams.params = conditionHandleRlt.join(",")
|
||||
queryParams.type = curTab.prop
|
||||
}
|
||||
|
||||
@@ -630,6 +646,8 @@ export default {
|
||||
if (tableColumn.columnType === tableColumnType.chainRatio && tableColumn.isInMainUrl && tableDataTmp && tableDataTmp.length > 0) {
|
||||
get(self.gerCycleUrl(), queryParams).then(response => {
|
||||
if (response.code === 200) {
|
||||
tableColumn.showError = false
|
||||
tableColumn.errorMsg = ''
|
||||
cycleTotalList = response.data.result
|
||||
tableDataTmp.forEach(item => {
|
||||
const cycle = cycleTotalList.find(i => i[curTab.prop] === item.tab)
|
||||
@@ -674,9 +692,14 @@ export default {
|
||||
}
|
||||
item[tableColumn.prop] = [(item[tableColumn.prop] || item[tableColumn.prop] === 0) ? item[tableColumn.prop] : '', trend, trendPercent]
|
||||
})
|
||||
}else {
|
||||
tableColumn.showError = true
|
||||
tableColumn.errorMsg = response.message || 'Unknown'
|
||||
}
|
||||
}).catch(e => {
|
||||
console.log(e)
|
||||
tableColumn.showError = true
|
||||
tableColumn.errorMsg = e.message || 'Unknown'
|
||||
}).finally(e => {
|
||||
this.tableData = tableDataTmp
|
||||
this.tableDataBackup = tableDataTmp
|
||||
@@ -689,6 +712,10 @@ export default {
|
||||
if (tableColumn.columnType === tableColumnType.chainRatio && !tableColumn.isInMainUrl) {
|
||||
get(self.gerColumnUrl(tableColumn), queryParams).then(response => {
|
||||
if (response.code === 200) {
|
||||
if (!tableColumn.showError) {
|
||||
tableColumn.showError = false
|
||||
tableColumn.errorMsg = ''
|
||||
}
|
||||
const columnList = response.data.result
|
||||
self.tableData.forEach((item, i) => {
|
||||
const data = columnList.find(i => i[curTab.prop] === item.tab)
|
||||
@@ -703,11 +730,19 @@ export default {
|
||||
}
|
||||
if (Object.keys(item.scoreGroup).length >= 5) {
|
||||
item.score = computeScore(item.scoreGroup)
|
||||
if(!_.isNumber(item.score)){
|
||||
item.score = 0
|
||||
}
|
||||
}
|
||||
})
|
||||
}else {
|
||||
tableColumn.showError = true
|
||||
tableColumn.errorMsg = response.message || 'Unknown'
|
||||
}
|
||||
}).catch(e => {
|
||||
console.log(e)
|
||||
tableColumn.showError = true
|
||||
tableColumn.errorMsg = e.message || 'Unknown'
|
||||
}).finally(e => {
|
||||
// 查询需要单独查询的,且需要展示环比图标,列的前一周期的数据
|
||||
if (tableColumn.cycle && self.tableData && self.tableData.length > 0) {
|
||||
@@ -717,6 +752,10 @@ export default {
|
||||
}
|
||||
get(self.gerColumnUrl(tableColumn), queryCycleParams).then(response => {
|
||||
if (response.code === 200) {
|
||||
if(!tableColumn.showError){
|
||||
tableColumn.showError = false
|
||||
tableColumn.errorMsg = ''
|
||||
}
|
||||
cycleTotalList = response.data.result
|
||||
self.tableData.forEach(item => {
|
||||
const cycle = cycleTotalList.find(i => i[curTab.prop] === item.tab)
|
||||
@@ -764,9 +803,14 @@ export default {
|
||||
item[tableColumn.prop] = [(item[tableColumn.prop] || item[tableColumn.prop] === 0) ? item[tableColumn.prop] : '', trend, trendPercent]
|
||||
}
|
||||
})
|
||||
}else {
|
||||
tableColumn.showError = true
|
||||
tableColumn.errorMsg = response.message || 'Unknown'
|
||||
}
|
||||
}).catch(e => {
|
||||
console.log(e)
|
||||
tableColumn.showError = true
|
||||
tableColumn.errorMsg = e.message || 'Unknown'
|
||||
})
|
||||
}
|
||||
})
|
||||
@@ -824,7 +868,7 @@ export default {
|
||||
this.index = index
|
||||
this.column = column
|
||||
const arr = []
|
||||
this.tableData.slice(0, this.showRecordNum).forEach(val => {
|
||||
this.tableData.forEach(val => {
|
||||
arr.push(val)
|
||||
})
|
||||
if (column.order == 'descending') {
|
||||
@@ -866,11 +910,7 @@ export default {
|
||||
return res
|
||||
}
|
||||
})
|
||||
if (this.tableData.length - 1 > this.showRecordNum) {
|
||||
this.tableData = arr.concat(this.tableDataBackup.slice(this.showRecordNum))
|
||||
} else {
|
||||
this.tableData = arr
|
||||
}
|
||||
this.tableData = arr
|
||||
} else if (column.order == 'ascending') {
|
||||
arr.sort((a, b) => {
|
||||
const str1 = Array.isArray(a[column.prop]) ? a[column.prop][0] : a[column.prop]
|
||||
@@ -910,11 +950,7 @@ export default {
|
||||
return res
|
||||
}
|
||||
})
|
||||
if (this.tableData.length - 1 > this.showRecordNum) {
|
||||
this.tableData = arr.concat(this.tableDataBackup.slice(this.showRecordNum))
|
||||
} else {
|
||||
this.tableData = arr
|
||||
}
|
||||
this.tableData = arr
|
||||
} else if (!column.order) {
|
||||
this.tableData = this.tableDataBackup
|
||||
}
|
||||
@@ -1075,7 +1111,7 @@ export default {
|
||||
this.urlChangeParams[this.curTabState.networkOverviewBeforeTab] = tab.prop
|
||||
},
|
||||
setQueryCondition (tab, value) {
|
||||
value = value.replaceAll("'", "\\\\'")
|
||||
value = handleSpecialValue(value)//value.replaceAll("'", "\\\\'")
|
||||
const queryCondition = []
|
||||
if (tab.prop === 'protocolPort') {
|
||||
const valueGroup = value.split(':')
|
||||
@@ -1087,7 +1123,7 @@ export default {
|
||||
} else {
|
||||
if (tab.queryCondition) {
|
||||
tab.queryCondition.forEach(item => {
|
||||
queryCondition.push(item.replace('$param', value))
|
||||
queryCondition.push(item.replaceAll('$param', value))
|
||||
})
|
||||
} else {
|
||||
if (tab.dillDownProp) {
|
||||
@@ -1115,8 +1151,10 @@ export default {
|
||||
4.设置菜单:第三级,第四级名称,并保存到store中
|
||||
5.设置panel名称,表格维度类型:如ip,domain等(即查询参数中的type)
|
||||
* */
|
||||
handleTabValue (columnName, columnValue) {
|
||||
async handleTabValue (columnName, columnValue) {
|
||||
// console.log('NetworkOverview类------handleTabValue:下钻')
|
||||
// 下钻前保存当前路由状态
|
||||
this.beforeRouterPush()
|
||||
const clickTab = this.getTabByName(columnName)// 下钻后,显示的下钻tab对应的drilldownTabs
|
||||
const tabLable = clickTab.label
|
||||
const tabName = clickTab.name
|
||||
@@ -1155,14 +1193,13 @@ export default {
|
||||
})
|
||||
}
|
||||
|
||||
this.saveUserLocalConfig()
|
||||
// console.log(this.drillDownTableConfigs)
|
||||
await this.saveUserLocalConfig()
|
||||
let forthMenuName = ''
|
||||
if(clickTab.prop === 'qtype'){
|
||||
if (clickTab.prop === 'qtype') {
|
||||
forthMenuName = this.dnsQtypeMapData.get(columnValue)
|
||||
}else if(clickTab.prop === 'rcode'){
|
||||
} else if (clickTab.prop === 'rcode') {
|
||||
forthMenuName = this.dnsRcodeMapData.get(columnValue)
|
||||
}else {
|
||||
} else {
|
||||
forthMenuName = columnValue
|
||||
}
|
||||
this.$store.getters.menuList.forEach(menu => {
|
||||
@@ -1188,6 +1225,14 @@ export default {
|
||||
})
|
||||
}
|
||||
})
|
||||
if (!this.getUrlParam(this.curTabState.tabIndex)) {
|
||||
let thirdMenu = this.urlChangeParams[this.curTabState.thirdMenu]
|
||||
if(thirdMenu === 'network.serverIps'){
|
||||
this.urlChangeParams[this.curTabState.tabIndex] = 1
|
||||
}else if(thirdMenu === 'network.clientIps' || thirdMenu === 'network.ips'){
|
||||
this.urlChangeParams[this.curTabState.tabIndex] = 0
|
||||
}
|
||||
}
|
||||
this.changeUrlTabState()
|
||||
this.$router.push({
|
||||
path: this.$route.path,
|
||||
@@ -1199,8 +1244,38 @@ export default {
|
||||
}
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 在路由跳转前,即下钻前将路由数据保存起来,确保回退和前进保留当时状态
|
||||
*/
|
||||
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)
|
||||
},
|
||||
handleSearchParams (columnValue) {
|
||||
columnValue = columnValue.replaceAll("'", "\\\\'")
|
||||
columnValue = handleSpecialValue(columnValue)//columnValue.replaceAll("'", "\\\\'")
|
||||
const queryCondition = []
|
||||
const curTab = this.getCurTab()
|
||||
if (curTab.prop === 'protocolPort') {
|
||||
@@ -1213,7 +1288,7 @@ export default {
|
||||
} else {
|
||||
if (curTab.queryCondition) {
|
||||
curTab.queryCondition.forEach(item => {
|
||||
queryCondition.push(item.replace('$param', columnValue))
|
||||
queryCondition.push(item.replaceAll('$param', columnValue))
|
||||
})
|
||||
} else {
|
||||
if (curTab.dillDownProp) {
|
||||
@@ -1276,13 +1351,13 @@ export default {
|
||||
item.order = ''
|
||||
})
|
||||
}
|
||||
this.cancleSortArrow()
|
||||
this.column = {}
|
||||
this.index = 0
|
||||
this.tableSortColumn = ''
|
||||
this.tableSortType = ''
|
||||
this.tableSortTab = ''
|
||||
this.urlChangeParams = this.$_.omit(this.urlChangeParams, [this.curTabState.tableSortColumn, this.curTabState.tableSortType, this.curTabState.tableSortTab])
|
||||
this.cancleSortArrow()
|
||||
},
|
||||
// 切换tab
|
||||
handleClick (tab) {
|
||||
@@ -1304,11 +1379,11 @@ export default {
|
||||
this.saveUserLocalConfig()
|
||||
this.tab = curTab.prop
|
||||
this.isDnsMapType = false
|
||||
if(this.tab === 'qtype'){
|
||||
this.dnsMapData =this.dnsQtypeMapData
|
||||
if (this.tab === 'qtype') {
|
||||
this.dnsMapData = this.dnsQtypeMapData
|
||||
this.isDnsMapType = true
|
||||
}else if(this.tab === 'rcode'){
|
||||
this.dnsMapData =this.dnsRcodeMapData
|
||||
} else if (this.tab === 'rcode') {
|
||||
this.dnsMapData = this.dnsRcodeMapData
|
||||
this.isDnsMapType = true
|
||||
}
|
||||
let queryParams = {
|
||||
@@ -1409,7 +1484,7 @@ export default {
|
||||
this.activeCustomize = tab.paneName
|
||||
},
|
||||
tableCellStyle ({ row, column, rowIndex, columnIndex }) {
|
||||
let style = 'border-right:0px;font-size:12px;padding:7px 0 !important;border-bottom: 1px solid #ECECEC;'
|
||||
let style = 'border-right:0px;font-size:12px;padding:7px 0 !important;border-bottom: 1px solid #ECECEC;height:41px !important;'
|
||||
if (rowIndex === this.tableData.length - 1) {
|
||||
// style = style + 'border-bottom:0px !important;'
|
||||
}
|
||||
@@ -1588,15 +1663,6 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
/*
|
||||
async getUserLocalConfig () {
|
||||
const userLocalCongfig = await db[dbDrilldownTableConfig].get({ id: this.userId })
|
||||
if (userLocalCongfig) {
|
||||
return userLocalCongfig.config
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
}, */
|
||||
isDrilldown () {
|
||||
if (this.getUrlParam(this.curTabState.fourthMenu)) {
|
||||
return true
|
||||
@@ -1618,6 +1684,7 @@ export default {
|
||||
let curUserConfigs = await readDrilldownTableConfigByUser()
|
||||
const hiddenColumns = this.getHiddenColumnNameGroup()
|
||||
this.curTable.hiddenColumns = hiddenColumns
|
||||
let version = ''
|
||||
if (curUserConfigs && curUserConfigs.length > 0) { // 当前用户存在缓存配置
|
||||
const currentRouteConfig = curUserConfigs.find(config => config.route === this.tableType)
|
||||
if (currentRouteConfig) { // 用户的缓存中存在当前路径对应的下钻表格对应的配置
|
||||
@@ -1633,13 +1700,16 @@ export default {
|
||||
} else { // 用户的缓存中不存在当前路径对应的下钻表格对应的配置
|
||||
curUserConfigs.push(this.handleInitDrilldownTableConfig())
|
||||
}
|
||||
version = await getConfigVersion(this.userId)
|
||||
} else { // 当前用户不存在缓存配置
|
||||
curUserConfigs = []
|
||||
curUserConfigs.push(this.handleInitDrilldownTableConfig())
|
||||
version = await getConfigVersion('default')
|
||||
}
|
||||
// 更新缓存中的配置
|
||||
await db[dbDrilldownTableConfig].put({
|
||||
id: this.userId,
|
||||
version: version,
|
||||
config: this.$_.cloneDeep(curUserConfigs)
|
||||
})
|
||||
// 更新使用的配置
|
||||
@@ -1742,9 +1812,28 @@ export default {
|
||||
}
|
||||
},
|
||||
async mounted () {
|
||||
console.log('mounted start...')
|
||||
this.list = null
|
||||
this.tabList = null
|
||||
this.allList = null
|
||||
this.drillDownTableConfigs = null
|
||||
this.curTable = null
|
||||
this.commonColumnList = null
|
||||
|
||||
this.userId = localStorage.getItem(storageKey.userId)
|
||||
this.drillDownTableConfigs = await combinDrilldownTableWithUserConfig()
|
||||
this.tableType = this.$route.params ? this.$route.params.typeName : 'networkOverview'
|
||||
// 是否需要dns的qtype和rcode的数据字典
|
||||
if(this.tableType === fromRoute.dnsServiceInsights) {
|
||||
this.dnsQtypeMapData = this.$store.getters.getDnsQtypeMapData
|
||||
this.dnsRcodeMapData = this.$store.getters.getDnsRcodeMapData
|
||||
if(!this.dnsQtypeMapData || this.dnsQtypeMapData.size === 0){
|
||||
this.dnsQtypeMapData = await getDnsMapData('dnsQtype')
|
||||
this.dnsRcodeMapData = await getDnsMapData('dnsRcode')
|
||||
this.$store.commit('setDnsQtypeMapData', this.dnsQtypeMapData)
|
||||
this.$store.commit('setDnsRcodeMapData', this.dnsRcodeMapData)
|
||||
}
|
||||
}
|
||||
this.curTableInCode = this.networkTable[this.tableType] ? this.networkTable[this.tableType] : this.networkTable.networkOverview
|
||||
// 表格状态初始化(url)
|
||||
this.showRecordNum = Number(this.getUrlParam(this.curTabState.tableShowMore, 10))
|
||||
@@ -1760,6 +1849,7 @@ export default {
|
||||
const curTableOldConfig = this.tables.find(table => table.id === this.tableType)
|
||||
this.curTable = curTableOldConfig
|
||||
if (this.curTable) {
|
||||
let curTab = null
|
||||
if (this.isDrilldown()) { // 下钻状态
|
||||
const thirdMenu = this.getUrlParam(this.curTabState.thirdMenu, '')
|
||||
const tabList = this.getAllTabList()
|
||||
@@ -1770,7 +1860,7 @@ export default {
|
||||
const drilldownTab = tabList.find(item => item.label === thirdMenu)
|
||||
this.list = drilldownTab ? drilldownTab.drilldownTabs : []
|
||||
this.allList = this.$_.cloneDeep(tabList)// 备份所有配置,下钻及返回时使用
|
||||
const curTab = this.getCurTab()// 初始化完list,才能正确执行
|
||||
curTab = this.getCurTab()// 初始化完list,才能正确执行
|
||||
const curTabColumns = tabList.find(item => item.prop === curTab.prop)
|
||||
this.combineColumnList(curTabColumns.name)
|
||||
this.activeTab = ref(curTab.label)
|
||||
@@ -1782,11 +1872,22 @@ export default {
|
||||
}
|
||||
this.allList = this.$_.cloneDeep(this.list)// 备份所有配置,下钻及返回时使用
|
||||
if (this.list && this.list.length > 0) {
|
||||
const curTab = this.getCurTab()// 初始化完list,才能正确执行
|
||||
curTab = this.getCurTab()// 初始化完list,才能正确执行
|
||||
this.combineColumnList(curTab.name)
|
||||
this.activeTab = ref(curTab.label)
|
||||
}
|
||||
}
|
||||
if (curTab && curTab.prop) {
|
||||
const tabName = curTab.prop
|
||||
this.isDnsMapType = false
|
||||
if (tabName === 'qtype') {
|
||||
this.dnsMapData = this.dnsQtypeMapData
|
||||
this.isDnsMapType = true
|
||||
} else if (tabName === 'rcode') {
|
||||
this.dnsMapData = this.dnsRcodeMapData
|
||||
this.isDnsMapType = true
|
||||
}
|
||||
}
|
||||
this.activeCustomize = ref('tabs')
|
||||
this.networkSearchUrl = this.curTable.url
|
||||
// let metric = this.getUrlParam(this.curTabState.tableMetric, 'Bits/s')
|
||||
@@ -1798,14 +1899,14 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
//是否需要dns的qtype和rcode的数据字典
|
||||
this.isDnsMapType = false
|
||||
this.dnsQtypeMapData = await getDnsMapData('dnsQtype')
|
||||
this.dnsRcodeMapData = await getDnsMapData('dnsRcode')
|
||||
this.saveUserLocalConfig()
|
||||
await this.saveUserLocalConfig()
|
||||
this.getChartData()
|
||||
},
|
||||
setup (props) {
|
||||
},
|
||||
beforeUnmount () {
|
||||
// 以下元素,检测到内存并未释放
|
||||
|
||||
},
|
||||
unmounted () {
|
||||
this.isNoData = false
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<template>
|
||||
<div class="npm-app">
|
||||
<div class="npm-app-left">
|
||||
<div class="npm-app" :class="showError?'npm-app-border':''">
|
||||
<chart-error v-if="showError" :content="errorMsg" />
|
||||
|
||||
<div class="npm-app-left" v-if="!showError">
|
||||
<div class="npm-app-letter" :class="{'npm-app-letter-no-data': isNoData}">
|
||||
<div v-for="(letter, index) in colorPatchData" :key="index">
|
||||
{{letter.letter}}
|
||||
@@ -21,7 +23,7 @@
|
||||
class="app-table"
|
||||
height="100%"
|
||||
empty-text=" "
|
||||
>
|
||||
v-if="!showError">
|
||||
<template v-for="(item, index) in customTableTitles" :key="index">
|
||||
<el-table-column class="data-column">
|
||||
<template #header>
|
||||
@@ -137,13 +139,13 @@ import { get } from '@/utils/http'
|
||||
import {
|
||||
getChainRatio,
|
||||
computeScore,
|
||||
changeCurTab,
|
||||
urlParamsHandler,
|
||||
overwriteUrl,
|
||||
getUserDrilldownTableConfig
|
||||
} from '@/utils/tools'
|
||||
import chartMixin from '@/views/charts2/chart-mixin'
|
||||
import ChartNoData from '@/views/charts/charts/ChartNoData'
|
||||
import ChartError from '@/components/common/Error'
|
||||
export default {
|
||||
name: 'NpmAppCategoryScore',
|
||||
data () {
|
||||
@@ -169,16 +171,19 @@ export default {
|
||||
],
|
||||
isNoData: false,
|
||||
curTabState: curTabState,
|
||||
urlChangeParams: {}
|
||||
urlChangeParams: {},
|
||||
showError: false,
|
||||
errorMsg: ''
|
||||
}
|
||||
},
|
||||
components: {
|
||||
ChartError,
|
||||
ChartNoData
|
||||
},
|
||||
mixins: [chartMixin],
|
||||
watch: {
|
||||
timeFilter: {
|
||||
handler (n) {
|
||||
handler () {
|
||||
this.init()
|
||||
}
|
||||
}
|
||||
@@ -194,66 +199,98 @@ export default {
|
||||
const lastCycleTrafficRequest = get(api.npm.overview.appTrafficAnalysis, { ...params, cycle: 1 })
|
||||
this.toggleLoading(true)
|
||||
Promise.all([currentTrafficRequest, lastCycleTrafficRequest]).then(res => {
|
||||
const prevData = res[1].data.result
|
||||
const data = res[0].data.result
|
||||
if (data && data.length > 0) {
|
||||
this.isNoData = false
|
||||
const tableData = data.map(d => {
|
||||
const mapping = npmCategoryInfoMapping.find(mapping => mapping.appSubcategory === d.appSubcategory)
|
||||
const result = {
|
||||
...mapping,
|
||||
...d,
|
||||
bytesRateChainRatio: '-',
|
||||
inboundBytesRateChainRatio: '-',
|
||||
outboundBytesRateChainRatio: '-'
|
||||
}
|
||||
if (res[0].code === 200 && res[1].code === 200) {
|
||||
this.showError = false
|
||||
this.errorMsg = ''
|
||||
const prevData = res[1].data.result
|
||||
const data = res[0].data.result
|
||||
if (data && data.length > 0) {
|
||||
this.isNoData = false
|
||||
const tableData = data.map(d => {
|
||||
const mapping = npmCategoryInfoMapping.find(mapping => mapping.appSubcategory === d.appSubcategory)
|
||||
const result = {
|
||||
...mapping,
|
||||
...d,
|
||||
bytesRateChainRatio: '-',
|
||||
inboundBytesRateChainRatio: '-',
|
||||
outboundBytesRateChainRatio: '-'
|
||||
}
|
||||
|
||||
const prev = prevData.find(p => p.appSubcategory === d.appSubcategory)
|
||||
if (prev) {
|
||||
result.bytesRateChainRatio = getChainRatio(d.totalBitsRate, prev.totalBitsRate)
|
||||
result.inboundBytesRateChainRatio = getChainRatio(d.inboundBitsRate, prev.inboundBitsRate)
|
||||
result.outboundBytesRateChainRatio = getChainRatio(d.outboundBitsRate, prev.outboundBitsRate)
|
||||
}
|
||||
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)
|
||||
Promise.all([tcpRequest, httpRequest, sslRequest, tcpLostRequest, packetRetransRequest]).then(res => {
|
||||
const keyPre = ['tcp', 'http', 'ssl', 'tcpLost', 'packetRetrans']
|
||||
res.forEach((r, i) => {
|
||||
if (r.code === 200) {
|
||||
tableData.forEach(t => {
|
||||
const find = r.data.result.find(d => d.appSubcategory === t.appSubcategory)
|
||||
t[keyPre[i] + 'Score'] = find
|
||||
})
|
||||
const prev = prevData.find(p => p.appSubcategory === d.appSubcategory)
|
||||
if (prev) {
|
||||
result.bytesRateChainRatio = getChainRatio(d.totalBitsRate, prev.totalBitsRate)
|
||||
result.inboundBytesRateChainRatio = getChainRatio(d.inboundBitsRate, prev.inboundBitsRate)
|
||||
result.outboundBytesRateChainRatio = getChainRatio(d.outboundBitsRate, prev.outboundBitsRate)
|
||||
}
|
||||
return result
|
||||
})
|
||||
tableData.forEach(t => {
|
||||
const data = {
|
||||
establishLatencyMs: t.tcpScore ? t.tcpScore.establishLatencyMs : null,
|
||||
httpResponseLatency: t.httpScore ? t.httpScore.httpResponseLatency : null,
|
||||
sslConLatency: t.sslScore ? t.sslScore.sslConLatency : null,
|
||||
tcpLostlenPercent: t.tcpLostScore ? t.tcpLostScore.tcpLostlenPercent : null,
|
||||
pktRetransPercent: t.packetRetransScore ? t.packetRetransScore.pktRetransPercent : null
|
||||
}
|
||||
t.score = computeScore(data)
|
||||
// 计算分数
|
||||
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)
|
||||
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) {
|
||||
tableData.forEach(t => {
|
||||
const find = r.data.result.find(d => d.appSubcategory === t.appSubcategory)
|
||||
t[keyPre[i] + 'Score'] = find
|
||||
})
|
||||
} else {
|
||||
this.showError = true
|
||||
// todo 此处目前返回字段为msg,后续字段会修改为message
|
||||
msg = msg + ',' + r.message
|
||||
if (msg.indexOf(',') === 0) {
|
||||
msg = msg.substring(1, msg.length)
|
||||
}
|
||||
if (msg.lastIndexOf(',') === msg.length - 1) {
|
||||
msg = msg.substring(0, msg.length - 1)
|
||||
}
|
||||
this.errorMsg = msg
|
||||
}
|
||||
})
|
||||
tableData.forEach(t => {
|
||||
const data = {
|
||||
establishLatencyMs: t.tcpScore ? t.tcpScore.establishLatencyMs : null,
|
||||
httpResponseLatency: t.httpScore ? t.httpScore.httpResponseLatency : null,
|
||||
sslConLatency: t.sslScore ? t.sslScore.sslConLatency : null,
|
||||
tcpLostlenPercent: t.tcpLostScore ? t.tcpLostScore.tcpLostlenPercent : null,
|
||||
pktRetransPercent: t.packetRetransScore ? t.packetRetransScore.pktRetransPercent : null
|
||||
}
|
||||
t.score = computeScore(data)
|
||||
})
|
||||
this.tableData = tableData
|
||||
}).finally(() => {
|
||||
this.toggleLoading(false)
|
||||
})
|
||||
this.tableData = tableData
|
||||
}).finally(() => {
|
||||
} else {
|
||||
this.tableData = []
|
||||
this.isNoData = true
|
||||
this.toggleLoading(false)
|
||||
})
|
||||
}
|
||||
} else {
|
||||
this.tableData = []
|
||||
this.isNoData = true
|
||||
this.toggleLoading(false)
|
||||
this.showError = true
|
||||
this.errorMsg = ''
|
||||
let msg = res[0].message + ', ' + res[1].message
|
||||
if (msg.indexOf(',') === 0) {
|
||||
msg = msg.substring(1, msg.length)
|
||||
}
|
||||
if (msg.lastIndexOf(',') === msg.length - 1) {
|
||||
msg = msg.substring(0, msg.length - 1)
|
||||
}
|
||||
this.errorMsg = msg
|
||||
}
|
||||
}).catch(e => {
|
||||
console.error(e)
|
||||
this.toggleLoading(false)
|
||||
this.showError = true
|
||||
this.errorMsg = ''
|
||||
this.errorMsg = e.message
|
||||
})
|
||||
},
|
||||
getUrlParam (param, defaultValue, isNumber) {
|
||||
|
||||
@@ -1,40 +1,41 @@
|
||||
<template>
|
||||
<div class="npm-app-event">
|
||||
<div class="metric-select" >
|
||||
<el-select v-model="metric"
|
||||
class="option__select select-column"
|
||||
popper-class="option-popper common-select"
|
||||
:popper-append-to-body="false"
|
||||
key="tabMetric"
|
||||
@change="changeMetric"
|
||||
size="mini"
|
||||
width="100">
|
||||
<div class="metric-select">
|
||||
<el-select
|
||||
v-model="metric"
|
||||
class="option__select select-column"
|
||||
popper-class="option-popper common-select"
|
||||
:popper-append-to-body="false"
|
||||
key="tabMetric"
|
||||
@change="changeMetric"
|
||||
size="mini"
|
||||
width="100">
|
||||
<el-option
|
||||
v-for="item in options"
|
||||
:key="item.label"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
v-for="item in options"
|
||||
:key="item.label"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
<span>{{$t('network.metric')}}:</span>
|
||||
<span>{{ $t('network.metric') }}:</span>
|
||||
</div>
|
||||
<el-table
|
||||
:id="`tabTable_${index}`"
|
||||
:ref="`dataTable_${index}`"
|
||||
:data="tableData"
|
||||
class="npm-app-event-table"
|
||||
height="100%"
|
||||
empty-text=""
|
||||
:id="`tabTable_${index}`"
|
||||
:ref="`dataTable_${index}`"
|
||||
:data="tableData"
|
||||
class="npm-app-event-table"
|
||||
height="100%"
|
||||
empty-text=""
|
||||
>
|
||||
<template v-for="(item, index) in customTableTitles" :key="index">
|
||||
<el-table-column class="data-column" :min-width="columnWidth(index)">
|
||||
<template #header>
|
||||
<span class="data-column__span">{{$t(item.label)}}</span>
|
||||
<span class="data-column__span">{{ $t(item.label) }}</span>
|
||||
</template>
|
||||
<template #default="scope" :column="item">
|
||||
<template #default="scope" :column="item">
|
||||
<div class="data-app-event-table">
|
||||
<template v-if="item.prop === 'domain' ||item.prop === 'appName' ||item.prop === 'serverIp' ">
|
||||
<span class="data-applications">{{$t(scope.row[item.prop])}}</span>
|
||||
<span class="data-applications">{{ $t(scope.row[item.prop]) }}</span>
|
||||
</template>
|
||||
<template v-else-if="item.prop === 'eventSeverity'">
|
||||
<template v-if="scope.row[item.prop]==='critical'">
|
||||
@@ -56,14 +57,14 @@
|
||||
<div v-for="item in 1" class="red-dot"></div>
|
||||
<div v-for="item in 4" class="grey-dot"></div>
|
||||
</template>
|
||||
<span class="data-severity" >{{$t(scope.row[item.prop])}}</span>
|
||||
<span class="data-severity">{{ $t(scope.row[item.prop]) }}</span>
|
||||
</template>
|
||||
<template v-else-if="item.prop === 'eventType'">
|
||||
<!-- <span class="data-eventType" v-for="type in scope.row[item.prop]">{{type}}</span>-->
|
||||
<span class="data-eventType" >{{$t(scope.row[item.prop])}}</span>
|
||||
<!-- <span class="data-eventType" v-for="type in scope.row[item.prop]">{{type}}</span>-->
|
||||
<span class="data-eventType">{{ $t(scope.row[item.prop]) }}</span>
|
||||
</template>
|
||||
<template v-else-if="item.prop === 'count'">
|
||||
<span class="data-eventCount">{{scope.row[item.prop]}}</span>
|
||||
<span class="data-eventCount">{{ scope.row[item.prop] }}</span>
|
||||
</template>
|
||||
<span v-else>-</span>
|
||||
</div>
|
||||
@@ -76,20 +77,23 @@
|
||||
</div>
|
||||
</template>
|
||||
</el-table>
|
||||
|
||||
<div class="table-error">
|
||||
<chart-error v-if="showError" :content="errorMsg"></chart-error>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { unitTypes, npmCategoryInfoMapping } from '@/utils/constants'
|
||||
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 } from '@/utils/tools'
|
||||
import chartMixin from '@/views/charts2/chart-mixin'
|
||||
import ChartError from '@/components/common/Error'
|
||||
|
||||
export default {
|
||||
name: 'NpmAppEventTable',
|
||||
components: { ChartError },
|
||||
data () {
|
||||
return {
|
||||
metric: 'appLabel',
|
||||
@@ -115,18 +119,32 @@ export default {
|
||||
dotList: ['grey-dot', 'grey-dot', 'grey-dot', 'grey-dot', 'grey-dot'],
|
||||
tableData: [],
|
||||
customTableTitles: [
|
||||
{ label: 'network.applications', prop: 'serverIp' },
|
||||
{ label: 'network.severity', prop: 'eventSeverity' },
|
||||
{ label: 'network.eventType', prop: 'eventType' },
|
||||
{ label: 'network.eventCount', prop: 'count' }
|
||||
{
|
||||
label: 'network.applications',
|
||||
prop: 'serverIp'
|
||||
},
|
||||
{
|
||||
label: 'network.severity',
|
||||
prop: 'eventSeverity'
|
||||
},
|
||||
{
|
||||
label: 'network.eventType',
|
||||
prop: 'eventType'
|
||||
},
|
||||
{
|
||||
label: 'network.eventCount',
|
||||
prop: 'count'
|
||||
}
|
||||
],
|
||||
isNoData: false
|
||||
isNoData: false,
|
||||
showError: false,
|
||||
errorMsg: ''
|
||||
}
|
||||
},
|
||||
mixins: [chartMixin],
|
||||
watch: {
|
||||
timeFilter: {
|
||||
handler (n) {
|
||||
handler () {
|
||||
this.init()
|
||||
}
|
||||
}
|
||||
@@ -149,13 +167,20 @@ export default {
|
||||
}
|
||||
get(api.npm.events.dimensionEvents, params).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.showError = false
|
||||
if (!res.data.result || res.data.result.length === 0) {
|
||||
this.isNoData = true
|
||||
}
|
||||
this.tableData = res.data.result
|
||||
} else {
|
||||
this.isNoData = true
|
||||
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)
|
||||
})
|
||||
@@ -172,9 +197,7 @@ export default {
|
||||
return '15%'
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
computed: {
|
||||
}
|
||||
computed: {}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
<template>
|
||||
<div class="npm-event">
|
||||
<div class="npm-event-title">{{$t('network.eventByType')}}</div>
|
||||
<div class="npm-event-title">
|
||||
{{$t('network.eventByType')}}
|
||||
<chart-error tooltip v-if="showError" :content="errorMsg"></chart-error>
|
||||
</div>
|
||||
<div class="npm-event-pie">
|
||||
<chart-no-data v-if="isNoData"></chart-no-data>
|
||||
<div class="npm-event-pies" v-else>
|
||||
@@ -35,6 +38,7 @@ import { pieChartOption3 } from '@/views/charts2/charts/options/echartOption'
|
||||
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'
|
||||
|
||||
export default {
|
||||
name: 'NpmEventsByType',
|
||||
@@ -42,6 +46,7 @@ export default {
|
||||
type: String
|
||||
},
|
||||
components: {
|
||||
ChartError,
|
||||
ChartNoData
|
||||
},
|
||||
mixins: [chartMixin],
|
||||
@@ -54,7 +59,9 @@ export default {
|
||||
return {
|
||||
chartData: [],
|
||||
timer: null,
|
||||
isNoData: false
|
||||
isNoData: false,
|
||||
showError: false,
|
||||
errorMsg: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -104,6 +111,7 @@ export default {
|
||||
this.toggleLoading(true)
|
||||
get(api.npm.events.recentEvents, params).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.showError = false
|
||||
this.isNoData = res.data.result.length === 0
|
||||
const arrData = []
|
||||
res.data.result.forEach(t => {
|
||||
@@ -121,8 +129,14 @@ export default {
|
||||
this.init()
|
||||
})
|
||||
} else {
|
||||
this.isNoData = true
|
||||
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)
|
||||
})
|
||||
@@ -140,6 +154,8 @@ export default {
|
||||
beforeUnmount () {
|
||||
clearTimeout(this.timer)
|
||||
window.removeEventListener('resize', this.resize)
|
||||
this.myChart = null
|
||||
this.chartOption = null
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
<div class="npm-header-body-severity-icon" :class="item.eventSeverity"></div>
|
||||
<div class="npm-header-body-severity-value">{{item.eventSeverity}}</div>
|
||||
</div>
|
||||
<div class="npm-header-body-total">{{item.count}}</div>
|
||||
<chart-error v-if="showError" tooltip :content="errorMsg" />
|
||||
<div v-else class="npm-header-body-total">{{item.count}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -15,8 +16,10 @@ 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'
|
||||
export default {
|
||||
name: 'NpmEventsHeader',
|
||||
components: { ChartError },
|
||||
mixins: [chartMixin],
|
||||
data () {
|
||||
return {
|
||||
@@ -47,12 +50,14 @@ export default {
|
||||
index: 4
|
||||
}
|
||||
],
|
||||
type: 'severity'
|
||||
type: 'severity',
|
||||
showError: false,
|
||||
errorMsg: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
timeFilter: {
|
||||
handler (n) {
|
||||
handler () {
|
||||
this.recentEventsListData()
|
||||
}
|
||||
}
|
||||
@@ -67,6 +72,7 @@ export default {
|
||||
this.toggleLoading(true)
|
||||
get(api.npm.events.list, params).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.showError = false
|
||||
res.data.result.forEach(t => {
|
||||
this.chartData.forEach(d => {
|
||||
if (d.eventSeverity === t.eventSeverity) {
|
||||
@@ -74,7 +80,13 @@ export default {
|
||||
}
|
||||
})
|
||||
})
|
||||
} else {
|
||||
this.showError = true
|
||||
this.errorMsg = res.message
|
||||
}
|
||||
}).catch(error => {
|
||||
this.showError = true
|
||||
this.errorMsg = error.message
|
||||
}).finally(() => {
|
||||
this.toggleLoading(false)
|
||||
})
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<template>
|
||||
<div class="cn-chart__map-title" v-if="queryCondition">{{$t('npm.clientLocation')}}</div>
|
||||
<div class="cn-chart__map-title" v-if="queryCondition">
|
||||
{{$t('npm.clientLocation')}}
|
||||
<chart-error v-if="showError" width="300" tooltip :content="errorMsg" />
|
||||
</div>
|
||||
<div class="cn-chart__map" :class="{'cn-chart__map-drilldown': queryCondition}">
|
||||
<div class="map-canvas" id="npmDrillDownMap"></div>
|
||||
</div>
|
||||
@@ -10,15 +13,17 @@ import { ref, shallowRef } from 'vue'
|
||||
import * as am4Core from '@amcharts/amcharts4/core'
|
||||
import * as am4Maps from '@amcharts/amcharts4/maps'
|
||||
import { computeScore, getGeoData } from '@/utils/tools'
|
||||
import { storageKey, unitTypes, countryNameIdMapping, curTabState } from '@/utils/constants'
|
||||
import { storageKey, unitTypes, curTabState } from '@/utils/constants'
|
||||
import { valueToRangeValue } from '@/utils/unit-convert'
|
||||
import { getSecond } from '@/utils/date-util'
|
||||
import { api, getData } from '@/utils/api'
|
||||
import { get } from '@/utils/http'
|
||||
import chartMixin from '@/views/charts2/chart-mixin'
|
||||
import { useRoute } from 'vue-router'
|
||||
import ChartError from '@/components/common/Error'
|
||||
export default {
|
||||
name: 'NpmIpMap',
|
||||
components: { ChartError },
|
||||
setup () {
|
||||
const { query } = useRoute()
|
||||
const tabIndex = ref(query.tabIndex || '')
|
||||
@@ -37,7 +42,9 @@ export default {
|
||||
countryImageSeries: null,
|
||||
// Server | Client
|
||||
trafficDirection: 'Server',
|
||||
curTabState: curTabState
|
||||
curTabState: curTabState,
|
||||
showError: false,
|
||||
errorMsg: ''
|
||||
}
|
||||
},
|
||||
mixins: [chartMixin],
|
||||
@@ -90,48 +97,64 @@ export default {
|
||||
// typeVal: this.$store.getters.getBreadcrumbColumnValue
|
||||
typeVal: this.getUrlParam(this.curTabState.fourthMenu, '')
|
||||
}
|
||||
if (params.type === 'serverIp' || params.type === 'clientIp') params.type = 'ip'
|
||||
getData(api.npm.overview.map, params).then(res => {
|
||||
const subParams = {
|
||||
...params,
|
||||
params: res.map(r => r.country).join(',')
|
||||
this.showError = false
|
||||
if (res && res.length > 0) {
|
||||
const subParams = {
|
||||
...params,
|
||||
params: res.map(r => `'${r.country}'`).join(',')
|
||||
}
|
||||
// 计算分数
|
||||
const tcpRequest = get(api.npm.overview.mapTcp, subParams)
|
||||
const httpRequest = get(api.npm.overview.mapHttp, subParams)
|
||||
const sslRequest = get(api.npm.overview.mapSsl, subParams)
|
||||
const tcpLostRequest = get(api.npm.overview.mapPacketLoss, subParams)
|
||||
const packetRetransRequest = get(api.npm.overview.mapPacketRetrans, subParams)
|
||||
Promise.all([tcpRequest, httpRequest, sslRequest, tcpLostRequest, packetRetransRequest]).then(res2 => {
|
||||
const keyPre = ['tcp', 'http', 'ssl', 'tcpLost', 'packetRetrans']
|
||||
const mapData = res
|
||||
res2.forEach((r, i) => {
|
||||
if (r.code === 200) {
|
||||
mapData.forEach(t => {
|
||||
const find = r.data.result.find(d => d.country === t.country)
|
||||
t[keyPre[i] + 'Score'] = find
|
||||
})
|
||||
} else {
|
||||
this.showError = true
|
||||
this.errorMsg = r.message
|
||||
}
|
||||
})
|
||||
mapData.forEach(t => {
|
||||
const data = {
|
||||
establishLatencyMs: t.tcpScore ? t.tcpScore.establishLatencyMs : null,
|
||||
httpResponseLatency: t.httpScore ? t.httpScore.httpResponseLatency : null,
|
||||
sslConLatency: t.sslScore ? t.sslScore.sslConLatency : null,
|
||||
tcpLostlenPercent: t.tcpLostScore ? t.tcpLostScore.tcpLostlenPercent : null,
|
||||
pktRetransPercent: t.packetRetransScore ? t.packetRetransScore.pktRetransPercent : null
|
||||
}
|
||||
t.score = computeScore(data)
|
||||
if (t.score === '-') {
|
||||
t.score = ''
|
||||
}
|
||||
})
|
||||
this.loadMarkerData(imageSeries, mapData)
|
||||
})
|
||||
}
|
||||
// 计算分数
|
||||
const tcpRequest = get(api.npm.overview.mapTcp, subParams)
|
||||
const httpRequest = get(api.npm.overview.mapHttp, subParams)
|
||||
const sslRequest = get(api.npm.overview.mapSsl, subParams)
|
||||
const tcpLostRequest = get(api.npm.overview.mapPacketLoss, subParams)
|
||||
const packetRetransRequest = get(api.npm.overview.mapPacketRetrans, subParams)
|
||||
Promise.all([tcpRequest, httpRequest, sslRequest, tcpLostRequest, packetRetransRequest]).then(res2 => {
|
||||
const keyPre = ['tcp', 'http', 'ssl', 'tcpLost', 'packetRetrans']
|
||||
const mapData = res
|
||||
res2.forEach((r, i) => {
|
||||
if (r.code === 200) {
|
||||
mapData.forEach(t => {
|
||||
const find = r.data.result.find(d => d.country === t.country)
|
||||
t[keyPre[i] + 'Score'] = find
|
||||
})
|
||||
}
|
||||
})
|
||||
mapData.forEach(t => {
|
||||
const data = {
|
||||
establishLatencyMs: t.tcpScore ? t.tcpScore.establishLatencyMs : null,
|
||||
httpResponseLatency: t.httpScore ? t.httpScore.httpResponseLatency : null,
|
||||
sslConLatency: t.sslScore ? t.sslScore.sslConLatency : null,
|
||||
tcpLostlenPercent: t.tcpLostScore ? t.tcpLostScore.tcpLostlenPercent : null,
|
||||
pktRetransPercent: t.packetRetransScore ? t.packetRetransScore.pktRetransPercent : null
|
||||
}
|
||||
t.score = computeScore(data)
|
||||
})
|
||||
this.loadMarkerData(imageSeries, mapData)
|
||||
})
|
||||
}).catch(e => {
|
||||
this.showError = true
|
||||
this.errorMsg = e.message
|
||||
}).finally(() => {
|
||||
this.toggleLoading(false)
|
||||
})
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
this.showError = true
|
||||
this.errorMsg = e.message
|
||||
}
|
||||
},
|
||||
loadMarkerData (imageSeries, data) {
|
||||
data = data.filter(d => d.score || d.score === 0)
|
||||
imageSeries.data = data.map(r => ({
|
||||
score: r.score,
|
||||
name: r.province || r.country,
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
<chart-no-data v-if="isNoData"></chart-no-data>
|
||||
<template v-if="chartData.id === 11">
|
||||
<div class="npm-line-header">
|
||||
<div class="npm-line-header-title">{{$t(chartData.i18n) || chartData.name}}</div>
|
||||
<div class="npm-line-header-title">
|
||||
{{$t(chartData.i18n) || chartData.name}}
|
||||
<chart-error v-if="showError" tooltip :content="errorMsg"></chart-error>
|
||||
</div>
|
||||
<div class="npm-line-header-rights" v-if="chartData.params && chartData.params.showLegend && !isNoData">
|
||||
<div class="npm-line-header-right" :class="{'active': item.show}" v-for="(item, index) in chartOptionLineData" :key="index" @click="highlightEvent(item)">
|
||||
<div class="npm-line-header-icon" :class="'icon' + index"></div>
|
||||
@@ -14,23 +17,38 @@
|
||||
<div v-show="!isNoData" class="chart-drawing" :id="`chart${chartData.name}`"></div>
|
||||
</template>
|
||||
<template v-else-if="chartData.id === 12">
|
||||
<div class="npm-line-title">{{$t(chartData.i18n) || chartData.name}}(ms)</div>
|
||||
<div class="npm-line-title">
|
||||
{{$t(chartData.i18n) || chartData.name}}(ms)
|
||||
<chart-error v-if="showError" tooltip :content="errorMsg"></chart-error>
|
||||
</div>
|
||||
<div v-show="!isNoData" class="chart-drawing" :id="`chart${chartData.name}`"></div>
|
||||
</template>
|
||||
<template v-else-if="chartData.id === 13">
|
||||
<div class="npm-line-title">{{$t(chartData.i18n) || chartData.name}}(ms)</div>
|
||||
<div class="npm-line-title">
|
||||
{{$t(chartData.i18n) || chartData.name}}(ms)
|
||||
<chart-error v-if="showError" tooltip :content="errorMsg"></chart-error>
|
||||
</div>
|
||||
<div v-show="!isNoData" class="chart-drawing" :id="`chart${chartData.name}`"></div>
|
||||
</template>
|
||||
<template v-else-if="chartData.id === 14">
|
||||
<div class="npm-line-title">{{$t(chartData.i18n) || chartData.name}}(ms)</div>
|
||||
<div class="npm-line-title">
|
||||
{{$t(chartData.i18n) || chartData.name}}(ms)
|
||||
<chart-error v-if="showError" tooltip :content="errorMsg"></chart-error>
|
||||
</div>
|
||||
<div v-show="!isNoData" class="chart-drawing" :id="`chart${chartData.name}`"></div>
|
||||
</template>
|
||||
<template v-else-if="chartData.id === 15">
|
||||
<div class="npm-line-title">{{$t(chartData.i18n) || chartData.name}}(%)</div>
|
||||
<div class="npm-line-title">
|
||||
{{$t(chartData.i18n) || chartData.name}}(%)
|
||||
<chart-error v-if="showError" tooltip :content="errorMsg"></chart-error>
|
||||
</div>
|
||||
<div v-show="!isNoData" class="chart-drawing" :id="`chart${chartData.name}`"></div>
|
||||
</template>
|
||||
<template v-else-if="chartData.id === 16">
|
||||
<div class="npm-line-title">{{$t(chartData.i18n) || chartData.name}}(%)</div>
|
||||
<div class="npm-line-title">
|
||||
{{$t(chartData.i18n) || chartData.name}}(%)
|
||||
<chart-error v-if="showError" tooltip :content="errorMsg"></chart-error>
|
||||
</div>
|
||||
<div v-show="!isNoData" class="chart-drawing" :id="`chart${chartData.name}`"></div>
|
||||
</template>
|
||||
</div>
|
||||
@@ -48,10 +66,12 @@ import { api } from '@/utils/api'
|
||||
import ChartNoData from '@/views/charts/charts/ChartNoData'
|
||||
import chartMixin from '@/views/charts2/chart-mixin'
|
||||
import unitConvert from '@/utils/unit-convert'
|
||||
import ChartError from '@/components/common/Error'
|
||||
|
||||
export default {
|
||||
name: 'NpmLine',
|
||||
components: {
|
||||
ChartError,
|
||||
ChartNoData
|
||||
},
|
||||
mixins: [chartMixin],
|
||||
@@ -76,8 +96,10 @@ export default {
|
||||
timer: null,
|
||||
myChartArray: [],
|
||||
side: this.$store.state.panel.npmLocationSide,
|
||||
country: this.$store.state.panel.npmLocationCountry
|
||||
country: this.$store.state.panel.npmLocationCountry,
|
||||
// province: '',
|
||||
showError: false,
|
||||
errorMsg: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -92,24 +114,29 @@ export default {
|
||||
deep: true,
|
||||
handler (n) {
|
||||
this.country = n
|
||||
this.init()
|
||||
this.init(n)
|
||||
}
|
||||
},
|
||||
timeFilter: {
|
||||
handler (n) {
|
||||
handler () {
|
||||
this.init()
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
init () {
|
||||
init (n) {
|
||||
const params = {
|
||||
startTime: getSecond(this.timeFilter.startTime),
|
||||
endTime: getSecond(this.timeFilter.endTime),
|
||||
side: this.side,
|
||||
country: this.country
|
||||
side: this.side
|
||||
// country: this.country
|
||||
// province: this.province
|
||||
}
|
||||
if (n) {
|
||||
params.country = n
|
||||
} else {
|
||||
params.country = ''
|
||||
}
|
||||
this.toggleLoading(true)
|
||||
let url
|
||||
if (this.chart.params) {
|
||||
@@ -129,23 +156,34 @@ export default {
|
||||
if (url) {
|
||||
get(url, params).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.showError = false
|
||||
this.isNoData = res.data.result.length === 0
|
||||
if (this.chart.params.index === 0) {
|
||||
res.data.result.forEach((t, i) => {
|
||||
if (t.type === 'totalBitsRate') {
|
||||
this.chartOptionLineData[i].values = t.values
|
||||
} else if (t.type === 'inboundBitsRate') {
|
||||
this.chartOptionLineData[i].values = t.values
|
||||
} else if (t.type === 'outboundBitsRate') {
|
||||
this.chartOptionLineData[i].values = t.values
|
||||
}
|
||||
})
|
||||
const result = this.chartOptionLineData.filter(t => this.chartData.params.color.indexOf(t.color) > -1)
|
||||
this.echartsInit(result, this.chartData, this.chartData.params.unitType)
|
||||
} else {
|
||||
this.echartsInit(res.data.result, this.chartData, this.chartData.params.unitType)
|
||||
if (!this.isNoData) {
|
||||
if (this.chart.params.index === 0) {
|
||||
res.data.result.forEach((t, i) => {
|
||||
if (t.type === 'totalBitsRate') {
|
||||
this.chartOptionLineData[i].values = t.values
|
||||
} else if (t.type === 'inboundBitsRate') {
|
||||
this.chartOptionLineData[i].values = t.values
|
||||
} else if (t.type === 'outboundBitsRate') {
|
||||
this.chartOptionLineData[i].values = t.values
|
||||
}
|
||||
})
|
||||
const result = this.chartOptionLineData.filter(t => this.chartData.params.color.indexOf(t.color) > -1)
|
||||
this.echartsInit(result, this.chartData, this.chartData.params.unitType)
|
||||
} else {
|
||||
this.echartsInit(res.data.result, this.chartData, this.chartData.params.unitType)
|
||||
}
|
||||
}
|
||||
} 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)
|
||||
})
|
||||
@@ -162,11 +200,16 @@ export default {
|
||||
this.myChart = echarts.init(dom)
|
||||
}
|
||||
this.chartOption = npmLineChartOption
|
||||
const seriesTemplate = this.chartOption.series[0]
|
||||
this.chartOption.color = this.chartData.params.color
|
||||
this.chartOption.series = data.map((t, i) => {
|
||||
return {
|
||||
...seriesTemplate,
|
||||
type: 'line',
|
||||
symbol: 'circle',
|
||||
smooth: true,
|
||||
showSymbol: false,
|
||||
emphasis: {
|
||||
focus: 'series'
|
||||
},
|
||||
name: t.legend ? t.legend : this.$t(chartData.i18n) || chartData.name,
|
||||
stack: this.chartData.params.isStack ? 'network.total' : '',
|
||||
lineStyle: {
|
||||
@@ -288,6 +331,7 @@ export default {
|
||||
beforeUnmount () {
|
||||
clearTimeout(this.timer)
|
||||
window.removeEventListener('resize', this.resize)
|
||||
this.myChart = null
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<template>
|
||||
<div class="cn-chart__map">
|
||||
<div class="map-canvas" id="npmMap"></div>
|
||||
<chart-error v-if="showError" max-width="900" :content="errorMsg"></chart-error>
|
||||
|
||||
<div class="map-filter">
|
||||
<el-select
|
||||
size="mini"
|
||||
@@ -55,9 +57,11 @@ import { getSecond } from '@/utils/date-util'
|
||||
import { api, getData } from '@/utils/api'
|
||||
import { get } from '@/utils/http'
|
||||
import chartMixin from '@/views/charts2/chart-mixin'
|
||||
import { Rectangle3D } from '@amcharts/amcharts4/.internal/core/elements/3d/Rectangle3D'
|
||||
// import { Rectangle3D } from '@amcharts/amcharts4/.internal/core/elements/3d/Rectangle3D'
|
||||
import ChartError from '@/components/common/Error'
|
||||
export default {
|
||||
name: 'NpmMap',
|
||||
components: { ChartError },
|
||||
data () {
|
||||
return {
|
||||
locationOptions,
|
||||
@@ -68,7 +72,9 @@ export default {
|
||||
countryImageSeries: null,
|
||||
// Server | Client
|
||||
trafficDirection: 'Server',
|
||||
location: ''
|
||||
location: '',
|
||||
showError: false,
|
||||
errorMsg: ''
|
||||
}
|
||||
},
|
||||
mixins: [chartMixin],
|
||||
@@ -118,6 +124,7 @@ export default {
|
||||
getData(api.npm.location.map, params).then(res => {
|
||||
if (res.length > 0) {
|
||||
// 计算分数
|
||||
params.country = params.country ? `'${params.country}'` : ''
|
||||
const tcpRequest = get(api.npm.location.mapTcp, params)
|
||||
const httpRequest = get(api.npm.location.mapHttp, params)
|
||||
const sslRequest = get(api.npm.location.mapSsl, params)
|
||||
@@ -126,12 +133,24 @@ export default {
|
||||
Promise.all([tcpRequest, httpRequest, sslRequest, tcpLostRequest, packetRetransRequest]).then(res2 => {
|
||||
const keyPre = ['tcp', 'http', 'ssl', 'tcpLost', 'packetRetrans']
|
||||
const mapData = res
|
||||
let msg = ''
|
||||
res2.forEach((r, i) => {
|
||||
if (r.code === 200) {
|
||||
mapData.forEach(t => {
|
||||
const find = r.data.result.find(d => d.country === t.country)
|
||||
t[keyPre[i] + 'Score'] = find
|
||||
})
|
||||
} else {
|
||||
this.showError = true
|
||||
// todo 此处目前返回字段为msg,后续字段会修改为message
|
||||
msg = msg + ',' + r.message
|
||||
if (msg.indexOf(',') === 0) {
|
||||
msg = msg.substring(1, msg.length)
|
||||
}
|
||||
if (msg.lastIndexOf(',') === msg.length - 1) {
|
||||
msg = msg.substring(0, msg.length - 1)
|
||||
}
|
||||
this.errorMsg = msg
|
||||
}
|
||||
})
|
||||
mapData.forEach(t => {
|
||||
@@ -148,20 +167,29 @@ export default {
|
||||
}
|
||||
})
|
||||
this.loadMarkerData(imageSeries, mapData)
|
||||
}).catch((e) => {
|
||||
this.showError = true
|
||||
this.errorMsg = e.message
|
||||
})
|
||||
} else {
|
||||
imageSeries.data = [{}]
|
||||
}
|
||||
}).catch((e) => {
|
||||
this.showError = true
|
||||
this.errorMsg = e.message
|
||||
}).finally(() => {
|
||||
this.toggleLoading(false)
|
||||
})
|
||||
} catch (e) {
|
||||
this.showError = true
|
||||
// todo 此处错误信息有待考证,后续可能会改动
|
||||
this.errorMsg = e
|
||||
console.error(e)
|
||||
}
|
||||
},
|
||||
loadMarkerData (imageSeries, data) {
|
||||
imageSeries.data = data.map(r => ({
|
||||
score: r.score,
|
||||
score: r.score || '–',
|
||||
name: r.province || r.country,
|
||||
throughput: valueToRangeValue(r.throughBitsRate, unitTypes.bps).join(' '),
|
||||
id: r.serverId,
|
||||
@@ -303,7 +331,7 @@ export default {
|
||||
}
|
||||
},
|
||||
timeFilter: {
|
||||
handler (n) {
|
||||
handler () {
|
||||
if (this.location) {
|
||||
this.loadAm4ChartMap(this.countrySeries, this.countryImageSeries)
|
||||
} else {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<div class="npm-network-quantity">
|
||||
<single-value
|
||||
v-if="npmNetworkData.length>0"
|
||||
:npm-network-name="npmNetworkName"
|
||||
:npm-network-data="npmNetworkData"
|
||||
></single-value>
|
||||
@@ -14,7 +15,7 @@ import { getSecond } from '@/utils/date-util'
|
||||
import { api } from '@/utils/api'
|
||||
import chartMixin from '@/views/charts2/chart-mixin'
|
||||
import _ from 'lodash'
|
||||
import { computeScore, getChainRatio } from '@/utils/tools'
|
||||
import { getChainRatio } from '@/utils/tools'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { ref } from 'vue'
|
||||
export default {
|
||||
@@ -25,9 +26,15 @@ export default {
|
||||
const { query } = useRoute()
|
||||
const queryCondition = ref(query.queryCondition || '')
|
||||
const dimensionType = ref(query.dimensionType || '')
|
||||
const tabIndex = ref(query.tabIndex || 0)
|
||||
const tabOperationType = ref(query.tabOperationType)
|
||||
const networkOverviewBeforeTab = ref(query.networkOverviewBeforeTab || '')
|
||||
return {
|
||||
queryCondition,
|
||||
dimensionType
|
||||
dimensionType,
|
||||
tabIndex,
|
||||
tabOperationType,
|
||||
networkOverviewBeforeTab
|
||||
}
|
||||
},
|
||||
data () {
|
||||
@@ -43,7 +50,9 @@ export default {
|
||||
npmNetworkLastCycleData: [],
|
||||
npmNetworkData: [],
|
||||
side: '',
|
||||
chartData: {}
|
||||
chartData: {},
|
||||
timer1: null,
|
||||
timer2: null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -57,28 +66,36 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
npmNetworkCycleQuery () {
|
||||
// const conditionStr = this.$route.query.queryCondition ? this.$route.query.queryCondition : ''
|
||||
let condition = ''
|
||||
let url = ''
|
||||
if (this.queryCondition.indexOf(' OR ') > -1) {
|
||||
condition = this.queryCondition.split(/["|'](.*?)["|']/)
|
||||
} else {
|
||||
condition = this.queryCondition
|
||||
}
|
||||
// const type = this.$store.getters.getDimensionType
|
||||
// const type = this.$route.query.dimensionType ? this.$route.query.dimensionType : ''
|
||||
const type = this.dimensionType
|
||||
const type = this.dimensionType || this.networkOverviewBeforeTab
|
||||
const params = {
|
||||
startTime: getSecond(this.timeFilter.startTime),
|
||||
endTime: getSecond(this.timeFilter.endTime),
|
||||
cycle: 0
|
||||
}
|
||||
if (this.chartData.id === 23) {
|
||||
if (this.tabIndex == 0) {
|
||||
this.side = 'client'
|
||||
} else if (this.chartData.id === 26) {
|
||||
} else if (this.tabIndex == 1) {
|
||||
this.side = 'server'
|
||||
}
|
||||
if (condition && (typeof condition !== 'object') && type) {
|
||||
params.q = condition
|
||||
if (type === 'clientIp') {
|
||||
params.q = `ip='${condition.split(/'(.*?)'/)[1]}' and side='client'`
|
||||
} else if (type === 'serverIp') {
|
||||
params.q = `ip='${condition.split(/'(.*?)'/)[1]}' and side='server'`
|
||||
} else if (type === 'clientCity') {
|
||||
params.q = `client_city='${condition.split(/'(.*?)'/)[1]}'`
|
||||
} else if (type === 'serverCity') {
|
||||
params.q = `server_city='${condition.split(/'(.*?)'/)[1]}'`
|
||||
} else {
|
||||
params.q = condition
|
||||
}
|
||||
params.type = type
|
||||
} else if (condition.length > 1 && type && type === 'ip') {
|
||||
params.q = `${type}='${condition[1]}' and side='${this.side}'`
|
||||
@@ -95,23 +112,19 @@ export default {
|
||||
params.type = type
|
||||
}
|
||||
}
|
||||
if (type && condition) {
|
||||
if (parseFloat(this.tabOperationType) === 3) {
|
||||
url = api.npm.overview.allNetworkAnalysis
|
||||
} else {
|
||||
url = api.npm.overview.networkAnalysis
|
||||
}
|
||||
if ((type && condition) || type) {
|
||||
params.type = params.type || type
|
||||
this.toggleLoading(true)
|
||||
get(api.npm.overview.networkAnalysis, params).then(res => {
|
||||
let score = 0
|
||||
get(url, params).then(res => {
|
||||
if (res.code === 200) {
|
||||
const data = {
|
||||
establishLatencyMs: res.data.result.establishLatencyMsAvg || null,
|
||||
httpResponseLatency: res.data.result.httpResponseLatencyAvg || null,
|
||||
sslConLatency: res.data.result.sslConLatencyAvg || null,
|
||||
tcpLostlenPercent: res.data.result.tcpLostlenPercentAvg || null,
|
||||
pktRetransPercent: res.data.result.pktRetransPercentAvg || null
|
||||
}
|
||||
score = computeScore(data)
|
||||
this.npmNetworkCycleData = res.data.result
|
||||
this.npmNetworkLastCycleQuery()
|
||||
}
|
||||
this.$store.commit('setNpmThirdLevelMenuScore', score)
|
||||
this.npmNetworkLastCycleQuery(url, params)
|
||||
}).catch(e => {
|
||||
this.toggleLoading(false)
|
||||
})
|
||||
@@ -124,77 +137,62 @@ export default {
|
||||
this.toggleLoading(true)
|
||||
Promise.all([tcp, http, ssl, tcpPercent, packetPercent]).then(res => {
|
||||
this.npmNetworkCycleData = []
|
||||
let score = 0
|
||||
res.forEach(t => {
|
||||
if (t.code === 200) {
|
||||
this.npmNetworkCycleData.push(t.data.result)
|
||||
const data = {
|
||||
establishLatencyMs: t.data.result.establishLatencyMsAvg,
|
||||
httpResponseLatency: t.data.result.httpResponseLatencyAvg,
|
||||
sslConLatency: t.data.result.sslConLatencyAvg,
|
||||
tcpLostlenPercent: t.data.result.tcpLostlenPercentAvg,
|
||||
pktRetransPercent: t.data.result.pktRetransPercentAvg
|
||||
}
|
||||
score = computeScore(data)
|
||||
} else {
|
||||
this.npmNetworkCycleData.push(t)
|
||||
}
|
||||
})
|
||||
this.$store.commit('setNpmThirdLevelMenuScore', score)
|
||||
this.npmNetworkLastCycleQuery()
|
||||
}).catch(e => {
|
||||
this.toggleLoading(false)
|
||||
// 此时e为数组
|
||||
if (e instanceof Array) {
|
||||
this.npmNetworkCycleData = []
|
||||
e.forEach(t => {
|
||||
this.npmNetworkCycleData.push(t)
|
||||
})
|
||||
this.npmNetworkLastCycleQuery()
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
npmNetworkLastCycleQuery () {
|
||||
let condition = ''
|
||||
if (this.queryCondition.indexOf(' OR ') > -1) {
|
||||
condition = this.queryCondition.split(/["|'](.*?)["|']/)
|
||||
} else {
|
||||
condition = this.queryCondition
|
||||
}
|
||||
// const type = this.$store.getters.getDimensionType
|
||||
const type = this.dimensionType
|
||||
npmNetworkLastCycleQuery (url, param) {
|
||||
const params = {
|
||||
startTime: getSecond(this.timeFilter.startTime),
|
||||
endTime: getSecond(this.timeFilter.endTime),
|
||||
cycle: 1
|
||||
}
|
||||
if (this.chartData.id === 23) {
|
||||
this.side = 'client'
|
||||
} else if (this.chartData.id === 26) {
|
||||
this.side = 'server'
|
||||
if (param && param.type && param.q) {
|
||||
params.type = param.type
|
||||
params.q = param.q
|
||||
}
|
||||
if (condition && (typeof condition !== 'object') && type) {
|
||||
params.q = condition
|
||||
params.type = type
|
||||
} else if (condition.length > 1 && 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]}'`
|
||||
params.type = type
|
||||
} else if (type === 'idcRenter') {
|
||||
params.q = `idc_renter='${condition[1]}'`
|
||||
params.type = type
|
||||
} else {
|
||||
params.q = `${condition[0]}'${condition[1]}'`
|
||||
params.type = type
|
||||
}
|
||||
}
|
||||
if (type && condition) {
|
||||
if ((params.type && params.q) || (param && param.type)) {
|
||||
params.type = params.type || param.type
|
||||
this.toggleLoading(true)
|
||||
get(api.npm.overview.networkAnalysis, params).then(res => {
|
||||
get(url, params).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.npmNetworkLastCycleData = res.data.result
|
||||
let timer = null
|
||||
if (timer) {
|
||||
clearTimeout(timer)
|
||||
}
|
||||
timer = setTimeout(() => {
|
||||
this.npmNetworkQuantity(this.npmNetworkCycleData, this.npmNetworkLastCycleData, 0)
|
||||
}, 300)
|
||||
} else {
|
||||
this.npmNetworkLastCycleData = [res]
|
||||
}
|
||||
let timer = null
|
||||
if (timer) {
|
||||
clearTimeout(timer)
|
||||
}
|
||||
this.timer1 = setTimeout(() => {
|
||||
this.npmNetworkQuantity(this.npmNetworkCycleData, this.npmNetworkLastCycleData, 0)
|
||||
}, 300)
|
||||
}).catch((e) => {
|
||||
let timer = null
|
||||
if (timer) {
|
||||
clearTimeout(timer)
|
||||
}
|
||||
this.npmNetworkLastCycleData = [e]
|
||||
this.timer2 = setTimeout(() => {
|
||||
this.npmNetworkQuantity(this.npmNetworkCycleData, this.npmNetworkLastCycleData, 0)
|
||||
}, 300)
|
||||
}).finally(() => {
|
||||
this.toggleLoading(false)
|
||||
})
|
||||
@@ -209,9 +207,19 @@ export default {
|
||||
res.forEach((t, i) => {
|
||||
if (t.code === 200) {
|
||||
this.npmNetworkLastCycleData.push(t.data.result)
|
||||
this.npmNetworkQuantity(this.npmNetworkCycleData, this.npmNetworkLastCycleData, 1)
|
||||
} else {
|
||||
this.npmNetworkLastCycleData.push(t)
|
||||
}
|
||||
this.npmNetworkQuantity(this.npmNetworkCycleData, this.npmNetworkLastCycleData, 1)
|
||||
})
|
||||
}).catch((e) => {
|
||||
// todo 此处的e可能为数组
|
||||
if (e instanceof Array) {
|
||||
e.forEach((t, i) => {
|
||||
this.npmNetworkLastCycleData.push(t)
|
||||
this.npmNetworkQuantity(this.npmNetworkCycleData, this.npmNetworkLastCycleData, 1)
|
||||
})
|
||||
}
|
||||
}).finally(() => {
|
||||
this.toggleLoading(false)
|
||||
})
|
||||
@@ -270,6 +278,10 @@ export default {
|
||||
this.chartData = _.cloneDeep(this.chart)
|
||||
}
|
||||
this.npmNetworkCycleQuery()
|
||||
},
|
||||
beforeUnmount () {
|
||||
clearTimeout(this.timer1)
|
||||
clearTimeout(this.timer2)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
<template>
|
||||
<div class="npm-recent">
|
||||
<div class="npm-recent-title">{{ $t('network.recentEvents') }}</div>
|
||||
<div class="npm-recent-title">
|
||||
{{ $t('network.recentEvents') }}
|
||||
<chart-error v-if="showError" tooltip :content="errorMsg" />
|
||||
</div>
|
||||
<el-table
|
||||
:id="`tabTable_${index}`"
|
||||
:ref="`dataTable_${index}`"
|
||||
@@ -51,9 +54,11 @@ 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'
|
||||
|
||||
export default {
|
||||
name: 'NpmRecentEvents',
|
||||
components: { ChartError },
|
||||
mixins: [chartMixin],
|
||||
setup () {
|
||||
const { query } = useRoute()
|
||||
@@ -71,7 +76,9 @@ export default {
|
||||
{ label: 'network.severity', prop: 'eventSeverity' },
|
||||
{ label: 'network.entity', prop: 'eventKey' },
|
||||
{ label: 'detections.eventType', prop: 'eventType' }
|
||||
]
|
||||
],
|
||||
showError: false,
|
||||
errorMsg: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -83,11 +90,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
recentEventsListData () {
|
||||
// const condition = this.$store.getters.getQueryCondition.split(/["|'](.*?)["|']/)
|
||||
// const conditionStr = this.$route.query.queryCondition ? this.$route.query.queryCondition : ''
|
||||
const condition = this.queryCondition.split(/["|'](.*?)["|']/)
|
||||
// const type = this.$store.getters.getDimensionType
|
||||
// const type = this.$route.query.dimensionType ? this.$route.query.dimensionType : ''
|
||||
let url = ''
|
||||
const params = {
|
||||
startTime: getSecond(this.timeFilter.startTime),
|
||||
@@ -97,6 +100,7 @@ export default {
|
||||
if (condition.length > 1 && this.dimensionType) {
|
||||
params.param = condition[1]
|
||||
params.type = this.dimensionType
|
||||
if (params.type === 'serverIp' || params.type === 'clientIp') params.type = 'ip'
|
||||
params.limit = 10
|
||||
url = api.npm.events.recentEventsD
|
||||
this.customTableTitles = [
|
||||
@@ -110,6 +114,7 @@ export default {
|
||||
this.toggleLoading(true)
|
||||
get(url, params).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.showError = false
|
||||
this.isNoData = res.data.result.length === 0
|
||||
res.data.result.forEach(e => {
|
||||
if (e.startTime) {
|
||||
@@ -118,8 +123,13 @@ export default {
|
||||
})
|
||||
this.tableData = res.data.result
|
||||
} else {
|
||||
this.isNoData = true
|
||||
// this.isNoData = true
|
||||
this.showError = true
|
||||
this.errorMsg = res.message
|
||||
}
|
||||
}).catch(error => {
|
||||
this.showError = true
|
||||
this.errorMsg = error.message
|
||||
}).finally(() => {
|
||||
this.toggleLoading(false)
|
||||
})
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<template>
|
||||
<div class="npm-tabs">
|
||||
<div class="npm-tabs__active-bar"></div>
|
||||
<el-tabs v-model="currentTab" ref="elTabs" type="border-card">
|
||||
<el-tabs v-model="currentTab" ref="elTabs" type="border-card" v-show="isCurTabReady"
|
||||
@tab-click="handleClick">
|
||||
<el-tab-pane v-for="(tab,index) in tabs" :key="tab.i18n" :name="index" :disabled="tab.disable" >
|
||||
<template #label>
|
||||
<div class="npm-tab__label">
|
||||
@@ -27,7 +28,9 @@ export default {
|
||||
name: 'NpmTabs',
|
||||
data () {
|
||||
return {
|
||||
leftOffset: 27
|
||||
leftOffset: 27,
|
||||
currentTab: ref(0),
|
||||
isCurTabReady:false
|
||||
}
|
||||
},
|
||||
mixins: [chartMixin],
|
||||
@@ -39,11 +42,7 @@ export default {
|
||||
item.disable = false
|
||||
})
|
||||
}
|
||||
const { query } = useRoute()
|
||||
const tabIndexParam = query.tabIndex
|
||||
const currentTab = ref(tabIndexParam ? parseInt(tabIndexParam) : 0)
|
||||
return {
|
||||
currentTab,
|
||||
tabs
|
||||
}
|
||||
},
|
||||
@@ -64,6 +63,13 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleClick(tab){
|
||||
const { query } = this.$route
|
||||
const newUrl = urlParamsHandler(window.location.href, query, {
|
||||
tabIndex: tab.index
|
||||
})
|
||||
overwriteUrl(newUrl)
|
||||
},
|
||||
handleActiveBar (index) {
|
||||
const tabDom = document.getElementById('tab-' + index)
|
||||
if (tabDom) {
|
||||
@@ -73,9 +79,17 @@ export default {
|
||||
const activeBar = document.querySelector('.npm-tabs .npm-tabs__active-bar')
|
||||
activeBar.style.cssText += `width: ${clientWidth + 2}px; left: ${offsetLeft + this.leftOffset + clientLeft - 1}px;`
|
||||
}
|
||||
},
|
||||
disableTab(n){
|
||||
this.tabs[n].disable = true
|
||||
const tabEle = document.getElementById('tab-'+n)
|
||||
tabEle.style.cssText = 'cursor: not-allowed;'
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
const { query } = useRoute()
|
||||
const tabIndexParam = query.tabIndex
|
||||
let curTabIndexInUrl = tabIndexParam ? parseInt(tabIndexParam) : null
|
||||
if (this.chart.panelId === drillDownPanelTypeMapping.npmOverviewIp) {
|
||||
const self = this
|
||||
// 当client或server的session数为0时,对应tab置灰,不可选,默认高亮另一个不为0的tab
|
||||
@@ -93,34 +107,53 @@ export default {
|
||||
self.serverSessions = self.sessionData.serverSessions / (self.sessionData.clientSessions * 1 + self.sessionData.serverSessions * 1)
|
||||
}
|
||||
}).finally(() => {
|
||||
if (self.clientSessions === 0) {
|
||||
self.currentTab = 1
|
||||
self.tabs[0].disable = true
|
||||
self.tabs[1].disable = false
|
||||
const tabEle = document.getElementById('tab-0')
|
||||
tabEle.style.cssText = 'cursor: not-allowed;'
|
||||
setTimeout(() => {
|
||||
self.handleActiveBar(1)
|
||||
}, 400)
|
||||
let thirdMenu = this.$route.query['thirdMenu']
|
||||
self.tabs[0].disable = false
|
||||
self.tabs[1].disable = false
|
||||
let curTabIndex = 0
|
||||
if(thirdMenu === 'network.clientIps'){
|
||||
curTabIndex = 0
|
||||
if (self.serverSessions === 0) {
|
||||
self.disableTab(1)
|
||||
}else if(curTabIndexInUrl !== null){
|
||||
curTabIndex = curTabIndexInUrl
|
||||
}
|
||||
}else if(thirdMenu === 'network.serverIps'){
|
||||
curTabIndex = 1
|
||||
if (self.clientSessions === 0) {
|
||||
self.disableTab(0)
|
||||
}else if(curTabIndexInUrl !== null){
|
||||
curTabIndex = curTabIndexInUrl
|
||||
}
|
||||
}else if (self.clientSessions === 0) {
|
||||
curTabIndex = 1
|
||||
self.disableTab(0)
|
||||
} else if (self.serverSessions === 0) {
|
||||
self.currentTab = 0
|
||||
self.tabs[0].disable = false
|
||||
self.tabs[1].disable = true
|
||||
setTimeout(() => {
|
||||
const tabEle = document.getElementById('tab-1')
|
||||
tabEle.style.cssText = 'cursor: not-allowed;'
|
||||
self.handleActiveBar(0)
|
||||
}, 400)
|
||||
} else {
|
||||
self.currentTab = 0
|
||||
self.tabs[0].disable = false
|
||||
self.tabs[1].disable = false
|
||||
setTimeout(() => {
|
||||
self.handleActiveBar(0)
|
||||
}, 400)
|
||||
curTabIndex = 0
|
||||
self.disableTab(1)
|
||||
} else if(curTabIndexInUrl !== null){
|
||||
curTabIndex = curTabIndexInUrl
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
self.currentTab = curTabIndex
|
||||
self.isCurTabReady = true
|
||||
//URL中tabIndex的设置,client初始化时查询条件需要:side条件
|
||||
const { query } = this.$route
|
||||
const newUrl = urlParamsHandler(window.location.href, query, {
|
||||
tabIndex: self.currentTab
|
||||
})
|
||||
overwriteUrl(newUrl)
|
||||
setTimeout(() => {
|
||||
self.handleActiveBar(self.currentTab)
|
||||
}, 400)
|
||||
setTimeout(() => {
|
||||
this.$emit('tabChange', self.currentTab)
|
||||
}, 400)
|
||||
})
|
||||
})
|
||||
} else {
|
||||
this.currentTab = curTabIndexInUrl ? curTabIndexInUrl : 0
|
||||
this.isCurTabReady = true
|
||||
setTimeout(() => {
|
||||
this.handleActiveBar(this.currentTab)
|
||||
}, 400)
|
||||
|
||||
@@ -19,8 +19,9 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="npm-traffic-line-body">
|
||||
<chart-no-data v-if="isNoData"></chart-no-data>
|
||||
<div v-show="!isNoData" class="chart-drawing" id="chart"></div>
|
||||
<chart-error v-if="showError" :content="errorMsg" />
|
||||
<chart-no-data v-if="isNoData && !showError"></chart-no-data>
|
||||
<div v-show="!isNoData && !showError" class="chart-drawing" id="chart"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -40,10 +41,12 @@ import _ from 'lodash'
|
||||
import chartMixin from '@/views/charts2/chart-mixin'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { overwriteUrl, urlParamsHandler } from '@/utils/tools'
|
||||
import ChartError from '@/components/common/Error'
|
||||
export default {
|
||||
name: 'NpmTrafficLine',
|
||||
mixins: [chartMixin],
|
||||
components: {
|
||||
ChartError,
|
||||
ChartNoData
|
||||
},
|
||||
setup () {
|
||||
@@ -51,10 +54,12 @@ export default {
|
||||
const metricFilter = ref(query.lineMetric || 'Bits/s')
|
||||
const queryCondition = ref(query.queryCondition || '')
|
||||
const dimensionType = ref(query.dimensionType || '')
|
||||
const tabIndex = ref(query.tabIndex || 0)
|
||||
return {
|
||||
metricFilter,
|
||||
queryCondition,
|
||||
dimensionType,
|
||||
tabIndex,
|
||||
myChart: shallowRef(null)
|
||||
}
|
||||
},
|
||||
@@ -112,7 +117,9 @@ export default {
|
||||
value: 'pktRetransPercent',
|
||||
label: this.$t('overall.packetRetrans')
|
||||
}
|
||||
]
|
||||
],
|
||||
showError: false,
|
||||
errorMsg: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -142,10 +149,9 @@ export default {
|
||||
} else {
|
||||
condition = this.queryCondition
|
||||
}
|
||||
// const type = this.$store.getters.getDimensionType
|
||||
if (this.chartData.id === 24) {
|
||||
if (this.tabIndex == 0) {
|
||||
this.side = 'client'
|
||||
} else if (this.chartData.id === 29) {
|
||||
} else if (this.tabIndex == 1) {
|
||||
this.side = 'server'
|
||||
}
|
||||
const params = {
|
||||
@@ -156,7 +162,17 @@ export default {
|
||||
params.type = type
|
||||
}
|
||||
if (condition && (typeof condition !== 'object') && type) {
|
||||
params.q = condition
|
||||
if (type === 'clientIp') {
|
||||
params.q = `ip='${condition.split(/'(.*?)'/)[1]}' and side='client'`
|
||||
} else if (type === 'serverIp') {
|
||||
params.q = `ip='${condition.split(/'(.*?)'/)[1]}' and side='server'`
|
||||
} else if (type === 'clientCity') {
|
||||
params.q = `client_city='${condition.split(/'(.*?)'/)[1]}'`
|
||||
} else if (type === 'serverCity') {
|
||||
params.q = `server_city='${condition.split(/'(.*?)'/)[1]}'`
|
||||
} else {
|
||||
params.q = condition
|
||||
}
|
||||
} 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') {
|
||||
@@ -172,6 +188,7 @@ export default {
|
||||
if (params.type && params.q) {
|
||||
get(api.npm.overview.trafficGraph, params).then((res) => {
|
||||
if (res.code === 200) {
|
||||
this.showError = false
|
||||
this.isNoData = res.data.result.length === 0
|
||||
if (this.isNoData) {
|
||||
this.mpackets = [
|
||||
@@ -290,10 +307,14 @@ export default {
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.isNoData = true
|
||||
this.isNoData = false
|
||||
this.showError = true
|
||||
this.errorMsg = res.message
|
||||
}
|
||||
}).catch(e => {
|
||||
this.isNoData = true
|
||||
this.isNoData = false
|
||||
this.showError = true
|
||||
this.errorMsg = e.message
|
||||
}).finally(() => {
|
||||
this.toggleLoading(false)
|
||||
})
|
||||
@@ -302,6 +323,7 @@ export default {
|
||||
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 = [
|
||||
@@ -352,9 +374,15 @@ export default {
|
||||
this.echartsInit(this.mpackets)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.isNoData = false
|
||||
this.showError = true
|
||||
this.errorMsg = res.message
|
||||
}
|
||||
}).catch(e => {
|
||||
this.isNoData = true
|
||||
this.isNoData = false
|
||||
this.showError = true
|
||||
this.errorMsg = e.message
|
||||
}).finally(() => {
|
||||
this.toggleLoading(false)
|
||||
})
|
||||
@@ -362,6 +390,7 @@ export default {
|
||||
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 = [
|
||||
@@ -411,9 +440,15 @@ export default {
|
||||
this.echartsInit(this.npmQuantity, '(%)')
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.isNoData = false
|
||||
this.showError = true
|
||||
this.errorMsg = res.message
|
||||
}
|
||||
}).catch(e => {
|
||||
this.isNoData = true
|
||||
this.isNoData = false
|
||||
this.showError = true
|
||||
this.errorMsg = e.message
|
||||
}).finally(() => {
|
||||
this.toggleLoading(false)
|
||||
})
|
||||
@@ -421,6 +456,7 @@ export default {
|
||||
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 = [
|
||||
@@ -446,9 +482,15 @@ export default {
|
||||
this.echartsInit(this.npmQuantity, '(ms)')
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.isNoData = false
|
||||
this.showError = true
|
||||
this.errorMsg = res.message
|
||||
}
|
||||
}).catch(e => {
|
||||
this.isNoData = true
|
||||
this.isNoData = false
|
||||
this.showError = true
|
||||
this.errorMsg = e.message
|
||||
}).finally(() => {
|
||||
this.toggleLoading(false)
|
||||
})
|
||||
@@ -456,6 +498,7 @@ export default {
|
||||
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 = [
|
||||
@@ -481,9 +524,15 @@ export default {
|
||||
this.echartsInit(this.npmQuantity, '(ms)')
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.isNoData = false
|
||||
this.showError = true
|
||||
this.errorMsg = res.message
|
||||
}
|
||||
}).catch(e => {
|
||||
this.isNoData = true
|
||||
this.isNoData = false
|
||||
this.showError = true
|
||||
this.errorMsg = e.message
|
||||
}).finally(() => {
|
||||
this.toggleLoading(false)
|
||||
})
|
||||
@@ -617,6 +666,7 @@ export default {
|
||||
beforeUnmount () {
|
||||
clearTimeout(this.timer)
|
||||
window.removeEventListener('resize', this.resize)
|
||||
this.myChart = null
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
<template>
|
||||
<div class="npm-sessions">
|
||||
<div class="npm-sessions-title">{{$t('npm.relatedSessions')}}</div>
|
||||
<div class="npm-sessions-title">
|
||||
{{$t('npm.relatedSessions')}}
|
||||
<chart-error v-if="showError" tooltip :content="errorMsg" />
|
||||
</div>
|
||||
<div class="npm-sessions-div">
|
||||
<div class="npm-sessions-div-green" id="green" v-show="clientSessions > 0"></div>
|
||||
<div class="npm-sessions-div-red" id="red" v-show="serverSessions > 0"></div>
|
||||
<div class="npm-sessions-div-gray" id="gray" v-show="showError || isNoData"></div>
|
||||
</div>
|
||||
<div class="npm-sessions-body">
|
||||
<div class="npm-sessions-body-left">
|
||||
@@ -36,9 +40,11 @@ import { getSecond } from '@/utils/date-util'
|
||||
import unitConvert from '@/utils/unit-convert'
|
||||
import { unitTypes } from '@/utils/constants'
|
||||
import chartMixin from '@/views/charts2/chart-mixin'
|
||||
import ChartError from '@/components/common/Error'
|
||||
|
||||
export default {
|
||||
name: 'RelatedSessions',
|
||||
components: { ChartError },
|
||||
mixins: [chartMixin],
|
||||
data () {
|
||||
return {
|
||||
@@ -46,12 +52,16 @@ export default {
|
||||
unitConvert,
|
||||
unitTypes,
|
||||
clientSessions: 0,
|
||||
serverSessions: 0
|
||||
serverSessions: 0,
|
||||
showError: false,
|
||||
errorMsg: '',
|
||||
noData: false,
|
||||
isNoData: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
timeFilter: {
|
||||
handler (n) {
|
||||
handler () {
|
||||
this.relatedSessionsData()
|
||||
}
|
||||
}
|
||||
@@ -66,25 +76,63 @@ export default {
|
||||
ip: condition[1]
|
||||
}
|
||||
const divGreen = document.getElementById('green')
|
||||
const divred = document.getElementById('red')
|
||||
const divRed = document.getElementById('red')
|
||||
const divGray = document.getElementById('gray')
|
||||
get(api.npm.overview.relatedSessions, params).then(res => {
|
||||
if (res.code === 200) {
|
||||
this.showError = false
|
||||
this.isNoData = false
|
||||
|
||||
this.sessionData = res.data.result
|
||||
this.clientSessions = this.sessionData.clientSessions / (this.sessionData.clientSessions * 1 + this.sessionData.serverSessions * 1)
|
||||
this.serverSessions = this.sessionData.serverSessions / (this.sessionData.clientSessions * 1 + this.sessionData.serverSessions * 1)
|
||||
this.sessionData.clientSessions = unitConvert(this.clientSessions, unitTypes.percent).join('')
|
||||
this.sessionData.serverSessions = unitConvert(this.serverSessions, unitTypes.percent).join('')
|
||||
if (this.clientSessions === 1) {
|
||||
divGreen.style.borderRadius = 4 + 'px'
|
||||
} else if (this.serverSessions === 1) {
|
||||
divred.style.borderRadius = 4 + 'px'
|
||||
const client = this.sessionData.clientSessions
|
||||
const server = this.sessionData.serverSessions
|
||||
|
||||
// 如果返回数据为-,则不必计算比例
|
||||
if (!isNaN(client) && !isNaN(server)) {
|
||||
this.clientSessions = client / (client * 1 + server * 1)
|
||||
this.serverSessions = server / (client * 1 + server * 1)
|
||||
this.sessionData.clientSessions = unitConvert(this.clientSessions, unitTypes.percent).join('')
|
||||
this.sessionData.serverSessions = unitConvert(this.serverSessions, unitTypes.percent).join('')
|
||||
|
||||
if (this.clientSessions === 1) {
|
||||
divGreen.style.borderRadius = 4 + 'px'
|
||||
} else if (this.serverSessions === 1) {
|
||||
divRed.style.borderRadius = 4 + 'px'
|
||||
} else if (this.clientSessions === 0 && this.serverSessions === 0) {
|
||||
this.isNoData = true
|
||||
divGray.style.borderRadius = 4 + 'px'
|
||||
divGray.style.width = '100%'
|
||||
}
|
||||
divGreen.style.width = this.sessionData.clientSessions
|
||||
divRed.style.width = this.sessionData.serverSessions
|
||||
} else {
|
||||
this.isNoData = true
|
||||
this.changeByErrorOrNodata()
|
||||
}
|
||||
divGreen.style.width = this.sessionData.clientSessions
|
||||
divred.style.width = this.sessionData.serverSessions
|
||||
} else {
|
||||
this.showError = true
|
||||
this.errorMsg = res.message
|
||||
this.changeByErrorOrNodata()
|
||||
}
|
||||
}).catch(error => {
|
||||
this.showError = true
|
||||
this.errorMsg = error.message
|
||||
this.changeByErrorOrNodata()
|
||||
}).finally(() => {
|
||||
this.toggleLoading(false)
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 当无数据或者报错时改变界面样式,出现灰条
|
||||
*/
|
||||
changeByErrorOrNodata () {
|
||||
const divGray = document.getElementById('gray')
|
||||
divGray.style.borderRadius = 4 + 'px'
|
||||
divGray.style.width = '100%'
|
||||
this.sessionData.clientSessions = '—'
|
||||
this.sessionData.serverSessions = '—'
|
||||
this.clientSessions = 0
|
||||
this.serverSessions = 0
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
|
||||
@@ -1,153 +1,65 @@
|
||||
<template v-if="npmNetworkData.length > 0">
|
||||
<div class="single-value" v-for="(npm, index) in npmNetworkData" :key="index">
|
||||
<template v-if="index === 0">
|
||||
<div class="single-value__title">{{$t(npmNetworkName[index].name)}}</div>
|
||||
<div class="single-value__content">
|
||||
<div class="single-value__content-number">{{unitConvert(npm.establishLatencyMsAvg, unitTypes.time).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>
|
||||
<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__circle">
|
||||
<div class="single-value__circle-p95">P95: {{unitConvert(npm.establishLatencyMsP95, unitTypes.time).join(' ')}}</div>
|
||||
<div class="single-value__circle-p99">P99: {{unitConvert(npm.establishLatencyMsP99, unitTypes.time).join(' ')}}</div>
|
||||
<div class="single-value__content-number" v-else>
|
||||
{{unitConvert(npm.Avg, unitTypes.percent).join(' ')}}
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="index === 1">
|
||||
<div class="single-value__title">{{$t(npmNetworkName[index].name)}}</div>
|
||||
<div class="single-value__content">
|
||||
<div class="single-value__content-number">{{unitConvert(npm.httpResponseLatencyAvg, unitTypes.time).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 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 class="single-value__circle">
|
||||
<div class="single-value__circle-p95">P95: {{unitConvert(npm.httpResponseLatencyP95, unitTypes.time).join(' ')}}</div>
|
||||
<div class="single-value__circle-p99">P99: {{unitConvert(npm.httpResponseLatencyP99, unitTypes.time).join(' ')}}</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>
|
||||
</template>
|
||||
<template v-if="index === 2">
|
||||
<div class="single-value__title">{{$t(npmNetworkName[index].name)}}</div>
|
||||
<div class="single-value__content">
|
||||
<div class="single-value__content-number">{{unitConvert(npm.sslConLatencyAvg, unitTypes.time).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 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 class="single-value__circle">
|
||||
<div class="single-value__circle-p95">P95: {{unitConvert(npm.sslConLatencyP95, unitTypes.time).join(' ')}}</div>
|
||||
<div class="single-value__circle-p99">P99: {{unitConvert(npm.sslConLatencyP99, unitTypes.time).join(' ')}}</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>
|
||||
</template>
|
||||
<template v-if="index === 3">
|
||||
<div class="single-value__title">{{$t(npmNetworkName[index].name)}}</div>
|
||||
<div class="single-value__content">
|
||||
<div class="single-value__content-number">{{unitConvert(npm.tcpLostlenPercentAvg, 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 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 class="single-value__circle">
|
||||
<div class="single-value__circle-p95">P95: {{unitConvert(npm.tcpLostlenPercentP95, unitTypes.percent).join(' ')}}</div>
|
||||
<div class="single-value__circle-p99">P99: {{unitConvert(npm.tcpLostlenPercentP99, unitTypes.percent).join(' ')}}</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="index === 4">
|
||||
<div class="single-value__title">{{$t(npmNetworkName[index].name)}}</div>
|
||||
<div class="single-value__content">
|
||||
<div class="single-value__content-number">{{unitConvert(npm.pktRetransPercentAvg, 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">P95: {{unitConvert(npm.pktRetransPercentP95, unitTypes.percent).join(' ')}}</div>
|
||||
<div class="single-value__circle-p99">P99: {{unitConvert(npm.pktRetransPercentP99, unitTypes.percent).join(' ')}}</div>
|
||||
</div>
|
||||
</template>
|
||||
</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
|
||||
@@ -155,7 +67,58 @@ export default {
|
||||
data () {
|
||||
return {
|
||||
unitTypes,
|
||||
unitConvert
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ export const pieChartOption1 = {
|
||||
const data = pieChartOption1.series[0].data
|
||||
let value
|
||||
data.forEach(t => {
|
||||
if (t.name == name) {
|
||||
if (t.name === name) {
|
||||
value = t.value
|
||||
}
|
||||
})
|
||||
@@ -103,7 +103,7 @@ export const pieChartOption2 = {
|
||||
const data = pieChartOption2.series[0].data
|
||||
let value
|
||||
data.forEach(t => {
|
||||
if (t.name == name) {
|
||||
if (t.name === name) {
|
||||
value = t.value
|
||||
}
|
||||
})
|
||||
@@ -164,6 +164,15 @@ export const stackedLineChartOption = {
|
||||
trigger: 'axis',
|
||||
className: 'echarts-tooltip echarts-tooltip-dark'
|
||||
},
|
||||
toolbox: {
|
||||
show: false
|
||||
},
|
||||
brush: {
|
||||
toolbox: ['lineX'],
|
||||
xAxisIndex: 'all',
|
||||
throttleType: 'debounce',
|
||||
transformable: false
|
||||
},
|
||||
legend: {
|
||||
show: false
|
||||
},
|
||||
@@ -177,7 +186,7 @@ export const stackedLineChartOption = {
|
||||
xAxis: [
|
||||
{
|
||||
type: 'time',
|
||||
splitNumber: 12
|
||||
splitNumber: 8
|
||||
// axisLabel: {
|
||||
// formatter: function (value) {
|
||||
// const data = new Date(value)
|
||||
@@ -234,7 +243,7 @@ export const linkTrafficLineChartOption = {
|
||||
xAxis: [
|
||||
{
|
||||
type: 'time',
|
||||
splitNumber: 12
|
||||
splitNumber: 8
|
||||
// axisLabel: {
|
||||
// formatter: function (value) {
|
||||
// const data = new Date(value)
|
||||
@@ -294,7 +303,7 @@ export const appListChartOption = {
|
||||
bottom: 0
|
||||
},
|
||||
animation: false,
|
||||
color: chartColor,
|
||||
color: chartColor3[2],
|
||||
axisLabel: {},
|
||||
series: [
|
||||
{
|
||||
@@ -351,18 +360,7 @@ export const npmLineChartOption = {
|
||||
}
|
||||
}
|
||||
],
|
||||
series: [
|
||||
{
|
||||
type: 'line',
|
||||
symbol: 'circle',
|
||||
smooth: true,
|
||||
showSymbol: false,
|
||||
emphasis: {
|
||||
focus: 'series'
|
||||
},
|
||||
data: []
|
||||
}
|
||||
]
|
||||
series: []
|
||||
}
|
||||
|
||||
export const trafficLineChartOption = {
|
||||
@@ -397,7 +395,7 @@ export const trafficLineChartOption = {
|
||||
xAxis: [
|
||||
{
|
||||
type: 'time',
|
||||
splitNumber: 12
|
||||
splitNumber: 8
|
||||
// axisLabel: {
|
||||
// formatter: function (value) {
|
||||
// const data = new Date(value)
|
||||
@@ -487,7 +485,7 @@ export const stackedBarChartOption = {
|
||||
xAxis: {
|
||||
type: 'time',
|
||||
boundaryGap: ['1%', '3%'],
|
||||
splitNumber: 12,
|
||||
splitNumber: 8,
|
||||
axisLine: {
|
||||
show: false
|
||||
},
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
<template>
|
||||
<div class="detection-filter-case">
|
||||
<div class="no-data" v-if="isNoData">No data</div>
|
||||
|
||||
<div class="new-detection-filter-title">{{$t('detections.filters')}}</div>
|
||||
<template v-for="(filter, index) in filterData" :key="index">
|
||||
<div class="detection-filter" v-show="filter.data.length > 0">
|
||||
<div class="filter__header" @click="filter.collapse = !filter.collapse">
|
||||
<i class="el-icon-arrow-right" :class="{ 'arrow-rotate': !filter.collapse }"></i>
|
||||
<span>{{filter.title}}</span>
|
||||
<span class="new-detection-filter-header-title">{{filter.title}}</span>
|
||||
<i class="el-icon-arrow-right new-detection-filter-icon" :class="{ 'arrow-rotate': !filter.collapse }"></i>
|
||||
</div>
|
||||
<el-collapse-transition>
|
||||
<div class="filter__body" v-show="!filter.collapse">
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
<div class="detection-list__content">
|
||||
<div class="detection-list--list">
|
||||
<div class="no-data" v-if="noData">No data</div>
|
||||
<div v-if="!isCollapse" @click="collapse" class="cn-detection__shadow"></div>
|
||||
<div v-if="!isCollapse" @click="collapse" class="cn-detection__shadow new-cn-detection__shadow"></div>
|
||||
<detection-row
|
||||
style="margin-bottom: 10px"
|
||||
class="detection-border"
|
||||
v-for="(data, index) in listData"
|
||||
:detection="data"
|
||||
:page-type="pageType"
|
||||
|
||||
@@ -1,13 +1,22 @@
|
||||
<template>
|
||||
<div class="cn-detection--list" :style="{zIndex: !isCollapse ? 1 : 'unset'}">
|
||||
<div class="cn-detection--list" :style="{zIndex: !isCollapse ? 5 : 'unset'}">
|
||||
<!-- 左侧下拉按钮 -->
|
||||
<div class="cn-detection__collapse">
|
||||
<span @click="switchCollapse" :class="{'reg-down': !isCollapse}"><i class="cn-icon cn-icon-arrow-right"></i></span>
|
||||
<div class="cn-detection__collapse-block" @click="switchCollapse">
|
||||
<span :class="{'reg-down': !isCollapse}">
|
||||
<i class="cn-icon cn-icon-arrow-right"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cn-detection__case">
|
||||
<div class="cn-detection__icon" :style="`background-color: ${eventSeverityColor[detection.eventSecurity]}`"></div>
|
||||
<div class="cn-detection__row">
|
||||
<div class="cn-detection__header" v-if="pageType === detectionPageType.securityEvent">
|
||||
<span
|
||||
class="detection-event-severity-color-block"
|
||||
:style="`background-color: ${eventSeverityColor[detection.eventSeverity]}`">
|
||||
</span>
|
||||
<span class="detection-event-severity-block">{{ detection.securityType || '-' }}</span>
|
||||
<i class="cn-icon cn-icon-attacker" ></i>{{detection.offenderIp || '-'}}
|
||||
<div v-if="detection.domain" class="domain">{{detection.domain}}</div>
|
||||
<span class="line">-------</span>
|
||||
@@ -31,11 +40,6 @@
|
||||
<span>{{$t('detections.eventSeverity')}} : </span>
|
||||
<span>{{detection.eventSeverity || '-'}}</span>
|
||||
</div>
|
||||
<div class="basic-info__item" v-if="detection.securityType">
|
||||
<i class="cn-icon cn-icon-event-type"></i>
|
||||
<span>{{$t('detection.list.securityType')}} : </span>
|
||||
<span>{{detection.securityType || '-'}}</span>
|
||||
</div>
|
||||
<div class="basic-info__item" v-if="detection.eventType">
|
||||
<i class="cn-icon cn-icon-event-type"></i>
|
||||
<span>{{$t('detections.eventType')}} : </span>
|
||||
|
||||
94
src/views/detections/DetectionTabs.vue
Normal file
94
src/views/detections/DetectionTabs.vue
Normal file
@@ -0,0 +1,94 @@
|
||||
<template>
|
||||
<div class="npm-tabs">
|
||||
12345678
|
||||
<div class="npm-tabs__active-bar"></div>
|
||||
<el-tabs v-model="currentTab" ref="elTabs" type="border-card" @tab-click="jumpPage">
|
||||
<el-tab-pane
|
||||
v-for="(tab,index) in tabs"
|
||||
:key="tab.i18n"
|
||||
:name="index"
|
||||
:disabled="tab.disable">
|
||||
<template #label>
|
||||
<div class="npm-tab__label">
|
||||
<i :class="tab.icon"></i>
|
||||
<span>{{ $t(tab.i18n) }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import chartMixin from '@/views/charts2/chart-mixin'
|
||||
import { overwriteUrl, urlParamsHandler } from '@/utils/tools'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { ref } from 'vue'
|
||||
|
||||
export default {
|
||||
name: 'DetectionTabs',
|
||||
data () {
|
||||
return {
|
||||
leftOffset: 27
|
||||
}
|
||||
},
|
||||
mixins: [chartMixin],
|
||||
setup (props) {
|
||||
const tabs = ref([])
|
||||
if (props.chart) {
|
||||
tabs.value = [...props.chart]
|
||||
tabs.value.forEach(item => {
|
||||
item.disable = false
|
||||
})
|
||||
}
|
||||
const { query } = useRoute()
|
||||
const tabIndexParam = query.tabIndex
|
||||
const currentTab = ref(tabIndexParam ? parseInt(tabIndexParam) : 0)
|
||||
return {
|
||||
currentTab,
|
||||
tabs
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
currentTab (n) {
|
||||
const { query } = this.$route
|
||||
const newUrl = urlParamsHandler(window.location.href, query, {
|
||||
tabIndex: n
|
||||
})
|
||||
overwriteUrl(newUrl)
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.handleActiveBar(n)
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleActiveBar (index) {
|
||||
const tabDom = document.getElementById('tab-' + index)
|
||||
if (tabDom) {
|
||||
const offsetLeft = tabDom.offsetLeft
|
||||
const clientWidth = tabDom.clientWidth
|
||||
const clientLeft = tabDom.clientLeft
|
||||
const activeBar = document.querySelector('.npm-tabs .npm-tabs__active-bar')
|
||||
activeBar.style.cssText += `width: ${clientWidth + 2}px; left: ${offsetLeft + this.leftOffset + clientLeft - 1}px;`
|
||||
}
|
||||
},
|
||||
jumpPage (item) {
|
||||
this.$router.push({
|
||||
path: this.tabs[item.index].path,
|
||||
query: {
|
||||
t: +new Date(),
|
||||
tabIndex: this.currentTab
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
// setTimeout(() => {
|
||||
this.$nextTick(() => {
|
||||
this.handleActiveBar(this.currentTab)
|
||||
})
|
||||
// }, 120)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,37 +1,57 @@
|
||||
<template>
|
||||
<div
|
||||
class="entity-explorer entity-explorer--show-list"
|
||||
>
|
||||
<div class="entity-explorer entity-explorer--show-list">
|
||||
<!-- 顶部工具栏,在列表页显示 -->
|
||||
<div class="explorer-top-tools">
|
||||
<DateTimeRange class="date-time-range" :start-time="timeFilter.startTime" :end-time="timeFilter.endTime" :date-range="timeFilter.dateRangeValue" ref="dateTimeRange" @change="reload"/>
|
||||
<TimeRefresh class="date-time-range" @change="timeRefreshChange" :end-time="timeFilter.endTime"/>
|
||||
<div class="explorer-top-tools explorer-detection-top-tools">
|
||||
<div class="explorer-top-tools-title">{{$t('overall.detections')}}</div>
|
||||
<div style="display: flex">
|
||||
<div class="explorer-top-tools-block">
|
||||
<i class="cn-icon cn-icon-setting detection-icon-setting"></i>
|
||||
<span>Configure Policies</span>
|
||||
</div>
|
||||
<DateTimeRange
|
||||
class="date-time-range"
|
||||
:start-time="timeFilter.startTime"
|
||||
:end-time="timeFilter.endTime"
|
||||
:date-range="timeFilter.dateRangeValue"
|
||||
ref="dateTimeRange"
|
||||
@change="reload"/>
|
||||
<TimeRefresh
|
||||
class="date-time-range"
|
||||
@change="timeRefreshChange"
|
||||
:end-time="timeFilter.endTime"/>
|
||||
</div>
|
||||
</div>
|
||||
<div style="width: 100%;padding-bottom: 26px;">
|
||||
<detection-tabs :time-filter="timeFilter" :chart="tabsData" />
|
||||
</div>
|
||||
|
||||
<!-- 搜索组件 -->
|
||||
<detection-search
|
||||
class="detection-border"
|
||||
ref="search"
|
||||
:page-type="pageType"
|
||||
@search="search"
|
||||
></detection-search>
|
||||
<!-- 内容区 -->
|
||||
<div class="explorer-container" style="height: calc(100% - 20px); flex-direction: column">
|
||||
<div class="explorer-container" style="height: calc(100% - 20px);flex-direction: column">
|
||||
<loading :loading="loading"></loading>
|
||||
<template v-if="isEventSeverityNoData">
|
||||
<div class="no-data detection__event-severity-bar" >No data</div>
|
||||
</template>
|
||||
<template v-if="!isEventSeverityNoData">
|
||||
<div class="detection__event-severity-bar" :id="`eventSeverityTrendBar${pageType}`">
|
||||
<div class="detection__event-severity-bar detection-border" :id="`eventSeverityTrendBar${pageType}`">
|
||||
</div>
|
||||
</template>
|
||||
<div style="display: flex; flex-grow: 1; height: 100%;">
|
||||
<detection-filter
|
||||
class="detection-border"
|
||||
:filter-data="filterData[pageType]"
|
||||
:q="q"
|
||||
:time-filter="timeFilter"
|
||||
></detection-filter>
|
||||
|
||||
<div class="detection__list">
|
||||
<div class="detection__list-statistics">
|
||||
<div class="detection__list-statistics detection-border">
|
||||
<div class="statistics__severity">
|
||||
<div class="chart-header">
|
||||
<div class="chart-header__title">{{$t('detection.severity')}}</div>
|
||||
@@ -81,15 +101,14 @@
|
||||
></detection-list>
|
||||
<div class="entity__pagination" >
|
||||
<Pagination
|
||||
ref="pagination"
|
||||
:page-obj="pageObj"
|
||||
@pageNo='pageNo'
|
||||
@pageSize='pageSize'
|
||||
@size-change="pageSize"
|
||||
@prev-click="prev"
|
||||
@next-click="next"
|
||||
>
|
||||
</Pagination>
|
||||
ref="pagination"
|
||||
:page-obj="pageObj"
|
||||
@pageNo='pageNo'
|
||||
@pageSize='pageSize'
|
||||
@size-change="pageSize"
|
||||
@prev-click="prev"
|
||||
@next-click="next"
|
||||
></Pagination>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -108,12 +127,13 @@ import { defaultPageSize, detectionPageType } from '@/utils/constants'
|
||||
import { getNowTime, getSecond, rTime } from '@/utils/date-util'
|
||||
import { ref, shallowRef } from 'vue'
|
||||
import * as echarts from 'echarts'
|
||||
import { multipleBarOption, pieForSeverity, activeAttackBar, getAttackColor, getSeverityColor, getSeriesIndex } from '@/views/detections/options/detectionOptions'
|
||||
import { multipleBarOption, pieForSeverity, activeAttackBar, getAttackColor, getSeverityColor } from '@/views/detections/options/detectionOptions'
|
||||
import { api, getData } from '@/utils/api'
|
||||
import { reverseSortBy, sortBy, extensionEchartY } from '@/utils/tools'
|
||||
import { reverseSortBy, extensionEchartY } from '@/utils/tools'
|
||||
import { useRoute } from 'vue-router'
|
||||
import DetectionNoData from '@/views/detections/DetectionNoData'
|
||||
// import DetectionNoData from '@/views/detections/DetectionNoData'
|
||||
import Loading from '@/components/common/Loading'
|
||||
import DetectionTabs from '@/views/detections/DetectionTabs'
|
||||
|
||||
export default {
|
||||
name: 'Index',
|
||||
@@ -125,10 +145,31 @@ export default {
|
||||
DetectionFilter,
|
||||
DetectionList,
|
||||
Pagination,
|
||||
DetectionNoData
|
||||
// DetectionNoData,
|
||||
DetectionTabs
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
tabsData: [
|
||||
{
|
||||
name: 'SecurityEvents',
|
||||
i18n: 'entities.securityEvents',
|
||||
path: '/detection/securityEvent',
|
||||
icon: 'cn-icon cn-icon-a-SecurityEvent'
|
||||
},
|
||||
{
|
||||
name: 'Regulatory Risk Event',
|
||||
i18n: 'entities.regulatoryRiskEvents',
|
||||
path: '/detection/securityEvent',
|
||||
icon: 'cn-icon cn-icon-a-RegulatoryRiskEvent'
|
||||
},
|
||||
{
|
||||
name: 'PerformanceEvents',
|
||||
i18n: 'overall.performanceEvents',
|
||||
path: '/detection/performanceEvent',
|
||||
icon: 'cn-icon cn-icon-a-PerformanceEvent'
|
||||
}
|
||||
],
|
||||
chartInit: [],
|
||||
pageObj: {
|
||||
pageNo: 1,
|
||||
@@ -231,7 +272,6 @@ export default {
|
||||
isStatisticsCategoryNoData: false,
|
||||
isStatisticsActiveAttackNoData: false,
|
||||
loading: false,
|
||||
|
||||
oldActiveEntitySearchValue: ''
|
||||
}
|
||||
},
|
||||
@@ -258,7 +298,7 @@ export default {
|
||||
const eventSeverityTrendOption = this.$_.cloneDeep(multipleBarOption)
|
||||
|
||||
const xData = []
|
||||
dataMap.forEach(function (value, key) {
|
||||
dataMap.forEach(function (value) {
|
||||
// eventSeverityTrendOption.series[Number(getSeriesIndex(key))].data = value.map(v => Number(v[1]))
|
||||
value.forEach(item => {
|
||||
if (xData.indexOf(item[0]) < 0) {
|
||||
@@ -270,8 +310,10 @@ export default {
|
||||
const seriesData = []
|
||||
xData.forEach(item => {
|
||||
if (dataMap.has(serie.name)) {
|
||||
// todo 下面这行注释可解决eslint报红线的问题,暂不知道原因,后续解决
|
||||
// eslint-disable-next-line array-callback-return
|
||||
const hasX = dataMap.get(serie.name).some(function (v) {
|
||||
if (item == v[0]) {
|
||||
if (item === v[0]) {
|
||||
seriesData.push(Number(v[1]))
|
||||
return true
|
||||
}
|
||||
@@ -296,7 +338,7 @@ export default {
|
||||
// this.isEventSeverityNoData = true
|
||||
}
|
||||
}).catch(error => {
|
||||
|
||||
console.log(error)
|
||||
}).finally(() => {
|
||||
this.$nextTick(() => {
|
||||
this.loading = false
|
||||
@@ -329,7 +371,7 @@ export default {
|
||||
})
|
||||
}
|
||||
}).catch(error => {
|
||||
|
||||
console.log(error)
|
||||
})
|
||||
},
|
||||
initEventTypeData (params) {
|
||||
@@ -357,7 +399,7 @@ export default {
|
||||
})
|
||||
}
|
||||
}).catch(error => {
|
||||
|
||||
console.log(error)
|
||||
})
|
||||
},
|
||||
initSecurityTypeData (params) {
|
||||
@@ -385,7 +427,7 @@ export default {
|
||||
})
|
||||
}
|
||||
}).catch(error => {
|
||||
|
||||
console.log(error)
|
||||
})
|
||||
},
|
||||
initOffenderIpData (params) {
|
||||
@@ -419,7 +461,7 @@ export default {
|
||||
})
|
||||
}
|
||||
}).catch(error => {
|
||||
|
||||
console.log(error)
|
||||
})
|
||||
},
|
||||
|
||||
@@ -430,7 +472,7 @@ export default {
|
||||
this.filterData[this.pageType][2].showMore = showMore
|
||||
this.filterData[this.pageType][2].showIndex = showIndex
|
||||
}).catch(error => {
|
||||
|
||||
console.log(error)
|
||||
})
|
||||
},
|
||||
initVictimLocationData (params) {
|
||||
@@ -440,7 +482,7 @@ export default {
|
||||
this.filterData[this.pageType][3].showMore = showMore
|
||||
this.filterData[this.pageType][3].showIndex = showIndex
|
||||
}).catch(error => {
|
||||
|
||||
console.log(error)
|
||||
})
|
||||
},
|
||||
initOffenderLocationData (params) {
|
||||
@@ -450,7 +492,7 @@ export default {
|
||||
this.filterData[this.pageType][5].showMore = showMore
|
||||
this.filterData[this.pageType][5].showIndex = showIndex
|
||||
}).catch(error => {
|
||||
|
||||
console.log(error)
|
||||
})
|
||||
},
|
||||
initActiveEntity (params) {
|
||||
@@ -510,6 +552,7 @@ export default {
|
||||
})
|
||||
}
|
||||
}).catch(error => {
|
||||
console.log(error)
|
||||
})
|
||||
},
|
||||
triggerFilterDataValue (array, value) {
|
||||
@@ -539,12 +582,12 @@ export default {
|
||||
getData(api.detection[this.pageType].listBasic, params).then(data => {
|
||||
this.listData = data
|
||||
}).catch(error => {
|
||||
|
||||
console.log(error)
|
||||
})
|
||||
getData(api.detection[this.pageType].listCount, params).then(data => {
|
||||
this.pageObj.total = data
|
||||
}).catch(error => {
|
||||
|
||||
console.log(error)
|
||||
})
|
||||
},
|
||||
timeRefreshChange () {
|
||||
@@ -720,7 +763,7 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
timeFilter (n) {
|
||||
timeFilter () {
|
||||
this.search(this.metaList, this.q)
|
||||
},
|
||||
'filterData.securityEvent.0.value': {
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
<div class="overview__title">{{$t('detections.goToEntity')}}</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__content">
|
||||
<span>{{ $t('detections.viewDetailOf') }}</span>
|
||||
<span class="row__content--span">{{ $t('detections.viewDetailOf') }}</span>
|
||||
<span
|
||||
class="row__content--link"
|
||||
@click="goDetail('app', detection.appName)">{{detection.appName}}</span>
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
<div class="overview__title">{{$t('detections.goToEntity')}}</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__content">
|
||||
<span>{{ $t('detections.viewDetailOf') }}</span>
|
||||
<span class="row__content--span">{{ $t('detections.viewDetailOf') }}</span>
|
||||
<span
|
||||
class="row__content--link"
|
||||
@click="goDetail('domain', computeSecondaryDomain(detection.domain))">{{detection.domain}}</span>
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
<div class="overview__title">{{$t('detections.goToEntity')}}</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__content">
|
||||
<span>{{ $t('detections.viewDetailOf') }}</span>
|
||||
<span class="row__content--span">{{ $t('detections.viewDetailOf') }}</span>
|
||||
<span
|
||||
class="row__content--link"
|
||||
@click="goDetail('ip', detection.serverIp)">{{detection.serverIp}}</span>
|
||||
|
||||
@@ -164,7 +164,7 @@
|
||||
<div class="overview__title">{{ $t('detections.goToVictim') }}</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__content">
|
||||
<span>{{ $t('detections.viewDetailOf') }}</span>
|
||||
<span class="row__content--span">{{ $t('detections.viewDetailOf') }}</span>
|
||||
<span
|
||||
class="row__content--link"
|
||||
@click="goDetail('ip', basicInfo.victimIp)">{{ basicInfo.victimIp }}</span>
|
||||
@@ -173,7 +173,7 @@
|
||||
<div class="overview__title">{{ $t('detections.goToOffender') }}</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__content">
|
||||
<span>{{ $t('detections.viewDetailOf') }}</span>
|
||||
<span class="row__content--span">{{ $t('detections.viewDetailOf') }}</span>
|
||||
<span
|
||||
class="row__content--link"
|
||||
@click="goDetail('ip', basicInfo.offenderIp)"
|
||||
|
||||
Reference in New Issue
Block a user