Compare commits

..

21 Commits

Author SHA1 Message Date
刘洪洪
374c66fcff fix: 还原之前版本 2024-01-02 11:05:01 +08:00
刘洪洪
705572b245 fix: 修复实体、检测界面因路由路径问题不能打开,以及实体详情界面部分问题 2024-01-02 10:42:54 +08:00
chenjinsong
0152c46d05 fix: 修复知识库更新记录的时间丢失时区的问题 2023-10-31 19:39:54 +08:00
chenjinsong
64f376e22a CN-1445 fix: 修复切换不同知识库的更新页面后,psiphon3的柱状图不能显示的问题 2023-10-31 18:46:02 +08:00
chenjinsong
5b89fca77c CN-1404 fix: 去掉其他知识库的update按钮 2023-10-31 18:05:36 +08:00
陈劲松
d1f5997b88 Merge branch 'cherry-pick-f151415d' into 'dev-23.10'
fix: detection--policy的trigger去除秒时间选项

See merge request cyber-narrator/cn-ui!54
2023-10-31 09:25:41 +00:00
刘洪洪
88002a8fc4 fix: detection--policy的trigger去除秒时间选项
(cherry picked from commit f151415de6)
2023-10-31 09:25:33 +00:00
陈劲松
556a9b03b4 Merge branch 'cherry-pick-bd1f7556' into 'dev-23.10'
CN-1425 fix: 修复dashboard下钻后切换顶部最后一级面包屑时会回到下钻前页面的问题

See merge request cyber-narrator/cn-ui!53
2023-10-30 08:38:35 +00:00
chenjinsong
ca5c81d8be CN-1425 fix: 修复dashboard下钻后切换顶部最后一级面包屑时会回到下钻前页面的问题
(cherry picked from commit bd1f755612)
2023-10-30 08:38:28 +00:00
陈劲松
02779c26d1 Merge branch 'cherry-pick-dd4f5e1f' into 'dev-23.10'
fix: eventType取消国际化转换

See merge request cyber-narrator/cn-ui!52
2023-10-30 08:37:51 +00:00
刘洪洪
20692705e9 fix: eventType取消国际化转换
(cherry picked from commit dd4f5e1fba)
2023-10-30 08:37:42 +00:00
陈劲松
bc3bc7eaf3 Merge branch 'cherry-pick-ed1d994d' into 'dev-23.10'
fix: eventType取消国际化转换

See merge request cyber-narrator/cn-ui!51
2023-10-30 08:37:21 +00:00
刘洪洪
d05ae06af6 fix: eventType取消国际化转换
(cherry picked from commit ed1d994d5e)
2023-10-30 08:37:15 +00:00
陈劲松
ca3d8766ba Merge branch 'cherry-pick-815af776' into 'dev-23.10'
fix: 修复policy新建时点击save按钮不生效的问题

See merge request cyber-narrator/cn-ui!50
2023-10-30 08:35:12 +00:00
刘洪洪
00e73adadb fix: 修复policy新建时点击save按钮不生效的问题
(cherry picked from commit 815af776aa)
2023-10-30 08:35:01 +00:00
陈劲松
4ede5768e4 Merge branch 'cherry-pick-a4da1dbf' into 'dev-23.10'
fix: 去掉部分控制台打印

See merge request cyber-narrator/cn-ui!49
2023-10-30 08:34:06 +00:00
chenjinsong
541692f50f fix: 去掉部分控制台打印
(cherry picked from commit a4da1dbfac)
2023-10-30 08:33:59 +00:00
陈劲松
89294c98e1 Merge branch 'cherry-pick-7b8ca904' into 'dev-23.10'
fix: 修复policy新建时form的时间提示被盖住,以及限制输入框内容长度的问题

See merge request cyber-narrator/cn-ui!48
2023-10-30 08:33:22 +00:00
刘洪洪
8fd283c1e7 fix: 修复policy新建时form的时间提示被盖住,以及限制输入框内容长度的问题
(cherry picked from commit 7b8ca90436)
2023-10-30 08:33:16 +00:00
陈劲松
90b90fdd3c Merge branch 'cherry-pick-90827fd7' into 'dev-23.10'
fix: policy新建时添加小时不得超过24等时间限制

See merge request cyber-narrator/cn-ui!47
2023-10-30 07:19:38 +00:00
刘洪洪
72ee214877 fix: policy新建时添加小时不得超过24等时间限制
(cherry picked from commit 90827fd706)
2023-10-30 07:19:27 +00:00
108 changed files with 1348 additions and 2702 deletions

View File

@@ -3,18 +3,3 @@ const BASE_CONFIG = {
version: '23.10', version: '23.10',
apiVersion: 'v1' apiVersion: 'v1'
} }
// 默认时间过滤条件,单位分钟. 0表示请求接口时不传时间参数
const DEFAULT_TIME_FILTER_RANGE = {
dashboard: 60,
entity: {
list: 60,
trafficLine: 60,
informationAggregation: 0,
relatedEntity: 60 * 24 * 7,
openPort: 60 * 24 * 7,
securityEvent: 60 * 24 * 7,
performanceEvent: 60 * 24 * 7,
behaviorPattern: 60 * 24 * 7
},
detection: 60
}

View File

@@ -54,8 +54,7 @@ export default {
return { return {
loading: false, loading: false,
username: '', username: '',
pin: '', pin: ''
language: ''
} }
}, },
methods: { methods: {
@@ -76,9 +75,6 @@ export default {
if (!_.isEmpty(res.data.data.user.lang)) { if (!_.isEmpty(res.data.data.user.lang)) {
localStorage.setItem(storageKey.language, res.data.data.user.lang) localStorage.setItem(storageKey.language, res.data.data.user.lang)
} }
if (!localStorage.getItem(storageKey.language)) {
localStorage.setItem(storageKey.language, this.language)
}
if (!_.isEmpty(res.data.data.user.theme)) { if (!_.isEmpty(res.data.data.user.theme)) {
localStorage.setItem(storageKey.theme, res.data.data.user.theme) localStorage.setItem(storageKey.theme, res.data.data.user.theme)
} }
@@ -111,7 +107,6 @@ export default {
}) })
}, },
appearanceOut (data) { appearanceOut (data) {
this.language = data.lang || defaultLang
if (_.isEmpty(localStorage.getItem(storageKey.language))) { if (_.isEmpty(localStorage.getItem(storageKey.language))) {
localStorage.setItem(storageKey.language, data.lang || defaultLang) localStorage.setItem(storageKey.language, data.lang || defaultLang)
} }

View File

@@ -3,92 +3,84 @@
height: 100%; height: 100%;
.search__suffixes { .search__suffixes {
height: 38px;
&.entity-explorer-home {
margin-right: 1px;
color: #3976CB;
&.search__suffixes--text-mode, &.search__suffixes--tag-mode {
.search__suffix:last-of-type {
width: unset;
height: unset;
margin-right: 12px;
background-color: transparent;
.el-icon-search {
color: #3976CB;
}
}
}
}
&.search__suffixes--text-mode, &.search__suffixes--tag-mode { &.search__suffixes--text-mode, &.search__suffixes--tag-mode {
position: absolute; position: absolute;
display: flex; display: flex;
align-items: center; top: 10px;
top: 1px; right: 10px;
right: 0;
.search__suffix { .search__suffix {
display: flex; // margin-left: 8px;
align-items: center;
justify-content: center;
margin-right: 12px;
border-radius: 0 2px 2px 0;
.cn-icon-search-advance, .cn-icon-search-normal, .cn-icon-filter { .cn-icon-search-advance, .cn-icon-search-normal, .cn-icon-filter {
color: #A6AAAE; color: #A6AAAE;
font-size: 18px; font-size: 18px;
} }
.el-icon-search {
color: #3976CB;
font-size: 22px;
}
&:hover { &:hover {
cursor: pointer; cursor: pointer;
} }
&:last-of-type {
margin-right: 0;
width: 41px;
height: 38px;
line-height: 39px;
background: #38ACD2;
.el-icon-search {
font-size: 22px;
color: #fff;
}
}
} }
.search__suffix-close { .search__suffix-close {
height: 40px;
line-height: 40px;
margin-top: -9px;
.el-icon-error { .el-icon-error {
font-size: 17px; font-size: 17px;
color: #C4C4C4; color: #C4C4C4;
margin-right: 12px;
cursor: pointer; cursor: pointer;
} }
} }
.entity-explorer-search {
color: #3976CB;
margin-top: -2px;
}
.margin-r-12 {
margin-right: 12px;
}
.new-search__suffix {
width: 41px;
height: 41px;
line-height: 41px;
background: #38ACD2;
text-align: center;
margin-top: -10px;
margin-right: -10px;
.el-icon-search {
color: #fff !important;
margin-top: 9px !important;
}
}
.my-popper-class .el-popper__arrow { .my-popper-class .el-popper__arrow {
display: none; display: none;
} }
} }
&.search__suffixes--tag-mode__block {
background: #fff;
}
} }
/*.search-tip--error {
font-size: 14px;
color: #F56C6C;
}*/
} }
.detections { .advanced-search--show-list .CodeMirror, .advanced-search--show-list .tag-search {
.tag-search, .CodeMirror { border: none;
border: 1px solid #E2E5EC;
}
} }
.tag-search { .tag-search {
display: flex; display: flex;
align-items: center; align-items: center;
height: 40px; height: 40px;
overflow: auto hidden; overflow: auto hidden;
border: 1px solid #CECECE;
border-radius: 2px; border-radius: 2px;
padding-left: 10px; padding-left: 10px;
padding-right: 80px; padding-right: 80px;
background-color: white; background-color: white;
border: 1px solid #DEDEDE;
&::-webkit-scrollbar { &::-webkit-scrollbar {
width: 8px; width: 8px;
@@ -112,7 +104,6 @@
border-radius: 1px; border-radius: 1px;
cursor: pointer; cursor: pointer;
transition: all linear .1s; transition: all linear .1s;
margin-right: 30px;
&:hover { &:hover {
background-color: white; background-color: white;
@@ -176,9 +167,6 @@
} }
} }
} }
.entity__search .tag-search {
padding-left: 65px;
}
.el-popover.my-popper-class { .el-popover.my-popper-class {
width: auto !important; width: auto !important;

View File

@@ -13,16 +13,11 @@
color: #ccc; color: #ccc;
} }
} }
.entity__search {
.CodeMirror {
padding-left: 60px;
}
}
/* PADDING */ /* PADDING */
.CodeMirror-lines { .CodeMirror-lines {
padding: 9px 5px; /* Vertical padding around content */ padding: 11px 5px; /* Vertical padding around content */
} }
.CodeMirror pre.CodeMirror-line, .CodeMirror pre.CodeMirror-line,
.CodeMirror pre.CodeMirror-line-like { .CodeMirror pre.CodeMirror-line-like {

View File

@@ -5,7 +5,6 @@
&>div { &>div {
height: 100%; height: 100%;
} }
overflow-y: auto;
} }
.cn-header { .cn-header {

View File

@@ -15,7 +15,8 @@
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: 20px; margin-top: 20px;
padding: 0 20px 20px;
.panel__title { .panel__title {
font-size: 24px; font-size: 24px;

View File

@@ -194,13 +194,12 @@
} }
} }
.form-setting__btn, .form-setting__btn1, .policy-form__footer__btn { .form-setting__btn, .form-setting__btn1 {
width: 100%; width: 100%;
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
.el-button { .el-button {
width: 80px !important;
height: 30px !important; height: 30px !important;
min-height: 30px !important; min-height: 30px !important;
line-height: 30px !important; line-height: 30px !important;
@@ -223,15 +222,8 @@
} }
} }
} }
.policy-form__footer__btn {
justify-content: center;
margin-top: 8px;
.btn1 { .form-setting__btn1 {
margin-right: 16px;
}
}
.form-setting__btn1, .policy-form__footer__btn {
.el-button { .el-button {
padding: 0 11px !important; padding: 0 11px !important;
} }

View File

@@ -10,9 +10,9 @@
} }
.detection-form-content { .detection-form-content {
height: calc(100% - 92px); height: 100%;
overflow: scroll; overflow: scroll;
padding-bottom: 20px; padding-bottom: 40px;
.detection-form-collapse { .detection-form-collapse {
margin-top: 20px; margin-top: 20px;
@@ -130,12 +130,6 @@
} }
} }
} }
.policy-form-trigger {
.el-collapse-item__content {
padding-bottom: 0 !important;
}
}
} }
.el-input--mini, .el-input--mini .el-input__inner { .el-input--mini, .el-input--mini .el-input__inner {
@@ -149,13 +143,4 @@
padding-bottom: 20px; padding-bottom: 20px;
} }
.policy-form__footer {
width: calc(100% + 40px);
height: 60px;
margin-left: -20px;
box-shadow: 0 -1px 4px 0 rgba(0,0,0,0.10);
display: flex;
align-items: center;
justify-content: center;
}
} }

View File

@@ -34,15 +34,6 @@
.drawer-basic-id { .drawer-basic-id {
margin-bottom: 10px; margin-bottom: 10px;
display: flex;
justify-content: space-between;
align-items: center;
i {
font-size: 14px;
font-weight: 400;
cursor: pointer;
}
} }
} }
} }

View File

@@ -2,124 +2,98 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
width: 280px; width: 280px;
margin-right: 12px; padding: 10px;
margin-right: 10px;
background-color: white;
overflow: auto; overflow: auto;
z-index: 1;
border: 1px solid rgba(226, 229, 236, 1) !important;
border-radius: 4px !important;
.filter-case__header { .detection-filter {
padding-left: 8px; display: flex;
height: 36px; flex-direction: column;
line-height: 36px; margin-bottom: 10px;
color: #666;
font-size: 14px;
background: #F7F7F7;
box-shadow: 0 1px 0 0 rgba(226,229,236,1);
border-radius: 4px 4px 0 0;
}
.filter__header { .filter__header {
height: 46px;
line-height: 46px;
margin: 0 20px;
font-size: 14px;
color: #353636;
font-weight: 500;
}
.filter__body {
width: calc(100% - 30px);
margin: 0 10px 0 20px;
max-height: 265px;
overflow-y: scroll;
overflow-x: hidden;
.filter__body-item {
height: 26px;
line-height: 26px;
display: flex; display: flex;
flex: 0 0 32px;
align-items: center; align-items: center;
justify-content: space-between; padding-left: 10px;
color: #666;
//background-color: #F3F7FA;
cursor: pointer; cursor: pointer;
.filter__body-item-left { span {
display: flex; font-size: 14px;
align-items: center; padding-left: 6px;
}
i {
font-size: 12px;
transition: all linear .1s;
transform: rotate(0) translate(0, 2px);
}
i.arrow-rotate {
transform: rotate(90deg) translate(2px, 3px);
}
.new-detection-filter-header-title {
font-size: 14px; font-size: 14px;
color: #353636; color: #353636;
font-weight: 400; font-weight: 600;
}
.new-detection-filter-icon {
margin-left: 8px;
margin-bottom: 2px;
font-weight: bold !important;
}
}
.filter__body-item-left-index { .filter__body {
width: 16px; padding: 5px 0 0 15px;
height: 16px;
text-align: center; .el-checkbox-group {
background: #EFF2F5; display: flex;
border-radius: 2px; flex-direction: column;
margin-right: 6px;
font-family: NotoSansHans-Black; .el-checkbox {
font-size: 9px;
color: #96A2B0;
font-weight: 900;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; padding: 5px 0;
} margin-right: 5px;
.el-checkbox__label {
width: 100%;
}
.filter__body-item-left-label { .filter__checkbox-label {
max-width: 180px; display: flex;
font-family: NotoSansSChineseRegular; justify-content: space-between;
font-size: 14px; align-items: center;
color: #353636;
font-weight: 400;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
.filter__body-item-right { .severity-color-block {
flex-shrink: 0; width: 4px;
font-family: NotoSansSChineseRegular; height: 15px;
font-size: 12px; border-radius: 2px;
color: #717171; }
font-weight: 400; }
margin-right: 10px;
&:last-of-type {
padding-bottom: 0;
}
}
} }
} }
} }
.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;
}
} }
.filter-country-flag {
width: 18px;
height: 12px;
margin-right: 6px;
border: 1px solid #E8E8E8;
}
.filter-show-more, .filter-no-show-more {
cursor: pointer;
height: 26px;
line-height: 26px;
margin-left: 20px;
color: #046ECA;
user-select: none; // 禁止文本选中
font-size: 12px;
}
.filter-no-show-more {
cursor: not-allowed;
color: rgba(16, 16, 16, 0.3);
}
.filter-hr {
width: calc(100% - 40px);
margin-left: 20px;
margin-top: 6px;
height: 1px;
background: #EFF2F5;
//background: #000;
}
.new-detection-filter-title { .new-detection-filter-title {
height: 32px; height: 32px;
line-height: 32px; line-height: 32px;

View File

@@ -149,7 +149,7 @@
flex-direction: row; flex-direction: row;
flex-wrap: wrap; flex-wrap: wrap;
.basic-info__item, .basic-info__item1 { .basic-info__item {
padding-right: 30px; padding-right: 30px;
display: flex; display: flex;
align-items: center; align-items: center;
@@ -172,11 +172,6 @@
color: #666; color: #666;
} }
} }
.basic-info__item1 {
span: {
color: #666;
}
}
} }
.show-detail { .show-detail {

View File

@@ -203,7 +203,6 @@
color: #046ECA; color: #046ECA;
margin-bottom: 10px; margin-bottom: 10px;
font-weight: 500; font-weight: 500;
height: 36px;
} }
.timeline__start-time { .timeline__start-time {
font-size: 12px; font-size: 12px;

View File

@@ -26,7 +26,7 @@
justify-content: flex-start; justify-content: flex-start;
} }
.explorer-top-tools, .explorer-detection-top-tools, .explorer-entity-top-tools { .explorer-top-tools, .explorer-detection-top-tools {
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
align-items: center; align-items: center;
@@ -46,10 +46,7 @@
} }
} }
} }
.explorer-entity-top-tools { .explorer-detection-top-tools {
width: 100%;
}
.explorer-detection-top-tools, .explorer-entity-top-tools {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
} }
@@ -90,13 +87,6 @@
font-size: 14px; font-size: 14px;
color: #353636; color: #353636;
font-weight: 400; font-weight: 400;
.entity-hide-entity {
margin-left: 20px;
.el-checkbox__label {
padding-left: 6px;
}
}
} }
.explorer-container, .explorer-container-new { .explorer-container, .explorer-container-new {
display: flex; display: flex;

View File

@@ -2,7 +2,7 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
width: 320px; width: 320px;
margin-right: 12px; margin-right: 20px;
overflow: auto; overflow: auto;
z-index: 1; z-index: 1;
border: 1px solid rgba(226, 229, 236, 1) !important; border: 1px solid rgba(226, 229, 236, 1) !important;

View File

@@ -351,7 +351,6 @@
} }
.score-dot { .score-dot {
display: inline-block; display: inline-block;
margin-bottom: 2px;
width: 6px; width: 6px;
height: 6px; height: 6px;
border-radius: 50%; border-radius: 50%;

View File

@@ -79,20 +79,9 @@
.cn-entity__header-title { .cn-entity__header-title {
margin-right: 10px; margin-right: 10px;
} }
.entity-related-entity { .cn-entity__header-tag {
font-size: 12px;
color: #717171;
cursor: pointer;
margin-right: 6px;
}
}
.entity-row-tag { }
display: flex;
margin-left: 6px;
margin-top: 1px;
flex-wrap: wrap;
margin-bottom: -10px;
} }
.cn-entity__body { .cn-entity__body {
@@ -109,7 +98,7 @@
flex-direction: row; flex-direction: row;
flex-wrap: wrap; flex-wrap: wrap;
.basic-info__item, .basic-info__item1 { .basic-info__item {
padding-right: 30px; padding-right: 30px;
.item__box { .item__box {
@@ -172,17 +161,6 @@
color: #666; color: #666;
} }
} }
.basic-info__item1 {
span: {
color: #666;
}
span:first-of-type {
color: #666;
}
.row-item-label {
color: #999 !important;
}
}
.row-item-label { .row-item-label {
font-family: NotoSansSChineseRegular; font-family: NotoSansSChineseRegular;
@@ -199,7 +177,6 @@
.score-dot { .score-dot {
display: inline-block; display: inline-block;
margin-bottom: 2px;
width: 6px; width: 6px;
height: 6px; height: 6px;
border-radius: 50%; border-radius: 50%;

View File

@@ -26,8 +26,7 @@
padding: 0 20px; padding: 0 20px;
&.explorer-search__input-case--question-mark-in-line { &.explorer-search__input-case--question-mark-in-line {
//flex-direction: row; flex-direction: row;
flex-direction: column;
padding: 0; padding: 0;
.explorer-search__input { .explorer-search__input {
@@ -35,8 +34,9 @@
max-width: unset; max-width: unset;
} }
.explorer-search__input--border .CodeMirror { .explorer-search__input__border {
border: 1px solid #DEDEDE; border: 1px #DEDEDE solid;
height: 43px;
} }
} }
.search-symbol-inline { .search-symbol-inline {
@@ -53,14 +53,14 @@
max-width: 1000px; max-width: 1000px;
height: 40px; height: 40px;
} }
.explorer-search__foot,.explorer-search__foot-list { .explorer-search__foot {
display: flex; display: flex;
padding-top: 9px; padding-top: 18px;
width: 100%; width: 100%;
max-width: 1000px; max-width: 1000px;
position: relative; position: relative;
justify-content: flex-start; justify-content: space-between;
//font-weight: bold; font-weight: bold;
.foot__item { .foot__item {
display: flex; display: flex;
@@ -87,15 +87,14 @@
.search__history { .search__history {
position: absolute; position: absolute;
top: 6px;
display: flex; display: flex;
padding: 10px 0 0 0; padding: 10px 0 0 0;
flex-direction: column; flex-direction: column;
width: 100%; width: 100%;
max-width: 1000px; max-width: 1000px;
z-index: 2; z-index: 2;
//top: 47px; top: 47px;
border: 1px solid rgba(226,229,236,1); border: 1px solid rgba(206,206,206,0.20);
border-radius: 2px; border-radius: 2px;
background-color: white; background-color: white;
@@ -138,32 +137,8 @@
color: #66b1ff; color: #66b1ff;
} }
} }
.history__items-new {
max-height: 300px;
overflow: auto;
.el-table th,.el-table td {
padding: 6px 0;
border: none !important;
}
.el-table {
font-family: NotoSansSChineseRegular;
font-size: 14px;
color: #575757;
font-weight: 400;
thead {
font-family: NotoSansHans-Medium;
font-size: 14px;
color: #353636;
font-weight: 500;
}
.cell {
padding-left: 18px;
}
}
}
.clear-all { .clear-all {
padding-left: 18px; padding-left: 30px;
font-weight: normal; font-weight: normal;
font-size: 14px; font-size: 14px;
height: 35px; height: 35px;
@@ -177,71 +152,6 @@
} }
} }
} }
.explorer-search__foot-list {
max-width: 756px;
position: absolute;
left: 196px;
top: 44px;
.search__history {
top: 6px;
max-width: 756px;
margin-left: -196px;
.history__items-new {
max-height: 300px;
overflow: auto;
.el-table th,.el-table td {
padding: 4px 0;
border: none !important;
}
.el-table {
font-size: 12px;
thead {
font-size: 12px;
}
}
.el-table--scrollable-x .el-table__body-wrapper {
overflow-x: hidden;
}
}
}
}
} }
} }
.highlight__text {
background: #FEECC2;
padding: 0 3px;
}
.highlight__block {
background: #FEECC2;
}
.explorer-search__foot-list .explorer-search__block {
margin-left: -196px;
top: -44px;
}
.explorer-search__foot .explorer-search__block {
margin-left: 0;
top: -40px;
}
.explorer-search__block {
position: absolute;
padding-left: 15px;
height: 39px;
display: flex;
align-items: center;
cursor: pointer;
z-index: 1;
i {
font-size: 20px;
color: #999;
}
.search-dividing-line {
width: 1px;
height: 26px;
background: #DEDEDE;
margin-left: 15px;
margin-top: 2px;
}
}

View File

