Compare commits
91 Commits
23.10.demo
...
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
|
||||||
|
}
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 12 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 18 KiB |
@@ -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 {
|
}
|
||||||
border: none;
|
.detections {
|
||||||
|
.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;
|
||||||
@@ -130,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 {
|
||||||
@@ -143,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;
|
||||||
|
|||||||
@@ -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.
@@ -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,8 +42,8 @@
|
|||||||
</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" >
|
||||||
@@ -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 = ''
|
||||||
|
|||||||
@@ -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') }}
|
||||||
@@ -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"
|
||||||
@@ -17,15 +18,15 @@
|
|||||||
</el-switch>
|
</el-switch>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-icon">
|
<div class="card-icon">
|
||||||
<img :src="data.iconUrl" style="max-height: 50px;"/>
|
<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>
|
||||||
@@ -77,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"
|
||||||
@@ -85,11 +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'"
|
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">
|
||||||
@@ -111,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>
|
||||||
@@ -123,7 +124,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="update-operate">
|
<div class="update-operate">
|
||||||
<button :title="$t('overall.update')" class="top-tool-btn--update"
|
<button :title="$t('overall.update')" class="top-tool-btn--update"
|
||||||
@click="uploadRecord">
|
@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>
|
||||||
@@ -150,7 +151,7 @@
|
|||||||
<span>{{scope.row.opTime ? dateFormatByAppearance(scope.row.opTime) : '-'}}</span>
|
<span>{{scope.row.opTime ? dateFormatByAppearance(scope.row.opTime) : '-'}}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="user" :label="$t('knowledgeBase.operator')" width="150" v-if="activeTab === 'updateRecord'">
|
<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>
|
||||||
@@ -256,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>
|
||||||
@@ -283,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>
|
||||||
@@ -295,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'
|
||||||
@@ -339,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,
|
||||||
@@ -348,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',
|
||||||
@@ -380,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,
|
||||||
@@ -397,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: {
|
||||||
@@ -427,7 +423,6 @@ export default {
|
|||||||
},
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
type: 'time',
|
type: 'time',
|
||||||
boundaryGap: ['1%', '3%'],
|
|
||||||
axisLine: {
|
axisLine: {
|
||||||
show: false
|
show: false
|
||||||
},
|
},
|
||||||
@@ -471,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 => {
|
||||||
@@ -486,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)
|
||||||
}
|
}
|
||||||
@@ -534,14 +532,14 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
timeChange () {
|
timeChange () {
|
||||||
this.timeFilter.endTime = window.$dayJs.tz().valueOf()
|
|
||||||
this.timeFilter.startTime = this.timeFilter.endTime - this.selectTime * 60 * 1000
|
|
||||||
if (this.updateKnowledge.source === 'cn_psiphon3_ip') {
|
if (this.updateKnowledge.source === 'cn_psiphon3_ip') {
|
||||||
this.init()
|
this.init()
|
||||||
}
|
}
|
||||||
|
if (this.activeTab === knowledgeCardUpdateRecordType.intelligenceLearning) {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.handleActiveBar()
|
this.handleActiveBar()
|
||||||
})
|
})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
activeChange (item) { // isClick:代表是通过点击操作来的
|
activeChange (item) { // isClick:代表是通过点击操作来的
|
||||||
if (item) {
|
if (item) {
|
||||||
@@ -555,9 +553,11 @@ export default {
|
|||||||
mouseenterTab (item) {
|
mouseenterTab (item) {
|
||||||
if (this.isNoDataForPsiphon3) return
|
if (this.isNoDataForPsiphon3) return
|
||||||
this.mousemoveCursor = item.class
|
this.mousemoveCursor = item.class
|
||||||
|
if (this.activeTab === knowledgeCardUpdateRecordType.intelligenceLearning) {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.handleActiveBar()
|
this.handleActiveBar()
|
||||||
})
|
})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
mouseleaveTab () {
|
mouseleaveTab () {
|
||||||
this.mousemoveCursor = ''
|
this.mousemoveCursor = ''
|
||||||
@@ -587,17 +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()
|
||||||
if (this.updateKnowledge.source === 'cn_psiphon3_ip') {
|
|
||||||
this.init()
|
|
||||||
}
|
|
||||||
/* } else {
|
|
||||||
this.$message.error(this.$t('tip.uploadFailed', { msg: response.message }))
|
|
||||||
} */
|
|
||||||
},
|
},
|
||||||
beforeUpload (file) {
|
beforeUpload (file) {
|
||||||
this.uploadLoading = true
|
this.uploadLoading = true
|
||||||
@@ -609,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)
|
||||||
@@ -659,9 +654,11 @@ export default {
|
|||||||
await this.init()
|
await this.init()
|
||||||
}
|
}
|
||||||
this.showUpdate()
|
this.showUpdate()
|
||||||
|
if (this.activeTab === knowledgeCardUpdateRecordType.intelligenceLearning) {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.handleActiveBar()
|
this.handleActiveBar()
|
||||||
})
|
})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
uploadRecord () {
|
uploadRecord () {
|
||||||
this.showAddUpdateDialog = true
|
this.showAddUpdateDialog = true
|
||||||
@@ -674,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
|
||||||
@@ -693,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(() => {
|
||||||
@@ -703,7 +709,7 @@ export default {
|
|||||||
handleClick (tab) {
|
handleClick (tab) {
|
||||||
this.getCurTabData()
|
this.getCurTabData()
|
||||||
if (tab.index === '1') {
|
if (tab.index === '1') {
|
||||||
this.init()
|
this.timeChange()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
clearSelect () {
|
clearSelect () {
|
||||||
@@ -743,15 +749,13 @@ 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
|
||||||
const url = toStatus === 0 ? api.knowledgeBaseLearningStop : api.knowledgeBaseLearningStart
|
const url = toStatus === 0 ? api.knowledgeBaseLearningStop : api.knowledgeBaseLearningStart
|
||||||
if (hint.knowledgeId === 101 || hint.knowledgeId === 102) {
|
|
||||||
hint.status = toStatus
|
|
||||||
this.$message.success(this.$t('tip.success'))
|
|
||||||
this.showConfirmSwitch = false
|
|
||||||
} else {
|
|
||||||
axios.post(`${url}?knowledgeId=${hint.knowledgeId}`).then(res => {
|
axios.post(`${url}?knowledgeId=${hint.knowledgeId}`).then(res => {
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
hint.status = toStatus
|
hint.status = toStatus
|
||||||
@@ -767,24 +771,22 @@ export default {
|
|||||||
this.showConfirmSwitch = false
|
this.showConfirmSwitch = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
tabType (n) {
|
tabType (n) {
|
||||||
this.$nextTick(() => {
|
this.timeChange()
|
||||||
this.handleActiveBar()
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
timeFilter: {
|
/*
|
||||||
handler () {
|
hasUpdatingRecord (n) {
|
||||||
if (this.updateKnowledge.source === 'cn_psiphon3_ip') {
|
if (n) { // update record页存在“正在更新”的记录时,每20秒自动请求一次接口
|
||||||
this.init()
|
this.timer = setTimeout(() => {
|
||||||
}
|
this.getCurTabData()
|
||||||
this.$nextTick(() => {
|
}, 20000)
|
||||||
this.handleActiveBar()
|
} else { // 直到出现新的记录,出现新记录后(失败或者成功),取消定时请求接口,右上角"update"按钮恢复可用。"正在更新"和"失败”都会有对应的强调样式。
|
||||||
})
|
clearTimeout(this.timer)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
*/
|
||||||
tableData: {
|
tableData: {
|
||||||
handler (n) {
|
handler (n) {
|
||||||
if (this.tableData && this.tableData.length > 0) {
|
if (this.tableData && this.tableData.length > 0) {
|
||||||
@@ -805,40 +807,6 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// 2024-01-15 以下两个是为105环境演示准备的假数据
|
|
||||||
const data1 = {
|
|
||||||
knowledgeId: 101,
|
|
||||||
name: 'CyberGhost',
|
|
||||||
category: 'ai_tagging',
|
|
||||||
description: 'CyberGhost is a VPN service used to unblock sites and browse privately and anonymously.',
|
|
||||||
isBuiltIn: 1,
|
|
||||||
isPublished: 1,
|
|
||||||
status: 1,
|
|
||||||
showUpdate: false
|
|
||||||
}
|
|
||||||
const basicInfo1 = builtInKnowledgeBaseBasicInfo.find(bi => bi.knowledgeId === data1.knowledgeId)
|
|
||||||
this.aiTaggingList.push({
|
|
||||||
...data1,
|
|
||||||
...basicInfo1
|
|
||||||
})
|
|
||||||
const data2 = {
|
|
||||||
knowledgeId: 102,
|
|
||||||
name: 'HotSpotshield VPN',
|
|
||||||
category: 'ai_tagging',
|
|
||||||
description: 'Hotspot Shield is a public VPN service, providing\n' +
|
|
||||||
'a secure proxy connection through an encrypted\n' +
|
|
||||||
'channel between your device and the target\n' +
|
|
||||||
'website, using VPN technology.',
|
|
||||||
isBuiltIn: 1,
|
|
||||||
isPublished: 1,
|
|
||||||
status: 1,
|
|
||||||
showUpdate: false
|
|
||||||
}
|
|
||||||
const basicInfo2 = builtInKnowledgeBaseBasicInfo.find(bi => bi.knowledgeId === data2.knowledgeId)
|
|
||||||
this.aiTaggingList.push({
|
|
||||||
...data2,
|
|
||||||
...basicInfo2
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -854,9 +822,7 @@ export default {
|
|||||||
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 {
|
||||||
if (this.myChart) {
|
if (this.myChart) {
|
||||||
this.myChart.dispose()
|
this.myChart.dispose()
|
||||||
@@ -883,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) {
|
||||||
@@ -912,9 +878,9 @@ export default {
|
|||||||
const find = this.aiTaggingList.find(item => item.knowledgeId === this.switchKnowledgeId)
|
const find = this.aiTaggingList.find(item => item.knowledgeId === this.switchKnowledgeId)
|
||||||
if (find) {
|
if (find) {
|
||||||
if (find.status === 0) {
|
if (find.status === 0) {
|
||||||
tip = this.$t('tip.confirmEnable') + '?'
|
tip = this.$t('tip.confirmEnablePsiphon3') + '?'
|
||||||
} else if (find.status === 1) {
|
} else if (find.status === 1) {
|
||||||
tip = this.$t('tip.confirmDisable') + '?'
|
tip = this.$t('tip.confirmDisablePsiphon3') + '?'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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]
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ export const storageKey = {
|
|||||||
leftMenuShrink: 'cn-left-menu-shrink',
|
leftMenuShrink: 'cn-left-menu-shrink',
|
||||||
unsavedChange: 'cn-unsaved-change',
|
unsavedChange: 'cn-unsaved-change',
|
||||||
entitySearchHistory: 'cn-entity-search-history',
|
entitySearchHistory: 'cn-entity-search-history',
|
||||||
|
detectionSearchHistory: 'cn-detection-search-history',
|
||||||
echartLegendFontSize: 'echartLegendFontSize',
|
echartLegendFontSize: 'echartLegendFontSize',
|
||||||
echartLabelFontSize: 'echartLabelFontSize',
|
echartLabelFontSize: 'echartLabelFontSize',
|
||||||
tokenExpireCurrentPath: 'token-expire-current-path',
|
tokenExpireCurrentPath: 'token-expire-current-path',
|
||||||
@@ -74,6 +75,7 @@ export const panelTypeAndRouteMapping = {
|
|||||||
ipEntityDetail: 21,
|
ipEntityDetail: 21,
|
||||||
domainEntityDetail: 22,
|
domainEntityDetail: 22,
|
||||||
appEntityDetail: 23,
|
appEntityDetail: 23,
|
||||||
|
subscribeEntityDetail: 24,
|
||||||
cryptocurrency: 7,
|
cryptocurrency: 7,
|
||||||
ipDrillDownTest: 8,
|
ipDrillDownTest: 8,
|
||||||
linkMonitor: 14,
|
linkMonitor: 14,
|
||||||
@@ -98,6 +100,11 @@ export const entityType = {
|
|||||||
ip: 'IP'
|
ip: 'IP'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const knowledgeCardUpdateRecordType = {
|
||||||
|
updateRecord: 'updateRecord',
|
||||||
|
intelligenceLearning: 'intelligenceLearning'
|
||||||
|
}
|
||||||
|
|
||||||
export const entityDetailTabsName = {
|
export const entityDetailTabsName = {
|
||||||
informationAggregation: 'informationAggregation',
|
informationAggregation: 'informationAggregation',
|
||||||
relatedEntity: 'relatedEntity',
|
relatedEntity: 'relatedEntity',
|
||||||
@@ -213,7 +220,7 @@ export const detectionPageType = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const listScrollPath = [
|
export const listScrollPath = [
|
||||||
'/entityExplorer',
|
'/entity',
|
||||||
'/detection/performanceEvent',
|
'/detection/performanceEvent',
|
||||||
'/detection/securityEvent'
|
'/detection/securityEvent'
|
||||||
]
|
]
|
||||||
@@ -1792,6 +1799,8 @@ export const langData = [
|
|||||||
{ value: 'zh', label: 'zh' },
|
{ value: 'zh', label: 'zh' },
|
||||||
{ value: 'en', label: 'en' }
|
{ value: 'en', label: 'en' }
|
||||||
]
|
]
|
||||||
|
export const ZH = 'zh'
|
||||||
|
export const EN = 'en'
|
||||||
|
|
||||||
export const performanceMetricMapping = {
|
export const performanceMetricMapping = {
|
||||||
'dns error': 'DNS Error Rate',
|
'dns error': 'DNS Error Rate',
|
||||||
@@ -1804,77 +1813,61 @@ export const builtInKnowledgeBaseBasicInfo = [
|
|||||||
knowledgeId: 10,
|
knowledgeId: 10,
|
||||||
label: 'Psiphon3 VPN',
|
label: 'Psiphon3 VPN',
|
||||||
iconUrl: 'images/knowledge-base-logo/psiphon3-vpn.png',
|
iconUrl: 'images/knowledge-base-logo/psiphon3-vpn.png',
|
||||||
desc: 'Psiphon3 is a circumvention software for Windows and other platforms that provides uncensored access to Internet content.'
|
desc: 'knowledgeBase.desc.psiphon3'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
knowledgeId: 5,
|
knowledgeId: 5,
|
||||||
label: 'Domain Category',
|
label: 'network.domainCategory',
|
||||||
iconUrl: 'images/knowledge-base-logo/fqdn.png',
|
iconUrl: 'images/knowledge-base-logo/fqdn.png',
|
||||||
desc: 'Domain category provides basic information including categories, providers, reputation score.'
|
desc: 'knowledgeBase.desc.domainCategory'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
knowledgeId: 6,
|
knowledgeId: 6,
|
||||||
label: 'Domain Whois',
|
label: 'knowledgeBase.domainWhois',
|
||||||
iconUrl: 'images/knowledge-base-logo/fqdn-whois.png',
|
iconUrl: 'images/knowledge-base-logo/fqdn-whois.png',
|
||||||
desc: 'Domain whois contains registration and ownership information for domain names. It includes details like domain registrar, registrant, creation/expiry dates, and contact information.'
|
desc: 'knowledgeBase.desc.domainWhois'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
knowledgeId: 2,
|
knowledgeId: 2,
|
||||||
label: 'IP ASN',
|
label: 'IP ASN',
|
||||||
iconUrl: 'images/knowledge-base-logo/ip-asn.png',
|
iconUrl: 'images/knowledge-base-logo/ip-asn.png',
|
||||||
desc: 'ASN Database associates IP addresses with their corresponding Autonomous System Numbers, which are unique identifiers assigned to internet networks. This database helps identify the network and its owner, facilitating network analysis and monitoring tasks.'
|
desc: 'knowledgeBase.desc.ipAsn'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
knowledgeId: 3,
|
knowledgeId: 3,
|
||||||
label: 'DNS Server Info',
|
label: 'knowledgeBase.dnsServerInfo',
|
||||||
iconUrl: 'images/knowledge-base-logo/dns-server-info.png',
|
iconUrl: 'images/knowledge-base-logo/dns-server-info.png',
|
||||||
desc: 'A DNS Server Info stores information about Domain Name System (DNS) servers. It includes details such as IP addresses, host names, locations, software name, operation system, and roles of the servers.'
|
desc: 'knowledgeBase.desc.dnsServer'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
knowledgeId: 9,
|
knowledgeId: 9,
|
||||||
label: 'APP Category',
|
label: 'knowledgeBase.appCategory',
|
||||||
iconUrl: 'images/knowledge-base-logo/app-category.png',
|
iconUrl: 'images/knowledge-base-logo/app-category.png',
|
||||||
desc: 'APP category provides basic information for over 3000 popular applications, including their categories and service providers.'
|
desc: 'knowledgeBase.desc.appCategory'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
knowledgeId: 7,
|
knowledgeId: 7,
|
||||||
label: 'Indicators of Compromise',
|
label: 'knowledgeBase.ioc',
|
||||||
iconUrl: 'images/knowledge-base-logo/indicators-of-compromise.png',
|
iconUrl: 'images/knowledge-base-logo/indicators-of-compromise.png',
|
||||||
desc: 'Indicator of Compromise (IoC) refers to forensic artifacts, such as unusual network traffic or malicious files, indicating a security breach or cyberattack.'
|
desc: 'knowledgeBase.desc.ioc'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
knowledgeId: 4,
|
knowledgeId: 4,
|
||||||
label: 'ICP',
|
label: 'ICP',
|
||||||
iconUrl: 'images/knowledge-base-logo/icp.png',
|
iconUrl: 'images/knowledge-base-logo/icp.png',
|
||||||
desc: 'ICP (Internet Content Provider) license is a permit issued by Chinese authorities, mandatory for websites to legally operate and publish content within mainland China.'
|
desc: 'knowledgeBase.desc.icp'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
knowledgeId: 1,
|
knowledgeId: 1,
|
||||||
label: 'IP Location',
|
label: 'knowledgeBase.ipLocation',
|
||||||
iconUrl: 'images/knowledge-base-logo/ip-location.png',
|
iconUrl: 'images/knowledge-base-logo/ip-location.png',
|
||||||
desc: 'IP location Database is a repository containing geographical data associated with IP addresses, such as country, city, ISP, organization, latitude, longitude, and other relevant details.'
|
desc: 'knowledgeBase.desc.ipLocation'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
knowledgeId: 8,
|
knowledgeId: 8,
|
||||||
label: 'Anonymity',
|
label: 'eventType.anonymity',
|
||||||
iconUrl: 'images/knowledge-base-logo/anonymity.png',
|
iconUrl: 'images/knowledge-base-logo/anonymity.png',
|
||||||
desc: 'Communication system that conceals users\' identities and activities to protect privacy and prevent tracking or surveillance. This database provides lists of Tor nodes, I2P nodes, obfs4, etc.'
|
desc: 'knowledgeBase.desc.anonymity'
|
||||||
},
|
|
||||||
// 2024-01-15 以下两个是为105环境演示准备的假数据
|
|
||||||
{
|
|
||||||
knowledgeId: 101,
|
|
||||||
label: 'CyberGhost',
|
|
||||||
iconUrl: 'images/knowledge-base-logo/cyber-ghost.png',
|
|
||||||
desc: 'CyberGhost is a VPN service used to unblock sites and browse privately and anonymously.'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
knowledgeId: 102,
|
|
||||||
label: 'HotSpotshield VPN',
|
|
||||||
iconUrl: 'images/knowledge-base-logo/hospot-vpn.png',
|
|
||||||
desc: 'Hotspot Shield is a public VPN service, providing\n' +
|
|
||||||
'a secure proxy connection through an encrypted\n' +
|
|
||||||
'channel between your device and the target\n' +
|
|
||||||
'website, using VPN technology.'
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -13,17 +13,11 @@ export function getMillisecond (time) {
|
|||||||
ms = window.$dayJs.tz(new Date(time)).valueOf()
|
ms = window.$dayJs.tz(new Date(time)).valueOf()
|
||||||
} else if (_.isNumber(time)) {
|
} else if (_.isNumber(time)) {
|
||||||
const timeStr = _.toString(time)
|
const timeStr = _.toString(time)
|
||||||
/* const difference = timeStr.length - 13
|
const difference = timeStr.length - 13
|
||||||
if (difference >= 0) {
|
if (difference >= 0) {
|
||||||
ms = window.$dayJs.tz(new Date(Number(timeStr.slice(0, 13)))).valueOf()
|
ms = window.$dayJs.tz(new Date(Number(timeStr.slice(0, 13)))).valueOf()
|
||||||
} else {
|
} else {
|
||||||
ms = window.$dayJs.tz(new Date(Math.floor(time * (10 ** (0 - difference))))).valueOf()
|
ms = window.$dayJs.tz(new Date(Math.floor(time * (10 ** (0 - difference))))).valueOf()
|
||||||
} */
|
|
||||||
// 判断9位和10位数为秒,12位和13位为毫秒。其他位数不做处理
|
|
||||||
if (timeStr.length === 9 || timeStr.length === 10) {
|
|
||||||
ms = window.$dayJs.tz(new Date(Number(time * 1000))).valueOf()
|
|
||||||
} else {
|
|
||||||
ms = window.$dayJs.tz(new Date(Number(time))).valueOf()
|
|
||||||
}
|
}
|
||||||
} else if (_.isString(time)) {
|
} else if (_.isString(time)) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -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>'
|
||||||
|
|||||||
@@ -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,21 +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 => {
|
|
||||||
if (response[0].status === 200) {
|
Promise.allSettled([informationAggregation, openPort, security, performance]).then(response => {
|
||||||
|
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,
|
||||||
@@ -151,44 +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)
|
||||||
if (this.entity.entityName === 'hqzc.wssp.hainan.gov.cn' || this.entity.entityName === '218.77.183.150') {
|
|
||||||
this.initSetTag(entityDetailTabsName.securityEvent, 3)
|
|
||||||
this.initSetTag(entityDetailTabsName.performanceEvent, 1)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
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 => {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
<div class="cn-detection__case entity-detail-performance">
|
<div class="cn-detection__case entity-detail-performance">
|
||||||
<div class="cn-detection__icon" :style="`background-color: ${eventSeverityColor[item.eventSecurity]}`"></div>
|
<div class="cn-detection__icon" :style="`background-color: ${eventSeverityColor[item.eventSecurity]}`"></div>
|
||||||
<div class="cn-detection__row">
|
<div class="cn-detection__row">
|
||||||
<div class="cn-detection__header" style="padding-bottom: 0">
|
<div class="cn-detection__header">
|
||||||
<span
|
<span
|
||||||
:test-id="`severity-color-block${index}`"
|
:test-id="`severity-color-block${index}`"
|
||||||
class="detection-event-severity-color-block"
|
class="detection-event-severity-color-block"
|
||||||
@@ -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>
|
||||||
@@ -38,11 +38,6 @@
|
|||||||
<span>{{ $t('overall.duration') }} : </span>
|
<span>{{ $t('overall.duration') }} : </span>
|
||||||
<span :test-id="`duration-time${index}`">{{ unitConvert(item.durationMs, 'time', null, null, 0).join(' ') || '-' }}</span>
|
<span :test-id="`duration-time${index}`">{{ unitConvert(item.durationMs, 'time', null, null, 0).join(' ') || '-' }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="basic-info__item">
|
|
||||||
<i class="cn-icon cn-icon-traffic-overview"></i>
|
|
||||||
<span>{{ $t('entity.detail.anomaly') }} : </span>
|
|
||||||
<div id="anomalyChart" style="height: 20px; width: 100px;"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -55,20 +50,17 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { dateFormatByAppearance } from '@/utils/date-util'
|
import { dateFormatByAppearance, getNowTime } from '@/utils/date-util'
|
||||||
import { eventSeverityColor, entityDetailTabsName, unitTypes } 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'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import chartMixin from '@/views/charts2/chart-mixin'
|
import chartMixin from '@/views/charts2/chart-mixin'
|
||||||
import ChartError from '@/components/common/Error'
|
import ChartError from '@/components/common/Error'
|
||||||
import { reverseSortBy, sortBy, toUpperCaseByString } from '@/utils/tools'
|
import { toUpperCaseByString } from '@/utils/tools'
|
||||||
import ChartNoData from '@/views/charts/charts/ChartNoData'
|
import ChartNoData from '@/views/charts/charts/ChartNoData'
|
||||||
import { markRaw } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { metricOption } from '@/views/detections/options/detectionOptions'
|
|
||||||
import * as echarts from 'echarts'
|
|
||||||
import _ from 'lodash'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PerformanceEvent',
|
name: 'PerformanceEvent',
|
||||||
@@ -86,16 +78,23 @@ 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,
|
||||||
chartOption: metricOption
|
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(() => {
|
||||||
@@ -108,57 +107,9 @@ export default {
|
|||||||
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 => {
|
||||||
if (this.entityName === 'hqzc.wssp.hainan.gov.cn' || this.entityName === '218.77.183.150') {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.toggleLoading(false)
|
|
||||||
this.isNoData = false
|
|
||||||
this.eventList = [
|
|
||||||
{
|
|
||||||
"serverIp": "1.1.1.1",
|
|
||||||
"domain": "www.baidu.com",
|
|
||||||
"appName": "ab",
|
|
||||||
"eventSeverity": "critical",
|
|
||||||
"eventType": "Http error",
|
|
||||||
"durationMs": 840000,
|
|
||||||
"startTime": new Date().getTime() - 1957 * 1000,
|
|
||||||
"endTime": 2222222222
|
|
||||||
}
|
|
||||||
]
|
|
||||||
this.metricList = [
|
|
||||||
[new Date().getTime() / 1000 - 2677, 2],
|
|
||||||
[new Date().getTime() / 1000 - 2557, 3],
|
|
||||||
[new Date().getTime() / 1000 - 2437, 2],
|
|
||||||
[new Date().getTime() / 1000 - 2317, 7],
|
|
||||||
[new Date().getTime() / 1000 - 2197, 8],
|
|
||||||
[new Date().getTime() / 1000 - 2077, 38],
|
|
||||||
[new Date().getTime() / 1000 - 1857, 12],
|
|
||||||
[new Date().getTime() / 1000 - 1637, 8],
|
|
||||||
[new Date().getTime() / 1000 - 1517, 7],
|
|
||||||
[new Date().getTime() / 1000 - 1277, 3],
|
|
||||||
[new Date().getTime() / 1000 - 1157, 1],
|
|
||||||
[new Date().getTime() / 1000 - 1037, 2]
|
|
||||||
]
|
|
||||||
this.$emit('checkTag', entityDetailTabsName.performanceEvent, 1)
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.initChart()
|
|
||||||
})
|
|
||||||
}, 200)
|
|
||||||
} else {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.isNoData = true
|
|
||||||
this.toggleLoading(false)
|
|
||||||
this.eventList = []
|
|
||||||
this.$emit('checkTag', entityDetailTabsName.performanceEvent, 0)
|
|
||||||
}, 200)
|
|
||||||
/*axios.get(`${api.entity.performance}/${this.entityType}`, {params: params}).then(response => {
|
|
||||||
const res = response.data
|
const res = response.data
|
||||||
|
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
@@ -176,8 +127,7 @@ export default {
|
|||||||
this.httpError(e)
|
this.httpError(e)
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
this.toggleLoading(false)
|
this.toggleLoading(false)
|
||||||
})*/
|
})
|
||||||
}
|
|
||||||
},
|
},
|
||||||
httpError (e) {
|
httpError (e) {
|
||||||
this.isNoData = false
|
this.isNoData = false
|
||||||
@@ -185,18 +135,17 @@ export default {
|
|||||||
this.errorMsg = this.errorMsgHandler(e)
|
this.errorMsg = this.errorMsgHandler(e)
|
||||||
this.$emit('checkTag', entityDetailTabsName.performanceEvent, 0)
|
this.$emit('checkTag', entityDetailTabsName.performanceEvent, 0)
|
||||||
},
|
},
|
||||||
initChart () {
|
changeSecurity (value) {
|
||||||
this.metricChart = markRaw(echarts.init(document.getElementById('anomalyChart')))
|
if (value) {
|
||||||
this.chartOptionMetric = _.cloneDeep(this.chartOption)
|
const obj = securityLevel.find(d => d.value === value)
|
||||||
this.chartOptionMetric.series[0].data = this.metricList.slice(0, 4).map(v => [Number(v[0]) * 1000, Number(v[1]), unitTypes.number])
|
let label = value
|
||||||
this.chartOptionMetric.series[1].data = this.metricList.slice(3, 9).map(v => [Number(v[0]) * 1000, Number(v[1]), unitTypes.number])
|
if (obj) {
|
||||||
this.chartOptionMetric.series[2].data = this.metricList.slice(8, 11).map(v => [Number(v[0]) * 1000, Number(v[1]), unitTypes.number])
|
label = this.$t(obj.label)
|
||||||
|
}
|
||||||
this.chartOptionMetric.series.forEach(item => {
|
return label
|
||||||
item.name = 'Http error'
|
} else {
|
||||||
})
|
return '-'
|
||||||
|
}
|
||||||
this.chartOptionMetric && this.metricChart.setOption(this.chartOptionMetric)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
<span class="circle"></span>
|
<span class="circle"></span>
|
||||||
<i class="cn-icon cn-icon-attacked"></i>
|
<i class="cn-icon cn-icon-attacked"></i>
|
||||||
<span :test-id="`victim-ip${index}`">{{ item.victimIp || '-' }}</span>
|
<span :test-id="`victim-ip${index}`">{{ item.victimIp || '-' }}</span>
|
||||||
<div class="domain">{{ item.domain }}</div>
|
<div class="domain">{{ item.victimDomain }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="cn-detection__body">
|
<div class="cn-detection__body">
|
||||||
<div class="body__basic-info">
|
<div class="body__basic-info">
|
||||||
@@ -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>
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
<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>
|
||||||
<span>{{ $t('detection.list.startTime') }} : </span>
|
<span>{{ $t('detection.list.startTime') }} : </span>
|
||||||
<span>{{ dateFormatByAppearance(parseFloat(item.startTime)) || '-' }}</span>
|
<span>{{ dateFormatByAppearance(item.startTime) || '-' }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="basic-info__item">
|
<div class="basic-info__item">
|
||||||
<i class="cn-icon cn-icon-duration"></i>
|
<i class="cn-icon cn-icon-duration"></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,15 +103,23 @@ 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(() => {
|
||||||
@@ -123,89 +132,9 @@ export default {
|
|||||||
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)
|
||||||
if (this.entityName === 'hqzc.wssp.hainan.gov.cn' || this.entityName === '218.77.183.150') {
|
axios.get(`${api.entity.security}/${this.entityType}`, { params: params }).then(response => {
|
||||||
setTimeout(() => {
|
|
||||||
this.toggleLoading(false)
|
|
||||||
this.isNoData = false
|
|
||||||
this.eventList = [
|
|
||||||
{
|
|
||||||
eventId: '1717034000326447105',
|
|
||||||
eventType: 'Command and Control',
|
|
||||||
eventName: 'Mirai',
|
|
||||||
eventKey: '5,26.26.26.1,192.168.38.73',
|
|
||||||
ruleId: '5',
|
|
||||||
ruleType: 'indicator_match',
|
|
||||||
isBuiltin: '1',
|
|
||||||
eventSeverity: 'critical',
|
|
||||||
offenderIp: '119.102.149.177',
|
|
||||||
victimIp: '218.77.183.150',
|
|
||||||
domain: 'hqzc.wssp.hainan.gov.cn',
|
|
||||||
app: '',
|
|
||||||
startTime: new Date().getTime() - 3600 * 1000,
|
|
||||||
endTime: '1698207720',
|
|
||||||
durationMs: 1613000,
|
|
||||||
matchTimes: '1',
|
|
||||||
status: '1',
|
|
||||||
eventInfo: '{\"knowledge_id\":\"8\",\"name\":\"built_in_ioc_darkweb\",\"ioc_type\":\"ip\",\"ioc_value\":\"26.26.26.1\"}'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventId: '1717034000326447105',
|
|
||||||
eventType: 'Command and Control',
|
|
||||||
eventName: 'Bashlite',
|
|
||||||
eventKey: '5,26.26.26.1,192.168.38.73',
|
|
||||||
ruleId: '5',
|
|
||||||
ruleType: 'indicator_match',
|
|
||||||
isBuiltin: '1',
|
|
||||||
eventSeverity: 'critical',
|
|
||||||
offenderIp: '142.4.196.195',
|
|
||||||
victimIp: '218.77.183.150',
|
|
||||||
domain: 'hqzc.wssp.hainan.gov.cn',
|
|
||||||
app: '',
|
|
||||||
startTime: new Date().getTime() - 1600 * 1000,
|
|
||||||
endTime: '1698207720',
|
|
||||||
durationMs: 1285000,
|
|
||||||
matchTimes: '1',
|
|
||||||
status: '1',
|
|
||||||
eventInfo: '{\"knowledge_id\":\"8\",\"name\":\"built_in_ioc_darkweb\",\"ioc_type\":\"ip\",\"ioc_value\":\"26.26.26.1\"}'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventId: '1717034000326447105',
|
|
||||||
eventType: 'Command and Control',
|
|
||||||
eventName: 'Mirai',
|
|
||||||
eventKey: '5,26.26.26.1,192.168.38.73',
|
|
||||||
ruleId: '5',
|
|
||||||
ruleType: 'indicator_match',
|
|
||||||
isBuiltin: '1',
|
|
||||||
eventSeverity: 'critical',
|
|
||||||
offenderIp: '103.119.112.54',
|
|
||||||
victimIp: '218.77.183.150',
|
|
||||||
domain: 'hqzc.wssp.hainan.gov.cn',
|
|
||||||
app: '',
|
|
||||||
startTime: new Date().getTime() - 2600 * 1000,
|
|
||||||
endTime: '1698207720',
|
|
||||||
durationMs: 2280000,
|
|
||||||
matchTimes: '1',
|
|
||||||
status: '1',
|
|
||||||
eventInfo: '{\"knowledge_id\":\"8\",\"name\":\"built_in_ioc_darkweb\",\"ioc_type\":\"ip\",\"ioc_value\":\"26.26.26.1\"}'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
this.$emit('checkTag', entityDetailTabsName.securityEvent, 3)
|
|
||||||
}, 200)
|
|
||||||
} else {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.isNoData = true
|
|
||||||
this.toggleLoading(false)
|
|
||||||
this.eventList = []
|
|
||||||
this.$emit('checkTag', entityDetailTabsName.securityEvent, 0)
|
|
||||||
}, 200)
|
|
||||||
/*axios.get(`${api.entity.security}/${this.entityType}`, { params: params }).then(response => {
|
|
||||||
const res = response.data
|
const res = response.data
|
||||||
|
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
@@ -223,14 +152,25 @@ export default {
|
|||||||
this.httpError(e)
|
this.httpError(e)
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
this.toggleLoading(false)
|
this.toggleLoading(false)
|
||||||
})*/
|
})
|
||||||
}
|
|
||||||
},
|
},
|
||||||
httpError (e) {
|
httpError (e) {
|
||||||
this.$emit('checkTag', entityDetailTabsName.securityEvent, 0)
|
this.$emit('checkTag', entityDetailTabsName.securityEvent, 0)
|
||||||
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
|
||||||
@@ -188,9 +186,9 @@ export default {
|
|||||||
// 链路下一跳数据
|
// 链路下一跳数据
|
||||||
let nextGridData = []
|
let nextGridData = []
|
||||||
const nextGridTemplate = [
|
const nextGridTemplate = [
|
||||||
{ linkId: 'Hundredgige2', nextHop: 'City2', out: [] },
|
{ linkId: 'Hundredgige2', nextHop: '太原', out: [] },
|
||||||
{ linkId: 'Hundredgige1', nextHop: 'City1', out: [] },
|
{ linkId: 'Hundredgige1', nextHop: '西安', out: [] },
|
||||||
{ linkId: 'Hundredgige4', nextHop: 'City3', out: [] }
|
{ linkId: 'Hundredgige4', nextHop: '西宁', out: [] }
|
||||||
]
|
]
|
||||||
nextGridData = JSON.parse(JSON.stringify(nextGridTemplate))
|
nextGridData = JSON.parse(JSON.stringify(nextGridTemplate))
|
||||||
nextGridData.forEach(link => {
|
nextGridData.forEach(link => {
|
||||||
@@ -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, [])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,7 +53,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<div class="form-collapse-content margin-t-18">
|
<div class="form-collapse-content margin-t-18">
|
||||||
<el-form v-if="language==='en'" class="trigger-block margin-b-20" ref="form3" :model="triggerObj" :rules="rules">
|
<el-form v-if="language===EN" class="trigger-block margin-b-20" ref="form3" :model="triggerObj" :rules="rules">
|
||||||
<div class="trigger-block-item margin-b-10">
|
<div class="trigger-block-item margin-b-10">
|
||||||
<div>At least</div>
|
<div>At least</div>
|
||||||
<el-form-item prop="atLeast">
|
<el-form-item prop="atLeast">
|
||||||
@@ -94,7 +94,7 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
</el-form>
|
</el-form>
|
||||||
<el-form v-if="language==='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">
|
||||||
@@ -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,7 +162,7 @@ import { useRoute } from 'vue-router'
|
|||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { getDurationsTimeByType, getTimeByDurations } from '@/utils/date-util'
|
import { getDurationsTimeByType, getTimeByDurations } from '@/utils/date-util'
|
||||||
import Loading from '@/components/common/Loading'
|
import Loading from '@/components/common/Loading'
|
||||||
import { storageKey, detectionUnitList } from '@/utils/constants'
|
import { storageKey, detectionUnitList, ZH, EN } from '@/utils/constants'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'DetectionForm',
|
name: 'DetectionForm',
|
||||||
@@ -257,7 +259,9 @@ export default {
|
|||||||
intervalList: [],
|
intervalList: [],
|
||||||
editObj: {},
|
editObj: {},
|
||||||
isComplete: true, // 参数完整标识,默认完整(照顾编辑模式),false即不完整
|
isComplete: true, // 参数完整标识,默认完整(照顾编辑模式),false即不完整
|
||||||
language: 'en'
|
language: EN,
|
||||||
|
ZH,
|
||||||
|
EN
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
@@ -266,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()
|
||||||
@@ -330,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()
|
||||||
@@ -367,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
|
||||||
|
|
||||||
@@ -376,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)
|
||||||
@@ -402,7 +403,7 @@ export default {
|
|||||||
})
|
})
|
||||||
|
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
path: '/detectionPolicy',
|
path: '/detection/policy',
|
||||||
query: {
|
query: {
|
||||||
t: +new Date()
|
t: +new Date()
|
||||||
}
|
}
|
||||||
@@ -418,7 +419,6 @@ export default {
|
|||||||
this.myLoading = false
|
this.myLoading = false
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
console.log('进来')
|
|
||||||
this.myLoading = true
|
this.myLoading = true
|
||||||
axios.put(api.detection.create.create, formObj).then(response => {
|
axios.put(api.detection.create.create, formObj).then(response => {
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
@@ -428,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)
|
||||||
@@ -491,7 +497,134 @@ export default {
|
|||||||
return { flag: false, msg: this.$t('policy.dateTimeRangeSeconds') }
|
return { flag: false, msg: this.$t('policy.dateTimeRangeSeconds') }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
cancel () {
|
||||||
|
const { query } = this.$route
|
||||||
|
const queryInfo = {
|
||||||
|
pageNo: this.pageNoForTable ? Number(this.pageNoForTable) : 1,
|
||||||
|
t: +new Date()
|
||||||
|
}
|
||||||
|
if (query.name && query.id) {
|
||||||
|
queryInfo.ruleId = query.id
|
||||||
|
queryInfo.name = this.settingObj.name
|
||||||
|
}
|
||||||
|
this.$refs.form3.validate(valid => {
|
||||||
|
if (this.settingObj.settingNoContinue || this.ruleObj.settingNoContinue || !valid) {
|
||||||
|
this.$confirm(this.$t('tip.leavePage'), {
|
||||||
|
confirmButtonText: this.$t('tip.confirm'),
|
||||||
|
cancelButtonText: this.$t('overall.cancel'),
|
||||||
|
message: this.$t('tip.leavePageTips'),
|
||||||
|
title: this.$t('tip.leavePage'),
|
||||||
|
type: 'warning',
|
||||||
|
iconClass: 'width:0px;height:0px;',
|
||||||
|
customClass: 'del-model'
|
||||||
|
}).then(() => {
|
||||||
|
this.$router.push({
|
||||||
|
path: '/detection/policy',
|
||||||
|
query: queryInfo
|
||||||
|
})
|
||||||
|
}).catch(() => {})
|
||||||
|
} else {
|
||||||
|
this.$router.push({
|
||||||
|
path: '/detection/policy',
|
||||||
|
query: queryInfo
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.del-model {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding-bottom: 0 !important;
|
||||||
|
width: 480px !important;
|
||||||
|
height: 190px;
|
||||||
|
|
||||||
|
.el-message-box__header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
height: 42px;
|
||||||
|
background: #F7F7F7;
|
||||||
|
box-shadow: 0 1px 0 0 rgba(53, 54, 54, 0.08);
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-top: 14px;
|
||||||
|
padding-bottom: 14px;
|
||||||
|
|
||||||
|
.el-message-box__headerbtn {
|
||||||
|
display: flex !important;
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 10px;
|
||||||
|
line-height: 10px;
|
||||||
|
padding-right: 5px !important;
|
||||||
|
|
||||||
|
i {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-message-box__title {
|
||||||
|
font-size: 14px !important;
|
||||||
|
color: #353636;
|
||||||
|
letter-spacing: 0;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-message-box__content {
|
||||||
|
height: 96px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #353636;
|
||||||
|
letter-spacing: 0;
|
||||||
|
line-height: 22px;
|
||||||
|
font-weight: 400;
|
||||||
|
padding-top: 8px;
|
||||||
|
padding-right: 20px;
|
||||||
|
padding-left: 20px;
|
||||||
|
|
||||||
|
.el-message-box__message {
|
||||||
|
padding-left: 0 !important;
|
||||||
|
padding-right: 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-message-box__btns {
|
||||||
|
height: 52px;
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
box-shadow: inset 0 -1px 0 0 rgba(0, 0, 0, 0.07);
|
||||||
|
padding: 11px 0 12px !important;
|
||||||
|
|
||||||
|
.el-button--small {
|
||||||
|
padding: 8px 21px !important;
|
||||||
|
line-height: 12px;
|
||||||
|
font-family: NotoSansHans-Medium !important;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
min-height: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-button:nth-child(1) {
|
||||||
|
margin-right: 20px;
|
||||||
|
width: 80px;
|
||||||
|
height: 28px;
|
||||||
|
color: #353636;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-button:nth-child(2) {
|
||||||
|
width: 80px;
|
||||||
|
height: 28px;
|
||||||
|
margin-right: 20px;
|
||||||
|
margin-left: 0 !important;
|
||||||
|
background-color: #2d8cf0;
|
||||||
|
border-color: #2d8cf0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -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>
|
||||||
@@ -82,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',
|
||||||
@@ -89,6 +92,9 @@ export default {
|
|||||||
isNoData: {
|
isNoData: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
|
},
|
||||||
|
policyDetail: {
|
||||||
|
type: Object
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mixins: [table],
|
mixins: [table],
|
||||||
@@ -146,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,
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -308,10 +308,6 @@ export const metricOption = {
|
|||||||
str += `<span class="cn-chart-tooltip-value">
|
str += `<span class="cn-chart-tooltip-value">
|
||||||
${unitConvert(item.data[1], unitTypes.time).join(' ')}
|
${unitConvert(item.data[1], unitTypes.time).join(' ')}
|
||||||
</span>`
|
</span>`
|
||||||
} else if (item.seriesName === 'Http error') {
|
|
||||||
str += `<span class="cn-chart-tooltip-value">
|
|
||||||
${unitConvert(item.data[1], unitTypes.number, '', '', 0).join(' ')}
|
|
||||||
</span>`
|
|
||||||
} else {
|
} else {
|
||||||
str += `<span class="cn-chart-tooltip-value">
|
str += `<span class="cn-chart-tooltip-value">
|
||||||
${unitConvert(item.data[1], unitTypes.percent, '', '', 0).join(' ')}
|
${unitConvert(item.data[1], unitTypes.percent, '', '', 0).join(' ')}
|
||||||
|
|||||||
@@ -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"
|
||||||
@@ -71,8 +89,7 @@
|
|||||||
<div class="right-label">{{ $t('network.total') }}</div>
|
<div class="right-label">{{ $t('network.total') }}</div>
|
||||||
<div class="right-label-loading">
|
<div class="right-label-loading">
|
||||||
<loading :loading="loadingApp" size="small"></loading>
|
<loading :loading="loadingApp" size="small"></loading>
|
||||||
<!-- <div class="right-value">{{ numberWithCommas(entityAppTotal) }}</div>-->
|
<div class="right-value">{{ numberWithCommas(entityAppTotal) }}</div>
|
||||||
<div class="right-value">837</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -93,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">
|
||||||
@@ -102,8 +119,7 @@
|
|||||||
<div class="right-label">{{ $t('network.total') }}</div>
|
<div class="right-label">{{ $t('network.total') }}</div>
|
||||||
<div class="right-label-loading">
|
<div class="right-label-loading">
|
||||||
<loading :loading="loadingDomain" size="small"></loading>
|
<loading :loading="loadingDomain" size="small"></loading>
|
||||||
<!-- <div class="right-value">{{ numberWithCommas(entityDomainTotal) }}</div>-->
|
<div class="right-value">{{ numberWithCommas(entityDomainTotal) }}</div>
|
||||||
<div class="right-value">1,032,544</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -133,8 +149,7 @@
|
|||||||
<div class="right-label">{{ $t('network.total') }}</div>
|
<div class="right-label">{{ $t('network.total') }}</div>
|
||||||
<div class="right-label-loading">
|
<div class="right-label-loading">
|
||||||
<loading :loading="loadingIp" size="small"></loading>
|
<loading :loading="loadingIp" size="small"></loading>
|
||||||
<!-- <div class="right-value">{{ numberWithCommas(entityIpTotal) }}</div>-->
|
<div class="right-value">{{ numberWithCommas(entityIpTotal) }}</div>
|
||||||
<div class="right-value">1,900,804</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -177,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',
|
||||||
@@ -184,7 +201,8 @@ export default {
|
|||||||
Loading,
|
Loading,
|
||||||
ExplorerSearch,
|
ExplorerSearch,
|
||||||
EntityFilter,
|
EntityFilter,
|
||||||
EntityList
|
EntityList,
|
||||||
|
DateTimeRange
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
@@ -203,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',
|
||||||
@@ -287,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: {
|
||||||
@@ -305,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) {
|
||||||
@@ -364,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 = ''
|
||||||
@@ -371,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添加到地址栏
|
||||||
@@ -392,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,
|
||||||
@@ -420,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 })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 点击上一页箭头
|
// 点击上一页箭头
|
||||||
@@ -492,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
|
||||||
@@ -551,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)
|
||||||
@@ -573,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
|
||||||
})
|
})
|
||||||
@@ -678,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]))
|
||||||
}
|
}
|
||||||
@@ -730,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,即列表页,并非首页,则开始搜索
|
||||||
@@ -744,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)
|
||||||
}
|
}
|
||||||
@@ -754,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 () {
|
||||||
@@ -766,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 {
|
||||||
@@ -784,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,
|
||||||
|
|||||||
@@ -10,18 +10,22 @@
|
|||||||
<img v-if="entity.location.country===countryNameIdMapping.Unknown || !countryNameIdMapping[entity.location.country]" src="../../../../../public/images/flag/Unknown.svg" class="filter-country-flag">
|
<img v-if="entity.location.country===countryNameIdMapping.Unknown || !countryNameIdMapping[entity.location.country]" src="../../../../../public/images/flag/Unknown.svg" class="filter-country-flag">
|
||||||
<img v-else :src="require(`../../../../../public/images/flag/${countryNameIdMapping[entity.location.country]}.png`)" class="filter-country-flag" >
|
<img v-else :src="require(`../../../../../public/images/flag/${countryNameIdMapping[entity.location.country]}.png`)" class="filter-country-flag" >
|
||||||
</div>
|
</div>
|
||||||
{{ipLocationRegion(entity.location)}}
|
<span v-high-light="keywordList" class="high-location">{{ ipLocationRegion(entity.location) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>-</div>
|
<div v-else>-</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="overview__row">
|
<div class="overview__row">
|
||||||
<div class="row__label row__label--width130">ASN</div>
|
<div class="row__label row__label--width130">ASN</div>
|
||||||
<div class="row__content">{{$_.get(entity, 'asn.asn', '-') || '-'}}</div>
|
<div class="row__content" v-high-light="keywordList">{{ $_.get(entity, 'asn.asn', '-') || '-' }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="overview__row">
|
||||||
|
<div class="row__label row__label--width130">ISP</div>
|
||||||
|
<div class="row__content" v-high-light="keywordList">{{ $_.get(entityData, 'location.isp', '-') || '-' }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="overview__row">
|
<div class="overview__row">
|
||||||
<div class="row__label row__label--width130">{{$t('entities.openPort')}}</div>
|
<div class="row__label row__label--width130">{{$t('entities.openPort')}}</div>
|
||||||
<div class="row__content" style="word-break: break-word;">{{ openPort }}</div>
|
<div class="row__content high-location" style="word-break: break-word;" v-high-light="keywordList">{{ openPort }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -128,7 +132,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>
|
||||||
@@ -137,7 +141,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>
|
||||||
@@ -151,7 +155,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>
|
||||||
@@ -160,7 +164,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>
|
||||||
@@ -181,7 +185,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>
|
||||||
@@ -208,7 +212,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>
|
||||||
@@ -251,7 +255,7 @@ import { valueToRangeValue } from '@/utils/unit-convert'
|
|||||||
import Chart from '@/views/charts/Chart'
|
import Chart from '@/views/charts/Chart'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
import relatedServer from '@/mixins/relatedServer'
|
import relatedServer from '@/mixins/relatedServer'
|
||||||
import { dateFormatByAppearance, getMillisecond } 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 axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
@@ -262,6 +266,9 @@ export default {
|
|||||||
Loading,
|
Loading,
|
||||||
Chart
|
Chart
|
||||||
},
|
},
|
||||||
|
props: {
|
||||||
|
keywordList: Array
|
||||||
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
entityType: 'ip',
|
entityType: 'ip',
|
||||||
@@ -401,10 +408,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 {
|
||||||
@@ -430,8 +449,8 @@ export default {
|
|||||||
},
|
},
|
||||||
getOpenPort () {
|
getOpenPort () {
|
||||||
const params = {
|
const params = {
|
||||||
// startTime: getSecond(this.timeFilter.startTime),
|
startTime: getSecond(this.timeFilter.startTime),
|
||||||
// endTime: getSecond(this.timeFilter.endTime),
|
endTime: getSecond(this.timeFilter.endTime),
|
||||||
resource: this.entity.entityValue
|
resource: this.entity.entityValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ export default {
|
|||||||
this.sentChart = echarts.init(document.getElementById(`entityDetailSend${this.entityName}`))
|
this.sentChart = echarts.init(document.getElementById(`entityDetailSend${this.entityName}`))
|
||||||
this.receivedChart = echarts.init(document.getElementById(`entityDetailReceived${this.entityName}`))
|
this.receivedChart = echarts.init(document.getElementById(`entityDetailReceived${this.entityName}`))
|
||||||
this.loadingTraffic = true
|
this.loadingTraffic = true
|
||||||
axios.get(this.trafficUrl, { params: this.getQueryParams() }).then(response => {
|
axios.get(this.trafficUrl, { params: this.getQueryParams(DEFAULT_TIME_FILTER_RANGE.entity.trafficLine) }).then(response => {
|
||||||
if (response.status === 200 && response.data.data.result && response.data.data.result.length > 0) {
|
if (response.status === 200 && response.data.data.result && response.data.data.result.length > 0) {
|
||||||
response.data.data.result.forEach(t => {
|
response.data.data.result.forEach(t => {
|
||||||
if (t.legend === 'rate') {
|
if (t.legend === 'rate') {
|
||||||
@@ -278,7 +278,7 @@ export default {
|
|||||||
this.performanceScoreData = {}
|
this.performanceScoreData = {}
|
||||||
this.scoreDataState = false
|
this.scoreDataState = false
|
||||||
if (this.networkQuantityUrl) {
|
if (this.networkQuantityUrl) {
|
||||||
axios.get(this.networkQuantityUrl, { params: this.getQueryParams() }).then(response => {
|
axios.get(this.networkQuantityUrl, { params: this.getQueryParams(DEFAULT_TIME_FILTER_RANGE.entity.trafficLine) }).then(response => {
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
this.performanceScoreData = {
|
this.performanceScoreData = {
|
||||||
establishLatencyMs: response.data.data.result.establishLatencyMsAvg || null,
|
establishLatencyMs: response.data.data.result.establishLatencyMsAvg || null,
|
||||||
@@ -347,7 +347,7 @@ export default {
|
|||||||
|
|
||||||
queryEntityDetailPerformance () {
|
queryEntityDetailPerformance () {
|
||||||
this.loadingAlert = true
|
this.loadingAlert = true
|
||||||
axios.get(this.performanceUrl, { params: this.getQueryParams() }).then(response => {
|
axios.get(this.performanceUrl, { params: this.getQueryParams(DEFAULT_TIME_FILTER_RANGE.entity.performanceEvent) }).then(response => {
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
this.entityData.performanceNum = response.data.data.result.length
|
this.entityData.performanceNum = response.data.data.result.length
|
||||||
this.performanceData = response.data.data.result
|
this.performanceData = response.data.data.result
|
||||||
@@ -359,7 +359,7 @@ export default {
|
|||||||
|
|
||||||
queryEntityDetailSecurity () {
|
queryEntityDetailSecurity () {
|
||||||
this.loadingSecurityEvents = true
|
this.loadingSecurityEvents = true
|
||||||
axios.get(this.securityUrl, { params: this.getQueryParams() }).then(response => {
|
axios.get(this.securityUrl, { params: this.getQueryParams(DEFAULT_TIME_FILTER_RANGE.entity.securityEvent) }).then(response => {
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
this.entityData.securityNum = response.data.data.result.length
|
this.entityData.securityNum = response.data.data.result.length
|
||||||
this.securityData = response.data.data.result
|
this.securityData = response.data.data.result
|
||||||
@@ -436,7 +436,7 @@ export default {
|
|||||||
queryEntityDetail () {
|
queryEntityDetail () {
|
||||||
this.queryEntityDetailTraffic()
|
this.queryEntityDetailTraffic()
|
||||||
// this.queryEntityDetailPerformance()
|
// this.queryEntityDetailPerformance()
|
||||||
// this.queryEntityDetailSecurity()
|
this.queryEntityDetailSecurity()
|
||||||
this.queryEntityDetailNetworkQuantity()
|
this.queryEntityDetailNetworkQuantity()
|
||||||
/* if (this.entity.entityType === 'ip') {
|
/* if (this.entity.entityType === 'ip') {
|
||||||
if (!this.entityData.dnsServerRole) {
|
if (!this.entityData.dnsServerRole) {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user