Compare commits
91 Commits
dev-23.10-
...
dev-23.11
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e26d2b40ab | ||
|
|
6c1f1ed71b | ||
|
|
b4b72fc1e1 | ||
|
|
b3d4bbd440 | ||
|
|
6c90ebe7bc | ||
|
|
ef3994e14a | ||
|
|
abc1d07e6c | ||
|
|
38af43b322 | ||
|
|
90ed543a84 | ||
|
|
c66a6b7f59 | ||
|
|
a0af36b7c0 | ||
|
|
f95dc60cd3 | ||
|
|
7d64868ce0 | ||
|
|
62a7a629e5 | ||
|
|
e3c6c21545 | ||
|
|
3b2eaf3851 | ||
|
|
ee05f47f2d | ||
|
|
07dd16f2c2 | ||
|
|
9103c454c2 | ||
|
|
e5a7c2abfa | ||
|
|
e288e20fd7 | ||
|
|
ec746f0fc7 | ||
|
|
4ca33e9ede | ||
|
|
b8105a4565 | ||
|
|
29157ae7d3 | ||
|
|
9c0ce493ab | ||
|
|
4662061fc5 | ||
|
|
0eb0346abc | ||
|
|
c8926177f7 | ||
|
|
5aa5d77511 | ||
|
|
38368a6cb8 | ||
|
|
051aeadbca | ||
|
|
8c2119e773 | ||
|
|
cb70fb0236 | ||
|
|
853fa79d4c | ||
|
|
2f919d1774 | ||
|
|
360fffde68 | ||
|
|
bb2a7676e6 | ||
|
|
de698f0a71 | ||
|
|
1c1d354a6c | ||
|
|
8126618e54 | ||
|
|
5a8796688a | ||
|
|
be36b2604b | ||
|
|
330a4b0d3b | ||
|
|
1410f890f3 | ||
|
|
78105475fb | ||
|
|
02a9f35070 | ||
|
|
c89397da97 | ||
|
|
36c3db5dee | ||
|
|
366bb8f17f | ||
|
|
1c00f568fa | ||
|
|
93be846064 | ||
|
|
ffb822d65d | ||
|
|
f8e9d36c8a | ||
|
|
241665cd80 | ||
|
|
ee57ca4c6c | ||
|
|
2bb6c54cab | ||
|
|
65827d27e4 | ||
|
|
98948ff179 | ||
|
|
74dc057090 | ||
|
|
e8959bab27 | ||
|
|
a7ce777e10 | ||
|
|
d7d450222b | ||
|
|
3da4b4b20a | ||
|
|
a0d2160b43 | ||
|
|
b94dba9ed3 | ||
|
|
696b03ad40 | ||
|
|
f199442c60 | ||
|
|
889903bb46 | ||
|
|
e12d76e2ad | ||
|
|
29df6ec60e | ||
|
|
20857e1203 | ||
|
|
8d4924a421 | ||
|
|
41d2f48766 | ||
|
|
f151415de6 | ||
|
|
73dec68e23 | ||
|
|
60e821fb16 | ||
|
|
4cb4aba707 | ||
|
|
ba4893dae1 | ||
|
|
19c42021db | ||
|
|
d6c9bd0ee2 | ||
|
|
63fd8b268f | ||
|
|
bd1f755612 | ||
|
|
dd4f5e1fba | ||
|
|
ed1d994d5e | ||
|
|
815af776aa | ||
|
|
a4da1dbfac | ||
|
|
9a3bf1a4af | ||
|
|
6a196ba3f0 | ||
|
|
7b8ca90436 | ||
|
|
90827fd706 |
@@ -3,3 +3,18 @@ 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
|
||||||
|
}
|
||||||
|
|||||||
@@ -54,7 +54,8 @@ export default {
|
|||||||
return {
|
return {
|
||||||
loading: false,
|
loading: false,
|
||||||
username: '',
|
username: '',
|
||||||
pin: ''
|
pin: '',
|
||||||
|
language: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -75,6 +76,9 @@ 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)
|
||||||
}
|
}
|
||||||
@@ -107,6 +111,7 @@ 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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,84 +3,92 @@
|
|||||||
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;
|
||||||
top: 10px;
|
align-items: center;
|
||||||
right: 10px;
|
top: 1px;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
.search__suffix {
|
.search__suffix {
|
||||||
// margin-left: 8px;
|
display: flex;
|
||||||
|
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;
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
.advanced-search--show-list .CodeMirror, .advanced-search--show-list .tag-search {
|
.detections {
|
||||||
border: none;
|
.tag-search, .CodeMirror {
|
||||||
|
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;
|
||||||
@@ -104,6 +112,7 @@
|
|||||||
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;
|
||||||
@@ -167,6 +176,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.entity__search .tag-search {
|
||||||
|
padding-left: 65px;
|
||||||
|
}
|
||||||
|
|
||||||
.el-popover.my-popper-class {
|
.el-popover.my-popper-class {
|
||||||
width: auto !important;
|
width: auto !important;
|
||||||
|
|||||||
@@ -13,11 +13,16 @@
|
|||||||
color: #ccc;
|
color: #ccc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.entity__search {
|
||||||
|
.CodeMirror {
|
||||||
|
padding-left: 60px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* PADDING */
|
/* PADDING */
|
||||||
|
|
||||||
.CodeMirror-lines {
|
.CodeMirror-lines {
|
||||||
padding: 11px 5px; /* Vertical padding around content */
|
padding: 9px 5px; /* Vertical padding around content */
|
||||||
}
|
}
|
||||||
.CodeMirror pre.CodeMirror-line,
|
.CodeMirror pre.CodeMirror-line,
|
||||||
.CodeMirror pre.CodeMirror-line-like {
|
.CodeMirror pre.CodeMirror-line-like {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
&>div {
|
&>div {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cn-header {
|
.cn-header {
|
||||||
|
|||||||
@@ -15,8 +15,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-top: 20px;
|
padding: 20px;
|
||||||
padding: 0 20px 20px;
|
|
||||||
|
|
||||||
.panel__title {
|
.panel__title {
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
|
|||||||
@@ -194,12 +194,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-setting__btn, .form-setting__btn1 {
|
.form-setting__btn, .form-setting__btn1, .policy-form__footer__btn {
|
||||||
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;
|
||||||
@@ -222,8 +223,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.policy-form__footer__btn {
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 8px;
|
||||||
|
|
||||||
.form-setting__btn1 {
|
.btn1 {
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.form-setting__btn1, .policy-form__footer__btn {
|
||||||
.el-button {
|
.el-button {
|
||||||
padding: 0 11px !important;
|
padding: 0 11px !important;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,9 +10,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.detection-form-content {
|
.detection-form-content {
|
||||||
height: 100%;
|
height: calc(100% - 92px);
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
padding-bottom: 40px;
|
padding-bottom: 20px;
|
||||||
|
|
||||||
.detection-form-collapse {
|
.detection-form-collapse {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
@@ -101,6 +101,12 @@
|
|||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
|
|
||||||
|
.policy-form-item {
|
||||||
|
.el-form-item__error {
|
||||||
|
width: 260px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-input--mini .el-input__inner {
|
.el-input--mini .el-input__inner {
|
||||||
@@ -124,6 +130,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.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 {
|
||||||
@@ -137,4 +149,13 @@
|
|||||||
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,15 @@
|
|||||||
|
|
||||||
.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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,98 +2,124 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
width: 280px;
|
width: 280px;
|
||||||
padding: 10px;
|
margin-right: 12px;
|
||||||
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;
|
||||||
|
|
||||||
.detection-filter {
|
.filter-case__header {
|
||||||
display: flex;
|
padding-left: 8px;
|
||||||
flex-direction: column;
|
height: 36px;
|
||||||
margin-bottom: 10px;
|
line-height: 36px;
|
||||||
|
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 {
|
||||||
display: flex;
|
height: 46px;
|
||||||
flex: 0 0 32px;
|
line-height: 46px;
|
||||||
align-items: center;
|
margin: 0 20px;
|
||||||
padding-left: 10px;
|
|
||||||
color: #666;
|
|
||||||
//background-color: #F3F7FA;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
span {
|
|
||||||
font-size: 14px;
|
|
||||||
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: 600;
|
font-weight: 500;
|
||||||
}
|
|
||||||
.new-detection-filter-icon {
|
|
||||||
margin-left: 8px;
|
|
||||||
margin-bottom: 2px;
|
|
||||||
font-weight: bold !important;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.filter__body {
|
.filter__body {
|
||||||
padding: 5px 0 0 15px;
|
width: calc(100% - 30px);
|
||||||
|
margin: 0 10px 0 20px;
|
||||||
|
max-height: 265px;
|
||||||
|
overflow-y: scroll;
|
||||||
|
overflow-x: hidden;
|
||||||
|
|
||||||
.el-checkbox-group {
|
.filter__body-item {
|
||||||
display: flex;
|
height: 26px;
|
||||||
flex-direction: column;
|
line-height: 26px;
|
||||||
|
|
||||||
.el-checkbox {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 5px 0;
|
|
||||||
margin-right: 5px;
|
|
||||||
.el-checkbox__label {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.filter__checkbox-label {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
.severity-color-block {
|
|
||||||
width: 4px;
|
|
||||||
height: 15px;
|
|
||||||
border-radius: 2px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&: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;
|
cursor: pointer;
|
||||||
|
|
||||||
|
.filter__body-item-left {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #353636;
|
color: #353636;
|
||||||
font-weight: 600;
|
font-weight: 400;
|
||||||
margin: -10px;
|
|
||||||
margin-bottom: 10px;
|
.filter__body-item-left-index {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
text-align: center;
|
||||||
|
background: #EFF2F5;
|
||||||
|
border-radius: 2px;
|
||||||
|
margin-right: 6px;
|
||||||
|
font-family: NotoSansHans-Black;
|
||||||
|
font-size: 9px;
|
||||||
|
color: #96A2B0;
|
||||||
|
font-weight: 900;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter__body-item-left-label {
|
||||||
|
max-width: 180px;
|
||||||
|
font-family: NotoSansSChineseRegular;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #353636;
|
||||||
|
font-weight: 400;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter__body-item-right {
|
||||||
|
flex-shrink: 0;
|
||||||
|
font-family: NotoSansSChineseRegular;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #717171;
|
||||||
|
font-weight: 400;
|
||||||
|
margin-right: 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;
|
||||||
|
|||||||
@@ -149,7 +149,7 @@
|
|||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
||||||
.basic-info__item {
|
.basic-info__item, .basic-info__item1 {
|
||||||
padding-right: 30px;
|
padding-right: 30px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -172,6 +172,11 @@
|
|||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.basic-info__item1 {
|
||||||
|
span: {
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.show-detail {
|
.show-detail {
|
||||||
|
|||||||
@@ -203,6 +203,7 @@
|
|||||||
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;
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.explorer-top-tools, .explorer-detection-top-tools {
|
.explorer-top-tools, .explorer-detection-top-tools, .explorer-entity-top-tools {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -46,7 +46,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.explorer-detection-top-tools {
|
.explorer-entity-top-tools {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.explorer-detection-top-tools, .explorer-entity-top-tools {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
@@ -87,6 +90,13 @@
|
|||||||
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;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
width: 320px;
|
width: 320px;
|
||||||
margin-right: 20px;
|
margin-right: 12px;
|
||||||
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;
|
||||||
|
|||||||
@@ -351,6 +351,7 @@
|
|||||||
}
|
}
|
||||||
.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%;
|
||||||
|
|||||||
@@ -79,11 +79,22 @@
|
|||||||
.cn-entity__header-title {
|
.cn-entity__header-title {
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
.cn-entity__header-tag {
|
.entity-related-entity {
|
||||||
|
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 {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@@ -98,7 +109,7 @@
|
|||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
||||||
.basic-info__item {
|
.basic-info__item, .basic-info__item1 {
|
||||||
padding-right: 30px;
|
padding-right: 30px;
|
||||||
|
|
||||||
.item__box {
|
.item__box {
|
||||||
@@ -161,6 +172,17 @@
|
|||||||
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;
|
||||||
@@ -177,6 +199,7 @@
|
|||||||
|
|
||||||
.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%;
|
||||||
|
|||||||
@@ -26,7 +26,8 @@
|
|||||||
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 {
|
||||||
@@ -34,9 +35,8 @@
|
|||||||
max-width: unset;
|
max-width: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
.explorer-search__input__border {
|
.explorer-search__input--border .CodeMirror {
|
||||||
border: 1px #DEDEDE solid;
|
border: 1px solid #DEDEDE;
|
||||||
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,.explorer-search__foot-list {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding-top: 18px;
|
padding-top: 9px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 1000px;
|
max-width: 1000px;
|
||||||
position: relative;
|
position: relative;
|
||||||
justify-content: space-between;
|
justify-content: flex-start;
|
||||||
font-weight: bold;
|
//font-weight: bold;
|
||||||
|
|
||||||
.foot__item {
|
.foot__item {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -87,14 +87,15 @@
|
|||||||
|
|
||||||
.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(206,206,206,0.20);
|
border: 1px solid rgba(226,229,236,1);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
|
|
||||||
@@ -137,8 +138,32 @@
|
|||||||
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: 30px;
|
padding-left: 18px;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
height: 35px;
|
height: 35px;
|
||||||
@@ -152,6 +177,71 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1798,6 +1798,12 @@
|
|||||||
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;
|
||||||
@@ -1846,6 +1852,12 @@
|
|||||||
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;
|
||||||
@@ -1905,6 +1917,9 @@
|
|||||||
&.update-dialog__table--psiphon3 {
|
&.update-dialog__table--psiphon3 {
|
||||||
height: calc(90vh - 190px - 200px - 50px - 10px);
|
height: calc(90vh - 190px - 200px - 50px - 10px);
|
||||||
}
|
}
|
||||||
|
&.update-dialog__table--system-user {
|
||||||
|
height: calc(100% - 139px);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.update-knowledge-form {
|
.update-knowledge-form {
|
||||||
.el-upload {
|
.el-upload {
|
||||||
|
|||||||
@@ -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=1698229141457') format('woff2'),
|
src: url('iconfont.woff2?t=1699411209748') format('woff2'),
|
||||||
url('iconfont.woff?t=1698229141457') format('woff'),
|
url('iconfont.woff?t=1699411209748') format('woff'),
|
||||||
url('iconfont.ttf?t=1698229141457') format('truetype');
|
url('iconfont.ttf?t=1699411209748') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
.cn-icon {
|
.cn-icon {
|
||||||
@@ -13,6 +13,10 @@
|
|||||||
-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.
@@ -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">
|
<div class="search__suffixes search__suffixes--tag-mode search__suffixes--tag-mode__block" :class="showList ? '' : 'entity-explorer-home'">
|
||||||
<div class="search__suffix" style="margin-right: 12px">
|
<span class="search__suffix">
|
||||||
<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>
|
||||||
</div>
|
</span>
|
||||||
<div v-show="metaList.length>0" class="search__suffix-close" @click="cleanMetaList">
|
<span v-show="metaList.length>0" class="search__suffix search__suffix-close" @click="cleanMetaList">
|
||||||
<i class="el-icon-error"></i>
|
<i class="el-icon-error"></i>
|
||||||
</div>
|
</span>
|
||||||
<div class="search__suffix" :class="showList ? 'new-search__suffix' : 'entity-explorer-search'" @click="search">
|
<span class="search__suffix" @click="search">
|
||||||
<i class="el-icon-search"></i>
|
<i class="el-icon-search"></i>
|
||||||
</div>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -202,6 +202,7 @@ 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 {
|
||||||
@@ -248,6 +249,7 @@ 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)
|
||||||
@@ -461,13 +463,21 @@ 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 })
|
this.$emit('search', { ...parser.parseStr(key), str: str2, keywordList: keywordList })
|
||||||
} else {
|
} else {
|
||||||
this.$message.error(handleErrorTip(errorList[0]))
|
this.$message.error(handleErrorTip(errorList[0]))
|
||||||
}
|
}
|
||||||
@@ -555,6 +565,8 @@ 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]))
|
||||||
|
if (obj) {
|
||||||
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))
|
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))
|
||||||
// 不是在首位,则删除时顺带删除前一个index(and或or),否则顺带删除后一个index
|
// 不是在首位,则删除时顺带删除前一个index(and或or),否则顺带删除后一个index
|
||||||
if (metaIndex > 0) {
|
if (metaIndex > 0) {
|
||||||
@@ -564,6 +576,7 @@ export default {
|
|||||||
} else {
|
} else {
|
||||||
this.metaList.splice(metaIndex, 2)
|
this.metaList.splice(metaIndex, 2)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
@@ -622,6 +635,9 @@ 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 {
|
||||||
@@ -650,6 +666,7 @@ 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)
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<textarea
|
<textarea
|
||||||
|
style="text-indent: 65px;"
|
||||||
|
cols="40"
|
||||||
ref="textSearch"
|
ref="textSearch"
|
||||||
></textarea>
|
></textarea>
|
||||||
<div class="search__suffixes search__suffixes--text-mode">
|
<div class="search__suffixes search__suffixes--text-mode" :class="showList ? '' : 'entity-explorer-home'" style="padding-left: 1px">
|
||||||
<div class="search__suffix">
|
<span class="search__suffix">
|
||||||
<el-popover
|
<el-popover
|
||||||
popper-class="my-popper-class"
|
popper-class="my-popper-class"
|
||||||
placement="top"
|
placement="top"
|
||||||
@@ -11,16 +13,16 @@
|
|||||||
:content="$t('entity.switchToAdvancedSearch')"
|
:content="$t('entity.switchToAdvancedSearch')"
|
||||||
>
|
>
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<i class="cn-icon cn-icon-filter margin-r-12" @click="changeMode"></i>
|
<i class="cn-icon cn-icon-filter" @click="changeMode"></i>
|
||||||
</template>
|
</template>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
</div>
|
</span>
|
||||||
<div v-show="isCloseIcon" class="search__suffix-close" @click="cleanParams">
|
<span v-show="isCloseIcon" class="search__suffix search__suffix-close" @click="cleanParams">
|
||||||
<i class="el-icon-error"></i>
|
<i class="el-icon-error"></i>
|
||||||
</div>
|
</span>
|
||||||
<div class="search__suffix" :class="showList ? 'new-search__suffix' : 'entity-explorer-search'" @click="search">
|
<span class="search__suffix" @click="search">
|
||||||
<i class="el-icon-search"></i>
|
<i class="el-icon-search"></i>
|
||||||
</div>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -68,7 +70,7 @@ export default {
|
|||||||
mode: {
|
mode: {
|
||||||
name: 'sql'
|
name: 'sql'
|
||||||
},
|
},
|
||||||
placeholder: 'Enter...',
|
placeholder: '',
|
||||||
lineNumbers: false
|
lineNumbers: false
|
||||||
})
|
})
|
||||||
this.codeMirror.setOption('extraKeys', {
|
this.codeMirror.setOption('extraKeys', {
|
||||||
@@ -97,10 +99,19 @@ 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 })
|
this.$emit('search', { ...parser.parseStr(keyInfo.key), str: str, keywordList: keywordList })
|
||||||
} else {
|
} else {
|
||||||
this.$message.error(handleErrorTip(errorList[0]))
|
this.$message.error(handleErrorTip(errorList[0]))
|
||||||
}
|
}
|
||||||
@@ -223,6 +234,9 @@ 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 {
|
||||||
|
|||||||
@@ -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]}`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<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"
|
||||||
@@ -20,16 +21,19 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
|
|
||||||
</el-pagination>
|
</el-pagination>
|
||||||
|
</el-config-provider>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { defaultPageSize, storageKey } from '@/utils/constants'
|
import { defaultPageSize, storageKey, ZH, EN } 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',
|
||||||
@@ -60,9 +64,15 @@ 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 () {
|
||||||
|
|||||||
@@ -18,7 +18,8 @@
|
|||||||
<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">Absolute time range</div>
|
<div class="date-range-title" style="padding-left: 0">{{$t('dateTime.absoluteTimeRange')}}</div>
|
||||||
|
<el-config-provider :locale="locale">
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-model="newDateValue"
|
v-model="newDateValue"
|
||||||
ref="newDatePicker"
|
ref="newDatePicker"
|
||||||
@@ -30,16 +31,17 @@
|
|||||||
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">To</div>
|
<div class="content-title">{{$t('dateTime.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">Recently used absolute ranges</div>
|
<div class="date-range-title" style="padding-left: 0">{{$t('dateTime.recentlyUsedRanges')}}</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)">
|
||||||
@@ -53,7 +55,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">Relatime time ranges</div>
|
<div class="date-range-title">{{$t('dateTime.relativeTimeRanges')}}</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)"
|
||||||
@@ -79,9 +81,12 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { ref, computed, watch, reactive } from 'vue'
|
import { ref, computed, watch, reactive } from 'vue'
|
||||||
import { storageKey } from '@/utils/constants'
|
import { EN, storageKey, ZH } 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',
|
||||||
@@ -105,6 +110,31 @@ 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()
|
||||||
@@ -124,24 +154,12 @@ 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 '
|
||||||
@@ -159,13 +177,6 @@ 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
|
||||||
@@ -289,6 +300,12 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const language = localStorage.getItem(storageKey.language) || EN // 初始未选择默认 en 英文
|
||||||
|
let locale = en
|
||||||
|
if (language === ZH) {
|
||||||
|
locale = cn
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
myStartTime,
|
myStartTime,
|
||||||
myEndTime,
|
myEndTime,
|
||||||
@@ -297,13 +314,11 @@ 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,
|
||||||
@@ -313,7 +328,8 @@ export default {
|
|||||||
timeArrChange,
|
timeArrChange,
|
||||||
returnValue,
|
returnValue,
|
||||||
quickChange,
|
quickChange,
|
||||||
historyChange
|
historyChange,
|
||||||
|
locale
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { storageKey } from '@/utils/constants'
|
import { storageKey, EN } 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()
|
||||||
|
|||||||
@@ -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 === 'cn'?'color:#0091ff':''" @click="changeLocal('cn')">
|
<div id="header-to-chinese" :style="language === ZH?'color:#0091ff':''" @click="changeLocal(ZH)">
|
||||||
中文
|
中文
|
||||||
</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=">">
|
<el-breadcrumb class="header__left-breadcrumb" separator=">" v-if="route.startsWith('/panel')">
|
||||||
<el-breadcrumb-item class="header__left-breadcrumb-item" :id="`breadcrumb${item.value}`" :title="item.value"
|
<el-breadcrumb-item class="header__left-breadcrumb-item" :id="`breadcrumb${item.value}`" :title="index===3?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,6 +113,13 @@
|
|||||||
</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>
|
||||||
|
|
||||||
<!-- 菜单 -->
|
<!-- 菜单 -->
|
||||||
@@ -196,7 +203,9 @@ 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'
|
||||||
@@ -234,7 +243,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: {
|
||||||
@@ -296,7 +305,9 @@ export default {
|
|||||||
curTabState: curTabState,
|
curTabState: curTabState,
|
||||||
urlChangeParams: {},
|
urlChangeParams: {},
|
||||||
wholeScreenRouterMapping,
|
wholeScreenRouterMapping,
|
||||||
logo: 'images/logo-header.svg'
|
logo: 'images/logo-header.svg',
|
||||||
|
ZH,
|
||||||
|
EN
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -304,7 +315,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', 'chart', 'I18N', 'entityDetail', 'temp', 'entityGraph', 'detectionPolicy'].indexOf(menu.code) === -1)
|
return this.$store.getters.menuList.filter(menu => ['networkAnalytics', 'I18N', 'entityDetail', '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++) {
|
||||||
@@ -322,15 +333,17 @@ export default {
|
|||||||
breadcrumb () {
|
breadcrumb () {
|
||||||
const breadcrumb = []
|
const breadcrumb = []
|
||||||
this.generateBreadcrumb(breadcrumb, this.$store.getters.menuList)
|
this.generateBreadcrumb(breadcrumb, this.$store.getters.menuList)
|
||||||
// 写死一级和二级菜单是否可以点击跳转
|
if (breadcrumb) {
|
||||||
if (breadcrumb[0]) {
|
// panel菜单是否可以点击跳转:一级菜单不可点击,二级菜单可以点击
|
||||||
if (['knowledgeBase'].indexOf(breadcrumb[0].code) > -1) {
|
if (breadcrumb[0] && breadcrumb[1] && breadcrumb[1].route &&
|
||||||
breadcrumb[0].clickable = true
|
breadcrumb[1].route.indexOf('/panel/') === 0) {
|
||||||
}
|
|
||||||
if (breadcrumb[1]) {
|
|
||||||
if (breadcrumb[1].route && breadcrumb[1].route.indexOf('/panel/') === 0) {
|
|
||||||
breadcrumb[1].clickable = true
|
breadcrumb[1].clickable = true
|
||||||
|
} else { // 除panel外的菜单是否可以点击跳转:除了新增、编辑,其它均可点击
|
||||||
|
breadcrumb.forEach(item => {
|
||||||
|
if (item.value !== 'Create' && item.value !== 'Edit') {
|
||||||
|
item.clickable = true
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,7 +379,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.params.typeName === fromRoute.dnsServiceInsights) {
|
if (this.$route.path.replace('/panel/', '') === fromRoute.dnsServiceInsights) {
|
||||||
if (this.dnsQtypeMapData.size === 0) {
|
if (this.dnsQtypeMapData.size === 0) {
|
||||||
this.dnsQtypeMapData = await getDnsMapData('dnsQtype')
|
this.dnsQtypeMapData = await getDnsMapData('dnsQtype')
|
||||||
}
|
}
|
||||||
@@ -384,7 +397,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.params.typeName === fromRoute.dnsServiceInsights) {
|
if (this.$route.path.replace('/panel/', '') === fromRoute.dnsServiceInsights) {
|
||||||
if (this.dnsQtypeMapData.size === 0) {
|
if (this.dnsQtypeMapData.size === 0) {
|
||||||
this.dnsQtypeMapData = await getDnsMapData('dnsQtype')
|
this.dnsQtypeMapData = await getDnsMapData('dnsQtype')
|
||||||
}
|
}
|
||||||
@@ -405,10 +418,10 @@ export default {
|
|||||||
const endTimeParam = query.endTime
|
const endTimeParam = query.endTime
|
||||||
// 若url携带了,使用携带的值,否则使用默认值。
|
// 若url携带了,使用携带的值,否则使用默认值。
|
||||||
|
|
||||||
const dateRangeValue = rangeParam ? parseInt(query.range) : 60
|
const dateRangeValue = rangeParam ? parseInt(rangeParam) : 60
|
||||||
const chartTimeFilter = ref({ dateRangeValue })
|
const chartTimeFilter = ref({ dateRangeValue })
|
||||||
if (!startTimeParam || !endTimeParam) {
|
if (!startTimeParam || !endTimeParam) {
|
||||||
const { startTime, endTime } = getNowTime(60)
|
const { startTime, endTime } = getNowTime(dateRangeValue)
|
||||||
chartTimeFilter.value.startTime = startTime
|
chartTimeFilter.value.startTime = startTime
|
||||||
chartTimeFilter.value.endTime = endTime
|
chartTimeFilter.value.endTime = endTime
|
||||||
} else {
|
} else {
|
||||||
@@ -423,39 +436,6 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
generateBreadcrumb (breadcrumb, menus) {
|
generateBreadcrumb (breadcrumb, menus) {
|
||||||
if (this.route === '/entityDetail') {
|
|
||||||
const entityMenu = menus.find(m => m.route === '/entityExplorer')
|
|
||||||
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 === '/entityExplorer')
|
|
||||||
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({
|
||||||
@@ -507,7 +487,7 @@ export default {
|
|||||||
},
|
},
|
||||||
getCurTabByLabel (label) {
|
getCurTabByLabel (label) {
|
||||||
let curTab = null
|
let curTab = null
|
||||||
const tableType = this.$route.params ? this.$route.params.typeName : 'networkOverview'
|
const tableType = this.$route.path.replace('/panel/', '') || '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)
|
||||||
@@ -520,7 +500,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.params ? this.$route.params.typeName : 'networkOverview'
|
const tableType = this.$route.path.replace('/panel/', '') || '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)
|
||||||
@@ -544,7 +524,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.params.typeName === fromRoute.dnsServiceInsights) {
|
if (this.$route.path.replace('/panel/', '') === fromRoute.dnsServiceInsights) {
|
||||||
if (this.dnsQtypeMapData.size === 0) {
|
if (this.dnsQtypeMapData.size === 0) {
|
||||||
this.dnsQtypeMapData = await getDnsMapData('dnsQtype')
|
this.dnsQtypeMapData = await getDnsMapData('dnsQtype')
|
||||||
}
|
}
|
||||||
@@ -675,7 +655,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.params ? this.$route.params.typeName : 'networkOverview'
|
const tableType = this.$route.path.replace('/panel/', '') || '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)
|
||||||
@@ -696,7 +676,26 @@ 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
|
||||||
}
|
}
|
||||||
@@ -716,7 +715,7 @@ export default {
|
|||||||
this.$store.commit('setNetworkOverviewTabList', [])
|
this.$store.commit('setNetworkOverviewTabList', [])
|
||||||
}
|
}
|
||||||
// 清空网络概况的特殊面包屑
|
// 清空网络概况的特殊面包屑
|
||||||
const tableType = this.$route.params ? this.$route.params.typeName : 'networkOverview'
|
const tableType = this.$route.path.replace('/panel/', '') || '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 => {
|
||||||
@@ -728,11 +727,6 @@ 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 = ''
|
||||||
@@ -791,10 +785,10 @@ export default {
|
|||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
/* if (route === this.route) {
|
if (route === this.route) {
|
||||||
this.refresh()
|
this.refresh()
|
||||||
return
|
return
|
||||||
} */
|
}
|
||||||
if (route) {
|
if (route) {
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
path: route,
|
path: route,
|
||||||
|
|||||||
@@ -23,7 +23,8 @@
|
|||||||
<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-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-checkbox v-model="isCheckAll" :label="$t('overall.all')" @change="checkAll"></el-checkbox>
|
||||||
|
<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>
|
||||||
@@ -90,7 +91,8 @@ export default {
|
|||||||
menus: [],
|
menus: [],
|
||||||
selectedIds: [],
|
selectedIds: [],
|
||||||
selectAllFlag: false,
|
selectAllFlag: false,
|
||||||
expandAllFlag: true
|
expandAllFlag: true,
|
||||||
|
isCheckAll: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@@ -150,9 +152,59 @@ 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
|
||||||
},
|
},
|
||||||
selectChange: function (data, isCheck, childIsCheck) {
|
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.$refs.menuTree) {
|
||||||
this.editRole.menuIds = this.$refs.menuTree.getCheckedKeys(true)
|
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) {
|
||||||
|
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) {
|
||||||
|
this.editRole.menuIds = this.$refs.menuTree.getCheckedKeys(false)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
selectAllOrNone: function () {
|
selectAllOrNone: function () {
|
||||||
|
|||||||
@@ -125,16 +125,16 @@ export default {
|
|||||||
mixins: [rightBoxMixin],
|
mixins: [rightBoxMixin],
|
||||||
data () {
|
data () {
|
||||||
const validatePin = (rule, value, callback) => { // 确认密码
|
const validatePin = (rule, value, callback) => { // 确认密码
|
||||||
if (value.length < 5) {
|
if (value && 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 (value === '' && this.editObject.pin) {
|
if (_.isEmpty(value) && !_.isEmpty(this.editObject.pin)) {//密码有内容,确认密码没内容
|
||||||
callback(new Error(this.$t('config.user.confirmPin')))
|
callback(new Error(this.$t('config.user.confirmPin')))
|
||||||
} else if (value !== this.editObject.pin) {
|
} else if (!_.isEmpty(value) && 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' },
|
||||||
{ pattern: /^[a-zA-Z0-9]{5,64}$/, message: this.$t('validate.atLeastFive') }
|
{ validator: validatePin, trigger: 'blur' }
|
||||||
],
|
],
|
||||||
roleIds: [
|
roleIds: [
|
||||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
||||||
|
|||||||
@@ -52,13 +52,17 @@
|
|||||||
</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"
|
v-if="scope.row.id && hasPermission('editUser')"
|
||||||
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>
|
||||||
|
|||||||
@@ -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==='cn'" style="color: rgba(0,0,0,0)">0</div>
|
<div v-if="language===ZH" 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') }}
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
<el-option
|
<el-option
|
||||||
v-for="item in eventTypeList"
|
v-for="item in eventTypeList"
|
||||||
:key="item.value"
|
:key="item.value"
|
||||||
:label="$t(item.label)"
|
:label="item.label"
|
||||||
:value="item.value"
|
:value="item.value"
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
@@ -109,7 +109,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { detectionRuleType, storageKey, detectionUnitList } from '@/utils/constants'
|
import { detectionRuleType, storageKey, detectionUnitList, ZH, EN } from '@/utils/constants'
|
||||||
import { switchStatus } from '@/utils/tools'
|
import { switchStatus } from '@/utils/tools'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -160,7 +160,8 @@ export default {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
language: 'en'
|
language: EN,
|
||||||
|
ZH
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@@ -183,7 +184,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
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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}} more</div>
|
<div class="reference-more">+{{scope.row[item.prop].length - 2}} {{$t('overall.more')}}</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div class="reference-tag__tip">
|
<div class="reference-tag__tip">
|
||||||
@@ -70,9 +70,11 @@
|
|||||||
</el-popover>
|
</el-popover>
|
||||||
</templage>
|
</templage>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<template v-for="(refer, index) in scope.row[item.prop]">
|
<div class="reference-tag__show">
|
||||||
<div class="type-tag">{{refer}}</div>
|
<div class="reference-tag__group">
|
||||||
</template>
|
<span class="reference-tag" v-for="(refer, index) in scope.row[item.prop]" >{{refer}}</span>
|
||||||
|
</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'">
|
||||||
@@ -96,6 +98,7 @@
|
|||||||
</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"
|
||||||
@@ -103,6 +106,10 @@
|
|||||||
@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">
|
||||||
@@ -156,7 +163,7 @@ export default {
|
|||||||
}, {
|
}, {
|
||||||
label: this.$t('knowledge.reference'),
|
label: this.$t('knowledge.reference'),
|
||||||
prop: 'reference',
|
prop: 'reference',
|
||||||
width: 180,
|
width: 190,
|
||||||
show: true
|
show: true
|
||||||
}, {
|
}, {
|
||||||
label: this.$t('overall.color'),
|
label: this.$t('overall.color'),
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
<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"
|
||||||
@@ -20,12 +21,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="data.label">{{data.label}}</div>
|
<div class="card-title-name" :title="$t(data.label)">{{$t(data.label)}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-desc" :title="data.desc">{{data.desc ? data.desc : '—'}}</div>
|
<div class="card-desc" :title="$t(data.desc)">{{$t(data.desc) || '—'}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-operate__footer">
|
<div class="card-operate__footer">
|
||||||
<button v-if="data.showUpdate"
|
<button v-if="data.showUpdate && hasPermission('editBuiltInKnowledgeBase')"
|
||||||
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>
|
||||||
@@ -44,12 +45,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="data.label">{{data.label}}</div>
|
<div class="card-title-name" :title="$t(data.label)">{{$t(data.label)}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-desc" :title="data.desc ? data.desc:'—'">{{data.desc ? data.desc : '—'}}</div>
|
<div class="card-desc" :title="data.desc ? $t(data.desc) : '—'">{{data.desc ? $t(data.desc) : '—'}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-operate__footer">
|
<div class="card-operate__footer">
|
||||||
<button v-if="data.showUpdate" :title="$t('overall.update')" class="top-tool-btn--update"
|
<button v-if="data.showUpdate && hasPermission('editBuiltInKnowledgeBase')" :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>
|
||||||
@@ -66,7 +67,9 @@
|
|||||||
|
|
||||||
<div class="center-dialog">
|
<div class="center-dialog">
|
||||||
<el-dialog v-model="showUpdateDialog"
|
<el-dialog v-model="showUpdateDialog"
|
||||||
|
:destroy-on-close="true"
|
||||||
:custom-class="showAddUpdateDialog ? 'update-knowledge update-knowledge--upload' : 'update-knowledge'"
|
:custom-class="showAddUpdateDialog ? 'update-knowledge update-knowledge--upload' : 'update-knowledge'"
|
||||||
|
:before-close="beforeClose"
|
||||||
:after-close="handleClose">
|
:after-close="handleClose">
|
||||||
<div class="knowledge-update__top" >
|
<div class="knowledge-update__top" >
|
||||||
<div class="update-left__icon">
|
<div class="update-left__icon">
|
||||||
@@ -75,7 +78,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="updateKnowledge.label">{{updateKnowledge.label}}</div>
|
<div class="card-title-name" :title="$t(updateKnowledge.label)">{{$t(updateKnowledge.label)}}</div>
|
||||||
</div>
|
</div>
|
||||||
<el-switch v-model="updateKnowledge.status"
|
<el-switch v-model="updateKnowledge.status"
|
||||||
active-color="#38ACD2"
|
active-color="#38ACD2"
|
||||||
@@ -83,10 +86,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')"
|
||||||
>
|
>
|
||||||
</el-switch>
|
</el-switch>
|
||||||
</div>
|
</div>
|
||||||
<div class="knowledge-desc" :title="updateKnowledge.desc">{{updateKnowledge.desc ? updateKnowledge.desc : '—'}}</div>
|
<div class="knowledge-desc" :title="updateKnowledge.desc ? $t(updateKnowledge.desc) : '-'">{{updateKnowledge.desc ? $t(updateKnowledge.desc) : '-'}}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="!showAddUpdateDialog">
|
<template v-if="!showAddUpdateDialog">
|
||||||
@@ -108,7 +112,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">
|
@click="uploadRecord"><!--:disabled="hasUpdatingRecord"-->
|
||||||
<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>
|
||||||
@@ -120,13 +124,13 @@
|
|||||||
</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">
|
@click="uploadRecord"><!-- :disabled="hasUpdatingRecord" -->
|
||||||
<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>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div :style="{height: updateKnowledge.source === 'cn_psiphon3_ip' ? 'calc(90vh - 190px - 200px - 50px - 42px)' : 'calc(100% - 242px)', marginTop: '42px', position: 'absolute', width: 'calc(100% - 60px)'}">
|
<div :style="{height: updateKnowledge.source === 'cn_psiphon3_ip' && activeTab === 'intelligenceLearning' ? 'calc(90vh - 190px - 200px - 50px - 42px)' : 'calc(100% - 242px)', marginTop: '42px', position: 'absolute', width: 'calc(100% - 60px)'}">
|
||||||
<loading :loading="updateLogLoading"></loading>
|
<loading :loading="updateLogLoading"></loading>
|
||||||
</div>
|
</div>
|
||||||
<el-table ref="updateDataTable"
|
<el-table ref="updateDataTable"
|
||||||
@@ -134,12 +138,20 @@
|
|||||||
:data="updateHistoryList"
|
:data="updateHistoryList"
|
||||||
@selection-change="secondSelectionChange"
|
@selection-change="secondSelectionChange"
|
||||||
width="100%"
|
width="100%"
|
||||||
:class="updateKnowledge.source === 'cn_psiphon3_ip' ? 'update-dialog__table update-dialog__table--psiphon3' : 'update-dialog__table'"
|
class="update-dialog__table"
|
||||||
|
:class="{
|
||||||
|
'update-dialog__table--psiphon3': updateKnowledge.source === 'cn_psiphon3_ip' && activeTab === 'intelligenceLearning',
|
||||||
|
'update-dialog__table--system-user': updateKnowledge.source === 'cn_psiphon3_ip' && activeTab !== 'intelligenceLearning'
|
||||||
|
}"
|
||||||
:header-cell-style="{background:'#f5f7fa',color:'#353636',fontWeight: '400',fontSize: '12px',borderRight: 'none',borderBottom: 'none'}"
|
:header-cell-style="{background:'#f5f7fa',color:'#353636',fontWeight: '400',fontSize: '12px',borderRight: 'none',borderBottom: 'none'}"
|
||||||
cell-style="padding:6px 0px;font-size: 12px;color: #353636;font-weight: 400;line-height: 20px;border-right:none;"
|
cell-style="padding:6px 0px;font-size: 12px;color: #353636;font-weight: 400;line-height: 20px;border-right:none;"
|
||||||
header-cell-style="padding:8px 0px;font-size: 12px;color: #353636;font-weight: 500;border-right:none;">
|
header-cell-style="padding:8px 0px;font-size: 12px;color: #353636;font-weight: 500;border-right:none;">
|
||||||
<el-table-column prop="opTime" :label="$t('entities.tab.informationAggregation.updateTime')" width="150" ></el-table-column>
|
<el-table-column prop="opTime" :label="$t('entities.tab.informationAggregation.updateTime')" width="150" >
|
||||||
<el-table-column prop="user" :label="$t('knowledgeBase.operator')" width="150" v-if="activeTab === 'updateRecord'">
|
<template #default="scope" :column="item">
|
||||||
|
<span>{{scope.row.opTime ? dateFormatByAppearance(scope.row.opTime) : '-'}}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="user" :label="$t('knowledgeBase.operator')" width="150" v-if="updateKnowledge.source !== 'cn_psiphon3_ip' || 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>
|
||||||
@@ -154,7 +166,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<div class="psiphon3" v-if="updateKnowledge.source === 'cn_psiphon3_ip'">
|
<div class="psiphon3" v-if="updateKnowledge.source === 'cn_psiphon3_ip' && activeTab === 'intelligenceLearning'">
|
||||||
<div class="psiphon3-title">{{$t('knowledgeBase.psiphon3IpCount')}}</div>
|
<div class="psiphon3-title">{{$t('knowledgeBase.psiphon3IpCount')}}</div>
|
||||||
<div class="psiphon3-bar">
|
<div class="psiphon3-bar">
|
||||||
<chart-error v-if="showErrorForPsiphon3" :content="errorMsgForPsiphon3"/>
|
<chart-error v-if="showErrorForPsiphon3" :content="errorMsgForPsiphon3"/>
|
||||||
@@ -245,7 +257,7 @@
|
|||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-button @click="showAddUpdateDialog = false">{{ $t('overall.cancel') }}</el-button>
|
<el-button @click="cancle">{{ $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>
|
||||||
@@ -272,8 +284,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="showConfirmSwitch = false">{{ $t('overall.cancel') }}</el-button>
|
<el-button @click="cancleSwitch">{{ $t('overall.cancel') }}</el-button>
|
||||||
<el-button type="primary" @click="switchLearning">OK</el-button>
|
<el-button type="primary" @click="switchLearning">{{$t('tip.confirm')}}</el-button>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
@@ -284,7 +296,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 } from '@/utils/constants'
|
import { knowledgeCategoryValue, unitTypes, storageKey, builtInKnowledgeBaseBasicInfo, knowledgeCardUpdateRecordType } 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'
|
||||||
@@ -328,6 +340,7 @@ 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,
|
||||||
@@ -337,6 +350,7 @@ export default {
|
|||||||
tabType: 'total',
|
tabType: 'total',
|
||||||
mousemoveCursor: '',
|
mousemoveCursor: '',
|
||||||
selectTime: 1440,
|
selectTime: 1440,
|
||||||
|
// hasUpdatingRecord: false,
|
||||||
tabs: [
|
tabs: [
|
||||||
{
|
{
|
||||||
name: 'knowledgeBase.total',
|
name: 'knowledgeBase.total',
|
||||||
@@ -369,12 +383,6 @@ 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,
|
||||||
@@ -386,8 +394,7 @@ 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: {
|
||||||
@@ -416,7 +423,6 @@ export default {
|
|||||||
},
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
type: 'time',
|
type: 'time',
|
||||||
boundaryGap: ['1%', '3%'],
|
|
||||||
axisLine: {
|
axisLine: {
|
||||||
show: false
|
show: false
|
||||||
},
|
},
|
||||||
@@ -460,9 +466,10 @@ 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(this.timeFilter.startTime),
|
startTime: getSecond(endTime - this.selectTime * 60 * 1000),
|
||||||
endTime: getSecond(this.timeFilter.endTime)
|
endTime: getSecond(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 => {
|
||||||
@@ -475,8 +482,10 @@ 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)
|
||||||
}
|
}
|
||||||
@@ -523,26 +532,32 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
timeChange () {
|
timeChange () {
|
||||||
this.timeFilter.endTime = window.$dayJs.tz().valueOf()
|
if (this.updateKnowledge.source === 'cn_psiphon3_ip') {
|
||||||
this.timeFilter.startTime = this.timeFilter.endTime - this.selectTime * 60 * 1000
|
|
||||||
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) {
|
||||||
this.tabType = item.class
|
this.tabType = item.class
|
||||||
}
|
}
|
||||||
this.legendSelectChange(item)
|
this.legendSelectChange(item)
|
||||||
|
if (this.updateKnowledge.source === 'cn_psiphon3_ip') {
|
||||||
this.init()
|
this.init()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
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 = ''
|
||||||
@@ -572,15 +587,9 @@ 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()
|
||||||
this.init()
|
|
||||||
/* } else {
|
|
||||||
this.$message.error(this.$t('tip.uploadFailed', { msg: response.message }))
|
|
||||||
} */
|
|
||||||
},
|
},
|
||||||
beforeUpload (file) {
|
beforeUpload (file) {
|
||||||
this.uploadLoading = true
|
this.uploadLoading = true
|
||||||
@@ -592,6 +601,9 @@ 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)
|
||||||
@@ -612,6 +624,13 @@ export default {
|
|||||||
data.isSelected = val
|
data.isSelected = val
|
||||||
this.$emit('checkboxStatusChange', val, data)
|
this.$emit('checkboxStatusChange', val, data)
|
||||||
},
|
},
|
||||||
|
beforeClose (done) {
|
||||||
|
if (this.myChart) {
|
||||||
|
this.myChart.dispose()
|
||||||
|
this.myChart = null
|
||||||
|
}
|
||||||
|
done()
|
||||||
|
},
|
||||||
handleClose () {
|
handleClose () {
|
||||||
this.showUpdateDialog = false
|
this.showUpdateDialog = false
|
||||||
this.showAddUpdateDialog = false
|
this.showAddUpdateDialog = false
|
||||||
@@ -631,11 +650,15 @@ export default {
|
|||||||
this.updateKnowledge = data
|
this.updateKnowledge = data
|
||||||
this.showEnable = showEnable
|
this.showEnable = showEnable
|
||||||
await this.getCurTabData()
|
await this.getCurTabData()
|
||||||
|
if (data.source === 'cn_psiphon3_ip') {
|
||||||
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
|
||||||
@@ -648,12 +671,12 @@ export default {
|
|||||||
pageSize: -1
|
pageSize: -1
|
||||||
}
|
}
|
||||||
if (this.showEnable) {
|
if (this.showEnable) {
|
||||||
if (this.activeTab === 'updateRecord') {
|
if (this.activeTab === knowledgeCardUpdateRecordType.updateRecord) {
|
||||||
params = {
|
params = {
|
||||||
...params,
|
...params,
|
||||||
opUser: -1
|
opUser: -1
|
||||||
}
|
}
|
||||||
} else if (this.activeTab === 'intelligenceLearning') {
|
} else if (this.activeTab === knowledgeCardUpdateRecordType.intelligenceLearning) {
|
||||||
params = {
|
params = {
|
||||||
...params,
|
...params,
|
||||||
opUser: 0
|
opUser: 0
|
||||||
@@ -667,6 +690,15 @@ 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(() => {
|
||||||
@@ -676,6 +708,9 @@ export default {
|
|||||||
// 切换tab
|
// 切换tab
|
||||||
handleClick (tab) {
|
handleClick (tab) {
|
||||||
this.getCurTabData()
|
this.getCurTabData()
|
||||||
|
if (tab.index === '1') {
|
||||||
|
this.timeChange()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
clearSelect () {
|
clearSelect () {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
@@ -714,6 +749,9 @@ 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
|
||||||
@@ -736,21 +774,21 @@ export default {
|
|||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
tabType (n) {
|
tabType (n) {
|
||||||
this.$nextTick(() => {
|
this.timeChange()
|
||||||
this.handleActiveBar()
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
timeFilter: {
|
/*
|
||||||
handler () {
|
hasUpdatingRecord (n) {
|
||||||
this.init()
|
if (n) { // update record页存在“正在更新”的记录时,每20秒自动请求一次接口
|
||||||
this.$nextTick(() => {
|
this.timer = setTimeout(() => {
|
||||||
this.handleActiveBar()
|
this.getCurTabData()
|
||||||
})
|
}, 20000)
|
||||||
|
} else { // 直到出现新的记录,出现新记录后(失败或者成功),取消定时请求接口,右上角"update"按钮恢复可用。"正在更新"和"失败”都会有对应的强调样式。
|
||||||
|
clearTimeout(this.timer)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
*/
|
||||||
tableData: {
|
tableData: {
|
||||||
handler (n) {
|
handler (n) {
|
||||||
console.info(n)
|
|
||||||
if (this.tableData && this.tableData.length > 0) {
|
if (this.tableData && this.tableData.length > 0) {
|
||||||
this.aiTaggingList = []
|
this.aiTaggingList = []
|
||||||
this.websketchList = []
|
this.websketchList = []
|
||||||
@@ -772,19 +810,27 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
activeTab (n) {
|
||||||
|
if (n === 'updateRecord') {
|
||||||
|
if (this.myChart) {
|
||||||
|
this.myChart.dispose()
|
||||||
|
this.myChart = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
showAddUpdateDialog: {
|
showAddUpdateDialog: {
|
||||||
handler (n) {
|
handler (n) {
|
||||||
if (!n) {
|
if (!n) {
|
||||||
this.fileList = []
|
this.fileList = []
|
||||||
if (this.updateKnowledge.source === 'cn_psiphon3_ip') {
|
this.timeChange()
|
||||||
this.init()
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
this.myChart && this.myChart.dispose()
|
if (this.myChart) {
|
||||||
|
this.myChart.dispose()
|
||||||
this.myChart = null
|
this.myChart = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.myChart = null
|
this.myChart = null
|
||||||
@@ -803,7 +849,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) {
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { createI18n } from 'vue-i18n/index'
|
import { createI18n } from 'vue-i18n/index'
|
||||||
import { storageKey } from '@/utils/constants'
|
import { storageKey, EN } 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) {
|
||||||
|
|||||||
@@ -5,9 +5,8 @@ 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 } from '@/utils/tools'
|
import { cancelWithChange, noData, myHighLight } 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'
|
||||||
@@ -37,10 +36,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)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { hasButton } from '@/permission'
|
import { hasPermission } 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,9 +28,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
hasButton (code) {
|
hasPermission,
|
||||||
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) {
|
||||||
|
|||||||
@@ -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() }).then(response => {
|
axios.get(relationshipUrlOne, { params: this.getQueryParams(DEFAULT_TIME_FILTER_RANGE.entity.relatedEntity) }).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() }).then(response => {
|
axios.get(relationshipUrlTow, { params: this.getQueryParams(DEFAULT_TIME_FILTER_RANGE.entity.relatedEntity) }).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) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { chartTableOrderOptionsMapping, storageKey, knowledgeCategoryValue } from '@/utils/constants'
|
import { chartTableOrderOptionsMapping, storageKey, knowledgeCategoryValue, ZH } 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 !== 'cn') {
|
if (language !== ZH) {
|
||||||
num = num + 1 // 最后一位加空格
|
num = num + 1 // 最后一位加空格
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,14 +32,19 @@ 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: '/',
|
||||||
|
name: 'home',
|
||||||
|
component: () => import('@/components/layout/Home'),
|
||||||
|
children: []
|
||||||
}
|
}
|
||||||
|
handleRoutes(menuList, homeRoute.children)
|
||||||
|
router.addRoute(homeRoute)
|
||||||
|
next({ ...to, replace: true })
|
||||||
|
} else {
|
||||||
if (to.path) {
|
if (to.path) {
|
||||||
next()
|
next()
|
||||||
/* if (hasMenu(store.getters.menuList, to.path)) {
|
}
|
||||||
next()
|
|
||||||
} else {
|
|
||||||
ElMessage.error('No access') // TODO 国际化
|
|
||||||
} */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -60,14 +65,14 @@ router.beforeEach(async (to, from, next) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// menuList中是否包含route权限
|
// menuList中是否包含code
|
||||||
export function hasMenu (menuList, route) {
|
export function hasMenu (menuList, code) {
|
||||||
return menuList.some(menu => {
|
return menuList.some(menu => {
|
||||||
if (menu.route === route) {
|
if (menu.code === code) {
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
if (menu.children) {
|
if (menu.children) {
|
||||||
if (hasMenu(menu.children, route)) {
|
if (hasMenu(menu.children, code)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,36 +101,9 @@ export function hasButton (buttonList, code) {
|
|||||||
return buttonList.some(button => button === code)
|
return buttonList.some(button => button === code)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 用法 v-has="code" | v-has="[code...]" 任意匹配一个 | v-has:all="[code...]" 全匹配
|
// 根据code从menuList和buttonList中判断是否有权限
|
||||||
export const hasPermission = {
|
export function hasPermission (code) {
|
||||||
beforeMount (el, binding) {
|
return hasButton(store.getters.buttonList, code) || hasMenu(store.getters.menuList, code)
|
||||||
// 节点权限处理
|
|
||||||
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排序
|
||||||
@@ -160,3 +138,100 @@ 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,106 +5,6 @@ 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: '/entityExplorer',
|
|
||||||
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')
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import router from '@/router'
|
import router from '@/router'
|
||||||
import { getWelcomeMenu, sortByOrderNum } from '@/permission'
|
import { getWelcomeMenu, sortByOrderNum, handleRoutes } 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,7 +64,14 @@ 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]
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -121,8 +121,6 @@ export function xAxisTimeFormatter (value) {
|
|||||||
':' +
|
':' +
|
||||||
(date.getMinutes() < 10 ? `0${date.getMinutes()}` : date.getMinutes())
|
(date.getMinutes() < 10 ? `0${date.getMinutes()}` : date.getMinutes())
|
||||||
// 如果是一天的开始
|
// 如果是一天的开始
|
||||||
console.info(date.getTime(), dayStart.getTime(), hourStart.getTime(), date.getTime() === dayStart.getTime(), date.getTime() === hourStart.getTime())
|
|
||||||
console.info(getSecond(date.getTime()), getSecond(dayStart.getTime()), getSecond(hourStart.getTime()))
|
|
||||||
if (getSecond(date.getTime()) === getSecond(dayStart.getTime())) {
|
if (getSecond(date.getTime()) === getSecond(dayStart.getTime())) {
|
||||||
return '{day|' + dateFormat(date, 'YYYY-MM-DD') + '}'
|
return '{day|' + dateFormat(date, 'YYYY-MM-DD') + '}'
|
||||||
} else if (getSecond(date.getTime()) === getSecond(hourStart.getTime())) {
|
} else if (getSecond(date.getTime()) === getSecond(hourStart.getTime())) {
|
||||||
|
|||||||
@@ -80,15 +80,15 @@ export const dataForNetworkOverviewLine = {
|
|||||||
options2: [
|
options2: [
|
||||||
{
|
{
|
||||||
value: 'Average',
|
value: 'Average',
|
||||||
label: 'Average'
|
label: 'overall.average'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: '95th Percentile',
|
value: '95th Percentile',
|
||||||
label: '95th Percentile'
|
label: ['overall.percentileNumber', { number: 95 }]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 'Maximum',
|
value: 'Maximum',
|
||||||
label: 'Maximum'
|
label: 'overall.maximum'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
tabsTemplate: [
|
tabsTemplate: [
|
||||||
@@ -200,15 +200,15 @@ export const dataForDnsTrafficLine = {
|
|||||||
options2: [
|
options2: [
|
||||||
{
|
{
|
||||||
value: 'Average',
|
value: 'Average',
|
||||||
label: 'Average'
|
label: 'overall.average'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: '95th Percentile',
|
value: '95th Percentile',
|
||||||
label: '95th Percentile'
|
label: ['overall.percentileNumber', { number: 95 }]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 'Maximum',
|
value: 'Maximum',
|
||||||
label: 'Maximum'
|
label: 'overall.maximum'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
tabs: [
|
tabs: [
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
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 } from '@/utils/constants'
|
import { storageKey, iso36112, topDomain, echartsFontSize, dbGeoDataTableName, networkTable, dbDrilldownTableConfig, ZH, EN } 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 = {
|
||||||
// 是否需要排序
|
// 是否需要排序
|
||||||
@@ -1248,10 +1249,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 'cn': {
|
case ZH: {
|
||||||
return 16
|
return 16
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1360,3 +1361,89 @@ 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -48,7 +48,9 @@
|
|||||||
</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>
|
||||||
@@ -58,7 +60,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import { api } from '@/utils/api'
|
import { api } from '@/utils/api'
|
||||||
import { storageKey } from '@/utils/constants'
|
import { storageKey, ZH, EN } from '@/utils/constants'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
|
|
||||||
@@ -97,12 +99,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
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,16 +11,19 @@
|
|||||||
>
|
>
|
||||||
<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>
|
||||||
|
|||||||
@@ -11,16 +11,19 @@
|
|||||||
>
|
>
|
||||||
<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>
|
||||||
|
|||||||
@@ -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 { params } = useRoute()
|
const { path } = useRoute()
|
||||||
panelType = props.entity ? props.entity.type : panelTypeAndRouteMapping[params.typeName]
|
panelType = props.entity ? props.entity.type : panelTypeAndRouteMapping[path.replace('/panel/', '')]
|
||||||
|
|
||||||
// date
|
// date
|
||||||
const dateRangeValue = 60
|
const dateRangeValue = 60
|
||||||
|
|||||||
@@ -338,7 +338,10 @@ export function axisFormatter (params) {
|
|||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
export function tooLongFormatter (name) {
|
export function tooLongFormatter (name) {
|
||||||
return format.truncateText(name, 110, '12px')
|
return format.truncateText(name, 160, '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>'
|
||||||
|
|||||||
@@ -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">Metric:</span>
|
<span class="select-prefix">{{$t('detections.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.params.typeName === fromRoute.dnsServiceInsights) {
|
if (this.$route.path.replace('/panel/', '') === 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,12 +249,11 @@ export default {
|
|||||||
|
|
||||||
const panel = ref({})
|
const panel = ref({})
|
||||||
let panelType = 1 // 取得panel的type
|
let panelType = 1 // 取得panel的type
|
||||||
let { params, query, path } = useRoute()
|
let { 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
|
||||||
|
|
||||||
@@ -292,19 +291,19 @@ export default {
|
|||||||
} else if (thirdPanel) {
|
} else if (thirdPanel) {
|
||||||
panelType = Number(thirdPanel)
|
panelType = Number(thirdPanel)
|
||||||
} else {
|
} else {
|
||||||
panelType = props.entity ? props.entity.type : panelTypeAndRouteMapping[params.typeName]
|
panelType = props.entity ? props.entity.type : panelTypeAndRouteMapping[path.replace('/panel/', '')]
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取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携带了,使用携带的值,否则使用默认值。
|
|
||||||
|
|
||||||
const dateRangeValue = rangeParam ? parseInt(query.range) : 60
|
// 优先级:url > config.js > 默认值。
|
||||||
|
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(60)
|
const { startTime, endTime } = getNowTime(dateRangeValue)
|
||||||
timeFilter.value.startTime = getSecond(startTime)
|
timeFilter.value.startTime = getSecond(startTime)
|
||||||
timeFilter.value.endTime = getSecond(endTime)
|
timeFilter.value.endTime = getSecond(endTime)
|
||||||
// 如果没有时间参数,就将参数写入url
|
// 如果没有时间参数,就将参数写入url
|
||||||
@@ -519,7 +518,7 @@ export default {
|
|||||||
},
|
},
|
||||||
jumpEntityDetail () {
|
jumpEntityDetail () {
|
||||||
const { href } = this.$router.resolve({
|
const { href } = this.$router.resolve({
|
||||||
path: '/entityDetail',
|
path: '/entity/detail',
|
||||||
query: {
|
query: {
|
||||||
entityType: this.entityType,
|
entityType: this.entityType,
|
||||||
entityName: this.entityValue
|
entityName: this.entityValue
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { entityDetailRelatedEntitiesShowSize } from '@/utils/constants'
|
import { entityDetailRelatedEntitiesShowSize, entityDetailTabsName } from '@/utils/constants'
|
||||||
|
import { getSecond } from '@/utils/date-util'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
@@ -28,6 +29,59 @@ 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
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>-->
|
</div>-->
|
||||||
<div class="line-select-reference-line">
|
<div class="line-select-reference-line">
|
||||||
<span>{{$t('network.referenceLine')}}:</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,7 +54,9 @@
|
|||||||
:popper-append-to-body="false"
|
:popper-append-to-body="false"
|
||||||
@change="referenceSelectChange"
|
@change="referenceSelectChange"
|
||||||
>
|
>
|
||||||
<el-option v-for="item in options2" :key="item.value" :label="item.label" :value="item.value"></el-option>
|
<el-option :key="options2[0].value" :label="$t(options2[0].label)" :value="options2[0].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>
|
||||||
@@ -255,6 +257,14 @@ 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',
|
||||||
|
|||||||
@@ -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">{{entityType[entity.entityType]}}</div>
|
<div class="entity-type">{{entityTypeName}}</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,6 +90,29 @@ 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) {
|
||||||
@@ -259,7 +282,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: '/entityGraph',
|
path: '/entity/graph',
|
||||||
query: {
|
query: {
|
||||||
entityType: props.entity.entityType,
|
entityType: props.entity.entityType,
|
||||||
entityName: props.entity.entityName
|
entityName: props.entity.entityName
|
||||||
|
|||||||
@@ -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携带了,使用携带的值,否则使用默认值。
|
|
||||||
|
|
||||||
const dateRangeValue = rangeParam ? parseInt(query.range) : 60
|
// 优先级:url > config.js > 默认值。
|
||||||
|
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(60)
|
const { startTime, endTime } = getNowTime(dateRangeValue)
|
||||||
timeFilter.value.startTime = startTime
|
timeFilter.value.startTime = startTime
|
||||||
timeFilter.value.endTime = endTime
|
timeFilter.value.endTime = endTime
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -15,12 +15,12 @@
|
|||||||
</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" :timeFilter="oneDayTimeFilter" @checkTag="setTag"></domain-name-resolution>
|
<domain-name-resolution v-else-if="tab.name === entityDetailTabsName.relatedEntity && tab.name === activeTab" @toggleLoading="setLoading" :entity="entity" @checkTag="setTag"></domain-name-resolution>
|
||||||
<digital-certificate v-else-if="tab.name === entityDetailTabsName.digitalCertificate && tab.name === activeTab" @toggleLoading="setLoading" :timeFilter="oneDayTimeFilter" @checkTag="setTag" />
|
<digital-certificate v-else-if="tab.name === entityDetailTabsName.digitalCertificate && tab.name === activeTab" @toggleLoading="setLoading" @checkTag="setTag" />
|
||||||
<security-event v-else-if="tab.name === entityDetailTabsName.securityEvent && 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" />
|
||||||
<performance-event v-else-if="tab.name === entityDetailTabsName.performanceEvent && 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" />
|
||||||
<open-port v-else-if="tab.name === entityDetailTabsName.openPort && tab.name === activeTab" @toggleLoading="setLoading" :entity="entity" :timeFilter="oneDayTimeFilter" @checkTag="setTag"></open-port>
|
<open-port v-else-if="tab.name === entityDetailTabsName.openPort && tab.name === activeTab" @toggleLoading="setLoading" :entity="entity" @checkTag="setTag"></open-port>
|
||||||
<behavior-pattern v-else-if="tab.name === entityDetailTabsName.behaviorPattern && tab.name === activeTab" @toggleLoading="setLoading" :entity="entity" :timeFilter="oneDayTimeFilter" @checkTag="setTag"></behavior-pattern>
|
<behavior-pattern v-else-if="tab.name === entityDetailTabsName.behaviorPattern && tab.name === activeTab" @toggleLoading="setLoading" :entity="entity" @checkTag="setTag"></behavior-pattern>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</div>
|
</div>
|
||||||
@@ -58,12 +58,7 @@ 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: {
|
||||||
@@ -114,22 +109,17 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
initData () {
|
initData () {
|
||||||
const params = {
|
|
||||||
resource: this.entity.entityName
|
|
||||||
// startTime: getSecond(this.oneDayTimeFilter.startTime),
|
|
||||||
// endTime: getSecond(this.oneDayTimeFilter.endTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
const url = this.getUrlByEntityType(this.entity.entityType)
|
const url = this.getUrlByEntityType(this.entity.entityType)
|
||||||
const informationAggregation = axios.get(`${api.entity.informationAggregation}/${this.entity.entityType}?resource=${this.entity.entityName}&pageSize=100&pageNo=1`, { params: params })
|
const informationAggregation = axios.get(`${api.entity.informationAggregation}/${this.entity.entityType}?resource=${this.entity.entityName}&pageSize=100&pageNo=1`, { params: this.getParamsByTabType(entityDetailTabsName.informationAggregation) })
|
||||||
const openPort = axios.get(url, { params: params })
|
const openPort = axios.get(url, { params: this.getParamsByTabType(entityDetailTabsName.openPort) })
|
||||||
// const security = axios.get(`${api.entity.security}/${this.entity.entityType}`, { params: params })
|
const security = axios.get(`${api.entity.security}/${this.entity.entityType}`, { params: this.getParamsByTabType(entityDetailTabsName.securityEvent) })
|
||||||
// const performance = axios.get(`${api.entity.performance}/${this.entityType}`, { params: params })
|
const performance = axios.get(`${api.entity.performance}/${this.entityType}`, { params: this.getParamsByTabType(entityDetailTabsName.performanceEvent) })
|
||||||
|
|
||||||
Promise.all([informationAggregation, openPort]).then(response => {
|
Promise.allSettled([informationAggregation, openPort, security, performance]).then(response => {
|
||||||
if (response[0].status === 200) {
|
const informationAggregationResponse = response[0].value
|
||||||
|
if (informationAggregationResponse.status === 200) {
|
||||||
const list = []
|
const list = []
|
||||||
response[0].data.data.result.forEach(r => {
|
informationAggregationResponse.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,
|
||||||
@@ -152,40 +142,42 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
this.initSetTag(entityDetailTabsName.informationAggregation, list.length)
|
this.initSetTag(entityDetailTabsName.informationAggregation, list.length)
|
||||||
}
|
}
|
||||||
if (response[1].status === 200) {
|
const openPortResponse = response[1].value
|
||||||
this.initSetTag(entityDetailTabsName.openPort, response[1].data.data.result.length)
|
if (openPortResponse.status === 200) {
|
||||||
|
this.initSetTag(entityDetailTabsName.openPort, openPortResponse.data.data.result.length)
|
||||||
}
|
}
|
||||||
// if (response[2].status === 200) {
|
const securityResponse = response[2].value
|
||||||
// this.initSetTag(entityDetailTabsName.securityEvent, response[2].data.data.result.length)
|
if (securityResponse.status === 200) {
|
||||||
|
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: params })
|
const ipsOfApp = axios.get(api.entity.domainNameResolutionAboutIpsOfApp, { params: relatedEntityParams })
|
||||||
const domainsOfApp = axios.get(api.entity.domainNameResolutionAboutDomainsOfApp, { params: params })
|
const domainsOfApp = axios.get(api.entity.domainNameResolutionAboutDomainsOfApp, { params: relatedEntityParams })
|
||||||
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: params })
|
const appsOfIp = axios.get(api.entity.domainNameResolutionAboutAppsOfIp, { params: relatedEntityParams })
|
||||||
const domainsOfIp = axios.get(api.entity.domainNameResolutionAboutDomainsOfIp, { params: params })
|
const domainsOfIp = axios.get(api.entity.domainNameResolutionAboutDomainsOfIp, { params: relatedEntityParams })
|
||||||
const behaviorPattern = axios.get(api.entity.behaviorPattern, { params: params })
|
const behaviorPattern = axios.get(api.entity.behaviorPattern, { params: relatedEntityParams })
|
||||||
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: params })
|
const appsOfDomain = axios.get(api.entity.domainNameResolutionAboutAppsOfDomain, { params: relatedEntityParams })
|
||||||
const ipsOfDomain = axios.get(api.entity.domainNameResolutionAboutIpsOfDomain, { params: params })
|
const ipsOfDomain = axios.get(api.entity.domainNameResolutionAboutIpsOfDomain, { params: relatedEntityParams })
|
||||||
const fqdnsOfDomain = axios.get(api.entity.domainNameResolutionAboutFQDNsOfDomain, { params: params })
|
const fqdnsOfDomain = axios.get(api.entity.domainNameResolutionAboutFQDNsOfDomain, { params: relatedEntityParams })
|
||||||
this.promiseData(appsOfDomain, ipsOfDomain, fqdnsOfDomain)
|
this.promiseData(appsOfDomain, ipsOfDomain, fqdnsOfDomain)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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" >{{ unitConvert(data.value, unitTypes.number).join('')}}</div>
|
<div class="legend-value" >{{ valueToRangeValue(data.value, unitTypes.number).join('')}}</div>
|
||||||
<div class="legend-percent">{{ unitConvert(data.percent, unitTypes.percent).join('') }}</div>
|
<div class="legend-percent">{{ valueToRangeValue(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 } from '@/utils/date-util'
|
import { dateFormatByAppearance, getNowTime } 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 } from 'vue'
|
import { shallowRef, ref } from 'vue'
|
||||||
import { entityDetailTabsName, chartColorForBehaviorPattern, unitTypes } from '@/utils/constants'
|
import { entityDetailTabsName, chartColorForBehaviorPattern, unitTypes } from '@/utils/constants'
|
||||||
import unitConvert from '@/utils/unit-convert'
|
import { valueToRangeValue } 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,13 +49,20 @@ 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 () {
|
||||||
@@ -67,7 +74,7 @@ export default {
|
|||||||
}, 200)
|
}, 200)
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
unitConvert,
|
valueToRangeValue,
|
||||||
toUpperCaseByString,
|
toUpperCaseByString,
|
||||||
dateFormatByAppearance,
|
dateFormatByAppearance,
|
||||||
initEcharts () {
|
initEcharts () {
|
||||||
@@ -130,9 +137,7 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
async initData () {
|
async initData () {
|
||||||
const params = {
|
const params = this.getParams()
|
||||||
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
|
||||||
@@ -144,22 +149,18 @@ 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) {
|
if (value !== 0 && key !== 'total') {
|
||||||
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) {
|
||||||
|
|||||||
@@ -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,16 +105,24 @@ 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 = {
|
const params = this.getParams()
|
||||||
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 })
|
||||||
|
|||||||
@@ -72,8 +72,9 @@ 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 } from '@/utils/date-util'
|
import { dateFormatByAppearance, getNowTime } 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',
|
||||||
@@ -83,6 +84,18 @@ 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: {
|
||||||
@@ -108,7 +121,12 @@ export default {
|
|||||||
this.showError = false
|
this.showError = false
|
||||||
this.toggleLoading(true)
|
this.toggleLoading(true)
|
||||||
this.informationAggregationList = []
|
this.informationAggregationList = []
|
||||||
axios.get(`${api.entity.informationAggregation}/${this.entity.entityType}?resource=${this.entity.entityName}&pageSize=100&pageNo=1`).then(response => {
|
const params = this.getParams()
|
||||||
|
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
|
||||||
|
|||||||
@@ -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.currentDevelopmentPortsAndServices') }}</span>({{ openPortList.length }})
|
<span class="type-title-word">{{ $t('entities.tab.currentOpenPortsAndServices') }}</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,6 +27,8 @@ 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',
|
||||||
@@ -50,16 +52,21 @@ export default {
|
|||||||
mounted () {
|
mounted () {
|
||||||
this.initData()
|
this.initData()
|
||||||
},
|
},
|
||||||
setup () {
|
setup (props) {
|
||||||
|
// 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 = {
|
const params = this.getParams()
|
||||||
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 => {
|
||||||
|
|||||||
@@ -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') }} : </span>
|
<span>{{ $t('network.severity') }} : </span>
|
||||||
<span :test-id="`severity${index}`">{{ toUpperCaseByString(item.eventSeverity) || '-' }}</span>
|
<span :test-id="`severity${index}`">{{ changeSecurity(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 } from '@/utils/date-util'
|
import { dateFormatByAppearance, getNowTime } from '@/utils/date-util'
|
||||||
import { eventSeverityColor, entityDetailTabsName } from '@/utils/constants'
|
import { eventSeverityColor, entityDetailTabsName, securityLevel } 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,6 +60,7 @@ 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',
|
||||||
@@ -77,33 +78,36 @@ 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 = {
|
const params = this.getParams()
|
||||||
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
|
||||||
@@ -130,6 +134,18 @@ 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 '-'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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" :style="`background-color: ${eventSeverityColor[item.eventSecurity]}`"></div>
|
<div class="cn-detection__icon"></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">{{ toUpperCaseByString(item.securityType) || '-' }}</span>
|
<span class="detection-event-severity-block">{{ item.eventName || '-' }}</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') }} : </span>
|
<span>{{ $t('network.severity') }} : </span>
|
||||||
<span>{{ toUpperCaseByString(item.eventSeverity) || '-' }}</span>
|
<span>{{ changeSecurity(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 } from '@/utils/date-util'
|
import { dateFormatByAppearance, getNowTime } from '@/utils/date-util'
|
||||||
import { eventSeverityColor, entityDetailTabsName } from '@/utils/constants'
|
import { eventSeverityColor, entityDetailTabsName, securityLevel } 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,6 +85,7 @@ 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',
|
||||||
@@ -102,33 +103,36 @@ 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 = {
|
const params = this.getParams()
|
||||||
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
|
||||||
@@ -155,6 +159,18 @@ 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 '-'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 } from '@/utils/constants'
|
import { storageKey, ZH } 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,11 +156,9 @@ export default {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// 一行如果无数据,则删除该行,默认10*10矩阵
|
// 一行如果无数据,则删除该行,默认10*10矩阵
|
||||||
const rowXIndex = 0
|
this.handleXRowNoData(linkGridData, 0)
|
||||||
this.handleXRowNoData(linkGridData, rowXIndex)
|
|
||||||
// 一列如果无数据,则删除该列,默认10*10矩阵
|
// 一列如果无数据,则删除该列,默认10*10矩阵
|
||||||
const rowYIndex = 0
|
this.handleYRowNoData(linkGridData, 0)
|
||||||
this.handleYRowNoData(linkGridData, rowYIndex)
|
|
||||||
this.isLinkNoData = linkGridData.length === 0
|
this.isLinkNoData = linkGridData.length === 0
|
||||||
this.linkGridData = linkGridData
|
this.linkGridData = linkGridData
|
||||||
}
|
}
|
||||||
@@ -178,9 +176,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
|
||||||
@@ -257,11 +255,9 @@ export default {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// 一行如果无数据,则删除该行,默认3*3矩阵
|
// 一行如果无数据,则删除该行,默认3*3矩阵
|
||||||
const rowXIndex = 0
|
this.handleXRowNoData(nextGridData, 0)
|
||||||
this.handleXRowNoData(nextGridData, rowXIndex)
|
|
||||||
// 一列如果无数据,则删除该列,默认3*3矩阵
|
// 一列如果无数据,则删除该列,默认3*3矩阵
|
||||||
const rowYIndex = 0
|
this.handleYRowNoData(nextGridData, 0)
|
||||||
this.handleYRowNoData(nextGridData, rowYIndex)
|
|
||||||
|
|
||||||
this.isNextNoData = nextGridData.length === 0
|
this.isNextNoData = nextGridData.length === 0
|
||||||
this.nextGridData = nextGridData
|
this.nextGridData = nextGridData
|
||||||
@@ -357,7 +353,7 @@ export default {
|
|||||||
* @param index
|
* @param index
|
||||||
*/
|
*/
|
||||||
handleXRowNoData (data, index) {
|
handleXRowNoData (data, index) {
|
||||||
if (data) {
|
if (data && data.length > 0) {
|
||||||
const item = data[index]
|
const item = data[index]
|
||||||
let tempList = []
|
let tempList = []
|
||||||
if (item) {
|
if (item) {
|
||||||
@@ -380,7 +376,7 @@ export default {
|
|||||||
*/
|
*/
|
||||||
handleYRowNoData (data, index) {
|
handleYRowNoData (data, index) {
|
||||||
const rowList = []
|
const rowList = []
|
||||||
if (data) {
|
if (data && data.length > 0) {
|
||||||
data.forEach(item => {
|
data.forEach(item => {
|
||||||
if (item.out[index]) {
|
if (item.out[index]) {
|
||||||
if (item.out[index].noData) {
|
if (item.out[index].noData) {
|
||||||
|
|||||||
@@ -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('network.metric')}}:</span>
|
<span>{{$t('detections.metric')}}:</span>
|
||||||
<div class="line-select__operation">
|
<div class="line-select__operation">
|
||||||
<el-select
|
<el-select
|
||||||
size="mini"
|
size="mini"
|
||||||
|
|||||||
@@ -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.params ? this.$route.params.typeName : 'networkOverview'
|
const tableType = this.$route.path.replace('/panel/', '') || '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,11 +493,9 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
if (val) {
|
if (!show) { // 非滚动滚动条操作,直接覆盖之前的数据
|
||||||
this.providerOptions = res.data.list
|
this.providerOptions = res.data.list
|
||||||
} else if (!val && !show) {
|
} else { // 滚动条操作,则将新数据和之前的数据组合
|
||||||
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)
|
||||||
}
|
}
|
||||||
@@ -519,11 +517,9 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
if (val) {
|
if (!show) { // 非滚动滚动条操作,直接覆盖之前的数据
|
||||||
this.appOptions = res.data.list
|
this.appOptions = res.data.list
|
||||||
} else if (!val && !show) {
|
} else { // 滚动条操作,则将新数据和之前的数据组合
|
||||||
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, [])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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') }}:</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,7 +43,9 @@
|
|||||||
:popper-append-to-body="false"
|
:popper-append-to-body="false"
|
||||||
@change="referenceSelectChange"
|
@change="referenceSelectChange"
|
||||||
>
|
>
|
||||||
<el-option v-for="item in options2" :key="item.value" :label="item.label" :value="item.value"></el-option>
|
<el-option :key="options2[0].value" :label="$t(options2[0].label)" :value="options2[0].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>
|
||||||
@@ -274,6 +276,14 @@ 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',
|
||||||
|
|||||||
@@ -289,7 +289,9 @@ 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'
|
||||||
@@ -501,7 +503,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.params ? this.$route.params.typeName : 'networkOverview'
|
const tableType = this.$route.path.replace('/panel/', '') || '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)
|
||||||
@@ -534,7 +536,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.params.typeName === fromRoute.dnsServiceInsights) {
|
if (this.$route.path.replace('/panel/', '') === fromRoute.dnsServiceInsights) {
|
||||||
if (this.dnsQtypeMapData.size === 0) {
|
if (this.dnsQtypeMapData.size === 0) {
|
||||||
this.dnsQtypeMapData = await getDnsMapData('dnsQtype')
|
this.dnsQtypeMapData = await getDnsMapData('dnsQtype')
|
||||||
}
|
}
|
||||||
@@ -1170,10 +1172,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]
|
||||||
@@ -1222,9 +1224,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
|
||||||
@@ -1262,9 +1264,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
|
||||||
@@ -2260,10 +2262,9 @@ 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.params ? this.$route.params.typeName : 'networkOverview'
|
this.tableType = this.$route.path.replace('/panel/', '') || '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
|
||||||
@@ -2345,8 +2346,6 @@ export default {
|
|||||||
await this.saveUserLocalConfig()
|
await this.saveUserLocalConfig()
|
||||||
this.getChartData()
|
this.getChartData()
|
||||||
},
|
},
|
||||||
setup (props) {
|
|
||||||
},
|
|
||||||
beforeUnmount () {
|
beforeUnmount () {
|
||||||
// 以下元素,检测到内存并未释放
|
// 以下元素,检测到内存并未释放
|
||||||
this.unitConvert = null
|
this.unitConvert = null
|
||||||
|
|||||||
@@ -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.params ? this.$route.params.typeName : 'networkOverview'
|
const tableType = this.$route.path.replace('/panel/', '') || '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)
|
||||||
|
|||||||
@@ -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)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -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)
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -12,15 +12,15 @@
|
|||||||
placeholder=" "
|
placeholder=" "
|
||||||
:popper-append-to-body="false"
|
:popper-append-to-body="false"
|
||||||
>
|
>
|
||||||
<el-option value="Server">Server</el-option>
|
<el-option value="Server" :label="$t('overall.server')">{{$t('overall.server')}}</el-option>
|
||||||
<el-option value="Client">Client</el-option>
|
<el-option value="Client" :label="$t('overall.client')">{{$t('overall.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="All"
|
:placeholder="$t('overall.country')"
|
||||||
filterable
|
filterable
|
||||||
popper-class="map-select-down"
|
popper-class="map-select-down"
|
||||||
:popper-append-to-body="false"
|
:popper-append-to-body="false"
|
||||||
|
|||||||
@@ -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}`">{{scope.row[item.prop]}}</span>
|
<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>
|
||||||
</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,6 +57,7 @@ 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',
|
||||||
@@ -158,6 +159,14 @@ 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 () {
|
||||||
|
|||||||
@@ -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('network.metric')}}:</span>
|
<span>{{$t('detections.metric')}}:</span>
|
||||||
<div class="line-select__operation">
|
<div class="line-select__operation">
|
||||||
<el-select
|
<el-select
|
||||||
size="mini"
|
size="mini"
|
||||||
|
|||||||
@@ -257,7 +257,8 @@ export const pieChartOption4 = {
|
|||||||
show: false,
|
show: false,
|
||||||
position: 'middle',
|
position: 'middle',
|
||||||
formatter: '{b}: {c}'
|
formatter: '{b}: {c}'
|
||||||
}
|
},
|
||||||
|
barMinHeight: 5
|
||||||
}],
|
}],
|
||||||
animation: false
|
animation: false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,31 +1,36 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="detection-filter-case">
|
<div class="detection-filter-case">
|
||||||
<div class="new-detection-filter-title">{{$t('detections.filters')}}</div>
|
<div class="filter-case__header">{{$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" @click="filter.collapse = !filter.collapse">
|
<div class="filter__header">{{filter.title}}</div>
|
||||||
<span class="new-detection-filter-header-title">{{filter.title}}</span>
|
|
||||||
<i class="el-icon-arrow-right new-detection-filter-icon" :class="{ 'arrow-rotate': !filter.collapse }"></i>
|
<div class="filter__body" style="position: relative">
|
||||||
|
<loading :loading="loadingLeft" style="top: -5px;"></loading>
|
||||||
|
|
||||||
|
<div class="filter__body-item"
|
||||||
|
v-for="(data, i) in filter.data.slice(0, filter.showIndex)"
|
||||||
|
:key="i"
|
||||||
|
@click="clickFilterItem(data.label, filter.column, index)">
|
||||||
|
<div class="filter__body-item-left">
|
||||||
|
<div class="filter__body-item-left-index">{{ i+1 }}</div>
|
||||||
|
<div class="filter__body-item-left-label">
|
||||||
|
<el-tooltip :content="data.label" placement="top" effect="light" :disabled="disabledLabel">
|
||||||
|
<span @mouseenter="handleMouse(`filter${index}${i}`)" :id="`filter${index}${i}`">
|
||||||
|
<span>{{ data.label }}</span>
|
||||||
|
</span>
|
||||||
|
</el-tooltip>
|
||||||
</div>
|
</div>
|
||||||
<el-collapse-transition>
|
|
||||||
<div class="filter__body" v-show="!filter.collapse">
|
|
||||||
<el-checkbox-group v-model="filter.value">
|
|
||||||
<template v-for="(d, i) in filter.data" :key="i">
|
|
||||||
<el-checkbox :label="d.value" v-if="!filter.showIndex || filter.showIndex >= i">
|
|
||||||
<div class="filter__checkbox-label">
|
|
||||||
<div style="display: flex">
|
|
||||||
<span class="severity-color-block" v-if="filter.column === 'eventSeverity'" :style="`background-color: ${eventSeverityColor[d.value]}`"></span>
|
|
||||||
<span :style="filter.column === 'eventSeverity' ? 'padding-left: 10px' : ''">{{d.label}}</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div v-if="d.count || d.count === 0">{{d.count}}</div>
|
<div class="filter__body-item-right">{{ data.count }}</div>
|
||||||
</div>
|
</div>
|
||||||
</el-checkbox>
|
|
||||||
</template>
|
|
||||||
</el-checkbox-group>
|
|
||||||
<div class="filter__more" v-if="filter.showMore" @click="showMore(filter)">{{$t('overall.showMore')}}</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>
|
||||||
@@ -42,13 +47,36 @@ export default {
|
|||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
eventSeverityColor
|
eventSeverityColor,
|
||||||
|
disabledLabel: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
showMore (filter) {
|
showMore (filter) {
|
||||||
filter.showIndex && (filter.showIndex += 10)
|
filter.showIndex && (filter.showIndex += 5)
|
||||||
filter.showIndex >= (filter.data.length - 1) && (filter.showMore = false)
|
filter.showIndex >= (filter.data.length - 1) && (filter.showDisabled = true)
|
||||||
|
},
|
||||||
|
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: {
|
||||||
|
|||||||
@@ -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">
|
<div class="explorer-search__input-case explorer-search__input-case--question-mark-in-line" style="position: relative">
|
||||||
<div class="explorer-search__input">
|
<div class="explorer-search__input entity__search">
|
||||||
<advanced-search
|
<advanced-search
|
||||||
ref="search"
|
ref="search"
|
||||||
:column-list="columnList[pageType]"
|
:column-list="columnList[pageType]"
|
||||||
@@ -13,6 +13,36 @@
|
|||||||
@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>-->
|
||||||
@@ -25,6 +55,9 @@ 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: {
|
||||||
@@ -95,7 +128,9 @@ export default {
|
|||||||
label: 'OR'
|
label: 'OR'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
showList: true
|
showList: true,
|
||||||
|
showHistory: false,
|
||||||
|
history: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
emits: ['search'],
|
emits: ['search'],
|
||||||
@@ -122,71 +157,67 @@ export default {
|
|||||||
}
|
}
|
||||||
this.$emit('search', metaList, sql)
|
this.$emit('search', metaList, sql)
|
||||||
}, */
|
}, */
|
||||||
search ({ q, metaList }) {
|
changeTimeByDate,
|
||||||
|
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) { // params: { column: columnName, oldValue: [...], newValue: [...] }
|
changeParams (params) {
|
||||||
// 向下传递时需要再转换一次param格式为[{column, operator, value}, ...]
|
this.$refs.search.addParams(params)
|
||||||
if (params.oldValue.length === 0 && params.newValue.length === 1) {
|
},
|
||||||
// 1.参数值数量从0到1,直接addParams
|
selectHistory (row) {
|
||||||
const p = {
|
this.$refs.search.setStr(row.str)
|
||||||
column: params.column,
|
this.showHistory = false
|
||||||
operator: '=',
|
this.$nextTick(() => {
|
||||||
value: params.newValue
|
if (this.$refs.search.$refs.textMode) {
|
||||||
}
|
this.$refs.search.$refs.textMode.focus()
|
||||||
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.参数值数量从多到1,operator由'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 }])
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
if (this.showList) {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.emitter.emit('advanced-search')
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -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">
|
<div class="explorer-top-tools-block" @click="jumpNewDetetion" v-if="hasPermission('detectionPolicy')">
|
||||||
<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,13 +21,12 @@
|
|||||||
:end-time="timeFilter.endTime"/>
|
:end-time="timeFilter.endTime"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style="width: 100%;padding-bottom: 47px;">
|
<div style="width: 100%; padding-bottom: 50px;">
|
||||||
<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"
|
||||||
@@ -48,6 +47,7 @@
|
|||||||
: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,6 +138,8 @@ 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',
|
||||||
@@ -172,12 +174,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: {
|
||||||
@@ -188,6 +190,7 @@ export default {
|
|||||||
topColumn: 'status',
|
topColumn: 'status',
|
||||||
collapse: false,
|
collapse: false,
|
||||||
value: [], // value之间是or的关系
|
value: [], // value之间是or的关系
|
||||||
|
showMore: false,
|
||||||
data: [] // 从接口动态获取,本项在获得数据后需要特殊处理左边框颜色
|
data: [] // 从接口动态获取,本项在获得数据后需要特殊处理左边框颜色
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -196,6 +199,7 @@ export default {
|
|||||||
topColumn: 'severity',
|
topColumn: 'severity',
|
||||||
collapse: false,
|
collapse: false,
|
||||||
value: [], // value之间是or的关系
|
value: [], // value之间是or的关系
|
||||||
|
showMore: false,
|
||||||
data: [] // 从接口动态获取,本项在获得数据后需要特殊处理左边框颜色
|
data: [] // 从接口动态获取,本项在获得数据后需要特殊处理左边框颜色
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -204,6 +208,9 @@ 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: [] // 从接口动态获取
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -213,43 +220,21 @@ export default {
|
|||||||
collapse: false,
|
collapse: false,
|
||||||
value: [],
|
value: [],
|
||||||
showMore: true,
|
showMore: true,
|
||||||
showIndex: 9,
|
showDisabled: true,
|
||||||
|
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: false,
|
showMore: true,
|
||||||
showIndex: 9,
|
showDisabled: true,
|
||||||
|
showIndex: 5,
|
||||||
data: [] // 从接口动态获取
|
data: [] // 从接口动态获取
|
||||||
}
|
}
|
||||||
// {
|
|
||||||
// title: this.$t('detections.offenderLocation'),
|
|
||||||
// column: 'offenderLocationCountry',
|
|
||||||
// collapse: false,
|
|
||||||
// value: [],
|
|
||||||
// showMore: false,
|
|
||||||
// showIndex: 9,
|
|
||||||
// data: [] // 从接口动态获取
|
|
||||||
// }
|
|
||||||
],
|
],
|
||||||
performanceEvent: [
|
performanceEvent: [
|
||||||
{
|
{
|
||||||
@@ -286,7 +271,8 @@ export default {
|
|||||||
isStatisticsActiveAttackNoData: false,
|
isStatisticsActiveAttackNoData: false,
|
||||||
loading: false,
|
loading: false,
|
||||||
oldActiveEntitySearchValue: '',
|
oldActiveEntitySearchValue: '',
|
||||||
initFlag: true // 初始化标识,初始化时保证mounted执行
|
initFlag: true, // 初始化标识,初始化时保证mounted执行
|
||||||
|
detectionChart:shallowRef(null)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -294,6 +280,11 @@ 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') {
|
||||||
@@ -388,6 +379,11 @@ 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 }))
|
||||||
@@ -410,6 +406,7 @@ 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)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -430,6 +427,11 @@ 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) {
|
||||||
@@ -441,6 +443,15 @@ 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
|
||||||
@@ -452,6 +463,9 @@ 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))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -467,28 +481,45 @@ 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}`)
|
||||||
let detectionChart = echarts.getInstanceByDom(chartDom)
|
this.detectionChart = echarts.getInstanceByDom(chartDom)
|
||||||
if (detectionChart) {
|
if (this.detectionChart) {
|
||||||
echarts.dispose(detectionChart)
|
echarts.dispose(this.detectionChart)
|
||||||
}
|
}
|
||||||
detectionChart = echarts.init(chartDom)
|
this.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) } }
|
||||||
})
|
})
|
||||||
detectionChart.setOption(securityTypeOption)
|
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')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.detectionChart.setOption(securityTypeOption)
|
||||||
|
|
||||||
const vm = this
|
const vm = this
|
||||||
detectionChart.off('click')
|
this.detectionChart.off('click')
|
||||||
detectionChart.on('click', e => {
|
this.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))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -504,9 +535,10 @@ export default {
|
|||||||
count: r.count
|
count: r.count
|
||||||
}))
|
}))
|
||||||
this.isCheckFilterByQ(params, 4)
|
this.isCheckFilterByQ(params, 4)
|
||||||
const { showMore, showIndex } = this.computeFilterPage(this.filterData[this.pageType][4].data)
|
const { showMore, showIndex, showDisabled } = 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)
|
||||||
@@ -526,14 +558,18 @@ 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.getFilter(e.data[1], vm.filterData.securityEvent[4].column)
|
||||||
vm.filterData.securityEvent[4].value = vm.triggerFilterDataValue(vm.filterData.securityEvent[4].value, e.data[1])
|
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 = 9
|
this.filterData[this.pageType][4].showIndex = 5
|
||||||
|
this.filterData[this.pageType][4].showDisabled = true
|
||||||
this.$message.error(this.errorMsgHandler(e))
|
this.$message.error(this.errorMsgHandler(e))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -543,14 +579,16 @@ 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 } = this.computeFilterPage(this.filterData[this.pageType][3].data)
|
const { showMore, showIndex, showDisabled } = 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 = 9
|
this.filterData[this.pageType][3].showIndex = 5
|
||||||
|
this.filterData[this.pageType][3].showDisabled = true
|
||||||
this.$message.error(this.errorMsgHandler(e))
|
this.$message.error(this.errorMsgHandler(e))
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -631,8 +669,9 @@ export default {
|
|||||||
},
|
},
|
||||||
computeFilterPage (data) {
|
computeFilterPage (data) {
|
||||||
return {
|
return {
|
||||||
showMore: data.length > 10,
|
showMore: data.length > 0,
|
||||||
showIndex: 9
|
showDisabled: data.length <= 5,
|
||||||
|
showIndex: 5
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
queryList (q) {
|
queryList (q) {
|
||||||
@@ -716,7 +755,7 @@ export default {
|
|||||||
this.q = ''
|
this.q = ''
|
||||||
this.metaList = []
|
this.metaList = []
|
||||||
}
|
}
|
||||||
if (this.pageObj.resetPageNo) {
|
if (this.pageObj.resetPageNo && !this.initFlag) {
|
||||||
this.pageObj.pageNo = 1
|
this.pageObj.pageNo = 1
|
||||||
} else {
|
} else {
|
||||||
this.pageObj.resetPageNo = true
|
this.pageObj.resetPageNo = true
|
||||||
@@ -774,11 +813,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)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -803,10 +842,28 @@ 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: '/detectionPolicy',
|
path: '/detection/policy',
|
||||||
query: {
|
query: {
|
||||||
t: +new Date()
|
t: +new Date()
|
||||||
}
|
}
|
||||||
@@ -823,11 +880,34 @@ 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 () {
|
||||||
@@ -846,7 +926,11 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.queryFilter(q)
|
this.queryFilter(q)
|
||||||
|
if (this.initFlag) {
|
||||||
|
this.timer = setTimeout(() => {
|
||||||
this.initFlag = false
|
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)
|
||||||
@@ -916,78 +1000,6 @@ 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 () {
|
||||||
@@ -995,11 +1007,10 @@ export default {
|
|||||||
},
|
},
|
||||||
setup () {
|
setup () {
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
let { params, query, path } = useRoute()
|
let { 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
|
||||||
|
|
||||||
@@ -1007,15 +1018,16 @@ 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 = params.typeName
|
const pageType = path.replace('/detection/', '')
|
||||||
// 获取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
|
||||||
const dateRangeValue = rangeParam ? parseInt(query.range) : 60
|
// 优先级:url > config.js > 默认值。
|
||||||
|
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(60)
|
const { startTime, endTime } = getNowTime(dateRangeValue)
|
||||||
timeFilter.value.startTime = getSecond(startTime)
|
timeFilter.value.startTime = getSecond(startTime)
|
||||||
timeFilter.value.endTime = getSecond(endTime)
|
timeFilter.value.endTime = getSecond(endTime)
|
||||||
// 如果没有时间参数,就将参数写入url
|
// 如果没有时间参数,就将参数写入url
|
||||||
@@ -1025,9 +1037,17 @@ 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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
: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"
|
||||||
@@ -75,7 +76,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"></detection-drawer>
|
<detection-drawer :drawer-info="drawerInfo" @edit="onEdit" />
|
||||||
</el-drawer>
|
</el-drawer>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -89,6 +90,7 @@ 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',
|
||||||
@@ -118,14 +120,40 @@ 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,
|
||||||
name: keyWord
|
q: keyWord
|
||||||
}
|
}
|
||||||
this.search(this.filterParams, 'detection')
|
this.search(this.filterParams, 'detection')
|
||||||
},
|
},
|
||||||
@@ -140,7 +168,7 @@ export default {
|
|||||||
},
|
},
|
||||||
onCreate () {
|
onCreate () {
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
path: '/detectionPolicy/create',
|
path: '/detection/policy/create',
|
||||||
query: {
|
query: {
|
||||||
t: +new Date()
|
t: +new Date()
|
||||||
}
|
}
|
||||||
@@ -149,11 +177,12 @@ 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: '/detectionPolicy/edit',
|
path: '/detection/policy/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 || ''
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,7 +2,10 @@
|
|||||||
<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">ID: {{ drawerInfo.ruleId }}</div>
|
<div class="drawer-basic-id">
|
||||||
|
<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>
|
||||||
@@ -82,7 +85,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">
|
||||||
@@ -102,7 +105,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="drawer-collapse-content" v-if="language==='cn'">
|
<div class="drawer-collapse-content" v-if="language===ZH">
|
||||||
<div class="drawer-collapse-trigger">
|
<div class="drawer-collapse-trigger">
|
||||||
当条件为
|
当条件为
|
||||||
<span style="color: #046ECA">
|
<span style="color: #046ECA">
|
||||||
@@ -131,7 +134,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { switchStatus, toUpperCaseByString } from '@/utils/tools'
|
import { switchStatus, toUpperCaseByString } from '@/utils/tools'
|
||||||
import { detectionUnitList, eventSeverityColor, securityLevel, storageKey } from '@/utils/constants'
|
import { detectionUnitList, eventSeverityColor, securityLevel, storageKey, ZH, EN } from '@/utils/constants'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { api } from '@/utils/api'
|
import { api } from '@/utils/api'
|
||||||
|
|
||||||
@@ -149,9 +152,11 @@ export default {
|
|||||||
detailData: {},
|
detailData: {},
|
||||||
eventSeverityColor,
|
eventSeverityColor,
|
||||||
severityList: [],
|
severityList: [],
|
||||||
language: 'en',
|
language: EN,
|
||||||
atLeast: 0,
|
atLeast: 0,
|
||||||
times: 'time'
|
times: 'time',
|
||||||
|
ZH,
|
||||||
|
EN
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@@ -166,7 +171,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.language = localStorage.getItem(storageKey.language) || 'en'
|
this.language = localStorage.getItem(storageKey.language) || EN
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
switchStatus,
|
switchStatus,
|
||||||
@@ -243,6 +248,9 @@ export default {
|
|||||||
} else {
|
} else {
|
||||||
return '-'
|
return '-'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
onEdit () {
|
||||||
|
this.$emit('edit')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
<div class="new-filter-content-content">
|
<div class="new-filter-content-content">
|
||||||
<el-checkbox-group v-model="checkEventType" @change="onChangeCategory" style="display: flex;flex-direction: column">
|
<el-checkbox-group v-model="checkEventType" @change="onChangeCategory" style="display: flex;flex-direction: column">
|
||||||
<el-checkbox v-for="item in eventTypeList" :key="item.name" class="new-filter-content-checkbox" :label="item.name">
|
<el-checkbox v-for="item in eventTypeList" :key="item.name" class="new-filter-content-checkbox" :label="item.name">
|
||||||
{{ item.label }}
|
{{ item.name }}
|
||||||
</el-checkbox>
|
</el-checkbox>
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</div>
|
</div>
|
||||||
@@ -94,13 +94,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (data.eventTypeList) {
|
if (data.eventTypeList) {
|
||||||
this.eventTypeList = []
|
this.eventTypeList = data.eventTypeList
|
||||||
data.eventTypeList.forEach(item => {
|
|
||||||
const obj = detectionUnitList.eventTypeList.find(d => d.value === item.name)
|
|
||||||
if (obj) {
|
|
||||||
this.eventTypeList.push({ ...item, label: this.$t(obj.label) })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
this.eventTypeList = []
|
this.eventTypeList = []
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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">
|
<el-collapse v-model="activeNames" class="policy-form-trigger">
|
||||||
<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,16 +53,16 @@
|
|||||||
</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">
|
||||||
<el-input size="mini" v-model="triggerObj.atLeast" oninput="value=value.replace(/[^\d]/g,'')"></el-input>
|
<el-input size="mini" maxlength="5" v-model="triggerObj.atLeast" oninput="value=value.replace(/[^\d]/g,'')"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<div>times within</div>
|
<div>times within</div>
|
||||||
|
|
||||||
<el-form-item prop="interval">
|
<el-form-item prop="interval" class="policy-form-item">
|
||||||
<el-input size="mini" v-model="triggerObj.interval" oninput="value=value.replace(/[^\d]/g,'')"></el-input>
|
<el-input size="mini" maxlength="5" v-model="triggerObj.interval" oninput="value=value.replace(/[^\d]/g,'')"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item prop="intervalVal">
|
<el-form-item prop="intervalVal">
|
||||||
@@ -79,8 +79,8 @@
|
|||||||
|
|
||||||
<div class="trigger-block-item">
|
<div class="trigger-block-item">
|
||||||
<div>With the counter resetting after no activity for</div>
|
<div>With the counter resetting after no activity for</div>
|
||||||
<el-form-item prop="resetInterval">
|
<el-form-item prop="resetInterval" class="policy-form-item">
|
||||||
<el-input size="mini" v-model="triggerObj.resetInterval" oninput="value=value.replace(/[^\d]/g,'')"></el-input>
|
<el-input size="mini" maxlength="5" v-model="triggerObj.resetInterval" oninput="value=value.replace(/[^\d]/g,'')"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="resetIntervalVal">
|
<el-form-item prop="resetIntervalVal">
|
||||||
<el-select v-model="triggerObj.resetIntervalVal" class="form-trigger__select" placeholder=" " size="mini">
|
<el-select v-model="triggerObj.resetIntervalVal" class="form-trigger__select" placeholder=" " size="mini">
|
||||||
@@ -94,11 +94,11 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
</el-form>
|
</el-form>
|
||||||
<el-form v-if="language==='cn'" class="trigger-block margin-b-20" ref="form3" :model="triggerObj" :rules="rules">
|
<el-form v-if="language===ZH" 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">
|
||||||
<el-input size="mini" v-model="triggerObj.interval" oninput="value=value.replace(/[^\d]/g,'')"></el-input>
|
<el-input size="mini" maxlength="5" v-model="triggerObj.interval" oninput="value=value.replace(/[^\d]/g,'')"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item prop="intervalVal">
|
<el-form-item prop="intervalVal">
|
||||||
@@ -113,7 +113,7 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
内至少发生
|
内至少发生
|
||||||
<el-form-item prop="atLeast">
|
<el-form-item prop="atLeast">
|
||||||
<el-input size="mini" v-model="triggerObj.atLeast" oninput="value=value.replace(/[^\d]/g,'')"></el-input>
|
<el-input size="mini" maxlength="5" v-model="triggerObj.atLeast" oninput="value=value.replace(/[^\d]/g,'')"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
次
|
次
|
||||||
</div>
|
</div>
|
||||||
@@ -121,7 +121,7 @@
|
|||||||
<div class="trigger-block-item">
|
<div class="trigger-block-item">
|
||||||
若连续
|
若连续
|
||||||
<el-form-item prop="resetInterval">
|
<el-form-item prop="resetInterval">
|
||||||
<el-input size="mini" v-model="triggerObj.resetInterval" oninput="value=value.replace(/[^\d]/g,'')"></el-input>
|
<el-input size="mini" maxlength="5" v-model="triggerObj.resetInterval" oninput="value=value.replace(/[^\d]/g,'')"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="resetIntervalVal">
|
<el-form-item prop="resetIntervalVal">
|
||||||
<el-select v-model="triggerObj.resetIntervalVal" class="form-trigger__select" placeholder=" " size="mini">
|
<el-select v-model="triggerObj.resetIntervalVal" class="form-trigger__select" placeholder=" " size="mini">
|
||||||
@@ -136,18 +136,20 @@
|
|||||||
不活跃将重置计数
|
不活跃将重置计数
|
||||||
</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>
|
||||||
|
|
||||||
@@ -160,11 +162,45 @@ 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 } from '@/utils/constants'
|
import { storageKey, detectionUnitList, ZH, EN } from '@/utils/constants'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'DetectionForm',
|
name: 'DetectionForm',
|
||||||
data () {
|
data () {
|
||||||
|
const intervalValidator = (rule, value, callback) => {
|
||||||
|
const obj = this.handleIntervalByDateType(rule, value, this.triggerObj.intervalVal)
|
||||||
|
if (!obj.flag && obj.msg) {
|
||||||
|
callback(new Error(obj.msg))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const intervalValValidator = (rule, value, callback) => {
|
||||||
|
const obj = this.handleIntervalByDateType(rule, this.triggerObj.intervalVal, value)
|
||||||
|
if (!obj.flag && obj.msg) {
|
||||||
|
this.$refs.form3.validateField('interval')
|
||||||
|
callback()
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const resetIntervalValidator = (rule, value, callback) => {
|
||||||
|
const obj = this.handleIntervalByDateType(rule, value, this.triggerObj.resetIntervalVal)
|
||||||
|
if (!obj.flag && obj.msg) {
|
||||||
|
callback(new Error(obj.msg))
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const resetIntervalValValidator = (rule, value, callback) => {
|
||||||
|
const obj = this.handleIntervalByDateType(rule, this.triggerObj.resetIntervalVal, value)
|
||||||
|
if (!obj.flag && obj.msg) {
|
||||||
|
this.$refs.form3.validateField('resetInterval')
|
||||||
|
callback()
|
||||||
|
} else {
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
activeNames: ['1'],
|
activeNames: ['1'],
|
||||||
rules: {
|
rules: {
|
||||||
@@ -180,6 +216,10 @@ export default {
|
|||||||
required: true,
|
required: true,
|
||||||
message: this.$t('validate.required'),
|
message: this.$t('validate.required'),
|
||||||
trigger: 'blur'
|
trigger: 'blur'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
validator: intervalValidator,
|
||||||
|
trigger: 'blur'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
intervalVal: [
|
intervalVal: [
|
||||||
@@ -187,6 +227,10 @@ export default {
|
|||||||
required: true,
|
required: true,
|
||||||
message: this.$t('validate.required'),
|
message: this.$t('validate.required'),
|
||||||
trigger: 'change'
|
trigger: 'change'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
validator: intervalValValidator,
|
||||||
|
trigger: 'change'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
resetInterval: [
|
resetInterval: [
|
||||||
@@ -194,6 +238,10 @@ export default {
|
|||||||
required: true,
|
required: true,
|
||||||
message: this.$t('validate.required'),
|
message: this.$t('validate.required'),
|
||||||
trigger: 'blur'
|
trigger: 'blur'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
validator: resetIntervalValidator,
|
||||||
|
trigger: 'blur'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
resetIntervalVal: [
|
resetIntervalVal: [
|
||||||
@@ -201,13 +249,19 @@ export default {
|
|||||||
required: true,
|
required: true,
|
||||||
message: this.$t('validate.required'),
|
message: this.$t('validate.required'),
|
||||||
trigger: 'change'
|
trigger: 'change'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
validator: resetIntervalValValidator,
|
||||||
|
trigger: 'change'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
intervalList: [],
|
intervalList: [],
|
||||||
editObj: {},
|
editObj: {},
|
||||||
isComplete: true, // 参数完整标识,默认完整(照顾编辑模式),false即不完整
|
isComplete: true, // 参数完整标识,默认完整(照顾编辑模式),false即不完整
|
||||||
language: 'en'
|
language: EN,
|
||||||
|
ZH,
|
||||||
|
EN
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
@@ -216,10 +270,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 === 'cn') {
|
} else if (this.language === ZH) {
|
||||||
this.intervalList = detectionUnitList.intervalListCN
|
this.intervalList = detectionUnitList.intervalListCN
|
||||||
}
|
}
|
||||||
this.getDetailInfo()
|
this.getDetailInfo()
|
||||||
@@ -280,7 +334,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: '/detectionPolicy',
|
path: '/detection/policy',
|
||||||
query: {
|
query: {
|
||||||
pageNo: this.pageNoForTable ? Number(this.pageNoForTable) : 1,
|
pageNo: this.pageNoForTable ? Number(this.pageNoForTable) : 1,
|
||||||
t: +new Date()
|
t: +new Date()
|
||||||
@@ -317,7 +371,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
/** 创建policy */
|
/** 创建policy */
|
||||||
createPolicy (flag) {
|
createPolicy () {
|
||||||
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
|
||||||
|
|
||||||
@@ -326,9 +380,6 @@ 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)
|
||||||
@@ -352,7 +403,7 @@ export default {
|
|||||||
})
|
})
|
||||||
|
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
path: '/detectionPolicy',
|
path: '/detection/policy',
|
||||||
query: {
|
query: {
|
||||||
t: +new Date()
|
t: +new Date()
|
||||||
}
|
}
|
||||||
@@ -377,12 +428,18 @@ export default {
|
|||||||
message: this.$t('tip.saveSuccess')
|
message: this.$t('tip.saveSuccess')
|
||||||
})
|
})
|
||||||
|
|
||||||
this.$router.push({
|
const { query } = this.$route
|
||||||
path: '/detectionPolicy',
|
const queryInfo = {
|
||||||
query: {
|
|
||||||
pageNo: self.pageNoForTable ? Number(self.pageNoForTable) : 1,
|
pageNo: self.pageNoForTable ? Number(self.pageNoForTable) : 1,
|
||||||
t: +new Date()
|
t: +new Date()
|
||||||
}
|
}
|
||||||
|
if (query.name && query.id) {
|
||||||
|
queryInfo.ruleId = query.id
|
||||||
|
queryInfo.name = this.settingObj.name
|
||||||
|
}
|
||||||
|
this.$router.push({
|
||||||
|
path: '/detection/policy',
|
||||||
|
query: queryInfo
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
console.error(response.data.message)
|
console.error(response.data.message)
|
||||||
@@ -417,7 +474,157 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
this.$message.error(this.$t('detection.create.informationFilled'))
|
this.$message.error(this.$t('detection.create.informationFilled'))
|
||||||
|
},
|
||||||
|
handleIntervalByDateType (rule, value, type) {
|
||||||
|
if (value && (type === 'hours' || type === '小时')) {
|
||||||
|
if (parseInt(value) <= 24) {
|
||||||
|
return { flag: true }
|
||||||
|
} else {
|
||||||
|
return { flag: false, msg: this.$t('policy.dateTimeRangeHours') }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (value && (type === 'minutes' || type === '分钟')) {
|
||||||
|
if (parseInt(value) <= 1440) {
|
||||||
|
return { flag: true }
|
||||||
|
} else {
|
||||||
|
return { flag: false, msg: this.$t('policy.dateTimeRangeMinutes') }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (value && (type === 'seconds' || type === '秒')) {
|
||||||
|
if (parseInt(value) <= 86400) {
|
||||||
|
return { flag: true }
|
||||||
|
} else {
|
||||||
|
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>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
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"
|
||||||
@@ -31,6 +32,7 @@
|
|||||||
: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>
|
||||||
@@ -56,9 +58,6 @@
|
|||||||
<template v-else-if="item.prop === 'category'">
|
<template v-else-if="item.prop === 'category'">
|
||||||
{{ changeCategory(scope.row[item.prop]) }}
|
{{ changeCategory(scope.row[item.prop]) }}
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="item.prop === 'eventType'">
|
|
||||||
{{ changeEventType(scope.row[item.prop]) }}
|
|
||||||
</template>
|
|
||||||
<template v-else-if="item.prop === 'description'">
|
<template v-else-if="item.prop === 'description'">
|
||||||
<div style="padding-right: 20px">{{ scope.row[item.prop] }}</div>
|
<div style="padding-right: 20px">{{ scope.row[item.prop] }}</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -85,6 +84,7 @@ 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,6 +92,9 @@ export default {
|
|||||||
isNoData: {
|
isNoData: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
|
},
|
||||||
|
policyDetail: {
|
||||||
|
type: Object
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mixins: [table],
|
mixins: [table],
|
||||||
@@ -149,6 +152,17 @@ 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,
|
||||||
@@ -181,16 +195,6 @@ export default {
|
|||||||
}
|
}
|
||||||
return label
|
return label
|
||||||
}
|
}
|
||||||
},
|
|
||||||
changeEventType (value) {
|
|
||||||
if (value) {
|
|
||||||
const obj = detectionUnitList.eventTypeList.find(d => d.value === value)
|
|
||||||
let label = value
|
|
||||||
if (obj) {
|
|
||||||
label = this.$t(obj.label)
|
|
||||||
}
|
|
||||||
return label
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
<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"
|
||||||
@@ -13,6 +14,7 @@
|
|||||||
|
|
||||||
<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"
|
||||||
@@ -24,6 +26,7 @@
|
|||||||
|
|
||||||
<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"
|
||||||
@@ -47,6 +50,9 @@
|
|||||||
</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: {
|
||||||
@@ -64,9 +70,21 @@ 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')
|
||||||
@@ -76,6 +94,14 @@ 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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ export const pieForSeverity = {
|
|||||||
legend: {
|
legend: {
|
||||||
orient: 'vertical',
|
orient: 'vertical',
|
||||||
type: 'plain',
|
type: 'plain',
|
||||||
left: '60%',
|
left: '44%',
|
||||||
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: ['30%', '50%'],
|
center: ['22%', '50%'],
|
||||||
data: [],
|
data: [],
|
||||||
label: {
|
label: {
|
||||||
show: false
|
show: false
|
||||||
|
|||||||
@@ -243,7 +243,7 @@ export default {
|
|||||||
},
|
},
|
||||||
goDetail (type, name) {
|
goDetail (type, name) {
|
||||||
const { href } = this.$router.resolve({
|
const { href } = this.$router.resolve({
|
||||||
path: '/entityDetail',
|
path: '/entity/detail',
|
||||||
query: {
|
query: {
|
||||||
entityType: type,
|
entityType: type,
|
||||||
entityName: name
|
entityName: name
|
||||||
|
|||||||
@@ -274,7 +274,7 @@ export default {
|
|||||||
},
|
},
|
||||||
goDetail (type, name) {
|
goDetail (type, name) {
|
||||||
const { href } = this.$router.resolve({
|
const { href } = this.$router.resolve({
|
||||||
path: '/entityDetail',
|
path: '/entity/detail',
|
||||||
query: {
|
query: {
|
||||||
entityType: type,
|
entityType: type,
|
||||||
entityName: name
|
entityName: name
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ export default {
|
|||||||
},
|
},
|
||||||
goDetail (type, name) {
|
goDetail (type, name) {
|
||||||
const { href } = this.$router.resolve({
|
const { href } = this.$router.resolve({
|
||||||
path: '/entityDetail',
|
path: '/entity/detail',
|
||||||
query: {
|
query: {
|
||||||
entityType: type,
|
entityType: type,
|
||||||
entityName: name
|
entityName: name
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<span class="row__content--link">{{detection.victimIp}}</span> communicated with <span class="row__content--link">{{detection.offenderIp}}</span> that was associated with the indicator of {{detection.eventName}}.
|
<span class="row__content--link">{{detection.victimIp}}</span> communicated with <span class="row__content--link">{{detection.offenderIp}}</span> that was associated with the indicator of {{detection.eventName}}.
|
||||||
</div>
|
</div>
|
||||||
<div class="row__content1" v-else>
|
<div class="row__content1" v-else>
|
||||||
{{basicInfo.ruleDescription || '-'}}
|
{{ $_.get(basicInfo, 'ruleInfo.description', '-') || '-' }}
|
||||||
</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('entities.reputationLevel') }}</div>
|
<div class="row__label">{{ $t('detection.domainReputationLevel') }}</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,6 +242,17 @@
|
|||||||
</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>
|
||||||
|
<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">
|
||||||
@@ -431,10 +442,7 @@ export default {
|
|||||||
dateFormatByAppearance,
|
dateFormatByAppearance,
|
||||||
/** 初始化实体详情 */
|
/** 初始化实体详情 */
|
||||||
initEntityDetail () {
|
initEntityDetail () {
|
||||||
// 为完整填充IP信息,攻击者ip、受害者ip都进行调用;
|
// 调接口查询攻击者和受害者IP、Domain、APP的更多信息;
|
||||||
// 根据detection的eventInfo对象的ioc_type进行判断,若为domain,malware信息从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) {
|
||||||
@@ -466,7 +474,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.ruleDescription = res.data.data.description
|
this.basicInfo.ruleInfo = res.data.data
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -491,7 +499,7 @@ export default {
|
|||||||
goDetail (type, name) {
|
goDetail (type, name) {
|
||||||
if (name) {
|
if (name) {
|
||||||
const { href } = this.$router.resolve({
|
const { href } = this.$router.resolve({
|
||||||
path: '/entityDetail',
|
path: '/entity/detail',
|
||||||
query: {
|
query: {
|
||||||
entityType: type,
|
entityType: type,
|
||||||
entityName: name
|
entityName: name
|
||||||
@@ -499,6 +507,19 @@ 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 () {
|
||||||
|
|||||||
@@ -39,6 +39,11 @@ 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
|
||||||
|
|||||||
@@ -4,8 +4,16 @@
|
|||||||
: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-detection-top-tools">
|
<div class="explorer-entity-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>
|
||||||
<!-- 搜索组件 -->
|
<!-- 搜索组件 -->
|
||||||
@@ -36,16 +44,26 @@
|
|||||||
<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 }} </span>results,IP
|
<span>{{ summaryCount.totalCount }} </span>{{$t('overall.results')}},IP
|
||||||
<span>{{ summaryCount.ipCount }}</span>,Domain
|
<span>{{ summaryCount.ipCount }}</span>,{{$t('overall.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"
|
||||||
@@ -92,7 +110,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">Domain</span>
|
<span class="overview-left-loading-span">{{$t('overall.domain')}}</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="overview-right">
|
<div class="overview-right">
|
||||||
@@ -174,6 +192,8 @@ 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',
|
||||||
@@ -181,7 +201,8 @@ export default {
|
|||||||
Loading,
|
Loading,
|
||||||
ExplorerSearch,
|
ExplorerSearch,
|
||||||
EntityFilter,
|
EntityFilter,
|
||||||
EntityList
|
EntityList,
|
||||||
|
DateTimeRange
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
@@ -200,13 +221,6 @@ 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',
|
||||||
@@ -284,12 +298,13 @@ export default {
|
|||||||
initFlag: true, // 初始化标志,避免初始化时pageSize和pageNo会调用搜索
|
initFlag: true, // 初始化标志,避免初始化时pageSize和pageNo会调用搜索
|
||||||
timer: null, // 初始化标志的延时器,需要销毁
|
timer: null, // 初始化标志的延时器,需要销毁
|
||||||
summaryCount: {
|
summaryCount: {
|
||||||
total: 0,
|
totalCount: 0,
|
||||||
domainCount: 0,
|
domainCount: 0,
|
||||||
ipCount: 0,
|
ipCount: 0,
|
||||||
appCount: 0
|
appCount: 0
|
||||||
},
|
},
|
||||||
loadingCount: false // 实体基数统计的loading
|
loadingCount: false, // 实体基数统计的loading
|
||||||
|
keywordList: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -302,6 +317,13 @@ 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) {
|
||||||
@@ -361,6 +383,7 @@ export default {
|
|||||||
this.q = ''
|
this.q = ''
|
||||||
this.metaList = []
|
this.metaList = []
|
||||||
}
|
}
|
||||||
|
this.getKeyword(param.keywordList)
|
||||||
|
|
||||||
// 参数q,避免切换页码时,地址栏参数q为空
|
// 参数q,避免切换页码时,地址栏参数q为空
|
||||||
let urlQ = ''
|
let urlQ = ''
|
||||||
@@ -368,6 +391,8 @@ 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添加到地址栏
|
||||||
@@ -389,7 +414,7 @@ export default {
|
|||||||
if (!this.showList) {
|
if (!this.showList) {
|
||||||
// 首页进入搜索时重载页面,视觉上进入列表页面
|
// 首页进入搜索时重载页面,视觉上进入列表页面
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
path: '/entityExplorer',
|
path: '/entity',
|
||||||
query: {
|
query: {
|
||||||
listMode: this.listMode,
|
listMode: this.listMode,
|
||||||
q: urlQ,
|
q: urlQ,
|
||||||
@@ -417,19 +442,21 @@ 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 })
|
this.search({ metaList: this.metaList, q: this.q, keywordList: keywordList })
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.search({ metaList: this.metaList, q: this.q })
|
this.search({ metaList: this.metaList, q: this.q, keywordList: keywordList })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
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
|
||||||
this.search({ metaList: this.metaList, q: this.q })
|
const keywordList = this.getKeywordListByMetaList(this.metaList)
|
||||||
|
this.search({ metaList: this.metaList, q: this.q, keywordList: keywordList })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 点击上一页箭头
|
// 点击上一页箭头
|
||||||
@@ -489,8 +516,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
|
||||||
@@ -548,16 +575,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)
|
||||||
@@ -570,19 +597,21 @@ 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 = { total: 0, domainCount: 0, ipCount: 0, appCount: 0 }
|
this.summaryCount = { totalCount: 0, domainCount: 0, ipCount: 0, appCount: 0 }
|
||||||
}
|
}
|
||||||
}).catch(e => {
|
}).catch(e => {
|
||||||
console.log(e)
|
console.error(e)
|
||||||
this.summaryCount = { total: 0, domainCount: 0, ipCount: 0, appCount: 0 }
|
this.summaryCount = { totalCount: 0, domainCount: 0, ipCount: 0, appCount: 0 }
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
this.loadingCount = false
|
this.loadingCount = false
|
||||||
})
|
})
|
||||||
@@ -675,11 +704,13 @@ 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 })
|
this.search({ ...parser.parseStr(keyInfo.key), str: str, keywordList: keywordList })
|
||||||
} else {
|
} else {
|
||||||
this.$message.error(handleErrorTip(errorList[0]))
|
this.$message.error(handleErrorTip(errorList[0]))
|
||||||
}
|
}
|
||||||
@@ -727,10 +758,55 @@ 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,即列表页,并非首页,则开始搜索
|
||||||
@@ -741,7 +817,13 @@ export default {
|
|||||||
q = decodeURI(q)
|
q = decodeURI(q)
|
||||||
}
|
}
|
||||||
// %位置不为0,即内容包含非英文时
|
// %位置不为0,即内容包含非英文时
|
||||||
const str1 = q.substring(q.indexOf('%'), q.indexOf('%') + 3)
|
let str1 = ''
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
@@ -751,6 +833,10 @@ export default {
|
|||||||
this.$store.commit('resetScoreBase')
|
this.$store.commit('resetScoreBase')
|
||||||
this.queryScoreBase()
|
this.queryScoreBase()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this.showList) {
|
||||||
|
this.getEntityIndexData()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
timeFilter () {
|
timeFilter () {
|
||||||
@@ -763,11 +849,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携带了,使用携带的值,否则使用默认值。
|
// 优先级:url > config.js > 默认值。
|
||||||
const dateRangeValue = rangeParam ? parseInt(query.range) : 60
|
const dateRangeValue = rangeParam ? parseInt(rangeParam) : (DEFAULT_TIME_FILTER_RANGE.entity.list || 60)
|
||||||
const timeFilter = ref({ dateRangeValue })
|
const timeFilter = ref({ dateRangeValue })
|
||||||
if (!startTimeParam || !endTimeParam) {
|
if (!startTimeParam || !endTimeParam) {
|
||||||
const { startTime, endTime } = getNowTime(60)
|
const { startTime, endTime } = getNowTime(dateRangeValue)
|
||||||
timeFilter.value.startTime = startTime
|
timeFilter.value.startTime = startTime
|
||||||
timeFilter.value.endTime = endTime
|
timeFilter.value.endTime = endTime
|
||||||
} else {
|
} else {
|
||||||
@@ -781,9 +867,11 @@ 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 () {
|
||||||
|
|||||||
@@ -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">{{ $_.get(node, 'myData.entityType') ? entityType[$_.get(node, 'myData.entityType')] : '-' }}</div>
|
<div class="entity-graph-type">{{entityTypeName}}</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,6 +144,27 @@ 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, '')
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
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}`"
|
||||||
@@ -65,7 +66,8 @@ 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,
|
||||||
|
|||||||
@@ -11,8 +11,20 @@
|
|||||||
<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">{{ entityData.entityValue || 'Unknown' }}</span>
|
<span class="cn-entity__header-title" v-high-light="keywordList">{{ entityData.entityValue || 'Unknown' }}</span>
|
||||||
<span class="entity-detail" style="display: flex;margin-left: 6px;margin-top: 1px;flex-wrap: wrap;margin-bottom: -10px;">
|
<span v-show="entityData.isRelated">
|
||||||
|
<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"
|
||||||
@@ -30,29 +42,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') }} : </span>
|
<span class="row-item-label">{{ $t('overall.country') }} : </span>
|
||||||
<span class="row-item-value">{{ $_.get(entityData, 'location.country', '-') || '-' }}</span>
|
<span class="row-item-value" v-high-light="keywordList">{{ $_.get(entityData, 'location.country', '-') || '-' }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="basic-info__item">
|
<div class="basic-info__item1">
|
||||||
<i class="cn-icon cn-icon-position"></i>
|
<i class="cn-icon cn-icon-position"></i>
|
||||||
<span class="row-item-label">{{ $t('overall.city') }} : </span>
|
<span class="row-item-label">{{ $t('overall.city') }} : </span>
|
||||||
<span class="row-item-value">{{ entityData.location ? ipLocationRegion(entityData.location) : '-' }}</span>
|
<span class="row-item-value high-location" v-high-light="keywordList">{{ 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') }} : </span>
|
<span class="row-item-label">{{ $t('entities.asn') }} : </span>
|
||||||
<span class="row-item-value">{{ $_.get(entityData, 'asn.asn', '-') || '-' }}</span>
|
<span class="row-item-value" v-high-light="keywordList">{{ $_.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') }} : </span>
|
<span class="row-item-label">{{ $t('entities.category') }} : </span>
|
||||||
<span class="row-item-value">{{ $_.get(entityData, 'category.categoryGroup', '-') || '-' }}</span>
|
<span class="row-item-value" v-high-light="keywordList">{{ $_.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') }} : </span>
|
<span class="row-item-label">{{ $t('entities.subcategory') }} : </span>
|
||||||
<span class="row-item-value">{{ $_.get(entityData, 'category.categoryName', '-') || '-' }}</span>
|
<span class="row-item-value" v-high-light="keywordList">{{ $_.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>
|
||||||
@@ -64,7 +76,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') }} : </span>
|
<span class="row-item-label">{{ $t('entities.category') }} : </span>
|
||||||
<span class="row-item-value">{{ $_.get(entityData, 'category.appCategory', '-') || '-' }}</span>
|
<span class="row-item-value" v-high-light="keywordList">{{ $_.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>
|
||||||
@@ -146,7 +158,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>{{score}}</span>
|
<span style="padding-left: 4px;">{{score}}</span>
|
||||||
<loading :loading="loadingNetworkQuality" size="small"></loading>
|
<loading :loading="loadingNetworkQuality" size="small"></loading>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -176,7 +188,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" @reloadEntity="getEntity" />
|
<detail-overview :entity="entityData" :time-filter="timeFilter" :keywordList="keywordList" @reloadEntity="getEntity" />
|
||||||
</div>
|
</div>
|
||||||
</el-collapse-transition>
|
</el-collapse-transition>
|
||||||
</div>
|
</div>
|
||||||
@@ -199,7 +211,8 @@ export default {
|
|||||||
props: {
|
props: {
|
||||||
index: Number,
|
index: Number,
|
||||||
timeFilter: Object,
|
timeFilter: Object,
|
||||||
listMode: String
|
listMode: String,
|
||||||
|
keywordList: Array
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
Loading,
|
Loading,
|
||||||
|
|||||||
@@ -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">{{$_.get(entity, 'category.appCategory', '-') || '-'}}</div>
|
<div class="row__content" v-high-light="keywordList">{{ $_.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">{{$_.get(entity, 'category.appSubcategory', '-') || '-'}}</div>
|
<div class="row__content" v-high-light="keywordList">{{ $_.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,7 +20,9 @@
|
|||||||
</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">{{$_.get(entity, 'category.appDescription', '-') || '-'}}</div>
|
<div class="row__content">
|
||||||
|
<span v-high-light="keywordList">{{ $_.get(entity, 'category.appDescription', '-') || '-' }}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -89,7 +91,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" v-show="item.show" v-for="(item, index) in relationshipDataOne" :key="index">
|
<div class="data-item high-light-block" v-high-light="keywordList" 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>
|
||||||
@@ -98,7 +100,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">{{item.value}}</span>
|
<span v-if="!item.show" class="high-light-block" v-high-light="keywordList">{{item.value}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -113,7 +115,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" v-show="item.show" v-for="(item, index) in relationshipDataTwo" :key="index">
|
<div class="data-item high-light-block" v-high-light="keywordList" 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>
|
||||||
@@ -122,7 +124,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">{{item.value}}</span>
|
<span v-if="!item.show" class="high-light-block" v-high-light="keywordList">{{item.value}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -170,7 +172,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">{{dateFormatByAppearance(security.startTime) || '-'}}</div>
|
<div class="row__label row__label--width130">{{security.startTime ? dateFormatByAppearance(Number(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>
|
||||||
@@ -214,7 +216,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 } from '@/utils/date-util'
|
import { dateFormatByAppearance, getMillisecond, getSecond, getNowTime } from '@/utils/date-util'
|
||||||
import Loading from '@/components/common/Loading'
|
import Loading from '@/components/common/Loading'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
|
||||||
@@ -225,6 +227,9 @@ export default {
|
|||||||
Chart,
|
Chart,
|
||||||
Loading
|
Loading
|
||||||
},
|
},
|
||||||
|
props: {
|
||||||
|
keywordList: Array
|
||||||
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
// entityData: {}
|
// entityData: {}
|
||||||
@@ -315,10 +320,22 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
getMillisecond,
|
getMillisecond,
|
||||||
dateFormatByAppearance,
|
dateFormatByAppearance,
|
||||||
getQueryParams () {
|
getQueryParams (dateRangeValue) {
|
||||||
|
if (dateRangeValue) {
|
||||||
|
// range取 config.js 中配置的值
|
||||||
|
const { startTime, endTime } = getNowTime(dateRangeValue)
|
||||||
return {
|
return {
|
||||||
|
startTime: getSecond(startTime),
|
||||||
|
endTime: getSecond(endTime),
|
||||||
resource: this.entity.entityValue
|
resource: this.entity.entityValue
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
startTime: getSecond(this.timeFilter.startTime),
|
||||||
|
endTime: getSecond(this.timeFilter.endTime),
|
||||||
|
resource: this.entity.entityValue
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
getPerformanceQueryParams () {
|
getPerformanceQueryParams () {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -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" @reloadEntity="getEntity"></ip-overview>
|
<ip-overview :entity="entity" :time-filter="timeFilter" :keywordList="keywordList" @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" @reloadEntity="getEntity"></domain-overview>
|
<domain-overview :entity="entity" :time-filter="timeFilter" :keywordList="keywordList" @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" @reloadEntity="getEntity"></app-overview>
|
<app-overview :entity="entity" :time-filter="timeFilter" :keywordList="keywordList" @reloadEntity="getEntity"></app-overview>
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -22,7 +22,8 @@ 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,
|
||||||
|
|||||||
@@ -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">{{$_.get(entityData, 'category.categoryName', '-') || '-'}}</div>
|
<div class="row__content" v-high-light="keywordList">{{ $_.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">{{$_.get(entityData, 'category.categoryGroup', '-') || '-'}}</div>
|
<div class="row__content" v-high-light="keywordList">{{ $_.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">{{$_.get(entityData, 'whois.registrantOrg', '-') || '-'}}</div>
|
<div class="row__content" v-high-light="keywordList">{{ $_.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" v-show="item.show" v-for="(item, index) in relationshipDataOne" :key="index">
|
<div class="data-item high-light-block" v-high-light="keywordList" 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">{{item.value}}</span>
|
<span v-if="!item.show" class="high-light-block" v-high-light="keywordList">{{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" v-show="item.show" v-for="(item, index) in relationshipDataTwo" :key="index">
|
<div class="data-item high-light-block" v-high-light="keywordList" 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">{{item.value}}</span>
|
<span v-if="!item.show" class="high-light-block" v-high-light="keywordList">{{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">{{dateFormatByAppearance(performance.startTime) || '-'}}</div>
|
<div class="row__label row__label--width130">{{performance.startTime ? dateFormatByAppearance(Number(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">{{dateFormatByAppearance(getMillisecond(security.startTime)) || '-'}}</div>
|
<div class="row__label row__label--width130">{{security.startTime ? dateFormatByAppearance(Number(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 } from '@/utils/date-util'
|
import { dateFormatByAppearance, getMillisecond, getSecond, getNowTime } 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,6 +229,9 @@ export default {
|
|||||||
Loading,
|
Loading,
|
||||||
Chart
|
Chart
|
||||||
},
|
},
|
||||||
|
props: {
|
||||||
|
keywordList: Array
|
||||||
|
},
|
||||||
mixins: [entityDetailMixin, relatedServer],
|
mixins: [entityDetailMixin, relatedServer],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
@@ -321,16 +324,21 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
getMillisecond,
|
getMillisecond,
|
||||||
dateFormatByAppearance,
|
dateFormatByAppearance,
|
||||||
getQueryParams () {
|
getQueryParams (dateRangeValue) {
|
||||||
|
if (dateRangeValue) {
|
||||||
|
// range取 config.js 中配置的值
|
||||||
|
const { startTime, endTime } = getNowTime(dateRangeValue)
|
||||||
return {
|
return {
|
||||||
|
startTime: getSecond(startTime),
|
||||||
|
endTime: getSecond(endTime),
|
||||||
resource: this.entity.entityValue
|
resource: this.entity.entityValue
|
||||||
}
|
}
|
||||||
},
|
} else {
|
||||||
getQueryParamsWithTime () {
|
|
||||||
return {
|
return {
|
||||||
startTime: getSecond(this.timeFilter.startTime),
|
startTime: getSecond(this.timeFilter.startTime),
|
||||||
endTime: getSecond(this.timeFilter.endTime),
|
endTime: getSecond(this.timeFilter.endTime),
|
||||||
domain: this.entity.entityValue
|
resource: this.entity.entityValue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getPerformanceQueryParams () {
|
getPerformanceQueryParams () {
|
||||||
@@ -352,7 +360,7 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
getBasicProperties () {
|
getBasicProperties () {
|
||||||
axios.get(this.basicProperties, { params: this.getQueryParamsWithTime() }).then(response => {
|
axios.get(this.basicProperties, { params: this.getQueryParams() }).then(response => {
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
this.entityData = {
|
this.entityData = {
|
||||||
...this.entityData,
|
...this.entityData,
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user