@@ -1798,12 +1798,6 @@
margin-right:5px; margin-right:5px;
} }
} }
.top-tool-btn--update:disabled {
cursor: not-allowed;
opacity: 0.66;
i {
}
}
.top-tool-btn--update:hover { .top-tool-btn--update:hover {
background-color: #57B8D9 !important; background-color: #57B8D9 !important;
border-color: #2E88A6 !important; border-color: #2E88A6 !important;
@@ -1852,12 +1846,6 @@
margin-right:5px; margin-right:5px;
} }
} }
.top-tool-btn--update:disabled {
cursor: not-allowed;
opacity: 0.66;
i {
}
}
.top-tool-btn--update:hover { .top-tool-btn--update:hover {
background-color: #57B8D9 !important; background-color: #57B8D9 !important;
border-color: #2E88A6 !important; border-color: #2E88A6 !important;

View File

@@ -1,8 +1,8 @@
@font-face { @font-face {
font-family: "cn-icon"; /* Project id 2614877 */ font-family: "cn-icon"; /* Project id 2614877 */
src: url('iconfont.woff2?t=1699411209748') format('woff2'), src: url('iconfont.woff2?t=1698229141457') format('woff2'),
url('iconfont.woff?t=1699411209748') format('woff'), url('iconfont.woff?t=1698229141457') format('woff'),
url('iconfont.ttf?t=1699411209748') format('truetype'); url('iconfont.ttf?t=1698229141457') format('truetype');
} }
.cn-icon { .cn-icon {
@@ -13,10 +13,6 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.cn-icon-related:before {
content: "\e640";
}
.cn-icon-indicator-match:before { .cn-icon-indicator-match:before {
content: "\e80c"; content: "\e80c";
} }

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -17,7 +17,7 @@
size="mini" size="mini"
v-model="meta.column.label" v-model="meta.column.label"
ref="columnSelect" ref="columnSelect"
:placeholder="meta.column.label || ' '" :placeholder="meta.column.label || ''"
@blur="columnBlur(meta, index)" @blur="columnBlur(meta, index)"
@change="(value) => selectColumn(value, meta)" @change="(value) => selectColumn(value, meta)"
> >
@@ -90,8 +90,8 @@
</template> </template>
</div> </div>
<div class="tag-search__add" @click="addCondition">{{$t('entities.advancedSearch.add')}}</div> <div class="tag-search__add" @click="addCondition">{{$t('entities.advancedSearch.add')}}</div>
<div class="search__suffixes search__suffixes--tag-mode search__suffixes--tag-mode__block" :class="showList ? '' : 'entity-explorer-home'"> <div class="search__suffixes search__suffixes--tag-mode">
<span class="search__suffix"> <div class="search__suffix" style="margin-right: 12px">
<el-popover <el-popover
popper-class="my-popper-class" popper-class="my-popper-class"
placement="top" placement="top"
@@ -102,13 +102,13 @@
<i class="cn-icon cn-icon-search-normal" @click="changeMode"></i> <i class="cn-icon cn-icon-search-normal" @click="changeMode"></i>
</template> </template>
</el-popover> </el-popover>
</span> </div>
<span v-show="metaList.length>0" class="search__suffix search__suffix-close" @click="cleanMetaList"> <div v-show="metaList.length>0" class="search__suffix-close" @click="cleanMetaList">
<i class="el-icon-error"></i> <i class="el-icon-error"></i>
</span> </div>
<span class="search__suffix" @click="search"> <div class="search__suffix" :class="showList ? 'new-search__suffix' : 'entity-explorer-search'" @click="search">
<i class="el-icon-search"></i> <i class="el-icon-search"></i>
</span> </div>
</div> </div>
</div> </div>
</template> </template>
@@ -202,7 +202,6 @@ export default {
if (this.isCustomized(value)) { if (this.isCustomized(value)) {
meta.column.type = columnType.fullText meta.column.type = columnType.fullText
meta.column.label = value meta.column.label = value
meta.column.isFullText = true
meta.resetOperator() meta.resetOperator()
meta.resetValue() meta.resetValue()
} else { } else {
@@ -249,7 +248,6 @@ export default {
if (meta.column && meta.column.type === 'fullText') { if (meta.column && meta.column.type === 'fullText') {
meta.operator.value = '=' meta.operator.value = '='
meta.column.show = false meta.column.show = false
meta.column.isFullText = true
meta.operator.show = false meta.operator.show = false
const label = JSON.parse(JSON.stringify(meta.column.label)) const label = JSON.parse(JSON.stringify(meta.column.label))
meta.column.label = parser.getEntityTypeByValue(meta.column.label) meta.column.label = parser.getEntityTypeByValue(meta.column.label)
@@ -463,21 +461,13 @@ export default {
if (this.metaList.length > 0) { if (this.metaList.length > 0) {
const parser = new Parser(this.columnList) const parser = new Parser(this.columnList)
const errorList = parser.validateMeta(this.metaList) const errorList = parser.validateMeta(this.metaList)
const keywordList = []
this.metaList.forEach(item => {
if (item.column && item.column.isFullText) {
keywordList.push({ type: 'fullText', value: item.value.value })
} else if (item.column && !item.column.isFullText) {
keywordList.push({ type: item.column.type, value: item.value.value })
}
})
if (_.isEmpty(errorList)) { if (_.isEmpty(errorList)) {
const strObj = parser.handleMetaListToStr(this.metaList) const strObj = parser.handleMetaListToStr(this.metaList)
const str = strObj.str ? strObj.str : strObj const str = strObj.str ? strObj.str : strObj
const str2 = strObj.str2 ? strObj.str2 : strObj const str2 = strObj.str2 ? strObj.str2 : strObj
// str为将metaList转成字符串的值str2为地址栏展示的值 // str为将metaList转成字符串的值str2为地址栏展示的值
const key = parser.handleEntityTypeByStr(str) const key = parser.handleEntityTypeByStr(str)
this.$emit('search', { ...parser.parseStr(key), str: str2, keywordList: keywordList }) this.$emit('search', { ...parser.parseStr(key), str: str2 })
} else { } else {
this.$message.error(handleErrorTip(errorList[0])) this.$message.error(handleErrorTip(errorList[0]))
} }
@@ -565,17 +555,14 @@ export default {
const column = this.columnList.find(c => { const column = this.columnList.find(c => {
return c.label === param.column return c.label === param.column
}) })
const obj = this.metaList.find(d => d.column && d.column.label === param.column && d.value && (d.value.value === `'${param.value[0]}'` || d.value.value === param.value[0])) const metaIndex = this.metaList.findIndex(m => m.column && m.column.label === param.column && m.operator.value === param.operator && m.value.value === this.handleValue(param.value, column, param.operator))
if (obj) { // 不是在首位则删除时顺带删除前一个indexand或or否则顺带删除后一个index
const metaIndex = this.metaList.findIndex(m => m.column && m.column.label === param.column && m.operator.value === param.operator && m.value.value === this.handleValue(param.value, column, param.operator)) if (metaIndex > 0) {
// 不是在首位则删除时顺带删除前一个indexand或or否则顺带删除后一个index this.metaList.splice(metaIndex - 1, 2)
if (metaIndex > 0) { } else if (this.metaList.length === 1) {
this.metaList.splice(metaIndex - 1, 2) this.metaList.splice(metaIndex, 1)
} else if (this.metaList.length === 1) { } else {
this.metaList.splice(metaIndex, 1) this.metaList.splice(metaIndex, 2)
} else {
this.metaList.splice(metaIndex, 2)
}
} }
}) })
}, },
@@ -635,9 +622,6 @@ export default {
let { q } = this.$route.query let { q } = this.$route.query
if (q && !this.convertMetaList) { if (q && !this.convertMetaList) {
const parser = new Parser(this.columnList) const parser = new Parser(this.columnList)
if (q.indexOf('+') > -1) {
q = q.replace('+', '')
}
if (q.indexOf('%') === 0 || q.indexOf('%20') > -1 || q.indexOf('%25') > -1) { if (q.indexOf('%') === 0 || q.indexOf('%20') > -1 || q.indexOf('%25') > -1) {
q = decodeURI(q) q = decodeURI(q)
} else { } else {
@@ -666,7 +650,6 @@ export default {
if (item.column && item.column.type === 'fullText') { if (item.column && item.column.type === 'fullText') {
item.operator.value = '=' item.operator.value = '='
item.column.show = false item.column.show = false
item.column.isFullText = true
item.operator.show = false item.operator.show = false
const label = JSON.parse(JSON.stringify(item.column.label)) const label = JSON.parse(JSON.stringify(item.column.label))
item.column.label = parser.getEntityTypeByValue(item.column.label) item.column.label = parser.getEntityTypeByValue(item.column.label)

View File

@@ -1,11 +1,9 @@
<template> <template>
<textarea <textarea
style="text-indent: 65px;"
cols="40"
ref="textSearch" ref="textSearch"
></textarea> ></textarea>
<div class="search__suffixes search__suffixes--text-mode" :class="showList ? '' : 'entity-explorer-home'" style="padding-left: 1px"> <div class="search__suffixes search__suffixes--text-mode">
<span class="search__suffix"> <div class="search__suffix">
<el-popover <el-popover
popper-class="my-popper-class" popper-class="my-popper-class"
placement="top" placement="top"
@@ -13,16 +11,16 @@
:content="$t('entity.switchToAdvancedSearch')" :content="$t('entity.switchToAdvancedSearch')"
> >
<template #reference> <template #reference>
<i class="cn-icon cn-icon-filter" @click="changeMode"></i> <i class="cn-icon cn-icon-filter margin-r-12" @click="changeMode"></i>
</template> </template>
</el-popover> </el-popover>
</span> </div>
<span v-show="isCloseIcon" class="search__suffix search__suffix-close" @click="cleanParams"> <div v-show="isCloseIcon" class="search__suffix-close" @click="cleanParams">
<i class="el-icon-error"></i> <i class="el-icon-error"></i>
</span> </div>
<span class="search__suffix" @click="search"> <div class="search__suffix" :class="showList ? 'new-search__suffix' : 'entity-explorer-search'" @click="search">
<i class="el-icon-search"></i> <i class="el-icon-search"></i>
</span> </div>
</div> </div>
</template> </template>
@@ -70,7 +68,7 @@ export default {
mode: { mode: {
name: 'sql' name: 'sql'
}, },
placeholder: '', placeholder: 'Enter...',
lineNumbers: false lineNumbers: false
}) })
this.codeMirror.setOption('extraKeys', { this.codeMirror.setOption('extraKeys', {
@@ -99,19 +97,10 @@ export default {
if (str) { if (str) {
const parser = new Parser(this.columnList) const parser = new Parser(this.columnList)
const keyInfo = parser.comparedEntityKey(parser.handleEntityTypeByStr(str)) const keyInfo = parser.comparedEntityKey(parser.handleEntityTypeByStr(str))
const metaList = parser.parseStr(_.cloneDeep(str)).metaList
const keywordList = []
metaList.forEach(item => {
if (item.column && item.column.type === columnType.fullText) {
keywordList.push({ type: item.column.type, value: item.column.label })
} else if (item.column && item.column.type === columnType.string) {
keywordList.push({ type: item.column.type, value: item.value.value })
}
})
if (keyInfo.isKey) { if (keyInfo.isKey) {
const errorList = parser.validateStr(keyInfo.key) const errorList = parser.validateStr(keyInfo.key)
if (_.isEmpty(errorList)) { if (_.isEmpty(errorList)) {
this.$emit('search', { ...parser.parseStr(keyInfo.key), str: str, keywordList: keywordList }) this.$emit('search', { ...parser.parseStr(keyInfo.key), str: str })
} else { } else {
this.$message.error(handleErrorTip(errorList[0])) this.$message.error(handleErrorTip(errorList[0]))
} }
@@ -234,9 +223,6 @@ export default {
toRaw(this.codeMirror).setValue(this.str) toRaw(this.codeMirror).setValue(this.str)
} }
if (q) { if (q) {
if (q.indexOf('+') > -1) {
q = q.replace('+', '')
}
if (q.indexOf('%') === 0 || q.indexOf('%20') > -1 || q.indexOf('%25') > -1) { if (q.indexOf('%') === 0 || q.indexOf('%20') > -1 || q.indexOf('%25') > -1) {
q = decodeURI(q) q = decodeURI(q)
} else { } else {

View File

@@ -1414,8 +1414,8 @@ export default class Parser {
} else if (i.toLowerCase() === 'tag') { } else if (i.toLowerCase() === 'tag') {
lastObj[i] = `has(${i},${commonObj[i]})` lastObj[i] = `has(${i},${commonObj[i]})`
} else { } else {
// 单独存在的,直接保留 todo 后续观察当初添加单引号动机和问题 // 单独存在的,直接保留
lastObj[i] = `${i} = ${commonObj[i]}` lastObj[i] = `${i} = '${commonObj[i]}'`
} }
} }

View File

@@ -1,39 +1,35 @@
<template> <template>
<div class="pagination" > <div class="pagination" >
<el-config-provider :locale="locale"> <el-pagination
<el-pagination ref="page"
ref="page" @size-change="size"
@size-change="size" @prev-click="prev"
@prev-click="prev" @next-click="next"
@next-click="next" @current-change="current"
@current-change="current" :current-page="pageObj.pageNo"
:current-page="pageObj.pageNo" :page-sizes="pageSizes?pageSizes:[20, 50, 100]"
:page-sizes="pageSizes?pageSizes:[20, 50, 100]" :page-size="Number(pageObj.pageSize)"
:page-size="Number(pageObj.pageSize)" :layout="layout"
:layout="layout" :total="pageObj.total"
:total="pageObj.total" v-bind="bind"
v-bind="bind" >
> <el-select v-model="pageSize" :placeholder="pageSize+$t('pageSize')" size="mini"
<el-select v-model="pageSize" :placeholder="pageSize+$t('pageSize')" size="mini" :popper-append-to-body="appendToBody" class="pagination-size-select" @change="size"
:popper-append-to-body="appendToBody" class="pagination-size-select" @change="size" :popper-class="popClass" @visible-change="popperVisible">
:popper-class="popClass" @visible-change="popperVisible"> <el-option v-for="(item, index) in pageSizes" :key="index" :label="item.label" :value="item.value"></el-option>
<el-option v-for="(item, index) in pageSizes" :key="index" :label="item.label" :value="item.value"></el-option> </el-select>
</el-select>
</el-pagination> </el-pagination>
</el-config-provider>
</div> </div>
</template> </template>
<script> <script>
import { defaultPageSize, storageKey, ZH, EN } from '@/utils/constants' import { defaultPageSize, storageKey } from '@/utils/constants'
import { urlParamsHandler, overwriteUrl } from '@/utils/tools' import { urlParamsHandler, overwriteUrl } from '@/utils/tools'
import { ref } from 'vue' import { ref } from 'vue'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import { parseInt } from 'lodash' import { parseInt } from 'lodash'
import ElConfigProvider from 'element-plus'
import cn from 'element-plus/lib/locale/lang/zh-cn'
import en from 'element-plus/lib/locale/lang/en'
export default { export default {
name: 'pagination', name: 'pagination',
@@ -64,15 +60,9 @@ export default {
const { query } = useRoute() const { query } = useRoute()
const pageSize = ref(defaultPageSize) const pageSize = ref(defaultPageSize)
const currentPageNo = ref(props.storePageNoOnUrl ? (query.pageNo || (props.pageObj.pageNo || 1)) : (props.pageObj.pageNo || 1)) const currentPageNo = ref(props.storePageNoOnUrl ? (query.pageNo || (props.pageObj.pageNo || 1)) : (props.pageObj.pageNo || 1))
const language = localStorage.getItem(storageKey.language) || EN // 初始未选择默认 en 英文
let locale = en
if (language === ZH) {
locale = cn
}
return { return {
pageSize, pageSize,
currentPageNo, currentPageNo
locale
} }
}, },
data () { data () {

View File

@@ -18,30 +18,28 @@
<div v-if="dropdownFlag" class="date-range-panel"> <div v-if="dropdownFlag" class="date-range-panel">
<el-row class="date-range-panel-top" style="position: relative"> <el-row class="date-range-panel-top" style="position: relative">
<el-col :span="16" class="date-range-panel-content date-range-panel-content-left"> <el-col :span="16" class="date-range-panel-content date-range-panel-content-left">
<div class="date-range-title" style="padding-left: 0">{{$t('dateTime.absoluteTimeRange')}}</div> <div class="date-range-title" style="padding-left: 0">Absolute time range</div>
<el-config-provider :locale="locale"> <el-date-picker
<el-date-picker v-model="newDateValue"
v-model="newDateValue" ref="newDatePicker"
ref="newDatePicker" popper-class="my-date-picker"
popper-class="my-date-picker" style="position: absolute;top: -53px;left: -536px;"
style="position: absolute;top: -53px;left: -536px;" :clearable="false"
:clearable="false" :default-time="defaultTime"
:default-time="defaultTime" :unlink-panels="true"
:unlink-panels="true" type="datetimerange"
type="datetimerange" @change="timeArrChange"
@change="timeArrChange" />
/> <div class="content-title">From</div>
</el-config-provider>
<div class="content-title">{{$t('dateTime.from')}}</div>
<div @click="myDatePickerShow" tabindex="1" class="content-input"> <div @click="myDatePickerShow" tabindex="1" class="content-input">
{{ dateFormatByAppearance(getMillisecond(myStartTime)) }} {{ dateFormatByAppearance(getMillisecond(myStartTime)) }}
</div> </div>
<div class="content-title">{{$t('dateTime.to')}}</div> <div class="content-title">To</div>
<div @click="myDatePickerShow" tabindex="2" class="content-input"> <div @click="myDatePickerShow" tabindex="2" class="content-input">
{{ dateFormatByAppearance(getMillisecond(myEndTime)) }} {{ dateFormatByAppearance(getMillisecond(myEndTime)) }}
</div> </div>
<div class="date-range-title" style="padding-left: 0">{{$t('dateTime.recentlyUsedRanges')}}</div> <div class="date-range-title" style="padding-left: 0">Recently used absolute ranges</div>
<div class="date-range-history"> <div class="date-range-history">
<div v-for="(item, index) in rangeHistoryArr" :key="index" class="date-range-history-item" <div v-for="(item, index) in rangeHistoryArr" :key="index" class="date-range-history-item"
@click="historyChange(item)"> @click="historyChange(item)">
@@ -55,7 +53,7 @@
:span="8" :span="8"
class="date-range-panel-content date-range-panel-content-right" class="date-range-panel-content date-range-panel-content-right"
style="border-left: 1px solid rgba(0,0,0,0.09);"> style="border-left: 1px solid rgba(0,0,0,0.09);">
<div class="date-range-title">{{$t('dateTime.relativeTimeRanges')}}</div> <div class="date-range-title">Relatime time ranges</div>
<ul class="date-range-item"> <ul class="date-range-item">
<li v-for="item in dateRangeArr" <li v-for="item in dateRangeArr"
@click="quickChange(item.value)" @click="quickChange(item.value)"
@@ -81,12 +79,9 @@
<script> <script>
import { ref, computed, watch, reactive } from 'vue' import { ref, computed, watch, reactive } from 'vue'
import { EN, storageKey, ZH } from '@/utils/constants' import { storageKey } from '@/utils/constants'
import { getMillisecond, millTimestampDiffFromTz, timestampToList } from '@/utils/date-util' import { getMillisecond, millTimestampDiffFromTz, timestampToList } from '@/utils/date-util'
import { useStore } from 'vuex' import { useStore } from 'vuex'
import ElConfigProvider from 'element-plus'
import cn from 'element-plus/lib/locale/lang/zh-cn'
import en from 'element-plus/lib/locale/lang/en'
export default { export default {
name: 'DateTimeRange', name: 'DateTimeRange',
@@ -110,31 +105,6 @@ export default {
} }
}, },
emits: ['change'], emits: ['change'],
data () {
return {
dateRangeArr: [
{ value: 5, name: this.$t('dateTime.last5Mins') }, // 'last 5 mins'
{ value: 15, name: this.$t('dateTime.last15Mins') },
{ value: 30, name: this.$t('dateTime.last30Mins') },
{ value: 60, name: this.$t('dateTime.last1Hour') }, // dateTime.last1Hour
{ value: 180, name: this.$t('dateTime.last3Hours') },
{ value: 360, name: this.$t('dateTime.last6Hours') },
{ value: 720, name: this.$t('dateTime.last12Hours') },
{ value: 1440, name: this.$t('dateTime.last1Day') }, // dateTime.last2Days
{ value: 2880, name: this.$t('dateTime.last2Days') }
]
}
},
computed: {
showDetail () {
let str = ''
if (this.dateRangeValue !== -1) {
const rangeItem = this.dateRangeArr.find(item => item.value === this.dateRangeValue)
str = rangeItem ? rangeItem.name : this.dateRangeArr[0].name
}
return str
}
},
setup (props, ctx) { setup (props, ctx) {
// data // data
const store = useStore() const store = useStore()
@@ -154,12 +124,24 @@ export default {
const rangeHistory = ref(localStorage.getItem(storageKey.dataRangeHistory) ? JSON.parse(localStorage.getItem(storageKey.dataRangeHistory)) : []) const rangeHistory = ref(localStorage.getItem(storageKey.dataRangeHistory) ? JSON.parse(localStorage.getItem(storageKey.dataRangeHistory)) : [])
const dateRangeValue = props.dateRange ? ref(props.dateRange) : ref(60) const dateRangeValue = props.dateRange ? ref(props.dateRange) : ref(60)
const isCustom = ref(dateRangeValue.value === -1) const isCustom = ref(dateRangeValue.value === -1)
const dateRangeArr = [
{ value: 5, name: 'last 5 mins' },
{ value: 15, name: 'last 15 mins' },
{ value: 30, name: 'last 30 mins' },
{ value: 60, name: 'last 1 hour' },
{ value: 180, name: 'last 3 hours' },
{ value: 360, name: 'last 6 hours' },
{ value: 720, name: 'last 12 hours' },
{ value: 1440, name: 'last 1 day' },
{ value: 2880, name: 'last 2 days' }
]
const dropdownFlag = ref(false) const dropdownFlag = ref(false)
// 默认日历选择时间即开始时间YYYY-MM-DD 00:00:00,结束时间YYYY-MM-DD 59:59:59 // 默认日历选择时间即开始时间YYYY-MM-DD 00:00:00,结束时间YYYY-MM-DD 59:59:59
const defaultTime = ref([ const defaultTime = ref([
new Date(2023, 1, 1, 0, 0, 0), new Date(2023, 1, 1, 0, 0, 0),
new Date(2023, 1, 2, 23, 59, 59) new Date(2023, 1, 2, 23, 59, 59)
]) ])
// computed // computed
const utcStr = computed(() => { const utcStr = computed(() => {
let str = 'UTC ' let str = 'UTC '
@@ -177,6 +159,13 @@ export default {
str += ':00 ' str += ':00 '
return str return str
}) })
const showDetail = computed(() => {
let str = ''
if (dateRangeValue.value !== -1) {
str = dateRangeArr.find(item => item.value === dateRangeValue.value).name
}
return str
})
const rangeHistoryArr = rangeHistory const rangeHistoryArr = rangeHistory
// refs // refs
@@ -300,12 +289,6 @@ export default {
}) })
} }
} }
const language = localStorage.getItem(storageKey.language) || EN // 初始未选择默认 en 英文
let locale = en
if (language === ZH) {
locale = cn
}
return { return {
myStartTime, myStartTime,
myEndTime, myEndTime,
@@ -314,11 +297,13 @@ export default {
utcStr, utcStr,
rangeEchartsData, rangeEchartsData,
address, address,
dateRangeArr,
defaultTime, defaultTime,
dateRangeValue, dateRangeValue,
isCustom, isCustom,
newDateValue, newDateValue,
newDatePicker, newDatePicker,
showDetail,
rangeHistory, rangeHistory,
rangeHistoryArr, rangeHistoryArr,
getMillisecond, getMillisecond,
@@ -328,8 +313,7 @@ export default {
timeArrChange, timeArrChange,
returnValue, returnValue,
quickChange, quickChange,
historyChange, historyChange
locale
} }
} }
} }

View File

@@ -58,7 +58,7 @@
<script> <script>
import axios from 'axios' import axios from 'axios'
import { storageKey, EN } from '@/utils/constants' import { storageKey } from '@/utils/constants'
export default { export default {
name: 'TopToolMoreOptions', name: 'TopToolMoreOptions',
@@ -108,7 +108,7 @@ export default {
if (this.paramsType) { if (this.paramsType) {
form.append('type', this.paramsType) form.append('type', this.paramsType)
} }
form.append('language', localStorage.getItem(storageKey.language) ? localStorage.getItem(storageKey.language) : EN) form.append('language', localStorage.getItem(storageKey.language) ? localStorage.getItem(storageKey.language) : 'en')
axios.post(this.importUrl, form, { 'Content-Type': 'multipart/form-data' }).then(response => { axios.post(this.importUrl, form, { 'Content-Type': 'multipart/form-data' }).then(response => {
if (response.status === 200 && response.data.msg === 'success') { if (response.status === 200 && response.data.msg === 'success') {
this.$message({ duration: 2000, type: 'success', message: this.$t('tip.importSuccess') }) this.$message({ duration: 2000, type: 'success', message: this.$t('tip.importSuccess') })
@@ -128,7 +128,7 @@ export default {
this.importFile = null this.importFile = null
}, },
downloadTemplate () { downloadTemplate () {
const language = localStorage.getItem(storageKey.language) || EN // 初始未选择默认 en 英文 const language = localStorage.getItem(storageKey.language) || 'en' // 初始未选择默认 en 英文
const fileName = this.exportFileName + '-' + this.$t('overall.template') + '-' + this.getTimeString() + '.json' const fileName = this.exportFileName + '-' + this.$t('overall.template') + '-' + this.getTimeString() + '.json'
let url = null let url = null
@@ -159,7 +159,7 @@ export default {
}) })
} }
params.pageSize = -1 params.pageSize = -1
params.language = localStorage.getItem(storageKey.language) || EN params.language = localStorage.getItem(storageKey.language) || 'en'
this.export(this.exportUrl, params, this.exportFileName + '-' + this.getTimeString() + '.json') this.export(this.exportUrl, params, this.exportFileName + '-' + this.getTimeString() + '.json')
this.closeDialog() this.closeDialog()

View File

@@ -13,12 +13,12 @@
<template #dropdown> <template #dropdown>
<el-dropdown-menu> <el-dropdown-menu>
<el-dropdown-item> <el-dropdown-item>
<div id="header-to-english" :style="language === EN?'color:#0091ff':''" @click="changeLocal(EN)"> <div id="header-to-english" :style="language === 'en'?'color:#0091ff':''" @click="changeLocal('en')">
English English
</div> </div>
</el-dropdown-item> </el-dropdown-item>
<el-dropdown-item> <el-dropdown-item>
<div id="header-to-chinese" :style="language === ZH?'color:#0091ff':''" @click="changeLocal(ZH)"> <div id="header-to-chinese" :style="language === 'cn'?'color:#0091ff':''" @click="changeLocal('cn')">
中文 中文
</div> </div>
</el-dropdown-item> </el-dropdown-item>
@@ -42,11 +42,11 @@
</div> </div>
<div class="cn-header__nav"> <div class="cn-header__nav">
<i class="cn-icon cn-icon-a-NetworkAnalytics"></i> <i class="cn-icon cn-icon-a-NetworkAnalytics"></i>
<el-breadcrumb class="header__left-breadcrumb" separator=">" v-if="route.startsWith('/panel')"> <el-breadcrumb class="header__left-breadcrumb" separator=">">
<el-breadcrumb-item class="header__left-breadcrumb-item" :id="`breadcrumb${item.value}`" :title="index===3?item.value:''" <el-breadcrumb-item class="header__left-breadcrumb-item" :id="`breadcrumb${item.value}`" :title="item.value"
v-for="(item,index) in breadcrumb" :key="item.value"> v-for="(item,index) in breadcrumb" :key="item.value">
<template v-if="index===3" > <template v-if="index===3">
<div class="header__left-breadcrumb-item-select" > <div class="header__left-breadcrumb-item-select">
<el-popover placement="bottom-start" <el-popover placement="bottom-start"
ref="breadcrumbPopover" ref="breadcrumbPopover"
:show-arrow="false" :show-arrow="false"
@@ -113,13 +113,6 @@
</template> </template>
</el-breadcrumb-item> </el-breadcrumb-item>
</el-breadcrumb> </el-breadcrumb>
<el-breadcrumb class="header__left-breadcrumb" separator=">" v-else>
<el-breadcrumb-item class="header__left-breadcrumb-item" :id="`breadcrumb${item.value}`"
v-for="(item,index) in breadcrumb" :key="item.value">
<span v-if="item.clickable" class="route-menu" @click="jumpOther(item.route,index)">{{ item.value }}</span>
<span v-else>{{ item.value }}</span>
</el-breadcrumb-item>
</el-breadcrumb>
</div> </div>
<!-- 菜单 --> <!-- 菜单 -->
@@ -203,9 +196,7 @@ import {
networkTable, networkTable,
operationType, operationType,
storageKey, storageKey,
wholeScreenRouterMapping, wholeScreenRouterMapping
ZH,
EN
} from '@/utils/constants' } from '@/utils/constants'
import { api } from '@/utils/api' import { api } from '@/utils/api'
import { ref } from 'vue' import { ref } from 'vue'
@@ -243,7 +234,7 @@ export default {
return { return {
username: localStorage.getItem(storageKey.username), username: localStorage.getItem(storageKey.username),
nickName: localStorage.getItem(storageKey.nickName), nickName: localStorage.getItem(storageKey.nickName),
language: localStorage.getItem(storageKey.language) ? localStorage.getItem(storageKey.language) : EN, language: localStorage.getItem(storageKey.language) ? localStorage.getItem(storageKey.language) : 'en',
showChangePin: false, showChangePin: false,
from: '', // entity类型 from: '', // entity类型
changePassForm: { changePassForm: {
@@ -305,9 +296,7 @@ export default {
curTabState: curTabState, curTabState: curTabState,
urlChangeParams: {}, urlChangeParams: {},
wholeScreenRouterMapping, wholeScreenRouterMapping,
logo: 'images/logo-header.svg', logo: 'images/logo-header.svg'
ZH,
EN
} }
}, },
computed: { computed: {
@@ -315,7 +304,7 @@ export default {
return this.$store.getters.menuList.find(menu => menu.code === 'networkAnalytics') return this.$store.getters.menuList.find(menu => menu.code === 'networkAnalytics')
}, },
otherMenu () { otherMenu () {
return this.$store.getters.menuList.filter(menu => ['networkAnalytics', 'I18N', 'entityDetail', 'entityGraph', 'detectionPolicy'].indexOf(menu.code) === -1) return this.$store.getters.menuList.filter(menu => ['networkAnalytics', 'chart', 'I18N', 'entityDetail', 'temp', 'entityGraph', 'detectionPolicy'].indexOf(menu.code) === -1)
/* function excludeButton (menu) { /* function excludeButton (menu) {
for (let i = 0; i < menu.length; i++) { for (let i = 0; i < menu.length; i++) {
@@ -333,17 +322,15 @@ export default {
breadcrumb () { breadcrumb () {
const breadcrumb = [] const breadcrumb = []
this.generateBreadcrumb(breadcrumb, this.$store.getters.menuList) this.generateBreadcrumb(breadcrumb, this.$store.getters.menuList)
if (breadcrumb) { // 写死一级和二级菜单是否可以点击跳转
// panel菜单是否可以点击跳转一级菜单不可点击二级菜单可以点击 if (breadcrumb[0]) {
if (breadcrumb[0] && breadcrumb[1] && breadcrumb[1].route && if (['knowledgeBase'].indexOf(breadcrumb[0].code) > -1) {
breadcrumb[1].route.indexOf('/panel/') === 0) { breadcrumb[0].clickable = true
breadcrumb[1].clickable = true }
} else { // 除panel外的菜单是否可以点击跳转:除了新增、编辑,其它均可点击 if (breadcrumb[1]) {
breadcrumb.forEach(item => { if (breadcrumb[1].route && breadcrumb[1].route.indexOf('/panel/') === 0) {
if (item.value !== 'Create' && item.value !== 'Edit') { breadcrumb[1].clickable = true
item.clickable = true }
}
})
} }
} }
@@ -379,7 +366,7 @@ export default {
}, },
async breadcrumb (n) { async breadcrumb (n) {
this.curTabProp = this.$route.query.dimensionType ? this.$route.query.dimensionType : null this.curTabProp = this.$route.query.dimensionType ? this.$route.query.dimensionType : null
if (this.$route.path.replace('/panel/', '') === fromRoute.dnsServiceInsights) { if (this.$route.params.typeName === fromRoute.dnsServiceInsights) {
if (this.dnsQtypeMapData.size === 0) { if (this.dnsQtypeMapData.size === 0) {
this.dnsQtypeMapData = await getDnsMapData('dnsQtype') this.dnsQtypeMapData = await getDnsMapData('dnsQtype')
} }
@@ -397,7 +384,7 @@ export default {
async mounted () { async mounted () {
this.from = Object.keys(this.entityType)[0] this.from = Object.keys(this.entityType)[0]
// 是否需要dns的qtype和rcode的数据字典 // 是否需要dns的qtype和rcode的数据字典
if (this.$route.path.replace('/panel/', '') === fromRoute.dnsServiceInsights) { if (this.$route.params.typeName === fromRoute.dnsServiceInsights) {
if (this.dnsQtypeMapData.size === 0) { if (this.dnsQtypeMapData.size === 0) {
this.dnsQtypeMapData = await getDnsMapData('dnsQtype') this.dnsQtypeMapData = await getDnsMapData('dnsQtype')
} }
@@ -418,10 +405,10 @@ export default {
const endTimeParam = query.endTime const endTimeParam = query.endTime
// 若url携带了使用携带的值否则使用默认值。 // 若url携带了使用携带的值否则使用默认值。
const dateRangeValue = rangeParam ? parseInt(rangeParam) : 60 const dateRangeValue = rangeParam ? parseInt(query.range) : 60
const chartTimeFilter = ref({ dateRangeValue }) const chartTimeFilter = ref({ dateRangeValue })
if (!startTimeParam || !endTimeParam) { if (!startTimeParam || !endTimeParam) {
const { startTime, endTime } = getNowTime(dateRangeValue) const { startTime, endTime } = getNowTime(60)
chartTimeFilter.value.startTime = startTime chartTimeFilter.value.startTime = startTime
chartTimeFilter.value.endTime = endTime chartTimeFilter.value.endTime = endTime
} else { } else {
@@ -436,6 +423,39 @@ export default {
}, },
methods: { methods: {
generateBreadcrumb (breadcrumb, menus) { generateBreadcrumb (breadcrumb, menus) {
if (this.route === '/entityDetail') {
const entityMenu = menus.find(m => m.route === '/entity')
const entityDetailMenu = menus.find(m => m.route === '/entityDetail')
breadcrumb.push({
code: entityMenu.code,
value: entityMenu.i18n ? this.$t(entityMenu.i18n) : entityMenu.name,
route: entityMenu.route,
type: entityMenu.type
})
breadcrumb.push({
code: entityDetailMenu.code,
value: entityDetailMenu.i18n ? this.$t(entityDetailMenu.i18n) : entityDetailMenu.name,
route: entityDetailMenu.route,
type: entityDetailMenu.type
})
return true
} else if (this.route === '/entityGraph') {
const entityMenu = menus.find(m => m.route === '/entity')
const entityGraphMenu = menus.find(m => m.route === '/entityGraph')
breadcrumb.push({
code: entityMenu.code,
value: entityMenu.i18n ? this.$t(entityMenu.i18n) : entityMenu.name,
route: entityMenu.route,
type: entityMenu.type
})
breadcrumb.push({
code: entityGraphMenu.code,
value: entityGraphMenu.i18n ? this.$t(entityGraphMenu.i18n) : entityGraphMenu.name,
route: entityGraphMenu.route,
type: entityGraphMenu.type
})
return true
}
const menu = menus.find(m => m.route === this.route) const menu = menus.find(m => m.route === this.route)
if (menu) { if (menu) {
breadcrumb.unshift({ breadcrumb.unshift({
@@ -487,7 +507,7 @@ export default {
}, },
getCurTabByLabel (label) { getCurTabByLabel (label) {
let curTab = null let curTab = null
const tableType = this.$route.path.replace('/panel/', '') || 'networkOverview' const tableType = this.$route.params ? this.$route.params.typeName : 'networkOverview'
const curTableInCode = networkTable[tableType] ? networkTable[tableType] : networkTable.networkOverview const curTableInCode = networkTable[tableType] ? networkTable[tableType] : networkTable.networkOverview
if (curTableInCode && curTableInCode.tabList) { if (curTableInCode && curTableInCode.tabList) {
curTab = curTableInCode.tabList.find(item => item.label === label) curTab = curTableInCode.tabList.find(item => item.label === label)
@@ -500,7 +520,7 @@ export default {
const currentValue = document.getElementById('breadcrumbValue') ? document.getElementById('breadcrumbValue').innerText : '' const currentValue = document.getElementById('breadcrumbValue') ? document.getElementById('breadcrumbValue').innerText : ''
const columnName = this.getUrlParam(this.curTabState.thirdMenu, '') const columnName = this.getUrlParam(this.curTabState.thirdMenu, '')
let type = 'ip' let type = 'ip'
const tableType = this.$route.path.replace('/panel/', '') || 'networkOverview' const tableType = this.$route.params ? this.$route.params.typeName : 'networkOverview'
const curTableInCode = networkTable[tableType] ? networkTable[tableType] : networkTable.networkOverview const curTableInCode = networkTable[tableType] ? networkTable[tableType] : networkTable.networkOverview
if (curTableInCode && curTableInCode.tabList) { if (curTableInCode && curTableInCode.tabList) {
const curTab = curTableInCode.tabList.find(item => item.label === columnName) const curTab = curTableInCode.tabList.find(item => item.label === columnName)
@@ -524,7 +544,7 @@ export default {
axios.get(curTableInCode.url.drilldownList, { params }).then(async response => { axios.get(curTableInCode.url.drilldownList, { params }).then(async response => {
if (response.status === 200) { if (response.status === 200) {
this.breadcrumbColumnValueListShow = response.data.data.result this.breadcrumbColumnValueListShow = response.data.data.result
if (this.$route.path.replace('/panel/', '') === fromRoute.dnsServiceInsights) { if (this.$route.params.typeName === fromRoute.dnsServiceInsights) {
if (this.dnsQtypeMapData.size === 0) { if (this.dnsQtypeMapData.size === 0) {
this.dnsQtypeMapData = await getDnsMapData('dnsQtype') this.dnsQtypeMapData = await getDnsMapData('dnsQtype')
} }
@@ -655,7 +675,7 @@ export default {
}, },
async handleCurDrilldownTableConfig (thirdMenu) { async handleCurDrilldownTableConfig (thirdMenu) {
// const userId = localStorage.getItem(storageKey.userId) // const userId = localStorage.getItem(storageKey.userId)
const tableType = this.$route.path.replace('/panel/', '') || 'networkOverview' const tableType = this.$route.params ? this.$route.params.typeName : 'networkOverview'
const metric = this.getUrlParam(this.curTabState.tableMetric, 'Bits/s') const metric = this.getUrlParam(this.curTabState.tableMetric, 'Bits/s')
const drillDownTableConfigs = await combineDrilldownTableWithUserConfig() const drillDownTableConfigs = await combineDrilldownTableWithUserConfig()
const currentTableConfig = drillDownTableConfigs.find(config => config.route === tableType) const currentTableConfig = drillDownTableConfigs.find(config => config.route === tableType)
@@ -676,26 +696,7 @@ export default {
} }
} }
}, },
// 仅处理除panel外的相关路径的导航
async jumpOther (route, index) {
route = route.replace('redirect:', '')
this.showMenu = false
if (route === this.route && index > 0) { // 当前只有一级菜单时,点击不进行刷新,重新跳转
this.refresh()
return
}
if (route) {
this.$router.push({
path: route,
query: {
t: +new Date()
}
})
}
},
// 仅处理panel相关路径的导航
async jump (route, columnName, columnValue, opeType) { async jump (route, columnName, columnValue, opeType) {
route = route.replace('redirect:', '')
if (route === '/panel/linkMonitor' && opeType === 3) { if (route === '/panel/linkMonitor' && opeType === 3) {
return true return true
} }
@@ -715,7 +716,7 @@ export default {
this.$store.commit('setNetworkOverviewTabList', []) this.$store.commit('setNetworkOverviewTabList', [])
} }
// 清空网络概况的特殊面包屑 // 清空网络概况的特殊面包屑
const tableType = this.$route.path.replace('/panel/', '') || 'networkOverview' const tableType = this.$route.params ? this.$route.params.typeName : 'networkOverview'
const metric = this.getUrlParam(this.curTabState.tableMetric, 'Bits/s') const metric = this.getUrlParam(this.curTabState.tableMetric, 'Bits/s')
const curTab = await getDefaultCurTab(tableType, metric, columnName) const curTab = await getDefaultCurTab(tableType, metric, columnName)
this.$store.getters.menuList.forEach(menu => { this.$store.getters.menuList.forEach(menu => {
@@ -727,6 +728,11 @@ export default {
child.columnName = columnName child.columnName = columnName
this.urlChangeParams[this.curTabState.thirdMenu] = columnName this.urlChangeParams[this.curTabState.thirdMenu] = columnName
this.urlChangeParams[this.curTabState.fourthMenu] = columnValue 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
this.urlChangeParams[this.curTabState.panelName] = columnValue this.urlChangeParams[this.curTabState.panelName] = columnValue
} else if (columnName) { // 点击的为列名 } else if (columnName) { // 点击的为列名
child.columnValue = '' child.columnValue = ''

View File

@@ -23,8 +23,7 @@
<button type="button" class="cn-btn cn-btn-size-small-new cn-btn-style-light-new option-btn" style="margin-left: 0px;" @click="expandAllOrNone" :class="{'btn-active':expandAllFlag}">展开/收缩</button> <button type="button" class="cn-btn cn-btn-size-small-new cn-btn-style-light-new option-btn" style="margin-left: 0px;" @click="expandAllOrNone" :class="{'btn-active':expandAllFlag}">展开/收缩</button>
<button type="button" class="cn-btn cn-btn-size-small-new cn-btn-style-light-new option-btn" @click="selectAllOrNone" :class="{'btn-active':selectAllFlag}"><span ><i class="cn-icon cn-icon-delete"></i></span></button> <button type="button" class="cn-btn cn-btn-size-small-new cn-btn-style-light-new option-btn" @click="selectAllOrNone" :class="{'btn-active':selectAllFlag}"><span ><i class="cn-icon cn-icon-delete"></i></span></button>
</div>--> </div>-->
<el-checkbox v-model="isCheckAll" :label="$t('overall.all')" @change="checkAll"></el-checkbox> <el-tree :data="menus" :default-expand-all="expandAllFlag" :props="{label:labelFormatter}" @check-change="selectChange" class="tree-border" node-key="id" ref="menuTree" show-checkbox id="role-box-input-menus">
<el-tree :data="menus" :default-expand-all="expandAllFlag" check-strictly="true" :props="{label:labelFormatter}" @check-change="selectChange" class="tree-border" node-key="id" ref="menuTree" show-checkbox id="role-box-input-menus">
<template #default="{ data }"> <template #default="{ data }">
<span> <span>
<i v-if="data.type === '1'" class="el-icon-menu"></i> <i v-if="data.type === '1'" class="el-icon-menu"></i>
@@ -91,8 +90,7 @@ export default {
menus: [], menus: [],
selectedIds: [], selectedIds: [],
selectAllFlag: false, selectAllFlag: false,
expandAllFlag: true, expandAllFlag: true
isCheckAll: false
} }
}, },
watch: { watch: {
@@ -152,59 +150,9 @@ export default {
labelFormatter: function (data, node) { labelFormatter: function (data, node) {
return data && data.i18n ? this.$t(data.i18n) : data.name return data && data.i18n ? this.$t(data.i18n) : data.name
}, },
getChildNodes (menu) {
let nodeGroup = []
if (menu.children && menu.children.length > 0) {
nodeGroup = menu.children
const _this = this
menu.children.forEach(node => {
const childNodes = _this.getChildNodes(node)
if (childNodes && childNodes.length > 0) {
nodeGroup = nodeGroup.concat(childNodes)
}
})
}
return nodeGroup
},
checkAll () {
if (this.$refs.menuTree) {
if (this.isCheckAll) {
let nodeGroup = this.menus
const _this = this
this.menus.forEach(menu => {
const childNodes = _this.getChildNodes(menu)
if (childNodes && childNodes.length > 0) {
nodeGroup = nodeGroup.concat(childNodes)
}
})
this.$refs.menuTree.setCheckedNodes(nodeGroup)
} else {
this.$refs.menuTree.setCheckedNodes([])
}
}
},
checkParentNode(node) {
if(node && this.$refs.menuTree.getNode(node)){
let parent = this.$refs.menuTree.getNode(node).parent
let parentNode = parent.data
if(parentNode && parentNode.id && parentNode.id !== 0 ){
this.$refs.menuTree.setChecked(parentNode,true,false)
this.checkParentNode(parentNode)
}
}
},
selectChange: function (data, isCheck, childIsCheck) { selectChange: function (data, isCheck, childIsCheck) {
if(isCheck) {//如果是选中节点,则同步选中所有的父辈节点(有全选和半选两种状态)
this.checkParentNode(data)
} else {//如果是取消节点,则同步取消选中所有子节点
if(data.children && data.children.length > 0) {
data.children.forEach(node => {
this.$refs.menuTree.setChecked(node, false, true)
})
}
}
if (this.$refs.menuTree) { if (this.$refs.menuTree) {
this.editRole.menuIds = this.$refs.menuTree.getCheckedKeys(false) this.editRole.menuIds = this.$refs.menuTree.getCheckedKeys(true)
} }
}, },
selectAllOrNone: function () { selectAllOrNone: function () {

View File

@@ -125,16 +125,16 @@ export default {
mixins: [rightBoxMixin], mixins: [rightBoxMixin],
data () { data () {
const validatePin = (rule, value, callback) => { // 确认密码 const validatePin = (rule, value, callback) => { // 确认密码
if (value && value.length < 5) { if (value.length < 5) {
callback(new Error(this.$t('validate.atLeastFive'))) callback(new Error(this.$t('validate.atLeastFive')))
} else { } else {
callback() callback()
} }
} }
const validateConfirmPin = (rule, value, callback) => { // 确认密码的二次校验 const validateConfirmPin = (rule, value, callback) => { // 确认密码的二次校验
if (_.isEmpty(value) && !_.isEmpty(this.editObject.pin)) {//密码有内容,确认密码没内容 if (value === '' && this.editObject.pin) {
callback(new Error(this.$t('config.user.confirmPin'))) callback(new Error(this.$t('config.user.confirmPin')))
} else if (!_.isEmpty(value) && value !== this.editObject.pin) {//密码有内容,确认密码也有内容,内容不一致 } else if (value !== this.editObject.pin) {
callback(new Error(this.$t('config.user.confirmPinErr'))) callback(new Error(this.$t('config.user.confirmPinErr')))
} else { } else {
callback() callback()
@@ -207,7 +207,7 @@ export default {
], ],
pinChange: [ pinChange: [
{ validator: validateConfirmPin, trigger: 'blur' }, { validator: validateConfirmPin, trigger: 'blur' },
{ validator: validatePin, trigger: 'blur' } { pattern: /^[a-zA-Z0-9]{5,64}$/, message: this.$t('validate.atLeastFive') }
], ],
roleIds: [ roleIds: [
{ required: true, message: this.$t('validate.required'), trigger: 'blur' } { required: true, message: this.$t('validate.required'), trigger: 'blur' }

View File

@@ -52,17 +52,13 @@
</template> </template>
<template v-else-if="item.prop === 'status'"> <template v-else-if="item.prop === 'status'">
<el-switch <el-switch
v-if="scope.row.id && hasPermission('editUser')" v-if="scope.row.id"
v-model="scope.row.status" v-model="scope.row.status"
active-value="1" active-value="1"
:disabled="(scope.row.username === loginName) || (scope.row.username==='admin' && scope.row.id===1) || scope.row.buildIn === 1" :disabled="(scope.row.username === loginName) || (scope.row.username==='admin' && scope.row.id===1) || scope.row.buildIn === 1"
inactive-value="0" inactive-value="0"
@change="()=>{statusChange(scope.row)}"> @change="()=>{statusChange(scope.row)}">
</el-switch> </el-switch>
<template v-else>
<span v-if="scope.row.status === '1'">{{$t('detection.create.enabled')}}</span>
<span v-else>{{$t('detection.create.disabled')}}</span>
</template>
</template> </template>
<span v-else>{{scope.row[item.prop] || '-'}}</span> <span v-else>{{scope.row[item.prop] || '-'}}</span>
</template> </template>

View File

@@ -11,7 +11,7 @@
<div class="block-mode-title">{{ $t('detection.policy.indicatorMatch') }}</div> <div class="block-mode-title">{{ $t('detection.policy.indicatorMatch') }}</div>
<div class="block-mode-content"> <div class="block-mode-content">
{{ $t('detection.policy.indicatorMatchIntroduce') }} {{ $t('detection.policy.indicatorMatchIntroduce') }}
<div v-if="language===ZH" style="color: rgba(0,0,0,0)">0</div> <div v-if="language==='cn'" style="color: rgba(0,0,0,0)">0</div>
</div> </div>
<div :class="settingObj.ruleType===detectionRuleType.indicator?'block-mode-btn-active':'block-mode-btn'" <div :class="settingObj.ruleType===detectionRuleType.indicator?'block-mode-btn-active':'block-mode-btn'"
@click="selectMode(detectionRuleType.indicator)">{{ $t('overall.select') }} @click="selectMode(detectionRuleType.indicator)">{{ $t('overall.select') }}
@@ -109,7 +109,7 @@
</template> </template>
<script> <script>
import { detectionRuleType, storageKey, detectionUnitList, ZH, EN } from '@/utils/constants' import { detectionRuleType, storageKey, detectionUnitList } from '@/utils/constants'
import { switchStatus } from '@/utils/tools' import { switchStatus } from '@/utils/tools'
export default { export default {
@@ -160,8 +160,7 @@ export default {
} }
] ]
}, },
language: EN, language: 'en'
ZH
} }
}, },
watch: { watch: {
@@ -184,7 +183,7 @@ export default {
methods: { methods: {
switchStatus, switchStatus,
initData () { initData () {
this.language = localStorage.getItem(storageKey.language) || EN this.language = localStorage.getItem(storageKey.language) || 'en'
this.categoryList = detectionUnitList.categoryList this.categoryList = detectionUnitList.categoryList
this.eventTypeList = detectionUnitList.eventTypeList this.eventTypeList = detectionUnitList.eventTypeList
}, },

View File

@@ -61,7 +61,7 @@
<div class="reference-tag__group"> <div class="reference-tag__group">
<span class="reference-tag" v-for="(refer, index) in scope.row[item.prop].slice(0,2)" >{{refer}}</span> <span class="reference-tag" v-for="(refer, index) in scope.row[item.prop].slice(0,2)" >{{refer}}</span>
</div> </div>
<div class="reference-more">+{{scope.row[item.prop].length - 2}} {{$t('overall.more')}}</div> <div class="reference-more">+{{scope.row[item.prop].length - 2}} more</div>
</div> </div>
</template> </template>
<div class="reference-tag__tip"> <div class="reference-tag__tip">
@@ -70,11 +70,9 @@
</el-popover> </el-popover>
</templage> </templage>
<template v-else> <template v-else>
<div class="reference-tag__show"> <template v-for="(refer, index) in scope.row[item.prop]">
<div class="reference-tag__group"> <div class="type-tag">{{refer}}</div>
<span class="reference-tag" v-for="(refer, index) in scope.row[item.prop]" >{{refer}}</span> </template>
</div>
</div>
</template> </template>
</template> </template>
<template v-else-if="item.prop === 'opTime' || item.prop === 'ctime'"> <template v-else-if="item.prop === 'opTime' || item.prop === 'ctime'">
@@ -98,7 +96,6 @@
</template> </template>
<template v-else-if="item.prop === 'status'"> <template v-else-if="item.prop === 'status'">
<el-switch v-model="scope.row.status" <el-switch v-model="scope.row.status"
v-if="hasPermission('editUserDefinedLibrary')"
active-color="#38ACD2" active-color="#38ACD2"
inactive-color="#C0CEDB" inactive-color="#C0CEDB"
:active-value="1" :active-value="1"
@@ -106,10 +103,6 @@
@change="changeStatus($event,scope.row.knowledgeId)" @change="changeStatus($event,scope.row.knowledgeId)"
> >
</el-switch> </el-switch>
<template v-else>
<span v-if="scope.row.status === 1">{{$t('detection.create.enabled')}}</span>
<span v-else>{{$t('detection.create.disabled')}}</span>
</template>
</template> </template>
<template v-else-if="item.prop === 'color'"> <template v-else-if="item.prop === 'color'">
<div class="knowledge-color"> <div class="knowledge-color">
@@ -163,7 +156,7 @@ export default {
}, { }, {
label: this.$t('knowledge.reference'), label: this.$t('knowledge.reference'),
prop: 'reference', prop: 'reference',
width: 190, width: 180,
show: true show: true
}, { }, {
label: this.$t('overall.color'), label: this.$t('overall.color'),

View File

@@ -7,7 +7,6 @@
<div class="card-content"> <div class="card-content">
<div class="card-operate"> <div class="card-operate">
<el-switch v-model="data.status" <el-switch v-model="data.status"
v-if="hasPermission('editBuiltInKnowledgeBase')"
class="card-enable" class="card-enable"
active-color="#38ACD2" active-color="#38ACD2"
inactive-color="#C0CEDB" inactive-color="#C0CEDB"
@@ -21,12 +20,12 @@
<img :src="data.iconUrl"/> <img :src="data.iconUrl"/>
</div> </div>
<div class="card-title"> <div class="card-title">
<div class="card-title-name" :title="$t(data.label)">{{$t(data.label)}}</div> <div class="card-title-name" :title="data.label">{{data.label}}</div>
</div> </div>
<div class="card-desc" :title="$t(data.desc)">{{$t(data.desc) || '—'}}</div> <div class="card-desc" :title="data.desc">{{data.desc ? data.desc : '—'}}</div>
</div> </div>
<div class="card-operate__footer"> <div class="card-operate__footer">
<button v-if="data.showUpdate && hasPermission('editBuiltInKnowledgeBase')" <button v-if="data.showUpdate"
class="top-tool-btn--update" class="top-tool-btn--update"
@click="jumpToUpdatePage(data,true)"> @click="jumpToUpdatePage(data,true)">
<i class="cn-icon-update-knowledge-base cn-icon"></i> <i class="cn-icon-update-knowledge-base cn-icon"></i>
@@ -45,12 +44,12 @@
<img :src="data.iconUrl"/> <img :src="data.iconUrl"/>
</div> </div>
<div class="card-title"> <div class="card-title">
<div class="card-title-name" :title="$t(data.label)">{{$t(data.label)}}</div> <div class="card-title-name" :title="data.label">{{data.label}}</div>
</div> </div>
<div class="card-desc" :title="data.desc ? $t(data.desc) : '—'">{{data.desc ? $t(data.desc) : '—'}}</div> <div class="card-desc" :title="data.desc ? data.desc:'—'">{{data.desc ? data.desc : '—'}}</div>
</div> </div>
<div class="card-operate__footer"> <div class="card-operate__footer">
<button v-if="data.showUpdate && hasPermission('editBuiltInKnowledgeBase')" :title="$t('overall.update')" class="top-tool-btn--update" <button v-if="data.showUpdate" :title="$t('overall.update')" class="top-tool-btn--update"
@click="jumpToUpdatePage(data,false)"> @click="jumpToUpdatePage(data,false)">
<i class="cn-icon-update-knowledge-base cn-icon"></i> <i class="cn-icon-update-knowledge-base cn-icon"></i>
<span>{{$t('overall.update')}}</span> <span>{{$t('overall.update')}}</span>
@@ -78,7 +77,7 @@
<div class="update-right"> <div class="update-right">
<div class="knowledge-enable"> <div class="knowledge-enable">
<div class="update-title"> <div class="update-title">
<div class="card-title-name" :title="$t(updateKnowledge.label)">{{$t(updateKnowledge.label)}}</div> <div class="card-title-name" :title="updateKnowledge.label">{{updateKnowledge.label}}</div>
</div> </div>
<el-switch v-model="updateKnowledge.status" <el-switch v-model="updateKnowledge.status"
active-color="#38ACD2" active-color="#38ACD2"
@@ -86,11 +85,11 @@
:active-value="1" :active-value="1"
:inactive-value="0" :inactive-value="0"
:before-change="(knowledgeId) => confirmSwitchLearning(updateKnowledge.knowledgeId)" :before-change="(knowledgeId) => confirmSwitchLearning(updateKnowledge.knowledgeId)"
v-if="updateKnowledge.source === 'cn_psiphon3_ip' && hasPermission('editBuiltInKnowledgeBase')" v-if="updateKnowledge.source === 'cn_psiphon3_ip'"
> >
</el-switch> </el-switch>
</div> </div>
<div class="knowledge-desc" :title="updateKnowledge.desc ? $t(updateKnowledge.desc) : '-'">{{updateKnowledge.desc ? $t(updateKnowledge.desc) : '-'}}</div> <div class="knowledge-desc" :title="updateKnowledge.desc">{{updateKnowledge.desc ? updateKnowledge.desc : ''}}</div>
</div> </div>
</div> </div>
<template v-if="!showAddUpdateDialog"> <template v-if="!showAddUpdateDialog">
@@ -112,7 +111,7 @@
</el-tabs> </el-tabs>
<div class="update-operate"> <div class="update-operate">
<button :title="$t('overall.update')" class="top-tool-btn--update" <button :title="$t('overall.update')" class="top-tool-btn--update"
@click="uploadRecord"><!--:disabled="hasUpdatingRecord"--> @click="uploadRecord">
<i class="cn-icon-update-knowledge-base cn-icon"></i> <i class="cn-icon-update-knowledge-base cn-icon"></i>
<span>{{$t('overall.update')}}</span> <span>{{$t('overall.update')}}</span>
</button> </button>
@@ -124,7 +123,7 @@
</div> </div>
<div class="update-operate"> <div class="update-operate">
<button :title="$t('overall.update')" class="top-tool-btn--update" <button :title="$t('overall.update')" class="top-tool-btn--update"
@click="uploadRecord"><!-- :disabled="hasUpdatingRecord" --> @click="uploadRecord">
<i class="cn-icon-update-knowledge-base cn-icon"></i> <i class="cn-icon-update-knowledge-base cn-icon"></i>
<span>{{$t('overall.update')}}</span> <span>{{$t('overall.update')}}</span>
</button> </button>
@@ -151,7 +150,7 @@
<span>{{scope.row.opTime ? dateFormatByAppearance(scope.row.opTime) : '-'}}</span> <span>{{scope.row.opTime ? dateFormatByAppearance(scope.row.opTime) : '-'}}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="user" :label="$t('knowledgeBase.operator')" width="150" v-if="updateKnowledge.source !== 'cn_psiphon3_ip' || activeTab === 'updateRecord'"> <el-table-column prop="user" :label="$t('knowledgeBase.operator')" width="150" v-if="activeTab === 'updateRecord'">
<template #default="scope" :column="item"> <template #default="scope" :column="item">
<span>{{$_.get(scope.row, 'user.name', '-')}}</span> <span>{{$_.get(scope.row, 'user.name', '-')}}</span>
</template> </template>
@@ -257,7 +256,7 @@
</el-form> </el-form>
</div> </div>
<div class="dialog-footer"> <div class="dialog-footer">
<el-button @click="cancle">{{ $t('overall.cancel') }}</el-button> <el-button @click="showAddUpdateDialog = false">{{ $t('overall.cancel') }}</el-button>
<el-button type="primary" @click="submitConfirm">{{ $t('tip.confirm') }}</el-button> <el-button type="primary" @click="submitConfirm">{{ $t('tip.confirm') }}</el-button>
</div> </div>
</template> </template>
@@ -284,8 +283,8 @@
<div class="dialog-message">{{ confirmSwitchLearningTip }}</div> <div class="dialog-message">{{ confirmSwitchLearningTip }}</div>
<template #footer> <template #footer>
<span class="dialog-footer"> <span class="dialog-footer">
<el-button @click="cancleSwitch">{{ $t('overall.cancel') }}</el-button> <el-button @click="showConfirmSwitch = false">{{ $t('overall.cancel') }}</el-button>
<el-button type="primary" @click="switchLearning">{{$t('tip.confirm')}}</el-button> <el-button type="primary" @click="switchLearning">OK</el-button>
</span> </span>
</template> </template>
</el-dialog> </el-dialog>
@@ -296,7 +295,7 @@
import table from '@/mixins/table' import table from '@/mixins/table'
import Loading from '@/components/common/Loading' import Loading from '@/components/common/Loading'
import { getSecond, getMillisecond, xAxisTimeFormatter, xAxisTimeRich } from '@/utils/date-util' import { getSecond, getMillisecond, xAxisTimeFormatter, xAxisTimeRich } from '@/utils/date-util'
import { knowledgeCategoryValue, unitTypes, storageKey, builtInKnowledgeBaseBasicInfo, knowledgeCardUpdateRecordType } from '@/utils/constants' import { knowledgeCategoryValue, unitTypes, storageKey, builtInKnowledgeBaseBasicInfo } from '@/utils/constants'
import { ref, shallowRef } from 'vue' import { ref, shallowRef } from 'vue'
import { api } from '@/utils/api' import { api } from '@/utils/api'
import { detectionTooltipFormatter } from '@/views/charts/charts/tools' import { detectionTooltipFormatter } from '@/views/charts/charts/tools'
@@ -340,7 +339,6 @@ export default {
psiphon3Loading: false, psiphon3Loading: false,
updateLogLoading: false, updateLogLoading: false,
showConfirmSwitch: false, showConfirmSwitch: false,
// timer: null,
switchKnowledgeId: '', switchKnowledgeId: '',
activeTab: 'updateRecord', activeTab: 'updateRecord',
isNoDataForPsiphon3: false, isNoDataForPsiphon3: false,
@@ -350,7 +348,6 @@ export default {
tabType: 'total', tabType: 'total',
mousemoveCursor: '', mousemoveCursor: '',
selectTime: 1440, selectTime: 1440,
// hasUpdatingRecord: false,
tabs: [ tabs: [
{ {
name: 'knowledgeBase.total', name: 'knowledgeBase.total',
@@ -383,6 +380,12 @@ export default {
setup () { setup () {
// 没上传过文件的提示 // 没上传过文件的提示
const uploadErrorTip = ref('') const uploadErrorTip = ref('')
const nowMill = window.$dayJs.tz().valueOf()
const timeFilter = ref({
startTime: nowMill - 1000 * 60 * 60 * 24,
endTime: nowMill,
dateRangeValue: 1440
})
return { return {
baseUrl: BASE_CONFIG.baseUrl, baseUrl: BASE_CONFIG.baseUrl,
apiVersion: BASE_CONFIG.apiVersion, apiVersion: BASE_CONFIG.apiVersion,
@@ -394,7 +397,8 @@ export default {
fileList: ref([]), fileList: ref([]),
uploadFileSizeLimit: 1024 * 1024 * 1024, uploadFileSizeLimit: 1024 * 1024 * 1024,
myChart: shallowRef(null), myChart: shallowRef(null),
chartOption: shallowRef(null) chartOption: shallowRef(null),
timeFilter
} }
}, },
methods: { methods: {
@@ -423,6 +427,7 @@ export default {
}, },
xAxis: { xAxis: {
type: 'time', type: 'time',
boundaryGap: ['1%', '3%'],
axisLine: { axisLine: {
show: false show: false
}, },
@@ -466,10 +471,9 @@ export default {
}, },
init (val, show, active, n) { init (val, show, active, n) {
this.psiphon3Loading = true this.psiphon3Loading = true
const endTime = window.$dayJs.tz().valueOf()
const params = { const params = {
startTime: getSecond(endTime - this.selectTime * 60 * 1000), startTime: getSecond(this.timeFilter.startTime),
endTime: getSecond(endTime) endTime: getSecond(this.timeFilter.endTime)
} }
const url = api.knowledgeBaseTimedistribution.replace('{{knowledgeId}}', this.updateKnowledge.knowledgeId).replace('{{type}}', this.tabType) const url = api.knowledgeBaseTimedistribution.replace('{{knowledgeId}}', this.updateKnowledge.knowledgeId).replace('{{type}}', this.tabType)
axios.get(url, { params: params }).then(response => { axios.get(url, { params: params }).then(response => {
@@ -482,9 +486,7 @@ export default {
const chartsData = res.data.result.map(item => { const chartsData = res.data.result.map(item => {
return [getMillisecond(item.statTime), item.count] return [getMillisecond(item.statTime), item.count]
}) })
if (this.activeTab === knowledgeCardUpdateRecordType.intelligenceLearning) { this.echartsInit(chartsData)
this.echartsInit(chartsData)
}
} }
} else { } else {
this.httpError(res) this.httpError(res)
@@ -532,14 +534,14 @@ export default {
}) })
}, },
timeChange () { timeChange () {
this.timeFilter.endTime = window.$dayJs.tz().valueOf()
this.timeFilter.startTime = this.timeFilter.endTime - this.selectTime * 60 * 1000
if (this.updateKnowledge.source === 'cn_psiphon3_ip') { if (this.updateKnowledge.source === 'cn_psiphon3_ip') {
this.init() this.init()
} }
if (this.activeTab === knowledgeCardUpdateRecordType.intelligenceLearning) { this.$nextTick(() => {
this.$nextTick(() => { this.handleActiveBar()
this.handleActiveBar() })
})
}
}, },
activeChange (item) { // isClick:代表是通过点击操作来的 activeChange (item) { // isClick:代表是通过点击操作来的
if (item) { if (item) {
@@ -553,11 +555,9 @@ export default {
mouseenterTab (item) { mouseenterTab (item) {
if (this.isNoDataForPsiphon3) return if (this.isNoDataForPsiphon3) return
this.mousemoveCursor = item.class this.mousemoveCursor = item.class
if (this.activeTab === knowledgeCardUpdateRecordType.intelligenceLearning) { this.$nextTick(() => {
this.$nextTick(() => { this.handleActiveBar()
this.handleActiveBar() })
})
}
}, },
mouseleaveTab () { mouseleaveTab () {
this.mousemoveCursor = '' this.mousemoveCursor = ''
@@ -587,9 +587,17 @@ export default {
uploadSuccess (response) { uploadSuccess (response) {
this.uploadLoading = false this.uploadLoading = false
this.uploaded = true this.uploaded = true
/* this.uploaded = response.code === 200
if (response.code === 200) { */
this.$message.success(this.$t('tip.success')) this.$message.success(this.$t('tip.success'))
this.showAddUpdateDialog = false this.showAddUpdateDialog = false
this.getCurTabData() this.getCurTabData()
if (this.updateKnowledge.source === 'cn_psiphon3_ip') {
this.init()
}
/* } else {
this.$message.error(this.$t('tip.uploadFailed', { msg: response.message }))
} */
}, },
beforeUpload (file) { beforeUpload (file) {
this.uploadLoading = true this.uploadLoading = true
@@ -601,9 +609,6 @@ export default {
submit () { submit () {
this.$refs.knowledgeUpload.submit() this.$refs.knowledgeUpload.submit()
}, },
cancle () {
this.showAddUpdateDialog = false
},
clickCard (data, event) { clickCard (data, event) {
if (data.isSelected) { // 原来为选中,当前点击后未选中 if (data.isSelected) { // 原来为选中,当前点击后未选中
const index = this.checkList.indexOf(data) const index = this.checkList.indexOf(data)
@@ -654,11 +659,9 @@ export default {
await this.init() await this.init()
} }
this.showUpdate() this.showUpdate()
if (this.activeTab === knowledgeCardUpdateRecordType.intelligenceLearning) { this.$nextTick(() => {
this.$nextTick(() => { this.handleActiveBar()
this.handleActiveBar() })
})
}
}, },
uploadRecord () { uploadRecord () {
this.showAddUpdateDialog = true this.showAddUpdateDialog = true
@@ -671,12 +674,12 @@ export default {
pageSize: -1 pageSize: -1
} }
if (this.showEnable) { if (this.showEnable) {
if (this.activeTab === knowledgeCardUpdateRecordType.updateRecord) { if (this.activeTab === 'updateRecord') {
params = { params = {
...params, ...params,
opUser: -1 opUser: -1
} }
} else if (this.activeTab === knowledgeCardUpdateRecordType.intelligenceLearning) { } else if (this.activeTab === 'intelligenceLearning') {
params = { params = {
...params, ...params,
opUser: 0 opUser: 0
@@ -690,15 +693,6 @@ export default {
if (this.updateHistoryList[0]) { if (this.updateHistoryList[0]) {
this.currentVersion = this.updateHistoryList[0].commitVersion + 1 this.currentVersion = this.updateHistoryList[0].commitVersion + 1
} }
/*
this.hasUpdatingRecord = false
this.updateHistoryList.forEach(item => {
if (item.isUpdating) { // if(item.isUpdating){//????????
this.hasUpdatingRecord = true
}
})
*/
}).catch(e => { }).catch(e => {
console.error(e) console.error(e)
}).finally(() => { }).finally(() => {
@@ -709,7 +703,7 @@ export default {
handleClick (tab) { handleClick (tab) {
this.getCurTabData() this.getCurTabData()
if (tab.index === '1') { if (tab.index === '1') {
this.timeChange() this.init()
} }
}, },
clearSelect () { clearSelect () {
@@ -749,9 +743,6 @@ export default {
this.switchKnowledgeId = id this.switchKnowledgeId = id
return false return false
}, },
cancleSwitch () {
this.showConfirmSwitch = false
},
switchLearning () { switchLearning () {
const hint = this.aiTaggingList.find(d => d.knowledgeId === this.switchKnowledgeId) const hint = this.aiTaggingList.find(d => d.knowledgeId === this.switchKnowledgeId)
const toStatus = hint.status === 0 ? 1 : 0 const toStatus = hint.status === 0 ? 1 : 0
@@ -774,19 +765,20 @@ export default {
}, },
watch: { watch: {
tabType (n) { tabType (n) {
this.timeChange() this.$nextTick(() => {
this.handleActiveBar()
})
}, },
/* timeFilter: {
hasUpdatingRecord (n) { handler () {
if (n) { // update record页存在“正在更新”的记录时每20秒自动请求一次接口 if (this.updateKnowledge.source === 'cn_psiphon3_ip') {
this.timer = setTimeout(() => { this.init()
this.getCurTabData() }
}, 20000) this.$nextTick(() => {
} else { // 直到出现新的记录,出现新记录后(失败或者成功),取消定时请求接口,右上角"update"按钮恢复可用。"正在更新"和"失败都会有对应的强调样式 this.handleActiveBar()
clearTimeout(this.timer) })
} }
}, },
*/
tableData: { tableData: {
handler (n) { handler (n) {
if (this.tableData && this.tableData.length > 0) { if (this.tableData && this.tableData.length > 0) {
@@ -822,7 +814,9 @@ export default {
handler (n) { handler (n) {
if (!n) { if (!n) {
this.fileList = [] this.fileList = []
this.timeChange() if (this.updateKnowledge.source === 'cn_psiphon3_ip') {
this.init()
}
} else { } else {
if (this.myChart) { if (this.myChart) {
this.myChart.dispose() this.myChart.dispose()
@@ -849,7 +843,7 @@ export default {
}) })
}, },
beforeUnmount () { beforeUnmount () {
//clearTimeout(this.timer) clearTimeout(this.timer)
window.removeEventListener('resize', this.resize) window.removeEventListener('resize', this.resize)
const dom = document.getElementById('psiphonBarChart') const dom = document.getElementById('psiphonBarChart')
if (dom) { if (dom) {

View File

@@ -1,10 +1,10 @@
import { createI18n } from 'vue-i18n/index' import { createI18n } from 'vue-i18n/index'
import { storageKey, EN } from '@/utils/constants' import { storageKey } from '@/utils/constants'
import { getI18n } from '@/utils/api' import { getI18n } from '@/utils/api'
import store from '@/store' import store from '@/store'
const i18n = createI18n({ const i18n = createI18n({
locale: localStorage.getItem(storageKey.language) || EN locale: localStorage.getItem(storageKey.language) || 'en'
}) })
export async function loadI18n () { export async function loadI18n () {
if (!store.state.i18n) { if (!store.state.i18n) {

View File

@@ -5,8 +5,9 @@ import router from '@/router'
import store from '@/store' import store from '@/store'
import App from '@/App.vue' import App from '@/App.vue'
import '@/utils/http.js' import '@/utils/http.js'
import { hasPermission } from '@/permission'
import commonMixin from '@/mixins/common' import commonMixin from '@/mixins/common'
import { cancelWithChange, noData, myHighLight } from '@/utils/tools' import { cancelWithChange, noData } from '@/utils/tools'
import { ClickOutside } from 'element-plus/lib/directives' import { ClickOutside } from 'element-plus/lib/directives'
import i18n from '@/i18n' import i18n from '@/i18n'
// import '@/mock/index.js' // import '@/mock/index.js'
@@ -36,10 +37,10 @@ app.use(i18n)
app.use(hljsVuePlugin) app.use(hljsVuePlugin)
app.use(VueGridLayout) app.use(VueGridLayout)
app.directive('has', hasPermission) // 注册指令
app.directive('ele-click-outside', ClickOutside) app.directive('ele-click-outside', ClickOutside)
app.directive('cancel', cancelWithChange) app.directive('cancel', cancelWithChange)
app.directive('no-data', noData) app.directive('no-data', noData)
app.directive('high-light', myHighLight)
app.config.globalProperties.$_ = _ app.config.globalProperties.$_ = _
app.mixin(commonMixin) app.mixin(commonMixin)

View File

@@ -1,4 +1,4 @@
import { hasPermission } from '@/permission' import { hasButton } from '@/permission'
import { dateFormatByAppearance } from '@/utils/date-util' import { dateFormatByAppearance } from '@/utils/date-util'
import { commonErrorTip } from '@/utils/constants' import { commonErrorTip } from '@/utils/constants'
export default { export default {
@@ -28,7 +28,9 @@ export default {
} }
}, },
methods: { methods: {
hasPermission, hasButton (code) {
return hasButton(this.$store.getters.buttonList, code)
},
errorMsgHandler (axiosError) { errorMsgHandler (axiosError) {
if (axiosError.response) { if (axiosError.response) {
if (axiosError.response.data) { if (axiosError.response.data) {

View File

@@ -17,7 +17,7 @@ export default {
// 请求数据 relationshipUrlOne => 路由 refOne => ref // 请求数据 relationshipUrlOne => 路由 refOne => ref
getRelatedServerDataOne (relationshipUrlOne, refOne) { getRelatedServerDataOne (relationshipUrlOne, refOne) {
this.loadingRelationshipOne = true this.loadingRelationshipOne = true
axios.get(relationshipUrlOne, { params: this.getQueryParams(DEFAULT_TIME_FILTER_RANGE.entity.relatedEntity) }).then(response => { axios.get(relationshipUrlOne, { params: this.getQueryParams() }).then(response => {
if (response.status === 200) { if (response.status === 200) {
const relationshipDataOne = [] const relationshipDataOne = []
if (response.data.data.result.length > 0) { if (response.data.data.result.length > 0) {
@@ -33,7 +33,7 @@ export default {
}, },
getRelatedServerDataTwo (relationshipUrlTow, refTow) { getRelatedServerDataTwo (relationshipUrlTow, refTow) {
this.loadingRelationshipTwo = true this.loadingRelationshipTwo = true
axios.get(relationshipUrlTow, { params: this.getQueryParams(DEFAULT_TIME_FILTER_RANGE.entity.relatedEntity) }).then(response => { axios.get(relationshipUrlTow, { params: this.getQueryParams() }).then(response => {
if (response.status === 200) { if (response.status === 200) {
const relationshipDataTwo = [] const relationshipDataTwo = []
if (response.data.data.result.length > 0) { if (response.data.data.result.length > 0) {

View File

@@ -1,4 +1,4 @@
import { chartTableOrderOptionsMapping, storageKey, knowledgeCategoryValue, ZH } from '@/utils/constants' import { chartTableOrderOptionsMapping, storageKey, knowledgeCategoryValue } from '@/utils/constants'
import { getWidthByLanguage } from '@/utils/tools' import { getWidthByLanguage } from '@/utils/tools'
import { api } from '@/utils/api' import { api } from '@/utils/api'
import axios from 'axios' import axios from 'axios'
@@ -58,7 +58,7 @@ export default {
const language = localStorage.getItem(storageKey.language) const language = localStorage.getItem(storageKey.language)
// 文字所占宽度一个英文字母占7px中文16px // 文字所占宽度一个英文字母占7px中文16px
let num = getWidthByLanguage(language) || 7 let num = getWidthByLanguage(language) || 7
if (language !== ZH) { if (language !== 'cn') {
num = num + 1 // 最后一位加空格 num = num + 1 // 最后一位加空格
} }

View File

@@ -32,19 +32,14 @@ router.beforeEach(async (to, from, next) => {
store.commit('setMenuList', menuList) store.commit('setMenuList', menuList)
store.commit('setButtonList', buttonList) store.commit('setButtonList', buttonList)
store.commit('setRoleList', roleList) store.commit('setRoleList', roleList)
const homeRoute = { }
path: '/', if (to.path) {
name: 'home', next()
component: () => import('@/components/layout/Home'), /* if (hasMenu(store.getters.menuList, to.path)) {
children: []
}
handleRoutes(menuList, homeRoute.children)
router.addRoute(homeRoute)
next({ ...to, replace: true })
} else {
if (to.path) {
next() next()
} } else {
ElMessage.error('No access') // TODO 国际化
} */
} }
} }
} else { } else {
@@ -65,14 +60,14 @@ router.beforeEach(async (to, from, next) => {
} }
}) })
// menuList中是否包含code // menuList中是否包含route权限
export function hasMenu (menuList, code) { export function hasMenu (menuList, route) {
return menuList.some(menu => { return menuList.some(menu => {
if (menu.code === code) { if (menu.route === route) {
return true return true
} else { } else {
if (menu.children) { if (menu.children) {
if (hasMenu(menu.children, code)) { if (hasMenu(menu.children, route)) {
return true return true
} }
} }
@@ -101,9 +96,36 @@ export function hasButton (buttonList, code) {
return buttonList.some(button => button === code) return buttonList.some(button => button === code)
} }
// 根据code从menuList和buttonList中判断是否有权限 // 用法 v-has="code" | v-has="[code...]" 任意匹配一个 | v-has:all="[code...]" 全匹配
export function hasPermission (code) { export const hasPermission = {
return hasButton(store.getters.buttonList, code) || hasMenu(store.getters.menuList, code) beforeMount (el, binding) {
// 节点权限处理
const buttonCode = binding.value
const arg = binding.arg
if (buttonCode) {
if (buttonCode instanceof Array) {
let has = true
if (arg && arg === 'all') { // 全匹配
buttonCode.forEach(button => {
if (has) {
has = hasButton(store.getters.buttonList, button)
}
})
} else { // 任意匹配
has = buttonCode.some(button => {
return hasButton(store.getters.buttonList, button)
})
}
if (!has) {
el.parentNode.removeChild(el)
}
} else { // 单个匹配
if (!hasButton(store.getters.buttonList, buttonCode)) {
el.parentNode && el.parentNode.removeChild(el)
}
}
}
}
} }
// 根据orderNum排序 // 根据orderNum排序
@@ -138,100 +160,3 @@ export function getWelcomeMenu (menu) {
} }
} }
} }
export function handleComponent (code) {
switch (code) {
case 'networkOverview':
case 'networkAppPerformance':
case 'dnsServiceInsights':
case 'linkMonitor':
return () => import('@/views/charts2/Panel')
case 'entity':
return () => import('@/views/entityExplorer/EntityExplorer')
case 'entityDetail':
return () => import('@/views/entityExplorer/EntityDetail')
case 'entityGraph':
return () => import('@/views/entityExplorer/EntityGraph')
case 'securityEvents':
case 'performanceEvents':
return () => import('@/views/detections/Index')
case 'detectionPolicy':
return () => import('@/views/detections/detectionPolicies/Index')
case 'createDetectionPolicy':
case 'editDetectionPolicy':
return () => import('@/views/detections/detectionPolicies/PolicyForm')
case 'report':
return () => import('@/views/report/Report')
case 'knowledgeBase':
return () => import('@/views/setting/KnowledgeBase')
case 'userDefinedLibrary':
return () => import('@/views/setting/KnowledgeBaseUserDefinedList')
case 'createUserDefinedLibrary':
case 'editUserDefinedLibrary':
return () => import('@/views/setting/KnowledgeBaseForm')
case 'administration':
return () => import('@/views/administration/Index')
case 'user':
return () => import('@/views/administration/User')
case 'role':
return () => import('@/views/administration/Roles')
case 'operationLog':
return () => import('@/views/administration/OperationLog')
case 'appearance':
return () => import('@/views/administration/Appearance')
case 'I18N':
return () => import('@/views/administration/I18n')
default:
return null
}
}
export function handleRoutes (menus, routes) {
menus.forEach(menu => {
if (menu.route === '' && (!menu.children || menu.children.length < 0)) {
return false
}
// administration的路由使用了嵌套其他的是平铺
if (menu.pid === 0 && menu.code === 'administration') {
const path = menu.route.replace('redirect:', '')
if (menu.children && menu.children.length > 0) {
const route = {
name: menu.name,
path,
redirect: menu.children[0].route,
component: handleComponent(menu.code),
children: []
}
menu.children.forEach(c => {
route.children.push({
name: c.name,
path: c.route,
component: handleComponent(c.code)
})
})
routes.push(route)
}
} else {
if (menu.route && menu.route.startsWith('redirect:')) {
const path = menu.route.replace('redirect:', '')
if (menu.children && menu.children.length > 0) {
routes.push({
name: menu.name,
path,
redirect: menu.children[0].route
})
handleRoutes(menu.children, routes)
}
} else {
routes.push({
name: menu.code,
path: menu.route,
component: handleComponent(menu.code)
})
}
if (menu.children && menu.children.length > 0) {
handleRoutes(menu.children, routes)
}
}
})
}

View File

@@ -5,6 +5,106 @@ const routes = [
{ {
path: '/login', path: '/login',
component: () => import('@/Login') component: () => import('@/Login')
},
{
path: '/',
component: () => import('@/components/layout/Home'),
children: [
{
name: 'panel',
path: '/panel/:typeName',
component: () => import('@/views/charts2/Panel')
},
{
path: '/report/builtIn',
component: () => import('@/views/report/Report')
},
{
path: '/entity',
component: () => import('@/views/entityExplorer/EntityExplorer')
},
{
path: '/entityDetail',
component: () => import('@/views/entityExplorer/EntityDetail')
},
{
path: '/entityGraph',
component: () => import('@/views/entityExplorer/EntityGraph')
},
{
path: '/detection',
redirect: '/detection/securityEvent'
},
{
path: '/detection/:typeName',
component: () => import('@/views/detections/Index')
},
{
path: '/businessLog/viewer',
component: () => import('@/views/businessLog/Viewer')
},
{
path: '/knowledgeBase',
component: () => import('@/views/setting/KnowledgeBase')
},
{
path: '/knowledgeBase/userDefinedLibrary',
component: () => import('@/views/setting/KnowledgeBase')
},
{
path: '/knowledgeBase/userDefinedLibrary/create',
component: () => import('@/views/setting/KnowledgeBaseForm')
},
{
path: '/knowledgeBase/userDefinedLibrary/edit',
component: () => import('@/views/setting/KnowledgeBaseForm')
},
{
name: 'Administration',
path: '/administration',
redirect: '/administration/user',
component: () => import('@/views/administration/Index'),
children: [
{
name: 'User',
path: '/administration/user',
component: () => import('@/views/administration/User')
},
{
name: 'Role',
path: '/administration/role',
component: () => import('@/views/administration/Roles')
},
{
name: 'OperationLog',
path: '/administration/operationLog',
component: () => import('@/views/administration/OperationLog')
},
{
name: 'Appearance',
path: '/administration/appearance',
component: () => import('@/views/administration/Appearance')
}
]
},
{
name: 'I18n',
path: '/i18n',
component: () => import('@/views/administration/I18n')
},
{
path: '/detectionPolicy',
component: () => import('@/views/detections/detectionPolicies/Index')
},
{
path: '/detectionPolicy/create',
component: () => import('@/views/detections/detectionPolicies/PolicyForm')
},
{
path: '/detectionPolicy/edit',
component: () => import('@/views/detections/detectionPolicies/PolicyForm')
}
]
} }
] ]

View File

@@ -1,6 +1,6 @@
import axios from 'axios' import axios from 'axios'
import router from '@/router' import router from '@/router'
import { getWelcomeMenu, sortByOrderNum, handleRoutes } from '@/permission' import { getWelcomeMenu, sortByOrderNum } from '@/permission'
import { ElMessage } from 'element-plus' // dependent on utc plugin import { ElMessage } from 'element-plus' // dependent on utc plugin
import { dbDrilldownTableConfig, storageKey } from '@/utils/constants' import { dbDrilldownTableConfig, storageKey } from '@/utils/constants'
import { getConfigVersion } from '@/utils/tools' import { getConfigVersion } from '@/utils/tools'
@@ -64,14 +64,7 @@ const user = {
store.commit('setMenuList', menuList) store.commit('setMenuList', menuList)
store.commit('setButtonList', res2.data.buttons) store.commit('setButtonList', res2.data.buttons)
store.commit('setRoleList', res2.data.roles) store.commit('setRoleList', res2.data.roles)
const homeRoute = {
path: '/',
name: 'home',
component: () => import('@/components/layout/Home'),
children: []
}
handleRoutes(menuList, homeRoute.children)
router.addRoute(homeRoute)
if (res.loginSuccessPath) { if (res.loginSuccessPath) {
let tempArr = res.loginSuccessPath.split('?') let tempArr = res.loginSuccessPath.split('?')
const path = tempArr[0] const path = tempArr[0]

View File

@@ -38,7 +38,6 @@ export const storageKey = {
leftMenuShrink: 'cn-left-menu-shrink', leftMenuShrink: 'cn-left-menu-shrink',
unsavedChange: 'cn-unsaved-change', unsavedChange: 'cn-unsaved-change',
entitySearchHistory: 'cn-entity-search-history', entitySearchHistory: 'cn-entity-search-history',
detectionSearchHistory: 'cn-detection-search-history',
echartLegendFontSize: 'echartLegendFontSize', echartLegendFontSize: 'echartLegendFontSize',
echartLabelFontSize: 'echartLabelFontSize', echartLabelFontSize: 'echartLabelFontSize',
tokenExpireCurrentPath: 'token-expire-current-path', tokenExpireCurrentPath: 'token-expire-current-path',
@@ -75,7 +74,6 @@ export const panelTypeAndRouteMapping = {
ipEntityDetail: 21, ipEntityDetail: 21,
domainEntityDetail: 22, domainEntityDetail: 22,
appEntityDetail: 23, appEntityDetail: 23,
subscribeEntityDetail: 24,
cryptocurrency: 7, cryptocurrency: 7,
ipDrillDownTest: 8, ipDrillDownTest: 8,
linkMonitor: 14, linkMonitor: 14,
@@ -100,11 +98,6 @@ export const entityType = {
ip: 'IP' ip: 'IP'
} }
export const knowledgeCardUpdateRecordType = {
updateRecord: 'updateRecord',
intelligenceLearning: 'intelligenceLearning'
}
export const entityDetailTabsName = { export const entityDetailTabsName = {
informationAggregation: 'informationAggregation', informationAggregation: 'informationAggregation',
relatedEntity: 'relatedEntity', relatedEntity: 'relatedEntity',
@@ -220,7 +213,7 @@ export const detectionPageType = {
} }
export const listScrollPath = [ export const listScrollPath = [
'/entity', '/entityExplorer',
'/detection/performanceEvent', '/detection/performanceEvent',
'/detection/securityEvent' '/detection/securityEvent'
] ]
@@ -1799,8 +1792,6 @@ export const langData = [
{ value: 'zh', label: 'zh' }, { value: 'zh', label: 'zh' },
{ value: 'en', label: 'en' } { value: 'en', label: 'en' }
] ]
export const ZH = 'zh'
export const EN = 'en'
export const performanceMetricMapping = { export const performanceMetricMapping = {
'dns error': 'DNS Error Rate', 'dns error': 'DNS Error Rate',
@@ -1813,61 +1804,61 @@ export const builtInKnowledgeBaseBasicInfo = [
knowledgeId: 10, knowledgeId: 10,
label: 'Psiphon3 VPN', label: 'Psiphon3 VPN',
iconUrl: 'images/knowledge-base-logo/psiphon3-vpn.png', iconUrl: 'images/knowledge-base-logo/psiphon3-vpn.png',
desc: 'knowledgeBase.desc.psiphon3' desc: 'Psiphon3 is a circumvention software for Windows and other platforms that provides uncensored access to Internet content.'
}, },
{ {
knowledgeId: 5, knowledgeId: 5,
label: 'network.domainCategory', label: 'Domain Category',
iconUrl: 'images/knowledge-base-logo/fqdn.png', iconUrl: 'images/knowledge-base-logo/fqdn.png',
desc: 'knowledgeBase.desc.domainCategory' desc: 'Domain category provides basic information including categories, providers, reputation score.'
}, },
{ {
knowledgeId: 6, knowledgeId: 6,
label: 'knowledgeBase.domainWhois', label: 'Domain Whois',
iconUrl: 'images/knowledge-base-logo/fqdn-whois.png', iconUrl: 'images/knowledge-base-logo/fqdn-whois.png',
desc: 'knowledgeBase.desc.domainWhois' desc: 'Domain whois contains registration and ownership information for domain names. It includes details like domain registrar, registrant, creation/expiry dates, and contact information.'
}, },
{ {
knowledgeId: 2, knowledgeId: 2,
label: 'IP ASN', label: 'IP ASN',
iconUrl: 'images/knowledge-base-logo/ip-asn.png', iconUrl: 'images/knowledge-base-logo/ip-asn.png',
desc: 'knowledgeBase.desc.ipAsn' desc: 'ASN Database associates IP addresses with their corresponding Autonomous System Numbers, which are unique identifiers assigned to internet networks. This database helps identify the network and its owner, facilitating network analysis and monitoring tasks.'
}, },
{ {
knowledgeId: 3, knowledgeId: 3,
label: 'knowledgeBase.dnsServerInfo', label: 'DNS Server Info',
iconUrl: 'images/knowledge-base-logo/dns-server-info.png', iconUrl: 'images/knowledge-base-logo/dns-server-info.png',
desc: 'knowledgeBase.desc.dnsServer' desc: 'A DNS Server Info stores information about Domain Name System (DNS) servers. It includes details such as IP addresses, host names, locations, software name, operation system, and roles of the servers.'
}, },
{ {
knowledgeId: 9, knowledgeId: 9,
label: 'knowledgeBase.appCategory', label: 'APP Category',
iconUrl: 'images/knowledge-base-logo/app-category.png', iconUrl: 'images/knowledge-base-logo/app-category.png',
desc: 'knowledgeBase.desc.appCategory' desc: 'APP category provides basic information for over 3000 popular applications, including their categories and service providers.'
}, },
{ {
knowledgeId: 7, knowledgeId: 7,
label: 'knowledgeBase.ioc', label: 'Indicators of Compromise',
iconUrl: 'images/knowledge-base-logo/indicators-of-compromise.png', iconUrl: 'images/knowledge-base-logo/indicators-of-compromise.png',
desc: 'knowledgeBase.desc.ioc' desc: 'Indicator of Compromise (IoC) refers to forensic artifacts, such as unusual network traffic or malicious files, indicating a security breach or cyberattack.'
}, },
{ {
knowledgeId: 4, knowledgeId: 4,
label: 'ICP', label: 'ICP',
iconUrl: 'images/knowledge-base-logo/icp.png', iconUrl: 'images/knowledge-base-logo/icp.png',
desc: 'knowledgeBase.desc.icp' desc: 'ICP (Internet Content Provider) license is a permit issued by Chinese authorities, mandatory for websites to legally operate and publish content within mainland China.'
}, },
{ {
knowledgeId: 1, knowledgeId: 1,
label: 'knowledgeBase.ipLocation', label: 'IP Location',
iconUrl: 'images/knowledge-base-logo/ip-location.png', iconUrl: 'images/knowledge-base-logo/ip-location.png',
desc: 'knowledgeBase.desc.ipLocation' desc: 'IP location Database is a repository containing geographical data associated with IP addresses, such as country, city, ISP, organization, latitude, longitude, and other relevant details.'
}, },
{ {
knowledgeId: 8, knowledgeId: 8,
label: 'eventType.anonymity', label: 'Anonymity',
iconUrl: 'images/knowledge-base-logo/anonymity.png', iconUrl: 'images/knowledge-base-logo/anonymity.png',
desc: 'knowledgeBase.desc.anonymity' desc: 'Communication system that conceals users\' identities and activities to protect privacy and prevent tracking or surveillance. This database provides lists of Tor nodes, I2P nodes, obfs4, etc.'
} }
] ]

View File

@@ -80,15 +80,15 @@ export const dataForNetworkOverviewLine = {
options2: [ options2: [
{ {
value: 'Average', value: 'Average',
label: 'overall.average' label: 'Average'
}, },
{ {
value: '95th Percentile', value: '95th Percentile',
label: ['overall.percentileNumber', { number: 95 }] label: '95th Percentile'
}, },
{ {
value: 'Maximum', value: 'Maximum',
label: 'overall.maximum' label: 'Maximum'
} }
], ],
tabsTemplate: [ tabsTemplate: [
@@ -200,15 +200,15 @@ export const dataForDnsTrafficLine = {
options2: [ options2: [
{ {
value: 'Average', value: 'Average',
label: 'overall.average' label: 'Average'
}, },
{ {
value: '95th Percentile', value: '95th Percentile',
label: ['overall.percentileNumber', { number: 95 }] label: '95th Percentile'
}, },
{ {
value: 'Maximum', value: 'Maximum',
label: 'overall.maximum' label: 'Maximum'
} }
], ],
tabs: [ tabs: [

View File

@@ -1,13 +1,12 @@
import { ElMessageBox, ElMessage } from 'element-plus' import { ElMessageBox, ElMessage } from 'element-plus'
import i18n from '@/i18n' import i18n from '@/i18n'
import _ from 'lodash' import _ from 'lodash'
import { storageKey, iso36112, topDomain, echartsFontSize, dbGeoDataTableName, networkTable, dbDrilldownTableConfig, ZH, EN } from '@/utils/constants' 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 { format } from 'echarts'
import router from '@/router' import router from '@/router'
import store from '@/store' import store from '@/store'
import indexedDBUtils from '@/indexedDB' import indexedDBUtils from '@/indexedDB'
import { columnType } from '@/components/advancedSearch/meta/meta'
export const tableSort = { export const tableSort = {
// 是否需要排序 // 是否需要排序
@@ -1249,10 +1248,10 @@ export function getQueryByFlag2 (type, condition) {
*/ */
export function getWidthByLanguage (language) { export function getWidthByLanguage (language) {
switch (language) { switch (language) {
case EN: { case 'en': {
return 7 return 7
} }
case ZH: { case 'cn': {
return 16 return 16
} }
} }
@@ -1361,89 +1360,3 @@ export function getTagColor (color) {
return `color: ${color};border-color: ${color};background-color: ${backgroundColor};` return `color: ${color};border-color: ${color};background-color: ${backgroundColor};`
} }
} }
/**
* 字段高亮
* 用法: <span v-high-light=[{type: 'string', value: '搜索'}, {type: 'fullText', value: '高亮'}]>搜索关键字高亮<span>
* 其中type为fullText的为模糊搜索
* @type {{updated(*, *): (*|undefined)}}
*/
export const myHighLight = {
updated (el, binding) {
if (el && binding.value) {
const { value } = binding
if (value && value.length > 0) {
const text = _.cloneDeep(el.innerHTML)
const regex = new RegExp(value.map(item => `${item.value}`).join('|'), 'g')
if (el.getElementsByClassName('highlight__text').length === 0) {
const newText = text.replace(regex, (match) => {
// 将value中的value提取出来对比string即精准搜索fullText模糊搜索
for (const item of value) {
if ((item.type === columnType.string && item.value === el.innerHTML) || el.className.indexOf('high-location') > -1) {
if (el.className.indexOf('high-light-block') > -1) {
return `<span class="highlight__block">${match}</span>`
} else {
return `<span class="highlight__text">${match}</span>`
}
} else if (item.type === columnType.fullText && item.value === match) {
if (el.className.indexOf('high-light-block') > -1) {
return `<span class="highlight__block">${match}</span>`
} else {
return `<span class="highlight__text">${match}</span>`
}
}
}
return match
})
if (newText && newText !== '-') {
// 此处不用el.className.indexOf('high-light-block')判断是因为block可能会有多个有一个满足所有的都会渲染
if (newText.indexOf('highlight__block') > -1) {
el.style.cssText = el.style.cssText + 'background: #FEECC2;'
// 此处是相关app、相关ip、相关domain弹窗获取不到dom的草错
let dom
if (document.getElementById('showRelatedApp')) {
dom = document.getElementById('showRelatedApp')
} else if (document.getElementById('showRelatedDomain')) {
dom = document.getElementById('showRelatedDomain')
}
if (dom) {
const itemDom = dom.getElementsByClassName('high-light-block')
if (itemDom) {
for (let i = 0; i < itemDom.length; i++) {
if (itemDom[i].innerHTML === el.innerHTML) {
itemDom[i].style.cssText = itemDom[i].style.cssText + 'background: #FEECC2;'
}
}
}
}
} else {
el.innerHTML = newText
}
} else {
return newText
}
}
}
}
}
}
export const changeTimeByDate = (date) => {
if (date) {
const nowDate = Date.now()
const oldDate = isNaN(date) ? Date.parse(date) : date
const diff = Math.floor((nowDate - oldDate) / 1000)
if (diff < 60) {
return diff + i18n.global.t('entity.search.secondsAgo')
} else if (diff >= 60 && diff < 3600) {
const minutes = Math.floor(diff / 60)
return minutes === 1 ? `${minutes} ${i18n.global.t('entity.search.minuteAgo')}` : `${minutes} ${i18n.global.t('entity.search.minutesAgo')}`
} else if (diff >= 3600 && diff < 86400) {
const hours = Math.floor(diff / 3600)
return hours === 1 ? `${hours} ${i18n.global.t('entity.search.hourAgo')}` : `${hours} ${i18n.global.t('entity.search.hoursAgo')}`
} else {
return date
}
}
}

View File

@@ -48,9 +48,7 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
<div class="edit-appearance-base__footer"> <div class="edit-appearance-base__footer">
<button style="position: relative;" :class="{'footer__btn--disabled': blockOperation.save}" :disabled="blockOperation.save" class="footer__btn" @click="save" <button style="position: relative;" :class="{'footer__btn--disabled': blockOperation.save}" :disabled="blockOperation.save" class="footer__btn" @click="save">
v-if="hasPermission('editAppearence')"
>
<loading size="small" :loading="blockOperation.save"></loading> <loading size="small" :loading="blockOperation.save"></loading>
<span>{{$t('overall.save')}}</span> <span>{{$t('overall.save')}}</span>
</button> </button>
@@ -60,7 +58,7 @@
</template> </template>
<script> <script>
import { api } from '@/utils/api' import { api } from '@/utils/api'
import { storageKey, ZH, EN } from '@/utils/constants' import { storageKey } from '@/utils/constants'
import axios from 'axios' import axios from 'axios'
import dayjs from 'dayjs' import dayjs from 'dayjs'
@@ -99,12 +97,12 @@ export default {
{ {
id: 1, id: 1,
label: 'English', label: 'English',
value: EN value: 'en'
}, },
{ {
id: 2, id: 2,
label: '中文', label: '中文',
value: ZH value: 'zh'
} }
] ]
} }

View File

@@ -11,19 +11,16 @@
> >
<template v-slot:top-tool-left> <template v-slot:top-tool-left>
<button id="roles-add" class="top-tool-btn margin-r-10 top-tool-btn--create" <button id="roles-add" class="top-tool-btn margin-r-10 top-tool-btn--create"
v-if="hasPermission('createRole')"
@click="add"> @click="add">
<i class="cn-icon-xinjian cn-icon"></i> <i class="cn-icon-xinjian cn-icon"></i>
<span>{{$t('overall.create')}}</span> <span>{{$t('overall.create')}}</span>
</button> </button>
<button id="roles-edit" class="top-tool-btn margin-r-10" :disabled="disableEdit" <button id="roles-edit" class="top-tool-btn margin-r-10" :disabled="disableEdit"
v-if="hasPermission('editRole')"
@click="edit"> @click="edit">
<i class="cn-icon-edit cn-icon"></i> <i class="cn-icon-edit cn-icon"></i>
<span>{{$t('overall.edit')}}</span> <span>{{$t('overall.edit')}}</span>
</button> </button>
<button id="roles-delete" class="top-tool-btn margin-r-10" :disabled="disableDelete" <button id="roles-delete" class="top-tool-btn margin-r-10" :disabled="disableDelete"
v-if="hasPermission('deleteRole')"
@click="delBatch"> @click="delBatch">
<i class="cn-icon-delete cn-icon"></i> <i class="cn-icon-delete cn-icon"></i>
<span>{{$t('overall.delete')}}</span> <span>{{$t('overall.delete')}}</span>

View File

@@ -11,19 +11,16 @@
> >
<template #top-tool-left> <template #top-tool-left>
<button id="account-add" class="top-tool-btn margin-r-10 top-tool-btn--create" <button id="account-add" class="top-tool-btn margin-r-10 top-tool-btn--create"
v-if="hasPermission('createUser')"
@click="add"> @click="add">
<i class="cn-icon-xinjian cn-icon"></i> <i class="cn-icon-xinjian cn-icon"></i>
<span>{{$t('overall.create')}}</span> <span>{{$t('overall.create')}}</span>
</button> </button>
<button id="account-edit" class="top-tool-btn margin-r-10" :disabled="disableEdit" <button id="account-edit" class="top-tool-btn margin-r-10" :disabled="disableEdit"
v-if="hasPermission('editUser')"
@click="editSelectRecord"> @click="editSelectRecord">
<i class="cn-icon-edit cn-icon"></i> <i class="cn-icon-edit cn-icon"></i>
<span>{{$t('overall.edit')}}</span> <span>{{$t('overall.edit')}}</span>
</button> </button>
<button id="account-delete" class="top-tool-btn margin-r-10" :disabled="disableDelete" <button id="account-delete" class="top-tool-btn margin-r-10" :disabled="disableDelete"
v-if="hasPermission('deleteUser')"
@click="delBatch"> @click="delBatch">
<i class="cn-icon-delete cn-icon"></i> <i class="cn-icon-delete cn-icon"></i>
<span>{{$t('overall.delete')}}</span> <span>{{$t('overall.delete')}}</span>

View File

@@ -5,12 +5,12 @@
v-if="panel.params && panel.params.wholeScreenScroll" v-if="panel.params && panel.params.wholeScreenScroll"
id="wholeScreenBox" id="wholeScreenBox"
> >
<!-- <dns-screen v-if="currentPath === wholeScreenRouterMapping.dns" <dns-screen v-if="currentPath === wholeScreenRouterMapping.dns"
:copy-data-list="chartList" :copy-data-list="chartList"
ref="dnsScreen" ref="dnsScreen"
:time-filter="timeFilter" :time-filter="timeFilter"
:entity="entity"> :entity="entity">
</dns-screen>--> </dns-screen>
</div> </div>
<div id="panelList" v-if="!isEntityDetail" class="panel-list"> <div id="panelList" v-if="!isEntityDetail" class="panel-list">
<div id="cn-panel" class="cn-panel2"> <div id="cn-panel" class="cn-panel2">
@@ -49,7 +49,7 @@
<script> <script>
import { useRoute, useRouter } from 'vue-router' import { useRoute, useRouter } from 'vue-router'
import { ref } from 'vue' import { ref } from 'vue'
// import DnsScreen from '@/views/charts/wholeScreenScroll/DnsScreen' import DnsScreen from '@/views/charts/wholeScreenScroll/DnsScreen'
import { panelTypeAndRouteMapping, wholeScreenRouterMapping } from '@/utils/constants' import { panelTypeAndRouteMapping, wholeScreenRouterMapping } from '@/utils/constants'
import { api, getPanelList, getChartList } from '@/utils/api' import { api, getPanelList, getChartList } from '@/utils/api'
import { getNowTime } from '@/utils/date-util' import { getNowTime } from '@/utils/date-util'
@@ -66,9 +66,9 @@ export default {
isEntityDetail: Boolean, isEntityDetail: Boolean,
typeName: String typeName: String
}, },
/* components: { components: {
DnsScreen DnsScreen
}, */ },
data () { data () {
return { return {
chartList: [], // 普通panel的chart chartList: [], // 普通panel的chart
@@ -104,8 +104,8 @@ export default {
setup (props, ctx) { setup (props, ctx) {
const panel = ref({}) const panel = ref({})
let panelType = 1 // 取得panel的type let panelType = 1 // 取得panel的type
const { path } = useRoute() const { params } = useRoute()
panelType = props.entity ? props.entity.type : panelTypeAndRouteMapping[path.replace('/panel/', '')] panelType = props.entity ? props.entity.type : panelTypeAndRouteMapping[params.typeName]
// date // date
const dateRangeValue = 60 const dateRangeValue = 60

View File

@@ -338,10 +338,7 @@ export function axisFormatter (params) {
return str return str
} }
export function tooLongFormatter (name) { export function tooLongFormatter (name) {
return format.truncateText(name, 160, '12px') return format.truncateText(name, 110, '12px')
}
export function tooLongFormatterFor2Columns (name) {
return format.truncateText(name, 100, '12px')
} }
export function timeHorizontalFormatter (params) { export function timeHorizontalFormatter (params) {
let str = '<div>' let str = '<div>'

View File

@@ -1,7 +1,7 @@
<template> <template>
<div class="panel-box2" :class="{'panel-box2--entity-detail': entity && entity.entityType}"> <div class="panel-box2" :class="{'panel-box2--entity-detail': entity && entity.entityType}">
<div class="panel__header" v-if="!entity"> <div class="panel__header" v-if="!entity">
<div class="panel__title">{{panelName ? panelName:(panel.i18n ? $t(panel.i18n) : panel.name)}} <div class="panel__title">{{panelName?panelName:(panel.i18n ? $t(panel.i18n) : panel.name)}}
<div v-if="showScore" class="score"> <div v-if="showScore" class="score">
<div class="circle-icon" v-if="score <= 2 || score === '-'" :class="{'data-score-red': score <= 2 || score === '-'}" ></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 <= 4" :class="{'data-score-yellow': score <= 4}" ></div>
@@ -31,7 +31,7 @@
@change="metricChange" @change="metricChange"
> >
<template #prefix> <template #prefix>
<span class="select-prefix">{{$t('detections.metric')}}:</span> <span class="select-prefix">Metric:</span>
</template> </template>
<el-option v-for="item in metricOptions" :key="item.value" :label="item.label" :value="item.value"></el-option> <el-option v-for="item in metricOptions" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select> </el-select>
@@ -148,7 +148,7 @@ export default {
// this.panelName = this.$store.getters.getPanelName // this.panelName = this.$store.getters.getPanelName
const pName = this.$route.query.panelName ? this.$t(this.$route.query.panelName) : '' const pName = this.$route.query.panelName ? this.$t(this.$route.query.panelName) : ''
const curTabProp = this.$route.query.dimensionType ? this.$route.query.dimensionType : null const curTabProp = this.$route.query.dimensionType ? this.$route.query.dimensionType : null
if (this.$route.path.replace('/panel/', '') === fromRoute.dnsServiceInsights) { if (this.$route.params.typeName === fromRoute.dnsServiceInsights) {
this.dnsQtypeMapData = await getDnsMapData('dnsQtype') this.dnsQtypeMapData = await getDnsMapData('dnsQtype')
this.dnsRcodeMapData = await getDnsMapData('dnsRcode') this.dnsRcodeMapData = await getDnsMapData('dnsRcode')
this.$store.commit('setDnsQtypeMapData', this.dnsQtypeMapData) this.$store.commit('setDnsQtypeMapData', this.dnsQtypeMapData)
@@ -249,11 +249,12 @@ export default {
const panel = ref({}) const panel = ref({})
let panelType = 1 // 取得panel的type let panelType = 1 // 取得panel的type
let { query, path } = useRoute() let { params, query, path } = useRoute()
// 获取路由跳转过的历史状态,赋值给当前界面,起到保留状态的作用,如浏览器的回退前进等 // 获取路由跳转过的历史状态,赋值给当前界面,起到保留状态的作用,如浏览器的回退前进等
const routerObj = store.getters.getRouterHistoryList.find(item => item.t === query.t) const routerObj = store.getters.getRouterHistoryList.find(item => item.t === query.t)
if (routerObj) { if (routerObj) {
params = routerObj.params
query = routerObj.query query = routerObj.query
path = routerObj.path path = routerObj.path
@@ -291,19 +292,19 @@ export default {
} else if (thirdPanel) { } else if (thirdPanel) {
panelType = Number(thirdPanel) panelType = Number(thirdPanel)
} else { } else {
panelType = props.entity ? props.entity.type : panelTypeAndRouteMapping[path.replace('/panel/', '')] panelType = props.entity ? props.entity.type : panelTypeAndRouteMapping[params.typeName]
} }
// 获取url携带的range、startTime、endTime // 获取url携带的range、startTime、endTime
const rangeParam = query.range const rangeParam = query.range
const startTimeParam = query.startTime const startTimeParam = query.startTime
const endTimeParam = query.endTime const endTimeParam = query.endTime
// 若url携带了使用携带的值否则使用默认值。
// 优先级url > config.js > 默认值。 const dateRangeValue = rangeParam ? parseInt(query.range) : 60
const dateRangeValue = rangeParam ? parseInt(rangeParam) : (DEFAULT_TIME_FILTER_RANGE.dashboard || 60)
const timeFilter = ref({ dateRangeValue }) const timeFilter = ref({ dateRangeValue })
if (!startTimeParam || !endTimeParam) { if (!startTimeParam || !endTimeParam) {
const { startTime, endTime } = getNowTime(dateRangeValue) const { startTime, endTime } = getNowTime(60)
timeFilter.value.startTime = getSecond(startTime) timeFilter.value.startTime = getSecond(startTime)
timeFilter.value.endTime = getSecond(endTime) timeFilter.value.endTime = getSecond(endTime)
// 如果没有时间参数就将参数写入url // 如果没有时间参数就将参数写入url
@@ -518,7 +519,7 @@ export default {
}, },
jumpEntityDetail () { jumpEntityDetail () {
const { href } = this.$router.resolve({ const { href } = this.$router.resolve({
path: '/entity/detail', path: '/entityDetail',
query: { query: {
entityType: this.entityType, entityType: this.entityType,
entityName: this.entityValue entityName: this.entityValue

View File

@@ -1,5 +1,4 @@
import { entityDetailRelatedEntitiesShowSize, entityDetailTabsName } from '@/utils/constants' import { entityDetailRelatedEntitiesShowSize } from '@/utils/constants'
import { getSecond } from '@/utils/date-util'
export default { export default {
props: { props: {
@@ -29,59 +28,6 @@ export default {
} }
} }
}, },
getParamsByTabType (tabType) {
let params = {
resource: this.entity.entityName
}
let dataRangeValue = 60 * 24 * 7
switch (tabType) {
case entityDetailTabsName.relatedEntity:
dataRangeValue = DEFAULT_TIME_FILTER_RANGE.entity.relatedEntity
break
case entityDetailTabsName.performanceEvent:
dataRangeValue = DEFAULT_TIME_FILTER_RANGE.entity.performanceEvent
break
case entityDetailTabsName.securityEvent:
dataRangeValue = DEFAULT_TIME_FILTER_RANGE.entity.securityEvent
break
case entityDetailTabsName.openPort:
dataRangeValue = DEFAULT_TIME_FILTER_RANGE.entity.openPort
break
case entityDetailTabsName.informationAggregation:
dataRangeValue = DEFAULT_TIME_FILTER_RANGE.entity.informationAggregation
break
case entityDetailTabsName.behaviorPattern:
dataRangeValue = DEFAULT_TIME_FILTER_RANGE.entity.behaviorPattern
break
default:
dataRangeValue = 60 * 24 * 7
}
if (dataRangeValue !== 0) {
const endTime = window.$dayJs.tz().valueOf()
const startTime = endTime - dataRangeValue * 60 * 1000
params = {
...params,
startTime: getSecond(startTime),
endTime: getSecond(endTime)
}
}
return params
},
getParams () {
const range = this.timeFilter.dateRangeValue
let params = {
resource: this.entity.entityName
}
if (range !== 0) {
params = {
...params,
startTime: getSecond(this.timeFilter.startTime),
endTime: getSecond(this.timeFilter.endTime)
}
}
return params
},
handleShowDataNum (showListInfo, allList) { handleShowDataNum (showListInfo, allList) {
if (allList.length <= entityDetailRelatedEntitiesShowSize) { if (allList.length <= entityDetailRelatedEntitiesShowSize) {
showListInfo.num = allList.length showListInfo.num = allList.length

View File

@@ -43,7 +43,7 @@
</div> </div>
</div>--> </div>-->
<div class="line-select-reference-line"> <div class="line-select-reference-line">
<span>{{$t('network.referenceLine')}}&nbsp;:&nbsp;</span> <span>{{$t('network.referenceLine')}}:</span>
<div class="line-select__operation"> <div class="line-select__operation">
<el-select <el-select
size="mini" size="mini"
@@ -54,9 +54,7 @@
:popper-append-to-body="false" :popper-append-to-body="false"
@change="referenceSelectChange" @change="referenceSelectChange"
> >
<el-option :key="options2[0].value" :label="$t(options2[0].label)" :value="options2[0].value"></el-option> <el-option v-for="item in options2" :key="item.value" :label="item.label" :value="item.value"></el-option>
<el-option :key="options2[1].value" :label="$t(options2[1].label[0], options2[1].label[1])" :value="options2[1].value"></el-option>
<el-option :key="options2[2].value" :label="$t(options2[2].label)" :value="options2[2].value"></el-option>
</el-select> </el-select>
</div> </div>
</div> </div>
@@ -257,14 +255,6 @@ export default {
label: { label: {
formatter (params) { formatter (params) {
const arr = unitConvert(params.value, unitTypes.number).join('') const arr = unitConvert(params.value, unitTypes.number).join('')
const referIndex = _this.options2.findIndex(o => o.value === _this.lineRefer)
if (referIndex > -1) {
if (referIndex === 1) {
return _this.$t(_this.options2[1].label[0], _this.options2[1].label[1]) + '(' + arr + echartsData[0].unitType + ')'
} else {
return _this.$t(_this.options2[referIndex].label) + '(' + arr + echartsData[0].unitType + ')'
}
}
return _this.lineRefer + '(' + arr + echartsData[0].unitType + ')' return _this.lineRefer + '(' + arr + echartsData[0].unitType + ')'
}, },
position: 'insideStartTop', position: 'insideStartTop',

View File

@@ -1,7 +1,7 @@
<template> <template>
<div class="entity-detail-basic-info"> <div class="entity-detail-basic-info">
<chart-error v-if="showError" :content="errorMsg"/> <chart-error v-if="showError" :content="errorMsg"/>
<div class="entity-type">{{entityTypeName}}</div> <div class="entity-type">{{entityType[entity.entityType]}}</div>
<div class="entity-basic-info"> <div class="entity-basic-info">
<div class="entity-basic-info__name"> <div class="entity-basic-info__name">
<span id="entityName">{{entity.entityName}}</span> <span id="entityName">{{entity.entityName}}</span>
@@ -90,29 +90,6 @@ export default {
hideTagArea: false hideTagArea: false
} }
}, },
computed: {
entityTypeName () {
const type = this.entity.entityType
let entityTypeName = '-'
switch (type) {
case ('ip'): {
entityTypeName = 'IP'
break
}
case ('domain'): {
entityTypeName = this.$t('overall.domain')
break
}
case ('app'): {
entityTypeName = 'APP'
break
}
default:
break
}
return entityTypeName
}
},
methods: { methods: {
getTagColor, getTagColor,
tagValueHandler (value) { tagValueHandler (value) {
@@ -282,7 +259,7 @@ export default {
icon: 'cn-icon cn-icon-graph', icon: 'cn-icon cn-icon-graph',
label: i18n.global.t('entities.graph'), label: i18n.global.t('entities.graph'),
url: resolvePath({ url: resolvePath({
path: '/entity/graph', path: '/entityGraph',
query: { query: {
entityType: props.entity.entityType, entityType: props.entity.entityType,
entityName: props.entity.entityName entityName: props.entity.entityName

View File

@@ -124,12 +124,12 @@ export default {
const rangeParam = query.range const rangeParam = query.range
const startTimeParam = query.startTime const startTimeParam = query.startTime
const endTimeParam = query.endTime const endTimeParam = query.endTime
// 若url携带了使用携带的值否则使用默认值。
// 优先级url > config.js > 默认值。 const dateRangeValue = rangeParam ? parseInt(query.range) : 60
const dateRangeValue = rangeParam ? parseInt(rangeParam) : (DEFAULT_TIME_FILTER_RANGE.entity.trafficLine || 60)
const timeFilter = ref({ dateRangeValue }) const timeFilter = ref({ dateRangeValue })
if (!startTimeParam || !endTimeParam) { if (!startTimeParam || !endTimeParam) {
const { startTime, endTime } = getNowTime(dateRangeValue) const { startTime, endTime } = getNowTime(60)
timeFilter.value.startTime = startTime timeFilter.value.startTime = startTime
timeFilter.value.endTime = endTime timeFilter.value.endTime = endTime
} else { } else {

View File

@@ -14,13 +14,13 @@
<span :style="{color: tab.name === activeTab ? '#046ECA' : '#717171'}">{{ tab.tag }}</span> <span :style="{color: tab.name === activeTab ? '#046ECA' : '#717171'}">{{ tab.tag }}</span>
</el-tag> </el-tag>
</template> </template>
<information-aggregation v-if="tab.name === entityDetailTabsName.informationAggregation && tab.name === activeTab" @toggleLoading="setLoading" :entity="entity" @checkTag="setTag"></information-aggregation> <information-aggregation v-if="tab.name === entityDetailTabsName.informationAggregation && tab.name === activeTab" @toggleLoading="setLoading" :entity="entity" @checkTag="setTag"></information-aggregation>
<domain-name-resolution v-else-if="tab.name === entityDetailTabsName.relatedEntity && tab.name === activeTab" @toggleLoading="setLoading" :entity="entity" @checkTag="setTag"></domain-name-resolution> <domain-name-resolution v-else-if="tab.name === entityDetailTabsName.relatedEntity && tab.name === activeTab" @toggleLoading="setLoading" :entity="entity" :timeFilter="oneDayTimeFilter" @checkTag="setTag"></domain-name-resolution>
<digital-certificate v-else-if="tab.name === entityDetailTabsName.digitalCertificate && tab.name === activeTab" @toggleLoading="setLoading" @checkTag="setTag" /> <digital-certificate v-else-if="tab.name === entityDetailTabsName.digitalCertificate && tab.name === activeTab" @toggleLoading="setLoading" :timeFilter="oneDayTimeFilter" @checkTag="setTag" />
<security-event v-else-if="tab.name === entityDetailTabsName.securityEvent && tab.name === activeTab" @toggleLoading="setLoading" :entity="entity" @checkTag="setTag" /> <security-event v-else-if="tab.name === entityDetailTabsName.securityEvent && tab.name === activeTab" @toggleLoading="setLoading" :timeFilter="oneDayTimeFilter" @checkTag="setTag" />
<performance-event v-else-if="tab.name === entityDetailTabsName.performanceEvent && tab.name === activeTab" @toggleLoading="setLoading" :entity="entity" @checkTag="setTag" /> <performance-event v-else-if="tab.name === entityDetailTabsName.performanceEvent && tab.name === activeTab" @toggleLoading="setLoading" :timeFilter="oneDayTimeFilter" @checkTag="setTag" />
<open-port v-else-if="tab.name === entityDetailTabsName.openPort && tab.name === activeTab" @toggleLoading="setLoading" :entity="entity" @checkTag="setTag"></open-port> <open-port v-else-if="tab.name === entityDetailTabsName.openPort && tab.name === activeTab" @toggleLoading="setLoading" :entity="entity" :timeFilter="oneDayTimeFilter" @checkTag="setTag"></open-port>
<behavior-pattern v-else-if="tab.name === entityDetailTabsName.behaviorPattern && tab.name === activeTab" @toggleLoading="setLoading" :entity="entity" @checkTag="setTag"></behavior-pattern> <behavior-pattern v-else-if="tab.name === entityDetailTabsName.behaviorPattern && tab.name === activeTab" @toggleLoading="setLoading" :entity="entity" :timeFilter="oneDayTimeFilter" @checkTag="setTag"></behavior-pattern>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
</div> </div>
@@ -58,7 +58,12 @@ export default {
}, },
data () { data () {
return { return {
timer: null timer: null,
// 最近一天的时间
oneDayTimeFilter: {
startTime: window.$dayJs.tz().valueOf() - 1440 * 60 * 1000,
endTime: window.$dayJs.tz().valueOf()
}
} }
}, },
watch: { watch: {
@@ -109,17 +114,22 @@ export default {
}, },
methods: { methods: {
initData () { initData () {
const url = this.getUrlByEntityType(this.entity.entityType) const params = {
const informationAggregation = axios.get(`${api.entity.informationAggregation}/${this.entity.entityType}?resource=${this.entity.entityName}&pageSize=100&pageNo=1`, { params: this.getParamsByTabType(entityDetailTabsName.informationAggregation) }) resource: this.entity.entityName
const openPort = axios.get(url, { params: this.getParamsByTabType(entityDetailTabsName.openPort) }) // startTime: getSecond(this.oneDayTimeFilter.startTime),
const security = axios.get(`${api.entity.security}/${this.entity.entityType}`, { params: this.getParamsByTabType(entityDetailTabsName.securityEvent) }) // endTime: getSecond(this.oneDayTimeFilter.endTime)
const performance = axios.get(`${api.entity.performance}/${this.entityType}`, { params: this.getParamsByTabType(entityDetailTabsName.performanceEvent) }) }
Promise.allSettled([informationAggregation, openPort, security, performance]).then(response => { const url = this.getUrlByEntityType(this.entity.entityType)
const informationAggregationResponse = response[0].value const informationAggregation = axios.get(`${api.entity.informationAggregation}/${this.entity.entityType}?resource=${this.entity.entityName}&pageSize=100&pageNo=1`, { params: params })
if (informationAggregationResponse.status === 200) { const openPort = axios.get(url, { params: params })
// const security = axios.get(`${api.entity.security}/${this.entity.entityType}`, { params: params })
// const performance = axios.get(`${api.entity.performance}/${this.entityType}`, { params: params })
Promise.all([informationAggregation, openPort]).then(response => {
if (response[0].status === 200) {
const list = [] const list = []
informationAggregationResponse.data.data.result.forEach(r => { response[0].data.data.result.forEach(r => {
Object.keys(r).forEach(k => { Object.keys(r).forEach(k => {
const aggregation = { const aggregation = {
createTime: r[k].createTime, createTime: r[k].createTime,
@@ -142,42 +152,40 @@ export default {
} }
}) })
}) })
this.initSetTag(entityDetailTabsName.informationAggregation, list.length) this.initSetTag(entityDetailTabsName.informationAggregation, list.length)
} }
const openPortResponse = response[1].value if (response[1].status === 200) {
if (openPortResponse.status === 200) { this.initSetTag(entityDetailTabsName.openPort, response[1].data.data.result.length)
this.initSetTag(entityDetailTabsName.openPort, openPortResponse.data.data.result.length)
} }
const securityResponse = response[2].value // if (response[2].status === 200) {
if (securityResponse.status === 200) { // this.initSetTag(entityDetailTabsName.securityEvent, response[2].data.data.result.length)
this.initSetTag(entityDetailTabsName.securityEvent, securityResponse.data.data.result.length)
}
// let performanceResponse = response[3].value
// if (performanceResponse.status === 200) {
// this.initSetTag(entityDetailTabsName.performanceEvent, performanceResponse.data.data.result.length)
// } // }
// if (response[3].status === 200) {
// this.initSetTag(entityDetailTabsName.performanceEvent, response[3].data.data.result.length)
// }
this.initSetTag(entityDetailTabsName.securityEvent, 0)
this.initSetTag(entityDetailTabsName.performanceEvent, 0) this.initSetTag(entityDetailTabsName.performanceEvent, 0)
}) })
const relatedEntityParams = this.getParamsByTabType(entityDetailTabsName.relatedEntity)
// 域名解析 // 域名解析
if (this.entity.entityType === 'app') { if (this.entity.entityType === 'app') {
const ipsOfApp = axios.get(api.entity.domainNameResolutionAboutIpsOfApp, { params: relatedEntityParams }) const ipsOfApp = axios.get(api.entity.domainNameResolutionAboutIpsOfApp, { params: params })
const domainsOfApp = axios.get(api.entity.domainNameResolutionAboutDomainsOfApp, { params: relatedEntityParams }) const domainsOfApp = axios.get(api.entity.domainNameResolutionAboutDomainsOfApp, { params: params })
this.promiseData(ipsOfApp, domainsOfApp) this.promiseData(ipsOfApp, domainsOfApp)
} }
if (this.entity.entityType === 'ip') { if (this.entity.entityType === 'ip') {
const appsOfIp = axios.get(api.entity.domainNameResolutionAboutAppsOfIp, { params: relatedEntityParams }) const appsOfIp = axios.get(api.entity.domainNameResolutionAboutAppsOfIp, { params: params })
const domainsOfIp = axios.get(api.entity.domainNameResolutionAboutDomainsOfIp, { params: relatedEntityParams }) const domainsOfIp = axios.get(api.entity.domainNameResolutionAboutDomainsOfIp, { params: params })
const behaviorPattern = axios.get(api.entity.behaviorPattern, { params: relatedEntityParams }) const behaviorPattern = axios.get(api.entity.behaviorPattern, { params: params })
this.promiseData(appsOfIp, domainsOfIp, behaviorPattern) this.promiseData(appsOfIp, domainsOfIp, behaviorPattern)
} }
if (this.entity.entityType === 'domain') { if (this.entity.entityType === 'domain') {
const appsOfDomain = axios.get(api.entity.domainNameResolutionAboutAppsOfDomain, { params: relatedEntityParams }) const appsOfDomain = axios.get(api.entity.domainNameResolutionAboutAppsOfDomain, { params: params })
const ipsOfDomain = axios.get(api.entity.domainNameResolutionAboutIpsOfDomain, { params: relatedEntityParams }) const ipsOfDomain = axios.get(api.entity.domainNameResolutionAboutIpsOfDomain, { params: params })
const fqdnsOfDomain = axios.get(api.entity.domainNameResolutionAboutFQDNsOfDomain, { params: relatedEntityParams }) const fqdnsOfDomain = axios.get(api.entity.domainNameResolutionAboutFQDNsOfDomain, { params: params })
this.promiseData(appsOfDomain, ipsOfDomain, fqdnsOfDomain) this.promiseData(appsOfDomain, ipsOfDomain, fqdnsOfDomain)
} }
}, },

View File

@@ -8,8 +8,8 @@
<div class="behavior-pattern-legend__item" v-for="(data, index) in tableData" :key="index"> <div class="behavior-pattern-legend__item" v-for="(data, index) in tableData" :key="index">
<div class="legend-icon" :style="`background:${chartColorForBehaviorPattern[index%10]};`"></div> <div class="legend-icon" :style="`background:${chartColorForBehaviorPattern[index%10]};`"></div>
<div class="legend-name">{{data.name}}</div> <div class="legend-name">{{data.name}}</div>
<div class="legend-value" >{{ valueToRangeValue(data.value, unitTypes.number).join('')}}</div> <div class="legend-value" >{{ unitConvert(data.value, unitTypes.number).join('')}}</div>
<div class="legend-percent">{{ valueToRangeValue(data.percent, unitTypes.percent).join('') }}</div> <div class="legend-percent">{{ unitConvert(data.percent, unitTypes.percent).join('') }}</div>
</div> </div>
</div> </div>
<div id="entityIpRoseType" class="behavior-pattern-chart"></div> <div id="entityIpRoseType" class="behavior-pattern-chart"></div>
@@ -20,12 +20,12 @@
</template> </template>
<script> <script>
import { dateFormatByAppearance, getNowTime } from '@/utils/date-util' import { dateFormatByAppearance } from '@/utils/date-util'
import * as echarts from 'echarts' import * as echarts from 'echarts'
import { pieChartOption4 } from '@/views/charts2/charts/options/echartOption' import { pieChartOption4 } from '@/views/charts2/charts/options/echartOption'
import { shallowRef, ref } from 'vue' import { shallowRef } from 'vue'
import { entityDetailTabsName, chartColorForBehaviorPattern, unitTypes } from '@/utils/constants' import { entityDetailTabsName, chartColorForBehaviorPattern, unitTypes } from '@/utils/constants'
import { valueToRangeValue } from '@/utils/unit-convert' import unitConvert from '@/utils/unit-convert'
import axios from 'axios' import axios from 'axios'
import { api } from '@/utils/api' import { api } from '@/utils/api'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
@@ -49,20 +49,13 @@ export default {
const { query } = useRoute() const { query } = useRoute()
const entityType = query.entityType const entityType = query.entityType
const entityName = query.entityName const entityName = query.entityName
// range取 config.js 中配置的值
const dateRangeValue = DEFAULT_TIME_FILTER_RANGE.entity.behaviorPattern
const timeFilter = ref({ dateRangeValue })
const { startTime, endTime } = getNowTime(dateRangeValue)
timeFilter.value.startTime = startTime
timeFilter.value.endTime = endTime
return { return {
entityType, entityType,
entityName, entityName,
myChart: shallowRef(null), myChart: shallowRef(null),
chartColorForBehaviorPattern, chartColorForBehaviorPattern,
unitTypes, unitTypes
timeFilter
} }
}, },
async mounted () { async mounted () {
@@ -74,7 +67,7 @@ export default {
}, 200) }, 200)
}, },
methods: { methods: {
valueToRangeValue, unitConvert,
toUpperCaseByString, toUpperCaseByString,
dateFormatByAppearance, dateFormatByAppearance,
initEcharts () { initEcharts () {
@@ -137,7 +130,9 @@ export default {
}) })
}, },
async initData () { async initData () {
const params = this.getParams() const params = {
resource: this.entityName
}
this.toggleLoading(true) this.toggleLoading(true)
await axios.get(`${api.entity.behaviorPattern}`, { params: params }).then(response => { await axios.get(`${api.entity.behaviorPattern}`, { params: params }).then(response => {
const res = response.data const res = response.data
@@ -149,18 +144,22 @@ export default {
if (!this.isNoData) { if (!this.isNoData) {
const data = res.data.result const data = res.data.result
this.tableData = [] this.tableData = []
let sum = 0
if (data && data[0]) { if (data && data[0]) {
const dataObject = data[0] const dataObject = data[0]
Object.keys(dataObject).forEach(key => { Object.keys(dataObject).forEach(key => {
const value = Number(dataObject[key]) ? Number(dataObject[key]) : 0 const value = Number(dataObject[key]) ? Number(dataObject[key]) : 0
if (value !== 0 && key !== 'total') { if (value !== 0) {
sum = sum + value
this.tableData.push({ this.tableData.push({
name: key, name: key,
value: value, value: value
percent: dataObject.total ? value / dataObject.total : '-'
}) })
} }
}) })
this.tableData.forEach(item => {
item.percent = item.value / sum
})
this.tableData = this.tableData.sort(reverseSortBy('value')) this.tableData = this.tableData.sort(reverseSortBy('value'))
this.$emit('checkTag', entityDetailTabsName.behaviorPattern, this.tableData.length) this.$emit('checkTag', entityDetailTabsName.behaviorPattern, this.tableData.length)
if (this.tableData.length === 0) { if (this.tableData.length === 0) {

View File

@@ -70,15 +70,15 @@
<script> <script>
import axios from 'axios' import axios from 'axios'
import { api } from '@/utils/api' import { api } from '@/utils/api'
import { getNowTime } from '@/utils/date-util'
import chartMixin from '@/views/charts2/chart-mixin' import chartMixin from '@/views/charts2/chart-mixin'
import chartNoData from '@/views/charts/charts/ChartNoData' import chartNoData from '@/views/charts/charts/ChartNoData'
import { entityDetailTabsName } from '@/utils/constants' import { entityDetailTabsName } from '@/utils/constants'
import { ref } from 'vue'
export default { export default {
name: 'DomainNameResolution', name: 'DomainNameResolution',
mixins: [chartMixin], mixins: [chartMixin],
props: {
},
components: { components: {
chartNoData chartNoData
}, },
@@ -105,24 +105,16 @@ export default {
errorMsg2: '' errorMsg2: ''
} }
}, },
setup (props) {
// range取 config.js 中配置的值
const dateRangeValue = DEFAULT_TIME_FILTER_RANGE.entity.relatedEntity
const timeFilter = ref({ dateRangeValue })
const { startTime, endTime } = getNowTime(dateRangeValue)
timeFilter.value.startTime = startTime
timeFilter.value.endTime = endTime
return {
timeFilter
}
},
mounted () { mounted () {
this.initData() this.initData()
}, },
methods: { methods: {
initData () { initData () {
const params = this.getParams() const params = {
resource: this.entity.entityName
// startTime: getSecond(this.timeFilter.startTime),
// endTime: getSecond(this.timeFilter.endTime)
}
if (this.entity.entityType === 'app') { if (this.entity.entityType === 'app') {
const ipsOfApp = axios.get(api.entity.domainNameResolutionAboutIpsOfApp, { params: params }) const ipsOfApp = axios.get(api.entity.domainNameResolutionAboutIpsOfApp, { params: params })
const domainsOfApp = axios.get(api.entity.domainNameResolutionAboutDomainsOfApp, { params: params }) const domainsOfApp = axios.get(api.entity.domainNameResolutionAboutDomainsOfApp, { params: params })

View File

@@ -72,9 +72,8 @@ import chartMixin from '@/views/charts2/chart-mixin'
import axios from 'axios' import axios from 'axios'
import { api } from '@/utils/api' import { api } from '@/utils/api'
import { entityDetailTabsName, entityDetailTags, tagValueLabelMapping } from '@/utils/constants' import { entityDetailTabsName, entityDetailTags, tagValueLabelMapping } from '@/utils/constants'
import { dateFormatByAppearance, getNowTime } from '@/utils/date-util' import { dateFormatByAppearance } from '@/utils/date-util'
import chartNoData from '@/views/charts/charts/ChartNoData' import chartNoData from '@/views/charts/charts/ChartNoData'
import { ref } from 'vue'
export default { export default {
name: 'InformationAggregation', name: 'InformationAggregation',
@@ -84,18 +83,6 @@ export default {
loading: true loading: true
} }
}, },
setup (props) {
// range取 config.js 中配置的值
const dateRangeValue = DEFAULT_TIME_FILTER_RANGE.entity.informationAggregation
const timeFilter = ref({ dateRangeValue })
const { startTime, endTime } = getNowTime(dateRangeValue)
timeFilter.value.startTime = startTime
timeFilter.value.endTime = endTime
return {
timeFilter
}
},
mixins: [chartMixin], mixins: [chartMixin],
components: { chartNoData }, components: { chartNoData },
methods: { methods: {
@@ -121,12 +108,7 @@ export default {
this.showError = false this.showError = false
this.toggleLoading(true) this.toggleLoading(true)
this.informationAggregationList = [] this.informationAggregationList = []
const params = this.getParams() axios.get(`${api.entity.informationAggregation}/${this.entity.entityType}?resource=${this.entity.entityName}&pageSize=100&pageNo=1`).then(response => {
let timeStr = ''
if (params.startTime && params.endTime) {
timeStr = '&startTime=' + params.startTime + '&endTime=' + params.endTime
}
axios.get(`${api.entity.informationAggregation}/${this.entity.entityType}?resource=${this.entity.entityName}&pageSize=100&pageNo=1${timeStr}`).then(response => {
const res = response.data const res = response.data
if (response.status === 200) { if (response.status === 200) {
// this.isNoData = res.data.result.length === 0 // this.isNoData = res.data.result.length === 0

View File

@@ -7,7 +7,7 @@
<div class="type-data"> <div class="type-data">
<div class="type-title"> <div class="type-title">
<span class="title-mark"></span> <span class="title-mark"></span>
<span class="type-title-word">{{ $t('entities.tab.currentOpenPortsAndServices') }}</span>({{ openPortList.length }}) <span class="type-title-word">{{ $t('entities.tab.currentDevelopmentPortsAndServices') }}</span>({{ openPortList.length }})
</div> </div>
<div class="type-content"> <div class="type-content">
<div v-for="(openPort, index) in openPortList.slice(0,showOpenPortListInfo.num)" :key="index" class="data-item"> <div v-for="(openPort, index) in openPortList.slice(0,showOpenPortListInfo.num)" :key="index" class="data-item">
@@ -27,8 +27,6 @@ import chartMixin from '@/views/charts2/chart-mixin'
import { api } from '@/utils/api' import { api } from '@/utils/api'
import chartNoData from '@/views/charts/charts/ChartNoData' import chartNoData from '@/views/charts/charts/ChartNoData'
import { entityDetailTabsName } from '@/utils/constants' import { entityDetailTabsName } from '@/utils/constants'
import { ref } from 'vue'
import { getNowTime } from '@/utils/date-util'
export default { export default {
name: 'OpenPort', name: 'OpenPort',
@@ -52,21 +50,16 @@ export default {
mounted () { mounted () {
this.initData() this.initData()
}, },
setup (props) { setup () {
// range取 config.js 中配置的值
const dateRangeValue = DEFAULT_TIME_FILTER_RANGE.entity.openPort
const timeFilter = ref({ dateRangeValue })
const { startTime, endTime } = getNowTime(dateRangeValue)
timeFilter.value.startTime = startTime
timeFilter.value.endTime = endTime
return {
timeFilter
}
}, },
methods: { methods: {
initData () { initData () {
const params = this.getParams() const params = {
resource: this.entity.entityName
// startTime: getSecond(this.timeFilter.startTime),
// endTime: getSecond(this.timeFilter.endTime)
}
this.toggleLoading(true) this.toggleLoading(true)
const url = this.getUrlByEntityType(this.entity.entityType) const url = this.getUrlByEntityType(this.entity.entityType)
axios.get(url, { params: params }).then(response => { axios.get(url, { params: params }).then(response => {

View File

@@ -26,7 +26,7 @@
<div class="basic-info__item" v-if="item.eventSeverity"> <div class="basic-info__item" v-if="item.eventSeverity">
<i class="cn-icon cn-icon-severity-level"></i> <i class="cn-icon cn-icon-severity-level"></i>
<span>{{ $t('network.severity') }}&nbsp;:&nbsp;&nbsp;</span> <span>{{ $t('network.severity') }}&nbsp;:&nbsp;&nbsp;</span>
<span :test-id="`severity${index}`">{{ changeSecurity(item.eventSeverity) }}</span> <span :test-id="`severity${index}`">{{ toUpperCaseByString(item.eventSeverity) || '-' }}</span>
</div> </div>
<div class="basic-info__item"> <div class="basic-info__item">
<i class="cn-icon cn-icon-time2"></i> <i class="cn-icon cn-icon-time2"></i>
@@ -50,8 +50,8 @@
</template> </template>
<script> <script>
import { dateFormatByAppearance, getNowTime } from '@/utils/date-util' import { dateFormatByAppearance } from '@/utils/date-util'
import { eventSeverityColor, entityDetailTabsName, securityLevel } from '@/utils/constants' import { eventSeverityColor, entityDetailTabsName } from '@/utils/constants'
import unitConvert from '@/utils/unit-convert' import unitConvert from '@/utils/unit-convert'
import axios from 'axios' import axios from 'axios'
import { api } from '@/utils/api' import { api } from '@/utils/api'
@@ -60,7 +60,6 @@ import chartMixin from '@/views/charts2/chart-mixin'
import ChartError from '@/components/common/Error' import ChartError from '@/components/common/Error'
import { toUpperCaseByString } from '@/utils/tools' import { toUpperCaseByString } from '@/utils/tools'
import ChartNoData from '@/views/charts/charts/ChartNoData' import ChartNoData from '@/views/charts/charts/ChartNoData'
import { ref } from 'vue'
export default { export default {
name: 'PerformanceEvent', name: 'PerformanceEvent',
@@ -78,36 +77,33 @@ export default {
const { query } = useRoute() const { query } = useRoute()
const entityType = query.entityType const entityType = query.entityType
const entityName = query.entityName const entityName = query.entityName
// range取 config.js 中配置的值
const dateRangeValue = DEFAULT_TIME_FILTER_RANGE.entity.performanceEvent
const timeFilter = ref({ dateRangeValue })
const { startTime, endTime } = getNowTime(dateRangeValue)
timeFilter.value.startTime = startTime
timeFilter.value.endTime = endTime
return { return {
entityType, entityType,
entityName, entityName
timeFilter
} }
}, },
mounted () { mounted () {
this.initData() // this.initData()
/*
this.isNoData = true this.isNoData = true
this.$emit('checkTag', entityDetailTabsName.performanceEvent, 0) this.$emit('checkTag', entityDetailTabsName.performanceEvent, 0)
this.toggleLoading(true) this.toggleLoading(true)
const timer = setTimeout(() => { const timer = setTimeout(() => {
this.toggleLoading(false) this.toggleLoading(false)
clearInterval(timer) clearInterval(timer)
}, 200) */ }, 200)
}, },
methods: { methods: {
unitConvert, unitConvert,
toUpperCaseByString, toUpperCaseByString,
dateFormatByAppearance, dateFormatByAppearance,
initData () { initData () {
const params = this.getParams() const params = {
resource: this.entityName
// startTime: getSecond(this.timeFilter.startTime),
// endTime: getSecond(this.timeFilter.endTime)
}
this.toggleLoading(true) this.toggleLoading(true)
axios.get(`${api.entity.performance}/${this.entityType}`, { params: params }).then(response => { axios.get(`${api.entity.performance}/${this.entityType}`, { params: params }).then(response => {
const res = response.data const res = response.data
@@ -134,18 +130,6 @@ export default {
this.showError = true this.showError = true
this.errorMsg = this.errorMsgHandler(e) this.errorMsg = this.errorMsgHandler(e)
this.$emit('checkTag', entityDetailTabsName.performanceEvent, 0) this.$emit('checkTag', entityDetailTabsName.performanceEvent, 0)
},
changeSecurity (value) {
if (value) {
const obj = securityLevel.find(d => d.value === value)
let label = value
if (obj) {
label = this.$t(obj.label)
}
return label
} else {
return '-'
}
} }
} }
} }

View File

@@ -9,7 +9,7 @@
:key="item.eventId"> :key="item.eventId">
<div class="cn-detection--list"> <div class="cn-detection--list">
<div class="cn-detection__case entity-detail-security"> <div class="cn-detection__case entity-detail-security">
<div class="cn-detection__icon"></div> <div class="cn-detection__icon" :style="`background-color: ${eventSeverityColor[item.eventSecurity]}`"></div>
<div class="cn-detection__row"> <div class="cn-detection__row">
<div class="cn-detection__header"> <div class="cn-detection__header">
<span <span
@@ -17,7 +17,7 @@
class="detection-event-severity-color-block" class="detection-event-severity-color-block"
:style="`background-color: ${eventSeverityColor[item.eventSeverity]}`"> :style="`background-color: ${eventSeverityColor[item.eventSeverity]}`">
</span> </span>
<span class="detection-event-severity-block">{{ item.eventName || '-' }}</span> <span class="detection-event-severity-block">{{ toUpperCaseByString(item.securityType) || '-' }}</span>
<i class="cn-icon cn-icon-attacker"></i> <i class="cn-icon cn-icon-attacker"></i>
<span :test-id="`offender-ip${index}`">{{ item.offenderIp || '-' }}</span> <span :test-id="`offender-ip${index}`">{{ item.offenderIp || '-' }}</span>
<div class="domain">{{ item.offenderDomain }}</div> <div class="domain">{{ item.offenderDomain }}</div>
@@ -38,7 +38,7 @@
<div class="basic-info__item" v-if="item.eventSeverity"> <div class="basic-info__item" v-if="item.eventSeverity">
<i class="cn-icon cn-icon-severity-level"></i> <i class="cn-icon cn-icon-severity-level"></i>
<span>{{ $t('network.severity') }}&nbsp;:&nbsp;&nbsp;</span> <span>{{ $t('network.severity') }}&nbsp;:&nbsp;&nbsp;</span>
<span>{{ changeSecurity(item.eventSeverity) }}</span> <span>{{ toUpperCaseByString(item.eventSeverity) || '-' }}</span>
</div> </div>
<div class="basic-info__item" v-if="item.eventType"> <div class="basic-info__item" v-if="item.eventType">
<i class="cn-icon cn-icon-event-type"></i> <i class="cn-icon cn-icon-event-type"></i>
@@ -76,8 +76,8 @@
</template> </template>
<script> <script>
import { dateFormatByAppearance, getNowTime } from '@/utils/date-util' import { dateFormatByAppearance } from '@/utils/date-util'
import { eventSeverityColor, entityDetailTabsName, securityLevel } from '@/utils/constants' import { eventSeverityColor, entityDetailTabsName } from '@/utils/constants'
import unitConvert from '@/utils/unit-convert' import unitConvert from '@/utils/unit-convert'
import axios from 'axios' import axios from 'axios'
import { api } from '@/utils/api' import { api } from '@/utils/api'
@@ -85,7 +85,6 @@ import { useRoute } from 'vue-router'
import chartMixin from '@/views/charts2/chart-mixin' import chartMixin from '@/views/charts2/chart-mixin'
import { toUpperCaseByString } from '@/utils/tools' import { toUpperCaseByString } from '@/utils/tools'
import chartNoData from '@/views/charts/charts/ChartNoData' import chartNoData from '@/views/charts/charts/ChartNoData'
import { ref } from 'vue'
export default { export default {
name: 'SecurityEvent', name: 'SecurityEvent',
@@ -103,36 +102,33 @@ export default {
const { query } = useRoute() const { query } = useRoute()
const entityType = query.entityType const entityType = query.entityType
const entityName = query.entityName const entityName = query.entityName
// range取 config.js 中配置的值
const dateRangeValue = DEFAULT_TIME_FILTER_RANGE.entity.securityEvent
const timeFilter = ref({ dateRangeValue })
const { startTime, endTime } = getNowTime(dateRangeValue)
timeFilter.value.startTime = startTime
timeFilter.value.endTime = endTime
return { return {
entityType, entityType,
entityName, entityName
timeFilter
} }
}, },
mounted () { mounted () {
this.initData() // this.initData()
/*
this.isNoData = true this.isNoData = true
this.$emit('checkTag', entityDetailTabsName.securityEvent, 0) this.$emit('checkTag', entityDetailTabsName.securityEvent, 0)
this.toggleLoading(true) this.toggleLoading(true)
const timer = setTimeout(() => { const timer = setTimeout(() => {
this.toggleLoading(false) this.toggleLoading(false)
clearInterval(timer) clearInterval(timer)
}, 200) */ }, 200)
}, },
methods: { methods: {
unitConvert, unitConvert,
toUpperCaseByString, toUpperCaseByString,
dateFormatByAppearance, dateFormatByAppearance,
initData () { initData () {
const params = this.getParams() const params = {
resource: this.entityName
// startTime: getSecond(this.timeFilter.startTime),
// endTime: getSecond(this.timeFilter.endTime)
}
this.toggleLoading(true) this.toggleLoading(true)
axios.get(`${api.entity.security}/${this.entityType}`, { params: params }).then(response => { axios.get(`${api.entity.security}/${this.entityType}`, { params: params }).then(response => {
const res = response.data const res = response.data
@@ -159,18 +155,6 @@ export default {
this.isNoData = false this.isNoData = false
this.showError = true this.showError = true
this.errorMsg = this.errorMsgHandler(e) this.errorMsg = this.errorMsgHandler(e)
},
changeSecurity (value) {
if (value) {
const obj = securityLevel.find(d => d.value === value)
let label = value
if (obj) {
label = this.$t(obj.label)
}
return label
} else {
return '-'
}
} }
} }
} }

View File

@@ -12,7 +12,7 @@
import chartMixin from '@/views/charts2/chart-mixin' import chartMixin from '@/views/charts2/chart-mixin'
import { getSecond } from '@/utils/date-util' import { getSecond } from '@/utils/date-util'
import { api } from '@/utils/api' import { api } from '@/utils/api'
import { storageKey, ZH } from '@/utils/constants' import { storageKey } from '@/utils/constants'
import PopoverContent from './LinkDirectionGrid/PopoverContent' import PopoverContent from './LinkDirectionGrid/PopoverContent'
import { computeScore } from '@/utils/tools' import { computeScore } from '@/utils/tools'
import axios from 'axios' import axios from 'axios'
@@ -156,9 +156,11 @@ export default {
}) })
// 一行如果无数据则删除该行默认10*10矩阵 // 一行如果无数据则删除该行默认10*10矩阵
this.handleXRowNoData(linkGridData, 0) const rowXIndex = 0
this.handleXRowNoData(linkGridData, rowXIndex)
// 一列如果无数据则删除该列默认10*10矩阵 // 一列如果无数据则删除该列默认10*10矩阵
this.handleYRowNoData(linkGridData, 0) const rowYIndex = 0
this.handleYRowNoData(linkGridData, rowYIndex)
this.isLinkNoData = linkGridData.length === 0 this.isLinkNoData = linkGridData.length === 0
this.linkGridData = linkGridData this.linkGridData = linkGridData
} }
@@ -176,9 +178,9 @@ export default {
// 接口数据乱序,根据入方向排序,再根据同个入方向下的出方向进行排序 // 接口数据乱序,根据入方向排序,再根据同个入方向下的出方向进行排序
nextLinkData.sort((a, b) => { nextLinkData.sort((a, b) => {
if (a.inLinkDirection !== b.inLinkDirection) { if (a.inLinkDirection !== b.inLinkDirection) {
return a.inLinkDirection.localeCompare(b.inLinkDirection, ZH) return a.inLinkDirection.localeCompare(b.inLinkDirection, 'zh')
} }
return a.outLinkDirection.localeCompare(b.outLinkDirection, ZH) return a.outLinkDirection.localeCompare(b.outLinkDirection, 'zh')
}) })
this.isNextNoData = nextLinkData.length === 0 this.isNextNoData = nextLinkData.length === 0
@@ -255,9 +257,11 @@ export default {
}) })
// 一行如果无数据则删除该行默认3*3矩阵 // 一行如果无数据则删除该行默认3*3矩阵
this.handleXRowNoData(nextGridData, 0) const rowXIndex = 0
this.handleXRowNoData(nextGridData, rowXIndex)
// 一列如果无数据则删除该列默认3*3矩阵 // 一列如果无数据则删除该列默认3*3矩阵
this.handleYRowNoData(nextGridData, 0) const rowYIndex = 0
this.handleYRowNoData(nextGridData, rowYIndex)
this.isNextNoData = nextGridData.length === 0 this.isNextNoData = nextGridData.length === 0
this.nextGridData = nextGridData this.nextGridData = nextGridData
@@ -353,7 +357,7 @@ export default {
* @param index * @param index
*/ */
handleXRowNoData (data, index) { handleXRowNoData (data, index) {
if (data && data.length > 0) { if (data) {
const item = data[index] const item = data[index]
let tempList = [] let tempList = []
if (item) { if (item) {
@@ -376,7 +380,7 @@ export default {
*/ */
handleYRowNoData (data, index) { handleYRowNoData (data, index) {
const rowList = [] const rowList = []
if (data && data.length > 0) { if (data) {
data.forEach(item => { data.forEach(item => {
if (item.out[index]) { if (item.out[index]) {
if (item.out[index].noData) { if (item.out[index].noData) {

View File

@@ -37,7 +37,7 @@
</div> </div>
<div class="line-select line-header-right"> <div class="line-select line-header-right">
<div class="line-select-metric"> <div class="line-select-metric">
<span>{{$t('detections.metric')}}:</span> <span>{{$t('network.metric')}}:</span>
<div class="line-select__operation"> <div class="line-select__operation">
<el-select <el-select
size="mini" size="mini"

View File

@@ -326,7 +326,7 @@ export default {
if (tabType) { if (tabType) {
const oldCurTab = this.getUrlParam(this.curTabState.networkOverviewBeforeTab, '') const oldCurTab = this.getUrlParam(this.curTabState.networkOverviewBeforeTab, '')
const curTable = networkTable.networkOverview const curTable = networkTable.networkOverview
const tableType = this.$route.path.replace('/panel/', '') || 'networkOverview' const tableType = this.$route.params ? this.$route.params.typeName : 'networkOverview'
const metric = this.getUrlParam(this.curTabState.tableMetric, 'Bits/s') const metric = this.getUrlParam(this.curTabState.tableMetric, 'Bits/s')
const list = await getUserDrilldownTableConfig(tableType, metric) const list = await getUserDrilldownTableConfig(tableType, metric)
const tabGroup = list.filter(item => item.label === tabType) const tabGroup = list.filter(item => item.label === tabType)
@@ -493,9 +493,11 @@ export default {
} }
}) })
}) })
if (!show) { // 非滚动滚动条操作,直接覆盖之前的数据 if (val) {
this.providerOptions = res.data.list this.providerOptions = res.data.list
} else { // 滚动条操作,则将新数据和之前的数据组合 } else if (!val && !show) {
this.providerOptions = res.data.list
} else {
this.providerOptions.push(...res.data.list) this.providerOptions.push(...res.data.list)
this.appListData([], this.providerOptions) this.appListData([], this.providerOptions)
} }
@@ -517,9 +519,11 @@ export default {
} }
}) })
}) })
if (!show) { // 非滚动滚动条操作,直接覆盖之前的数据 if (val) {
this.appOptions = res.data.list this.appOptions = res.data.list
} else { // 滚动条操作,则将新数据和之前的数据组合 } else if (!val && !show) {
this.appOptions = res.data.list
} else {
this.appOptions.push(...res.data.list) this.appOptions.push(...res.data.list)
this.appListData(this.appOptions, []) this.appListData(this.appOptions, [])
} }

View File

@@ -66,7 +66,7 @@ export default {
startTime: this.timeFilter && this.timeFilter.startTime ? getSecond(this.timeFilter.startTime) : '', startTime: this.timeFilter && this.timeFilter.startTime ? getSecond(this.timeFilter.startTime) : '',
endTime: this.timeFilter && this.timeFilter.endTime ? getSecond(this.timeFilter.endTime) : '' endTime: this.timeFilter && this.timeFilter.endTime ? getSecond(this.timeFilter.endTime) : ''
} }
/* this.toggleLoading(true) /*this.toggleLoading(true)
axios.get(api.netWorkOverview.ddosEventAnalysis, { params: params }).then(response => { axios.get(api.netWorkOverview.ddosEventAnalysis, { params: params }).then(response => {
const res = response.data const res = response.data
if (response.status === 200) { if (response.status === 200) {
@@ -85,7 +85,7 @@ export default {
this.errorMsg = this.errorMsgHandler(e) this.errorMsg = this.errorMsgHandler(e)
}).finally(() => { }).finally(() => {
this.toggleLoading(false) this.toggleLoading(false)
}) */ })*/
this.toggleLoading(false) this.toggleLoading(false)
} }
}, },

View File

@@ -32,7 +32,7 @@
</div> </div>
<div class="line-select line-header-right"> <div class="line-select line-header-right">
<div class="line-select-reference-line"> <div class="line-select-reference-line">
<span>{{ $t('network.referenceLine') }}&nbsp;:&nbsp;</span> <span>{{ $t('network.referenceLine') }}:</span>
<div class="line-select__operation"> <div class="line-select__operation">
<el-select <el-select
size="mini" size="mini"
@@ -43,9 +43,7 @@
:popper-append-to-body="false" :popper-append-to-body="false"
@change="referenceSelectChange" @change="referenceSelectChange"
> >
<el-option :key="options2[0].value" :label="$t(options2[0].label)" :value="options2[0].value"></el-option> <el-option v-for="item in options2" :key="item.value" :label="item.label" :value="item.value"></el-option>
<el-option :key="options2[1].value" :label="$t(options2[1].label[0], options2[1].label[1])" :value="options2[1].value"></el-option>
<el-option :key="options2[2].value" :label="$t(options2[2].label)" :value="options2[2].value"></el-option>
</el-select> </el-select>
</div> </div>
</div> </div>
@@ -276,14 +274,6 @@ export default {
label: { label: {
formatter (params) { formatter (params) {
const arr = valueToRangeValue(params.value, unitTypes.number).join('') const arr = valueToRangeValue(params.value, unitTypes.number).join('')
const referIndex = _this.options2.findIndex(o => o.value === _this.lineRefer)
if (referIndex > -1) {
if (referIndex === 1) {
return _this.$t(_this.options2[1].label[0], _this.options2[1].label[1]) + '(' + arr + echartsData[0].unitType + ')'
} else {
return _this.$t(_this.options2[referIndex].label) + '(' + arr + echartsData[0].unitType + ')'
}
}
return _this.lineRefer + '(' + arr + echartsData[0].unitType + ')' return _this.lineRefer + '(' + arr + echartsData[0].unitType + ')'
}, },
position: 'insideStartTop', position: 'insideStartTop',

View File

@@ -289,9 +289,7 @@ import {
dbDrilldownTableConfig, dbDrilldownTableConfig,
fromRoute, fromRoute,
drillDownPanelTypeMapping, drillDownPanelTypeMapping,
commonErrorTip, commonErrorTip
ZH,
EN
} from '@/utils/constants' } from '@/utils/constants'
import axios from 'axios' import axios from 'axios'
import unitConvert, { valueToRangeValue } from '@/utils/unit-convert' import unitConvert, { valueToRangeValue } from '@/utils/unit-convert'
@@ -503,7 +501,7 @@ export default {
const currentValue = document.getElementById('tabSearchValue' + tabProp) ? document.getElementById('tabSearchValue' + tabProp).value : '' const currentValue = document.getElementById('tabSearchValue' + tabProp) ? document.getElementById('tabSearchValue' + tabProp).value : ''
const columnName = curTab ? curTab.label : '' const columnName = curTab ? curTab.label : ''
let type = 'ip' let type = 'ip'
const tableType = this.$route.path.replace('/panel/', '') || 'networkOverview' const tableType = this.$route.params ? this.$route.params.typeName : 'networkOverview'
const curTableInCode = networkTable[tableType] ? networkTable[tableType] : networkTable.networkOverview const curTableInCode = networkTable[tableType] ? networkTable[tableType] : networkTable.networkOverview
if (curTableInCode && curTableInCode.tabList) { if (curTableInCode && curTableInCode.tabList) {
const curTab = curTableInCode.tabList.find(item => item.label === columnName) const curTab = curTableInCode.tabList.find(item => item.label === columnName)
@@ -536,7 +534,7 @@ export default {
axios.get(url, { params }).then(async response => { axios.get(url, { params }).then(async response => {
if (response.status === 200) { if (response.status === 200) {
this.tabSearchColumnValueListShow = response.data.data.result this.tabSearchColumnValueListShow = response.data.data.result
if (this.$route.path.replace('/panel/', '') === fromRoute.dnsServiceInsights) { if (this.$route.params.typeName === fromRoute.dnsServiceInsights) {
if (this.dnsQtypeMapData.size === 0) { if (this.dnsQtypeMapData.size === 0) {
this.dnsQtypeMapData = await getDnsMapData('dnsQtype') this.dnsQtypeMapData = await getDnsMapData('dnsQtype')
} }
@@ -1172,10 +1170,10 @@ export default {
// 数字可按照排序的要求进行自定义,我这边产品的要求是 // 数字可按照排序的要求进行自定义,我这边产品的要求是
// 数字0->9->大写字母A->Z->小写字母a->z->中文拼音a->z // 数字0->9->大写字母A->Z->小写字母a->z->中文拼音a->z
if (/^[\u4e00-\u9fa5]$/.test(char)) { if (/^[\u4e00-\u9fa5]$/.test(char)) {
return [ZH, 300] return ['zh', 300]
} }
if (/^[a-zA-Z]$/.test(char)) { if (/^[a-zA-Z]$/.test(char)) {
return [EN, 200] return ['en', 200]
} }
if (/^[0-9]$/.test(char)) { if (/^[0-9]$/.test(char)) {
return ['number', 100] return ['number', 100]
@@ -1224,9 +1222,9 @@ export default {
if (char1 === char2) { if (char1 === char2) {
continue continue
} else { } else {
if (char1Type[0] === ZH) { if (char1Type[0] === 'zh') {
res = char2.localeCompare(char1) res = char2.localeCompare(char1)
} else if (char1Type[0] === EN) { } else if (char1Type[0] === 'en') {
res = char2.charCodeAt(0) - char1.charCodeAt(0) res = char2.charCodeAt(0) - char1.charCodeAt(0)
} else { } else {
res = char2 - char1 res = char2 - char1
@@ -1264,9 +1262,9 @@ export default {
if (char1 === char2) { if (char1 === char2) {
continue continue
} else { } else {
if (char1Type[0] === ZH) { if (char1Type[0] === 'zh') {
res = char1.localeCompare(char2) res = char1.localeCompare(char2)
} else if (char1Type[0] === EN) { } else if (char1Type[0] === 'en') {
res = char1.charCodeAt(0) - char2.charCodeAt(0) res = char1.charCodeAt(0) - char2.charCodeAt(0)
} else { } else {
res = char1 - char2 res = char1 - char2
@@ -2262,9 +2260,10 @@ export default {
this.drillDownTableConfigs = null this.drillDownTableConfigs = null
this.curTable = null this.curTable = null
this.commonColumnList = null this.commonColumnList = null
this.userId = localStorage.getItem(storageKey.userId) this.userId = localStorage.getItem(storageKey.userId)
this.drillDownTableConfigs = await combineDrilldownTableWithUserConfig() this.drillDownTableConfigs = await combineDrilldownTableWithUserConfig()
this.tableType = this.$route.path.replace('/panel/', '') || 'networkOverview' this.tableType = this.$route.params ? this.$route.params.typeName : 'networkOverview'
// 是否需要dns的qtype和rcode的数据字典 // 是否需要dns的qtype和rcode的数据字典
if (this.tableType === fromRoute.dnsServiceInsights) { if (this.tableType === fromRoute.dnsServiceInsights) {
this.dnsQtypeMapData = this.$store.getters.getDnsQtypeMapData this.dnsQtypeMapData = this.$store.getters.getDnsQtypeMapData
@@ -2346,6 +2345,8 @@ export default {
await this.saveUserLocalConfig() await this.saveUserLocalConfig()
this.getChartData() this.getChartData()
}, },
setup (props) {
},
beforeUnmount () { beforeUnmount () {
// 以下元素,检测到内存并未释放 // 以下元素,检测到内存并未释放
this.unitConvert = null this.unitConvert = null

View File

@@ -322,7 +322,7 @@ export default {
const tabType = 'network.applicationCategories' const tabType = 'network.applicationCategories'
const oldCurTab = this.getUrlParam(this.curTabState.networkOverviewBeforeTab, '') const oldCurTab = this.getUrlParam(this.curTabState.networkOverviewBeforeTab, '')
const curTable = networkTable.networkAppPerformance const curTable = networkTable.networkAppPerformance
const tableType = this.$route.path.replace('/panel/', '') || 'networkOverview' const tableType = this.$route.params ? this.$route.params.typeName : 'networkOverview'
const metric = this.getUrlParam(this.curTabState.tableMetric, 'Bits/s') const metric = this.getUrlParam(this.curTabState.tableMetric, 'Bits/s')
const list = await getUserDrilldownTableConfig(tableType, metric) const list = await getUserDrilldownTableConfig(tableType, metric)
const tabGroup = list.filter(item => item.label === tabType) const tabGroup = list.filter(item => item.label === tabType)

View File

@@ -150,7 +150,7 @@ export default {
limit: 10, limit: 10,
type: this.metric type: this.metric
} }
/* axios.get(api.npm.events.dimensionEvents, { params }).then(res => { /*axios.get(api.npm.events.dimensionEvents, { params }).then(res => {
if (res.status === 200) { if (res.status === 200) {
this.showError = false this.showError = false
if (!res.data.data.result || res.data.data.result.length === 0) { if (!res.data.data.result || res.data.data.result.length === 0) {
@@ -168,7 +168,7 @@ export default {
this.errorMsg = this.errorMsgHandler(e) this.errorMsg = this.errorMsgHandler(e)
}).finally(() => { }).finally(() => {
this.toggleLoading(false) this.toggleLoading(false)
}) */ })*/
this.isNoData = true this.isNoData = true
this.toggleLoading(false) this.toggleLoading(false)
}, },

View File

@@ -110,7 +110,7 @@ export default {
startTime: getSecond(this.timeFilter.startTime), startTime: getSecond(this.timeFilter.startTime),
endTime: getSecond(this.timeFilter.endTime) endTime: getSecond(this.timeFilter.endTime)
} }
/* this.toggleLoading(true) /*this.toggleLoading(true)
axios.get(api.npm.events.recentEvents, { params: params }).then(response => { axios.get(api.npm.events.recentEvents, { params: params }).then(response => {
const res = response.data const res = response.data
if (response.status === 200) { if (response.status === 200) {
@@ -151,7 +151,7 @@ export default {
this.errorMsg = this.errorMsgHandler(e) this.errorMsg = this.errorMsgHandler(e)
}).finally(() => { }).finally(() => {
this.toggleLoading(false) this.toggleLoading(false)
}) */ })*/
this.isNoData = true this.isNoData = true
this.toggleLoading(false) this.toggleLoading(false)
}, },

View File

@@ -12,15 +12,15 @@
placeholder=" " placeholder=" "
:popper-append-to-body="false" :popper-append-to-body="false"
> >
<el-option value="Server" :label="$t('overall.server')">{{$t('overall.server')}}</el-option> <el-option value="Server">Server</el-option>
<el-option value="Client" :label="$t('overall.client')">{{$t('overall.client')}}</el-option> <el-option value="Client">Client</el-option>
</el-select> </el-select>
<el-select <el-select
size="mini" size="mini"
v-model="location" v-model="location"
class="map-select map-select__location" class="map-select map-select__location"
clearable clearable
:placeholder="$t('overall.country')" placeholder="All"
filterable filterable
popper-class="map-select-down" popper-class="map-select-down"
:popper-append-to-body="false" :popper-append-to-body="false"

View File

@@ -21,7 +21,7 @@
<template #default="scope" :column="item"> <template #default="scope" :column="item">
<div class="data-recent-table"> <div class="data-recent-table">
<template v-if="item.prop === 'eventSeverity'"> <template v-if="item.prop === 'eventSeverity'">
<span class="data-recent-table-severity" :class="scope.row[item.prop]" :test-id="`eventSeverity-${scope.row.eventSeverity}-${scope.$index}`">{{ getEventSeverity(scope.row[item.prop]) }}</span> <span class="data-recent-table-severity" :class="scope.row[item.prop]" :test-id="`eventSeverity-${scope.row.eventSeverity}-${scope.$index}`">{{scope.row[item.prop]}}</span>
</template> </template>
<template v-else-if="item.prop === 'eventKey'"> <template v-else-if="item.prop === 'eventKey'">
<span class="data-recent-table-entity click-active" @click="jumpPage(scope.row)" :test-id="`eventKey-${splitEventKey(scope.row.eventKey)}-${scope.$index}`">{{splitEventKey(scope.row[item.prop])}}</span> <span class="data-recent-table-entity click-active" @click="jumpPage(scope.row)" :test-id="`eventKey-${splitEventKey(scope.row.eventKey)}-${scope.$index}`">{{splitEventKey(scope.row[item.prop])}}</span>
@@ -57,7 +57,6 @@ import ChartError from '@/components/common/Error'
import axios from 'axios' import axios from 'axios'
import { dataForNpmRecentEvents } from '@/utils/static-data' import { dataForNpmRecentEvents } from '@/utils/static-data'
import { beforeRouterPush } from '@/utils/tools' import { beforeRouterPush } from '@/utils/tools'
import { securityLevel } from '@/utils/constants'
export default { export default {
name: 'NpmRecentEvents', name: 'NpmRecentEvents',
@@ -159,14 +158,6 @@ export default {
this.isNoData = false this.isNoData = false
this.showError = true this.showError = true
this.errorMsg = this.errorMsgHandler(res) this.errorMsg = this.errorMsgHandler(res)
},
getEventSeverity (severity) {
const obj = securityLevel.find(d => d.value === severity)
if (obj) {
return this.$t(obj.label)
} else {
return severity
}
} }
}, },
mounted () { mounted () {

View File

@@ -3,7 +3,7 @@
<div class="npm-traffic-line-header"> <div class="npm-traffic-line-header">
<div class="npm-traffic-line-title"></div> <div class="npm-traffic-line-title"></div>
<div class="line-select-metric"> <div class="line-select-metric">
<span>{{$t('detections.metric')}}:</span> <span>{{$t('network.metric')}}:</span>
<div class="line-select__operation"> <div class="line-select__operation">
<el-select <el-select
size="mini" size="mini"

View File

@@ -257,8 +257,7 @@ export const pieChartOption4 = {
show: false, show: false,
position: 'middle', position: 'middle',
formatter: '{b}: {c}' formatter: '{b}: {c}'
}, }
barMinHeight: 5
}], }],
animation: false animation: false
} }

View File

@@ -1,36 +1,31 @@
<template> <template>
<div class="detection-filter-case"> <div class="detection-filter-case">
<div class="filter-case__header">{{$t('detections.filters')}}</div> <div class="new-detection-filter-title">{{$t('detections.filters')}}</div>
<div class="no-data" v-if="isNoData">{{ $t('npm.noData') }}</div> <div class="no-data" v-if="isNoData">{{ $t('npm.noData') }}</div>
<template v-for="(filter, index) in filterData" :key="index"> <template v-for="(filter, index) in filterData" :key="index">
<div class="detection-filter" v-show="filter.data.length > 0"> <div class="detection-filter" v-show="filter.data.length > 0">
<div class="filter__header">{{filter.title}}</div> <div class="filter__header" @click="filter.collapse = !filter.collapse">
<span class="new-detection-filter-header-title">{{filter.title}}</span>
<div class="filter__body" style="position: relative"> <i class="el-icon-arrow-right new-detection-filter-icon" :class="{ 'arrow-rotate': !filter.collapse }"></i>
<loading :loading="loadingLeft" style="top: -5px;"></loading> </div>
<el-collapse-transition>
<div class="filter__body-item" <div class="filter__body" v-show="!filter.collapse">
v-for="(data, i) in filter.data.slice(0, filter.showIndex)" <el-checkbox-group v-model="filter.value">
:key="i" <template v-for="(d, i) in filter.data" :key="i">
@click="clickFilterItem(data.label, filter.column, index)"> <el-checkbox :label="d.value" v-if="!filter.showIndex || filter.showIndex >= i">
<div class="filter__body-item-left"> <div class="filter__checkbox-label">
<div class="filter__body-item-left-index">{{ i+1 }}</div> <div style="display: flex">
<div class="filter__body-item-left-label"> <span class="severity-color-block" v-if="filter.column === 'eventSeverity'" :style="`background-color: ${eventSeverityColor[d.value]}`"></span>
<el-tooltip :content="data.label" placement="top" effect="light" :disabled="disabledLabel"> <span :style="filter.column === 'eventSeverity' ? 'padding-left: 10px' : ''">{{d.label}}</span>
<span @mouseenter="handleMouse(`filter${index}${i}`)" :id="`filter${index}${i}`"> </div>
<span>{{ data.label }}</span> <div v-if="d.count || d.count === 0">{{d.count}}</div>
</span> </div>
</el-tooltip> </el-checkbox>
</div> </template>
</div> </el-checkbox-group>
<div class="filter__body-item-right">{{ data.count }}</div> <div class="filter__more" v-if="filter.showMore" @click="showMore(filter)">{{$t('overall.showMore')}}</div>
</div> </div>
</div> </el-collapse-transition>
<div v-show="filter.showMore" @click="showMore(filter)"
:class="filter.showDisabled? 'filter-no-show-more' : 'filter-show-more'">
{{ $t('overall.showMore') }}
</div>
<div class="filter-hr"></div>
</div> </div>
</template> </template>
</div> </div>
@@ -47,36 +42,13 @@ export default {
}, },
data () { data () {
return { return {
eventSeverityColor, eventSeverityColor
disabledLabel: true
} }
}, },
methods: { methods: {
showMore (filter) { showMore (filter) {
filter.showIndex && (filter.showIndex += 5) filter.showIndex && (filter.showIndex += 10)
filter.showIndex >= (filter.data.length - 1) && (filter.showDisabled = true) filter.showIndex >= (filter.data.length - 1) && (filter.showMore = false)
},
clickFilterItem (name, data, index) {
if (index === 0) {
let status = 0
if (name === this.$t('detections.active')) {
status = '0'
} else if (name === this.$t('detections.ended')) {
status = '1'
}
this.$emit('filter', status, data)
} else {
this.$emit('filter', name, data)
}
},
handleMouse (id) {
const dom = document.getElementById(id)
if (dom) {
const width = document.getElementById(id).offsetWidth
this.disabledLabel = width < 180
} else {
this.disabledLabel = true
}
} }
}, },
computed: { computed: {

View File

@@ -1,7 +1,7 @@
<template> <template>
<div class="explorer-search explorer-search--show-list"> <div class="explorer-search explorer-search--show-list">
<div class="explorer-search__input-case explorer-search__input-case--question-mark-in-line" style="position: relative"> <div class="explorer-search__input-case explorer-search__input-case--question-mark-in-line">
<div class="explorer-search__input entity__search"> <div class="explorer-search__input">
<advanced-search <advanced-search
ref="search" ref="search"
:column-list="columnList[pageType]" :column-list="columnList[pageType]"
@@ -13,36 +13,6 @@
@search="search" @search="search"
></advanced-search> ></advanced-search>
</div> </div>
<div class="explorer-search__foot-list" v-ele-click-outside="esc">
<div class="explorer-search__block" @click="triggerHistory">
<i class="cn-icon cn-icon-time"></i>
<div class="search-dividing-line"></div>
</div>
<transition name="el-zoom-in-top">
<div class="search__history" v-if="showHistory">
<div class="history__items-new">
<el-table
:data="history"
scrollbar-always-on="false"
@row-click="selectHistory"
style="overflow-x: unset"
empty-text=" "
>
<el-table-column prop="str" :label="$t('overall.expression')" min-width="560" />
<el-table-column prop="date" :label="$t('overall.time')" sortable width="200">
<template #default="scope">
<span>{{ changeTimeByDate(scope.row.date) }}</span>
</template>
</el-table-column>
</el-table>
</div>
<div class="clear-all">
<span @click="clearHistory" v-if="!$_.isEmpty(history)">{{$t('entity.clearAll')}}</span>
<div v-else>{{$t('overall.noRecords')}}</div>
</div>
</div>
</transition>
</div>
<!-- <div class="search-symbol-inline">--> <!-- <div class="search-symbol-inline">-->
<!-- <i class="cn-icon cn-icon-help"></i>--> <!-- <i class="cn-icon cn-icon-help"></i>-->
<!-- </div>--> <!-- </div>-->
@@ -55,9 +25,6 @@ import AdvancedSearch from '@/components/advancedSearch/Index'
import { schemaDetectionSecurity } from '@/utils/static-data' import { schemaDetectionSecurity } from '@/utils/static-data'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import { ref } from 'vue' import { ref } from 'vue'
import { storageKey } from '@/utils/constants'
import _ from 'lodash'
import { changeTimeByDate } from '@/utils/tools'
export default { export default {
name: 'DetectionSearch', name: 'DetectionSearch',
props: { props: {
@@ -128,9 +95,7 @@ export default {
label: 'OR' label: 'OR'
} }
], ],
showList: true, showList: true
showHistory: false,
history: []
} }
}, },
emits: ['search'], emits: ['search'],
@@ -157,66 +122,70 @@ export default {
} }
this.$emit('search', metaList, sql) this.$emit('search', metaList, sql)
}, */ }, */
changeTimeByDate, search ({ q, metaList }) {
search ({ str, q, metaList }) {
if (str) {
// 加入搜索记录将记录数量控制在30以内
const oldHistory = localStorage.getItem(storageKey.detectionSearchHistory)
let arr = []
const newItem = { str, date: this.dateFormatByAppearance(new Date()) }
if (!_.isEmpty(oldHistory)) {
const oldArr = JSON.parse(oldHistory)
if (str === oldArr[0].str) {
oldArr[0].date = this.dateFormatByAppearance(new Date())
} else {
oldArr.unshift(newItem)
}
arr = [...oldArr]
if (arr.length > 30) {
arr = arr.slice(0, 30)
}
} else {
arr.push(newItem)
}
localStorage.setItem(storageKey.detectionSearchHistory, JSON.stringify(arr))
}
this.$emit('search', { q, metaList }) this.$emit('search', { q, metaList })
}, },
changeParams (params) { changeParams (params) { // params: { column: columnName, oldValue: [...], newValue: [...] }
this.$refs.search.addParams(params) // 向下传递时需要再转换一次param格式为[{column, operator, value}, ...]
}, if (params.oldValue.length === 0 && params.newValue.length === 1) {
selectHistory (row) { // 1.参数值数量从0到1直接addParams
this.$refs.search.setStr(row.str) const p = {
this.showHistory = false column: params.column,
operator: '=',
value: params.newValue
}
this.$refs.search.addParams([p])
} else if (params.oldValue.length === 1 && params.newValue.length === 0) {
// 2.参数值数量从1到0直接removeParams
const p = {
column: params.column,
operator: '=',
value: params.oldValue
}
this.$refs.search.removeParams([p])
} else if (params.oldValue.length === 2 && params.newValue.length === 1) {
// 3.参数值数量从多到1operator由'in'改为'='
const oldParam = {
column: params.column,
operator: 'IN',
value: params.oldValue
}
const newParam = {
column: params.column,
operator: '=',
value: params.newValue
}
this.$refs.search.changeParams([{ newParam, oldParam }])
} else if (params.oldValue.length === 1 && params.newValue.length === 2) {
// 4.参数值数量从1到多, operator由'='改为'in'
const oldParam = {
column: params.column,
operator: '=',
value: params.oldValue
}
const newParam = {
column: params.column,
operator: 'IN',
value: params.newValue
}
this.$refs.search.changeParams([{ newParam, oldParam }])
} else {
// 5.参数值数量从多到多加1或者减1
const oldParam = {
column: params.column,
operator: 'IN',
value: params.oldValue
}
const newParam = {
column: params.column,
operator: 'IN',
value: params.newValue
}
this.$refs.search.changeParams([{ newParam, oldParam }])
}
this.$nextTick(() => { this.$nextTick(() => {
if (this.$refs.search.$refs.textMode) { this.emitter.emit('advanced-search')
this.$refs.search.$refs.textMode.focus()
}
}) })
if (this.showList) {
this.$nextTick(() => {
this.emitter.emit('advanced-search')
})
}
},
clearHistory () {
localStorage.setItem(storageKey.detectionSearchHistory, '')
this.history = []
},
triggerHistory () {
this.showHistory = !this.showHistory
if (this.showHistory) {
const history = localStorage.getItem(storageKey.detectionSearchHistory)
if (!_.isEmpty(history)) {
this.history = JSON.parse(history)
}
}
},
esc () {
const timer = setTimeout(() => {
this.showHistory = false
clearTimeout(timer)
}, 100)
} }
} }
} }

View File

@@ -4,7 +4,7 @@
<div class="explorer-top-tools explorer-detection-top-tools"> <div class="explorer-top-tools explorer-detection-top-tools">
<div class="explorer-top-tools-title">{{$t('overall.detections')}}</div> <div class="explorer-top-tools-title">{{$t('overall.detections')}}</div>
<div style="display: flex"> <div style="display: flex">
<div class="explorer-top-tools-block" @click="jumpNewDetetion" v-if="hasPermission('detectionPolicy')"> <div class="explorer-top-tools-block" @click="jumpNewDetetion">
<i class="cn-icon cn-icon-configure-policies detection-icon-setting"></i> <i class="cn-icon cn-icon-configure-policies detection-icon-setting"></i>
<span>{{$t('config.detections.configurePolicies')}}</span> <span>{{$t('config.detections.configurePolicies')}}</span>
</div> </div>
@@ -21,12 +21,13 @@
:end-time="timeFilter.endTime"/> :end-time="timeFilter.endTime"/>
</div> </div>
</div> </div>
<div style="width: 100%; padding-bottom: 50px;"> <div style="width: 100%;padding-bottom: 47px;">
<chart-tabs :data="tabsData" router></chart-tabs> <chart-tabs :data="tabsData" router></chart-tabs>
</div> </div>
<!-- 搜索组件 --> <!-- 搜索组件 -->
<detection-search <detection-search
class="detection-border"
ref="search" ref="search"
:page-type="pageType" :page-type="pageType"
@search="search" @search="search"
@@ -47,7 +48,6 @@
:filter-data="filterData[pageType]" :filter-data="filterData[pageType]"
:q="q" :q="q"
:time-filter="timeFilter" :time-filter="timeFilter"
@filter="getFilter"
></detection-filter> ></detection-filter>
<div class="detection__list"> <div class="detection__list">
@@ -138,8 +138,6 @@ import { useRoute } from 'vue-router'
import Loading from '@/components/common/Loading' import Loading from '@/components/common/Loading'
import ChartTabs from '@/components/common/ChartTabs' import ChartTabs from '@/components/common/ChartTabs'
import { useStore } from 'vuex' import { useStore } from 'vuex'
import { tooLongFormatter } from '@/views/charts/charts/tools'
import { format } from 'echarts'
export default { export default {
name: 'Index', name: 'Index',
@@ -174,12 +172,12 @@ export default {
// } // }
], ],
chartInit: [], chartInit: [],
// pageObj: { pageObj: {
// pageNo: 1, pageNo: 1,
// pageSize: defaultPageSize, pageSize: defaultPageSize,
// total: 0, total: 0,
// resetPageNo: true resetPageNo: true
// }, },
q: '', q: '',
detectionPageType, detectionPageType,
filterData: { filterData: {
@@ -190,7 +188,6 @@ export default {
topColumn: 'status', topColumn: 'status',
collapse: false, collapse: false,
value: [], // value之间是or的关系 value: [], // value之间是or的关系
showMore: false,
data: [] // 从接口动态获取,本项在获得数据后需要特殊处理左边框颜色 data: [] // 从接口动态获取,本项在获得数据后需要特殊处理左边框颜色
}, },
{ {
@@ -199,7 +196,6 @@ export default {
topColumn: 'severity', topColumn: 'severity',
collapse: false, collapse: false,
value: [], // value之间是or的关系 value: [], // value之间是or的关系
showMore: false,
data: [] // 从接口动态获取,本项在获得数据后需要特殊处理左边框颜色 data: [] // 从接口动态获取,本项在获得数据后需要特殊处理左边框颜色
}, },
{ {
@@ -208,9 +204,6 @@ export default {
topColumn: 'event_type', topColumn: 'event_type',
collapse: false, collapse: false,
value: [], value: [],
showMore: true,
showDisabled: true,
showIndex: 5, // index作为showMore分割从1开始而非0
data: [] // 从接口动态获取 data: [] // 从接口动态获取
}, },
{ {
@@ -220,21 +213,43 @@ export default {
collapse: false, collapse: false,
value: [], value: [],
showMore: true, showMore: true,
showDisabled: true, showIndex: 9,
showIndex: 5,
data: [] // 从接口动态获取 data: [] // 从接口动态获取
}, },
// {
// title: this.$t('detections.victimLocation'),
// column: 'victimLocationCountry',
// collapse: false,
// value: [],
// showMore: false,
// showIndex: 9,
// data: [
// {
// label: 'China',
// value: 'china',
// count: 50
// }
// ] // 从接口动态获取
// },
{ {
title: this.$t('detections.offenderIp'), title: this.$t('detections.offenderIp'),
column: 'offenderIP', column: 'offenderIP',
topColumn: 'offender_ip', topColumn: 'offender_ip',
collapse: false, collapse: false,
value: [], value: [],
showMore: true, showMore: false,
showDisabled: true, showIndex: 9,
showIndex: 5,
data: [] // 从接口动态获取 data: [] // 从接口动态获取
} }
// {
// title: this.$t('detections.offenderLocation'),
// column: 'offenderLocationCountry',
// collapse: false,
// value: [],
// showMore: false,
// showIndex: 9,
// data: [] // 从接口动态获取
// }
], ],
performanceEvent: [ performanceEvent: [
{ {
@@ -271,8 +286,7 @@ export default {
isStatisticsActiveAttackNoData: false, isStatisticsActiveAttackNoData: false,
loading: false, loading: false,
oldActiveEntitySearchValue: '', oldActiveEntitySearchValue: '',
initFlag: true, // 初始化标识初始化时保证mounted执行 initFlag: true // 初始化标识初始化时保证mounted执行
detectionChart:shallowRef(null)
} }
}, },
methods: { methods: {
@@ -280,11 +294,6 @@ export default {
axios.get(api.detection[this.pageType].statusStatistics, { params }).then(res => { axios.get(api.detection[this.pageType].statusStatistics, { params }).then(res => {
if (res.status === 200) { if (res.status === 200) {
const data = res.data.data.result const data = res.data.data.result
if (data && data.length > 0) {
data.sort((a, b) => {
return Number(b.count) - Number(a.count)
})
}
this.filterData[this.pageType][0].data = data.map(r => { this.filterData[this.pageType][0].data = data.map(r => {
let label = '' let label = ''
if (r.status === '0') { if (r.status === '0') {
@@ -379,11 +388,6 @@ export default {
initEventSeverityData (params) { initEventSeverityData (params) {
axios.get(api.detection[this.pageType].severityStatistics, { params }).then(res => { axios.get(api.detection[this.pageType].severityStatistics, { params }).then(res => {
const data = res.data.data.result const data = res.data.data.result
if (data && data.length > 0) {
data.sort((a, b) => {
return Number(b.count) - Number(a.count)
})
}
this.statisticsSeverityData = data this.statisticsSeverityData = data
if (!this.$_.isEmpty(data)) { if (!this.$_.isEmpty(data)) {
this.filterData[this.pageType][1].data = data.map(r => ({ label: r.severity, value: r.severity, count: r.count })) this.filterData[this.pageType][1].data = data.map(r => ({ label: r.severity, value: r.severity, count: r.count }))
@@ -406,7 +410,6 @@ export default {
if (this.pageType === 'performanceEvent') { if (this.pageType === 'performanceEvent') {
vm.filterData.performanceEvent[0].value = vm.triggerFilterDataValue(vm.filterData.performanceEvent[0].value, e.data.name) vm.filterData.performanceEvent[0].value = vm.triggerFilterDataValue(vm.filterData.performanceEvent[0].value, e.data.name)
} else if (this.pageType === 'securityEvent') { } else if (this.pageType === 'securityEvent') {
this.getFilter(e.data.name, vm.filterData.securityEvent[1].column)
vm.filterData.securityEvent[1].value = vm.triggerFilterDataValue(vm.filterData.securityEvent[1].value, e.data.name) vm.filterData.securityEvent[1].value = vm.triggerFilterDataValue(vm.filterData.securityEvent[1].value, e.data.name)
} }
}) })
@@ -427,11 +430,6 @@ export default {
value: r.eventType, value: r.eventType,
count: r.count count: r.count
})) }))
const { showMore, showIndex, showDisabled } = this.computeFilterPage(this.filterData[this.pageType][2].data)
this.filterData[this.pageType][2].showMore = showMore
this.filterData[this.pageType][2].showIndex = showIndex
this.filterData[this.pageType][2].showDisabled = showDisabled
const chartDom = document.getElementById(`detectionCategoryPer${this.pageType}`) const chartDom = document.getElementById(`detectionCategoryPer${this.pageType}`)
let detectionChart = echarts.getInstanceByDom(chartDom) let detectionChart = echarts.getInstanceByDom(chartDom)
if (detectionChart) { if (detectionChart) {
@@ -443,15 +441,6 @@ export default {
securityTypeOption.series[0].data = data.map(d => { securityTypeOption.series[0].data = data.map(d => {
return { value: d.count, name: d.eventType } return { value: d.count, name: d.eventType }
}) })
if (chartDom) {
let oneColumnWidth = (chartDom.clientWidth * 0.56) - 30
if (data.length > 6) {
oneColumnWidth = (chartDom.clientWidth * 0.56) / 2 - 30
}
securityTypeOption.legend.formatter = function (name) {
return format.truncateText(name, oneColumnWidth, '12px')
}
}
detectionChart.setOption(securityTypeOption) detectionChart.setOption(securityTypeOption)
const vm = this const vm = this
@@ -463,9 +452,6 @@ export default {
}).catch(e => { }).catch(e => {
console.error(e) console.error(e)
this.filterData[this.pageType][2].data = [] this.filterData[this.pageType][2].data = []
this.filterData[this.pageType][2].showMore = false
this.filterData[this.pageType][2].showIndex = 5
this.filterData[this.pageType][2].showDisabled = true
this.$message.error(this.errorMsgHandler(e)) this.$message.error(this.errorMsgHandler(e))
}) })
}, },
@@ -481,45 +467,28 @@ export default {
count: r.count count: r.count
})) }))
this.isCheckFilterByQ(params, 2) this.isCheckFilterByQ(params, 2)
const { showMore, showIndex, showDisabled } = this.computeFilterPage(this.filterData[this.pageType][2].data)
this.filterData[this.pageType][2].showMore = showMore
this.filterData[this.pageType][2].showIndex = showIndex
this.filterData[this.pageType][2].showDisabled = showDisabled
const chartDom = document.getElementById(`detectionCategoryPer${this.pageType}`) const chartDom = document.getElementById(`detectionCategoryPer${this.pageType}`)
this.detectionChart = echarts.getInstanceByDom(chartDom) let detectionChart = echarts.getInstanceByDom(chartDom)
if (this.detectionChart) { if (detectionChart) {
echarts.dispose(this.detectionChart) echarts.dispose(detectionChart)
} }
this.detectionChart = echarts.init(chartDom) detectionChart = echarts.init(chartDom)
//this.chartInit.push(shallowRef(detectionChart)) this.chartInit.push(shallowRef(detectionChart))
const securityTypeOption = this.$_.cloneDeep(pieForSeverity) const securityTypeOption = this.$_.cloneDeep(pieForSeverity)
securityTypeOption.series[0].data = data.map(d => { securityTypeOption.series[0].data = data.map(d => {
return { value: d.count, name: d.eventType, itemStyle: { color: getAttackColor(d.eventType) } } return { value: d.count, name: d.eventType, itemStyle: { color: getAttackColor(d.eventType) } }
}) })
if (chartDom) { detectionChart.setOption(securityTypeOption)
let oneColumnWidth = (chartDom.clientWidth * 0.56) - 30
if (data.length > 6) {
oneColumnWidth = (chartDom.clientWidth * 0.56) / 2 - 30
}
securityTypeOption.legend.formatter = function (name) {
return format.truncateText(name, oneColumnWidth, '12px')
}
}
this.detectionChart.setOption(securityTypeOption)
const vm = this const vm = this
this.detectionChart.off('click') detectionChart.off('click')
this.detectionChart.on('click', e => { detectionChart.on('click', e => {
this.getFilter(e.data.name, vm.filterData.securityEvent[2].column)
vm.filterData.securityEvent[2].value = vm.triggerFilterDataValue(vm.filterData.securityEvent[2].value, e.data.name) vm.filterData.securityEvent[2].value = vm.triggerFilterDataValue(vm.filterData.securityEvent[2].value, e.data.name)
}) })
} }
}).catch(e => { }).catch(e => {
console.error(e) console.error(e)
this.filterData[this.pageType][2].data = [] this.filterData[this.pageType][2].data = []
this.filterData[this.pageType][2].showMore = false
this.filterData[this.pageType][2].showIndex = 5
this.filterData[this.pageType][2].showDisabled = true
this.$message.error(this.errorMsgHandler(e)) this.$message.error(this.errorMsgHandler(e))
}) })
}, },
@@ -535,10 +504,9 @@ export default {
count: r.count count: r.count
})) }))
this.isCheckFilterByQ(params, 4) this.isCheckFilterByQ(params, 4)
const { showMore, showIndex, showDisabled } = this.computeFilterPage(this.filterData[this.pageType][4].data) const { showMore, showIndex } = this.computeFilterPage(this.filterData[this.pageType][4].data)
this.filterData[this.pageType][4].showMore = showMore this.filterData[this.pageType][4].showMore = showMore
this.filterData[this.pageType][4].showIndex = showIndex this.filterData[this.pageType][4].showIndex = showIndex
this.filterData[this.pageType][4].showDisabled = showDisabled
const chartDom = document.getElementById(`detectionActiveAttacker${this.pageType}`) const chartDom = document.getElementById(`detectionActiveAttacker${this.pageType}`)
let detectionChart = echarts.getInstanceByDom(chartDom) let detectionChart = echarts.getInstanceByDom(chartDom)
@@ -558,18 +526,14 @@ export default {
const vm = this const vm = this
detectionChart.off('click') detectionChart.off('click')
detectionChart.on('click', e => { detectionChart.on('click', e => {
if (e.data) { vm.filterData.securityEvent[4].value = vm.triggerFilterDataValue(vm.filterData.securityEvent[4].value, e.data[1])
vm.getFilter(e.data[1], vm.filterData.securityEvent[4].column)
vm.filterData.securityEvent[4].value = vm.triggerFilterDataValue(vm.filterData.securityEvent[4].value, e.data[1])
}
}) })
} }
}).catch(e => { }).catch(e => {
console.error(e) console.error(e)
this.filterData[this.pageType][4].data = [] this.filterData[this.pageType][4].data = []
this.filterData[this.pageType][4].showMore = false this.filterData[this.pageType][4].showMore = false
this.filterData[this.pageType][4].showIndex = 5 this.filterData[this.pageType][4].showIndex = 9
this.filterData[this.pageType][4].showDisabled = true
this.$message.error(this.errorMsgHandler(e)) this.$message.error(this.errorMsgHandler(e))
}) })
}, },
@@ -579,16 +543,14 @@ export default {
const data = res.data.data.result const data = res.data.data.result
this.filterData[this.pageType][3].data = data.map(r => ({ label: r.victimIp, value: r.victimIp, count: r.count })) this.filterData[this.pageType][3].data = data.map(r => ({ label: r.victimIp, value: r.victimIp, count: r.count }))
this.isCheckFilterByQ(params, 3) this.isCheckFilterByQ(params, 3)
const { showMore, showIndex, showDisabled } = this.computeFilterPage(this.filterData[this.pageType][3].data) const { showMore, showIndex } = this.computeFilterPage(this.filterData[this.pageType][3].data)
this.filterData[this.pageType][3].showMore = showMore this.filterData[this.pageType][3].showMore = showMore
this.filterData[this.pageType][3].showIndex = showIndex this.filterData[this.pageType][3].showIndex = showIndex
this.filterData[this.pageType][3].showDisabled = showDisabled
}).catch(e => { }).catch(e => {
console.error(e) console.error(e)
this.filterData[this.pageType][3].data = [] this.filterData[this.pageType][3].data = []
this.filterData[this.pageType][3].showMore = false this.filterData[this.pageType][3].showMore = false
this.filterData[this.pageType][3].showIndex = 5 this.filterData[this.pageType][3].showIndex = 9
this.filterData[this.pageType][3].showDisabled = true
this.$message.error(this.errorMsgHandler(e)) this.$message.error(this.errorMsgHandler(e))
}) })
}, },
@@ -669,9 +631,8 @@ export default {
}, },
computeFilterPage (data) { computeFilterPage (data) {
return { return {
showMore: data.length > 0, showMore: data.length > 10,
showDisabled: data.length <= 5, showIndex: 9
showIndex: 5
} }
}, },
queryList (q) { queryList (q) {
@@ -755,7 +716,7 @@ export default {
this.q = '' this.q = ''
this.metaList = [] this.metaList = []
} }
if (this.pageObj.resetPageNo && !this.initFlag) { if (this.pageObj.resetPageNo) {
this.pageObj.pageNo = 1 this.pageObj.pageNo = 1
} else { } else {
this.pageObj.resetPageNo = true this.pageObj.resetPageNo = true
@@ -813,11 +774,11 @@ export default {
this.search(this.metaList, this.q) this.search(this.metaList, this.q)
}, },
pageNo (val) { pageNo (val) {
this.pageObj.pageNo = val || 1
this.pageObj.resetPageNo = false
// 初始化时mounted和pageNo都会调用列表接口且pageNo先执行 // 初始化时mounted和pageNo都会调用列表接口且pageNo先执行
// 初始化保证mounted执行后续pageNo变动则不影响接口调用 // 初始化保证mounted执行后续pageNo变动则不影响接口调用
if (!this.initFlag) { if (!this.initFlag) {
this.pageObj.pageNo = val || 1
this.pageObj.resetPageNo = false
this.search(this.metaList, this.q) this.search(this.metaList, this.q)
} }
}, },
@@ -842,28 +803,10 @@ export default {
}, },
resize () { resize () {
this.chartInit.forEach(e => { e.value.resize() }) this.chartInit.forEach(e => { e.value.resize() })
const chartDom = document.getElementById(`detectionCategoryPer${this.pageType}`)
this.detectionChart = echarts.getInstanceByDom(chartDom)
if(this.detectionChart){
let securityTypeOption = this.$_.cloneDeep(this.detectionChart.getOption())
echarts.dispose(this.detectionChart)
if (chartDom) {
this.detectionChart = echarts.init(chartDom)
let oneColumnWidth = (chartDom.clientWidth * 0.56) - 30
if (this.statisticsCategoryData.length > 6) {
oneColumnWidth = (chartDom.clientWidth * 0.56) / 2 - 30
}
securityTypeOption.legend[0].formatter = function (name) {
return format.truncateText(name, oneColumnWidth, '12px')
}
this.detectionChart.setOption(securityTypeOption)
}
}
}, },
jumpNewDetetion () { jumpNewDetetion () {
this.$router.push({ this.$router.push({
path: '/detection/policy', path: '/detectionPolicy',
query: { query: {
t: +new Date() t: +new Date()
} }
@@ -880,34 +823,11 @@ export default {
if (obj) { if (obj) {
this.filterData[this.pageType][index].value = [obj.value] this.filterData[this.pageType][index].value = [obj.value]
this.filterData[this.pageType][index].flag = true this.filterData[this.pageType][index].flag = true
} else {
this.filterData[this.pageType][index].value = []
this.filterData[this.pageType][index].flag = true
} }
} else { } else {
this.filterData[this.pageType][index].value = [] this.filterData[this.pageType][index].value = []
this.filterData[this.pageType][index].flag = true this.filterData[this.pageType][index].flag = true
} }
},
getFilter (name, topColumn) {
if (topColumn === 'tag') {
const params = {
column: topColumn,
operator: 'has',
value: name
}
this.$refs.search.changeParams([params])
} else {
const params = {
column: topColumn,
operator: '=',
value: name
}
this.$refs.search.changeParams([params])
}
this.$nextTick(() => {
this.emitter.emit('advanced-search')
})
} }
}, },
mounted () { mounted () {
@@ -926,11 +846,7 @@ export default {
} }
} }
this.queryFilter(q) this.queryFilter(q)
if (this.initFlag) { this.initFlag = false
this.timer = setTimeout(() => {
this.initFlag = false
}, 1000)
}
this.queryList(q) this.queryList(q)
this.debounceFunc = this.$_.debounce(this.resize, 300) this.debounceFunc = this.$_.debounce(this.resize, 300)
window.addEventListener('resize', this.debounceFunc) window.addEventListener('resize', this.debounceFunc)
@@ -1000,6 +916,78 @@ export default {
}, },
timeFilter () { timeFilter () {
this.search(this.metaList, this.q) this.search(this.metaList, this.q)
},
'filterData.securityEvent.0.value': {
deep: true,
handler (n, o) {
if (!this.filterData.securityEvent[0].flag) {
this.$refs.search.changeParams({ column: this.filterData.securityEvent[0].column, oldValue: o, newValue: n })
} else {
this.filterData.securityEvent[0].flag = false
}
}
},
'filterData.securityEvent.1.value': {
deep: true,
handler (n, o) {
if (!this.filterData.securityEvent[1].flag) {
this.$refs.search.changeParams({ column: this.filterData.securityEvent[1].column, oldValue: o, newValue: n })
} else {
this.filterData.securityEvent[1].flag = false
}
}
},
'filterData.securityEvent.2.value': {
deep: true,
handler (n, o) {
if (!this.filterData.securityEvent[2].flag) {
this.$refs.search.changeParams({ column: this.filterData.securityEvent[2].column, oldValue: o, newValue: n })
} else {
this.filterData.securityEvent[2].flag = false
}
}
},
'filterData.securityEvent.3.value': {
deep: true,
handler (n, o) {
if (!this.filterData.securityEvent[3].flag) {
this.$refs.search.changeParams({ column: this.filterData.securityEvent[3].column, oldValue: o, newValue: n })
} else {
this.filterData.securityEvent[3].flag = false
}
}
},
'filterData.securityEvent.4.value': {
deep: true,
handler (n, o) {
if (!this.filterData.securityEvent[4].flag) {
this.$refs.search.changeParams({ column: this.filterData.securityEvent[4].column, oldValue: o, newValue: n })
} else {
this.filterData.securityEvent[4].flag = false
}
}
},
'filterData.securityEvent.5.value': {
deep: true,
handler (n, o) {
if (!this.filterData.securityEvent[5].flag) {
this.$refs.search.changeParams({ column: this.filterData.securityEvent[5].column, oldValue: o, newValue: n })
} else {
this.filterData.securityEvent[5].flag = false
}
}
},
'filterData.performanceEvent.0.value': {
deep: true,
handler (n, o) {
this.$refs.search.changeParams({ column: this.filterData.performanceEvent[0].column, oldValue: o, newValue: n })
}
},
'filterData.performanceEvent.1.value': {
deep: true,
handler (n, o) {
this.$refs.search.changeParams({ column: this.filterData.performanceEvent[1].column, oldValue: o, newValue: n })
}
} }
}, },
beforeUnmount () { beforeUnmount () {
@@ -1007,10 +995,11 @@ export default {
}, },
setup () { setup () {
const store = useStore() const store = useStore()
let { query, path } = useRoute() let { params, query, path } = useRoute()
// 获取路由跳转过的历史状态,赋值给当前界面,起到保留状态的作用,如浏览器的回退前进等 // 获取路由跳转过的历史状态,赋值给当前界面,起到保留状态的作用,如浏览器的回退前进等
const routerObj = store.getters.getRouterHistoryList.find(item => item.t === query.t) const routerObj = store.getters.getRouterHistoryList.find(item => item.t === query.t)
if (routerObj) { if (routerObj) {
params = routerObj.params
query = routerObj.query query = routerObj.query
path = routerObj.path path = routerObj.path
@@ -1018,16 +1007,15 @@ export default {
const newUrl = urlParamsHandler(window.location.href, useRoute().query, query) const newUrl = urlParamsHandler(window.location.href, useRoute().query, query)
overwriteUrl(newUrl) overwriteUrl(newUrl)
} }
const pageType = path.replace('/detection/', '') const pageType = params.typeName
// 获取url携带的range、startTime、endTime // 获取url携带的range、startTime、endTime
const rangeParam = query.range const rangeParam = query.range
const startTimeParam = query.startTime const startTimeParam = query.startTime
const endTimeParam = query.endTime const endTimeParam = query.endTime
// 优先级url > config.js > 默认值。 const dateRangeValue = rangeParam ? parseInt(query.range) : 60
const dateRangeValue = rangeParam ? parseInt(rangeParam) : (DEFAULT_TIME_FILTER_RANGE.detection || 60)
const timeFilter = ref({ dateRangeValue }) const timeFilter = ref({ dateRangeValue })
if (!startTimeParam || !endTimeParam) { if (!startTimeParam || !endTimeParam) {
const { startTime, endTime } = getNowTime(dateRangeValue) const { startTime, endTime } = getNowTime(60)
timeFilter.value.startTime = getSecond(startTime) timeFilter.value.startTime = getSecond(startTime)
timeFilter.value.endTime = getSecond(endTime) timeFilter.value.endTime = getSecond(endTime)
// 如果没有时间参数就将参数写入url // 如果没有时间参数就将参数写入url
@@ -1037,17 +1025,9 @@ export default {
timeFilter.value.startTime = parseInt(startTimeParam) timeFilter.value.startTime = parseInt(startTimeParam)
timeFilter.value.endTime = parseInt(endTimeParam) timeFilter.value.endTime = parseInt(endTimeParam)
} }
const pageObj = ref({
pageNo: query.pageNo ? parseInt(query.pageNo) : 1,
// 是否重置pageNo在执行新搜索时是true
resetPageNo: true,
pageSize: query.pageSize ? parseInt(query.pageSize) : defaultPageSize,
total: 0
})
return { return {
timeFilter, timeFilter,
pageType, pageType
pageObj
} }
} }
} }

View File

@@ -30,7 +30,6 @@
:isNoData="isNoData" :isNoData="isNoData"
:custom-table-title="tools.customTableTitle" :custom-table-title="tools.customTableTitle"
:table-data="tableData" :table-data="tableData"
:policy-detail="policyDetail"
:is-selected-status="isSelectedStatus" :is-selected-status="isSelectedStatus"
:all-count="18" :all-count="18"
@selectionChange="selectionChange" @selectionChange="selectionChange"
@@ -76,7 +75,7 @@
<div class="detection-drawer"> <div class="detection-drawer">
<el-drawer v-model="showDrawer" :with-header="false"> <el-drawer v-model="showDrawer" :with-header="false">
<detection-drawer :drawer-info="drawerInfo" @edit="onEdit" /> <detection-drawer :drawer-info="drawerInfo"></detection-drawer>
</el-drawer> </el-drawer>
</div> </div>
@@ -90,7 +89,6 @@ import { api } from '@/utils/api'
import dataListMixin from '@/mixins/data-list' import dataListMixin from '@/mixins/data-list'
import DetectionDrawer from '@/views/detections/detectionPolicies/PolicyDrawer' import DetectionDrawer from '@/views/detections/detectionPolicies/PolicyDrawer'
import axios from 'axios' import axios from 'axios'
import { useRoute } from 'vue-router'
export default { export default {
name: 'Index', name: 'Index',
@@ -120,40 +118,14 @@ export default {
drawerInfo: {}, drawerInfo: {},
filterParams: {}, filterParams: {},
policyTotal: 0, policyTotal: 0,
policyEnabledNum: 0, policyEnabledNum: 0
policyDetail: {}
}
},
mounted () {
const { query } = useRoute()
if (query.name && query.ruleId) {
this.getPolicyDetail(query.ruleId)
} }
}, },
methods: { methods: {
getPolicyDetail (id) {
if (id) {
axios.get(`${api.detection.detail}/${id}`).then(res => {
if (res.status === 200) {
if (!res.data.data) {
throw new Error('No data found, id: ' + this.ruleId)
}
this.policyDetail = res.data.data
this.selectionChange([res.data.data])
this.onRowDoubleClick(res.data.data)
} else {
console.error(res.data)
}
}).catch(e => {
console.error(e)
this.$message.error(this.errorMsgHandler(e))
})
}
},
onSearch (keyWord) { onSearch (keyWord) {
this.filterParams = { this.filterParams = {
...this.filterParams, ...this.filterParams,
q: keyWord name: keyWord
} }
this.search(this.filterParams, 'detection') this.search(this.filterParams, 'detection')
}, },
@@ -168,7 +140,7 @@ export default {
}, },
onCreate () { onCreate () {
this.$router.push({ this.$router.push({
path: '/detection/policy/create', path: '/detectionPolicy/create',
query: { query: {
t: +new Date() t: +new Date()
} }
@@ -177,12 +149,11 @@ export default {
onEdit () { onEdit () {
const pageNo = this.$router.currentRoute.value.query.pageNo const pageNo = this.$router.currentRoute.value.query.pageNo
this.$router.push({ this.$router.push({
path: '/detection/policy/edit', path: '/detectionPolicy/edit',
query: { query: {
t: +new Date(), t: +new Date(),
pageNoForTable: pageNo || 1, pageNoForTable: pageNo || 1,
id: this.batchDeleteObjs[0].ruleId, id: this.batchDeleteObjs[0].ruleId
name: this.$route.query.name || ''
} }
}) })
}, },

View File

@@ -2,10 +2,7 @@
<div class="detection-drawer" style="height: 100vh;overflow: scroll;padding-bottom: 90px"> <div class="detection-drawer" style="height: 100vh;overflow: scroll;padding-bottom: 90px">
<div class="drawer-basic"> <div class="drawer-basic">
<div class="drawer-basic-header"> <div class="drawer-basic-header">
<div class="drawer-basic-id"> <div class="drawer-basic-id">ID: {{ drawerInfo.ruleId }}</div>
<div>ID: {{ drawerInfo.ruleId }}</div>
<i @click="onEdit" class="cn-icon cn-icon-bianji1"></i>
</div>
<div :class="`detection-tag-status${drawerInfo.status}`"> <div :class="`detection-tag-status${drawerInfo.status}`">
{{ $t(switchStatus(drawerInfo.status)) }} {{ $t(switchStatus(drawerInfo.status)) }}
</div> </div>
@@ -85,7 +82,7 @@
<div class="detection-drawer-collapse" style="margin: 20px 0"> <div class="detection-drawer-collapse" style="margin: 20px 0">
<el-collapse v-model="activeTrigger"> <el-collapse v-model="activeTrigger">
<el-collapse-item :title="$t('detection.create.trigger')" name="trigger"> <el-collapse-item :title="$t('detection.create.trigger')" name="trigger">
<div class="drawer-collapse-content" v-if="language===EN"> <div class="drawer-collapse-content" v-if="language==='en'">
<div class="drawer-collapse-trigger"> <div class="drawer-collapse-trigger">
Triggered when conditions occur at least Triggered when conditions occur at least
<span style="color: #046ECA"> <span style="color: #046ECA">
@@ -105,7 +102,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="drawer-collapse-content" v-if="language===ZH"> <div class="drawer-collapse-content" v-if="language==='cn'">
<div class="drawer-collapse-trigger"> <div class="drawer-collapse-trigger">
当条件为 当条件为
<span style="color: #046ECA"> <span style="color: #046ECA">
@@ -134,7 +131,7 @@
<script> <script>
import { switchStatus, toUpperCaseByString } from '@/utils/tools' import { switchStatus, toUpperCaseByString } from '@/utils/tools'
import { detectionUnitList, eventSeverityColor, securityLevel, storageKey, ZH, EN } from '@/utils/constants' import { detectionUnitList, eventSeverityColor, securityLevel, storageKey } from '@/utils/constants'
import axios from 'axios' import axios from 'axios'
import { api } from '@/utils/api' import { api } from '@/utils/api'
@@ -152,11 +149,9 @@ export default {
detailData: {}, detailData: {},
eventSeverityColor, eventSeverityColor,
severityList: [], severityList: [],
language: EN, language: 'en',
atLeast: 0, atLeast: 0,
times: 'time', times: 'time'
ZH,
EN
} }
}, },
watch: { watch: {
@@ -171,7 +166,7 @@ export default {
} }
}, },
mounted () { mounted () {
this.language = localStorage.getItem(storageKey.language) || EN this.language = localStorage.getItem(storageKey.language) || 'en'
}, },
methods: { methods: {
switchStatus, switchStatus,
@@ -248,9 +243,6 @@ export default {
} else { } else {
return '-' return '-'
} }
},
onEdit () {
this.$emit('edit')
} }
} }
} }

View File

@@ -6,8 +6,8 @@
{{ ruleId ? $t('detection.editEventPolicies') : $t('detection.createEventPolicies') }} {{ ruleId ? $t('detection.editEventPolicies') : $t('detection.createEventPolicies') }}
</div> </div>
<!--第一步General Settings-->
<div class="detection-form-content"> <div class="detection-form-content">
<!--第一步General Settings-->
<div class="detection-form-collapse"> <div class="detection-form-collapse">
<el-collapse v-model="activeNames"> <el-collapse v-model="activeNames">
<el-collapse-item name="1"> <el-collapse-item name="1">
@@ -43,7 +43,7 @@
<!--第三步Trigger--> <!--第三步Trigger-->
<div class="detection-form-collapse"> <div class="detection-form-collapse">
<el-collapse v-model="activeNames" class="policy-form-trigger"> <el-collapse v-model="activeNames">
<el-collapse-item name="3"> <el-collapse-item name="3">
<template #title> <template #title>
<div class="form-collapse-header"> <div class="form-collapse-header">
@@ -53,7 +53,7 @@
</template> </template>
<div class="form-collapse-content margin-t-18"> <div class="form-collapse-content margin-t-18">
<el-form v-if="language===EN" class="trigger-block margin-b-20" ref="form3" :model="triggerObj" :rules="rules"> <el-form v-if="language==='en'" class="trigger-block margin-b-20" ref="form3" :model="triggerObj" :rules="rules">
<div class="trigger-block-item margin-b-10"> <div class="trigger-block-item margin-b-10">
<div>At least</div> <div>At least</div>
<el-form-item prop="atLeast"> <el-form-item prop="atLeast">
@@ -94,7 +94,7 @@
</el-form-item> </el-form-item>
</div> </div>
</el-form> </el-form>
<el-form v-if="language===ZH" class="trigger-block margin-b-20" ref="form3" :model="triggerObj" :rules="rules"> <el-form v-if="language==='cn'" class="trigger-block margin-b-20" ref="form3" :model="triggerObj" :rules="rules">
<div class="trigger-block-item margin-b-10"> <div class="trigger-block-item margin-b-10">
<el-form-item prop="interval"> <el-form-item prop="interval">
@@ -136,20 +136,18 @@
不活跃将重置计数 不活跃将重置计数
</div> </div>
</el-form> </el-form>
<div class="form-setting__btn1">
<div class="btn1">
<el-button @click="createPolicy('')">{{ $t('overall.save') }}</el-button>
</div>
<el-button @click="createPolicy('enabled')">{{ $t('overall.save') }} & {{ $t('detection.create.enablePolicy') }}</el-button>
</div>
</div> </div>
</el-collapse-item> </el-collapse-item>
</el-collapse> </el-collapse>
</div> </div>
</div> </div>
<div class="policy-form__footer">
<div class="policy-form__footer__btn">
<div class="btn1">
<el-button @click="cancel">{{ $t('overall.cancel') }}</el-button>
</div>
<el-button @click="createPolicy">{{ $t('overall.save') }}</el-button>
</div>
</div>
</div> </div>
</template> </template>
@@ -162,7 +160,7 @@ import { useRoute } from 'vue-router'
import { ref } from 'vue' import { ref } from 'vue'
import { getDurationsTimeByType, getTimeByDurations } from '@/utils/date-util' import { getDurationsTimeByType, getTimeByDurations } from '@/utils/date-util'
import Loading from '@/components/common/Loading' import Loading from '@/components/common/Loading'
import { storageKey, detectionUnitList, ZH, EN } from '@/utils/constants' import { storageKey, detectionUnitList } from '@/utils/constants'
export default { export default {
name: 'DetectionForm', name: 'DetectionForm',
@@ -259,9 +257,7 @@ export default {
intervalList: [], intervalList: [],
editObj: {}, editObj: {},
isComplete: true, // 参数完整标识默认完整照顾编辑模式false即不完整 isComplete: true, // 参数完整标识默认完整照顾编辑模式false即不完整
language: EN, language: 'en'
ZH,
EN
} }
}, },
components: { components: {
@@ -270,10 +266,10 @@ export default {
Loading Loading
}, },
mounted () { mounted () {
this.language = localStorage.getItem(storageKey.language) || EN this.language = localStorage.getItem(storageKey.language) || 'en'
if (this.language === EN) { if (this.language === 'en') {
this.intervalList = detectionUnitList.intervalList this.intervalList = detectionUnitList.intervalList
} else if (this.language === ZH) { } else if (this.language === 'cn') {
this.intervalList = detectionUnitList.intervalListCN this.intervalList = detectionUnitList.intervalListCN
} }
this.getDetailInfo() this.getDetailInfo()
@@ -334,7 +330,7 @@ export default {
console.error(e) console.error(e)
this.$message.error(this.errorMsgHandler(e)) this.$message.error(this.errorMsgHandler(e))
this.$router.push({ this.$router.push({
path: '/detection/policy', path: '/detectionPolicy',
query: { query: {
pageNo: this.pageNoForTable ? Number(this.pageNoForTable) : 1, pageNo: this.pageNoForTable ? Number(this.pageNoForTable) : 1,
t: +new Date() t: +new Date()
@@ -371,7 +367,7 @@ export default {
} }
}, },
/** 创建policy */ /** 创建policy */
createPolicy () { createPolicy (flag) {
const settingLen = Object.keys(this.settingObj).length const settingLen = Object.keys(this.settingObj).length
const ruleLen = Object.keys(this.ruleObj).length const ruleLen = Object.keys(this.ruleObj).length
@@ -380,6 +376,9 @@ export default {
if (valid) { if (valid) {
// 最终提交form // 最终提交form
const formObj = this.$_.cloneDeep({ ...this.settingObj, ruleConfig: JSON.stringify(this.ruleObj), ruleTrigger: this.triggerObj }) const formObj = this.$_.cloneDeep({ ...this.settingObj, ruleConfig: JSON.stringify(this.ruleObj), ruleTrigger: this.triggerObj })
if (flag) {
formObj.status = 1
}
// 将时间转为参数所需如5分钟转为PT5M // 将时间转为参数所需如5分钟转为PT5M
formObj.ruleTrigger.resetInterval = getDurationsTimeByType(formObj.ruleTrigger.resetInterval, formObj.ruleTrigger.resetIntervalVal) formObj.ruleTrigger.resetInterval = getDurationsTimeByType(formObj.ruleTrigger.resetInterval, formObj.ruleTrigger.resetIntervalVal)
formObj.ruleTrigger.interval = getDurationsTimeByType(formObj.ruleTrigger.interval, formObj.ruleTrigger.intervalVal) formObj.ruleTrigger.interval = getDurationsTimeByType(formObj.ruleTrigger.interval, formObj.ruleTrigger.intervalVal)
@@ -403,7 +402,7 @@ export default {
}) })
this.$router.push({ this.$router.push({
path: '/detection/policy', path: '/detectionPolicy',
query: { query: {
t: +new Date() t: +new Date()
} }
@@ -419,6 +418,7 @@ export default {
this.myLoading = false this.myLoading = false
}) })
} else { } else {
console.log('进来')
this.myLoading = true this.myLoading = true
axios.put(api.detection.create.create, formObj).then(response => { axios.put(api.detection.create.create, formObj).then(response => {
if (response.status === 200) { if (response.status === 200) {
@@ -428,18 +428,12 @@ export default {
message: this.$t('tip.saveSuccess') message: this.$t('tip.saveSuccess')
}) })
const { query } = this.$route
const queryInfo = {
pageNo: self.pageNoForTable ? Number(self.pageNoForTable) : 1,
t: +new Date()
}
if (query.name && query.id) {
queryInfo.ruleId = query.id
queryInfo.name = this.settingObj.name
}
this.$router.push({ this.$router.push({
path: '/detection/policy', path: '/detectionPolicy',
query: queryInfo query: {
pageNo: self.pageNoForTable ? Number(self.pageNoForTable) : 1,
t: +new Date()
}
}) })
} else { } else {
console.error(response.data.message) console.error(response.data.message)
@@ -497,134 +491,7 @@ export default {
return { flag: false, msg: this.$t('policy.dateTimeRangeSeconds') } return { flag: false, msg: this.$t('policy.dateTimeRangeSeconds') }
} }
} }
},
cancel () {
const { query } = this.$route
const queryInfo = {
pageNo: this.pageNoForTable ? Number(this.pageNoForTable) : 1,
t: +new Date()
}
if (query.name && query.id) {
queryInfo.ruleId = query.id
queryInfo.name = this.settingObj.name
}
this.$refs.form3.validate(valid => {
if (this.settingObj.settingNoContinue || this.ruleObj.settingNoContinue || !valid) {
this.$confirm(this.$t('tip.leavePage'), {
confirmButtonText: this.$t('tip.confirm'),
cancelButtonText: this.$t('overall.cancel'),
message: this.$t('tip.leavePageTips'),
title: this.$t('tip.leavePage'),
type: 'warning',
iconClass: 'width:0px;height:0px;',
customClass: 'del-model'
}).then(() => {
this.$router.push({
path: '/detection/policy',
query: queryInfo
})
}).catch(() => {})
} else {
this.$router.push({
path: '/detection/policy',
query: queryInfo
})
}
})
} }
} }
} }
</script> </script>
<style lang="scss">
.del-model {
display: flex;
flex-direction: column;
padding-bottom: 0 !important;
width: 480px !important;
height: 190px;
.el-message-box__header {
display: flex;
flex-direction: row;
border-bottom: 1px solid #eee;
height: 42px;
background: #F7F7F7;
box-shadow: 0 1px 0 0 rgba(53, 54, 54, 0.08);
padding-left: 20px;
padding-top: 14px;
padding-bottom: 14px;
.el-message-box__headerbtn {
display: flex !important;
flex-direction: row-reverse;
justify-content: center;
align-items: center;
font-size: 10px;
line-height: 10px;
padding-right: 5px !important;
i {
width: 10px;
height: 10px;
}
}
.el-message-box__title {
font-size: 14px !important;
color: #353636;
letter-spacing: 0;
font-weight: 400;
}
}
.el-message-box__content {
height: 96px;
font-size: 14px;
color: #353636;
letter-spacing: 0;
line-height: 22px;
font-weight: 400;
padding-top: 8px;
padding-right: 20px;
padding-left: 20px;
.el-message-box__message {
padding-left: 0 !important;
padding-right: 0 !important;
}
}
.el-message-box__btns {
height: 52px;
border-top: 1px solid #eee;
box-shadow: inset 0 -1px 0 0 rgba(0, 0, 0, 0.07);
padding: 11px 0 12px !important;
.el-button--small {
padding: 8px 21px !important;
line-height: 12px;
font-family: NotoSansHans-Medium !important;
font-size: 12px;
font-weight: 500;
min-height: 28px;
}
.el-button:nth-child(1) {
margin-right: 20px;
width: 80px;
height: 28px;
color: #353636;
}
.el-button:nth-child(2) {
width: 80px;
height: 28px;
margin-right: 20px;
margin-left: 0 !important;
background-color: #2d8cf0;
border-color: #2d8cf0;
}
}
}
</style>

View File

@@ -5,7 +5,6 @@
ref="dataTable" ref="dataTable"
:data="tableData" :data="tableData"
height="100%" height="100%"
tooltip-effect="light"
border border
empty-text=" " empty-text=" "
@header-dragend="dragend" @header-dragend="dragend"
@@ -32,7 +31,6 @@
:sortable="item.sortable" :sortable="item.sortable"
:width="`${item.width}`" :width="`${item.width}`"
class="data-column" class="data-column"
:show-overflow-tooltip="['library'].indexOf(item.prop) > -1"
> >
<template #header> <template #header>
<span class="data-column__span">{{ item.label }}</span> <span class="data-column__span">{{ item.label }}</span>
@@ -84,7 +82,6 @@ import { dateFormatByAppearance } from '@/utils/date-util'
import { switchStatus } from '@/utils/tools' import { switchStatus } from '@/utils/tools'
import _ from 'lodash' import _ from 'lodash'
import { detectionUnitList } from '@/utils/constants' import { detectionUnitList } from '@/utils/constants'
import { useRoute } from 'vue-router'
export default { export default {
name: 'DetectionTable', name: 'DetectionTable',
@@ -92,9 +89,6 @@ export default {
isNoData: { isNoData: {
type: Boolean, type: Boolean,
default: false default: false
},
policyDetail: {
type: Object
} }
}, },
mixins: [table], mixins: [table],
@@ -152,17 +146,6 @@ export default {
] ]
} }
}, },
mounted () {
const { query } = useRoute()
// 初始化勾选状态
if (query.name && query.ruleId && this.policyDetail) {
this.selectionChange([this.policyDetail])
const timer = setTimeout(() => {
this.$refs.dataTable.toggleAllSelection([this.policyDetail])
clearTimeout(timer)
}, 400)
}
},
watch: { watch: {
tableData: { tableData: {
immediate: true, immediate: true,

View File

@@ -3,7 +3,6 @@
<div class="top-tools__left"> <div class="top-tools__left">
<button <button
id="knowledge-base-add" id="knowledge-base-add"
v-if="hasPermission('createDetectionPolicy')"
:title="$t('knowledgeBase.createKnowledgeBase')" :title="$t('knowledgeBase.createKnowledgeBase')"
class="top-tool-btn margin-r-10 top-tool-btn--create" class="top-tool-btn margin-r-10 top-tool-btn--create"
@click="onCreate" @click="onCreate"
@@ -14,7 +13,6 @@
<button <button
:disabled="disableEdit" :disabled="disableEdit"
v-if="hasPermission('editDetectionPolicy')"
id="knowledge-base-edit" id="knowledge-base-edit"
:title="$t('knowledgeBase.editKnowledgeBase')" :title="$t('knowledgeBase.editKnowledgeBase')"
class="top-tool-btn margin-r-10" class="top-tool-btn margin-r-10"
@@ -26,7 +24,6 @@
<button <button
:disabled="disableDelete" :disabled="disableDelete"
v-if="hasPermission('deleteDetectionPolicy')"
id="knowledge-base-delete" id="knowledge-base-delete"
:title="$t('knowledgeBase.deleteKnowledgeBase')" :title="$t('knowledgeBase.deleteKnowledgeBase')"
class="top-tool-btn margin-r-10" class="top-tool-btn margin-r-10"
@@ -50,9 +47,6 @@
</template> </template>
<script> <script>
import { useRoute } from 'vue-router'
import { overwriteUrl, urlParamsHandler } from '@/utils/tools'
export default { export default {
name: 'DetectionTools', name: 'DetectionTools',
props: { props: {
@@ -70,21 +64,9 @@ export default {
keyWord: '' keyWord: ''
} }
}, },
mounted () {
const { query } = useRoute()
if (query.name) {
this.keyWord = query.name
this.onSearch()
}
},
methods: { methods: {
onSearch () { onSearch () {
this.$emit('search', this.keyWord) this.$emit('search', this.keyWord)
if (!this.keyWord) {
const query = this.$route.query
delete query.name
this.reloadUrl(query, 'clear')
}
}, },
onCreate () { onCreate () {
this.$emit('create') this.$emit('create')
@@ -94,14 +76,6 @@ export default {
}, },
onDelete (data) { onDelete (data) {
this.$emit('delete', data) this.$emit('delete', data)
},
reloadUrl (newParam, clean) {
const { query } = this.$route
let newUrl = urlParamsHandler(window.location.href, query, newParam)
if (clean) {
newUrl = urlParamsHandler(window.location.href, query, newParam, clean)
}
overwriteUrl(newUrl)
} }
} }
} }

View File

@@ -187,7 +187,7 @@ export const pieForSeverity = {
legend: { legend: {
orient: 'vertical', orient: 'vertical',
type: 'plain', type: 'plain',
left: '44%', left: '60%',
top: 'middle', top: 'middle',
icon: 'circle', icon: 'circle',
itemWidth: 10, // 设置宽度 itemWidth: 10, // 设置宽度
@@ -203,7 +203,7 @@ export const pieForSeverity = {
type: 'pie', type: 'pie',
selectedMode: 'single', selectedMode: 'single',
radius: ['43%', '65%'], radius: ['43%', '65%'],
center: ['22%', '50%'], center: ['30%', '50%'],
data: [], data: [],
label: { label: {
show: false show: false

View File

@@ -243,7 +243,7 @@ export default {
}, },
goDetail (type, name) { goDetail (type, name) {
const { href } = this.$router.resolve({ const { href } = this.$router.resolve({
path: '/entity/detail', path: '/entityDetail',
query: { query: {
entityType: type, entityType: type,
entityName: name entityName: name

View File

@@ -274,7 +274,7 @@ export default {
}, },
goDetail (type, name) { goDetail (type, name) {
const { href } = this.$router.resolve({ const { href } = this.$router.resolve({
path: '/entity/detail', path: '/entityDetail',
query: { query: {
entityType: type, entityType: type,
entityName: name entityName: name

View File

@@ -235,7 +235,7 @@ export default {
}, },
goDetail (type, name) { goDetail (type, name) {
const { href } = this.$router.resolve({ const { href } = this.$router.resolve({
path: '/entity/detail', path: '/entityDetail',
query: { query: {
entityType: type, entityType: type,
entityName: name entityName: name

View File

@@ -10,7 +10,7 @@
<span class="row__content--link">{{detection.victimIp}}</span>&nbsp;&nbsp;communicated with&nbsp;<span class="row__content--link">{{detection.offenderIp}}</span>&nbsp;&nbsp;that was associated with the indicator of {{detection.eventName}}. <span class="row__content--link">{{detection.victimIp}}</span>&nbsp;&nbsp;communicated with&nbsp;<span class="row__content--link">{{detection.offenderIp}}</span>&nbsp;&nbsp;that was associated with the indicator of {{detection.eventName}}.
</div> </div>
<div class="row__content1" v-else> <div class="row__content1" v-else>
{{ $_.get(basicInfo, 'ruleInfo.description', '-') || '-' }} {{basicInfo.ruleDescription || '-'}}
</div> </div>
</div> </div>
<div class="overview__title">Fields</div> <div class="overview__title">Fields</div>
@@ -71,7 +71,7 @@
<div class="row__content">{{ $_.get(basicInfo, 'domainInfo.category.categoryGroup', '-') || '-' }}</div> <div class="row__content">{{ $_.get(basicInfo, 'domainInfo.category.categoryGroup', '-') || '-' }}</div>
</div> </div>
<div class="overview__row"> <div class="overview__row">
<div class="row__label">{{ $t('detection.domainReputationLevel') }}</div> <div class="row__label">{{ $t('entities.reputationLevel') }}</div>
<div class="row__content" v-if="$_.get(basicInfo, 'domainInfo.category.reputationLevel')"> <div class="row__content" v-if="$_.get(basicInfo, 'domainInfo.category.reputationLevel')">
<div <div
class="row__tag row__tag__level" class="row__tag row__tag__level"
@@ -242,17 +242,6 @@
</template> </template>
</div> </div>
<div class="overview__right"> <div class="overview__right">
<div v-if="$_.get(basicInfo, 'ruleInfo.ruleId') >= 10000">
<div class="overview__title">{{ $t('detections.goToPolicy') }}</div>
<div class="overview__row">
<div class="row__content">
<span class="row__content--span">{{ $t('detections.viewDetailOf') }}</span> &nbsp;
<span class="row__content--link" @click="goPolicyPage">
{{ $_.get(basicInfo, 'ruleInfo.name', '-') || '-' }} (ID: {{ $_.get(basicInfo, 'ruleInfo.ruleId', '-') || '-' }})
</span>
</div>
</div>
</div>
<div class="overview__title">{{ $t('detections.goToVictim') }}</div> <div class="overview__title">{{ $t('detections.goToVictim') }}</div>
<div class="overview__row"> <div class="overview__row">
<div class="row__content"> <div class="row__content">
@@ -442,7 +431,10 @@ export default {
dateFormatByAppearance, dateFormatByAppearance,
/** 初始化实体详情 */ /** 初始化实体详情 */
initEntityDetail () { initEntityDetail () {
// 调接口查询攻击者和受害者IP、Domain、APP的更多信息 // 为完整填充IP信息攻击者ip、受害者ip都进行调用
// 根据detection的eventInfo对象的ioc_type进行判断若为domainmalware信息从domain详情中获取并填充domain信息
// 若ioc_type为ip则调用ip接口填充malware信息
// 最后调用app填充app信息。经上获取完整实体详情则最少需要调用4次接口
if (this.detection.offenderIp) { if (this.detection.offenderIp) {
axios.get(`${api.detection.securityEvent.ipDetail}?resource=${this.detection.offenderIp}`).then(res => { axios.get(`${api.detection.securityEvent.ipDetail}?resource=${this.detection.offenderIp}`).then(res => {
if (res.status === 200) { if (res.status === 200) {
@@ -474,7 +466,7 @@ export default {
if (this.detection.ruleId) { if (this.detection.ruleId) {
axios.get(`${api.detection.detail}/${this.detection.ruleId}`).then(res => { axios.get(`${api.detection.detail}/${this.detection.ruleId}`).then(res => {
if (res.status === 200) { if (res.status === 200) {
this.basicInfo.ruleInfo = res.data.data this.basicInfo.ruleDescription = res.data.data.description
} }
}) })
} }
@@ -499,7 +491,7 @@ export default {
goDetail (type, name) { goDetail (type, name) {
if (name) { if (name) {
const { href } = this.$router.resolve({ const { href } = this.$router.resolve({
path: '/entity/detail', path: '/entityDetail',
query: { query: {
entityType: type, entityType: type,
entityName: name entityName: name
@@ -507,19 +499,6 @@ export default {
}) })
window.open(href, '_blank') window.open(href, '_blank')
} }
},
goPolicyPage () {
if (this.basicInfo.ruleInfo.name && Number(this.basicInfo.ruleInfo.ruleId) >= 10000) {
const { href } = this.$router.resolve({
path: '/detection/policy',
query: {
t: +new Date(),
name: this.basicInfo.ruleInfo.name,
ruleId: this.basicInfo.ruleInfo.ruleId
}
})
window.open(href, '_blank')
}
} }
}, },
mounted () { mounted () {

View File

@@ -39,11 +39,6 @@ export default {
entityData.appName = query.entityName entityData.appName = query.entityName
break break
} }
case 'subscribe': {
panelType = panelTypeAndRouteMapping.subscribeEntityDetail
entityData.appName = query.entityName
break
}
default: { default: {
panelType = panelTypeAndRouteMapping.ipEntityDetail panelType = panelTypeAndRouteMapping.ipEntityDetail
break break

View File

@@ -4,16 +4,8 @@
:class="{'entity-explorer--show-list': showList}"> :class="{'entity-explorer--show-list': showList}">
<!-- 顶部工具栏在列表页显示 --> <!-- 顶部工具栏在列表页显示 -->
<div class="explorer-top-tools explorer-top-tools-new" style="margin: 2px 0;" v-show="showList"> <div class="explorer-top-tools explorer-top-tools-new" style="margin: 2px 0;" v-show="showList">
<div class="explorer-entity-top-tools"> <div class="explorer-detection-top-tools">
<div class="explorer-top-tools-title" style="padding: 0;margin-left: -10px;">{{$t('network.entity')}}</div> <div class="explorer-top-tools-title" style="padding: 0;margin-left: -10px;">{{$t('network.entity')}}</div>
<date-time-range
class="date-time-range"
:start-time="timeFilter.startTime"
:end-time="timeFilter.endTime"
:date-range="timeFilter.dateRangeValue"
ref="dateTimeRange"
@change="reload"
/>
</div> </div>
</div> </div>
<!-- 搜索组件 --> <!-- 搜索组件 -->
@@ -44,26 +36,16 @@
<div style="display: flex;flex-direction: column;height: calc(100% - 42px);"> <div style="display: flex;flex-direction: column;height: calc(100% - 42px);">
<div class="explorer-result" v-if="showList" style="position: relative;"> <div class="explorer-result" v-if="showList" style="position: relative;">
<loading :loading="loadingCount" style="width: 240px"></loading> <loading :loading="loadingCount" style="width: 240px"></loading>
<span>{{ summaryCount.totalCount }}&nbsp;</span>{{$t('overall.results')}}IP <span>{{ summaryCount.totalCount }}&nbsp;</span>resultsIP
<span>{{ summaryCount.ipCount }}</span>{{$t('overall.domain')}} <span>{{ summaryCount.ipCount }}</span>Domain
<span>{{ summaryCount.domainCount }}</span>APP <span>{{ summaryCount.domainCount }}</span>APP
<span>{{ summaryCount.appCount }}</span> <span>{{ summaryCount.appCount }}</span>
<span class="entity-hide-entity" v-if="q">
<el-checkbox
v-model="isHideRelatedEntities"
:label="$t('entity.hideRelatedEntities')"
:disabled="listData.length===0"
@change="hideRelatedEntities"
size="large" />
</span>
</div> </div>
<entity-list <entity-list
style="width: 100%;" style="width: 100%;"
:list-data="listData" :list-data="listData"
:list-mode="listMode" :list-mode="listMode"
:keywordList="keywordList"
:pageObj="pageObj" :pageObj="pageObj"
:time-filter="timeFilter" :time-filter="timeFilter"
@pageSize="pageSize" @pageSize="pageSize"
@@ -110,7 +92,7 @@
<div class="entity-overview"> <div class="entity-overview">
<div class="overview-left"> <div class="overview-left">
<span class="overview-left-loading"> <span class="overview-left-loading">
<span class="overview-left-loading-span">{{$t('overall.domain')}}</span> <span class="overview-left-loading-span">Domain</span>
</span> </span>
</div> </div>
<div class="overview-right"> <div class="overview-right">
@@ -192,8 +174,6 @@ import Parser from '@/components/advancedSearch/meta/parser'
import { handleErrorTip } from '@/components/advancedSearch/meta/error' import { handleErrorTip } from '@/components/advancedSearch/meta/error'
import { columnList } from '@/utils/static-data' import { columnList } from '@/utils/static-data'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import { columnType } from '@/components/advancedSearch/meta/meta'
import DateTimeRange from '@/components/common/TimeRange/DateTimeRange'
export default { export default {
name: 'entity-explorer', name: 'entity-explorer',
@@ -201,8 +181,7 @@ export default {
Loading, Loading,
ExplorerSearch, ExplorerSearch,
EntityFilter, EntityFilter,
EntityList, EntityList
DateTimeRange
}, },
data () { data () {
return { return {
@@ -221,6 +200,13 @@ export default {
entityIpNew: '-', entityIpNew: '-',
entityIpActive: '-', entityIpActive: '-',
// pageObj: {
// pageNo: 1,
// // 是否重置pageNo在执行新搜索时是true
// resetPageNo: true,
// pageSize: defaultPageSize,
// total: 0
// },
newFilterData: [ newFilterData: [
{ {
icon: 'cn-icon cn-icon-registration-country', icon: 'cn-icon cn-icon-registration-country',
@@ -298,13 +284,12 @@ export default {
initFlag: true, // 初始化标志避免初始化时pageSize和pageNo会调用搜索 initFlag: true, // 初始化标志避免初始化时pageSize和pageNo会调用搜索
timer: null, // 初始化标志的延时器,需要销毁 timer: null, // 初始化标志的延时器,需要销毁
summaryCount: { summaryCount: {
totalCount: 0, total: 0,
domainCount: 0, domainCount: 0,
ipCount: 0, ipCount: 0,
appCount: 0 appCount: 0
}, },
loadingCount: false, // 实体基数统计的loading loadingCount: false // 实体基数统计的loading
keywordList: []
} }
}, },
methods: { methods: {
@@ -317,13 +302,6 @@ export default {
}, },
reload (s, e, v) { reload (s, e, v) {
this.dateTimeRangeChange(s, e, v) this.dateTimeRangeChange(s, e, v)
const { startTime, endTime } = getNowTime(this.timeFilter.dateRangeValue)
const newParam = {
range: this.timeFilter.dateRangeValue,
startTime: getSecond(startTime),
endTime: getSecond(endTime)
}
this.reloadUrl(newParam)
}, },
// methods // methods
dateTimeRangeChange (s, e, v) { dateTimeRangeChange (s, e, v) {
@@ -383,7 +361,6 @@ export default {
this.q = '' this.q = ''
this.metaList = [] this.metaList = []
} }
this.getKeyword(param.keywordList)
// 参数q避免切换页码时地址栏参数q为空 // 参数q避免切换页码时地址栏参数q为空
let urlQ = '' let urlQ = ''
@@ -391,8 +368,6 @@ export default {
urlQ = encodeURI(param.str) urlQ = encodeURI(param.str)
} else if (this.q) { } else if (this.q) {
urlQ = encodeURI(this.q) urlQ = encodeURI(this.q)
} else if (!this.q) {
this.isHideRelatedEntities = false
} }
// 在非列表模式下选择tag模式在地址栏输入内容时将mode添加到地址栏 // 在非列表模式下选择tag模式在地址栏输入内容时将mode添加到地址栏
@@ -414,7 +389,7 @@ export default {
if (!this.showList) { if (!this.showList) {
// 首页进入搜索时重载页面,视觉上进入列表页面 // 首页进入搜索时重载页面,视觉上进入列表页面
this.$router.push({ this.$router.push({
path: '/entity', path: '/entityExplorer',
query: { query: {
listMode: this.listMode, listMode: this.listMode,
q: urlQ, q: urlQ,
@@ -442,21 +417,19 @@ export default {
}, },
pageSize (val) { pageSize (val) {
this.pageObj.pageSize = val this.pageObj.pageSize = val
const keywordList = this.getKeywordListByMetaList(this.metaList)
if (this.initFlag) { if (this.initFlag) {
if (val !== 20) { if (val !== 20) {
this.search({ metaList: this.metaList, q: this.q, keywordList: keywordList }) this.search({ metaList: this.metaList, q: this.q })
} }
} else { } else {
this.search({ metaList: this.metaList, q: this.q, keywordList: keywordList }) this.search({ metaList: this.metaList, q: this.q })
} }
}, },
pageNo (val) { pageNo (val) {
if (!this.initFlag) { if (!this.initFlag) {
this.pageObj.pageNo = val this.pageObj.pageNo = val
this.pageObj.resetPageNo = false this.pageObj.resetPageNo = false
const keywordList = this.getKeywordListByMetaList(this.metaList) this.search({ metaList: this.metaList, q: this.q })
this.search({ metaList: this.metaList, q: this.q, keywordList: keywordList })
} }
}, },
// 点击上一页箭头 // 点击上一页箭头
@@ -516,8 +489,8 @@ export default {
/** 新版查询filter数据 */ /** 新版查询filter数据 */
queryFilterNew (params) { queryFilterNew (params) {
const queryParams = { const queryParams = {
startTime: getSecond(params.startTime), // startTime: getSecond(params.startTime),
endTime: getSecond(params.endTime), // endTime: getSecond(params.endTime),
resource: params.q || '' resource: params.q || ''
} }
this.loadingLeft = true this.loadingLeft = true
@@ -575,16 +548,16 @@ export default {
const queryParams = { const queryParams = {
pageSize: params.pageSize, pageSize: params.pageSize,
pageNo: params.pageNo, pageNo: params.pageNo,
startTime: getSecond(params.startTime), // startTime: getSecond(params.startTime),
endTime: getSecond(params.endTime), // endTime: getSecond(params.endTime),
resource: params.q || '', resource: params.q || ''
hideRelated: this.isHideRelatedEntities
} }
axios.get(api.entity.entityList.list, { params: queryParams }).then(response => { axios.get(api.entity.entityList.list, { params: queryParams }).then(response => {
if (response.status === 200) { if (response.status === 200) {
this.listData = [] this.listData = []
this.$nextTick(() => { this.$nextTick(() => {
this.listData = response.data.data.list this.listData = response.data.data.list
this.pageObj.total = response.data.data.total
}) })
} else { } else {
this.$message.error(response.data.message) this.$message.error(response.data.message)
@@ -597,21 +570,19 @@ export default {
queryCount (params) { queryCount (params) {
this.loadingCount = true this.loadingCount = true
const queryParams = { const queryParams = {
startTime: getSecond(params.startTime), // startTime: getSecond(params.startTime),
endTime: getSecond(params.endTime), // endTime: getSecond(params.endTime),
resource: params.q || '', resource: params.q || ''
hideRelated: this.isHideRelatedEntities
} }
axios.get(api.entity.entityList.summaryCount, { params: queryParams }).then(response => { axios.get(api.entity.entityList.summaryCount, { params: queryParams }).then(response => {
if (response.status === 200) { if (response.status === 200) {
this.summaryCount = response.data.data this.summaryCount = response.data.data
this.pageObj.total = response.data.data.totalCount
} else { } else {
this.summaryCount = { totalCount: 0, domainCount: 0, ipCount: 0, appCount: 0 } this.summaryCount = { total: 0, domainCount: 0, ipCount: 0, appCount: 0 }
} }
}).catch(e => { }).catch(e => {
console.error(e) console.log(e)
this.summaryCount = { totalCount: 0, domainCount: 0, ipCount: 0, appCount: 0 } this.summaryCount = { total: 0, domainCount: 0, ipCount: 0, appCount: 0 }
}).finally(() => { }).finally(() => {
this.loadingCount = false this.loadingCount = false
}) })
@@ -704,13 +675,11 @@ export default {
} }
} }
const parser = new Parser(columnList) const parser = new Parser(columnList)
const metaList = parser.parseStr(_.cloneDeep(str)).metaList
const keywordList = this.getKeywordListByMetaList(metaList)
const keyInfo = parser.comparedEntityKey(parser.handleEntityTypeByStr(str)) const keyInfo = parser.comparedEntityKey(parser.handleEntityTypeByStr(str))
if (keyInfo.isKey) { if (keyInfo.isKey) {
const errorList = parser.validateStr(keyInfo.key) const errorList = parser.validateStr(keyInfo.key)
if (_.isEmpty(errorList)) { if (_.isEmpty(errorList)) {
this.search({ ...parser.parseStr(keyInfo.key), str: str, keywordList: keywordList }) this.search({ ...parser.parseStr(keyInfo.key), str: str })
} else { } else {
this.$message.error(handleErrorTip(errorList[0])) this.$message.error(handleErrorTip(errorList[0]))
} }
@@ -758,55 +727,10 @@ export default {
}).catch((e) => { }).catch((e) => {
}).finally(() => { }).finally(() => {
}) })
},
getKeywordListByMetaList (metaList) {
if (metaList) {
const keywordList = []
metaList.forEach(item => {
if (item.column && item.column.type === columnType.fullText) {
keywordList.push({ type: item.column.type, value: item.column.label })
} else if (item.column && item.column.type === columnType.string) {
keywordList.push({ type: item.column.type, value: item.value.value })
}
})
return keywordList
}
},
getKeyword (list) {
if (list) {
const metaList = JSON.parse(JSON.stringify(list))
const keyList = []
metaList.forEach(item => {
if (item.value) {
keyList.push({ type: item.type, value: this.getKeyValue(item.value) })
}
})
this.keywordList = keyList
} else {
this.keywordList = []
}
},
getKeyValue (str) {
if (str[0] === "'" && str[str.length - 1] === "'") {
str = str.substring(1, str.length)
str = str.substring(0, str.length - 1)
}
if (str[0] === '%') {
str = str.substring(1, str.length)
}
if (str[str.length - 1] === '%') {
str = str.substring(0, str.length - 1)
}
return str
},
hideRelatedEntities (e) {
this.isHideRelatedEntities = e
this.reloadUrl({ hideRelated: e })
this.queryList({ q: this.q, ...this.pageObj, ...this.timeFilter })
this.queryCount({ q: this.q, ...this.pageObj, ...this.timeFilter })
} }
}, },
mounted () { mounted () {
this.getEntityIndexData()
let { q, listMode } = this.$route.query let { q, listMode } = this.$route.query
// 如果地址栏有listMode即列表页并非首页则开始搜索 // 如果地址栏有listMode即列表页并非首页则开始搜索
@@ -817,13 +741,7 @@ export default {
q = decodeURI(q) q = decodeURI(q)
} }
// %位置不为0即内容包含非英文时 // %位置不为0即内容包含非英文时
let str1 = '' const str1 = q.substring(q.indexOf('%'), q.indexOf('%') + 3)
if (q) {
str1 = q.substring(q.indexOf('%'), q.indexOf('%') + 3)
}
if (q && q.indexOf('+') > -1) {
q = q.replace('+', '')
}
if (q && q.indexOf('%') > 0 && (str1 !== '%20' || str1 === '%25')) { if (q && q.indexOf('%') > 0 && (str1 !== '%20' || str1 === '%25')) {
q = decodeURI(q) q = decodeURI(q)
} }
@@ -833,10 +751,6 @@ export default {
this.$store.commit('resetScoreBase') this.$store.commit('resetScoreBase')
this.queryScoreBase() this.queryScoreBase()
} }
if (!this.showList) {
this.getEntityIndexData()
}
}, },
watch: { watch: {
timeFilter () { timeFilter () {
@@ -849,11 +763,11 @@ export default {
const rangeParam = query.range const rangeParam = query.range
const startTimeParam = query.startTime const startTimeParam = query.startTime
const endTimeParam = query.endTime const endTimeParam = query.endTime
// 优先级url > config.js > 默认值。 // 若url携带了使用携带的值否则使用默认值。
const dateRangeValue = rangeParam ? parseInt(rangeParam) : (DEFAULT_TIME_FILTER_RANGE.entity.list || 60) const dateRangeValue = rangeParam ? parseInt(query.range) : 60
const timeFilter = ref({ dateRangeValue }) const timeFilter = ref({ dateRangeValue })
if (!startTimeParam || !endTimeParam) { if (!startTimeParam || !endTimeParam) {
const { startTime, endTime } = getNowTime(dateRangeValue) const { startTime, endTime } = getNowTime(60)
timeFilter.value.startTime = startTime timeFilter.value.startTime = startTime
timeFilter.value.endTime = endTime timeFilter.value.endTime = endTime
} else { } else {
@@ -867,11 +781,9 @@ export default {
pageSize: query.pageSize ? parseInt(query.pageSize) : defaultPageSize, pageSize: query.pageSize ? parseInt(query.pageSize) : defaultPageSize,
total: 0 total: 0
}) })
const isHideRelatedEntities = ref(query.hideRelated ? JSON.parse(query.hideRelated) : false) // 隐藏相关实体默认false不隐藏
return { return {
timeFilter, timeFilter,
pageObj, pageObj
isHideRelatedEntities
} }
}, },
beforeUnmount () { beforeUnmount () {

View File

@@ -5,7 +5,7 @@
<div class="graph-detail__icon"><i :class="iconClass"></i></div> <div class="graph-detail__icon"><i :class="iconClass"></i></div>
<div class="graph-detail-header"> <div class="graph-detail-header">
<div class="entity-graph-type">{{entityTypeName}}</div> <div class="entity-graph-type">{{ $_.get(node, 'myData.entityType') ? entityType[$_.get(node, 'myData.entityType')] : '-' }}</div>
<div class="graph-basic-info"> <div class="graph-basic-info">
<div class="graph-basic-info-name__block"> <div class="graph-basic-info-name__block">
<div class="graph-basic-info-name" :title="$_.get(node, 'id', '')" id="entityName">{{ $_.get(node, 'id', '') }}</div> <div class="graph-basic-info-name" :title="$_.get(node, 'id', '')" id="entityName">{{ $_.get(node, 'id', '') }}</div>
@@ -144,27 +144,6 @@ export default {
} }
return className return className
}, },
entityTypeName () {
const type = _.get(this.node, 'myData.entityType', '')
let entityTypeName = '-'
switch (type) {
case ('ip'): {
entityTypeName = 'IP'
break
}
case ('domain'): {
entityTypeName = this.$t('overall.domain')
break
}
case ('app'): {
entityTypeName = 'APP'
break
}
default:
break
}
return entityTypeName
},
handleDate () { handleDate () {
return function (key) { return function (key) {
const date = _.get(this.node, key, '') const date = _.get(this.node, key, '')

View File

@@ -11,7 +11,6 @@
v-for="(data, index) in listData" v-for="(data, index) in listData"
:entity="data" :entity="data"
:listMode="listMode" :listMode="listMode"
:keywordList="keywordList"
:timeFilter="timeFilter" :timeFilter="timeFilter"
:key="index" :key="index"
:ref="`entityRow${index}`" :ref="`entityRow${index}`"
@@ -66,8 +65,7 @@ export default {
pageObj: Object, pageObj: Object,
loading: Boolean, loading: Boolean,
timeFilter: Object, timeFilter: Object,
listMode: String, listMode: String
keywordList: Array
}, },
components: { components: {
'entity-card': Card, 'entity-card': Card,

View File

@@ -11,20 +11,8 @@
<div class="cn-entity__row"> <div class="cn-entity__row">
<!--标签--> <!--标签-->
<div class="cn-entity__header" style="display: flex;"> <div class="cn-entity__header" style="display: flex;">
<span class="cn-entity__header-title" v-high-light="keywordList">{{ entityData.entityValue || 'Unknown' }}</span> <span class="cn-entity__header-title">{{ entityData.entityValue || 'Unknown' }}</span>
<span v-show="entityData.isRelated"> <span class="entity-detail" style="display: flex;margin-left: 6px;margin-top: 1px;flex-wrap: wrap;margin-bottom: -10px;">
<el-popover
popper-class="my-popper-class"
placement="right"
trigger="hover"
:content="$t('entity.relatedEntities')"
>
<template #reference>
<i class="cn-icon cn-icon-related entity-related-entity"></i>
</template>
</el-popover>
</span>
<span class="entity-detail entity-row-tag" :style="{'margin-top' : entityData.isRelated ? '4px':'1px'}">
<span v-for="(item, index) in levelTwoTags" <span v-for="(item, index) in levelTwoTags"
:key="index" :key="index"
class="entity-tag entity-tag--small margin-r-10 margin-b-10" class="entity-tag entity-tag--small margin-r-10 margin-b-10"
@@ -42,29 +30,29 @@
<div class="basic-info__item"> <div class="basic-info__item">
<i class="cn-icon cn-icon-country"></i> <i class="cn-icon cn-icon-country"></i>
<span class="row-item-label">{{ $t('overall.country') }}&nbsp;:&nbsp;&nbsp;</span> <span class="row-item-label">{{ $t('overall.country') }}&nbsp;:&nbsp;&nbsp;</span>
<span class="row-item-value" v-high-light="keywordList">{{ $_.get(entityData, 'location.country', '-') || '-' }}</span> <span class="row-item-value">{{ $_.get(entityData, 'location.country', '-') || '-' }}</span>
</div> </div>
<div class="basic-info__item1"> <div class="basic-info__item">
<i class="cn-icon cn-icon-position"></i> <i class="cn-icon cn-icon-position"></i>
<span class="row-item-label">{{ $t('overall.city') }}&nbsp;:&nbsp;&nbsp;</span> <span class="row-item-label">{{ $t('overall.city') }}&nbsp;:&nbsp;&nbsp;</span>
<span class="row-item-value high-location" v-high-light="keywordList">{{ entityData.location ? ipLocationRegion(entityData.location) : '-' }}</span> <span class="row-item-value">{{ entityData.location ? ipLocationRegion(entityData.location) : '-' }}</span>
</div> </div>
<div class="basic-info__item"> <div class="basic-info__item">
<i class="cn-icon cn-icon-cloud"></i> <i class="cn-icon cn-icon-cloud"></i>
<span class="row-item-label">{{ $t('entities.asn') }}&nbsp;:&nbsp;&nbsp;</span> <span class="row-item-label">{{ $t('entities.asn') }}&nbsp;:&nbsp;&nbsp;</span>
<span class="row-item-value" v-high-light="keywordList">{{ $_.get(entityData, 'asn.asn', '-') || '-' }}</span> <span class="row-item-value">{{ $_.get(entityData, 'asn.asn', '-') || '-' }}</span>
</div> </div>
</template> </template>
<template v-else-if="entityData.entityType === 'domain'"> <template v-else-if="entityData.entityType === 'domain'">
<div class="basic-info__item"> <div class="basic-info__item">
<i class="cn-icon cn-icon-category-group"></i> <i class="cn-icon cn-icon-category-group"></i>
<span class="row-item-label">{{ $t('entities.category') }}&nbsp;:&nbsp;&nbsp;</span> <span class="row-item-label">{{ $t('entities.category') }}&nbsp;:&nbsp;&nbsp;</span>
<span class="row-item-value" v-high-light="keywordList">{{ $_.get(entityData, 'category.categoryGroup', '-') || '-' }}</span> <span class="row-item-value">{{ $_.get(entityData, 'category.categoryGroup', '-') || '-' }}</span>
</div> </div>
<div class="basic-info__item"> <div class="basic-info__item">
<i class="cn-icon cn-icon-sub-category"></i> <i class="cn-icon cn-icon-sub-category"></i>
<span class="row-item-label">{{ $t('entities.subcategory') }}&nbsp;:&nbsp;&nbsp;</span> <span class="row-item-label">{{ $t('entities.subcategory') }}&nbsp;:&nbsp;&nbsp;</span>
<span class="row-item-value" v-high-light="keywordList">{{ $_.get(entityData, 'category.categoryName', '-') || '-' }}</span> <span class="row-item-value">{{ $_.get(entityData, 'category.categoryName', '-') || '-' }}</span>
</div> </div>
<div class="basic-info__item"> <div class="basic-info__item">
<i class="cn-icon cn-icon-credit-rating"></i> <i class="cn-icon cn-icon-credit-rating"></i>
@@ -76,7 +64,7 @@
<div class="basic-info__item"> <div class="basic-info__item">
<i class="cn-icon cn-icon-category2"></i> <i class="cn-icon cn-icon-category2"></i>
<span class="row-item-label">{{ $t('entities.category') }}&nbsp;:&nbsp;&nbsp;</span> <span class="row-item-label">{{ $t('entities.category') }}&nbsp;:&nbsp;&nbsp;</span>
<span class="row-item-value" v-high-light="keywordList">{{ $_.get(entityData, 'category.appCategory', '-') || '-' }}</span> <span class="row-item-value">{{ $_.get(entityData, 'category.appCategory', '-') || '-' }}</span>
</div> </div>
<div class="basic-info__item"> <div class="basic-info__item">
<i class="cn-icon cn-icon-sub-category"></i> <i class="cn-icon cn-icon-sub-category"></i>
@@ -158,7 +146,7 @@
<template v-if="!loadingNetworkQuality && score !=='-'"> <template v-if="!loadingNetworkQuality && score !=='-'">
<span v-for="(dot, i) in scoreDot" :key="i" :class="dot.class"></span> <span v-for="(dot, i) in scoreDot" :key="i" :class="dot.class"></span>
</template> </template>
<span style="padding-left: 4px;">{{score}}</span> <span>{{score}}</span>
<loading :loading="loadingNetworkQuality" size="small"></loading> <loading :loading="loadingNetworkQuality" size="small"></loading>
</span> </span>
</div> </div>
@@ -188,7 +176,7 @@
<el-collapse-transition> <el-collapse-transition>
<div class="cn-entity__detail-overview" v-if="!isCollapse"> <div class="cn-entity__detail-overview" v-if="!isCollapse">
<el-divider></el-divider> <el-divider></el-divider>
<detail-overview :entity="entityData" :time-filter="timeFilter" :keywordList="keywordList" @reloadEntity="getEntity" /> <detail-overview :entity="entityData" :time-filter="timeFilter" @reloadEntity="getEntity" />
</div> </div>
</el-collapse-transition> </el-collapse-transition>
</div> </div>
@@ -211,8 +199,7 @@ export default {
props: { props: {
index: Number, index: Number,
timeFilter: Object, timeFilter: Object,
listMode: String, listMode: String
keywordList: Array
}, },
components: { components: {
Loading, Loading,

View File

@@ -8,11 +8,11 @@
</div> </div>
<div class="overview__row"> <div class="overview__row">
<div class="row__label row__label--width130">{{$t('entities.category')}}</div> <div class="row__label row__label--width130">{{$t('entities.category')}}</div>
<div class="row__content" v-high-light="keywordList">{{ $_.get(entity, 'category.appCategory', '-') || '-' }}</div> <div class="row__content">{{$_.get(entity, 'category.appCategory', '-') || '-'}}</div>
</div> </div>
<div class="overview__row"> <div class="overview__row">
<div class="row__label row__label--width130">{{$t('entities.subcategory')}}</div> <div class="row__label row__label--width130">{{$t('entities.subcategory')}}</div>
<div class="row__content" v-high-light="keywordList">{{ $_.get(entity, 'category.appSubcategory', '-') || '-' }}</div> <div class="row__content">{{$_.get(entity, 'category.appSubcategory', '-') || '-'}}</div>
</div> </div>
<div class="overview__row"> <div class="overview__row">
<div class="row__label row__label--width130">{{$t('entities.riskLevel')}}</div> <div class="row__label row__label--width130">{{$t('entities.riskLevel')}}</div>
@@ -20,9 +20,7 @@
</div> </div>
<div class="overview__row"> <div class="overview__row">
<div class="row__label row__label--width130">{{$t('overall.remark')}}</div> <div class="row__label row__label--width130">{{$t('overall.remark')}}</div>
<div class="row__content"> <div class="row__content">{{$_.get(entity, 'category.appDescription', '-') || '-'}}</div>
<span v-high-light="keywordList">{{ $_.get(entity, 'category.appDescription', '-') || '-' }}</span>
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -91,7 +89,7 @@
<loading :loading="loadingRelationshipOne" size="small" style="left: 1rem;"></loading> <loading :loading="loadingRelationshipOne" size="small" style="left: 1rem;"></loading>
</div> </div>
<div class="data-item high-light-block" v-high-light="keywordList" v-show="item.show" v-for="(item, index) in relationshipDataOne" :key="index"> <div class="data-item" v-show="item.show" v-for="(item, index) in relationshipDataOne" :key="index">
{{item.value}} {{item.value}}
</div> </div>
<div v-if="relationshipDataOne.length===0 && !loadingRelationshipOne">-</div> <div v-if="relationshipDataOne.length===0 && !loadingRelationshipOne">-</div>
@@ -100,7 +98,7 @@
<div class="data-item show-more-related" id="related-app-more" @click.stop="showMoreApp" style="position: relative">...</div> <div class="data-item show-more-related" id="related-app-more" @click.stop="showMoreApp" style="position: relative">...</div>
<div v-if="isShowMoreApp" class="app-popover_block" id="showRelatedApp"> <div v-if="isShowMoreApp" class="app-popover_block" id="showRelatedApp">
<div class="popover-content" v-for="(item, index) in relationshipDataOne" :key="index"> <div class="popover-content" v-for="(item, index) in relationshipDataOne" :key="index">
<span v-if="!item.show" class="high-light-block" v-high-light="keywordList">{{item.value}}</span> <span v-if="!item.show">{{item.value}}</span>
</div> </div>
</div> </div>
</div> </div>
@@ -115,7 +113,7 @@
<loading :loading="loadingRelationshipTwo" size="small" style="left: 1rem;"></loading> <loading :loading="loadingRelationshipTwo" size="small" style="left: 1rem;"></loading>
</div> </div>
<div class="data-item high-light-block" v-high-light="keywordList" v-show="item.show" v-for="(item, index) in relationshipDataTwo" :key="index"> <div class="data-item" v-show="item.show" v-for="(item, index) in relationshipDataTwo" :key="index">
{{item.value}} {{item.value}}
</div> </div>
<div v-if="relationshipDataTwo.length===0 && !loadingRelationshipTwo">-</div> <div v-if="relationshipDataTwo.length===0 && !loadingRelationshipTwo">-</div>
@@ -124,7 +122,7 @@
<div class="data-item show-more-related" id="related-domain-more" @click.stop="showMoreDomain" style="position: relative">...</div> <div class="data-item show-more-related" id="related-domain-more" @click.stop="showMoreDomain" style="position: relative">...</div>
<div v-if="isShowMoreDomain" class="domain-popover_block" id="showRelatedDomain"> <div v-if="isShowMoreDomain" class="domain-popover_block" id="showRelatedDomain">
<div v-for="(item, index) in relationshipDataTwo" :key="index"> <div v-for="(item, index) in relationshipDataTwo" :key="index">
<span v-if="!item.show" class="high-light-block" v-high-light="keywordList">{{item.value}}</span> <span v-if="!item.show">{{item.value}}</span>
</div> </div>
</div> </div>
</div> </div>
@@ -172,7 +170,7 @@
</div> </div>
<div class="overview__row overview__row--small-font" v-for="(security, index) in entityData.securityList" :key="index"> <div class="overview__row overview__row--small-font" v-for="(security, index) in entityData.securityList" :key="index">
<div class="row__label row__label--width130">{{security.startTime ? dateFormatByAppearance(Number(security.startTime)) : '-'}}</div> <div class="row__label row__label--width130">{{dateFormatByAppearance(security.startTime) || '-'}}</div>
<div class="row__content row__content--width90"> <div class="row__content row__content--width90">
<div class="alert-level-tag alert-level-tag--high" :class="iconClass(security)">{{security.eventSeverity}}</div> <div class="alert-level-tag alert-level-tag--high" :class="iconClass(security)">{{security.eventSeverity}}</div>
</div> </div>
@@ -216,7 +214,7 @@ import Chart from '@/views/charts/Chart'
import _ from 'lodash' import _ from 'lodash'
import axios from 'axios' import axios from 'axios'
import relatedServer from '@/mixins/relatedServer' import relatedServer from '@/mixins/relatedServer'
import { dateFormatByAppearance, getMillisecond, getSecond, getNowTime } from '@/utils/date-util' import { dateFormatByAppearance, getMillisecond } from '@/utils/date-util'
import Loading from '@/components/common/Loading' import Loading from '@/components/common/Loading'
import { ref } from 'vue' import { ref } from 'vue'
@@ -227,9 +225,6 @@ export default {
Chart, Chart,
Loading Loading
}, },
props: {
keywordList: Array
},
data () { data () {
return { return {
// entityData: {} // entityData: {}
@@ -320,21 +315,9 @@ export default {
methods: { methods: {
getMillisecond, getMillisecond,
dateFormatByAppearance, dateFormatByAppearance,
getQueryParams (dateRangeValue) { getQueryParams () {
if (dateRangeValue) { return {
// range取 config.js 中配置的值 resource: this.entity.entityValue
const { startTime, endTime } = getNowTime(dateRangeValue)
return {
startTime: getSecond(startTime),
endTime: getSecond(endTime),
resource: this.entity.entityValue
}
} else {
return {
startTime: getSecond(this.timeFilter.startTime),
endTime: getSecond(this.timeFilter.endTime),
resource: this.entity.entityValue
}
} }
}, },
getPerformanceQueryParams () { getPerformanceQueryParams () {

View File

@@ -1,13 +1,13 @@
<template> <template>
<div class="entity-detail-overview"> <div class="entity-detail-overview">
<template v-if="entity.entityType === 'ip'"> <template v-if="entity.entityType === 'ip'">
<ip-overview :entity="entity" :time-filter="timeFilter" :keywordList="keywordList" @reloadEntity="getEntity"></ip-overview> <ip-overview :entity="entity" :time-filter="timeFilter" @reloadEntity="getEntity"></ip-overview>
</template> </template>
<template v-else-if="entity.entityType === 'domain'"> <template v-else-if="entity.entityType === 'domain'">
<domain-overview :entity="entity" :time-filter="timeFilter" :keywordList="keywordList" @reloadEntity="getEntity"></domain-overview> <domain-overview :entity="entity" :time-filter="timeFilter" @reloadEntity="getEntity"></domain-overview>
</template> </template>
<template v-else-if="entity.entityType === 'app'"> <template v-else-if="entity.entityType === 'app'">
<app-overview :entity="entity" :time-filter="timeFilter" :keywordList="keywordList" @reloadEntity="getEntity"></app-overview> <app-overview :entity="entity" :time-filter="timeFilter" @reloadEntity="getEntity"></app-overview>
</template> </template>
</div> </div>
</template> </template>
@@ -22,8 +22,7 @@ export default {
name: 'DetailOverview', name: 'DetailOverview',
props: { props: {
entity: Object, entity: Object,
timeFilter: Object, timeFilter: Object
keywordList: Array
}, },
components: { components: {
'domain-overview': Domain, 'domain-overview': Domain,

View File

@@ -4,11 +4,11 @@
<div class="overview__content"> <div class="overview__content">
<div class="overview__row"> <div class="overview__row">
<div class="row__label row__label--width130">{{$t('entities.category')}}</div> <div class="row__label row__label--width130">{{$t('entities.category')}}</div>
<div class="row__content" v-high-light="keywordList">{{ $_.get(entityData, 'category.categoryName', '-') || '-' }}</div> <div class="row__content">{{$_.get(entityData, 'category.categoryName', '-') || '-'}}</div>
</div> </div>
<div class="overview__row"> <div class="overview__row">
<div class="row__label row__label--width130">{{$t('entities.domainDetail.categoryGroup')}}</div> <div class="row__label row__label--width130">{{$t('entities.domainDetail.categoryGroup')}}</div>
<div class="row__content" v-high-light="keywordList">{{ $_.get(entityData, 'category.categoryGroup', '-') || '-' }}</div> <div class="row__content">{{$_.get(entityData, 'category.categoryGroup', '-') || '-'}}</div>
</div> </div>
<div class="overview__row"> <div class="overview__row">
<div class="row__label row__label--width130">{{$t('entities.reputationLevel')}}</div> <div class="row__label row__label--width130">{{$t('entities.reputationLevel')}}</div>
@@ -20,7 +20,7 @@
</div> </div>
<div class="overview__row"> <div class="overview__row">
<div class="row__label row__label--width130">{{$t('entities.org')}}</div> <div class="row__label row__label--width130">{{$t('entities.org')}}</div>
<div class="row__content" v-high-light="keywordList">{{ $_.get(entityData, 'whois.registrantOrg', '-') || '-' }}</div> <div class="row__content">{{$_.get(entityData, 'whois.registrantOrg', '-') || '-'}}</div>
</div> </div>
<div class="overview__row"> <div class="overview__row">
<div class="row__label row__label--width130">{{$t('entities.icpCompanyName')}}</div> <div class="row__label row__label--width130">{{$t('entities.icpCompanyName')}}</div>
@@ -97,7 +97,7 @@
<loading :loading="loadingRelationshipOne" size="small" style="left: 1rem;"></loading> <loading :loading="loadingRelationshipOne" size="small" style="left: 1rem;"></loading>
</div> </div>
<div class="data-item high-light-block" v-high-light="keywordList" v-show="item.show" v-for="(item, index) in relationshipDataOne" :key="index"> <div class="data-item" v-show="item.show" v-for="(item, index) in relationshipDataOne" :key="index">
{{item.value}} {{item.value}}
</div> </div>
<div v-if="relationshipDataOne.length===0 && !loadingRelationshipOne">-</div> <div v-if="relationshipDataOne.length===0 && !loadingRelationshipOne">-</div>
@@ -106,7 +106,7 @@
<div class="data-item show-more-related" id="related-app-more" @click.stop="showMoreApp" style="position: relative">...</div> <div class="data-item show-more-related" id="related-app-more" @click.stop="showMoreApp" style="position: relative">...</div>
<div v-if="isShowMoreApp" class="app-popover_block" id="showRelatedApp"> <div v-if="isShowMoreApp" class="app-popover_block" id="showRelatedApp">
<div class="popover-content" v-for="(item, index) in relationshipDataOne" :key="index"> <div class="popover-content" v-for="(item, index) in relationshipDataOne" :key="index">
<span v-if="!item.show" class="high-light-block" v-high-light="keywordList">{{item.value}}</span> <span v-if="!item.show">{{item.value}}</span>
</div> </div>
</div> </div>
</div> </div>
@@ -119,7 +119,7 @@
<div v-if="loadingRelationshipTwo" style="position: relative;width: 450px;"> <div v-if="loadingRelationshipTwo" style="position: relative;width: 450px;">
<loading :loading="loadingRelationshipTwo" size="small" style="left: 1rem;"></loading> <loading :loading="loadingRelationshipTwo" size="small" style="left: 1rem;"></loading>
</div> </div>
<div class="data-item high-light-block" v-high-light="keywordList" v-show="item.show" v-for="(item, index) in relationshipDataTwo" :key="index"> <div class="data-item" v-show="item.show" v-for="(item, index) in relationshipDataTwo" :key="index">
{{item.value}} {{item.value}}
</div> </div>
<div v-if="relationshipDataTwo.length===0 && !loadingRelationshipTwo">-</div> <div v-if="relationshipDataTwo.length===0 && !loadingRelationshipTwo">-</div>
@@ -128,7 +128,7 @@
<div class="data-item show-more-related" id="related-domain-more" @click.stop="showMoreDomain" style="position: relative">...</div> <div class="data-item show-more-related" id="related-domain-more" @click.stop="showMoreDomain" style="position: relative">...</div>
<div v-if="isShowMoreDomain" class="domain-popover_block" id="showRelatedDomain"> <div v-if="isShowMoreDomain" class="domain-popover_block" id="showRelatedDomain">
<div v-for="(item, index) in relationshipDataTwo" :key="index"> <div v-for="(item, index) in relationshipDataTwo" :key="index">
<span v-if="!item.show" class="high-light-block" v-high-light="keywordList">{{item.value}}</span> <span v-if="!item.show">{{item.value}}</span>
</div> </div>
</div> </div>
</div> </div>
@@ -149,7 +149,7 @@
<div class="row__content">{{entityData.performanceNum}}</div> <div class="row__content">{{entityData.performanceNum}}</div>
</div> </div>
<div class="overview__row overview__row--small-font" v-for="(performance, index) in entityData.performanceList" :key="index"> <div class="overview__row overview__row--small-font" v-for="(performance, index) in entityData.performanceList" :key="index">
<div class="row__label row__label--width130">{{performance.startTime ? dateFormatByAppearance(Number(performance.startTime)) : '-'}}</div> <div class="row__label row__label--width130">{{dateFormatByAppearance(performance.startTime) || '-'}}</div>
<div class="row__content row__content--width90"> <div class="row__content row__content--width90">
<div class="alert-level-tag alert-level-tag--high" :class="iconClass(performance)">{{performance.eventSeverity}}</div> <div class="alert-level-tag alert-level-tag--high" :class="iconClass(performance)">{{performance.eventSeverity}}</div>
</div> </div>
@@ -176,7 +176,7 @@
</div> </div>
<div class="overview__row overview__row--small-font" v-for="(security, i) in entityData.securityList" :key="i"> <div class="overview__row overview__row--small-font" v-for="(security, i) in entityData.securityList" :key="i">
<div class="row__label row__label--width130">{{security.startTime ? dateFormatByAppearance(Number(security.startTime)) : '-'}}</div> <div class="row__label row__label--width130">{{dateFormatByAppearance(getMillisecond(security.startTime)) || '-'}}</div>
<div class="row__content row__content--width90"> <div class="row__content row__content--width90">
<div class="alert-level-tag alert-level-tag--high" :class="iconClass(security)">{{security.eventSeverity}}</div> <div class="alert-level-tag alert-level-tag--high" :class="iconClass(security)">{{security.eventSeverity}}</div>
</div> </div>
@@ -219,7 +219,7 @@ import Chart from '@/views/charts/Chart'
import _ from 'lodash' import _ from 'lodash'
import axios from 'axios' import axios from 'axios'
import relatedServer from '@/mixins/relatedServer' import relatedServer from '@/mixins/relatedServer'
import { dateFormatByAppearance, getMillisecond, getSecond, getNowTime } from '@/utils/date-util' import { dateFormatByAppearance, getMillisecond, getSecond } from '@/utils/date-util'
import Loading from '@/components/common/Loading' import Loading from '@/components/common/Loading'
import { ref } from 'vue' import { ref } from 'vue'
@@ -229,9 +229,6 @@ export default {
Loading, Loading,
Chart Chart
}, },
props: {
keywordList: Array
},
mixins: [entityDetailMixin, relatedServer], mixins: [entityDetailMixin, relatedServer],
data () { data () {
return { return {
@@ -324,21 +321,16 @@ export default {
methods: { methods: {
getMillisecond, getMillisecond,
dateFormatByAppearance, dateFormatByAppearance,
getQueryParams (dateRangeValue) { getQueryParams () {
if (dateRangeValue) { return {
// range取 config.js 中配置的值 resource: this.entity.entityValue
const { startTime, endTime } = getNowTime(dateRangeValue) }
return { },
startTime: getSecond(startTime), getQueryParamsWithTime () {
endTime: getSecond(endTime), return {
resource: this.entity.entityValue startTime: getSecond(this.timeFilter.startTime),
} endTime: getSecond(this.timeFilter.endTime),
} else { domain: this.entity.entityValue
return {
startTime: getSecond(this.timeFilter.startTime),
endTime: getSecond(this.timeFilter.endTime),
resource: this.entity.entityValue
}
} }
}, },
getPerformanceQueryParams () { getPerformanceQueryParams () {
@@ -360,7 +352,7 @@ export default {
}) })
}, },
getBasicProperties () { getBasicProperties () {
axios.get(this.basicProperties, { params: this.getQueryParams() }).then(response => { axios.get(this.basicProperties, { params: this.getQueryParamsWithTime() }).then(response => {
if (response.status === 200) { if (response.status === 200) {
this.entityData = { this.entityData = {
...this.entityData, ...this.entityData,

View File

@@ -10,22 +10,18 @@
<img v-if="entity.location.country===countryNameIdMapping.Unknown || !countryNameIdMapping[entity.location.country]" src="../../../../../public/images/flag/Unknown.svg" class="filter-country-flag"> <img v-if="entity.location.country===countryNameIdMapping.Unknown || !countryNameIdMapping[entity.location.country]" src="../../../../../public/images/flag/Unknown.svg" class="filter-country-flag">
<img v-else :src="require(`../../../../../public/images/flag/${countryNameIdMapping[entity.location.country]}.png`)" class="filter-country-flag" > <img v-else :src="require(`../../../../../public/images/flag/${countryNameIdMapping[entity.location.country]}.png`)" class="filter-country-flag" >
</div> </div>
<span v-high-light="keywordList" class="high-location">{{ ipLocationRegion(entity.location) }}</span> {{ipLocationRegion(entity.location)}}
</div> </div>
<div v-else>-</div> <div v-else>-</div>
</div> </div>
</div> </div>
<div class="overview__row"> <div class="overview__row">
<div class="row__label row__label--width130">ASN</div> <div class="row__label row__label--width130">ASN</div>
<div class="row__content" v-high-light="keywordList">{{ $_.get(entity, 'asn.asn', '-') || '-' }}</div> <div class="row__content">{{$_.get(entity, 'asn.asn', '-') || '-'}}</div>
</div>
<div class="overview__row">
<div class="row__label row__label--width130">ISP</div>
<div class="row__content" v-high-light="keywordList">{{ $_.get(entityData, 'location.isp', '-') || '-' }}</div>
</div> </div>
<div class="overview__row"> <div class="overview__row">
<div class="row__label row__label--width130">{{$t('entities.openPort')}}</div> <div class="row__label row__label--width130">{{$t('entities.openPort')}}</div>
<div class="row__content high-location" style="word-break: break-word;" v-high-light="keywordList">{{ openPort }}</div> <div class="row__content" style="word-break: break-word;">{{ openPort }}</div>
</div> </div>
</div> </div>
</div> </div>
@@ -132,7 +128,7 @@
<loading :loading="loadingRelationshipOne" size="small" style="left: 1rem;"></loading> <loading :loading="loadingRelationshipOne" size="small" style="left: 1rem;"></loading>
</div> </div>
<div class="data-item high-light-block" v-high-light="keywordList" v-show="item.show" v-for="(item, index) in relationshipDataOne" :key="index"> <div class="data-item" v-show="item.show" v-for="(item, index) in relationshipDataOne" :key="index">
{{item.value}} {{item.value}}
</div> </div>
<div v-if="relationshipDataOne.length===0 && !loadingRelationshipOne">-</div> <div v-if="relationshipDataOne.length===0 && !loadingRelationshipOne">-</div>
@@ -141,7 +137,7 @@
<div class="data-item show-more-related" id="related-app-more" @click.stop="showMoreApp" style="position: relative">...</div> <div class="data-item show-more-related" id="related-app-more" @click.stop="showMoreApp" style="position: relative">...</div>
<div v-if="isShowMoreApp" class="app-popover_block" id="showRelatedApp"> <div v-if="isShowMoreApp" class="app-popover_block" id="showRelatedApp">
<div class="popover-content" v-for="(item, index) in relationshipDataOne" :key="index"> <div class="popover-content" v-for="(item, index) in relationshipDataOne" :key="index">
<span v-if="!item.show" class="high-light-block" v-high-light="keywordList">{{item.value}}</span> <span v-if="!item.show">{{item.value}}</span>
</div> </div>
</div> </div>
</div> </div>
@@ -155,7 +151,7 @@
<loading :loading="loadingRelationshipTwo" size="small" style="left: 1rem;"></loading> <loading :loading="loadingRelationshipTwo" size="small" style="left: 1rem;"></loading>
</div> </div>
<div class="data-item high-light-block" v-high-light="keywordList" v-show="item.show" v-for="(item, index) in relationshipDataTwo" :key="index"> <div class="data-item" v-show="item.show" v-for="(item, index) in relationshipDataTwo" :key="index">
{{item.value}} {{item.value}}
</div> </div>
<div v-if="relationshipDataTwo.length===0 && !loadingRelationshipTwo">-</div> <div v-if="relationshipDataTwo.length===0 && !loadingRelationshipTwo">-</div>
@@ -164,7 +160,7 @@
<div class="data-item show-more-related" id="related-domain-more" @click.stop="showMoreDomain" style="position: relative">...</div> <div class="data-item show-more-related" id="related-domain-more" @click.stop="showMoreDomain" style="position: relative">...</div>
<div v-if="isShowMoreDomain" class="domain-popover_block" id="showRelatedDomain"> <div v-if="isShowMoreDomain" class="domain-popover_block" id="showRelatedDomain">
<div v-for="(item, index) in relationshipDataTwo" :key="index"> <div v-for="(item, index) in relationshipDataTwo" :key="index">
<span v-if="!item.show" class="high-light-block" v-high-light="keywordList">{{item.value}}</span> <span v-if="!item.show">{{item.value}}</span>
</div> </div>
</div> </div>
</div> </div>
@@ -185,7 +181,7 @@
<div class="row__content">{{entityData.performanceNum}}</div> <div class="row__content">{{entityData.performanceNum}}</div>
</div> </div>
<div class="overview__row overview__row--small-font" v-for="(performance, index) in entityData.performanceList" :key="index"> <div class="overview__row overview__row--small-font" v-for="(performance, index) in entityData.performanceList" :key="index">
<div class="row__label row__label--width130">{{performance.startTime ? dateFormatByAppearance(Number(performance.startTime)) : '-'}}</div> <div class="row__label row__label--width130">{{dateFormatByAppearance(performance.startTime) || '-'}}</div>
<div class="row__content row__content--width90"> <div class="row__content row__content--width90">
<div class="alert-level-tag alert-level-tag--high" :class="iconClass(performance)">{{performance.eventSeverity}}</div> <div class="alert-level-tag alert-level-tag--high" :class="iconClass(performance)">{{performance.eventSeverity}}</div>
</div> </div>
@@ -212,7 +208,7 @@
</div> </div>
<div class="overview__row overview__row--small-font" v-for="(security, index) in entityData.securityList" :key="index"> <div class="overview__row overview__row--small-font" v-for="(security, index) in entityData.securityList" :key="index">
<div class="row__label row__label--width130">{{security.startTime ? dateFormatByAppearance(Number(security.startTime)) : '-'}}</div> <div class="row__label row__label--width130">{{dateFormatByAppearance(security.startTime) || '-'}}</div>
<div class="row__content row__content--width90"> <div class="row__content row__content--width90">
<div class="alert-level-tag alert-level-tag--high" :class="iconClass(security)">{{security.eventSeverity}}</div> <div class="alert-level-tag alert-level-tag--high" :class="iconClass(security)">{{security.eventSeverity}}</div>
</div> </div>
@@ -255,7 +251,7 @@ import { valueToRangeValue } from '@/utils/unit-convert'
import Chart from '@/views/charts/Chart' import Chart from '@/views/charts/Chart'
import _ from 'lodash' import _ from 'lodash'
import relatedServer from '@/mixins/relatedServer' import relatedServer from '@/mixins/relatedServer'
import { dateFormatByAppearance, getMillisecond, getSecond, getNowTime } from '@/utils/date-util' import { dateFormatByAppearance, getMillisecond } from '@/utils/date-util'
import Loading from '@/components/common/Loading' import Loading from '@/components/common/Loading'
import axios from 'axios' import axios from 'axios'
@@ -266,9 +262,6 @@ export default {
Loading, Loading,
Chart Chart
}, },
props: {
keywordList: Array
},
data () { data () {
return { return {
entityType: 'ip', entityType: 'ip',
@@ -408,21 +401,9 @@ export default {
methods: { methods: {
getMillisecond, getMillisecond,
dateFormatByAppearance, dateFormatByAppearance,
getQueryParams (dateRangeValue) { getQueryParams () {
if (dateRangeValue) { return {
// range取 config.js 中配置的值 resource: this.entity.entityValue
const { startTime, endTime } = getNowTime(dateRangeValue)
return {
startTime: getSecond(startTime),
endTime: getSecond(endTime),
resource: this.entity.entityValue
}
} else {
return {
startTime: getSecond(this.timeFilter.startTime),
endTime: getSecond(this.timeFilter.endTime),
resource: this.entity.entityValue
}
} }
}, },
getPerformanceQueryParams () { getPerformanceQueryParams () {
@@ -449,8 +430,8 @@ export default {
}, },
getOpenPort () { getOpenPort () {
const params = { const params = {
startTime: getSecond(this.timeFilter.startTime), // startTime: getSecond(this.timeFilter.startTime),
endTime: getSecond(this.timeFilter.endTime), // endTime: getSecond(this.timeFilter.endTime),
resource: this.entity.entityValue resource: this.entity.entityValue
} }

View File

@@ -121,7 +121,7 @@ export default {
this.sentChart = echarts.init(document.getElementById(`entityDetailSend${this.entityName}`)) this.sentChart = echarts.init(document.getElementById(`entityDetailSend${this.entityName}`))
this.receivedChart = echarts.init(document.getElementById(`entityDetailReceived${this.entityName}`)) this.receivedChart = echarts.init(document.getElementById(`entityDetailReceived${this.entityName}`))
this.loadingTraffic = true this.loadingTraffic = true
axios.get(this.trafficUrl, { params: this.getQueryParams(DEFAULT_TIME_FILTER_RANGE.entity.trafficLine) }).then(response => { axios.get(this.trafficUrl, { params: this.getQueryParams() }).then(response => {
if (response.status === 200 && response.data.data.result && response.data.data.result.length > 0) { if (response.status === 200 && response.data.data.result && response.data.data.result.length > 0) {
response.data.data.result.forEach(t => { response.data.data.result.forEach(t => {
if (t.legend === 'rate') { if (t.legend === 'rate') {
@@ -278,7 +278,7 @@ export default {
this.performanceScoreData = {} this.performanceScoreData = {}
this.scoreDataState = false this.scoreDataState = false
if (this.networkQuantityUrl) { if (this.networkQuantityUrl) {
axios.get(this.networkQuantityUrl, { params: this.getQueryParams(DEFAULT_TIME_FILTER_RANGE.entity.trafficLine) }).then(response => { axios.get(this.networkQuantityUrl, { params: this.getQueryParams() }).then(response => {
if (response.status === 200) { if (response.status === 200) {
this.performanceScoreData = { this.performanceScoreData = {
establishLatencyMs: response.data.data.result.establishLatencyMsAvg || null, establishLatencyMs: response.data.data.result.establishLatencyMsAvg || null,
@@ -347,7 +347,7 @@ export default {
queryEntityDetailPerformance () { queryEntityDetailPerformance () {
this.loadingAlert = true this.loadingAlert = true
axios.get(this.performanceUrl, { params: this.getQueryParams(DEFAULT_TIME_FILTER_RANGE.entity.performanceEvent) }).then(response => { axios.get(this.performanceUrl, { params: this.getQueryParams() }).then(response => {
if (response.status === 200) { if (response.status === 200) {
this.entityData.performanceNum = response.data.data.result.length this.entityData.performanceNum = response.data.data.result.length
this.performanceData = response.data.data.result this.performanceData = response.data.data.result
@@ -359,7 +359,7 @@ export default {
queryEntityDetailSecurity () { queryEntityDetailSecurity () {
this.loadingSecurityEvents = true this.loadingSecurityEvents = true
axios.get(this.securityUrl, { params: this.getQueryParams(DEFAULT_TIME_FILTER_RANGE.entity.securityEvent) }).then(response => { axios.get(this.securityUrl, { params: this.getQueryParams() }).then(response => {
if (response.status === 200) { if (response.status === 200) {
this.entityData.securityNum = response.data.data.result.length this.entityData.securityNum = response.data.data.result.length
this.securityData = response.data.data.result this.securityData = response.data.data.result
@@ -436,9 +436,9 @@ export default {
queryEntityDetail () { queryEntityDetail () {
this.queryEntityDetailTraffic() this.queryEntityDetailTraffic()
// this.queryEntityDetailPerformance() // this.queryEntityDetailPerformance()
this.queryEntityDetailSecurity() // this.queryEntityDetailSecurity()
this.queryEntityDetailNetworkQuantity() this.queryEntityDetailNetworkQuantity()
/* if (this.entity.entityType === 'ip') { /*if (this.entity.entityType === 'ip') {
if (!this.entityData.dnsServerRole) { if (!this.entityData.dnsServerRole) {
this.loadingDns = true this.loadingDns = true
} }
@@ -449,7 +449,7 @@ export default {
this.queryDnsServerInfoRate() this.queryDnsServerInfoRate()
}, 200) }, 200)
}) })
} */ }*/
}, },
resize () { resize () {

Some files were not shown because too many files have changed in this diff Show More