Compare commits
191 Commits
| 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 | ||
|
|
99f97b76a7 | ||
|
|
b0260ea41a | ||
|
|
a7d6ffb4b4 | ||
|
|
dbc68077ca | ||
|
|
186e115adf | ||
|
|
6c5233a760 | ||
|
|
2df67c1972 | ||
|
|
cb3b66bdf7 | ||
|
|
6ba0ca0a82 | ||
|
|
00df0414c2 | ||
|
|
20a4bb22ef | ||
|
|
00bb6f8c5f | ||
|
|
e61c664802 | ||
|
|
a4dff135d1 | ||
|
|
0bd87db92f | ||
|
|
407d9ec667 | ||
|
|
e7637dd866 | ||
|
|
59c2b26d6c | ||
|
|
8b5b36a621 | ||
|
|
7762658864 | ||
|
|
eb25dc6aa7 | ||
|
|
1fff8f49c9 | ||
|
|
47d8212abe | ||
|
|
94940d745c | ||
|
|
030af380fd | ||
|
|
e9f21038b5 | ||
|
|
e355e427fb | ||
|
|
6dea1ee890 | ||
|
|
1fae281b8b | ||
|
|
60a527c765 | ||
|
|
3daa875a25 | ||
|
|
b4fcbd260b | ||
|
|
871781ab70 | ||
|
|
9bb9967353 | ||
|
|
327ae1956d | ||
|
|
4d4d197a80 | ||
|
|
46f1a880cd | ||
|
|
d1c9eba029 | ||
|
|
643ada9172 | ||
|
|
d0aa64fb9c | ||
|
|
5b7dd6da90 | ||
|
|
97d793471c | ||
|
|
6a2d5a0efe | ||
|
|
b90810470e | ||
|
|
d8865b74d7 | ||
|
|
012d873b71 | ||
|
|
fefca1588f | ||
|
|
f6af25e5e6 | ||
|
|
c5c7b58720 | ||
|
|
40d43acb6c | ||
|
|
7d34b8388c | ||
|
|
d2feedb319 | ||
|
|
0f52bd5362 | ||
|
|
48b3e2aebd | ||
|
|
9208a4fff2 | ||
|
|
19747cf326 | ||
|
|
c2de6c853c | ||
|
|
b0a7d44c42 | ||
|
|
3b641e1878 | ||
|
|
0a9d5591d5 | ||
|
|
0e82bebaac | ||
|
|
85db8cd745 | ||
|
|
c960c60790 | ||
|
|
18b62f1e3d | ||
|
|
11540d3c34 | ||
|
|
5fbab86a80 | ||
|
|
ed9a2c4e1f | ||
|
|
b94bc23a86 | ||
|
|
328f226a86 | ||
|
|
660950a73c | ||
|
|
8f9308a04e | ||
|
|
133c9a23c0 | ||
|
|
bc4a6c2a9e | ||
|
|
5798c0c5a7 | ||
|
|
15ac00d548 | ||
|
|
95217b84a5 | ||
|
|
24e549a444 | ||
|
|
e16d351efd | ||
|
|
ccec756baa | ||
|
|
a47e04fae2 | ||
|
|
8cc6edbdd4 | ||
|
|
afa86464d9 | ||
|
|
16e63ab905 | ||
|
|
6f72b2258f | ||
|
|
5a4301e3aa | ||
|
|
96c380001c | ||
|
|
40365decf6 | ||
|
|
ac9c16d464 | ||
|
|
7abe436127 | ||
|
|
d85e2d347f | ||
|
|
cc61cbc05c | ||
|
|
7cc2439dd2 | ||
|
|
8ba062054c | ||
|
|
cdb1d4baec | ||
|
|
1886f8214f | ||
|
|
aaaecfd9a1 | ||
|
|
9ab00df342 | ||
|
|
33293aaaa3 | ||
|
|
5cb105784a | ||
|
|
4e0e49585e |
@@ -39,9 +39,9 @@ build_project:
|
|||||||
stage: build_project
|
stage: build_project
|
||||||
script:
|
script:
|
||||||
- echo "npm install ..."
|
- echo "npm install ..."
|
||||||
- cnpm install --save-dev --unsafe-perm
|
- npm install --save-dev --unsafe-perm
|
||||||
- echo "npm run build"
|
- echo "npm run build"
|
||||||
- cnpm run build
|
- npm run build
|
||||||
artifacts:
|
artifacts:
|
||||||
name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME"
|
name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME"
|
||||||
when: on_success
|
when: on_success
|
||||||
|
|||||||
27002
package-lock.json
generated
27002
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
68
package.json
68
package.json
@@ -10,63 +10,64 @@
|
|||||||
"analyz": "cross-env NODE_ENV=production npm_config_report=true npm run build"
|
"analyz": "cross-env NODE_ENV=production npm_config_report=true npm run build"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@amcharts/amcharts4": "^4.10.24",
|
"@amcharts/amcharts4": "~4.10.0",
|
||||||
"@amcharts/amcharts4-geodata": "^4.1.20",
|
"@amcharts/amcharts4-geodata": "^4.1.20",
|
||||||
"@antv/g6": "^4.8.17",
|
"@antv/g6": "^4.8.17",
|
||||||
"axios": "^0.21.1",
|
"axios": "^0.21.1",
|
||||||
"babel-plugin-lodash": "^3.3.4",
|
"babel-plugin-lodash": "~3.3.0",
|
||||||
"codemirror": "^5.65.1",
|
"codemirror": "^5.65.1",
|
||||||
"core-js": "^3.6.5",
|
"core-js": "~3.31.0",
|
||||||
"dayjs": "^1.10.5",
|
"dayjs": "^1.10.5",
|
||||||
"dexie": "^3.2.2",
|
"dexie": "~3.2.0",
|
||||||
"echarts": "^5.1.1",
|
"echarts": "^5.1.1",
|
||||||
"element-plus": "^1.0.2-beta.44",
|
"element-plus": "~1.0.2-beta.71",
|
||||||
"lib-flexible": "^0.3.2",
|
"lib-flexible": "^0.3.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"mockjs": "^1.1.0",
|
"mockjs": "^1.1.0",
|
||||||
"moment-timezone": "^0.5.33",
|
"moment-timezone": "^0.5.33",
|
||||||
"node-sass": "^4.14.1",
|
"node-sass": "~4.14.0",
|
||||||
"postcss-plugin-px2rem": "^0.8.1",
|
"postcss-plugin-px2rem": "~0.8.1",
|
||||||
"postcss-px2rem-exclude": "0.0.6",
|
"postcss-px2rem-exclude": "0.0.6",
|
||||||
"sass-loader": "^8.0.2",
|
"sass-loader": "~8.0.2",
|
||||||
"sass-resources-loader": "^2.2.1",
|
"sass-resources-loader": "~2.2.5",
|
||||||
"tiny-emitter": "^2.1.0",
|
"tiny-emitter": "^2.1.0",
|
||||||
"vue": "^3.0.0",
|
"vue": "~3.3.0",
|
||||||
"vue-grid-layout": "^3.0.0-beta1",
|
"vue-grid-layout": "^3.0.0-beta1",
|
||||||
"vue-i18n": "^9.1.6",
|
"vue-i18n": "~9.2.0",
|
||||||
"vue-router": "^4.0.8",
|
"vue-router": "~4.2.0",
|
||||||
"vuex": "^4.0.1"
|
"vuex": "~4.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.12.1",
|
"@babel/cli": "~7.22.0",
|
||||||
"@babel/core": "^7.11.4",
|
"@babel/core": "~7.22.5",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.12.1",
|
"@babel/plugin-proposal-class-properties": "~7.18.0",
|
||||||
"@babel/plugin-proposal-private-methods": "^7.12.1",
|
"@babel/plugin-proposal-private-methods": "~7.18.0",
|
||||||
"@babel/plugin-transform-runtime": "^7.12.1",
|
"@babel/plugin-transform-runtime": "~7.22.0",
|
||||||
"@babel/plugin-proposal-private-property-in-object": "^7.12.1",
|
"@babel/plugin-proposal-private-property-in-object": "~7.21.0",
|
||||||
"@babel/preset-env": "^7.11.5",
|
"@babel/preset-env": "~7.22.0",
|
||||||
"@babel/preset-typescript": "^7.10.4",
|
"@babel/preset-typescript": "~7.22.0",
|
||||||
"@commitlint/cli": "^9.1.2",
|
"@commitlint/cli": "^9.1.2",
|
||||||
"@commitlint/config-conventional": "^9.1.2",
|
"@commitlint/config-conventional": "^9.1.2",
|
||||||
"@highlightjs/vue-plugin": "^2.0.1",
|
"@highlightjs/vue-plugin": "^2.0.1",
|
||||||
"@rollup/plugin-commonjs": "^15.1.0",
|
"@rollup/plugin-commonjs": "^15.1.0",
|
||||||
"@rollup/plugin-node-resolve": "^9.0.0",
|
"@rollup/plugin-node-resolve": "^9.0.0",
|
||||||
"@rollup/plugin-typescript": "^6.0.0",
|
"@rollup/plugin-typescript": "^6.0.0",
|
||||||
"@testing-library/jest-dom": "^5.16.5",
|
"@testing-library/jest-dom": "~5.16.0",
|
||||||
"@testing-library/user-event": "^14.4.3",
|
"@testing-library/user-event": "~14.4.0",
|
||||||
"@testing-library/vue": "^6.4.2",
|
"@testing-library/vue": "~6.6.0",
|
||||||
"@types/jest": "^26.0.24",
|
"@types/jest": "~26.0.0",
|
||||||
"@types/lodash": "^4.14.161",
|
"@types/lodash": "^4.14.161",
|
||||||
"@typescript-eslint/eslint-plugin": "^3.10.1",
|
"@typescript-eslint/eslint-plugin": "^3.10.1",
|
||||||
"@typescript-eslint/parser": "^3.10.1",
|
"@typescript-eslint/parser": "^3.10.1",
|
||||||
"@vue/babel-plugin-jsx": "^1.0.0",
|
"@vue/babel-plugin-jsx": "~1.1.0",
|
||||||
"@vue/babel-preset-app": "^5.0.8",
|
"@vue/babel-preset-app": "~5.0.0",
|
||||||
"@vue/cli-plugin-babel": "~4.5.0",
|
"@vue/cli-plugin-babel": "~4.5.0",
|
||||||
"@vue/cli-plugin-eslint": "~4.5.0",
|
"@vue/cli-plugin-eslint": "~4.5.0",
|
||||||
"@vue/cli-service": "~4.5.0",
|
"@vue/cli-service": "~4.5.0",
|
||||||
"@vue/compiler-sfc": "^3.0.0",
|
"@vue/compiler-sfc": "~3.3.0",
|
||||||
"@vue/component-compiler-utils": "^3.2.0",
|
"@vue/component-compiler-utils": "~3.3.0",
|
||||||
"@vue/test-utils": "^2.2.7",
|
"@vue/test-utils": "~2.4.0",
|
||||||
|
"@vue/server-renderer": "~3.3.0",
|
||||||
"babel-eslint": "^10.1.0",
|
"babel-eslint": "^10.1.0",
|
||||||
"babel-jest": "^26.0.0",
|
"babel-jest": "^26.0.0",
|
||||||
"compression-webpack-plugin": "^8.0.1",
|
"compression-webpack-plugin": "^8.0.1",
|
||||||
@@ -77,11 +78,10 @@
|
|||||||
"eslint-plugin-node": "^11.1.0",
|
"eslint-plugin-node": "^11.1.0",
|
||||||
"eslint-plugin-promise": "^4.3.1",
|
"eslint-plugin-promise": "^4.3.1",
|
||||||
"eslint-plugin-vue": "^7.7.0",
|
"eslint-plugin-vue": "^7.7.0",
|
||||||
"jest": "^26.0.0",
|
"jest": "~26.6.0",
|
||||||
"ts-jest": "^26.4.4",
|
"ts-jest": "~26.5.0",
|
||||||
"uglifyjs-webpack-plugin": "^2.2.0",
|
"uglifyjs-webpack-plugin": "^2.2.0",
|
||||||
"vue-jest": "^5.0.0-alpha.10",
|
"vue-jest": "^5.0.0-alpha.10"
|
||||||
"vue3-ace-editor": "^2.0.2"
|
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
"> 1%",
|
"> 1%",
|
||||||
|
|||||||
@@ -1,5 +1,20 @@
|
|||||||
const BASE_CONFIG = {
|
const BASE_CONFIG = {
|
||||||
baseUrl: 'http://192.168.44.54:8091/',
|
baseUrl: 'http://192.168.44.54:8090/',
|
||||||
version: '23.06',
|
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
|
||||||
|
}
|
||||||
|
|||||||
1
public/geojson/frenchPolynesiaLow.json
Normal file
1
public/geojson/frenchPolynesiaLow.json
Normal file
File diff suppressed because one or more lines are too long
1
public/geojson/lesothoLow.json
Normal file
1
public/geojson/lesothoLow.json
Normal file
File diff suppressed because one or more lines are too long
1
public/geojson/liberiaLow.json
Normal file
1
public/geojson/liberiaLow.json
Normal file
File diff suppressed because one or more lines are too long
11
public/geojson/mauritiusLow.json
Normal file
11
public/geojson/mauritiusLow.json
Normal file
File diff suppressed because one or more lines are too long
@@ -54,7 +54,8 @@ export default {
|
|||||||
return {
|
return {
|
||||||
loading: false,
|
loading: false,
|
||||||
username: '',
|
username: '',
|
||||||
pin: ''
|
pin: '',
|
||||||
|
language: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -75,6 +76,9 @@ export default {
|
|||||||
if (!_.isEmpty(res.data.data.user.lang)) {
|
if (!_.isEmpty(res.data.data.user.lang)) {
|
||||||
localStorage.setItem(storageKey.language, res.data.data.user.lang)
|
localStorage.setItem(storageKey.language, res.data.data.user.lang)
|
||||||
}
|
}
|
||||||
|
if (!localStorage.getItem(storageKey.language)) {
|
||||||
|
localStorage.setItem(storageKey.language, this.language)
|
||||||
|
}
|
||||||
if (!_.isEmpty(res.data.data.user.theme)) {
|
if (!_.isEmpty(res.data.data.user.theme)) {
|
||||||
localStorage.setItem(storageKey.theme, res.data.data.user.theme)
|
localStorage.setItem(storageKey.theme, res.data.data.user.theme)
|
||||||
}
|
}
|
||||||
@@ -107,6 +111,7 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
appearanceOut (data) {
|
appearanceOut (data) {
|
||||||
|
this.language = data.lang || defaultLang
|
||||||
if (_.isEmpty(localStorage.getItem(storageKey.language))) {
|
if (_.isEmpty(localStorage.getItem(storageKey.language))) {
|
||||||
localStorage.setItem(storageKey.language, data.lang || defaultLang)
|
localStorage.setItem(storageKey.language, data.lang || defaultLang)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,84 +3,92 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
.search__suffixes {
|
.search__suffixes {
|
||||||
|
height: 38px;
|
||||||
|
|
||||||
|
&.entity-explorer-home {
|
||||||
|
margin-right: 1px;
|
||||||
|
color: #3976CB;
|
||||||
|
|
||||||
|
&.search__suffixes--text-mode, &.search__suffixes--tag-mode {
|
||||||
|
.search__suffix:last-of-type {
|
||||||
|
width: unset;
|
||||||
|
height: unset;
|
||||||
|
margin-right: 12px;
|
||||||
|
background-color: transparent;
|
||||||
|
|
||||||
|
.el-icon-search {
|
||||||
|
color: #3976CB;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
&.search__suffixes--text-mode, &.search__suffixes--tag-mode {
|
&.search__suffixes--text-mode, &.search__suffixes--tag-mode {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: flex;
|
display: flex;
|
||||||
top: 10px;
|
align-items: center;
|
||||||
right: 10px;
|
top: 1px;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
.search__suffix {
|
.search__suffix {
|
||||||
// margin-left: 8px;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin-right: 12px;
|
||||||
|
border-radius: 0 2px 2px 0;
|
||||||
|
|
||||||
.cn-icon-search-advance, .cn-icon-search-normal, .cn-icon-filter {
|
.cn-icon-search-advance, .cn-icon-search-normal, .cn-icon-filter {
|
||||||
color: #A6AAAE;
|
color: #A6AAAE;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
.el-icon-search {
|
|
||||||
color: #3976CB;
|
|
||||||
font-size: 22px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
&:last-of-type {
|
||||||
|
margin-right: 0;
|
||||||
|
width: 41px;
|
||||||
|
height: 38px;
|
||||||
|
line-height: 39px;
|
||||||
|
background: #38ACD2;
|
||||||
|
|
||||||
|
.el-icon-search {
|
||||||
|
font-size: 22px;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.search__suffix-close {
|
.search__suffix-close {
|
||||||
height: 40px;
|
|
||||||
line-height: 40px;
|
|
||||||
margin-top: -9px;
|
|
||||||
|
|
||||||
.el-icon-error {
|
.el-icon-error {
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
color: #C4C4C4;
|
color: #C4C4C4;
|
||||||
margin-right: 12px;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.entity-explorer-search {
|
|
||||||
color: #3976CB;
|
|
||||||
margin-top: -2px;
|
|
||||||
}
|
|
||||||
.margin-r-12 {
|
|
||||||
margin-right: 12px;
|
|
||||||
}
|
|
||||||
.new-search__suffix {
|
|
||||||
width: 41px;
|
|
||||||
height: 41px;
|
|
||||||
line-height: 41px;
|
|
||||||
background: #38ACD2;
|
|
||||||
text-align: center;
|
|
||||||
margin-top: -10px;
|
|
||||||
margin-right: -10px;
|
|
||||||
|
|
||||||
.el-icon-search {
|
|
||||||
color: #fff !important;
|
|
||||||
margin-top: 9px !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.my-popper-class .el-popper__arrow {
|
.my-popper-class .el-popper__arrow {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.search__suffixes--tag-mode__block {
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*.search-tip--error {
|
|
||||||
font-size: 14px;
|
|
||||||
color: #F56C6C;
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
.advanced-search--show-list .CodeMirror, .advanced-search--show-list .tag-search {
|
.detections {
|
||||||
border: none;
|
.tag-search, .CodeMirror {
|
||||||
|
border: 1px solid #E2E5EC;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.tag-search {
|
.tag-search {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
overflow: auto hidden;
|
overflow: auto hidden;
|
||||||
border: 1px solid #CECECE;
|
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
padding-right: 80px;
|
padding-right: 80px;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
|
border: 1px solid #DEDEDE;
|
||||||
|
|
||||||
&::-webkit-scrollbar {
|
&::-webkit-scrollbar {
|
||||||
width: 8px;
|
width: 8px;
|
||||||
@@ -104,6 +112,7 @@
|
|||||||
border-radius: 1px;
|
border-radius: 1px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all linear .1s;
|
transition: all linear .1s;
|
||||||
|
margin-right: 30px;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
@@ -167,6 +176,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.entity__search .tag-search {
|
||||||
|
padding-left: 65px;
|
||||||
|
}
|
||||||
|
|
||||||
.el-popover.my-popper-class {
|
.el-popover.my-popper-class {
|
||||||
width: auto !important;
|
width: auto !important;
|
||||||
|
|||||||
@@ -13,11 +13,16 @@
|
|||||||
color: #ccc;
|
color: #ccc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.entity__search {
|
||||||
|
.CodeMirror {
|
||||||
|
padding-left: 60px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* PADDING */
|
/* PADDING */
|
||||||
|
|
||||||
.CodeMirror-lines {
|
.CodeMirror-lines {
|
||||||
padding: 11px 5px; /* Vertical padding around content */
|
padding: 9px 5px; /* Vertical padding around content */
|
||||||
}
|
}
|
||||||
.CodeMirror pre.CodeMirror-line,
|
.CodeMirror pre.CodeMirror-line,
|
||||||
.CodeMirror pre.CodeMirror-line-like {
|
.CodeMirror pre.CodeMirror-line-like {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
&>div {
|
&>div {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cn-header {
|
.cn-header {
|
||||||
|
|||||||
@@ -83,6 +83,71 @@
|
|||||||
|
|
||||||
.entity-detail-event-block {
|
.entity-detail-event-block {
|
||||||
width: calc(100% - 2px);
|
width: calc(100% - 2px);
|
||||||
|
.behavior-pattern {
|
||||||
|
height:100% ;
|
||||||
|
position: relative;
|
||||||
|
display:flex;
|
||||||
|
flex-direction: row;
|
||||||
|
.behavior-pattern-legend {
|
||||||
|
display:flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100%;
|
||||||
|
padding:10px 18px 10px 18px;
|
||||||
|
width:400px;
|
||||||
|
.behavior-pattern-legend__item {
|
||||||
|
display:flex;
|
||||||
|
flex-direction: row;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #353636;
|
||||||
|
line-height: 12px;
|
||||||
|
margin-bottom:11px;
|
||||||
|
.legend-icon {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
margin: 3px 8px 0 0;
|
||||||
|
border-radius: 1px;;
|
||||||
|
}
|
||||||
|
.legend-name {
|
||||||
|
width:180px;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
.legend-value{
|
||||||
|
display: flex;
|
||||||
|
justify-content: left;
|
||||||
|
margin-left:20px;
|
||||||
|
width:90px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
.legend-percent {
|
||||||
|
margin-left:20px;
|
||||||
|
width:70px;
|
||||||
|
justify-content: left;
|
||||||
|
display: flex;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.behavior-pattern-chart{
|
||||||
|
height: calc(100% - 50px);
|
||||||
|
width:calc(100% - 400px);
|
||||||
|
position: relative
|
||||||
|
}
|
||||||
|
.chart-bottom-dot__left {
|
||||||
|
position: absolute;
|
||||||
|
height: 0;
|
||||||
|
width: 195px;
|
||||||
|
border-bottom: 1px dashed #d3d3d3;
|
||||||
|
top: 319px;left: 575px;
|
||||||
|
}
|
||||||
|
.chart-bottom-dot__right {
|
||||||
|
position: absolute;
|
||||||
|
height: 0;
|
||||||
|
width: 195px;
|
||||||
|
border-bottom: 1px dashed #d3d3d3;
|
||||||
|
top: 319px;left: 830px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.entity-detail-event-error {
|
.entity-detail-event-error {
|
||||||
|
|||||||
@@ -128,24 +128,25 @@ $blue: #046ECA;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.link-statistical-dimension {
|
||||||
.row-dot {
|
.row-dot {
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.green-dot {
|
.green-dot {
|
||||||
width: 7px;
|
width: 7px;
|
||||||
height: 7px;
|
height: 7px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: #749F4D;
|
background: #749F4D;
|
||||||
}
|
}
|
||||||
|
|
||||||
.red-dot {
|
.red-dot {
|
||||||
width: 7px;
|
width: 7px;
|
||||||
height: 7px;
|
height: 7px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: #E26154;
|
background: #E26154;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-popover-up, .item-popover-down {
|
.item-popover-up, .item-popover-down {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -31,8 +31,12 @@
|
|||||||
line-height: 16px;
|
line-height: 16px;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
|
|
||||||
|
.block-mode-icon1 {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
.block-mode-icon {
|
.block-mode-icon {
|
||||||
font-size: 16px;
|
font-size: 15px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,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;
|
||||||
@@ -208,9 +213,25 @@
|
|||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
padding: 0 14px;
|
padding: 0 14px;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.form-setting__btn1 {
|
.btn1 {
|
||||||
|
margin-right: 10px;
|
||||||
|
.el-button {
|
||||||
|
background: #F5F6F7;
|
||||||
|
border: 1px solid rgba(215,215,215,1);
|
||||||
|
color: #353636;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.policy-form__footer__btn {
|
||||||
|
justify-content: center;
|
||||||
|
margin-top: 8px;
|
||||||
|
|
||||||
|
.btn1 {
|
||||||
|
margin-right: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.form-setting__btn1, .policy-form__footer__btn {
|
||||||
.el-button {
|
.el-button {
|
||||||
padding: 0 11px !important;
|
padding: 0 11px !important;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,9 +10,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.detection-form-content {
|
.detection-form-content {
|
||||||
height: 100%;
|
height: calc(100% - 92px);
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
padding-bottom: 40px;
|
padding-bottom: 20px;
|
||||||
|
|
||||||
.detection-form-collapse {
|
.detection-form-collapse {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
@@ -101,6 +101,12 @@
|
|||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
|
|
||||||
|
.policy-form-item {
|
||||||
|
.el-form-item__error {
|
||||||
|
width: 260px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-input--mini .el-input__inner {
|
.el-input--mini .el-input__inner {
|
||||||
@@ -124,6 +130,12 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.policy-form-trigger {
|
||||||
|
.el-collapse-item__content {
|
||||||
|
padding-bottom: 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-input--mini, .el-input--mini .el-input__inner {
|
.el-input--mini, .el-input--mini .el-input__inner {
|
||||||
@@ -137,4 +149,13 @@
|
|||||||
padding-bottom: 20px;
|
padding-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.policy-form__footer {
|
||||||
|
width: calc(100% + 40px);
|
||||||
|
height: 60px;
|
||||||
|
margin-left: -20px;
|
||||||
|
box-shadow: 0 -1px 4px 0 rgba(0,0,0,0.10);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
background-color: rgba(0, 0, 0, 0.16) !important;
|
background-color: rgba(0, 0, 0, 0.16) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.detection-drawer-title, .basic-function-value, basic-description-value {
|
.detection-drawer-title, .basic-function-value, basic-description-value, .drawer-trigger-minutes {
|
||||||
font-family: NotoSansSChineseRegular;
|
font-family: NotoSansSChineseRegular;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #717171;
|
color: #717171;
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -58,6 +67,10 @@
|
|||||||
color: #046ECA;
|
color: #046ECA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.drawer-trigger-minutes {
|
||||||
|
color: #353636;
|
||||||
|
}
|
||||||
|
|
||||||
.detection-drawer-collapse {
|
.detection-drawer-collapse {
|
||||||
background: #FFFFFF;
|
background: #FFFFFF;
|
||||||
border: 1px solid rgba(226, 229, 236, 1);
|
border: 1px solid rgba(226, 229, 236, 1);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -59,6 +59,7 @@
|
|||||||
width: 5px;
|
width: 5px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
|
margin-top: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cn-detection__row {
|
.cn-detection__row {
|
||||||
@@ -88,6 +89,7 @@
|
|||||||
margin-left: 12px;
|
margin-left: 12px;
|
||||||
font-size: xx-small;
|
font-size: xx-small;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
margin-top: -1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.circle {
|
.circle {
|
||||||
@@ -95,7 +97,7 @@
|
|||||||
height: 10px;
|
height: 10px;
|
||||||
border: 2px solid #da5656;
|
border: 2px solid #da5656;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
margin-top: 4px;
|
margin-top: 1px;
|
||||||
margin-right: 12px;
|
margin-right: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,10 +121,12 @@
|
|||||||
margin-right: 12px;
|
margin-right: 12px;
|
||||||
}
|
}
|
||||||
.detection-event-severity-block {
|
.detection-event-severity-block {
|
||||||
|
height: 20px;
|
||||||
|
line-height: 20px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #046EC9;
|
color: #046EC9;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
padding: 2px 10px;
|
padding: 0 10px;
|
||||||
background: rgba(56,172,210,0.10);
|
background: rgba(56,172,210,0.10);
|
||||||
border: 1px solid #ADC7DB;
|
border: 1px solid #ADC7DB;
|
||||||
box-shadow: 0 2px 4px 0 rgba(51,51,51,0.02);
|
box-shadow: 0 2px 4px 0 rgba(51,51,51,0.02);
|
||||||
@@ -145,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;
|
||||||
@@ -168,6 +172,11 @@
|
|||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.basic-info__item1 {
|
||||||
|
span: {
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.show-detail {
|
.show-detail {
|
||||||
@@ -262,3 +271,8 @@
|
|||||||
color: #FFD82D !important;
|
color: #FFD82D !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.detection-list-icon {
|
||||||
|
margin-top: 1px;
|
||||||
|
font-size: 16px !important;
|
||||||
|
}
|
||||||
|
|||||||
@@ -60,12 +60,14 @@
|
|||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
|
|
||||||
.row__content {
|
.row__content, .row__content1 {
|
||||||
display: flex;
|
display: flex;
|
||||||
//color: #3976CB;
|
//color: #3976CB;
|
||||||
color: #046ECA;
|
color: #046ECA;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
&.row__content--link {
|
&.row__content--link {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
@@ -87,6 +89,21 @@
|
|||||||
font-style: italic;
|
font-style: italic;
|
||||||
color: #1890FF;
|
color: #1890FF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.row__content__icon {
|
||||||
|
font-size: 14px;
|
||||||
|
margin-right: 5px;
|
||||||
|
color: #1890FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row__content__svg {
|
||||||
|
font-size: 14px;
|
||||||
|
margin-right: 7px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.row__content1 {
|
||||||
|
display: block;
|
||||||
|
padding-right: 50px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -186,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;
|
||||||
@@ -215,13 +233,20 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.row__tag {
|
.row__tag, .row__tag__level {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 4px;
|
padding: 0 4px;
|
||||||
//color: white;
|
//color: white;
|
||||||
}
|
}
|
||||||
|
.row__tag__level {
|
||||||
|
height: 16px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
.performance-event-remark {
|
.performance-event-remark {
|
||||||
font-family: NotoSansSChineseRegular;
|
font-family: NotoSansSChineseRegular;
|
||||||
|
|||||||
@@ -61,22 +61,19 @@
|
|||||||
|
|
||||||
.detection-tag-status0 {
|
.detection-tag-status0 {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-family: NotoSansHans-Medium;
|
|
||||||
background: rgba(113, 113, 113, 0.12);
|
background: rgba(113, 113, 113, 0.12);
|
||||||
color: #717171;
|
color: #717171;
|
||||||
padding: 0 12px;
|
padding: 0 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.detection-tag-status1 {
|
.detection-tag-status1 {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
font-family: NotoSansHans-Medium;
|
|
||||||
background: rgba(126, 159, 84, 0.12);
|
background: rgba(126, 159, 84, 0.12);
|
||||||
color: #7E9F54;
|
color: #7E9F54;
|
||||||
padding: 0 8px;
|
padding: 0 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.detection-table-library {
|
.detection-table-library {
|
||||||
font-family: NotoSansSChineseRegular;
|
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #046ECA;
|
color: #046ECA;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
|||||||
@@ -4,6 +4,18 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
.detections {
|
||||||
|
.entity__pagination{
|
||||||
|
bottom: 9px;
|
||||||
|
height: 40px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.detections__container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
.detection__list {
|
.detection__list {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -349,6 +349,25 @@
|
|||||||
.data-score-green {
|
.data-score-green {
|
||||||
background: #749F4D;
|
background: #749F4D;
|
||||||
}
|
}
|
||||||
|
.score-dot {
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #CBCBCB;
|
||||||
|
margin-right: 4px;
|
||||||
|
|
||||||
|
&.score-dot--red {
|
||||||
|
background-color: #E26154;
|
||||||
|
}
|
||||||
|
&.score-dot--yellow {
|
||||||
|
background-color: #E5A219;
|
||||||
|
}
|
||||||
|
&.score-dot--green {
|
||||||
|
background-color: #749F4D;
|
||||||
|
}
|
||||||
|
}
|
||||||
height:24px;
|
height:24px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #046ECA;
|
color: #046ECA;
|
||||||
|
|||||||
@@ -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;
|
||||||
@@ -174,6 +196,26 @@
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #353636;
|
color: #353636;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
|
||||||
|
.score-dot {
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #CBCBCB;
|
||||||
|
margin-right: 4px;
|
||||||
|
|
||||||
|
&.score-dot--red {
|
||||||
|
background-color: #E26154;
|
||||||
|
}
|
||||||
|
&.score-dot--yellow {
|
||||||
|
background-color: #E5A219;
|
||||||
|
}
|
||||||
|
&.score-dot--green {
|
||||||
|
background-color: #749F4D;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -38,8 +38,8 @@
|
|||||||
margin-right:20px;
|
margin-right:20px;
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.top-tool-btn--user_defined_library {
|
.top-tool-btn--user_defined_library {
|
||||||
background: #F5F8FA;
|
background: #F5F8FA;
|
||||||
border: 1px solid rgba(222,222,222,1);
|
border: 1px solid rgba(222,222,222,1);
|
||||||
box-shadow: 0px 2px 4px 0px rgba(51,51,51,0.02);
|
box-shadow: 0px 2px 4px 0px rgba(51,51,51,0.02);
|
||||||
@@ -58,13 +58,13 @@
|
|||||||
font-size:14px !important;
|
font-size:14px !important;
|
||||||
margin-right:6px;
|
margin-right:6px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.top-tool-btn--user_defined_library:hover {
|
.top-tool-btn--user_defined_library:hover {
|
||||||
border: 1px solid $--border-color-primary;
|
border: 1px solid $--border-color-primary;
|
||||||
background-color: $--button-gray-hover-background-color;
|
background-color: $--button-gray-hover-background-color;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.knowledge-base-built-in__content {
|
.knowledge-base-built-in__content {
|
||||||
display:flex;
|
display:flex;
|
||||||
flex-direction:row;
|
flex-direction:row;
|
||||||
padding:12px 0 20px 20px;
|
padding:12px 0 20px 20px;
|
||||||
@@ -356,8 +356,8 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.knowledge-base-user-defined__content {
|
.knowledge-base-user-defined__content {
|
||||||
display:flex;
|
display:flex;
|
||||||
flex-direction:row;
|
flex-direction:row;
|
||||||
padding:12px 20px 20px 20px;
|
padding:12px 20px 20px 20px;
|
||||||
@@ -962,35 +962,35 @@
|
|||||||
box-shadow: 0 -1px 4px 0 rgba(0,0,0,0.07);
|
box-shadow: 0 -1px 4px 0 rgba(0,0,0,0.07);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.reference-tag__tip {
|
.reference-tag__tip {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #575757;
|
color: #575757;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
min-width:130px;
|
min-width:130px;
|
||||||
max-height:240px;
|
max-height:240px;
|
||||||
overflow-y:auto;
|
overflow-y:auto;
|
||||||
cursor:pointer;
|
cursor:pointer;
|
||||||
.reference-tag {
|
.reference-tag {
|
||||||
height:24px;
|
height:24px;
|
||||||
min-height:24px;
|
min-height:24px;
|
||||||
padding-top: 3px;
|
padding-top: 3px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.edit-knowledge-base {
|
.edit-knowledge-base {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
.edit-knowledge-base__header {
|
.edit-knowledge-base__header {
|
||||||
padding: 30px 0 30px 20px;
|
padding: 30px 0 30px 20px;
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
color: #353636;
|
color: #353636;
|
||||||
}
|
}
|
||||||
.edit-knowledge-base__body {
|
.edit-knowledge-base__body {
|
||||||
display: flex;
|
display: flex;
|
||||||
height: calc(100% - 147px);
|
height: calc(100% - 147px);
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
@@ -1156,7 +1156,6 @@ height: 100%;
|
|||||||
.el-form {
|
.el-form {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
width: 620px;
|
width: 620px;
|
||||||
|
|
||||||
label {
|
label {
|
||||||
padding-bottom: 6px;
|
padding-bottom: 6px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
@@ -1191,6 +1190,7 @@ height: 100%;
|
|||||||
|
|
||||||
.el-input__inner {
|
.el-input__inner {
|
||||||
background-color: white !important;
|
background-color: white !important;
|
||||||
|
padding-left: 22px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1379,8 +1379,8 @@ height: 100%;
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.edit-knowledge-base__footer {
|
.edit-knowledge-base__footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -1419,142 +1419,47 @@ height: 100%;
|
|||||||
opacity: .6;
|
opacity: .6;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.addTagBtn {
|
.addTagBtn {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 9px;
|
bottom: 9px;
|
||||||
height:24px !important;
|
height:24px !important;
|
||||||
min-height: 24px !important;
|
min-height: 24px !important;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #353636;
|
color: #353636;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
width: 598px;
|
width: 598px;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
background: rgb(245, 248, 250);
|
background: rgb(245, 248, 250);
|
||||||
border: 1px #DEDEDE solid;
|
border: 1px #DEDEDE solid;
|
||||||
padding: 0 !important;
|
padding: 0 !important;
|
||||||
box-shadow: 0 2px 4px 0 rgba(51,51,51,0.02);
|
box-shadow: 0 2px 4px 0 rgba(51,51,51,0.02);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
font-family:NotoSansHans-Medium !important;
|
font-family:NotoSansHans-Medium !important;
|
||||||
|
|
||||||
.add-tag-btn {
|
.add-tag-btn {
|
||||||
color: #575757 !important;
|
color: #575757 !important;
|
||||||
font-size: 9px !important;
|
font-size: 9px !important;
|
||||||
margin: 0 8px 2px 8px;
|
margin: 0 8px 2px 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
i {
|
i {
|
||||||
color: #699DC9 !important;
|
color: #699DC9 !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
font-family:NotoSansHans-Medium !important;
|
font-family:NotoSansHans-Medium !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.del-model-hint {
|
.del-model-hint {
|
||||||
display:flex;
|
|
||||||
flex-direction: column;
|
|
||||||
padding-bottom:0px !important;
|
|
||||||
width:480px !important;
|
|
||||||
height:300px !important;
|
|
||||||
.el-dialog__header{
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
border-bottom:1px solid #eee;
|
|
||||||
height:42px;
|
|
||||||
min-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-dialog__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-dialog__title {
|
|
||||||
font-size: 14px !important;
|
|
||||||
color: #353636;
|
|
||||||
letter-spacing: 0;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.el-dialog__body {
|
|
||||||
height:206px;
|
|
||||||
min-height:206px;
|
|
||||||
font-size: 14px;
|
|
||||||
color: #353636;
|
|
||||||
letter-spacing: 0;
|
|
||||||
line-height: 22px;
|
|
||||||
font-weight: 400;
|
|
||||||
padding-top:8px;
|
|
||||||
padding-right:20px;
|
|
||||||
padding-left:20px;
|
|
||||||
.dialog-message {
|
|
||||||
padding-left:0px !important;
|
|
||||||
padding-right:0px !important;
|
|
||||||
}
|
|
||||||
.dialog-table {
|
|
||||||
margin-top:10px;
|
|
||||||
}
|
|
||||||
.el-checkbox__input.is-checked .el-checkbox__inner {
|
|
||||||
background-color: #38ACD2;
|
|
||||||
border-color: #38ACD2;
|
|
||||||
}
|
|
||||||
.el-checkbox__input.is-indeterminate .el-checkbox__inner {
|
|
||||||
background-color: #38ACD2;
|
|
||||||
border-color: #38ACD2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.el-dialog__footer {
|
|
||||||
height:52px;
|
|
||||||
min-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 {
|
|
||||||
padding:8px 21px !important;
|
|
||||||
line-height: 12px;
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 500;
|
|
||||||
min-height: 28px;
|
|
||||||
}
|
|
||||||
.el-button:nth-child(1) {
|
|
||||||
margin-right:20px;
|
|
||||||
width:80px;
|
|
||||||
height:28px;
|
|
||||||
color: #353636;
|
|
||||||
background: #F5F6F7;
|
|
||||||
border: 1px solid rgba(215,215,215,1);
|
|
||||||
border-radius: 2px;
|
|
||||||
}
|
|
||||||
.el-button:nth-child(2) {
|
|
||||||
width:80px;
|
|
||||||
height:28px;
|
|
||||||
margin-right:20px;
|
|
||||||
margin-left:0px !important;
|
|
||||||
background-color:#2d8cf0;
|
|
||||||
border-color:#2d8cf0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.update-knowledge-tip {
|
|
||||||
display:flex;
|
display:flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding-bottom: 0 !important;
|
padding-bottom:0px !important;
|
||||||
width: 480px !important;
|
width:480px !important;
|
||||||
|
height:300px !important;
|
||||||
.el-dialog__header{
|
.el-dialog__header{
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@@ -1587,8 +1492,8 @@ height:300px !important;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.el-dialog__body {
|
.el-dialog__body {
|
||||||
height:96px;
|
height:206px;
|
||||||
min-height:96px;
|
min-height:206px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #353636;
|
color: #353636;
|
||||||
letter-spacing: 0;
|
letter-spacing: 0;
|
||||||
@@ -1598,9 +1503,135 @@ height:300px !important;
|
|||||||
padding-right:20px;
|
padding-right:20px;
|
||||||
padding-left:20px;
|
padding-left:20px;
|
||||||
.dialog-message {
|
.dialog-message {
|
||||||
padding-left: 0 !important;
|
padding-left:0px !important;
|
||||||
padding-right: 0 !important;
|
padding-right:0px !important;
|
||||||
}
|
}
|
||||||
|
.dialog-table {
|
||||||
|
margin-top:10px;
|
||||||
|
}
|
||||||
|
.el-checkbox__input.is-checked .el-checkbox__inner {
|
||||||
|
background-color: #38ACD2;
|
||||||
|
border-color: #38ACD2;
|
||||||
|
}
|
||||||
|
.el-checkbox__input.is-indeterminate .el-checkbox__inner {
|
||||||
|
background-color: #38ACD2;
|
||||||
|
border-color: #38ACD2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.el-dialog__footer {
|
||||||
|
height:52px;
|
||||||
|
min-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 {
|
||||||
|
padding:8px 21px !important;
|
||||||
|
line-height: 12px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
min-height: 28px;
|
||||||
|
}
|
||||||
|
.el-button:nth-child(1) {
|
||||||
|
margin-right:20px;
|
||||||
|
width:80px;
|
||||||
|
height:28px;
|
||||||
|
color: #353636;
|
||||||
|
background: #F5F6F7;
|
||||||
|
border: 1px solid rgba(215,215,215,1);
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
.el-button:nth-child(2) {
|
||||||
|
width:80px;
|
||||||
|
height:28px;
|
||||||
|
margin-right:20px;
|
||||||
|
margin-left:0px !important;
|
||||||
|
background-color:#2d8cf0;
|
||||||
|
border-color:#2d8cf0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.confirm-knowledge-switch {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.el-dialog__header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
height: 42px;
|
||||||
|
min-height: 42px;
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 14px;
|
||||||
|
background: #F7F7F7;
|
||||||
|
|
||||||
|
.el-dialog__headerbtn {
|
||||||
|
display: flex !important;
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding-right: 5px !important;
|
||||||
|
top: 16px;
|
||||||
|
right: 10px;
|
||||||
|
i {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.el-dialog__title {
|
||||||
|
font-size: 14px !important;
|
||||||
|
color: #353636;
|
||||||
|
letter-spacing: 0;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.update-knowledge-tip, .confirm-knowledge-switch {
|
||||||
|
display:flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding-bottom: 0 !important;
|
||||||
|
|
||||||
|
.el-dialog__header{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
border-bottom:1px solid #eee;
|
||||||
|
height: 42px;
|
||||||
|
min-height:42px;
|
||||||
|
background: #F7F7F7;
|
||||||
|
box-shadow: 0 1px 0 0 rgba(53,54,54,0.08);
|
||||||
|
padding-left: 20px;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 14px;
|
||||||
|
|
||||||
|
.el-dialog__headerbtn {
|
||||||
|
display: flex !important;
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding-right: 5px !important;
|
||||||
|
top: 16px;
|
||||||
|
right: 10px;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.el-dialog__title {
|
||||||
|
font-size: 14px !important;
|
||||||
|
color: #353636;
|
||||||
|
letter-spacing: 0;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.el-dialog__body {
|
||||||
|
height:96px;
|
||||||
|
min-height:96px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #353636;
|
||||||
|
letter-spacing: 0;
|
||||||
|
line-height: 22px;
|
||||||
|
padding-top:12px;
|
||||||
|
padding-right: 20px;
|
||||||
|
padding-left: 20px;
|
||||||
}
|
}
|
||||||
.el-dialog__footer {
|
.el-dialog__footer {
|
||||||
height:52px;
|
height:52px;
|
||||||
@@ -1645,7 +1676,8 @@ height:300px !important;
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding-bottom:0 !important;
|
padding-bottom:0 !important;
|
||||||
width: 1080px !important;
|
width: 1080px !important;
|
||||||
height: 75vh;
|
height: 90vh;
|
||||||
|
margin-top:5vh !important;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
&.update-knowledge--upload {
|
&.update-knowledge--upload {
|
||||||
height: auto;
|
height: auto;
|
||||||
@@ -1699,6 +1731,85 @@ height:300px !important;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.knowledge-update__tab {
|
||||||
|
position:relative;
|
||||||
|
.update-log-tab {
|
||||||
|
.el-tabs__header {
|
||||||
|
margin-bottom:10px;
|
||||||
|
.el-tabs__active-bar {
|
||||||
|
background-color:#046ECA;
|
||||||
|
height:2px;
|
||||||
|
}
|
||||||
|
.el-tabs__item {
|
||||||
|
font-family: NotoSansSC-Bold;
|
||||||
|
font-size: 14px;
|
||||||
|
//color: #353636;
|
||||||
|
font-weight: 700;
|
||||||
|
padding:0 16px 0 0;
|
||||||
|
}
|
||||||
|
.el-tabs__item:hover {
|
||||||
|
color:#353636;
|
||||||
|
}
|
||||||
|
.el-tabs__item.is-active {
|
||||||
|
color: #046ECA;
|
||||||
|
}
|
||||||
|
.el-tabs__nav-wrap::after {
|
||||||
|
height:1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.update-title {
|
||||||
|
line-height: 14px;
|
||||||
|
font-family: NotoSansSC-Bold;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #353636;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.update-operate {
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
right: 0px;
|
||||||
|
|
||||||
|
height:28px;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content:center;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
.top-tool-btn--update {
|
||||||
|
background-color: #38ACD2 !important;
|
||||||
|
padding-left:7px;
|
||||||
|
padding-right:7px;
|
||||||
|
color:#FFFFFF;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
border: 1px solid rgba(46,136,166,0.85);
|
||||||
|
border-radius: 2px;
|
||||||
|
line-height: 28px;
|
||||||
|
height:28px;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
i {
|
||||||
|
color: #FFFFFF;
|
||||||
|
font-size:14px !important;
|
||||||
|
margin-right:5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.top-tool-btn--update:disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
opacity: 0.66;
|
||||||
|
i {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.top-tool-btn--update:hover {
|
||||||
|
background-color: #57B8D9 !important;
|
||||||
|
border-color: #2E88A6 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
.knowledge-update {
|
.knowledge-update {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@@ -1741,6 +1852,12 @@ height:300px !important;
|
|||||||
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;
|
||||||
@@ -1789,15 +1906,20 @@ height:300px !important;
|
|||||||
.update-dialog__table {
|
.update-dialog__table {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
border-radius: 0.28571rem;
|
border-radius: 0.28571rem;
|
||||||
max-height:calc(75vh - 190px);
|
height: calc(100% - 125px);//dialog为屏幕的90% - 表格以上内容的高度 - pishon3柱状图的高度 - 表格和柱状图之间的距离 - 底部留白的距离
|
||||||
.el-table--border th, .el-table--border td {
|
.el-table--border th, .el-table--border td {
|
||||||
border-right: none;
|
border-right: none;
|
||||||
}
|
}
|
||||||
.el-table__body-wrapper {
|
.el-table__body-wrapper {
|
||||||
height:fit-content;
|
height: calc(100% - 48px);
|
||||||
max-height: calc(75vh - 230px);
|
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
&.update-dialog__table--psiphon3 {
|
||||||
|
height: calc(90vh - 190px - 200px - 50px - 10px);
|
||||||
|
}
|
||||||
|
&.update-dialog__table--system-user {
|
||||||
|
height: calc(100% - 139px);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.update-knowledge-form {
|
.update-knowledge-form {
|
||||||
.el-upload {
|
.el-upload {
|
||||||
@@ -1871,4 +1993,173 @@ height:300px !important;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.psiphon3{
|
||||||
|
display:flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-top:25px;
|
||||||
|
.psiphon3-title {
|
||||||
|
font-family: NotoSansSC-Medium;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #353636;
|
||||||
|
letter-spacing: 0;
|
||||||
|
line-height: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
.psiphon3-bar {
|
||||||
|
height: 200px;
|
||||||
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
border: 1px solid #E2E5EC;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-top:10px;
|
||||||
|
//min-height:250px;
|
||||||
|
.chart-drawing {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
.echarts-tooltip.echarts-tooltip-dark {
|
||||||
|
.cn-chart-body {
|
||||||
|
display: flex;
|
||||||
|
.cn-chart-tooltip {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1;
|
||||||
|
.cn-chart-tooltip-box {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
.cn-chart-tooltip-value.cn-chart-tooltip__color {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #353636;
|
||||||
|
line-height: 21px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.bar-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
//height: 73px;
|
||||||
|
margin-right:20px;
|
||||||
|
.bar-select.bar-header-right {
|
||||||
|
display: flex;
|
||||||
|
//flex: 1;
|
||||||
|
.bar-select__operation {
|
||||||
|
.el-input__inner {
|
||||||
|
width: 132px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.bar-select-time {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
|
.bar-select__operation {
|
||||||
|
height: 24px;
|
||||||
|
margin-left: 3px;
|
||||||
|
box-shadow: none;
|
||||||
|
border-radius: 2px;
|
||||||
|
.cn-icon-Data {
|
||||||
|
color: #353636;
|
||||||
|
}
|
||||||
|
.el-input__inner {
|
||||||
|
padding-left: 4px;
|
||||||
|
line-height: 24px;
|
||||||
|
height: 24px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #353636;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
.el-input__suffix {
|
||||||
|
display: flex;
|
||||||
|
.el-input__suffix-inner {
|
||||||
|
line-height: 24px;
|
||||||
|
.el-select__caret {
|
||||||
|
line-height: 24px;
|
||||||
|
width: 16px;
|
||||||
|
color: #353636;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.bar-header-left {
|
||||||
|
.bar-value-active {
|
||||||
|
position: absolute;
|
||||||
|
height: 4px;
|
||||||
|
border-radius: 4px 0 0 0;
|
||||||
|
background: #046ECA;
|
||||||
|
top: 0;
|
||||||
|
z-index: 1;
|
||||||
|
transition: all linear .2s;
|
||||||
|
}
|
||||||
|
.bar-value {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #717171;
|
||||||
|
font-weight: 400;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
.is-active {
|
||||||
|
color: #353636;
|
||||||
|
}
|
||||||
|
.bar-value-tabs.mousemove-cursor {
|
||||||
|
border-top: 4px solid #D3D0D8;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
.bar-value-tabs {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 10px 0 0 20px;
|
||||||
|
border-top: 4px solid transparent;
|
||||||
|
width:88px;
|
||||||
|
.bar-value-tabs-name {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
.tabs-name {
|
||||||
|
flex: 1;
|
||||||
|
padding-left: 19px;
|
||||||
|
}
|
||||||
|
.total,.active,.new {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
position: absolute;
|
||||||
|
top: 6px;
|
||||||
|
}
|
||||||
|
.total {
|
||||||
|
background: #00A7AB;
|
||||||
|
}
|
||||||
|
.active {
|
||||||
|
background: #7FA054;
|
||||||
|
}
|
||||||
|
.new {
|
||||||
|
background: #98709B;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
.knowledge-color {
|
||||||
|
display:flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
.knowledge-color__icon {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 2px;
|
||||||
|
margin-right:6px;
|
||||||
|
margin-left:2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.info {
|
||||||
|
background-color:rgb(119,131,145)
|
||||||
|
}
|
||||||
|
.benign {
|
||||||
|
background-color:rgb(116,159,77)
|
||||||
|
}
|
||||||
|
.malicious {
|
||||||
|
background-color:rgb(226,97,84)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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=1693386443164') format('woff2'),
|
src: url('iconfont.woff2?t=1699411209748') format('woff2'),
|
||||||
url('iconfont.woff?t=1693386443164') format('woff'),
|
url('iconfont.woff?t=1699411209748') format('woff'),
|
||||||
url('iconfont.ttf?t=1693386443164') format('truetype');
|
url('iconfont.ttf?t=1699411209748') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
.cn-icon {
|
.cn-icon {
|
||||||
@@ -13,6 +13,22 @@
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cn-icon-related:before {
|
||||||
|
content: "\e640";
|
||||||
|
}
|
||||||
|
|
||||||
|
.cn-icon-indicator-match:before {
|
||||||
|
content: "\e80c";
|
||||||
|
}
|
||||||
|
|
||||||
|
.cn-icon-threshold:before {
|
||||||
|
content: "\e80d";
|
||||||
|
}
|
||||||
|
|
||||||
|
.cn-icon-behavior:before {
|
||||||
|
content: "\e61c";
|
||||||
|
}
|
||||||
|
|
||||||
.cn-icon-category-group:before {
|
.cn-icon-category-group:before {
|
||||||
content: "\e6c7";
|
content: "\e6c7";
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -17,7 +17,7 @@
|
|||||||
size="mini"
|
size="mini"
|
||||||
v-model="meta.column.label"
|
v-model="meta.column.label"
|
||||||
ref="columnSelect"
|
ref="columnSelect"
|
||||||
:placeholder="meta.column.label || ''"
|
:placeholder="meta.column.label || ' '"
|
||||||
@blur="columnBlur(meta, index)"
|
@blur="columnBlur(meta, index)"
|
||||||
@change="(value) => selectColumn(value, meta)"
|
@change="(value) => selectColumn(value, meta)"
|
||||||
>
|
>
|
||||||
@@ -90,8 +90,8 @@
|
|||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<div class="tag-search__add" @click="addCondition">{{$t('entities.advancedSearch.add')}}</div>
|
<div class="tag-search__add" @click="addCondition">{{$t('entities.advancedSearch.add')}}</div>
|
||||||
<div class="search__suffixes search__suffixes--tag-mode">
|
<div class="search__suffixes search__suffixes--tag-mode search__suffixes--tag-mode__block" :class="showList ? '' : 'entity-explorer-home'">
|
||||||
<div class="search__suffix" style="margin-right: 12px">
|
<span class="search__suffix">
|
||||||
<el-popover
|
<el-popover
|
||||||
popper-class="my-popper-class"
|
popper-class="my-popper-class"
|
||||||
placement="top"
|
placement="top"
|
||||||
@@ -102,13 +102,13 @@
|
|||||||
<i class="cn-icon cn-icon-search-normal" @click="changeMode"></i>
|
<i class="cn-icon cn-icon-search-normal" @click="changeMode"></i>
|
||||||
</template>
|
</template>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
</div>
|
</span>
|
||||||
<div v-show="metaList.length>0" class="search__suffix-close" @click="cleanMetaList">
|
<span v-show="metaList.length>0" class="search__suffix search__suffix-close" @click="cleanMetaList">
|
||||||
<i class="el-icon-error"></i>
|
<i class="el-icon-error"></i>
|
||||||
</div>
|
</span>
|
||||||
<div class="search__suffix" :class="showList ? 'new-search__suffix' : 'entity-explorer-search'" @click="search">
|
<span class="search__suffix" @click="search">
|
||||||
<i class="el-icon-search"></i>
|
<i class="el-icon-search"></i>
|
||||||
</div>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -202,6 +202,7 @@ export default {
|
|||||||
if (this.isCustomized(value)) {
|
if (this.isCustomized(value)) {
|
||||||
meta.column.type = columnType.fullText
|
meta.column.type = columnType.fullText
|
||||||
meta.column.label = value
|
meta.column.label = value
|
||||||
|
meta.column.isFullText = true
|
||||||
meta.resetOperator()
|
meta.resetOperator()
|
||||||
meta.resetValue()
|
meta.resetValue()
|
||||||
} else {
|
} else {
|
||||||
@@ -248,6 +249,7 @@ export default {
|
|||||||
if (meta.column && meta.column.type === 'fullText') {
|
if (meta.column && meta.column.type === 'fullText') {
|
||||||
meta.operator.value = '='
|
meta.operator.value = '='
|
||||||
meta.column.show = false
|
meta.column.show = false
|
||||||
|
meta.column.isFullText = true
|
||||||
meta.operator.show = false
|
meta.operator.show = false
|
||||||
const label = JSON.parse(JSON.stringify(meta.column.label))
|
const label = JSON.parse(JSON.stringify(meta.column.label))
|
||||||
meta.column.label = parser.getEntityTypeByValue(meta.column.label)
|
meta.column.label = parser.getEntityTypeByValue(meta.column.label)
|
||||||
@@ -461,13 +463,21 @@ export default {
|
|||||||
if (this.metaList.length > 0) {
|
if (this.metaList.length > 0) {
|
||||||
const parser = new Parser(this.columnList)
|
const parser = new Parser(this.columnList)
|
||||||
const errorList = parser.validateMeta(this.metaList)
|
const errorList = parser.validateMeta(this.metaList)
|
||||||
|
const keywordList = []
|
||||||
|
this.metaList.forEach(item => {
|
||||||
|
if (item.column && item.column.isFullText) {
|
||||||
|
keywordList.push({ type: 'fullText', value: item.value.value })
|
||||||
|
} else if (item.column && !item.column.isFullText) {
|
||||||
|
keywordList.push({ type: item.column.type, value: item.value.value })
|
||||||
|
}
|
||||||
|
})
|
||||||
if (_.isEmpty(errorList)) {
|
if (_.isEmpty(errorList)) {
|
||||||
const strObj = parser.handleMetaListToStr(this.metaList)
|
const strObj = parser.handleMetaListToStr(this.metaList)
|
||||||
const str = strObj.str ? strObj.str : strObj
|
const str = strObj.str ? strObj.str : strObj
|
||||||
const str2 = strObj.str2 ? strObj.str2 : strObj
|
const str2 = strObj.str2 ? strObj.str2 : strObj
|
||||||
// str为将metaList转成字符串的值,str2为地址栏展示的值
|
// str为将metaList转成字符串的值,str2为地址栏展示的值
|
||||||
const key = parser.handleEntityTypeByStr(str)
|
const key = parser.handleEntityTypeByStr(str)
|
||||||
this.$emit('search', { ...parser.parseStr(key), str: str2 })
|
this.$emit('search', { ...parser.parseStr(key), str: str2, keywordList: keywordList })
|
||||||
} else {
|
} else {
|
||||||
this.$message.error(handleErrorTip(errorList[0]))
|
this.$message.error(handleErrorTip(errorList[0]))
|
||||||
}
|
}
|
||||||
@@ -555,6 +565,8 @@ export default {
|
|||||||
const column = this.columnList.find(c => {
|
const column = this.columnList.find(c => {
|
||||||
return c.label === param.column
|
return c.label === param.column
|
||||||
})
|
})
|
||||||
|
const obj = this.metaList.find(d => d.column && d.column.label === param.column && d.value && (d.value.value === `'${param.value[0]}'` || d.value.value === param.value[0]))
|
||||||
|
if (obj) {
|
||||||
const metaIndex = this.metaList.findIndex(m => m.column && m.column.label === param.column && m.operator.value === param.operator && m.value.value === this.handleValue(param.value, column, param.operator))
|
const metaIndex = this.metaList.findIndex(m => m.column && m.column.label === param.column && m.operator.value === param.operator && m.value.value === this.handleValue(param.value, column, param.operator))
|
||||||
// 不是在首位,则删除时顺带删除前一个index(and或or),否则顺带删除后一个index
|
// 不是在首位,则删除时顺带删除前一个index(and或or),否则顺带删除后一个index
|
||||||
if (metaIndex > 0) {
|
if (metaIndex > 0) {
|
||||||
@@ -564,6 +576,7 @@ export default {
|
|||||||
} else {
|
} else {
|
||||||
this.metaList.splice(metaIndex, 2)
|
this.metaList.splice(metaIndex, 2)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
@@ -622,8 +635,16 @@ 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 {
|
||||||
|
const str1 = q.substring(q.indexOf('%'), q.indexOf('%') + 3)
|
||||||
|
if (q.indexOf('%') > 0 && (str1 !== '%20' || str1 === '%25')) {
|
||||||
|
q = decodeURI(q)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.metaList = parser.parseStr(q).metaList
|
this.metaList = parser.parseStr(q).metaList
|
||||||
}
|
}
|
||||||
@@ -645,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,8 +234,16 @@ 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 {
|
||||||
|
const str1 = q.substring(q.indexOf('%'), q.indexOf('%') + 3)
|
||||||
|
if (q.indexOf('%') > 0 && (str1 !== '%20' || str1 === '%25')) {
|
||||||
|
q = decodeURI(q)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 为避免地址栏任意输入导致全查询的q带QUERY,解析时不识别导致的语法错误
|
// 为避免地址栏任意输入导致全查询的q带QUERY,解析时不识别导致的语法错误
|
||||||
// 如地址栏输入116.178.222.171,此时的q很长,刷新界面时需要把q里的116.178.222.171拿出来进行搜索
|
// 如地址栏输入116.178.222.171,此时的q很长,刷新界面时需要把q里的116.178.222.171拿出来进行搜索
|
||||||
|
|||||||
@@ -6,9 +6,10 @@ import { ElMessage } from 'element-plus'
|
|||||||
import i18n from '@/i18n'
|
import i18n from '@/i18n'
|
||||||
|
|
||||||
const strReg = {
|
const strReg = {
|
||||||
all: /^[\da-zA-Z\s.'><!=-_(),%]$/,
|
// 需要不限制语言,正则过滤中英日俄语出错实现语言都通过。留个记录观察,后续校验
|
||||||
|
all: /^[\da-zA-Z\u4E00-\u9FA5\u3040-\u309F\u0800-\u4e00\u0400-\u04FF\u2000-\u206F\s.'><!=-_(),%]$/,
|
||||||
key: /^(?![\d])[\da-zA-Z\s.'-_]$/,
|
key: /^(?![\d])[\da-zA-Z\s.'-_]$/,
|
||||||
value: /^[\da-zA-Z\s.'-_%]$/
|
value: /^[\da-zA-Z\u4E00-\u9FA5\u3040-\u309F\u0800-\u4e00\u0400-\u04FF\u2000-\u206F\s.'-_%]$/
|
||||||
}
|
}
|
||||||
const operatorList = ['=', ' in ', ' IN ', ' like ', ' LIKE ', 'HAS(', 'has(']
|
const operatorList = ['=', ' in ', ' IN ', ' like ', ' LIKE ', 'HAS(', 'has(']
|
||||||
|
|
||||||
@@ -527,7 +528,9 @@ export default class Parser {
|
|||||||
}
|
}
|
||||||
// 在单引号里,又在括号里,则遇到逗号、右括号就报错
|
// 在单引号里,又在括号里,则遇到逗号、右括号就报错
|
||||||
if (isInBracket && isInApostrophe) {
|
if (isInBracket && isInApostrophe) {
|
||||||
if ([',', ')'].indexOf(strArr[j]) > -1) {
|
// if ([',', ')'].indexOf(strArr[j]) > -1) {
|
||||||
|
// 目前有ip in ('1.1.1.1,2.2.2.2')该情况,后续待验证
|
||||||
|
if ([')'].indexOf(strArr[j]) > -1) {
|
||||||
errorList.push(new ParserError(j, errorTypes.syntaxError, errorDesc.syntaxError.unclosedApostrophe))
|
errorList.push(new ParserError(j, errorTypes.syntaxError, errorDesc.syntaxError.unclosedApostrophe))
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -709,6 +712,13 @@ export default class Parser {
|
|||||||
meta.column.label = token.value
|
meta.column.label = token.value
|
||||||
meta.column.type = columnType.fullText
|
meta.column.type = columnType.fullText
|
||||||
}
|
}
|
||||||
|
} else if (nextToken.type === types.rightBracket) {
|
||||||
|
// 此处操作为ip='1,2' and has(tag,'222')中 ,'222')的情况
|
||||||
|
if (prevToken) {
|
||||||
|
if (prevToken.type === types.comma && token.type === types.commonStr && nextToken.type === types.rightBracket) {
|
||||||
|
meta.value.value = token.value
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
errorList.push(new ParserError(token.end, errorTypes.syntaxError, errorDesc.syntaxError.unexpectedString))
|
errorList.push(new ParserError(token.end, errorTypes.syntaxError, errorDesc.syntaxError.unexpectedString))
|
||||||
break
|
break
|
||||||
@@ -1163,7 +1173,9 @@ export default class Parser {
|
|||||||
const arr = []
|
const arr = []
|
||||||
// 如果出现this.columnList中的字段,如IP\Domain\App\Country等,则不进行模糊搜索,将str返回出去
|
// 如果出现this.columnList中的字段,如IP\Domain\App\Country等,则不进行模糊搜索,将str返回出去
|
||||||
this.columnList.forEach(item => {
|
this.columnList.forEach(item => {
|
||||||
arr.push(item.label.toLowerCase())
|
// todo 取消了大小写校验,后续观察是否出现问题
|
||||||
|
// arr.push(item.label.toLowerCase())
|
||||||
|
arr.push(item.label)
|
||||||
})
|
})
|
||||||
|
|
||||||
// 因为手动输入时可能会输入and,所以将操作符的AND转换为and,统一处理
|
// 因为手动输入时可能会输入and,所以将操作符的AND转换为and,统一处理
|
||||||
@@ -1173,7 +1185,9 @@ export default class Parser {
|
|||||||
newStr = newStr.replace(new RegExp(arr[i], 'g'), arr[i])
|
newStr = newStr.replace(new RegExp(arr[i], 'g'), arr[i])
|
||||||
}
|
}
|
||||||
// 检查str字段在arr中是否出现,true为出现过
|
// 检查str字段在arr中是否出现,true为出现过
|
||||||
const result = arr.some(item => newStr.toLowerCase().includes(item))
|
// todo 取消了大小写校验,后续观察是否出现问题
|
||||||
|
// const result = arr.some(item => newStr.toLowerCase().includes(item))
|
||||||
|
const result = arr.some(item => newStr.includes(item))
|
||||||
if (newStr.indexOf(' and ') > -1) {
|
if (newStr.indexOf(' and ') > -1) {
|
||||||
// 将单引号包裹的and拿出来放到数组tempList里,原来的单引号包裹内容用temp即'it is test keyword{键值}'代替
|
// 将单引号包裹的and拿出来放到数组tempList里,原来的单引号包裹内容用temp即'it is test keyword{键值}'代替
|
||||||
// 再将字符串用and转换为数组,遍历数组,发现值为temp的,获取键值,根据键值获取tempList的值组合起来,
|
// 再将字符串用and转换为数组,遍历数组,发现值为temp的,获取键值,根据键值获取tempList的值组合起来,
|
||||||
@@ -1184,7 +1198,7 @@ export default class Parser {
|
|||||||
|
|
||||||
// 将单引号包裹的and内容集合起来
|
// 将单引号包裹的and内容集合起来
|
||||||
while ((match = regex.exec(newStr)) !== null) {
|
while ((match = regex.exec(newStr)) !== null) {
|
||||||
if (match[1].includes('and')) {
|
if (match[1].includes(' and ')) {
|
||||||
tempList.push(match[1])
|
tempList.push(match[1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1224,7 +1238,8 @@ export default class Parser {
|
|||||||
// 不区分大小写,用this.columnList里的label
|
// 不区分大小写,用this.columnList里的label
|
||||||
arr.forEach(item => {
|
arr.forEach(item => {
|
||||||
if (str.toLowerCase().indexOf(item.toLowerCase()) > -1) {
|
if (str.toLowerCase().indexOf(item.toLowerCase()) > -1) {
|
||||||
str = str.replace(new RegExp(item, 'gi'), item)
|
// todo 记录一下此处取消了转小写转换,后续搜索验证
|
||||||
|
// str = str.replace(new RegExp(item, 'gi'), item)
|
||||||
if (!operatorList.some(ite => str.includes(ite)) && str.toLowerCase() !== item.toLowerCase()) {
|
if (!operatorList.some(ite => str.includes(ite)) && str.toLowerCase() !== item.toLowerCase()) {
|
||||||
str = this.checkFormatByStr(str)
|
str = this.checkFormatByStr(str)
|
||||||
}
|
}
|
||||||
@@ -1399,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
|
||||||
@@ -254,13 +265,15 @@ export default {
|
|||||||
const returnValue = () => {
|
const returnValue = () => {
|
||||||
store.commit('setTimeFilter', { startTime: myStartTime.value, endTime: myEndTime.value, range: dateRangeValue.value })
|
store.commit('setTimeFilter', { startTime: myStartTime.value, endTime: myEndTime.value, range: dateRangeValue.value })
|
||||||
cancelHttp()
|
cancelHttp()
|
||||||
const obj = rangeHistory.value.find(d => d.start === myStartTime.value && d.end === myEndTime.value)
|
if (rangeHistory.value[0]) {
|
||||||
if (!obj) {
|
const d = rangeHistory.value[0]
|
||||||
|
if (d.start !== myStartTime.value || d.end !== myEndTime.value) {
|
||||||
rangeHistory.value.unshift({
|
rangeHistory.value.unshift({
|
||||||
start: myStartTime.value,
|
start: myStartTime.value,
|
||||||
end: myEndTime.value
|
end: myEndTime.value
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (!rangeHistory.value[0]) {
|
if (!rangeHistory.value[0]) {
|
||||||
rangeHistory.value.unshift({
|
rangeHistory.value.unshift({
|
||||||
start: myStartTime.value,
|
start: myStartTime.value,
|
||||||
@@ -287,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,
|
||||||
@@ -295,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,
|
||||||
@@ -311,7 +328,8 @@ export default {
|
|||||||
timeArrChange,
|
timeArrChange,
|
||||||
returnValue,
|
returnValue,
|
||||||
quickChange,
|
quickChange,
|
||||||
historyChange
|
historyChange,
|
||||||
|
locale
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,7 +58,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { storageKey } from '@/utils/constants'
|
import { storageKey, EN } from '@/utils/constants'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'TopToolMoreOptions',
|
name: 'TopToolMoreOptions',
|
||||||
@@ -108,7 +108,7 @@ export default {
|
|||||||
if (this.paramsType) {
|
if (this.paramsType) {
|
||||||
form.append('type', this.paramsType)
|
form.append('type', this.paramsType)
|
||||||
}
|
}
|
||||||
form.append('language', localStorage.getItem(storageKey.language) ? localStorage.getItem(storageKey.language) : 'en')
|
form.append('language', localStorage.getItem(storageKey.language) ? localStorage.getItem(storageKey.language) : EN)
|
||||||
axios.post(this.importUrl, form, { 'Content-Type': 'multipart/form-data' }).then(response => {
|
axios.post(this.importUrl, form, { 'Content-Type': 'multipart/form-data' }).then(response => {
|
||||||
if (response.status === 200 && response.data.msg === 'success') {
|
if (response.status === 200 && response.data.msg === 'success') {
|
||||||
this.$message({ duration: 2000, type: 'success', message: this.$t('tip.importSuccess') })
|
this.$message({ duration: 2000, type: 'success', message: this.$t('tip.importSuccess') })
|
||||||
@@ -128,7 +128,7 @@ export default {
|
|||||||
this.importFile = null
|
this.importFile = null
|
||||||
},
|
},
|
||||||
downloadTemplate () {
|
downloadTemplate () {
|
||||||
const language = localStorage.getItem(storageKey.language) || 'en' // 初始未选择默认 en 英文
|
const language = localStorage.getItem(storageKey.language) || EN // 初始未选择默认 en 英文
|
||||||
const fileName = this.exportFileName + '-' + this.$t('overall.template') + '-' + this.getTimeString() + '.json'
|
const fileName = this.exportFileName + '-' + this.$t('overall.template') + '-' + this.getTimeString() + '.json'
|
||||||
|
|
||||||
let url = null
|
let url = null
|
||||||
@@ -159,7 +159,7 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
params.pageSize = -1
|
params.pageSize = -1
|
||||||
params.language = localStorage.getItem(storageKey.language) || 'en'
|
params.language = localStorage.getItem(storageKey.language) || EN
|
||||||
|
|
||||||
this.export(this.exportUrl, params, this.exportFileName + '-' + this.getTimeString() + '.json')
|
this.export(this.exportUrl, params, this.exportFileName + '-' + this.getTimeString() + '.json')
|
||||||
this.closeDialog()
|
this.closeDialog()
|
||||||
|
|||||||
@@ -13,12 +13,12 @@
|
|||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu>
|
<el-dropdown-menu>
|
||||||
<el-dropdown-item>
|
<el-dropdown-item>
|
||||||
<div id="header-to-english" :style="language === 'en'?'color:#0091ff':''" @click="changeLocal('en')">
|
<div id="header-to-english" :style="language === EN?'color:#0091ff':''" @click="changeLocal(EN)">
|
||||||
English
|
English
|
||||||
</div>
|
</div>
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item>
|
<el-dropdown-item>
|
||||||
<div id="header-to-chinese" :style="language === 'cn'?'color:#0091ff':''" @click="changeLocal('cn')">
|
<div id="header-to-chinese" :style="language === ZH?'color:#0091ff':''" @click="changeLocal(ZH)">
|
||||||
中文
|
中文
|
||||||
</div>
|
</div>
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
@@ -42,11 +42,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="cn-header__nav">
|
<div class="cn-header__nav">
|
||||||
<i class="cn-icon cn-icon-a-NetworkAnalytics"></i>
|
<i class="cn-icon cn-icon-a-NetworkAnalytics"></i>
|
||||||
<el-breadcrumb class="header__left-breadcrumb" separator=">">
|
<el-breadcrumb class="header__left-breadcrumb" separator=">" v-if="route.startsWith('/panel')">
|
||||||
<el-breadcrumb-item class="header__left-breadcrumb-item" :id="`breadcrumb${item.value}`" :title="item.value"
|
<el-breadcrumb-item class="header__left-breadcrumb-item" :id="`breadcrumb${item.value}`" :title="index===3?item.value:''"
|
||||||
v-for="(item,index) in breadcrumb" :key="item.value">
|
v-for="(item,index) in breadcrumb" :key="item.value">
|
||||||
<template v-if="index===3">
|
<template v-if="index===3" >
|
||||||
<div class="header__left-breadcrumb-item-select">
|
<div class="header__left-breadcrumb-item-select" >
|
||||||
<el-popover placement="bottom-start"
|
<el-popover placement="bottom-start"
|
||||||
ref="breadcrumbPopover"
|
ref="breadcrumbPopover"
|
||||||
:show-arrow="false"
|
:show-arrow="false"
|
||||||
@@ -99,7 +99,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="index===2">
|
<template v-else-if="index===2">
|
||||||
<span v-if="route===wholeScreenRouterMapping.dns">{{ $t(item.value) }}</span>
|
<span v-if="route===wholeScreenRouterMapping.dns || !route.startsWith('/panel')">{{ $t(item.value) }}</span>
|
||||||
<span v-else class="route-menu" @click="jump(route,item.value,'',3)">{{ $t(item.value) }}</span>
|
<span v-else class="route-menu" @click="jump(route,item.value,'',3)">{{ $t(item.value) }}</span>
|
||||||
</template>
|
</template>
|
||||||
<!-- index=0和index=1的点击跳转由breadcrumb里的数据控制 -->
|
<!-- index=0和index=1的点击跳转由breadcrumb里的数据控制 -->
|
||||||
@@ -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')
|
||||||
}
|
}
|
||||||
@@ -392,7 +405,7 @@ export default {
|
|||||||
this.dnsRcodeMapData = await getDnsMapData('dnsRcode')
|
this.dnsRcodeMapData = await getDnsMapData('dnsRcode')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let path = this.$route.path;
|
const path = this.$route.path
|
||||||
if (path.indexOf('panel') > -1 && path.indexOf('linkMonitor') === -1) {
|
if (path.indexOf('panel') > -1 && path.indexOf('linkMonitor') === -1) {
|
||||||
await this.initDropdownList()
|
await this.initDropdownList()
|
||||||
}
|
}
|
||||||
@@ -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,55 +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
|
|
||||||
} else if (this.route === '/detectionsNew') {
|
|
||||||
const detectionMenu = menus.find(m => m.route === '/detection')
|
|
||||||
const policyMenu = menus.find(m => m.route === '/detectionsNew')
|
|
||||||
breadcrumb.push({
|
|
||||||
code: detectionMenu.code,
|
|
||||||
value: detectionMenu.i18n ? this.$t(detectionMenu.i18n) : detectionMenu.name,
|
|
||||||
route: detectionMenu.route,
|
|
||||||
type: detectionMenu.type
|
|
||||||
})
|
|
||||||
breadcrumb.push({
|
|
||||||
code: policyMenu.code,
|
|
||||||
value: policyMenu.i18n ? this.$t(policyMenu.i18n) : policyMenu.name,
|
|
||||||
route: policyMenu.route,
|
|
||||||
type: policyMenu.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({
|
||||||
@@ -523,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)
|
||||||
@@ -536,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)
|
||||||
@@ -560,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')
|
||||||
}
|
}
|
||||||
@@ -691,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)
|
||||||
@@ -712,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
|
||||||
}
|
}
|
||||||
@@ -732,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 => {
|
||||||
@@ -744,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 = ''
|
||||||
@@ -786,6 +764,7 @@ export default {
|
|||||||
t: +new Date()
|
t: +new Date()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
return
|
||||||
} else if (opeType === 3) {
|
} else if (opeType === 3) {
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
query: {
|
query: {
|
||||||
@@ -794,6 +773,7 @@ export default {
|
|||||||
t: +new Date()
|
t: +new Date()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
return
|
||||||
} else if (opeType !== 4) {
|
} else if (opeType !== 4) {
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
query: {
|
query: {
|
||||||
@@ -803,6 +783,7 @@ export default {
|
|||||||
t: +new Date()
|
t: +new Date()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
if (route === this.route) {
|
if (route === this.route) {
|
||||||
this.refresh()
|
this.refresh()
|
||||||
|
|||||||
@@ -1,408 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="right-box right-box-user">
|
|
||||||
<div class="right-box__header">
|
|
||||||
<div class="header__title">{{editObject.id ? $t('config.chart.edit') : $t('config.chart.add')}}</div>
|
|
||||||
<div class="header__operation">
|
|
||||||
<span v-cancel="{object: editObject, func: esc}"><i class="cn-icon cn-icon-close"></i></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="right-box__container">
|
|
||||||
<div class="container__form">
|
|
||||||
<el-form ref="chartForm" :model="editObject" :rules="editObject.id ? rules2 : rules" label-position="top" label-width="120px">
|
|
||||||
<!--name-->
|
|
||||||
<el-form-item :label="$t('overall.name')" prop="name">
|
|
||||||
<el-input id="chart-input-name" v-model="editObject.name" :disabled="editObject.name==='admin' && editObject.id === 1"
|
|
||||||
maxlength="64" placeholder="" show-word-limit size="small" type="text"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<!--i18n-->
|
|
||||||
<el-form-item :label="$t('config.chart.i18n')" prop="i18n">
|
|
||||||
<el-input id="chart-input-i18n" v-model="editObject.i18n"
|
|
||||||
maxlength="64" placeholder="" show-word-limit size="small" type="text"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<!--type-->
|
|
||||||
<el-form-item :label="$t('config.chart.type')" prop="type">
|
|
||||||
<el-select id="chart-type"
|
|
||||||
v-model="editObject.type"
|
|
||||||
class="right-box__select"
|
|
||||||
clearable
|
|
||||||
collapse-tags
|
|
||||||
placeholder=""
|
|
||||||
popper-class="right-box-select-dropdown prevent-clickoutside"
|
|
||||||
size="small"
|
|
||||||
@change="()=>{ this.$forceUpdate() }">
|
|
||||||
|
|
||||||
<el-option
|
|
||||||
v-for="item in options"
|
|
||||||
:key="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
:value="item.value">
|
|
||||||
<span style="float: left">{{ item.label }}</span><span style="float: right;color: #909399;font-size: 13px;">{{ item.remark }}</span>
|
|
||||||
</el-option>
|
|
||||||
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<!--panel-->
|
|
||||||
<el-form-item :label="$t('config.chart.panel')" prop="panelId">
|
|
||||||
<el-select id="chart-input-panelId"
|
|
||||||
v-model="editObject.panelId"
|
|
||||||
class="right-box__select"
|
|
||||||
clearable
|
|
||||||
collapse-tags
|
|
||||||
placeholder=""
|
|
||||||
:disabled="editObject.id?true:false"
|
|
||||||
popper-class="right-box-select-dropdown prevent-clickoutside"
|
|
||||||
size="small"
|
|
||||||
@change="getChartData">
|
|
||||||
|
|
||||||
<el-option :key="panelTypeAndRouteMapping.trafficSummary" :label="$t('trafficSummary.trafficSummary')" :value="panelTypeAndRouteMapping.trafficSummary"></el-option>
|
|
||||||
<el-option :key="panelTypeAndRouteMapping.networkAppPerformance" :label="$t('networkAppPerformance.networkAppPerformance')" :value="panelTypeAndRouteMapping.networkAppPerformance"></el-option>
|
|
||||||
<el-option :key="panelTypeAndRouteMapping.cryptocurrency" :label="$t('overall.cryptocurrency')" :value="panelTypeAndRouteMapping.cryptocurrency"></el-option>
|
|
||||||
<el-option :key="panelTypeAndRouteMapping.dnsServiceInsights" :label="$t('dnsServiceInsights.dnsServiceInsights')" :value="panelTypeAndRouteMapping.dnsServiceInsights"></el-option>
|
|
||||||
<el-option :key="panelTypeAndRouteMapping.ipEntityDetail" :label="$t('entities.ipEntityDetail')" :value="panelTypeAndRouteMapping.ipEntityDetail"></el-option>
|
|
||||||
<el-option :key="panelTypeAndRouteMapping.domainEntityDetail" :label="$t('entities.domainEntityDetail')" :value="panelTypeAndRouteMapping.domainEntityDetail"></el-option>
|
|
||||||
<el-option :key="panelTypeAndRouteMapping.appEntityDetail" :label="$t('entities.appEntityDetail')" :value="panelTypeAndRouteMapping.appEntityDetail"></el-option>
|
|
||||||
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<!--pid-->
|
|
||||||
<el-form-item :label="$t('config.chart.pid')" prop="pid">
|
|
||||||
<el-select id="chart-pid"
|
|
||||||
v-model="editObject.pid"
|
|
||||||
class="right-box__select"
|
|
||||||
clearable
|
|
||||||
collapse-tags
|
|
||||||
placeholder=""
|
|
||||||
:disabled="editObject.id?true:false"
|
|
||||||
popper-class="right-box-select-dropdown prevent-clickoutside"
|
|
||||||
size="small"
|
|
||||||
@change="()=>{ this.$forceUpdate() }">
|
|
||||||
|
|
||||||
<template v-for="chart in chartData" :key="chart.id">
|
|
||||||
<el-option :label="chart.name" :value="chart.id"></el-option>
|
|
||||||
</template>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<!--x-->
|
|
||||||
<el-form-item :label="$t('config.chart.x')" prop="x">
|
|
||||||
<el-input id="chart-input-x" v-model="editObject.x"
|
|
||||||
maxlength="64" placeholder="" show-word-limit size="small" type="text"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<!--y-->
|
|
||||||
<el-form-item :label="$t('config.chart.y')" prop="y">
|
|
||||||
<el-input id="chart-input-y" v-model="editObject.y"
|
|
||||||
maxlength="64" placeholder="" show-word-limit size="small" type="text"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<!--w-->
|
|
||||||
<el-form-item :label="$t('config.chart.w')" prop="w">
|
|
||||||
<el-input id="chart-input-x" v-model="editObject.w"
|
|
||||||
maxlength="64" placeholder="" show-word-limit size="small" type="text"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<!--h-->
|
|
||||||
<el-form-item :label="$t('config.chart.h')" prop="h">
|
|
||||||
<el-input id="chart-input-y" v-model="editObject.h"
|
|
||||||
maxlength="64" placeholder="" show-word-limit size="small" type="text"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<!--params-->
|
|
||||||
<el-form-item :label="$t('config.chart.params')" prop="params">
|
|
||||||
<v-ace-editor
|
|
||||||
v-model:value="editObject.params"
|
|
||||||
lang="json"
|
|
||||||
theme="chrome"
|
|
||||||
style="height: 300px" />
|
|
||||||
</el-form-item>
|
|
||||||
<!--remark-->
|
|
||||||
<el-form-item :label="$t('config.chart.remark')">
|
|
||||||
<el-input maxlength="1024" show-word-limit :rows="2" size='mini' type="textarea" v-model="editObject.remark" id="chart-box-remark"/>
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
</el-form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="right-box__footer">
|
|
||||||
<button id="chart-edit-cancel" v-cancel="{object: editObject, func: esc}" class="footer__btn footer__btn--light">
|
|
||||||
<span>{{$t('overall.cancel')}}</span>
|
|
||||||
</button>
|
|
||||||
<button id="chart-edit-save" :class="{'footer__btn--disabled': blockOperation.save}" :disabled="blockOperation.save" class="footer__btn" @click="save">
|
|
||||||
<span>{{$t('overall.save')}}</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import rightBoxMixin from '@/mixins/right-box'
|
|
||||||
import axios from 'axios'
|
|
||||||
import { panelTypeAndRouteMapping, storageKey } from '@/utils/constants'
|
|
||||||
import { api } from '@/utils/api'
|
|
||||||
import { VAceEditor } from 'vue3-ace-editor'
|
|
||||||
import 'ace-builds/src-noconflict/mode-javascript'
|
|
||||||
import 'ace-builds/src-noconflict/mode-json'
|
|
||||||
import 'ace-builds/src-noconflict/theme-chrome'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'ChartBox',
|
|
||||||
mixins: [rightBoxMixin],
|
|
||||||
components: {
|
|
||||||
VAceEditor
|
|
||||||
},
|
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
url: api.chart,
|
|
||||||
loginName: localStorage.getItem(storageKey.username),
|
|
||||||
panelTypeAndRouteMapping: panelTypeAndRouteMapping,
|
|
||||||
rules: { // 表单校验规则
|
|
||||||
name: [
|
|
||||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
|
||||||
],
|
|
||||||
type: [
|
|
||||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
|
||||||
],
|
|
||||||
panel_id: [
|
|
||||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
|
||||||
],
|
|
||||||
x: [
|
|
||||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
|
||||||
],
|
|
||||||
y: [
|
|
||||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
|
||||||
],
|
|
||||||
w: [
|
|
||||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
|
||||||
],
|
|
||||||
h: [
|
|
||||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
rules2: { // 表单校验规则
|
|
||||||
name: [
|
|
||||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
|
||||||
],
|
|
||||||
type: [
|
|
||||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
|
||||||
],
|
|
||||||
panel_id: [
|
|
||||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
|
||||||
],
|
|
||||||
x: [
|
|
||||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
|
||||||
],
|
|
||||||
y: [
|
|
||||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
|
||||||
],
|
|
||||||
w: [
|
|
||||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
|
||||||
],
|
|
||||||
h: [
|
|
||||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
chartData: [],
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
value: 1,
|
|
||||||
label: 'map-1',
|
|
||||||
remark: '流量流向地图-连线'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 2,
|
|
||||||
label: 'map-2',
|
|
||||||
remark: '地图-色块'
|
|
||||||
}, {
|
|
||||||
value: 3,
|
|
||||||
label: 'map-3',
|
|
||||||
remark: '地图-点'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 4,
|
|
||||||
label: 'map-4',
|
|
||||||
remark: '地图-点'
|
|
||||||
}, {
|
|
||||||
value: 11,
|
|
||||||
label: 'line-1',
|
|
||||||
remark: '折线图-常规'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 61,
|
|
||||||
label: 'table-1',
|
|
||||||
remark: '表格'
|
|
||||||
}, {
|
|
||||||
value: 62,
|
|
||||||
label: 'table-2',
|
|
||||||
remark: 'DNS记录'
|
|
||||||
}, {
|
|
||||||
value: 63,
|
|
||||||
label: 'table-3',
|
|
||||||
remark: '挖矿活跃ip'
|
|
||||||
}, {
|
|
||||||
value: 31,
|
|
||||||
label: 'pie-1',
|
|
||||||
remark: '饼图-带联动表格'
|
|
||||||
}, {
|
|
||||||
value: 51,
|
|
||||||
label: 'singleValue-1',
|
|
||||||
remark: '单值图'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 91,
|
|
||||||
label: 'tab-container',
|
|
||||||
remark: 'tab标签(容器)'
|
|
||||||
}, {
|
|
||||||
value: 92,
|
|
||||||
label: 'tab-item',
|
|
||||||
remark: 'tab标签(标签页)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 93,
|
|
||||||
label: 'title',
|
|
||||||
remark: '标题'
|
|
||||||
}, {
|
|
||||||
value: 94,
|
|
||||||
label: 'group',
|
|
||||||
remark: '组'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 12,
|
|
||||||
label: 'line-2',
|
|
||||||
remark: '折线图-带统计'
|
|
||||||
}, {
|
|
||||||
value: 52,
|
|
||||||
label: 'singleValue-2',
|
|
||||||
remark: '详情单值图'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 53,
|
|
||||||
label: 'singleValue-3',
|
|
||||||
remark: '单值图'
|
|
||||||
}, {
|
|
||||||
value: 13,
|
|
||||||
label: 'line-3',
|
|
||||||
remark: '折线图-堆叠面积'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 21,
|
|
||||||
label: 'bar-1',
|
|
||||||
remark: '柱状图'
|
|
||||||
}, {
|
|
||||||
value: 22,
|
|
||||||
label: 'bar-2',
|
|
||||||
remark: '开放端口'
|
|
||||||
}, {
|
|
||||||
value: 23,
|
|
||||||
label: 'bar-3',
|
|
||||||
remark: '挖矿事件统计(time类型柱状图)'
|
|
||||||
}, {
|
|
||||||
value: 24,
|
|
||||||
label: 'bar-4',
|
|
||||||
remark: '矿机所属单位(category类型柱状图)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 32,
|
|
||||||
label: 'pie-2',
|
|
||||||
remark: '饼图-常规'
|
|
||||||
}, {
|
|
||||||
value: 33,
|
|
||||||
label: 'pie-3',
|
|
||||||
remark: '托管域名'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 34,
|
|
||||||
label: 'pie-4',
|
|
||||||
remark: '相关域名'
|
|
||||||
}, {
|
|
||||||
value: 42,
|
|
||||||
label: 'relation-2',
|
|
||||||
remark: '关系图谱'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 43,
|
|
||||||
label: 'relation-3',
|
|
||||||
remark: '访问链路图'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 82,
|
|
||||||
label: 'base-2',
|
|
||||||
remark: 'APP基本信息'
|
|
||||||
}, {
|
|
||||||
value: 83,
|
|
||||||
label: 'list-1',
|
|
||||||
remark: 'Whois'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 84,
|
|
||||||
label: 'list-2',
|
|
||||||
remark: 'DNS记录'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 85,
|
|
||||||
label: 'list-3',
|
|
||||||
remark: '近期挖矿事件'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setup () {
|
|
||||||
},
|
|
||||||
mounted () {
|
|
||||||
if (this.editObject.id) {
|
|
||||||
this.getChartData(this.editObject.panelId)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
'editObject.panelId': function (newValue, oldValue) {
|
|
||||||
this.editObject.pid = ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
isCurrentUser (username) {
|
|
||||||
return localStorage.getItem(storageKey.username) === username
|
|
||||||
},
|
|
||||||
/* 密码失去焦点 检验确认密码 */
|
|
||||||
pinBlur () {
|
|
||||||
if (this.editObject.pin && this.editObject.pinChange) {
|
|
||||||
this.$refs.chartForm.validateField('pinChange')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
save () {
|
|
||||||
if (this.blockOperation.save) { return }
|
|
||||||
this.blockOperation.save = true
|
|
||||||
|
|
||||||
this.$refs.chartForm.validate((valid) => {
|
|
||||||
if (valid) {
|
|
||||||
if (this.editObject.id) {
|
|
||||||
axios.put(this.url, this.editObject).then(res => {
|
|
||||||
this.blockOperation.save = false
|
|
||||||
if (res.status === 200) {
|
|
||||||
this.$message({ duration: 2000, type: 'success', message: this.$t('tip.saveSuccess') })
|
|
||||||
this.esc(true)
|
|
||||||
} else {
|
|
||||||
this.$message.error(res.data.message)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
axios.post(this.url, this.editObject).then(res => {
|
|
||||||
this.blockOperation.save = false
|
|
||||||
if (res.status === 200) {
|
|
||||||
this.$message({ duration: 2000, type: 'success', message: this.$t('tip.saveSuccess') })
|
|
||||||
this.esc(true)
|
|
||||||
} else {
|
|
||||||
this.$message.error(res.data.message)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.blockOperation.save = false
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
async getChartData (value) {
|
|
||||||
await axios.get(api.chart, { params: { panelId: value } }).then(response => {
|
|
||||||
if (response.status === 200) {
|
|
||||||
this.chartData = response.data.data.list
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="right-box">
|
|
||||||
<div class="right-box__header">
|
|
||||||
<div class="header__title">{{editObject.id ? $t('overall.edit') : $t('overall.new')}}</div>
|
|
||||||
<div class="header__operation">
|
|
||||||
<span v-cancel="{object: editObject, func: esc}"><i class="cn-icon cn-icon-close"></i></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="right-box__container">
|
|
||||||
<div class="container__form">
|
|
||||||
<el-form ref="form" :model="editObject" :rules="rules" label-position="top" label-width="120px">
|
|
||||||
<!--name-->
|
|
||||||
<el-form-item :label="$t('overall.name')" prop="name">
|
|
||||||
<el-input id="proxy-name" v-model="editObject.name"
|
|
||||||
maxlength="64" placeholder="" show-word-limit size="small" type="text"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<!--path-->
|
|
||||||
<el-form-item :label="$t('overall.path')" prop="path">
|
|
||||||
<el-input id="proxy-path" v-model="editObject.path"
|
|
||||||
placeholder="" show-word-limit size="small" type="text"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<!--method-->
|
|
||||||
<el-form-item :label="$t('overall.method')" prop="method">
|
|
||||||
<el-select id="proxy-method"
|
|
||||||
v-model="editObject.method"
|
|
||||||
placeholder=" "
|
|
||||||
size="small"
|
|
||||||
class="right-box__select"
|
|
||||||
popper-class="right-box-select-dropdown prevent-clickoutside"
|
|
||||||
>
|
|
||||||
<el-option value="get"></el-option>
|
|
||||||
<el-option value="post"></el-option>
|
|
||||||
<el-option value="put"></el-option>
|
|
||||||
<el-option value="fetch"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<!--version-->
|
|
||||||
<el-form-item :label="$t('overall.version')" prop="version">
|
|
||||||
<el-input id="proxy-version" v-model="editObject.version" placeholder="" size="small" type="text"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<!--target-->
|
|
||||||
<el-form-item :label="$t('galaxyProxy.targetUrl')" prop="targetUrl">
|
|
||||||
<el-input id="proxy-targetUrl" v-model="editObject.targetUrl" placeholder="" size="small" type="text"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<!--target param-->
|
|
||||||
<el-form-item :label="$t('galaxyProxy.targetParam')" prop="targetParam">
|
|
||||||
<!-- <prism-editor class="my-editor" v-model="editObject.targetParam" :highlight="jsonHl" line-numbers></prism-editor>-->
|
|
||||||
<v-ace-editor
|
|
||||||
v-model:value="editObject.targetParam"
|
|
||||||
lang="json"
|
|
||||||
theme="chrome"
|
|
||||||
style="height: 300px" />
|
|
||||||
</el-form-item>
|
|
||||||
<!--target header-->
|
|
||||||
<el-form-item :label="$t('galaxyProxy.targetHeader')" prop="targetHeader">
|
|
||||||
<v-ace-editor
|
|
||||||
v-model:value="editObject.targetHeader"
|
|
||||||
lang="json"
|
|
||||||
theme="chrome"
|
|
||||||
style="height: 300px" />
|
|
||||||
</el-form-item>
|
|
||||||
<!--pre handle-->
|
|
||||||
<el-form-item label="Pre handle" prop="preHandle">
|
|
||||||
<v-ace-editor
|
|
||||||
v-model:value="editObject.preHandle"
|
|
||||||
lang="javascript"
|
|
||||||
theme="chrome"
|
|
||||||
style="height: 300px" />
|
|
||||||
</el-form-item>
|
|
||||||
<!--post handle-->
|
|
||||||
<el-form-item label="Post handle" prop="postHandle">
|
|
||||||
<v-ace-editor
|
|
||||||
v-model:value="editObject.postHandle"
|
|
||||||
lang="javascript"
|
|
||||||
theme="chrome"
|
|
||||||
style="height: 300px" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="right-box__footer">
|
|
||||||
<button id="asset-edit-cancel" v-cancel="{object: editObject, func: esc}" class="footer__btn footer__btn--light">
|
|
||||||
<span>{{$t('overall.cancel')}}</span>
|
|
||||||
</button>
|
|
||||||
<button id="asset-edit-save" :class="{'footer__btn--disabled': blockOperation.save}" :disabled="blockOperation.save" class="footer__btn" @click="save">
|
|
||||||
<span>{{$t('overall.save')}}</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import rightBoxMixin from '@/mixins/right-box'
|
|
||||||
import { api } from '@/utils/api'
|
|
||||||
import { VAceEditor } from 'vue3-ace-editor'
|
|
||||||
import 'ace-builds/src-noconflict/mode-javascript'
|
|
||||||
import 'ace-builds/src-noconflict/mode-json'
|
|
||||||
import 'ace-builds/src-noconflict/theme-chrome'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'GalaxyProxyBox',
|
|
||||||
mixins: [rightBoxMixin],
|
|
||||||
components: {
|
|
||||||
VAceEditor
|
|
||||||
},
|
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
url: api.galaxyProxy,
|
|
||||||
rules: { // 表单校验规则
|
|
||||||
name: [
|
|
||||||
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
class="right-box__select"
|
class="right-box__select"
|
||||||
clearable
|
clearable
|
||||||
collapse-tags
|
collapse-tags
|
||||||
placeholder=""
|
placeholder=" "
|
||||||
popper-class="right-box-select-dropdown prevent-clickoutside"
|
popper-class="right-box-select-dropdown prevent-clickoutside"
|
||||||
size="small"
|
size="small"
|
||||||
@change="()=>{ this.$forceUpdate() }">
|
@change="()=>{ this.$forceUpdate() }">
|
||||||
|
|||||||
@@ -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 () {
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
class="right-box__select"
|
class="right-box__select"
|
||||||
clearable
|
clearable
|
||||||
collapse-tags
|
collapse-tags
|
||||||
placeholder=""
|
placeholder=" "
|
||||||
popper-class="right-box-select-dropdown prevent-clickoutside"
|
popper-class="right-box-select-dropdown prevent-clickoutside"
|
||||||
size="small"
|
size="small"
|
||||||
@change="()=>{ this.$forceUpdate() }">
|
@change="()=>{ this.$forceUpdate() }">
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
class="right-box__select"
|
class="right-box__select"
|
||||||
clearable
|
clearable
|
||||||
collapse-tags
|
collapse-tags
|
||||||
placeholder=""
|
placeholder=" "
|
||||||
popper-class="right-box-select-dropdown prevent-clickoutside"
|
popper-class="right-box-select-dropdown prevent-clickoutside"
|
||||||
size="small">
|
size="small">
|
||||||
<template v-for="lang in langData" :key="lang.value">
|
<template v-for="lang in langData" :key="lang.value">
|
||||||
@@ -70,20 +70,20 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!--theme-->
|
<!--theme-->
|
||||||
<el-form-item :label="$t('config.user.theme')" prop="i18n">
|
<!-- <el-form-item :label="$t('config.user.theme')" prop="i18n">
|
||||||
<el-select id="account-input-roleIds"
|
<el-select id="account-input-roleIds"
|
||||||
v-model="editObject.theme"
|
v-model="editObject.theme"
|
||||||
class="right-box__select"
|
class="right-box__select"
|
||||||
clearable
|
clearable
|
||||||
collapse-tags
|
collapse-tags
|
||||||
placeholder=""
|
placeholder=" "
|
||||||
popper-class="right-box-select-dropdown prevent-clickoutside"
|
popper-class="right-box-select-dropdown prevent-clickoutside"
|
||||||
size="small">
|
size="small">
|
||||||
<template v-for="theme in themeData" :key="theme.value">
|
<template v-for="theme in themeData" :key="theme.value">
|
||||||
<el-option :label="theme.label" :value="theme.value"></el-option>
|
<el-option :label="theme.label" :value="theme.value"></el-option>
|
||||||
</template>
|
</template>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>-->
|
||||||
<!--enable-->
|
<!--enable-->
|
||||||
<el-form-item :label="$t('config.user.enable')">
|
<el-form-item :label="$t('config.user.enable')">
|
||||||
<el-switch
|
<el-switch
|
||||||
@@ -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' }
|
||||||
|
|||||||
@@ -1,329 +0,0 @@
|
|||||||
<template>
|
|
||||||
<el-dialog
|
|
||||||
v-model="show"
|
|
||||||
:top="top"
|
|
||||||
:modal="modal"
|
|
||||||
:custom-class="customClass"
|
|
||||||
:show-close="showClose"
|
|
||||||
:width="width"
|
|
||||||
@close="closeDebug"
|
|
||||||
@open="openDebug"
|
|
||||||
destroy-on-close
|
|
||||||
>
|
|
||||||
|
|
||||||
<div class="debug-wrapper">
|
|
||||||
<el-select v-model="name" filterable placeholder="Select" class="item item-1" allow-create
|
|
||||||
@change="changPath">
|
|
||||||
<template v-for="(proxy,index) in galaxyProxyData" :key="proxy.id">
|
|
||||||
<el-option :label="proxy.name" :value="index"></el-option>
|
|
||||||
</template>
|
|
||||||
</el-select>
|
|
||||||
<div class="item item-2 sub-grid-send">
|
|
||||||
<el-select v-model="method" filterable placeholder="Select" style="width:100px;" >
|
|
||||||
<el-option
|
|
||||||
v-for="item in methodOptions"
|
|
||||||
:key="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
:value="item.value"
|
|
||||||
>
|
|
||||||
</el-option>
|
|
||||||
</el-select>
|
|
||||||
<el-input v-model="fullPathWithParams" placeholder="Please input" readonly/>
|
|
||||||
<el-button @click="send">{{$t('galaxyProxy.debug.send')}}</el-button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="item item-3 sub-grid-params">
|
|
||||||
<div class="sub-grid-params-add">
|
|
||||||
<span style="padding-left: 15px;">{{$t('galaxyProxy.debug.requestParams')}}</span>
|
|
||||||
<el-button size="mini" @click="handleAddDetails"><i class="cn-icon-add cn-icon"></i></el-button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-table :data="paramsTableData"
|
|
||||||
width="100%"
|
|
||||||
@selection-change="handleDetailSelectionChange"
|
|
||||||
:row-class-name="rowClassName"
|
|
||||||
empty-text=""
|
|
||||||
ref="tb">
|
|
||||||
|
|
||||||
<el-table-column type="selection" align="center" label="" width="30px" style="border-left:0px;" />
|
|
||||||
|
|
||||||
<el-table-column prop="key" align="center" width="80px" >
|
|
||||||
<template #header>
|
|
||||||
<div class="table-operation-title">{{$t('galaxyProxy.debug.key')}}</div>
|
|
||||||
</template>
|
|
||||||
<template #default="scope">
|
|
||||||
<el-input @change="paramsChange(scope.row)" v-model="scope.row.key"></el-input>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
|
|
||||||
<el-table-column prop="value" align="center" >
|
|
||||||
<template #header>
|
|
||||||
<div class="table-operation-title">{{$t('galaxyProxy.debug.value')}}</div>
|
|
||||||
</template>
|
|
||||||
<template #default="scope">
|
|
||||||
<el-input @change="paramsChange(scope.row)" v-model="scope.row.value"></el-input>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
|
|
||||||
<el-table-column align="center" style="border-right:0px;" width="70px">
|
|
||||||
<template #header>
|
|
||||||
<div class="table-operation-title">{{$t('overall.option')}}</div>
|
|
||||||
</template>
|
|
||||||
<template #default="scope">
|
|
||||||
<div @click="deleteRow(scope.$index)" class="debug__params-delete">{{$t('overall.delete')}}</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<template v-slot:empty>
|
|
||||||
<div style="height:0px;"></div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
</el-table>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="item item-4">
|
|
||||||
<div class="request-header" >{{$t('galaxyProxy.debug.request.header')}}</div>
|
|
||||||
<div class="request-header-content" ><pre v-html="proxyRequestHeader" style="height: 98%;width: 98%;margin-left: -15px;margin-top: -10px;"></pre></div>
|
|
||||||
<div class="response-header">{{$t('galaxyProxy.debug.response.header')}}</div>
|
|
||||||
<div class="response-body">{{$t('galaxyProxy.debug.response.body')}}</div>
|
|
||||||
<div class="response-header-content"><pre v-html="proxyResponseHeader" style="height: 98%;width: 98%;margin-left: -15px;margin-top: -10px;"></pre></div>
|
|
||||||
<div class="response-body-content color-pre__style">
|
|
||||||
<v-ace-editor
|
|
||||||
v-model:value="proxyResponseBody"
|
|
||||||
lang="json"
|
|
||||||
readonly="true"
|
|
||||||
theme="chrome"
|
|
||||||
style="height: 100%" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { api } from '@/utils/api'
|
|
||||||
import { getForDebug, postForDebug } from '@/utils/http'
|
|
||||||
import axios from 'axios'
|
|
||||||
import { VAceEditor } from 'vue3-ace-editor'
|
|
||||||
import 'ace-builds/src-noconflict/mode-javascript'
|
|
||||||
import 'ace-builds/src-noconflict/mode-json'
|
|
||||||
import 'ace-builds/src-noconflict/theme-chrome'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'GalaxyProxyDebug',
|
|
||||||
components: {
|
|
||||||
VAceEditor
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
showDebug: Boolean,
|
|
||||||
top: {
|
|
||||||
type: String,
|
|
||||||
default: '5vh'
|
|
||||||
},
|
|
||||||
modal: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
customClass: {
|
|
||||||
type: String,
|
|
||||||
default: 'proxy-debug__dialog'
|
|
||||||
},
|
|
||||||
showClose: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
width: { // 高度需要通过customClass自行定义
|
|
||||||
type: [String, Number],
|
|
||||||
default: '90vw'
|
|
||||||
},
|
|
||||||
curGalaxyProxy: Object // 实体,{ name: '', path: '', icon: icon-class }
|
|
||||||
},
|
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
show: false,
|
|
||||||
galaxyProxyData: [],
|
|
||||||
name: '',
|
|
||||||
paramsTableData: [
|
|
||||||
|
|
||||||
],
|
|
||||||
// 选中的数据
|
|
||||||
checkedDetail: {},
|
|
||||||
checkedRowData: [],
|
|
||||||
methodOptions: [
|
|
||||||
{
|
|
||||||
value: 'GET',
|
|
||||||
label: 'GET'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'POST',
|
|
||||||
label: 'POST'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
method: 'GET',
|
|
||||||
path: '', // 不带参数的路径,用于请求URL
|
|
||||||
fullPathWithParams: '', // 带参数的完整路径,用于界面显示
|
|
||||||
proxyResponseBody: '',
|
|
||||||
proxyRequestHeader: '',
|
|
||||||
proxyResponseHeader: ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setup () {
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
|
|
||||||
handleAddDetails () {
|
|
||||||
if (this.paramsTableData == undefined) {
|
|
||||||
this.paramsTableData = new Array()
|
|
||||||
}
|
|
||||||
const obj = {}
|
|
||||||
obj.key = ''
|
|
||||||
obj.value = ''
|
|
||||||
|
|
||||||
this.paramsTableData.push(obj)
|
|
||||||
},
|
|
||||||
|
|
||||||
// 删除当前行
|
|
||||||
deleteRow (index) {
|
|
||||||
this.paramsTableData.splice(index, 1)
|
|
||||||
this.updateUrlParams()
|
|
||||||
},
|
|
||||||
|
|
||||||
rowClassName ({ row, rowIndex }) {
|
|
||||||
// 把每一行的索引放进row
|
|
||||||
row.index = rowIndex
|
|
||||||
},
|
|
||||||
|
|
||||||
// 参数发送改变时
|
|
||||||
paramsChange (row) {
|
|
||||||
this.fullPathWithParams = this.path
|
|
||||||
this.checkedDetail = {}
|
|
||||||
this.checkedRowData.forEach(t => {
|
|
||||||
if (t.key != '') {
|
|
||||||
this.checkedDetail[t.key] = t.value
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if (this.fullPathWithParams != '') {
|
|
||||||
this.updateUrlParams()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
updateUrlParams () {
|
|
||||||
this.fullPathWithParams = this.path
|
|
||||||
let params = ''
|
|
||||||
for (const key in this.checkedDetail) {
|
|
||||||
if (key != '') {
|
|
||||||
params = params + key + '=' + this.checkedDetail[key] + '&'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (params.endsWith('&')) {
|
|
||||||
params = params.substring(0, params.length - 1)
|
|
||||||
}
|
|
||||||
if (params != '') {
|
|
||||||
this.fullPathWithParams = this.fullPathWithParams + '?' + params
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// 单选框选中数据
|
|
||||||
handleDetailSelectionChange (selection) {
|
|
||||||
this.checkedDetail = {}
|
|
||||||
this.checkedRowData = selection
|
|
||||||
selection.forEach((item, index) => {
|
|
||||||
this.checkedDetail[item.key] = item.value
|
|
||||||
})
|
|
||||||
this.updateUrlParams()
|
|
||||||
},
|
|
||||||
|
|
||||||
async getGalaxyProxyData (value) {
|
|
||||||
await axios.get(api.galaxyProxy + '?pageSize=-1').then(response => {
|
|
||||||
if (response.status === 200) {
|
|
||||||
this.galaxyProxyData = response.data.data.list
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
syntaxUrl (json) {
|
|
||||||
if (typeof json != 'string') {
|
|
||||||
json = JSON.stringify(json, undefined, 2)
|
|
||||||
}
|
|
||||||
return json = json.replace(/,/g, '&').replace(/{/g, '').replace(/}/g, '').replace(/"/g, '').replace(/:/g, '=').replace(/ /g, '')
|
|
||||||
},
|
|
||||||
|
|
||||||
changPath (index) {
|
|
||||||
// 修改input的值
|
|
||||||
this.path = axios.defaults.baseURL + 'interface' + this.galaxyProxyData[index].path
|
|
||||||
this.updateUrlParams()
|
|
||||||
this.method = this.galaxyProxyData[index].method.toUpperCase()
|
|
||||||
},
|
|
||||||
|
|
||||||
send () {
|
|
||||||
// this.path = "galaxy/setting?pageNo=1&pageSize=1"
|
|
||||||
// 注意有GET与POST两种方式
|
|
||||||
if (this.method.toUpperCase() == 'GET') {
|
|
||||||
getForDebug(this.path, this.checkedDetail).then(response => {
|
|
||||||
this.proxyResponseBody = this.syntaxJson(JSON.parse(JSON.stringify(response.data)))
|
|
||||||
this.proxyResponseHeader = this.syntaxJson(JSON.parse(JSON.stringify(response.headers)))
|
|
||||||
this.proxyRequestHeader = this.syntaxJson(JSON.parse(JSON.stringify(response.config.headers)))
|
|
||||||
this.proxyResponseHeader = this.proxyResponseHeader.replace(/{/g, '').replace(/}/g, '').replace(/"/g, '')
|
|
||||||
this.proxyRequestHeader = this.proxyRequestHeader.replace(/{/g, '').replace(/}/g, '').replace(/"/g, '')
|
|
||||||
})
|
|
||||||
} else if (this.method.toUpperCase() == 'POST') {
|
|
||||||
postForDebug(this.path, this.checkedDetail).then(response => {
|
|
||||||
if (response) {
|
|
||||||
this.proxyResponseBody = this.syntaxJson(JSON.parse(JSON.stringify(response.data)))
|
|
||||||
this.proxyResponseHeader = this.syntaxJson(JSON.parse(JSON.stringify(response.headers)))
|
|
||||||
this.proxyRequestHeader = this.syntaxJson(JSON.parse(JSON.stringify(response.config.headers)))
|
|
||||||
|
|
||||||
this.proxyResponseHeader = this.proxyResponseHeader.replace(/{/g, '').replace(/}/g, '').replace(/"/g, '')
|
|
||||||
this.proxyRequestHeader = this.proxyRequestHeader.replace(/{/g, '').replace(/}/g, '').replace(/"/g, '')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 格式化json
|
|
||||||
syntaxJson (json) {
|
|
||||||
if (typeof json != 'string') {
|
|
||||||
json = JSON.stringify(json, undefined, 2)
|
|
||||||
}
|
|
||||||
return json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
|
||||||
},
|
|
||||||
closeDebug () {
|
|
||||||
this.paramsTableData = []// JSON.parse(JSON.stringify(paramsTableData))
|
|
||||||
this.proxyResponseBody = ''
|
|
||||||
this.proxyResponseHeader = ''
|
|
||||||
this.proxyRequestHeader = ''
|
|
||||||
this.name = ''
|
|
||||||
this.path = ''
|
|
||||||
this.fullPathWithParams = ''
|
|
||||||
for (const key in this.curGalaxyProxy) {
|
|
||||||
delete this.curGalaxyProxy[key]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
openDebug () {
|
|
||||||
if (this.curGalaxyProxy.path) {
|
|
||||||
this.name = this.curGalaxyProxy.name
|
|
||||||
this.path = axios.defaults.baseURL + 'interface' + this.curGalaxyProxy.path
|
|
||||||
this.fullPathWithParams = this.path
|
|
||||||
this.method = this.curGalaxyProxy.method.toUpperCase()
|
|
||||||
} else {
|
|
||||||
this.name = ''
|
|
||||||
this.path = ''
|
|
||||||
this.method = 'GET'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted () {
|
|
||||||
// 获取代理名称及路径
|
|
||||||
this.getGalaxyProxyData()
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
showDebug (n, o) {
|
|
||||||
this.show = n
|
|
||||||
},
|
|
||||||
show (n, o) {
|
|
||||||
this.$emit('update:show-debug', n)
|
|
||||||
},
|
|
||||||
path (n, o) {
|
|
||||||
this.updateUrlParams()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -4,56 +4,60 @@
|
|||||||
<div class="block-mode">
|
<div class="block-mode">
|
||||||
<!--todo 图标没有,后期换-->
|
<!--todo 图标没有,后期换-->
|
||||||
<div class="block-mode-left">
|
<div class="block-mode-left">
|
||||||
<i class="cn-icon cn-icon-setting2 block-mode-icon"></i>
|
<i class="cn-icon cn-icon-indicator-match block-mode-icon1"></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="block-mode-right">
|
<div class="block-mode-right" style="position:relative;">
|
||||||
<div class="block-mode-title">Indicator Match</div>
|
<div class="block-mode-title">{{ $t('detection.policy.indicatorMatch') }}</div>
|
||||||
<div class="block-mode-content">
|
<div class="block-mode-content">
|
||||||
Use indicators from intelligencesources to detect matchingevents and alerts.
|
{{ $t('detection.policy.indicatorMatchIntroduce') }}
|
||||||
|
<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)">select
|
@click="selectMode(detectionRuleType.indicator)">{{ $t('overall.select') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="block-mode">
|
<div class="block-mode" style="cursor: no-drop;">
|
||||||
<!--todo 图标没有,后期换-->
|
|
||||||
<div class="block-mode-left">
|
<div class="block-mode-left">
|
||||||
<i class="cn-icon cn-icon-setting2 block-mode-icon"></i>
|
<i class="cn-icon cn-icon-threshold block-mode-icon"></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="block-mode-right">
|
<div class="block-mode-right">
|
||||||
<div class="block-mode-title">Threshold</div>
|
<div class="block-mode-title">{{ $t('detection.policy.threshold') }}</div>
|
||||||
<div class="block-mode-content">
|
<div class="block-mode-content">
|
||||||
Aggregate query results to detect when number of matches exceeds threshold.
|
{{ $t('detection.policy.thresholdIntroduce') }}
|
||||||
</div>
|
</div>
|
||||||
<div :class="settingObj.ruleType===detectionRuleType.threshold?'block-mode-btn-active':'block-mode-btn'"
|
<!--todo 当前版本暂时不可选择-->
|
||||||
@click="selectMode(detectionRuleType.threshold)">select
|
<div style="cursor: no-drop;" :class="settingObj.ruleType===detectionRuleType.threshold?'block-mode-btn-active':'block-mode-btn'">
|
||||||
|
{{ $t('overall.select') }}
|
||||||
</div>
|
</div>
|
||||||
|
<!-- <div :class="settingObj.ruleType===detectionRuleType.threshold?'block-mode-btn-active':'block-mode-btn'"-->
|
||||||
|
<!-- @click="selectMode(detectionRuleType.threshold)">select-->
|
||||||
|
<!-- </div>-->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!--category-->
|
<!--category-->
|
||||||
<el-form ref="form" :model="settingObj" label-position="top" :rules="rules">
|
<el-form ref="form" :model="settingObj" label-position="top" :rules="rules">
|
||||||
<el-form-item label="Category" prop="category" class="form-setting__block margin-b-20">
|
<el-form-item :label="$t('overall.category')" prop="category" class="form-setting__block margin-b-20">
|
||||||
<el-select v-model="settingObj.category" class="form-setting__select" placeholder=" " size="mini" @change="changeEditFlag">
|
<el-select :disabled="settingObj.ruleId" v-model="settingObj.category" class="form-setting__select" placeholder=" " size="mini" @change="changeEditFlag">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in categoryList"
|
v-for="item in categoryList"
|
||||||
:key="item.value"
|
:key="item.value"
|
||||||
:label="item.label"
|
:label="$t(item.label)"
|
||||||
:value="item.value"
|
:value="item.value"
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<!--type-->
|
<!--type-->
|
||||||
<el-form-item label="Type" prop="eventType" class="form-setting__block margin-b-20">
|
<el-form-item :label="$t('overall.type')" prop="eventType" class="form-setting__block margin-b-20">
|
||||||
<el-select v-model="settingObj.eventType" placeholder=" " size="mini" class="form-setting__select" @change="changeEditFlag">
|
<el-select v-model="settingObj.eventType" placeholder=" " size="mini" class="form-setting__select" @change="changeEditFlag">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in typeList"
|
v-for="item in eventTypeList"
|
||||||
:key="item.value"
|
:key="item.value"
|
||||||
:label="item.label"
|
:label="item.label"
|
||||||
:value="item.value"
|
:value="item.value"
|
||||||
@@ -62,32 +66,32 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<!--name-->
|
<!--name-->
|
||||||
<el-form-item label="Name" prop="name" class="form-setting__block margin-b-20">
|
<el-form-item :label="$t('overall.name')" prop="name" class="form-setting__block margin-b-20">
|
||||||
<el-input
|
<el-input
|
||||||
maxlength="64"
|
maxlength="64"
|
||||||
show-word-limit
|
show-word-limit
|
||||||
placeholder=""
|
placeholder=""
|
||||||
v-model="settingObj.name"
|
v-model="settingObj.name"
|
||||||
@input="changeEditFlag"
|
@blur="changeEditFlag"
|
||||||
class="form-setting__input" />
|
class="form-setting__input" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<!--Description-->
|
<!--Description-->
|
||||||
<div class="form-setting__block margin-b-20">
|
<div class="form-setting__block margin-b-20">
|
||||||
<div class="block-title">Description</div>
|
<div class="block-title">{{ $t('config.dataSet.description') }}</div>
|
||||||
<el-input
|
<el-input
|
||||||
maxlength="255"
|
maxlength="255"
|
||||||
show-word-limit
|
show-word-limit
|
||||||
v-model="settingObj.description"
|
v-model="settingObj.description"
|
||||||
type="textarea"
|
type="textarea"
|
||||||
resize='none'
|
resize='none'
|
||||||
@input="changeEditFlag"
|
@blur="changeEditFlag"
|
||||||
class="form-setting__textarea" />
|
class="form-setting__textarea" />
|
||||||
</div>
|
</div>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<div class="form-setting__block margin-b-20">
|
<div class="form-setting__block margin-b-20">
|
||||||
<div class="block-title">Policy Status</div>
|
<div class="block-title">{{ $t('detection.create.policyStatus') }}</div>
|
||||||
<el-switch
|
<el-switch
|
||||||
v-model="settingObj.status"
|
v-model="settingObj.status"
|
||||||
@change="changeEditFlag"
|
@change="changeEditFlag"
|
||||||
@@ -95,30 +99,36 @@
|
|||||||
inactive-color="#C0CEDB"
|
inactive-color="#C0CEDB"
|
||||||
:active-value="1"
|
:active-value="1"
|
||||||
:inactive-value="0"
|
:inactive-value="0"
|
||||||
:active-text="switchStatus(settingObj.status)"/>
|
:active-text="$t(switchStatus(settingObj.status))"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-setting__btn">
|
<div class="form-setting__btn">
|
||||||
<el-button @click="onContinue">Continue</el-button>
|
<el-button @click="onContinue">{{ $t('detection.create.continue') }}</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { detectionRuleType } from '@/utils/constants'
|
import { detectionRuleType, storageKey, detectionUnitList, ZH, EN } from '@/utils/constants'
|
||||||
import { switchStatus } from '@/utils/tools'
|
import { switchStatus } from '@/utils/tools'
|
||||||
import axios from 'axios'
|
|
||||||
import { api } from '@/utils/api'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'GeneralSettings',
|
name: 'GeneralSettings',
|
||||||
|
props: {
|
||||||
|
editObj: {
|
||||||
|
type: Object
|
||||||
|
},
|
||||||
|
isComplete: {
|
||||||
|
type: Boolean
|
||||||
|
}
|
||||||
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
detectionRuleType,
|
detectionRuleType,
|
||||||
categoryList: [],
|
categoryList: [],
|
||||||
typeList: [],
|
eventTypeList: [],
|
||||||
settingObj: {
|
settingObj: {
|
||||||
ruleType: detectionRuleType.threshold,
|
ruleType: detectionRuleType.indicator,
|
||||||
category: '',
|
category: '',
|
||||||
eventType: '',
|
eventType: '',
|
||||||
name: '',
|
name: '',
|
||||||
@@ -149,6 +159,22 @@ export default {
|
|||||||
trigger: 'blur'
|
trigger: 'blur'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
language: EN,
|
||||||
|
ZH
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
editObj (newVal) {
|
||||||
|
if (newVal.ruleId) {
|
||||||
|
this.settingObj = JSON.parse(JSON.stringify({ ...newVal }))
|
||||||
|
this.settingObj.editFlag = false
|
||||||
|
this.settingObj.saveFlag = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isComplete (newVal) {
|
||||||
|
if (!newVal) {
|
||||||
|
this.onContinue()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -158,15 +184,9 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
switchStatus,
|
switchStatus,
|
||||||
initData () {
|
initData () {
|
||||||
axios.get(api.detection.statistics, { params: { pageSize: -1 } }).then(response => {
|
this.language = localStorage.getItem(storageKey.language) || EN
|
||||||
if (response.status === 200) {
|
this.categoryList = detectionUnitList.categoryList
|
||||||
this.categoryList = response.data.data.categoryList || []
|
this.eventTypeList = detectionUnitList.eventTypeList
|
||||||
this.typeList = response.data.data.typeList || []
|
|
||||||
} else {
|
|
||||||
console.error(response.data)
|
|
||||||
}
|
|
||||||
}).finally(() => {
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
selectMode (ruleType) {
|
selectMode (ruleType) {
|
||||||
this.settingObj.ruleType = ruleType
|
this.settingObj.ruleType = ruleType
|
||||||
@@ -174,9 +194,16 @@ export default {
|
|||||||
},
|
},
|
||||||
changeEditFlag () {
|
changeEditFlag () {
|
||||||
this.settingObj.editFlag = true
|
this.settingObj.editFlag = true
|
||||||
|
if (this.settingObj.ruleType && this.settingObj.category && this.settingObj.eventType && this.settingObj.name) {
|
||||||
|
this.settingObj.settingNoContinue = true
|
||||||
|
this.onContinue()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
/** 点击继续,进行第二步 */
|
/** 点击继续,进行第二步 */
|
||||||
onContinue () {
|
onContinue (e) {
|
||||||
|
if (e) {
|
||||||
|
delete this.settingObj.settingNoContinue
|
||||||
|
}
|
||||||
this.$refs.form.validate(valid => {
|
this.$refs.form.validate(valid => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
this.settingObj.editFlag = false
|
this.settingObj.editFlag = false
|
||||||
@@ -188,7 +215,3 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -9,8 +9,7 @@
|
|||||||
<div class="key-search">
|
<div class="key-search">
|
||||||
<el-input v-model="searchKey" @keyup.enter="onSearch" size="mini" placeholder="Search for">
|
<el-input v-model="searchKey" @keyup.enter="onSearch" size="mini" placeholder="Search for">
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<!--todo 该图标名称错误,已在iconfont修改,后续记得改过来-->
|
<i class="cn-icon cn-icon-search key-search-icon"></i>
|
||||||
<i class="cn-icon cn-icon-serach key-search-icon"></i>
|
|
||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
|
|
||||||
@@ -24,7 +23,7 @@
|
|||||||
<div class="key-table">
|
<div class="key-table">
|
||||||
<loading :loading="loading"></loading>
|
<loading :loading="loading"></loading>
|
||||||
|
|
||||||
<el-table :data="tableData" style="width: 100%" @row-click="rowClick">
|
<el-table :data="tableData" style="width: 100%" :row-class-name="tableRowClassName" @row-click="rowClick">
|
||||||
<el-table-column
|
<el-table-column
|
||||||
v-for="(item, index) in tableTitle"
|
v-for="(item, index) in tableTitle"
|
||||||
:key="`col-${index}`"
|
:key="`col-${index}`"
|
||||||
@@ -73,6 +72,9 @@ export default {
|
|||||||
showDrawer: {
|
showDrawer: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
|
},
|
||||||
|
delKeyId: {
|
||||||
|
type: String
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
@@ -116,6 +118,16 @@ export default {
|
|||||||
this.myDrawer = this.showDrawer
|
this.myDrawer = this.showDrawer
|
||||||
this.getTopKeysData()
|
this.getTopKeysData()
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
delKeyId (newVal) {
|
||||||
|
if (newVal) {
|
||||||
|
const obj = this.tableData.find(d => d.keyId === newVal)
|
||||||
|
if (obj) {
|
||||||
|
obj.filterKey = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
unitConvert,
|
unitConvert,
|
||||||
dateFormatByAppearance,
|
dateFormatByAppearance,
|
||||||
@@ -150,6 +162,7 @@ export default {
|
|||||||
},
|
},
|
||||||
/** 单击topKeys弹窗某一项 */
|
/** 单击topKeys弹窗某一项 */
|
||||||
rowClick (data) {
|
rowClick (data) {
|
||||||
|
data.filterKey = true
|
||||||
this.$emit('keyRowClick', data)
|
this.$emit('keyRowClick', data)
|
||||||
},
|
},
|
||||||
onRefresh () {
|
onRefresh () {
|
||||||
@@ -161,6 +174,11 @@ export default {
|
|||||||
httpError (e) {
|
httpError (e) {
|
||||||
this.showError = true
|
this.showError = true
|
||||||
this.errorMsg = this.errorMsgHandler(e)
|
this.errorMsg = this.errorMsgHandler(e)
|
||||||
|
},
|
||||||
|
tableRowClassName (row) {
|
||||||
|
if (row.row.filterKey) {
|
||||||
|
return 'key-click-row'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -231,4 +249,8 @@ export default {
|
|||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.el-table .key-click-row {
|
||||||
|
background: #F5F7FA !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<el-form ref="form" :model="thresholdRuleObj" label-position="top" :rules="rules">
|
<el-form ref="form" :model="thresholdRuleObj" label-position="top" :rules="rules">
|
||||||
<!--source-->
|
<!--source-->
|
||||||
<el-form-item label="Source" prop="dataSource" class="form-setting__block margin-b-20">
|
<el-form-item :label="$t('config.user.source')" prop="dataSource" class="form-setting__block margin-b-20">
|
||||||
<el-select v-model="thresholdRuleObj.dataSource" placeholder=" " size="mini" class="form-setting__select">
|
<el-select v-model="thresholdRuleObj.dataSource" placeholder=" " size="mini" class="form-setting__select">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in sourceList"
|
v-for="item in sourceList"
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
<!--Dimensions-->
|
<!--Dimensions-->
|
||||||
<div class="form-setting__block margin-b-20">
|
<div class="form-setting__block margin-b-20">
|
||||||
<div class="block-title">Dimensions</div>
|
<div class="block-title">{{ $t('detection.create.dimensions') }}</div>
|
||||||
<div class="block-dimension">
|
<div class="block-dimension">
|
||||||
<div class="block-dimension-tag" v-for="(ite, ind) in dimensionList" :key="ind">{{ ite.label }}</div>
|
<div class="block-dimension-tag" v-for="(ite, ind) in dimensionList" :key="ind">{{ ite.label }}</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
size="mini"
|
size="mini"
|
||||||
oninput="value=value.replace(/[^\d]/g,'')"
|
oninput="value=value.replace(/[^\d]/g,'')"
|
||||||
v-model="item.value"></el-input>
|
v-model="item.value"></el-input>
|
||||||
<i class="cn-icon cn-icon-close" @click="delFilterItem(index)"></i>
|
<i class="cn-icon cn-icon-close" @click="delFilterItem(index, item)"></i>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="height: 10px;"></div>
|
<div style="height: 10px;"></div>
|
||||||
@@ -65,7 +65,7 @@
|
|||||||
|
|
||||||
<!--Condition模块-->
|
<!--Condition模块-->
|
||||||
<div class="form-setting__block margin-b-20">
|
<div class="form-setting__block margin-b-20">
|
||||||
<div class="block-title">Condition</div>
|
<div class="block-title">{{ $t('detection.create.condition') }}</div>
|
||||||
|
|
||||||
<el-form ref="form2" :model="thresholdRuleObj" label-position="top">
|
<el-form ref="form2" :model="thresholdRuleObj" label-position="top">
|
||||||
<div class="definition-condition-block" v-for="(item, index) in thresholdRuleObj.conditionData" :key="index">
|
<div class="definition-condition-block" v-for="(item, index) in thresholdRuleObj.conditionData" :key="index">
|
||||||
@@ -97,7 +97,7 @@
|
|||||||
v-for="item in metricList"
|
v-for="item in metricList"
|
||||||
:key="item.label"
|
:key="item.label"
|
||||||
:label="item.label"
|
:label="item.label"
|
||||||
:value="item.value"
|
:value="item.label"
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -144,7 +144,7 @@
|
|||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<div class="condition-add" @click="addCondition">
|
<div class="condition-add" @click="addCondition">
|
||||||
<i class="cn-icon cn-icon-add"></i>Add Condition
|
<i class="cn-icon cn-icon-add"></i>{{ $t('detection.create.addCondition') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -154,6 +154,7 @@
|
|||||||
<history-top-keys
|
<history-top-keys
|
||||||
v-if="showDrawer"
|
v-if="showDrawer"
|
||||||
:showDrawer="showDrawer"
|
:showDrawer="showDrawer"
|
||||||
|
:delKeyId="delKeyId"
|
||||||
@closeDrawer="onCloseDrawer"
|
@closeDrawer="onCloseDrawer"
|
||||||
@keyRowClick="getRowClick"
|
@keyRowClick="getRowClick"
|
||||||
></history-top-keys>
|
></history-top-keys>
|
||||||
@@ -163,24 +164,24 @@
|
|||||||
<div v-if="mySettingObj.ruleType===detectionRuleType.indicator">
|
<div v-if="mySettingObj.ruleType===detectionRuleType.indicator">
|
||||||
<el-form ref="form" :model="indicatorRuleObj" label-position="top" :rules="rules">
|
<el-form ref="form" :model="indicatorRuleObj" label-position="top" :rules="rules">
|
||||||
<!--Source-->
|
<!--Source-->
|
||||||
<el-form-item label="Source" prop="dataSource" class="form-setting__block margin-b-20">
|
<el-form-item :label="$t('config.user.source')" prop="dataSource" class="form-setting__block margin-b-20">
|
||||||
<el-select v-model="indicatorRuleObj.dataSource" class="form-setting__select" placeholder=" " size="mini">
|
<el-select v-model="indicatorRuleObj.dataSource" class="form-setting__select" placeholder=" " size="mini" @change="handleParamsComplete">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in sourceList"
|
v-for="item in sourceList"
|
||||||
:key="item.value"
|
:key="item.value"
|
||||||
:label="item.label"
|
:label="$t(item.label)"
|
||||||
:value="item.value"
|
:value="item.value"
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<!--Library-->
|
<!--Library-->
|
||||||
<el-form-item label="Library" prop="knowledgeId" class="form-setting__block margin-b-20">
|
<el-form-item :label="$t('detection.library')" prop="knowledgeId" class="form-setting__block margin-b-20">
|
||||||
<el-select v-model="indicatorRuleObj.knowledgeId" class="form-setting__select" placeholder=" " size="mini">
|
<el-select v-model="indicatorRuleObj.knowledgeId" class="form-setting__select" filterable placeholder=" " size="mini" @change="handleParamsComplete">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in libraryList"
|
v-for="item in libraryList"
|
||||||
:key="item.knowledgeId"
|
:key="item.knowledgeId"
|
||||||
:label="item.label"
|
:label="item.name"
|
||||||
:value="item.knowledgeId"
|
:value="item.knowledgeId"
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
@@ -188,7 +189,7 @@
|
|||||||
|
|
||||||
<!--Level-->
|
<!--Level-->
|
||||||
<el-form-item :label="$t('detection.level')" prop="level" class="form-setting__block">
|
<el-form-item :label="$t('detection.level')" prop="level" class="form-setting__block">
|
||||||
<el-select v-model="indicatorRuleObj.level" class="condition__select form-setting__select" placeholder=" " size="mini">
|
<el-select v-model="indicatorRuleObj.level" class="condition__select form-setting__select" placeholder=" " size="mini" @change="handleParamsComplete">
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<div
|
<div
|
||||||
class="condition__select__icon"
|
class="condition__select__icon"
|
||||||
@@ -198,7 +199,7 @@
|
|||||||
<el-option
|
<el-option
|
||||||
v-for="item in levelList"
|
v-for="item in levelList"
|
||||||
:key="item.label"
|
:key="item.label"
|
||||||
:label="item.label"
|
:label="$t(item.label)"
|
||||||
:value="item.value"
|
:value="item.value"
|
||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
@@ -207,22 +208,29 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-setting__btn">
|
<div class="form-setting__btn">
|
||||||
<el-button @click="onContinue">Continue</el-button>
|
<el-button @click="onContinue">{{ $t('detection.create.continue') }}</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import axios from 'axios'
|
|
||||||
import { api } from '@/utils/api'
|
|
||||||
import HistoryTopKeys from '@/components/table/detection/HistoryTopKeys'
|
import HistoryTopKeys from '@/components/table/detection/HistoryTopKeys'
|
||||||
import { eventSeverityColor, detectionRuleType } from '@/utils/constants'
|
import { eventSeverityColor, detectionRuleType, detectionUnitList, securityLevel } from '@/utils/constants'
|
||||||
|
import axios from 'axios'
|
||||||
|
import _ from 'lodash'
|
||||||
|
import { api } from '@/utils/api'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'RuleDefinition',
|
name: 'RuleDefinition',
|
||||||
props: {
|
props: {
|
||||||
settingObj: {
|
settingObj: {
|
||||||
type: Object
|
type: Object
|
||||||
|
},
|
||||||
|
editObj: {
|
||||||
|
type: Object
|
||||||
|
},
|
||||||
|
isComplete: {
|
||||||
|
type: Boolean
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
@@ -232,11 +240,31 @@ export default {
|
|||||||
settingObj: {
|
settingObj: {
|
||||||
immediate: true,
|
immediate: true,
|
||||||
deep: true,
|
deep: true,
|
||||||
handler (newVal, oldVal) {
|
handler (newVal) {
|
||||||
if (!newVal.editFlag && newVal.saveFlag) {
|
if (!newVal.editFlag && newVal.saveFlag) {
|
||||||
this.mySettingObj = JSON.parse(JSON.stringify(newVal))
|
this.mySettingObj = JSON.parse(JSON.stringify(newVal))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
editObj: {
|
||||||
|
immediate: true,
|
||||||
|
deep: true,
|
||||||
|
handler (newVal) {
|
||||||
|
if (newVal) {
|
||||||
|
if (newVal.ruleType === detectionRuleType.indicator) {
|
||||||
|
this.indicatorRuleObj = this.$_.cloneDeep(newVal.ruleConfigObj)
|
||||||
|
this.indicatorRuleObj.knowledgeId = newVal.ruleConfigObj.knowledgeBase.knowledgeId
|
||||||
|
}
|
||||||
|
if (newVal.ruleType === detectionRuleType.threshold) {
|
||||||
|
this.thresholdRuleObj = this.$_.cloneDeep(newVal.ruleConfigObj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isComplete (newVal) {
|
||||||
|
if (!newVal) {
|
||||||
|
this.onContinue()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
@@ -244,7 +272,7 @@ export default {
|
|||||||
eventSeverityColor,
|
eventSeverityColor,
|
||||||
detectionRuleType,
|
detectionRuleType,
|
||||||
mySettingObj: {
|
mySettingObj: {
|
||||||
ruleType: detectionRuleType.threshold
|
ruleType: detectionRuleType.indicator
|
||||||
},
|
},
|
||||||
dimensionList: [], // Dimensions数据
|
dimensionList: [], // Dimensions数据
|
||||||
// ruleType为Indicator时表单数据
|
// ruleType为Indicator时表单数据
|
||||||
@@ -327,7 +355,8 @@ export default {
|
|||||||
than: '>',
|
than: '>',
|
||||||
less: '<',
|
less: '<',
|
||||||
equal: '='
|
equal: '='
|
||||||
}
|
},
|
||||||
|
delKeyId: '' // 删除的keyId
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
@@ -341,18 +370,31 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
initData () {
|
initData () {
|
||||||
axios.get(api.detection.statistics, { params: { pageSize: -1 } }).then(response => {
|
this.sourceList = detectionUnitList.sourceList || []
|
||||||
|
this.levelList = securityLevel || []
|
||||||
|
// threshold模式还没确定,所以数据暂时静态数据,后续根据需要修改
|
||||||
|
this.conditionList = detectionUnitList.conditionList || []
|
||||||
|
this.metricList = detectionUnitList.metricList || []
|
||||||
|
|
||||||
|
if (this.mySettingObj.ruleType === this.detectionRuleType.indicator) {
|
||||||
|
axios.get(api.knowledgeBaseList, { params: { pageSize: -1 } }).then(response => {
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
this.sourceList = response.data.data.sourceList || []
|
this.libraryList = _.get(response, 'data.data.list', []).filter(l => l.isBuiltIn === 0)
|
||||||
this.levelList = response.data.data.levelList || []
|
|
||||||
this.conditionList = response.data.data.conditionList || []
|
|
||||||
this.metricList = response.data.data.metricList || []
|
|
||||||
this.libraryList = response.data.data.libraryList || []
|
|
||||||
} else {
|
} else {
|
||||||
console.error(response.data)
|
console.error(response.data.message)
|
||||||
|
this.libraryList = []
|
||||||
|
if (response.data.message) {
|
||||||
|
this.$message.error(response.data.message)
|
||||||
|
} else {
|
||||||
|
this.$message.error(this.$t('tip.somethingWentWrong'))
|
||||||
}
|
}
|
||||||
}).finally(() => {
|
}
|
||||||
|
}).catch(e => {
|
||||||
|
console.error(e)
|
||||||
|
this.libraryList = []
|
||||||
|
this.$message.error(this.errorMsgHandler(e))
|
||||||
})
|
})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
/** 单击History Top Keys列表某行,filter添加数据 */
|
/** 单击History Top Keys列表某行,filter添加数据 */
|
||||||
getRowClick (data) {
|
getRowClick (data) {
|
||||||
@@ -364,6 +406,7 @@ export default {
|
|||||||
},
|
},
|
||||||
/** filter模块点击add按钮 */
|
/** filter模块点击add按钮 */
|
||||||
addFilter (data) {
|
addFilter (data) {
|
||||||
|
this.delKeyId = ''
|
||||||
this.showFilter = true
|
this.showFilter = true
|
||||||
if (this.selectList.length === 0) {
|
if (this.selectList.length === 0) {
|
||||||
this.getFilterList()
|
this.getFilterList()
|
||||||
@@ -445,11 +488,15 @@ export default {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
/** 删除filter某一项 */
|
/** 删除filter某一项 */
|
||||||
delFilterItem (i) {
|
delFilterItem (i, item) {
|
||||||
|
this.delKeyId = item.keyId
|
||||||
this.thresholdRuleObj.filterList.splice(i, 1)
|
this.thresholdRuleObj.filterList.splice(i, 1)
|
||||||
},
|
},
|
||||||
/** 点击继续,展开第三步 */
|
/** 点击继续,展开第三步 */
|
||||||
onContinue () {
|
onContinue (e) {
|
||||||
|
if (e) {
|
||||||
|
delete this.indicatorRuleObj.ruleNoContinue
|
||||||
|
}
|
||||||
this.$refs.form.validate(valid => {
|
this.$refs.form.validate(valid => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
if (this.mySettingObj.ruleType === detectionRuleType.indicator) {
|
if (this.mySettingObj.ruleType === detectionRuleType.indicator) {
|
||||||
@@ -482,6 +529,12 @@ export default {
|
|||||||
obj[item.level] = str
|
obj[item.level] = str
|
||||||
})
|
})
|
||||||
this.thresholdRuleObj.conditions = obj
|
this.thresholdRuleObj.conditions = obj
|
||||||
|
},
|
||||||
|
handleParamsComplete () {
|
||||||
|
if (this.indicatorRuleObj.dataSource && this.indicatorRuleObj.knowledgeId && this.indicatorRuleObj.level) {
|
||||||
|
this.indicatorRuleObj.ruleNoContinue = true
|
||||||
|
this.onContinue()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,15 @@
|
|||||||
@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 v-else-if="item.prop === 'color'">
|
||||||
|
<div class="knowledge-color">
|
||||||
|
<span class="knowledge-color__icon" :class="colorName(scope.row[item.prop])"></span> <span>{{colorText(scope.row[item.prop])}}</span>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<span v-else>{{scope.row[item.prop] || '-'}}</span>
|
<span v-else>{{scope.row[item.prop] || '-'}}</span>
|
||||||
</template>
|
</template>
|
||||||
@@ -151,6 +163,11 @@ export default {
|
|||||||
}, {
|
}, {
|
||||||
label: this.$t('knowledge.reference'),
|
label: this.$t('knowledge.reference'),
|
||||||
prop: 'reference',
|
prop: 'reference',
|
||||||
|
width: 190,
|
||||||
|
show: true
|
||||||
|
}, {
|
||||||
|
label: this.$t('overall.color'),
|
||||||
|
prop: 'color',
|
||||||
width: 180,
|
width: 180,
|
||||||
show: true
|
show: true
|
||||||
}, {
|
}, {
|
||||||
@@ -189,6 +206,23 @@ export default {
|
|||||||
show: true,
|
show: true,
|
||||||
width: 80
|
width: 80
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
knowledgeBaseColor: [
|
||||||
|
{
|
||||||
|
label: this.$t('knowledge.info'),
|
||||||
|
value: 'rgb(119,131,145)',
|
||||||
|
name: 'info'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: this.$t('knowledge.benign'),
|
||||||
|
value: 'rgb(116,159,77)',
|
||||||
|
name: 'benign'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: this.$t('knowledge.malicious'),
|
||||||
|
value: 'rgb(226,97,84)',
|
||||||
|
name: 'malicious'
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -221,6 +255,20 @@ export default {
|
|||||||
const t = knowledgeBaseSource.find(t => t.value === type)
|
const t = knowledgeBaseSource.find(t => t.value === type)
|
||||||
return t ? t.name : ''
|
return t ? t.name : ''
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
colorText () {
|
||||||
|
const vm = this
|
||||||
|
return function (color) {
|
||||||
|
const t = vm.knowledgeBaseColor.find(t => t.value === color)
|
||||||
|
return t ? t.label : vm.knowledgeBaseColor[0].label
|
||||||
|
}
|
||||||
|
},
|
||||||
|
colorName () {
|
||||||
|
const vm = this
|
||||||
|
return function (color) {
|
||||||
|
const t = vm.knowledgeBaseColor.find(t => t.value === color)
|
||||||
|
return t ? t.name : vm.knowledgeBaseColor[0].name
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,35 +6,27 @@
|
|||||||
<div @click="isSelectedStatus && data.isBuiltIn !== 1 && clickCard(data,$event)" @mouseenter="mouseenter(data)" @mouseleave="mouseleave(data)" class="card-item" :class="data.isSelected ? 'card-selected' : ''">
|
<div @click="isSelectedStatus && data.isBuiltIn !== 1 && clickCard(data,$event)" @mouseenter="mouseenter(data)" @mouseleave="mouseleave(data)" class="card-item" :class="data.isSelected ? 'card-selected' : ''">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<div class="card-operate">
|
<div class="card-operate">
|
||||||
<el-tooltip
|
|
||||||
effect="light"
|
|
||||||
trigger="hover"
|
|
||||||
:content="$t('tip.notAvailable')"
|
|
||||||
placement="right"
|
|
||||||
popper-class="panel-tooltip"
|
|
||||||
>
|
|
||||||
<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"
|
||||||
:disabled="true"
|
|
||||||
:active-value="1"
|
:active-value="1"
|
||||||
:inactive-value="0"
|
:inactive-value="0"
|
||||||
@change="changeStatus($event,data.knowledgeId)"
|
:before-change="(knowledgeId) => confirmSwitchLearning(data.knowledgeId)"
|
||||||
>
|
>
|
||||||
</el-switch>
|
</el-switch>
|
||||||
</el-tooltip>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="card-icon">
|
<div class="card-icon">
|
||||||
<img :src="data.iconUrl"/>
|
<img :src="data.iconUrl"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-title">
|
<div class="card-title">
|
||||||
<div class="card-title-name" :title="data.label">{{data.label}}</div>
|
<div class="card-title-name" :title="$t(data.label)">{{$t(data.label)}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-desc" :title="data.desc">{{data.desc ? data.desc : '—'}}</div>
|
<div class="card-desc" :title="$t(data.desc)">{{$t(data.desc) || '—'}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-operate__footer">
|
<div class="card-operate__footer">
|
||||||
<button v-if="data.showUpdate"
|
<button v-if="data.showUpdate && hasPermission('editBuiltInKnowledgeBase')"
|
||||||
class="top-tool-btn--update"
|
class="top-tool-btn--update"
|
||||||
@click="jumpToUpdatePage(data,true)">
|
@click="jumpToUpdatePage(data,true)">
|
||||||
<i class="cn-icon-update-knowledge-base cn-icon"></i>
|
<i class="cn-icon-update-knowledge-base cn-icon"></i>
|
||||||
@@ -53,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>
|
||||||
@@ -75,7 +67,9 @@
|
|||||||
|
|
||||||
<div class="center-dialog">
|
<div class="center-dialog">
|
||||||
<el-dialog v-model="showUpdateDialog"
|
<el-dialog v-model="showUpdateDialog"
|
||||||
|
:destroy-on-close="true"
|
||||||
:custom-class="showAddUpdateDialog ? 'update-knowledge update-knowledge--upload' : 'update-knowledge'"
|
:custom-class="showAddUpdateDialog ? 'update-knowledge update-knowledge--upload' : 'update-knowledge'"
|
||||||
|
:before-close="beforeClose"
|
||||||
:after-close="handleClose">
|
:after-close="handleClose">
|
||||||
<div class="knowledge-update__top" >
|
<div class="knowledge-update__top" >
|
||||||
<div class="update-left__icon">
|
<div class="update-left__icon">
|
||||||
@@ -84,60 +78,144 @@
|
|||||||
<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-tooltip
|
|
||||||
effect="light"
|
|
||||||
trigger="hover"
|
|
||||||
v-if="showEnable"
|
|
||||||
:content="$t('tip.notAvailable')"
|
|
||||||
placement="right"
|
|
||||||
popper-class="panel-tooltip"
|
|
||||||
>
|
|
||||||
<el-switch v-model="updateKnowledge.status"
|
<el-switch v-model="updateKnowledge.status"
|
||||||
active-color="#38ACD2"
|
active-color="#38ACD2"
|
||||||
inactive-color="#C0CEDB"
|
inactive-color="#C0CEDB"
|
||||||
:disabled="true"
|
|
||||||
:active-value="1"
|
:active-value="1"
|
||||||
:inactive-value="0"
|
:inactive-value="0"
|
||||||
@change="changeStatus($event,updateKnowledge.knowledgeId)"
|
:before-change="(knowledgeId) => confirmSwitchLearning(updateKnowledge.knowledgeId)"
|
||||||
|
v-if="updateKnowledge.source === 'cn_psiphon3_ip' && hasPermission('editBuiltInKnowledgeBase')"
|
||||||
>
|
>
|
||||||
</el-switch>
|
</el-switch>
|
||||||
</el-tooltip>
|
|
||||||
</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">
|
||||||
<div class="knowledge-update" >
|
<div class="knowledge-update__tab" v-if="showEnable">
|
||||||
<div class="update-title">
|
<el-tabs v-model="activeTab"
|
||||||
<div class="card-title-name">update record</div>
|
class="update-log-tab"
|
||||||
</div>
|
@tab-click="handleClick"
|
||||||
|
>
|
||||||
|
<el-tab-pane :label="$t('knowledgeBase.updateRecord')"
|
||||||
|
name="updateRecord"
|
||||||
|
key="updateRecord"
|
||||||
|
ref="knowledgeUpdateRecordTab">
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane :label="$t('knowledgeBase.learningEngineLogs')"
|
||||||
|
name="intelligenceLearning"
|
||||||
|
key="intelligenceLearning"
|
||||||
|
ref="knowledgeIntelligenceLearningTab">
|
||||||
|
</el-tab-pane>
|
||||||
|
</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>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="knowledge-update" v-else>
|
||||||
|
<div class="update-title" >
|
||||||
|
<div class="card-title-name">{{$t('knowledgeBase.updateRecord')}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="update-operate">
|
||||||
|
<button :title="$t('overall.update')" class="top-tool-btn--update"
|
||||||
|
@click="uploadRecord"><!-- :disabled="hasUpdatingRecord" -->
|
||||||
|
<i class="cn-icon-update-knowledge-base cn-icon"></i>
|
||||||
|
<span>{{$t('overall.update')}}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div :style="{height: updateKnowledge.source === 'cn_psiphon3_ip' && activeTab === 'intelligenceLearning' ? 'calc(90vh - 190px - 200px - 50px - 42px)' : 'calc(100% - 242px)', marginTop: '42px', position: 'absolute', width: 'calc(100% - 60px)'}">
|
||||||
|
<loading :loading="updateLogLoading"></loading>
|
||||||
|
</div>
|
||||||
<el-table ref="updateDataTable"
|
<el-table ref="updateDataTable"
|
||||||
border
|
border
|
||||||
:data="updateHistoryList"
|
:data="updateHistoryList"
|
||||||
@selection-change="secondSelectionChange"
|
@selection-change="secondSelectionChange"
|
||||||
width="100%"
|
width="100%"
|
||||||
class="update-dialog__table"
|
class="update-dialog__table"
|
||||||
|
:class="{
|
||||||
|
'update-dialog__table--psiphon3': updateKnowledge.source === 'cn_psiphon3_ip' && activeTab === 'intelligenceLearning',
|
||||||
|
'update-dialog__table--system-user': updateKnowledge.source === 'cn_psiphon3_ip' && activeTab !== 'intelligenceLearning'
|
||||||
|
}"
|
||||||
|
:header-cell-style="{background:'#f5f7fa',color:'#353636',fontWeight: '400',fontSize: '12px',borderRight: 'none',borderBottom: 'none'}"
|
||||||
cell-style="padding:6px 0px;font-size: 12px;color: #353636;font-weight: 400;line-height: 20px;border-right:none;"
|
cell-style="padding:6px 0px;font-size: 12px;color: #353636;font-weight: 400;line-height: 20px;border-right:none;"
|
||||||
header-cell-style="padding:8px 0px;font-size: 12px;color: #353636;font-weight: 500;border-right:none;">
|
header-cell-style="padding:8px 0px;font-size: 12px;color: #353636;font-weight: 500;border-right:none;">
|
||||||
<el-table-column prop="opTime" label="Update time" width="150" ></el-table-column>
|
<el-table-column prop="opTime" :label="$t('entities.tab.informationAggregation.updateTime')" width="150" >
|
||||||
<el-table-column prop="user" label="Operating user" width="150" >
|
<template #default="scope" :column="item">
|
||||||
|
<span>{{scope.row.opTime ? dateFormatByAppearance(scope.row.opTime) : '-'}}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="user" :label="$t('knowledgeBase.operator')" width="150" v-if="updateKnowledge.source !== 'cn_psiphon3_ip' || activeTab === 'updateRecord'">
|
||||||
<template #default="scope" :column="item">
|
<template #default="scope" :column="item">
|
||||||
<span>{{$_.get(scope.row, 'user.name', '-')}}</span>
|
<span>{{$_.get(scope.row, 'user.name', '-')}}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="commitVersion" label="Version information" width="150" ></el-table-column>
|
<el-table-column prop="commitVersion" :label="$t('overall.version')" width="150" ></el-table-column>
|
||||||
<el-table-column prop="description" label="Description"></el-table-column>
|
<el-table-column prop="description" :label="$t('overall.remark')"></el-table-column>
|
||||||
|
<template v-slot:empty >
|
||||||
|
<div class="table-no-data" v-if="updateHistoryList.length === 0 && !updateLogLoading">
|
||||||
|
<div class="table-no-data__title">{{ $t('npm.noData') }}</div>
|
||||||
|
</div>
|
||||||
|
<div v-else></div>
|
||||||
|
</template>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
|
<div class="psiphon3" v-if="updateKnowledge.source === 'cn_psiphon3_ip' && activeTab === 'intelligenceLearning'">
|
||||||
|
<div class="psiphon3-title">{{$t('knowledgeBase.psiphon3IpCount')}}</div>
|
||||||
|
<div class="psiphon3-bar">
|
||||||
|
<chart-error v-if="showErrorForPsiphon3" :content="errorMsgForPsiphon3"/>
|
||||||
|
<div class="bar-header" v-else>
|
||||||
|
<div class="bar-header-left">
|
||||||
|
<div class="bar-value-active" ></div>
|
||||||
|
<div class="bar-value">
|
||||||
|
<template v-for="(item, index) in tabs" :key="index">
|
||||||
|
<div class="bar-value-tabs"
|
||||||
|
:class=" {'is-active': tabType === item.class, 'mousemove-cursor': mousemoveCursor === item.class}"
|
||||||
|
@mouseenter="mouseenterTab(item)"
|
||||||
|
@mouseleave="mouseleaveTab(item)"
|
||||||
|
@click="activeChange(item)"
|
||||||
|
>
|
||||||
|
<div class="bar-value-tabs-name">
|
||||||
|
<div :class="item.class"></div>
|
||||||
|
<div class="tabs-name" >{{ $t(item.name) }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bar-select bar-header-right">
|
||||||
|
<div class="bar-select-time">
|
||||||
|
<div class="bar-select__operation">
|
||||||
|
<el-select
|
||||||
|
size="mini"
|
||||||
|
v-model="selectTime"
|
||||||
|
placeholder=" "
|
||||||
|
popper-class="common-select"
|
||||||
|
:popper-append-to-body="false"
|
||||||
|
@change="timeChange"
|
||||||
|
>
|
||||||
|
<template #prefix>
|
||||||
|
<div class="calendar-popover-text"><i class="cn-icon cn-icon-Data"></i></div>
|
||||||
|
</template>
|
||||||
|
<el-option v-for="item in dateRangeArr" :key="item.value" :label="item.name" :value="item.value"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="height: calc(100% - 24px); position: relative">
|
||||||
|
<chart-no-data v-if="isNoDataForPsiphon3 && !showErrorForPsiphon3 && !psiphon3Loading"></chart-no-data>
|
||||||
|
<loading :loading="psiphon3Loading"></loading>
|
||||||
|
<div class="chart-drawing" v-show="!isNoDataForPsiphon3 && !showErrorForPsiphon3" id="psiphonBarChart"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-if="showAddUpdateDialog">
|
<template v-if="showAddUpdateDialog">
|
||||||
<div class="update-knowledge-form">
|
<div class="update-knowledge-form">
|
||||||
@@ -179,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>
|
||||||
@@ -187,6 +265,7 @@
|
|||||||
<el-dialog v-model="showConfirmDialog"
|
<el-dialog v-model="showConfirmDialog"
|
||||||
:title="$t('overall.tips')"
|
:title="$t('overall.tips')"
|
||||||
custom-class="update-knowledge-tip"
|
custom-class="update-knowledge-tip"
|
||||||
|
:width="480"
|
||||||
:before-close="handleConfirmClose">
|
:before-close="handleConfirmClose">
|
||||||
<div class="dialog-message">{{$t('knowledge.updateTips')}}</div>
|
<div class="dialog-message">{{$t('knowledge.updateTips')}}</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
@@ -196,18 +275,37 @@
|
|||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
<el-dialog
|
||||||
|
v-model="showConfirmSwitch"
|
||||||
|
:width="330"
|
||||||
|
custom-class="confirm-knowledge-switch"
|
||||||
|
:title="$t('overall.hint')"
|
||||||
|
>
|
||||||
|
<div class="dialog-message">{{ confirmSwitchLearningTip }}</div>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="cancleSwitch">{{ $t('overall.cancel') }}</el-button>
|
||||||
|
<el-button type="primary" @click="switchLearning">{{$t('tip.confirm')}}</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import table from '@/mixins/table'
|
import table from '@/mixins/table'
|
||||||
import Loading from '@/components/common/Loading'
|
import Loading from '@/components/common/Loading'
|
||||||
import { knowledgeCategoryValue, unitTypes, storageKey, builtInKnowledgeBaseBasicInfo } from '@/utils/constants'
|
import { getSecond, getMillisecond, xAxisTimeFormatter, xAxisTimeRich } from '@/utils/date-util'
|
||||||
import { ref } from 'vue'
|
import { knowledgeCategoryValue, unitTypes, storageKey, builtInKnowledgeBaseBasicInfo, knowledgeCardUpdateRecordType } from '@/utils/constants'
|
||||||
|
import { ref, shallowRef } from 'vue'
|
||||||
import { api } from '@/utils/api'
|
import { api } from '@/utils/api'
|
||||||
|
import { detectionTooltipFormatter } from '@/views/charts/charts/tools'
|
||||||
|
import ChartNoData from '@/views/charts/charts/ChartNoData'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
import * as echarts from 'echarts'
|
||||||
import unitConvert from '@/utils/unit-convert'
|
import unitConvert from '@/utils/unit-convert'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'knowledgeBaseTableForCard',
|
name: 'knowledgeBaseTableForCard',
|
||||||
mixins: [table],
|
mixins: [table],
|
||||||
@@ -221,7 +319,8 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
Loading
|
Loading,
|
||||||
|
ChartNoData
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
@@ -237,7 +336,48 @@ export default {
|
|||||||
updateHistoryList: [],
|
updateHistoryList: [],
|
||||||
updateObject: {},
|
updateObject: {},
|
||||||
currentVersion: 0,
|
currentVersion: 0,
|
||||||
uploadLoading: false
|
uploadLoading: false,
|
||||||
|
psiphon3Loading: false,
|
||||||
|
updateLogLoading: false,
|
||||||
|
showConfirmSwitch: false,
|
||||||
|
// timer: null,
|
||||||
|
switchKnowledgeId: '',
|
||||||
|
activeTab: 'updateRecord',
|
||||||
|
isNoDataForPsiphon3: false,
|
||||||
|
showErrorForPsiphon3: false,
|
||||||
|
errorMsgForPsiphon3: '',
|
||||||
|
leftOffset: 0,
|
||||||
|
tabType: 'total',
|
||||||
|
mousemoveCursor: '',
|
||||||
|
selectTime: 1440,
|
||||||
|
// hasUpdatingRecord: false,
|
||||||
|
tabs: [
|
||||||
|
{
|
||||||
|
name: 'knowledgeBase.total',
|
||||||
|
class: 'total',
|
||||||
|
color: '#00A7AB',
|
||||||
|
data: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'knowledgeBase.active',
|
||||||
|
class: 'active',
|
||||||
|
color: '#7FA054',
|
||||||
|
data: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'knowledgeBase.new',
|
||||||
|
class: 'new',
|
||||||
|
color: '#98709B',
|
||||||
|
data: []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
dateRangeArr: [
|
||||||
|
{ value: 1440, name: this.$t('dateTime.last1Day') },
|
||||||
|
{ value: 2880, name: this.$t('dateTime.last2Days') },
|
||||||
|
{ value: 10080, name: this.$t('dateTime.last7Days') },
|
||||||
|
{ value: 21600, name: this.$t('dateTime.last15Days') },
|
||||||
|
{ value: 43200, name: this.$t('dateTime.last30Days') }
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
setup () {
|
setup () {
|
||||||
@@ -252,13 +392,177 @@ export default {
|
|||||||
uploadErrorTip,
|
uploadErrorTip,
|
||||||
fileTypeLimit: '.csv',
|
fileTypeLimit: '.csv',
|
||||||
fileList: ref([]),
|
fileList: ref([]),
|
||||||
uploadFileSizeLimit: 100 * 1024 * 1024
|
uploadFileSizeLimit: 1024 * 1024 * 1024,
|
||||||
|
myChart: shallowRef(null),
|
||||||
|
chartOption: shallowRef(null)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
echartsInit (echartsData) {
|
||||||
|
const _this = this
|
||||||
|
const curTab = this.tabs.find(item => item.class === _this.tabType)
|
||||||
|
this.chartOption = {
|
||||||
|
color: curTab.color,
|
||||||
|
legend: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
show: true,
|
||||||
|
formatter: (params) => {
|
||||||
|
params.seriesName = this.$t(params.seriesName)
|
||||||
|
params.borderColor = params.color
|
||||||
|
return detectionTooltipFormatter(params)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
top: '12%',
|
||||||
|
left: '2%',
|
||||||
|
right: '2%',
|
||||||
|
bottom: 24,
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'time',
|
||||||
|
axisLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisTick: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
formatter: xAxisTimeFormatter,
|
||||||
|
rich: xAxisTimeRich
|
||||||
|
}
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
splitLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: '#ECECEC'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
margin: 20
|
||||||
|
},
|
||||||
|
minInterval: 1
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: curTab.name,
|
||||||
|
data: echartsData,
|
||||||
|
type: 'bar',
|
||||||
|
barWidth: 26
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (!this.myChart) {
|
||||||
|
this.myChart = echarts.init(document.getElementById('psiphonBarChart'))
|
||||||
|
}
|
||||||
|
this.myChart.setOption(this.chartOption)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
init (val, show, active, n) {
|
||||||
|
this.psiphon3Loading = true
|
||||||
|
const endTime = window.$dayJs.tz().valueOf()
|
||||||
|
const params = {
|
||||||
|
startTime: getSecond(endTime - this.selectTime * 60 * 1000),
|
||||||
|
endTime: getSecond(endTime)
|
||||||
|
}
|
||||||
|
const url = api.knowledgeBaseTimedistribution.replace('{{knowledgeId}}', this.updateKnowledge.knowledgeId).replace('{{type}}', this.tabType)
|
||||||
|
axios.get(url, { params: params }).then(response => {
|
||||||
|
const res = response.data
|
||||||
|
|
||||||
|
if (response.status === 200) {
|
||||||
|
this.isNoDataForPsiphon3 = res.data.result.length === 0
|
||||||
|
this.showErrorForPsiphon3 = false
|
||||||
|
if (!this.isNoDataForPsiphon3) {
|
||||||
|
const chartsData = res.data.result.map(item => {
|
||||||
|
return [getMillisecond(item.statTime), item.count]
|
||||||
|
})
|
||||||
|
if (this.activeTab === knowledgeCardUpdateRecordType.intelligenceLearning) {
|
||||||
|
this.echartsInit(chartsData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.httpError(res)
|
||||||
|
}
|
||||||
|
}).catch(e => {
|
||||||
|
console.error(e)
|
||||||
|
this.httpError(e)
|
||||||
|
}).finally(() => {
|
||||||
|
this.psiphon3Loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
httpError (e) {
|
||||||
|
this.isNoDataForPsiphon3 = false
|
||||||
|
this.showErrorForPsiphon3 = true
|
||||||
|
this.errorMsgForPsiphon3 = this.errorMsgHandler(e)
|
||||||
|
},
|
||||||
|
handleActiveBar () {
|
||||||
|
if (document.querySelector('.psiphon3-bar .bar-value-tabs.is-active')) {
|
||||||
|
const {
|
||||||
|
offsetLeft,
|
||||||
|
clientWidth,
|
||||||
|
clientLeft
|
||||||
|
} = document.querySelector('.psiphon3-bar .bar-value-tabs.is-active')
|
||||||
|
const activeBar = document.querySelector('.psiphon3-bar .bar-value-active')
|
||||||
|
activeBar.style.cssText += `width: ${clientWidth}px; left: ${offsetLeft + this.leftOffset + clientLeft}px;`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
resize () {
|
||||||
|
if (this.myChart) {
|
||||||
|
this.myChart.resize()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dispatchSelectAction (type, name) {
|
||||||
|
this.myChart && this.myChart.dispatchAction({
|
||||||
|
type: type,
|
||||||
|
name: name
|
||||||
|
})
|
||||||
|
},
|
||||||
|
legendSelectChange (item) {
|
||||||
|
this.dispatchSelectAction('legendSelect', item.name)
|
||||||
|
this.tabs.forEach((t) => {
|
||||||
|
if (t.name !== item.name) {
|
||||||
|
this.dispatchSelectAction('legendUnSelect', t.name)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
timeChange () {
|
||||||
|
if (this.updateKnowledge.source === 'cn_psiphon3_ip') {
|
||||||
|
this.init()
|
||||||
|
}
|
||||||
|
if (this.activeTab === knowledgeCardUpdateRecordType.intelligenceLearning) {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.handleActiveBar()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
activeChange (item) { // isClick:代表是通过点击操作来的
|
||||||
|
if (item) {
|
||||||
|
this.tabType = item.class
|
||||||
|
}
|
||||||
|
this.legendSelectChange(item)
|
||||||
|
if (this.updateKnowledge.source === 'cn_psiphon3_ip') {
|
||||||
|
this.init()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mouseenterTab (item) {
|
||||||
|
if (this.isNoDataForPsiphon3) return
|
||||||
|
this.mousemoveCursor = item.class
|
||||||
|
if (this.activeTab === knowledgeCardUpdateRecordType.intelligenceLearning) {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.handleActiveBar()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mouseleaveTab () {
|
||||||
|
this.mousemoveCursor = ''
|
||||||
|
},
|
||||||
fileChange (file, fileList) {
|
fileChange (file, fileList) {
|
||||||
console.info(!_.endsWith(file.name, '.csv'))
|
|
||||||
console.info(file.size > this.uploadFileSizeLimit)
|
|
||||||
// 判断后缀,仅支持.csv
|
// 判断后缀,仅支持.csv
|
||||||
if (!_.endsWith(file.name, '.csv')) {
|
if (!_.endsWith(file.name, '.csv')) {
|
||||||
this.fileList = []
|
this.fileList = []
|
||||||
@@ -283,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
|
||||||
axios.get(api.knowledgeBaseLog + '/' + this.updateKnowledge.knowledgeId, { params: { pageSize: 999 } }).then(res => {
|
this.getCurTabData()
|
||||||
this.updateHistoryList = res.data.data.list
|
|
||||||
this.currentVersion = this.updateHistoryList[0].commitVersion + 1
|
|
||||||
})
|
|
||||||
/* } else {
|
|
||||||
this.$message.error(this.$t('tip.uploadFailed', { msg: response.message }))
|
|
||||||
} */
|
|
||||||
},
|
},
|
||||||
beforeUpload (file) {
|
beforeUpload (file) {
|
||||||
this.uploadLoading = true
|
this.uploadLoading = true
|
||||||
@@ -305,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)
|
||||||
@@ -325,6 +624,13 @@ export default {
|
|||||||
data.isSelected = val
|
data.isSelected = val
|
||||||
this.$emit('checkboxStatusChange', val, data)
|
this.$emit('checkboxStatusChange', val, data)
|
||||||
},
|
},
|
||||||
|
beforeClose (done) {
|
||||||
|
if (this.myChart) {
|
||||||
|
this.myChart.dispose()
|
||||||
|
this.myChart = null
|
||||||
|
}
|
||||||
|
done()
|
||||||
|
},
|
||||||
handleClose () {
|
handleClose () {
|
||||||
this.showUpdateDialog = false
|
this.showUpdateDialog = false
|
||||||
this.showAddUpdateDialog = false
|
this.showAddUpdateDialog = false
|
||||||
@@ -340,14 +646,19 @@ export default {
|
|||||||
this.showUpdateDialog = true
|
this.showUpdateDialog = true
|
||||||
this.showAddUpdateDialog = false
|
this.showAddUpdateDialog = false
|
||||||
},
|
},
|
||||||
jumpToUpdatePage (data, showEnable) {
|
async jumpToUpdatePage (data, showEnable) {
|
||||||
axios.get(api.knowledgeBaseLog + '/' + data.knowledgeId, { params: { pageSize: 999 } }).then(res => {
|
|
||||||
this.updateKnowledge = data
|
this.updateKnowledge = data
|
||||||
this.updateHistoryList = res.data.data.list
|
|
||||||
this.currentVersion = this.updateHistoryList[0].commitVersion + 1
|
|
||||||
this.showEnable = showEnable
|
this.showEnable = showEnable
|
||||||
|
await this.getCurTabData()
|
||||||
|
if (data.source === 'cn_psiphon3_ip') {
|
||||||
|
await this.init()
|
||||||
|
}
|
||||||
this.showUpdate()
|
this.showUpdate()
|
||||||
|
if (this.activeTab === knowledgeCardUpdateRecordType.intelligenceLearning) {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.handleActiveBar()
|
||||||
})
|
})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
uploadRecord () {
|
uploadRecord () {
|
||||||
this.showAddUpdateDialog = true
|
this.showAddUpdateDialog = true
|
||||||
@@ -355,6 +666,52 @@ export default {
|
|||||||
this.updateObject.label = this.updateKnowledge.label
|
this.updateObject.label = this.updateKnowledge.label
|
||||||
this.updateObject.description = ''
|
this.updateObject.description = ''
|
||||||
},
|
},
|
||||||
|
getCurTabData () { // showEnable:true 为psiphon3的知识库,false为其它知识库
|
||||||
|
let params = {
|
||||||
|
pageSize: -1
|
||||||
|
}
|
||||||
|
if (this.showEnable) {
|
||||||
|
if (this.activeTab === knowledgeCardUpdateRecordType.updateRecord) {
|
||||||
|
params = {
|
||||||
|
...params,
|
||||||
|
opUser: -1
|
||||||
|
}
|
||||||
|
} else if (this.activeTab === knowledgeCardUpdateRecordType.intelligenceLearning) {
|
||||||
|
params = {
|
||||||
|
...params,
|
||||||
|
opUser: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.updateLogLoading = true
|
||||||
|
this.updateHistoryList = []
|
||||||
|
axios.get(api.knowledgeBaseLog + '/' + this.updateKnowledge.knowledgeId, { params: params }).then(res => {
|
||||||
|
this.updateHistoryList = res.data.data.list
|
||||||
|
if (this.updateHistoryList[0]) {
|
||||||
|
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 => {
|
||||||
|
console.error(e)
|
||||||
|
}).finally(() => {
|
||||||
|
this.updateLogLoading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 切换tab
|
||||||
|
handleClick (tab) {
|
||||||
|
this.getCurTabData()
|
||||||
|
if (tab.index === '1') {
|
||||||
|
this.timeChange()
|
||||||
|
}
|
||||||
|
},
|
||||||
clearSelect () {
|
clearSelect () {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.checkList = []
|
this.checkList = []
|
||||||
@@ -366,18 +723,10 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
mouseenter (card) {
|
mouseenter (card) {
|
||||||
this.tableData.forEach(t => {
|
|
||||||
if (t.knowledgeId === card.knowledgeId) {
|
|
||||||
card.showUpdate = true
|
card.showUpdate = true
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
mouseleave (card) {
|
mouseleave (card) {
|
||||||
this.tableData.forEach(t => {
|
|
||||||
if (t.knowledgeId === card.knowledgeId) {
|
|
||||||
card.showUpdate = false
|
card.showUpdate = false
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
del (data) {
|
del (data) {
|
||||||
this.$emit('delete', data)
|
this.$emit('delete', data)
|
||||||
@@ -394,9 +743,50 @@ export default {
|
|||||||
dataType: dataType
|
dataType: dataType
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
confirmSwitchLearning (id) {
|
||||||
|
this.showConfirmSwitch = true
|
||||||
|
this.switchKnowledgeId = id
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
cancleSwitch () {
|
||||||
|
this.showConfirmSwitch = false
|
||||||
|
},
|
||||||
|
switchLearning () {
|
||||||
|
const hint = this.aiTaggingList.find(d => d.knowledgeId === this.switchKnowledgeId)
|
||||||
|
const toStatus = hint.status === 0 ? 1 : 0
|
||||||
|
const url = toStatus === 0 ? api.knowledgeBaseLearningStop : api.knowledgeBaseLearningStart
|
||||||
|
axios.post(`${url}?knowledgeId=${hint.knowledgeId}`).then(res => {
|
||||||
|
if (res.status === 200) {
|
||||||
|
hint.status = toStatus
|
||||||
|
this.$message.success(this.$t('tip.success'))
|
||||||
|
} else {
|
||||||
|
console.error(res.message)
|
||||||
|
this.$message.error(this.errorMsgHandler(res))
|
||||||
|
}
|
||||||
|
}).catch(e => {
|
||||||
|
console.error(e)
|
||||||
|
this.$message.error(this.errorMsgHandler(e))
|
||||||
|
}).finally(() => {
|
||||||
|
this.showConfirmSwitch = false
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
tabType (n) {
|
||||||
|
this.timeChange()
|
||||||
|
},
|
||||||
|
/*
|
||||||
|
hasUpdatingRecord (n) {
|
||||||
|
if (n) { // update record页存在“正在更新”的记录时,每20秒自动请求一次接口
|
||||||
|
this.timer = setTimeout(() => {
|
||||||
|
this.getCurTabData()
|
||||||
|
}, 20000)
|
||||||
|
} 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) {
|
||||||
@@ -420,15 +810,33 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
activeTab (n) {
|
||||||
|
if (n === 'updateRecord') {
|
||||||
|
if (this.myChart) {
|
||||||
|
this.myChart.dispose()
|
||||||
|
this.myChart = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
showAddUpdateDialog: {
|
showAddUpdateDialog: {
|
||||||
handler (n) {
|
handler (n) {
|
||||||
if (!n) {
|
if (!n) {
|
||||||
this.fileList = []
|
this.fileList = []
|
||||||
|
this.timeChange()
|
||||||
|
} else {
|
||||||
|
if (this.myChart) {
|
||||||
|
this.myChart.dispose()
|
||||||
|
this.myChart = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
|
this.myChart = null
|
||||||
|
this.chartOption = null
|
||||||
|
window.addEventListener('resize', this.resize)
|
||||||
|
|
||||||
this.aiTaggingList = []
|
this.aiTaggingList = []
|
||||||
this.websketchList = []
|
this.websketchList = []
|
||||||
this.tableData.forEach(item => {
|
this.tableData.forEach(item => {
|
||||||
@@ -440,6 +848,22 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
beforeUnmount () {
|
||||||
|
//clearTimeout(this.timer)
|
||||||
|
window.removeEventListener('resize', this.resize)
|
||||||
|
const dom = document.getElementById('psiphonBarChart')
|
||||||
|
if (dom) {
|
||||||
|
let myChart = echarts.getInstanceByDom(document.getElementById('psiphonBarChart'))
|
||||||
|
if (myChart) {
|
||||||
|
echarts.dispose(myChart)
|
||||||
|
}
|
||||||
|
myChart = null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.myChart) {
|
||||||
|
echarts.dispose(this.myChart)
|
||||||
|
}
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
uploadParams () {
|
uploadParams () {
|
||||||
return {
|
return {
|
||||||
@@ -447,6 +871,20 @@ export default {
|
|||||||
action: 'overwrite',
|
action: 'overwrite',
|
||||||
description: this.updateObject.description
|
description: this.updateObject.description
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
confirmSwitchLearningTip () {
|
||||||
|
let tip = ''
|
||||||
|
if (this.switchKnowledgeId) {
|
||||||
|
const find = this.aiTaggingList.find(item => item.knowledgeId === this.switchKnowledgeId)
|
||||||
|
if (find) {
|
||||||
|
if (find.status === 0) {
|
||||||
|
tip = this.$t('tip.confirmEnablePsiphon3') + '?'
|
||||||
|
} else if (find.status === 1) {
|
||||||
|
tip = this.$t('tip.confirmDisablePsiphon3') + '?'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tip
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -110,43 +110,6 @@ export default {
|
|||||||
if (this.listUrl) {
|
if (this.listUrl) {
|
||||||
listUrl = this.listUrl
|
listUrl = this.listUrl
|
||||||
}
|
}
|
||||||
// todo 此段是为了避免mock没开启,打开detection界面报错提示,后续再开发detection时删除
|
|
||||||
if (listUrl === api.detection.list) {
|
|
||||||
const list = []
|
|
||||||
for (let i = 0; i < 20; i++) {
|
|
||||||
const obj = {
|
|
||||||
ruleId: 100000 + i,
|
|
||||||
ruleType: 'indicator_match',
|
|
||||||
status: 1,
|
|
||||||
name: 'name123',
|
|
||||||
category: 'Security Event',
|
|
||||||
eventType: 'C&C',
|
|
||||||
description: 'Built-in darkweb IoC',
|
|
||||||
ruleConfig: {
|
|
||||||
knowledge: {
|
|
||||||
name: 'VPN Server IP',
|
|
||||||
category: 'user_defined'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i % 2 === 0) {
|
|
||||||
obj.ruleType = 'threshold'
|
|
||||||
obj.ruleConfig = {
|
|
||||||
dimensions: 'Destination IP/CIDR'
|
|
||||||
}
|
|
||||||
obj.description = 'abuse.ch is providing community driven threat intelligence on \n' +
|
|
||||||
'cyber threats. It is the home of a couple of projects that are \n' +
|
|
||||||
'helping internet service providers and network operators protect …'
|
|
||||||
} else {
|
|
||||||
obj.status = 0
|
|
||||||
}
|
|
||||||
list.push(obj)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.tableData = list
|
|
||||||
this.pageObj.total = list.length
|
|
||||||
this.loading = false
|
|
||||||
} else {
|
|
||||||
axios.get(listUrl, { params: this.searchLabel }).then(response => {
|
axios.get(listUrl, { params: this.searchLabel }).then(response => {
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
this.tableData = _.get(response, 'data.data.list', [])
|
this.tableData = _.get(response, 'data.data.list', [])
|
||||||
@@ -167,7 +130,6 @@ export default {
|
|||||||
this.toggleLoading(false)
|
this.toggleLoading(false)
|
||||||
this.loading = false
|
this.loading = false
|
||||||
})
|
})
|
||||||
}
|
|
||||||
},
|
},
|
||||||
del (row) {
|
del (row) {
|
||||||
this.$confirm(this.$t('tip.confirmDelete'), {
|
this.$confirm(this.$t('tip.confirmDelete'), {
|
||||||
@@ -400,10 +362,23 @@ export default {
|
|||||||
this.searchLabel.orderBy = orderBy
|
this.searchLabel.orderBy = orderBy
|
||||||
this.getTableData()
|
this.getTableData()
|
||||||
},
|
},
|
||||||
search (params) {
|
search (params, flag, list) {
|
||||||
this.pageObj.pageNo = 1
|
this.pageObj.pageNo = 1
|
||||||
|
if (flag !== 'detection') {
|
||||||
delete this.searchLabel.category
|
delete this.searchLabel.category
|
||||||
delete this.searchLabel.source
|
delete this.searchLabel.source
|
||||||
|
}
|
||||||
|
if (list && list.length > 0) {
|
||||||
|
if (list.indexOf('status') > -1) {
|
||||||
|
delete this.searchLabel.status
|
||||||
|
}
|
||||||
|
if (list.indexOf('category') > -1) {
|
||||||
|
delete this.searchLabel.category
|
||||||
|
}
|
||||||
|
if (list.indexOf('eventType') > -1) {
|
||||||
|
delete this.searchLabel.eventType
|
||||||
|
}
|
||||||
|
}
|
||||||
this.getTableData(params)
|
this.getTableData(params)
|
||||||
},
|
},
|
||||||
getTimeString () {
|
getTimeString () {
|
||||||
|
|||||||
@@ -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) {
|
||||||
@@ -96,5 +96,41 @@ export default {
|
|||||||
this.relationshipShowMoreTwo = false
|
this.relationshipShowMoreTwo = false
|
||||||
this.relationshipShowMoreOne = false
|
this.relationshipShowMoreOne = false
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
scoreDot () {
|
||||||
|
const dots = []
|
||||||
|
if (this.score === '-') {
|
||||||
|
for (let i = 0; i < 6; i++) {
|
||||||
|
dots.push({
|
||||||
|
class: 'score-dot'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (let i = 0; i < 6; i++) {
|
||||||
|
if (i < this.score) {
|
||||||
|
dots.push({
|
||||||
|
class: `score-dot ${handleClass(this.score)}`
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
dots.push({
|
||||||
|
class: 'score-dot'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dots
|
||||||
|
|
||||||
|
function handleClass (score) {
|
||||||
|
if (score <= 2) {
|
||||||
|
return 'score-dot--red'
|
||||||
|
} else if (score <= 4) {
|
||||||
|
return 'score-dot--yellow'
|
||||||
|
} else if (score <= 6) {
|
||||||
|
return 'score-dot--green'
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 // 最后一位加空格
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ if (openMock) {
|
|||||||
const list = []
|
const list = []
|
||||||
for (let i = 0; i < 20; i++) {
|
for (let i = 0; i < 20; i++) {
|
||||||
const obj = {
|
const obj = {
|
||||||
ruleId: 100000 + i,
|
ruleId: 163 + i,
|
||||||
ruleType: 'indicator_match',
|
ruleType: 'indicator_match',
|
||||||
status: 1,
|
status: 1,
|
||||||
name: 'name123',
|
name: 'name123',
|
||||||
@@ -50,51 +50,17 @@ if (openMock) {
|
|||||||
Mock.mock(new RegExp(urlAndVersion + '/detection/statistics.*'), 'get', function (requestObj) {
|
Mock.mock(new RegExp(urlAndVersion + '/detection/statistics.*'), 'get', function (requestObj) {
|
||||||
const data = {
|
const data = {
|
||||||
statusList: [
|
statusList: [
|
||||||
{ status: 1 },
|
{ status: 1, count: 34 },
|
||||||
{ status: 0 }
|
{ status: 0, count: 28 }
|
||||||
],
|
],
|
||||||
categoryList: [
|
categoryList: [
|
||||||
{ value: 'security', label: 'Security Event' },
|
{ name: 'Security Event', count: 32 },
|
||||||
{ value: 'performance', label: 'Performance Event' },
|
{ name: 'Performance Event', count: 28 }
|
||||||
{ value: 'regulatory_risk', label: 'Regulatory Risk Event' }
|
|
||||||
],
|
],
|
||||||
typeList: [
|
eventTypeList: [
|
||||||
{ value: 'c&c', label: 'C&C' },
|
{ name: 'DDos', count: 15 },
|
||||||
{ value: 'ddos', label: 'DDos' },
|
{ name: 'Lateral movement', count: 17 },
|
||||||
{ value: 'lateral_movement', label: 'Lateral movement' },
|
{ name: 'Brute force', count: 12 }
|
||||||
{ value: 'brute_force', label: 'Brute force' }
|
|
||||||
],
|
|
||||||
sourceList: [
|
|
||||||
{ value: 'ip_metric', label: 'IP metric' },
|
|
||||||
{ value: 'performance_event', label: 'performance event' }
|
|
||||||
],
|
|
||||||
levelList: [
|
|
||||||
{ value: 'critical', label: 'Critical' },
|
|
||||||
{ value: 'high', label: 'High' },
|
|
||||||
{ value: 'medium', label: 'Medium' },
|
|
||||||
{ value: 'low', label: 'Low' },
|
|
||||||
{ value: 'info', label: 'Info' }
|
|
||||||
],
|
|
||||||
metricList: [
|
|
||||||
{ value: 'tcp_lostlen_ratio', label: 'Bits/second' },
|
|
||||||
{ value: 's2c_byte_retrans_ratio', label: 'Packets/second' },
|
|
||||||
{ value: 's2c_byte_retrans_ratio1', label: 'Sessions/second' }
|
|
||||||
],
|
|
||||||
conditionList: [
|
|
||||||
{ value: 'than', label: 'Greater Than' },
|
|
||||||
{ value: 'less', label: 'Greater Less' },
|
|
||||||
{ value: 'equal', label: 'Greater Equal' }
|
|
||||||
],
|
|
||||||
libraryList: [
|
|
||||||
{ value: 'library name2', knowledgeId: '101', label: 'Library name' },
|
|
||||||
{ value: 'library name1', knowledgeId: '102', label: 'Library name1' },
|
|
||||||
{ value: 'library name2', knowledgeId: '103', label: 'Library name2' }
|
|
||||||
],
|
|
||||||
intervalList: [
|
|
||||||
{ value: 'minutes', label: 'minutes' },
|
|
||||||
{ value: 'hours', label: 'hours' },
|
|
||||||
{ value: 'days', label: 'days' },
|
|
||||||
{ value: 'weeks', label: 'weeks' }
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,28 +95,50 @@ if (openMock) {
|
|||||||
const ruleId = getLastValue(requestObj.url)
|
const ruleId = getLastValue(requestObj.url)
|
||||||
const data = {
|
const data = {
|
||||||
name: 'name123',
|
name: 'name123',
|
||||||
category: 'Security Event',
|
category: 'security_event',
|
||||||
ruleType: 'indicator_match',
|
ruleType: 'indicator_match',
|
||||||
eventType: 'C&C',
|
eventType: 'C&C',
|
||||||
description: 'Built-in darkweb IoC',
|
description: 'Built-in darkweb IoC',
|
||||||
status: 1,
|
status: 1,
|
||||||
ruleConfig: {
|
ruleConfig: {
|
||||||
dataSource: 'VPN Server IP',
|
dataSource: 'VPN Server IP',
|
||||||
|
knowledgeBase: {
|
||||||
knowledgeId: 10,
|
knowledgeId: 10,
|
||||||
level: 10
|
name: 'cn_ioc_darkweb',
|
||||||
|
category: 'websketch',
|
||||||
|
source: 'cn_ioc_darkweb'
|
||||||
},
|
},
|
||||||
trigger: {
|
level: 'critical'
|
||||||
|
},
|
||||||
|
ruleConfigObj: {
|
||||||
|
dataSource: 'VPN Server IP',
|
||||||
|
knowledgeBase: {
|
||||||
|
knowledgeId: '101',
|
||||||
|
name: 'cn_ioc_darkweb',
|
||||||
|
category: 'websketch',
|
||||||
|
source: 'cn_ioc_darkweb'
|
||||||
|
},
|
||||||
|
level: 'critical'
|
||||||
|
},
|
||||||
|
ruleTrigger: {
|
||||||
|
atLeast: 1,
|
||||||
|
interval: 'PT5M',
|
||||||
|
resetInterval: 'PT10M'
|
||||||
|
},
|
||||||
|
ruleTriggerObj: {
|
||||||
atLeast: 1,
|
atLeast: 1,
|
||||||
interval: 'PT5M',
|
interval: 'PT5M',
|
||||||
resetInterval: 'PT10M'
|
resetInterval: 'PT10M'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
data.ruleConfig = JSON.stringify(data.ruleConfig)
|
||||||
|
data.trigger = JSON.stringify(data.trigger)
|
||||||
|
|
||||||
if (ruleId % 2 === 0) {
|
if (ruleId % 2 === 0) {
|
||||||
data.ruleType = 'threshold'
|
data.ruleType = 'threshold'
|
||||||
data.status = 1
|
|
||||||
} else {
|
|
||||||
data.status = 0
|
data.status = 0
|
||||||
|
} else {
|
||||||
|
data.status = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
353
src/mock/detectionList.js
Normal file
353
src/mock/detectionList.js
Normal file
@@ -0,0 +1,353 @@
|
|||||||
|
import Mock from 'mockjs'
|
||||||
|
|
||||||
|
const urlAndVersion = BASE_CONFIG.baseUrl + BASE_CONFIG.apiVersion
|
||||||
|
const openMock = true
|
||||||
|
if (openMock) {
|
||||||
|
Mock.mock(new RegExp(urlAndVersion + '/detection/security/list.*'), 'get', function (requestObj) {
|
||||||
|
const result = []
|
||||||
|
for (let i = 0; i < 20; i++) {
|
||||||
|
const obj = {
|
||||||
|
eventId: 1212,
|
||||||
|
eventType: 'Anonymity',
|
||||||
|
eventName: 'Tor',
|
||||||
|
eventKey: '2,1.1.1,12.2.2.2',
|
||||||
|
ruleId: 2,
|
||||||
|
ruleType: 'indicator_match',
|
||||||
|
isBuiltin: 1,
|
||||||
|
severity: 'critical',
|
||||||
|
offenderIp: '1.1.1.1',
|
||||||
|
victimIp: '2.2.2.2',
|
||||||
|
domain: '*.vioee.com',
|
||||||
|
app: 'vio',
|
||||||
|
startTime: 1697092617,
|
||||||
|
endTime: 1697092777,
|
||||||
|
durationS: 30000,
|
||||||
|
matchTimes: 1,
|
||||||
|
status: 1,
|
||||||
|
eventInfo: "{\'knowledge_id\': 123, \'name\': \'example_ioc_malware\', \'ioc_type\': \'domain\', \'ioc_value\': \'iocentity.com\'}",
|
||||||
|
eventInfoObj: {
|
||||||
|
knowledge_id: 123,
|
||||||
|
name: 'example_ioc_malware',
|
||||||
|
ioc_type: 'domain',
|
||||||
|
ioc_value: 'iocentity.com'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i % 2 === 0) {
|
||||||
|
obj.status = 0
|
||||||
|
}
|
||||||
|
result.push(obj)
|
||||||
|
}
|
||||||
|
const data = {
|
||||||
|
resultType: 'table',
|
||||||
|
result: result
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
msg: 'OK',
|
||||||
|
code: 200,
|
||||||
|
data: data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Mock.mock(new RegExp(urlAndVersion + '/detection/security/severity/timedistribution.*'), 'get', function (requestObj) {
|
||||||
|
const result = [
|
||||||
|
{
|
||||||
|
statTime: 1697523900,
|
||||||
|
severity: 'critical',
|
||||||
|
count: 25
|
||||||
|
},
|
||||||
|
{
|
||||||
|
statTime: 1697524200,
|
||||||
|
severity: 'high',
|
||||||
|
count: 31
|
||||||
|
},
|
||||||
|
{
|
||||||
|
statTime: 1697524500,
|
||||||
|
severity: 'info',
|
||||||
|
count: 21
|
||||||
|
},
|
||||||
|
{
|
||||||
|
statTime: 1697524800,
|
||||||
|
severity: 'low',
|
||||||
|
count: 25
|
||||||
|
},
|
||||||
|
{
|
||||||
|
statTime: 1697525100,
|
||||||
|
severity: 'medium',
|
||||||
|
count: 32
|
||||||
|
},
|
||||||
|
{
|
||||||
|
statTime: 1697525400,
|
||||||
|
severity: 'critical',
|
||||||
|
count: 22
|
||||||
|
},
|
||||||
|
{
|
||||||
|
statTime: 1697525700,
|
||||||
|
severity: 'critical',
|
||||||
|
count: 23
|
||||||
|
},
|
||||||
|
{
|
||||||
|
statTime: 1697526000,
|
||||||
|
severity: 'critical',
|
||||||
|
count: 25
|
||||||
|
},
|
||||||
|
{
|
||||||
|
statTime: 1697526300,
|
||||||
|
severity: 'critical',
|
||||||
|
count: 21
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
resultType: 'table',
|
||||||
|
result: result
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
msg: 'OK',
|
||||||
|
code: 200,
|
||||||
|
data: data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Mock.mock(new RegExp(urlAndVersion + '/detection/security/severity/statistics.*'), 'get', function (requestObj) {
|
||||||
|
const result = [
|
||||||
|
{
|
||||||
|
severity: 'critical',
|
||||||
|
count: 25
|
||||||
|
},
|
||||||
|
{
|
||||||
|
severity: 'high',
|
||||||
|
count: 31
|
||||||
|
},
|
||||||
|
{
|
||||||
|
severity: 'info',
|
||||||
|
count: 21
|
||||||
|
},
|
||||||
|
{
|
||||||
|
severity: 'low',
|
||||||
|
count: 25
|
||||||
|
},
|
||||||
|
{
|
||||||
|
severity: 'medium',
|
||||||
|
count: 32
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
resultType: 'table',
|
||||||
|
result: result
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
msg: 'OK',
|
||||||
|
code: 200,
|
||||||
|
data: data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Mock.mock(new RegExp(urlAndVersion + '/detection/security/event-type/statistics.*'), 'get', function (requestObj) {
|
||||||
|
const result = [
|
||||||
|
{
|
||||||
|
eventType: 'Anonymity',
|
||||||
|
count: 25
|
||||||
|
},
|
||||||
|
{
|
||||||
|
eventType: 'Command and Control',
|
||||||
|
count: 31
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
resultType: 'table',
|
||||||
|
result: result
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
msg: 'OK',
|
||||||
|
code: 200,
|
||||||
|
data: data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Mock.mock(new RegExp(urlAndVersion + '/detection/security/offender-ip/statistics.*'), 'get', function (requestObj) {
|
||||||
|
const result = [
|
||||||
|
{
|
||||||
|
offenderIp: '221.7.1.20',
|
||||||
|
count: 25
|
||||||
|
},
|
||||||
|
{
|
||||||
|
offenderIp: '58.247.118.253',
|
||||||
|
count: 31
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
resultType: 'table',
|
||||||
|
result: result
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
msg: 'OK',
|
||||||
|
code: 200,
|
||||||
|
data: data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Mock.mock(new RegExp(urlAndVersion + '/detection/security/victim-ip/statistics.*'), 'get', function (requestObj) {
|
||||||
|
const result = [
|
||||||
|
{
|
||||||
|
victimIp: '21.77.1.201',
|
||||||
|
count: 25
|
||||||
|
},
|
||||||
|
{
|
||||||
|
victimIp: '58.47.118.153',
|
||||||
|
count: 31
|
||||||
|
},
|
||||||
|
{
|
||||||
|
victimIp: '22.47.223.57',
|
||||||
|
count: 43
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
resultType: 'table',
|
||||||
|
result: result
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
msg: 'OK',
|
||||||
|
code: 200,
|
||||||
|
data: data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Mock.mock(new RegExp(urlAndVersion + '/detection/security/status/statistics.*'), 'get', function (requestObj) {
|
||||||
|
const result = [
|
||||||
|
{
|
||||||
|
status: 1,
|
||||||
|
count: 25
|
||||||
|
},
|
||||||
|
{
|
||||||
|
status: 0,
|
||||||
|
count: 31
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
resultType: 'table',
|
||||||
|
result: result
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
msg: 'OK',
|
||||||
|
code: 200,
|
||||||
|
data: data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Mock.mock(new RegExp(urlAndVersion + '/detection/security/ip/relation/event.*'), 'get', function (requestObj) {
|
||||||
|
const result = [
|
||||||
|
{
|
||||||
|
eventId: 10010,
|
||||||
|
severity: 'high',
|
||||||
|
eventType: 'Command and Control',
|
||||||
|
offenderIp: '1.1.1.1',
|
||||||
|
victimIp: '2.2.2.2',
|
||||||
|
startTime: 1697092617
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
resultType: 'table',
|
||||||
|
result: result
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
msg: 'OK',
|
||||||
|
code: 200,
|
||||||
|
data: data
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Mock.mock(new RegExp(urlAndVersion + '/detection/security/count.*'), 'get', function (requestObj) {
|
||||||
|
return {
|
||||||
|
msg: 'OK',
|
||||||
|
code: 200,
|
||||||
|
data: {
|
||||||
|
resultType: 'single',
|
||||||
|
result: 123
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Mock.mock(new RegExp(urlAndVersion + '/detection/security/entity/detail/ip.*'), 'get', function (requestObj) {
|
||||||
|
return {
|
||||||
|
msg: 'OK',
|
||||||
|
code: 200,
|
||||||
|
data: {
|
||||||
|
asn: {
|
||||||
|
id: 2,
|
||||||
|
asn: '14061',
|
||||||
|
organization: 'DIGITALOCEAN-ASN - DigitalOcean, LLC, US'
|
||||||
|
},
|
||||||
|
malware: {
|
||||||
|
threatType: 'command and control',
|
||||||
|
malwareName: 'IcedID',
|
||||||
|
malwareAlias: 'BokBot,IceID',
|
||||||
|
mitreAttackDescription: '[IcedID](https://attack.mitre.org/software/S0483) is a modular banking malware designed to steal financial information that has been observed in the wild since at least 2017. [IcedID](https://attack.mitre.org/software/S0483) has been downloaded by [Emotet](https://attack.mitre.org/software/S0367) in multiple campaigns.(Citation: IBM IcedID November 2017)(Citation: Juniper IcedID June 2020)',
|
||||||
|
mitreAttackPlatforms: 'Windows',
|
||||||
|
mitreAttackTechniques: '[""Asymmetric Cryptography(T1573.002)"",""Asynchronous Procedure Call(T1055.004)"",""Browser Session Hijacking(T1185)"",""Domain Account(T1087.002)"",""Ingress Tool Transfer(T1105)"",""Malicious File(T1204.002)"",""Msiexec(T1218.007)"",""Native API(T1106)"",""Obfuscated Files or Information(T1027)"",""Permission Groups Discovery(T1069)"",""Registry Run Keys / Startup Folder(T1547.001)"",""Scheduled Task(T1053.005)"",""Software Packing(T1027.002)"",""Spearphishing Attachment(T1566.001)"",""Steganography(T1027.003)"",""System Information Discovery(T1082)"",""Visual Basic(T1059.005)"",""Web Protocols(T1071.001)"",""Windows Management Instrumentation(T1047)""]',
|
||||||
|
mitreAttackGroups: '[""TA551(G0127)""]',
|
||||||
|
confidenceLevel: 'high',
|
||||||
|
reference: ''
|
||||||
|
},
|
||||||
|
location: {
|
||||||
|
continent: 'North America',
|
||||||
|
country: 'United States',
|
||||||
|
province: 'New York',
|
||||||
|
city: '',
|
||||||
|
lngwgs: '-74.006',
|
||||||
|
latwgs: '40.713',
|
||||||
|
isp: 'dba Omsoft',
|
||||||
|
owner: 'tie net'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Mock.mock(new RegExp(urlAndVersion + '/detection/security/entity/detail/domain.*'), 'get', function (requestObj) {
|
||||||
|
return {
|
||||||
|
msg: 'OK',
|
||||||
|
code: 200,
|
||||||
|
data: {
|
||||||
|
malware: {
|
||||||
|
threatType: 'command and control',
|
||||||
|
malwareName: 'IcedID',
|
||||||
|
malwareAlias: 'BokBot,IceID',
|
||||||
|
mitreAttackDescription: '[IcedID](https://attack.mitre.org/software/S0483) is a modular banking malware designed to steal financial information that has been observed in the wild since at least 2017. [IcedID](https://attack.mitre.org/software/S0483) has been downloaded by [Emotet](https://attack.mitre.org/software/S0367) in multiple campaigns.(Citation: IBM IcedID November 2017)(Citation: Juniper IcedID June 2020)',
|
||||||
|
mitreAttackPlatforms: 'Windows',
|
||||||
|
mitreAttackTechniques: '[""Asymmetric Cryptography(T1573.002)"",""Asynchronous Procedure Call(T1055.004)"",""Browser Session Hijacking(T1185)"",""Domain Account(T1087.002)"",""Ingress Tool Transfer(T1105)"",""Malicious File(T1204.002)"",""Msiexec(T1218.007)"",""Native API(T1106)"",""Obfuscated Files or Information(T1027)"",""Permission Groups Discovery(T1069)"",""Registry Run Keys / Startup Folder(T1547.001)"",""Scheduled Task(T1053.005)"",""Software Packing(T1027.002)"",""Spearphishing Attachment(T1566.001)"",""Steganography(T1027.003)"",""System Information Discovery(T1082)"",""Visual Basic(T1059.005)"",""Web Protocols(T1071.001)"",""Windows Management Instrumentation(T1047)""]',
|
||||||
|
mitreAttackGroups: '[""TA551(G0127)""]',
|
||||||
|
confidenceLevel: 'high',
|
||||||
|
reference: ''
|
||||||
|
},
|
||||||
|
category: {
|
||||||
|
categoryName: '门户网站',
|
||||||
|
categoryGroup: '互联网',
|
||||||
|
reputationLevel: 'high'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Mock.mock(new RegExp(urlAndVersion + '/detection/security/entity/detail/app.*'), 'get', function (requestObj) {
|
||||||
|
return {
|
||||||
|
msg: 'OK',
|
||||||
|
code: 200,
|
||||||
|
data: {
|
||||||
|
category: {
|
||||||
|
appName: 'QQ',
|
||||||
|
appId: 333,
|
||||||
|
appCategory: '娱乐',
|
||||||
|
appSubcategory: '聊天',
|
||||||
|
appRisk: 'low',
|
||||||
|
appDescription: '聊天社交软件',
|
||||||
|
appLongname: 'Tencent qq',
|
||||||
|
appTechnology: 'socket',
|
||||||
|
appCompany: 'tencent',
|
||||||
|
appCompanyCategory: '互联网'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -3,3 +3,4 @@ import './linkMonitor'
|
|||||||
import './dns'
|
import './dns'
|
||||||
import './entity'
|
import './entity'
|
||||||
import './detection'
|
import './detection'
|
||||||
|
import './detectionList'
|
||||||
|
|||||||
@@ -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,111 +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')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Chart',
|
|
||||||
path: '/chart',
|
|
||||||
component: () => import('@/views/administration/Chart')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/detectionsNew',
|
|
||||||
component: () => import('@/views/detectionsNew/Index')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/detection/policies',
|
|
||||||
component: () => import('@/views/detectionsNew/Index')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/detection/policies/create',
|
|
||||||
component: () => import('@/views/detectionsNew/DetectionForm')
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,29 @@ const panel = {
|
|||||||
routerHistoryList: [], // 路由跳转记录列表
|
routerHistoryList: [], // 路由跳转记录列表
|
||||||
dnsQtypeMapData: [],
|
dnsQtypeMapData: [],
|
||||||
dnsRcodeMapData: [],
|
dnsRcodeMapData: [],
|
||||||
|
scoreBase: {
|
||||||
|
isReady: false,
|
||||||
|
establishLatencyMs: {
|
||||||
|
p10: null,
|
||||||
|
p90: null
|
||||||
|
},
|
||||||
|
httpResponseLatency: {
|
||||||
|
p10: null,
|
||||||
|
p90: null
|
||||||
|
},
|
||||||
|
sslConLatency: {
|
||||||
|
p10: null,
|
||||||
|
p90: null
|
||||||
|
},
|
||||||
|
tcpLostlenPercent: {
|
||||||
|
p10: null,
|
||||||
|
p90: null
|
||||||
|
},
|
||||||
|
pktRetransPercent: {
|
||||||
|
p10: null,
|
||||||
|
p90: null
|
||||||
|
}
|
||||||
|
},
|
||||||
chartTabList: null // chartTabs组件的tab状态点击列表,初始化为null方便原有逻辑计算
|
chartTabList: null // chartTabs组件的tab状态点击列表,初始化为null方便原有逻辑计算
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
@@ -153,6 +176,56 @@ const panel = {
|
|||||||
setRouterHistoryList (state, list) {
|
setRouterHistoryList (state, list) {
|
||||||
state.routerHistoryList = list
|
state.routerHistoryList = list
|
||||||
},
|
},
|
||||||
|
resetScoreBase (state) {
|
||||||
|
state.scoreBase = {
|
||||||
|
isReady: false,
|
||||||
|
establishLatencyMs: {
|
||||||
|
p10: null,
|
||||||
|
p90: null
|
||||||
|
},
|
||||||
|
httpResponseLatency: {
|
||||||
|
p10: null,
|
||||||
|
p90: null
|
||||||
|
},
|
||||||
|
sslConLatency: {
|
||||||
|
p10: null,
|
||||||
|
p90: null
|
||||||
|
},
|
||||||
|
tcpLostlenPercent: {
|
||||||
|
p10: null,
|
||||||
|
p90: null
|
||||||
|
},
|
||||||
|
pktRetransPercent: {
|
||||||
|
p10: null,
|
||||||
|
p90: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setScoreBase (state, scoreBase) {
|
||||||
|
state.scoreBase = {
|
||||||
|
isReady: true,
|
||||||
|
establishLatencyMs: {
|
||||||
|
p10: scoreBase.establishLatencyMsP10,
|
||||||
|
p90: scoreBase.establishLatencyMsP90
|
||||||
|
},
|
||||||
|
httpResponseLatency: {
|
||||||
|
p10: scoreBase.httpResponseLatencyP10,
|
||||||
|
p90: scoreBase.httpResponseLatencyP90
|
||||||
|
},
|
||||||
|
sslConLatency: {
|
||||||
|
p10: scoreBase.sslConLatencyP10,
|
||||||
|
p90: scoreBase.sslConLatencyP90
|
||||||
|
},
|
||||||
|
tcpLostlenPercent: {
|
||||||
|
p10: scoreBase.tcpLostlenPercentP10,
|
||||||
|
p90: scoreBase.tcpLostlenPercentP90
|
||||||
|
},
|
||||||
|
pktRetransPercent: {
|
||||||
|
p10: scoreBase.pktRetransPercentP10,
|
||||||
|
p90: scoreBase.pktRetransPercentP90
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
setChartTabList (state, list) {
|
setChartTabList (state, list) {
|
||||||
state.chartTabList = list
|
state.chartTabList = list
|
||||||
}
|
}
|
||||||
@@ -232,6 +305,12 @@ const panel = {
|
|||||||
},
|
},
|
||||||
getChartTabList (state) {
|
getChartTabList (state) {
|
||||||
return state.chartTabList
|
return state.chartTabList
|
||||||
|
},
|
||||||
|
scoreBaseReady (state) {
|
||||||
|
return state.scoreBase.isReady
|
||||||
|
},
|
||||||
|
getScoreBase (state) {
|
||||||
|
return state.scoreBase
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
|
|||||||
@@ -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]
|
||||||
@@ -118,7 +125,7 @@ const user = {
|
|||||||
localStorage.setItem(storageKey.linkInfo, res.page.list[0].cvalue)
|
localStorage.setItem(storageKey.linkInfo, res.page.list[0].cvalue)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
axios.get(api.config, { params: { ckey: 'schema_entity_explore' } }).then(response => {
|
axios.get(api.config, { params: { ckey: 'schema_explore' } }).then(response => {
|
||||||
const res = response.data
|
const res = response.data
|
||||||
if (response.status === 200 && res.page.list && res.page.list.length > 0) {
|
if (response.status === 200 && res.page.list && res.page.list.length > 0) {
|
||||||
localStorage.setItem(storageKey.schemaEntityExplore, res.page.list[0].cvalue)
|
localStorage.setItem(storageKey.schemaEntityExplore, res.page.list[0].cvalue)
|
||||||
|
|||||||
@@ -38,9 +38,12 @@ export const api = {
|
|||||||
knowledgeBase: apiVersion + '/knowledgeBase',
|
knowledgeBase: apiVersion + '/knowledgeBase',
|
||||||
knowledgeBaseList: apiVersion + '/knowledgeBase/list',
|
knowledgeBaseList: apiVersion + '/knowledgeBase/list',
|
||||||
knowledgeBaseEnable: apiVersion + '/knowledgeBase/status',
|
knowledgeBaseEnable: apiVersion + '/knowledgeBase/status',
|
||||||
|
knowledgeBaseLearningStart: apiVersion + '/knowledgeBase/intelligence-learning/start',
|
||||||
|
knowledgeBaseLearningStop: apiVersion + '/knowledgeBase/intelligence-learning/stop',
|
||||||
knowledgeBaseStatistics: apiVersion + '/knowledgeBase/statistics',
|
knowledgeBaseStatistics: apiVersion + '/knowledgeBase/statistics',
|
||||||
updateKnowledgeUrl: apiVersion + '/knowledgeBase/items/batch',
|
updateKnowledgeUrl: apiVersion + '/knowledgeBase/items/batch',
|
||||||
knowledgeBaseLog: apiVersion + '/knowledgeBase/audit/log',
|
knowledgeBaseLog: apiVersion + '/knowledgeBase/audit/log',
|
||||||
|
knowledgeBaseTimedistribution: apiVersion + '/knowledgeBase/{{knowledgeId}}/{{type}}/timedistribution',
|
||||||
|
|
||||||
// 报告相关
|
// 报告相关
|
||||||
reportJob: '/report/job',
|
reportJob: '/report/job',
|
||||||
@@ -123,7 +126,20 @@ export const api = {
|
|||||||
listBasic: '/interface/detection/security/list/basic',
|
listBasic: '/interface/detection/security/list/basic',
|
||||||
listCount: '/interface/detection/security/list/count',
|
listCount: '/interface/detection/security/list/count',
|
||||||
overviewBasic: '/interface/detection/security/detail/overview/basic',
|
overviewBasic: '/interface/detection/security/detail/overview/basic',
|
||||||
overviewEvent: '/interface/detection/security/detail/overview/event'
|
overviewEvent: '/interface/detection/security/detail/overview/event',
|
||||||
|
securityList: apiVersion + '/detection/security/list', // 安全事件列表
|
||||||
|
timeDistribution: apiVersion + '/detection/security/severity/timedistribution', // 事件严重等级分布(顶部柱状图)
|
||||||
|
severityStatistics: apiVersion + '/detection/security/severity/statistics', // 事件严重等级统计(左侧filter事件严重等级和饼图)
|
||||||
|
statusStatistics: apiVersion + '/detection/security/status/statistics', // 事件状态统计
|
||||||
|
eventTypeStatistics: apiVersion + '/detection/security/event-type/statistics', // 事件类型统计
|
||||||
|
offenderIpStatistics: apiVersion + '/detection/security/offender-ip/statistics', // 攻击者IP统计
|
||||||
|
victimIpStatistics: apiVersion + '/detection/security/victim-ip/statistics', // 受害者IP统计
|
||||||
|
relationEvent: apiVersion + '/detection/security/ip/relation/event', // IP相关近期事件
|
||||||
|
securityCount: apiVersion + '/detection/security/count', // 安全事件总数
|
||||||
|
detail: apiVersion + '/detection/security/entity/detail', // 安全事件实体详情,后面得加上实体类型
|
||||||
|
ipDetail: apiVersion + '/detection/security/entity/detail/ip', // 安全事件实体详情ip响应
|
||||||
|
domainDetail: apiVersion + '/detection/security/entity/detail/domain', // 安全事件实体详情domain响应
|
||||||
|
appDetail: apiVersion + '/detection/security/entity/detail/app' // 安全事件实体详情app响应
|
||||||
},
|
},
|
||||||
performanceEvent: {
|
performanceEvent: {
|
||||||
eventSeverityTrend: '/interface/detection/performance/filter/severityTrend',
|
eventSeverityTrend: '/interface/detection/performance/filter/severityTrend',
|
||||||
@@ -139,13 +155,13 @@ export const api = {
|
|||||||
},
|
},
|
||||||
list: apiVersion + '/rule/detection/list', // 检测规则列表
|
list: apiVersion + '/rule/detection/list', // 检测规则列表
|
||||||
detail: apiVersion + '/rule/detection', // 检测规则详情
|
detail: apiVersion + '/rule/detection', // 检测规则详情
|
||||||
delete: apiVersion + '/rule', // 检测规则删除
|
delete: apiVersion + '/rule/detection', // 检测规则删除
|
||||||
// 获取单位列表,如source、type、metric等
|
// 获取单位列表,如source、type、metric等
|
||||||
statistics: apiVersion + '/detection/statistics',
|
statistics: apiVersion + '/rule/detection/statistics',
|
||||||
// 规则新建模块
|
// 规则新建模块
|
||||||
create: {
|
create: {
|
||||||
topKeys: apiVersion + '/detection/topKeys', // topKeys列表
|
topKeys: apiVersion + '/detection/topKeys', // topKeys列表
|
||||||
create: apiVersion + '/rule/detection/create' // todo 规则新建编辑,此api为模拟,后续需要修改
|
create: apiVersion + '/rule/detection'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// Dashboard
|
// Dashboard
|
||||||
@@ -248,6 +264,7 @@ export const api = {
|
|||||||
throughput: apiVersion + '/entity/detail/traffic/throughput',
|
throughput: apiVersion + '/entity/detail/traffic/throughput',
|
||||||
security: apiVersion + '/entity/detail/event/security',
|
security: apiVersion + '/entity/detail/event/security',
|
||||||
performance: apiVersion + '/entity/detail/event/performance',
|
performance: apiVersion + '/entity/detail/event/performance',
|
||||||
|
behaviorPattern: apiVersion + '/entity/detail/behavior/ip',
|
||||||
// 域名解析:ip相关app、domain
|
// 域名解析:ip相关app、domain
|
||||||
domainNameResolutionAboutAppsOfIp: apiVersion + '/entity/detail/ip/relate/apps',
|
domainNameResolutionAboutAppsOfIp: apiVersion + '/entity/detail/ip/relate/apps',
|
||||||
domainNameResolutionAboutDomainsOfIp: apiVersion + '/entity/detail/ip/relate/domains',
|
domainNameResolutionAboutDomainsOfIp: apiVersion + '/entity/detail/ip/relate/domains',
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -43,7 +43,7 @@ export function rTime (date) {
|
|||||||
}
|
}
|
||||||
// 日期转换为时间戳
|
// 日期转换为时间戳
|
||||||
export function toTime (date) {
|
export function toTime (date) {
|
||||||
return new Date(date).getTime()
|
return new Date(parseFloat(date)).getTime()
|
||||||
}
|
}
|
||||||
// 时间格式转换
|
// 时间格式转换
|
||||||
export function dateFormat (date, format = 'YYYY-MM-DD HH:mm:ss') {
|
export function dateFormat (date, format = 'YYYY-MM-DD HH:mm:ss') {
|
||||||
@@ -121,9 +121,9 @@ export function xAxisTimeFormatter (value) {
|
|||||||
':' +
|
':' +
|
||||||
(date.getMinutes() < 10 ? `0${date.getMinutes()}` : date.getMinutes())
|
(date.getMinutes() < 10 ? `0${date.getMinutes()}` : date.getMinutes())
|
||||||
// 如果是一天的开始
|
// 如果是一天的开始
|
||||||
if (date.getTime() === dayStart.getTime()) {
|
if (getSecond(date.getTime()) === getSecond(dayStart.getTime())) {
|
||||||
return '{day|' + dateFormat(date, 'YYYY-MM-DD') + '}'
|
return '{day|' + dateFormat(date, 'YYYY-MM-DD') + '}'
|
||||||
} else if (date.getTime() === hourStart.getTime()) {
|
} else if (getSecond(date.getTime()) === getSecond(hourStart.getTime())) {
|
||||||
return '{hour|' + HHmm + '}'
|
return '{hour|' + HHmm + '}'
|
||||||
} else {
|
} else {
|
||||||
return HHmm
|
return HHmm
|
||||||
@@ -137,3 +137,69 @@ export const xAxisTimeRich = {
|
|||||||
fontWeight: 'bold'
|
fontWeight: 'bold'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function switchDateTypeByStr (str) {
|
||||||
|
switch (str) {
|
||||||
|
// case 'Y':
|
||||||
|
// return 'years'
|
||||||
|
// case 'M':
|
||||||
|
// return 'months'
|
||||||
|
// case 'W':
|
||||||
|
// return 'weeks'
|
||||||
|
case 'D':
|
||||||
|
return 'days'
|
||||||
|
case 'H':
|
||||||
|
return 'hours'
|
||||||
|
case 'M':
|
||||||
|
return 'minutes'
|
||||||
|
case 'S':
|
||||||
|
return 'seconds'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function switchValueByDateType (str) {
|
||||||
|
switch (str) {
|
||||||
|
// case 'years':
|
||||||
|
// return 'Y'
|
||||||
|
// case 'months':
|
||||||
|
// return 'M'
|
||||||
|
// case 'weeks':
|
||||||
|
// return 'W'
|
||||||
|
case 'days':
|
||||||
|
return 'D'
|
||||||
|
case 'hours':
|
||||||
|
return 'H'
|
||||||
|
case 'minutes':
|
||||||
|
return 'M'
|
||||||
|
case 'seconds':
|
||||||
|
return 'S'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTimeByDurations (str) {
|
||||||
|
if (str && str.indexOf('P') === 0) {
|
||||||
|
const obj = {
|
||||||
|
type: '',
|
||||||
|
value: ''
|
||||||
|
}
|
||||||
|
for (let i = 1; i < str.length; i++) {
|
||||||
|
const item = str[i]
|
||||||
|
// P5D表示持续5天,PT5M持续5分钟,T是位于时间分量之前的时间指示符,即T之前是年月周日,T之后是时分秒
|
||||||
|
if (isNaN(item) && item !== 'T') {
|
||||||
|
obj.type = switchDateTypeByStr(item)
|
||||||
|
} else if (!isNaN(item)) {
|
||||||
|
obj.value += item
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getDurationsTimeByType (number, type) {
|
||||||
|
let T = ''
|
||||||
|
if (['hours', 'minutes', 'seconds'].indexOf(type) > -1) {
|
||||||
|
T = 'T'
|
||||||
|
}
|
||||||
|
return `P${T}${number}${switchValueByDateType(type)}`
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,42 +15,42 @@ _this.$t = _this.t
|
|||||||
export const dataForNpmTrafficLine = {
|
export const dataForNpmTrafficLine = {
|
||||||
tabs: [
|
tabs: [
|
||||||
{
|
{
|
||||||
name: _this.$t('network.total'),
|
name: 'network.total',
|
||||||
show: true,
|
show: true,
|
||||||
positioning: 0,
|
positioning: 0,
|
||||||
data: [],
|
data: [],
|
||||||
unitType: 'number'
|
unitType: 'number'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: _this.$t('network.inbound'),
|
name: 'network.inbound',
|
||||||
show: true,
|
show: true,
|
||||||
positioning: 1,
|
positioning: 1,
|
||||||
data: [],
|
data: [],
|
||||||
unitType: 'number'
|
unitType: 'number'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: _this.$t('network.outbound'),
|
name: 'network.outbound',
|
||||||
show: true,
|
show: true,
|
||||||
positioning: 2,
|
positioning: 2,
|
||||||
data: [],
|
data: [],
|
||||||
unitType: 'number'
|
unitType: 'number'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: _this.$t('network.internal'),
|
name: 'network.internal',
|
||||||
show: true,
|
show: true,
|
||||||
positioning: 3,
|
positioning: 3,
|
||||||
data: [],
|
data: [],
|
||||||
unitType: 'number'
|
unitType: 'number'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: _this.$t('network.through'),
|
name: 'network.through',
|
||||||
show: true,
|
show: true,
|
||||||
positioning: 4,
|
positioning: 4,
|
||||||
data: [],
|
data: [],
|
||||||
unitType: 'number'
|
unitType: 'number'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: _this.$t('network.other'),
|
name: 'network.other',
|
||||||
show: true,
|
show: true,
|
||||||
positioning: 5,
|
positioning: 5,
|
||||||
data: [],
|
data: [],
|
||||||
@@ -58,21 +58,21 @@ export const dataForNpmTrafficLine = {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
npmQuantity: [
|
npmQuantity: [
|
||||||
{ name: _this.$t('networkAppPerformance.tcpConnectionEstablishLatency'), show: true, positioning: 0, data: [], unitType: unitTypes.time, index: 0 },
|
{ name: 'networkAppPerformance.tcpConnectionEstablishLatency', show: true, positioning: 0, data: [], unitType: unitTypes.time, index: 0 },
|
||||||
{ name: _this.$t('networkAppPerformance.httpResponse'), show: true, positioning: 0, data: [], unitType: unitTypes.time, index: 1 },
|
{ name: 'networkAppPerformance.httpResponse', show: true, positioning: 0, data: [], unitType: unitTypes.time, index: 1 },
|
||||||
{ name: _this.$t('networkAppPerformance.sslResponseLatency'), show: true, positioning: 0, data: [], unitType: unitTypes.time, index: 2 },
|
{ name: 'networkAppPerformance.sslResponseLatency', show: true, positioning: 0, data: [], unitType: unitTypes.time, index: 2 },
|
||||||
{ name: _this.$t('networkAppPerformance.packetLoss'), show: true, positioning: 0, data: [], unitType: unitTypes.percent, index: 3 },
|
{ name: 'networkAppPerformance.packetLoss', show: true, positioning: 0, data: [], unitType: unitTypes.percent, index: 3 },
|
||||||
{ name: _this.$t('overall.packetRetrans'), show: true, positioning: 0, data: [], unitType: unitTypes.percent, index: 4 }
|
{ name: 'overall.packetRetrans', show: true, positioning: 0, data: [], unitType: unitTypes.percent, index: 4 }
|
||||||
],
|
],
|
||||||
metricOptions: [
|
metricOptions: [
|
||||||
/* { value: 'Bits/s', label: 'Bits/s' },
|
/* { value: 'Bits/s', label: 'Bits/s' },
|
||||||
{ value: 'Packets/s', label: 'Packets/s' },
|
{ value: 'Packets/s', label: 'Packets/s' },
|
||||||
{ value: 'Sessions/s', label: 'Sessions/s' }, */
|
{ value: 'Sessions/s', label: 'Sessions/s' }, */
|
||||||
{ value: 'establishLatencyMs', label: _this.$t('networkAppPerformance.tcpConnectionEstablishLatency') },
|
{ value: 'establishLatencyMs', label: 'networkAppPerformance.tcpConnectionEstablishLatency' },
|
||||||
{ value: 'httpResponseLatency', label: _this.$t('networkAppPerformance.httpResponse') },
|
{ value: 'httpResponseLatency', label: 'networkAppPerformance.httpResponse' },
|
||||||
{ value: 'sslConLatency', label: _this.$t('networkAppPerformance.sslResponseLatency') },
|
{ value: 'sslConLatency', label: 'networkAppPerformance.sslResponseLatency' },
|
||||||
{ value: 'tcpLostlenPercent', label: _this.$t('networkAppPerformance.packetLoss') },
|
{ value: 'tcpLostlenPercent', label: 'networkAppPerformance.packetLoss' },
|
||||||
{ value: 'pktRetransPercent', label: _this.$t('overall.packetRetrans') }
|
{ value: 'pktRetransPercent', label: 'overall.packetRetrans' }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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: [
|
||||||
@@ -175,9 +175,9 @@ export const dataForLinkTrafficLine = {
|
|||||||
|
|
||||||
export const dataForNpmLine = {
|
export const dataForNpmLine = {
|
||||||
chartOptionLineData: [
|
chartOptionLineData: [
|
||||||
{ legend: _this.$t('network.total'), index: 0, invertTab: true, show: false, color: '#749F4D' },
|
{ legend: 'network.total', index: 0, invertTab: true, show: false, color: '#749F4D' },
|
||||||
{ legend: _this.$t('network.inbound'), index: 1, invertTab: true, show: false, color: '#98709B' },
|
{ legend: 'network.inbound', index: 1, invertTab: true, show: false, color: '#98709B' },
|
||||||
{ legend: _this.$t('network.outbound'), index: 2, invertTab: true, show: false, color: '#E5A219' }
|
{ legend: 'network.outbound', index: 2, invertTab: true, show: false, color: '#E5A219' }
|
||||||
],
|
],
|
||||||
npmLineColor: [
|
npmLineColor: [
|
||||||
{ legend: '', color: '#749F4D' },
|
{ legend: '', color: '#749F4D' },
|
||||||
@@ -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: [
|
||||||
@@ -221,27 +221,27 @@ export const dataForDnsTrafficLine = {
|
|||||||
export const dataForNpmEventsHeader = {
|
export const dataForNpmEventsHeader = {
|
||||||
chartData: [
|
chartData: [
|
||||||
{
|
{
|
||||||
eventSeverity: 'critical',
|
eventSeverity: 'overall.critical',
|
||||||
count: '-',
|
count: '-',
|
||||||
index: 0
|
index: 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
eventSeverity: 'high',
|
eventSeverity: 'overall.high',
|
||||||
count: '-',
|
count: '-',
|
||||||
index: 1
|
index: 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
eventSeverity: 'medium',
|
eventSeverity: 'overall.medium',
|
||||||
count: '-',
|
count: '-',
|
||||||
index: 2
|
index: 2
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
eventSeverity: 'low',
|
eventSeverity: 'overall.low',
|
||||||
count: '-',
|
count: '-',
|
||||||
index: 3
|
index: 3
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
eventSeverity: 'info',
|
eventSeverity: 'overall.info',
|
||||||
count: '-',
|
count: '-',
|
||||||
index: 4
|
index: 4
|
||||||
}
|
}
|
||||||
@@ -334,11 +334,91 @@ export const columnList1 = [
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
const securityEvent = [
|
||||||
|
{
|
||||||
|
name: 'event_type',
|
||||||
|
type: 'string',
|
||||||
|
label: 'event_type',
|
||||||
|
doc: {
|
||||||
|
constraints: {
|
||||||
|
operator_functions: '=,in,like'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'event_name',
|
||||||
|
type: 'string',
|
||||||
|
label: 'event_name',
|
||||||
|
doc: {
|
||||||
|
constraints: {
|
||||||
|
operator_functions: '=,in,like'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'severity',
|
||||||
|
type: 'string',
|
||||||
|
label: 'severity',
|
||||||
|
doc: {
|
||||||
|
constraints: {
|
||||||
|
operator_functions: '=,in,like'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'offender_ip',
|
||||||
|
type: 'string',
|
||||||
|
label: 'offender Ip',
|
||||||
|
doc: {
|
||||||
|
constraints: {
|
||||||
|
operator_functions: '=,in,like'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'victim_ip',
|
||||||
|
type: 'string',
|
||||||
|
label: 'victim Ip',
|
||||||
|
doc: {
|
||||||
|
constraints: {
|
||||||
|
operator_functions: '=,in,like'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'domain',
|
||||||
|
type: 'string',
|
||||||
|
label: 'domain',
|
||||||
|
doc: {
|
||||||
|
constraints: {
|
||||||
|
operator_functions: '=,in,like'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'app',
|
||||||
|
type: 'string',
|
||||||
|
label: 'app',
|
||||||
|
doc: {
|
||||||
|
constraints: {
|
||||||
|
operator_functions: '=,in,like'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
let schemaEntityExplore = localStorage.getItem(storageKey.schemaEntityExplore)
|
const schema = localStorage.getItem(storageKey.schemaEntityExplore)
|
||||||
schemaEntityExplore = schemaEntityExplore ? JSON.parse(schemaEntityExplore).entityMetadata.searchColumns : columnList1
|
const schemaEntityExplore = schema ? JSON.parse(schema).entityMetadata.searchColumns : columnList1
|
||||||
export const columnList = schemaEntityExplore
|
export const columnList = schemaEntityExplore
|
||||||
|
|
||||||
|
let securityEventMetadata = securityEvent
|
||||||
|
if (schema) {
|
||||||
|
if (JSON.parse(schema).securityEventMetadata) {
|
||||||
|
securityEventMetadata = JSON.parse(schema).securityEventMetadata.searchColumns
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export const schemaDetectionSecurity = securityEventMetadata
|
||||||
|
|
||||||
export const operatorList = ['=', '!=', /* '>', '<', '>=', '<=', */'IN', 'NOT IN', 'LIKE', 'NOT LIKE']
|
export const operatorList = ['=', '!=', /* '>', '<', '>=', '<=', */'IN', 'NOT IN', 'LIKE', 'NOT LIKE']
|
||||||
export const connectionList = [
|
export const connectionList = [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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 = {
|
||||||
// 是否需要排序
|
// 是否需要排序
|
||||||
@@ -784,7 +785,7 @@ export function getChainRatio (current, prev) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function computeScore (data) {
|
export function computeScore (data, scoreBase) {
|
||||||
let score = 0
|
let score = 0
|
||||||
let k = 0
|
let k = 0
|
||||||
let totalScore = 0
|
let totalScore = 0
|
||||||
@@ -799,26 +800,14 @@ export function computeScore (data) {
|
|||||||
} else if (t === 'httpResponseLatency' || t === 'sslConLatency') {
|
} else if (t === 'httpResponseLatency' || t === 'sslConLatency') {
|
||||||
k = 0.05
|
k = 0.05
|
||||||
}
|
}
|
||||||
if (t === 'establishLatencyMs' || t === 'httpResponseLatency' || t === 'sslConLatency') {
|
|
||||||
if (!data[t] && data[t] !== 0) {
|
if (!data[t] && data[t] !== 0) {
|
||||||
score = 1
|
score = 1
|
||||||
} else if (data[t] <= 50) {
|
} else if (data[t] <= scoreBase[t].p10) {
|
||||||
score = 1
|
score = 1
|
||||||
} else if (data[t] > 200) {
|
} else if (data[t] >= scoreBase[t].p90) {
|
||||||
score = 0
|
score = 0
|
||||||
} else {
|
} else {
|
||||||
score = (data[t] - 200) / (50 - 200)
|
score = (data[t] - scoreBase[t].p90) / (scoreBase[t].p10 - scoreBase[t].p90)
|
||||||
}
|
|
||||||
} else if (t === 'tcpLostlenPercent' || t === 'pktRetransPercent') {
|
|
||||||
if (!data[t] && data[t] !== 0) {
|
|
||||||
score = 1
|
|
||||||
} else if (data[t] <= 0.01) {
|
|
||||||
score = 1
|
|
||||||
} else if (data[t] > 0.05) {
|
|
||||||
score = 0
|
|
||||||
} else {
|
|
||||||
score = (data[t] - 0.05) / (0.01 - 0.05)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
scoreArr.push(score * k)
|
scoreArr.push(score * k)
|
||||||
})
|
})
|
||||||
@@ -1260,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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1318,12 +1307,13 @@ export function numberWithCommas (num) {
|
|||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
export function switchStatus (status) {
|
export function switchStatus (status) {
|
||||||
switch (status) {
|
switch (status + '') {
|
||||||
case 0:
|
case '0':
|
||||||
return 'Disabled'
|
return 'detection.create.disabled'
|
||||||
case 1:
|
case '1':
|
||||||
return 'Enabled'
|
return 'detection.create.enabled'
|
||||||
}
|
}
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1356,3 +1346,104 @@ export function beforeRouterPush () {
|
|||||||
}
|
}
|
||||||
store.commit('setRouterHistoryList', historyList)
|
store.commit('setRouterHistoryList', historyList)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置tag颜色,此为接口返回的颜色字段,color为rgb格式
|
||||||
|
* @param color
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export function getTagColor (color) {
|
||||||
|
if (color) {
|
||||||
|
let backgroundColor = ''
|
||||||
|
if (color.indexOf('rgb(') > -1) {
|
||||||
|
backgroundColor = color.replace('rgb(', 'rgba(').replace(')', ',0.06)')
|
||||||
|
}
|
||||||
|
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
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,93 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div style="height: 100%;">
|
|
||||||
<cn-data-list
|
|
||||||
ref="dataList"
|
|
||||||
:tableId="tableId"
|
|
||||||
v-model:custom-table-title="tools.customTableTitle"
|
|
||||||
:api="url"
|
|
||||||
:from="fromRoute.chart"
|
|
||||||
:layout="['columnCustomize','elementSet','search']"
|
|
||||||
@search="search"
|
|
||||||
>
|
|
||||||
<template #top-tool-left>
|
|
||||||
<button id="chart-add"
|
|
||||||
class="top-tool-btn margin-r-10 top-tool-btn--create"
|
|
||||||
@click="add">
|
|
||||||
<i class="cn-icon-xinjian cn-icon"></i>
|
|
||||||
<span>{{$t('overall.create')}}</span>
|
|
||||||
</button>
|
|
||||||
<button id="chart-edit" class="top-tool-btn margin-r-10" :disabled="disableEdit"
|
|
||||||
@click="editSelectRecord">
|
|
||||||
<i class="cn-icon-edit cn-icon"></i>
|
|
||||||
<span>{{$t('overall.edit')}}</span>
|
|
||||||
</button>
|
|
||||||
<button id="chart-delete" class="top-tool-btn margin-r-10" :disabled="disableDelete"
|
|
||||||
@click="delBatch">
|
|
||||||
<i class="cn-icon-delete cn-icon"></i>
|
|
||||||
<span>{{$t('overall.delete')}}</span>
|
|
||||||
</button>
|
|
||||||
</template>
|
|
||||||
<template #default>
|
|
||||||
<loading :loading="loading"></loading>
|
|
||||||
<chart-table
|
|
||||||
ref="dataTable"
|
|
||||||
:api="url"
|
|
||||||
:isNoData="isNoData"
|
|
||||||
:custom-table-title="tools.customTableTitle"
|
|
||||||
:height="mainTableHeight"
|
|
||||||
:table-data="tableData"
|
|
||||||
@delete="del"
|
|
||||||
@edit="edit"
|
|
||||||
@orderBy="tableDataSort"
|
|
||||||
@reload="getTableData"
|
|
||||||
@selectionChange="selectionChange"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template #pagination>
|
|
||||||
<pagination ref="pagination" :page-obj="pageObj" :table-id="tableId" @pageNo='pageNo' @pageSize='pageSize'></pagination>
|
|
||||||
</template>
|
|
||||||
</cn-data-list>
|
|
||||||
<el-drawer
|
|
||||||
v-model="rightBox.show"
|
|
||||||
direction="rtl"
|
|
||||||
custom-class="common-right-box"
|
|
||||||
:size="700"
|
|
||||||
:with-header="false"
|
|
||||||
destroy-on-close>
|
|
||||||
<chart-box
|
|
||||||
:object="object"
|
|
||||||
@close="closeRightBox"
|
|
||||||
/>
|
|
||||||
</el-drawer>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
import cnDataList from '@/components/table/CnDataList'
|
|
||||||
import dataListMixin from '@/mixins/data-list'
|
|
||||||
import chartTable from '@/components/table/administration/ChartTable'
|
|
||||||
import chartBox from '@/components/rightBox/settings/ChartBox'
|
|
||||||
import { api } from '@/utils/api'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'Chart',
|
|
||||||
mixins: [dataListMixin],
|
|
||||||
components: {
|
|
||||||
cnDataList,
|
|
||||||
chartTable,
|
|
||||||
chartBox
|
|
||||||
},
|
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
url: api.chart,
|
|
||||||
listUrl: api.chartList,
|
|
||||||
blankObject: { // 空白对象
|
|
||||||
id: '',
|
|
||||||
name: '',
|
|
||||||
params: '',
|
|
||||||
i18n: ''
|
|
||||||
},
|
|
||||||
tableId: 'chartTable'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div style="height: 100%;">
|
|
||||||
<cn-data-list
|
|
||||||
ref="dataList"
|
|
||||||
:tableId="tableId"
|
|
||||||
v-model:custom-table-title="tools.customTableTitle"
|
|
||||||
:api="url"
|
|
||||||
:from="fromRoute.galaxyProxy"
|
|
||||||
:layout="['columnCustomize','elementSet','search']"
|
|
||||||
@search="search"
|
|
||||||
>
|
|
||||||
<template v-slot:top-tool-left>
|
|
||||||
<button id="galaxy-proxy-clear-cache" class="top-tool-btn margin-r-10" :title="$t('overall.clearCache')"
|
|
||||||
type="button" @click="clearCache">
|
|
||||||
<i class="cn-icon cn-icon-clear-cache"></i>
|
|
||||||
</button>
|
|
||||||
<button id="galaxy-proxy-add"
|
|
||||||
class="top-tool-btn margin-r-10 top-tool-btn--create"
|
|
||||||
@click="add">
|
|
||||||
<i class="cn-icon-xinjian cn-icon"></i>
|
|
||||||
<span>{{$t('overall.create')}}</span>
|
|
||||||
</button>
|
|
||||||
<button id="galaxy-edit" class="top-tool-btn margin-r-10" :disabled="disableEdit"
|
|
||||||
@click="editSelectRecord">
|
|
||||||
<i class="cn-icon-edit cn-icon"></i>
|
|
||||||
<span>{{$t('overall.edit')}}</span>
|
|
||||||
</button>
|
|
||||||
<button id="galaxy-delete" class="top-tool-btn margin-r-10"
|
|
||||||
@click="delBatch">
|
|
||||||
<i class="cn-icon-delete cn-icon"></i>
|
|
||||||
<span>{{$t('overall.delete')}}</span>
|
|
||||||
</button>
|
|
||||||
<button id="galaxy-proxy-debug" class="top-tool-btn margin-r-10" :title="$t('overall.debug')"
|
|
||||||
type="button" @click="debug(true,{})">
|
|
||||||
<i class="cn-icon-category cn-icon"></i>
|
|
||||||
</button>
|
|
||||||
<top-tool-more-options
|
|
||||||
ref="export"
|
|
||||||
id="model"
|
|
||||||
:params="searchLabel"
|
|
||||||
class="top-tool-export margin-l-10 margin-r-10"
|
|
||||||
export-file-name="galaxyProxy"
|
|
||||||
export-url="/galaxy/setting/export"
|
|
||||||
import-url="/galaxy/setting/import"
|
|
||||||
@afterImport="getTableData"
|
|
||||||
>
|
|
||||||
<template v-slot:before>
|
|
||||||
</template>
|
|
||||||
</top-tool-more-options>
|
|
||||||
</template>
|
|
||||||
<template v-slot:default>
|
|
||||||
<loading :loading="loading"></loading>
|
|
||||||
<galaxy-proxy-table
|
|
||||||
ref="dataTable"
|
|
||||||
:api="url"
|
|
||||||
:isNoData="isNoData"
|
|
||||||
:custom-table-title="tools.customTableTitle"
|
|
||||||
:height="mainTableHeight"
|
|
||||||
:table-data="tableData"
|
|
||||||
@delete="del"
|
|
||||||
@edit="edit"
|
|
||||||
@orderBy="tableDataSort"
|
|
||||||
@reload="getTableData"
|
|
||||||
@selectionChange="selectionChange"
|
|
||||||
@copy="copy"
|
|
||||||
@debug="debugRow"
|
|
||||||
></galaxy-proxy-table>
|
|
||||||
</template>
|
|
||||||
<!-- 分页组件 -->
|
|
||||||
<template #pagination>
|
|
||||||
<pagination ref="pagination" :page-obj="pageObj" :table-id="tableId" @pageNo='pageNo' @pageSize='pageSize'></pagination>
|
|
||||||
</template>
|
|
||||||
</cn-data-list>
|
|
||||||
<el-drawer
|
|
||||||
v-model="rightBox.show"
|
|
||||||
direction="rtl"
|
|
||||||
custom-class="common-right-box"
|
|
||||||
:size="700"
|
|
||||||
:with-header="false"
|
|
||||||
destroy-on-close>
|
|
||||||
<galaxy-proxy-box :object="object" @close="closeRightBox"></galaxy-proxy-box>
|
|
||||||
</el-drawer>
|
|
||||||
</div>
|
|
||||||
<galaxy-proxy-debug
|
|
||||||
v-model:show-debug="showDebug"
|
|
||||||
top="5vh"
|
|
||||||
:show-close="false"
|
|
||||||
:curGalaxyProxy="curGalaxyProxy"></galaxy-proxy-debug>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import cnDataList from '@/components/table/CnDataList'
|
|
||||||
import galaxyProxyBox from '@/components/rightBox/settings/GalaxyProxyBox'
|
|
||||||
import galaxyProxyTable from '@/components/table/administration/GalaxyProxyTable'
|
|
||||||
import dataListMixin from '@/mixins/data-list'
|
|
||||||
import { api } from '@/utils/api'
|
|
||||||
import axios from 'axios'
|
|
||||||
import TopToolMoreOptions from '@/components/common/popBox/TopToolMoreOptions'
|
|
||||||
import galaxyProxyDebug from '@/components/setting/GalaxyProxyDebug'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'GalaxyProxy',
|
|
||||||
components: {
|
|
||||||
cnDataList,
|
|
||||||
galaxyProxyBox,
|
|
||||||
galaxyProxyTable,
|
|
||||||
TopToolMoreOptions,
|
|
||||||
galaxyProxyDebug
|
|
||||||
},
|
|
||||||
mixins: [dataListMixin],
|
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
url: api.galaxyProxy,
|
|
||||||
tableId: 'galaxySettingTable', // 需要分页的table的id,用于记录每页数量
|
|
||||||
blankObject: { // 空白对象
|
|
||||||
name: ''
|
|
||||||
},
|
|
||||||
showDebug: false,
|
|
||||||
curGalaxyProxy: {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
edit (u) {
|
|
||||||
axios.get(`${this.url}/${u.id}`).then(response => {
|
|
||||||
if (response.status === 200) {
|
|
||||||
const editObject = response.data.data
|
|
||||||
editObject.targetHeader || (editObject.targetHeader = '')
|
|
||||||
editObject.preHandle || (editObject.preHandle = '')
|
|
||||||
editObject.postHandle || (editObject.postHandle = '')
|
|
||||||
editObject.targetParam || (editObject.targetParam = '')
|
|
||||||
this.object = editObject
|
|
||||||
this.rightBox.show = true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
debug (isTopDebug, u) {
|
|
||||||
if (!isTopDebug && u) {
|
|
||||||
this.curGalaxyProxy = JSON.parse(JSON.stringify(u))
|
|
||||||
}
|
|
||||||
this.showDebug = true
|
|
||||||
},
|
|
||||||
debugRow (u) {
|
|
||||||
this.debug(false, u)
|
|
||||||
},
|
|
||||||
clearCache () {
|
|
||||||
axios.put(`${this.url}/clearCache`).then(response => {
|
|
||||||
if (response.status === 200) {
|
|
||||||
this.$message({ duration: 2000, type: 'success', message: this.$t('tip.success') })
|
|
||||||
} else {
|
|
||||||
this.$message.error(response.data.message)
|
|
||||||
}
|
|
||||||
}).catch(() => {
|
|
||||||
this.$message.error(this.$t('tip.unknownError'))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -58,7 +58,7 @@
|
|||||||
size="mini"
|
size="mini"
|
||||||
v-model="table.limit"
|
v-model="table.limit"
|
||||||
class="option__select select-topn"
|
class="option__select select-topn"
|
||||||
placeholder=""
|
placeholder=" "
|
||||||
popper-class="option-popper"
|
popper-class="option-popper"
|
||||||
@change="tableLimitChange"
|
@change="tableLimitChange"
|
||||||
>
|
>
|
||||||
@@ -125,7 +125,7 @@
|
|||||||
size="mini"
|
size="mini"
|
||||||
v-model="copyOrderPieTable"
|
v-model="copyOrderPieTable"
|
||||||
class="option__select select-column"
|
class="option__select select-column"
|
||||||
placeholder=""
|
placeholder=" "
|
||||||
popper-class="option-popper"
|
popper-class="option-popper"
|
||||||
@change="orderPieTableChange"
|
@change="orderPieTableChange"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -5,12 +5,12 @@
|
|||||||
v-if="panel.params && panel.params.wholeScreenScroll"
|
v-if="panel.params && panel.params.wholeScreenScroll"
|
||||||
id="wholeScreenBox"
|
id="wholeScreenBox"
|
||||||
>
|
>
|
||||||
<dns-screen v-if="currentPath === wholeScreenRouterMapping.dns"
|
<!-- <dns-screen v-if="currentPath === wholeScreenRouterMapping.dns"
|
||||||
:copy-data-list="chartList"
|
:copy-data-list="chartList"
|
||||||
ref="dnsScreen"
|
ref="dnsScreen"
|
||||||
:time-filter="timeFilter"
|
:time-filter="timeFilter"
|
||||||
:entity="entity">
|
:entity="entity">
|
||||||
</dns-screen>
|
</dns-screen>-->
|
||||||
</div>
|
</div>
|
||||||
<div id="panelList" v-if="!isEntityDetail" class="panel-list">
|
<div id="panelList" v-if="!isEntityDetail" class="panel-list">
|
||||||
<div id="cn-panel" class="cn-panel2">
|
<div id="cn-panel" class="cn-panel2">
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import DnsScreen from '@/views/charts/wholeScreenScroll/DnsScreen'
|
// import DnsScreen from '@/views/charts/wholeScreenScroll/DnsScreen'
|
||||||
import { panelTypeAndRouteMapping, wholeScreenRouterMapping } from '@/utils/constants'
|
import { panelTypeAndRouteMapping, wholeScreenRouterMapping } from '@/utils/constants'
|
||||||
import { api, getPanelList, getChartList } from '@/utils/api'
|
import { api, getPanelList, getChartList } from '@/utils/api'
|
||||||
import { getNowTime } from '@/utils/date-util'
|
import { getNowTime } from '@/utils/date-util'
|
||||||
@@ -66,9 +66,9 @@ export default {
|
|||||||
isEntityDetail: Boolean,
|
isEntityDetail: Boolean,
|
||||||
typeName: String
|
typeName: String
|
||||||
},
|
},
|
||||||
components: {
|
/* components: {
|
||||||
DnsScreen
|
DnsScreen
|
||||||
},
|
}, */
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
chartList: [], // 普通panel的chart
|
chartList: [], // 普通panel的chart
|
||||||
@@ -104,8 +104,8 @@ export default {
|
|||||||
setup (props, ctx) {
|
setup (props, ctx) {
|
||||||
const panel = ref({})
|
const panel = ref({})
|
||||||
let panelType = 1 // 取得panel的type
|
let panelType = 1 // 取得panel的type
|
||||||
const { params } = useRoute()
|
const { path } = useRoute()
|
||||||
panelType = props.entity ? props.entity.type : panelTypeAndRouteMapping[params.typeName]
|
panelType = props.entity ? props.entity.type : panelTypeAndRouteMapping[path.replace('/panel/', '')]
|
||||||
|
|
||||||
// date
|
// date
|
||||||
const dateRangeValue = 60
|
const dateRangeValue = 60
|
||||||
|
|||||||
@@ -338,7 +338,10 @@ export function axisFormatter (params) {
|
|||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
export function tooLongFormatter (name) {
|
export function tooLongFormatter (name) {
|
||||||
return format.truncateText(name, 110, '12px')
|
return format.truncateText(name, 160, '12px')
|
||||||
|
}
|
||||||
|
export function tooLongFormatterFor2Columns (name) {
|
||||||
|
return format.truncateText(name, 100, '12px')
|
||||||
}
|
}
|
||||||
export function timeHorizontalFormatter (params) {
|
export function timeHorizontalFormatter (params) {
|
||||||
let str = '<div>'
|
let str = '<div>'
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="panel-box2" :class="{'panel-box2--entity-detail': entity && entity.entityType}">
|
<div class="panel-box2" :class="{'panel-box2--entity-detail': entity && entity.entityType}">
|
||||||
<div class="panel__header" v-if="!entity">
|
<div class="panel__header" v-if="!entity">
|
||||||
<div class="panel__title">{{panelName?panelName:(panel.i18n ? $t(panel.i18n) : panel.name)}}
|
<div class="panel__title">{{panelName ? panelName:(panel.i18n ? $t(panel.i18n) : panel.name)}}
|
||||||
<div v-if="showScore" class="score">
|
<div v-if="showScore" class="score">
|
||||||
<div class="circle-icon" v-if="score <= 2 || score === '-'" :class="{'data-score-red': score <= 2 || score === '-'}" ></div>
|
<div class="circle-icon" v-if="score <= 2 || score === '-'" :class="{'data-score-red': score <= 2 || score === '-'}" ></div>
|
||||||
<div class="circle-icon" v-else-if="score <= 4" :class="{'data-score-yellow': score <= 4}" ></div>
|
<div class="circle-icon" v-else-if="score <= 4" :class="{'data-score-yellow': score <= 4}" ></div>
|
||||||
@@ -24,14 +24,14 @@
|
|||||||
<el-select
|
<el-select
|
||||||
size="mini"
|
size="mini"
|
||||||
v-model="metric"
|
v-model="metric"
|
||||||
placeholder=""
|
placeholder=" "
|
||||||
popper-class="common-select"
|
popper-class="common-select"
|
||||||
v-if="showMetric"
|
v-if="showMetric"
|
||||||
:popper-append-to-body="false"
|
:popper-append-to-body="false"
|
||||||
@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>
|
||||||
@@ -104,7 +104,9 @@ export default {
|
|||||||
dnsRcodeMapData: [],
|
dnsRcodeMapData: [],
|
||||||
dnsQtypeMapData: [],
|
dnsQtypeMapData: [],
|
||||||
score: null,
|
score: null,
|
||||||
curTabState: curTabState
|
curTabState: curTabState,
|
||||||
|
performanceData: {},
|
||||||
|
scoreDataState: false // 评分数据是否加载完成
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -114,29 +116,39 @@ export default {
|
|||||||
// 显示顶部的Metric单位选项标识
|
// 显示顶部的Metric单位选项标识
|
||||||
showMetric () {
|
showMetric () {
|
||||||
return this.panelType === panelTypeAndRouteMapping.networkOverview || this.panelType === panelTypeAndRouteMapping.networkOverviewDrillDown
|
return this.panelType === panelTypeAndRouteMapping.networkOverview || this.panelType === panelTypeAndRouteMapping.networkOverviewDrillDown
|
||||||
|
},
|
||||||
|
scoreBaseState () {
|
||||||
|
return this.$store.getters.scoreBaseReady
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
// npmThirdLevelMenuScore: {
|
|
||||||
// deep: true,
|
|
||||||
// immediate: true,
|
|
||||||
// handler (n) {
|
|
||||||
// this.score = n
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
timeFilter: {
|
timeFilter: {
|
||||||
handler () {
|
handler () {
|
||||||
if (this.$route.path === '/panel/networkAppPerformance' && (this.lineQueryCondition || this.networkOverviewBeforeTab)) {
|
if (this.$route.path === '/panel/networkAppPerformance') {
|
||||||
|
this.$store.commit('resetScoreBase')
|
||||||
|
this.queryScoreBase()
|
||||||
|
if (this.lineQueryCondition || this.networkOverviewBeforeTab) {
|
||||||
this.scoreCalculation()
|
this.scoreCalculation()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
scoreBaseState (n) {
|
||||||
|
if (n && this.scoreDataState) {
|
||||||
|
this.handleScoreData()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
scoreDataState (n) {
|
||||||
|
if (n && this.scoreBaseState) {
|
||||||
|
this.handleScoreData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
async mounted () {
|
async mounted () {
|
||||||
// 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)
|
||||||
@@ -212,9 +224,15 @@ export default {
|
|||||||
return chart
|
return chart
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
if (this.$route.path === '/panel/networkAppPerformance' && (this.lineQueryCondition || this.networkOverviewBeforeTab)) {
|
if (this.$route.path === '/panel/networkAppPerformance') {
|
||||||
|
if (this.lineQueryCondition || this.networkOverviewBeforeTab) {
|
||||||
this.scoreCalculation()
|
this.scoreCalculation()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (this.$route.path === '/panel/networkAppPerformance' || this.$route.path === '/panel/linkMonitor') {
|
||||||
|
this.$store.commit('resetScoreBase')
|
||||||
|
this.queryScoreBase()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
setup (props) {
|
setup (props) {
|
||||||
// router引入store会报错,故在panel里调用
|
// router引入store会报错,故在panel里调用
|
||||||
@@ -231,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
|
||||||
|
|
||||||
@@ -274,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
|
||||||
@@ -396,6 +413,44 @@ export default {
|
|||||||
})
|
})
|
||||||
overwriteUrl(newUrl)
|
overwriteUrl(newUrl)
|
||||||
},
|
},
|
||||||
|
// 动态查询评分基准
|
||||||
|
queryScoreBase () {
|
||||||
|
const params = {
|
||||||
|
startTime: this.timeFilter.startTime,
|
||||||
|
endTime: this.timeFilter.endTime
|
||||||
|
}
|
||||||
|
const tcp = axios.get(api.npm.overview.tcpSessionDelay, { params: params })
|
||||||
|
const http = axios.get(api.npm.overview.httpResponseDelay, { params: params })
|
||||||
|
const ssl = axios.get(api.npm.overview.sslConDelay, { params: params })
|
||||||
|
const tcpPercent = axios.get(api.npm.overview.tcpLostlenPercent, { params: params })
|
||||||
|
const packetPercent = axios.get(api.npm.overview.packetRetransPercent, { params: params })
|
||||||
|
Promise.all([tcp, http, ssl, tcpPercent, packetPercent]).then(res => {
|
||||||
|
const scoreBase = {}
|
||||||
|
res.forEach((t, i) => {
|
||||||
|
if (t.status === 200) {
|
||||||
|
if (i === 0) {
|
||||||
|
scoreBase.establishLatencyMsP10 = _.get(t.data, 'data.result.establishLatencyMsP10', null)
|
||||||
|
scoreBase.establishLatencyMsP90 = _.get(t.data, 'data.result.establishLatencyMsP90', null)
|
||||||
|
} else if (i === 1) {
|
||||||
|
scoreBase.httpResponseLatencyP10 = _.get(t.data, 'data.result.httpResponseLatencyP10', null)
|
||||||
|
scoreBase.httpResponseLatencyP90 = _.get(t.data, 'data.result.httpResponseLatencyP90', null)
|
||||||
|
} else if (i === 2) {
|
||||||
|
scoreBase.sslConLatencyP10 = _.get(t.data, 'data.result.sslConLatencyP10', null)
|
||||||
|
scoreBase.sslConLatencyP90 = _.get(t.data, 'data.result.sslConLatencyP90', null)
|
||||||
|
} else if (i === 3) {
|
||||||
|
scoreBase.tcpLostlenPercentP10 = _.get(t.data, 'data.result.tcpLostlenPercentP10', null)
|
||||||
|
scoreBase.tcpLostlenPercentP90 = _.get(t.data, 'data.result.tcpLostlenPercentP90', null)
|
||||||
|
} else if (i === 4) {
|
||||||
|
scoreBase.pktRetransPercentP10 = _.get(t.data, 'data.result.pktRetransPercentP10', null)
|
||||||
|
scoreBase.pktRetransPercentP90 = _.get(t.data, 'data.result.pktRetransPercentP90', null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.$store.commit('setScoreBase', scoreBase)
|
||||||
|
}).catch((e) => {
|
||||||
|
}).finally(() => {
|
||||||
|
})
|
||||||
|
},
|
||||||
scoreCalculation () {
|
scoreCalculation () {
|
||||||
let condition = ''
|
let condition = ''
|
||||||
let url = ''
|
let url = ''
|
||||||
@@ -443,30 +498,36 @@ export default {
|
|||||||
url = api.npm.overview.networkAnalysis
|
url = api.npm.overview.networkAnalysis
|
||||||
}
|
}
|
||||||
if ((type && condition) || type) {
|
if ((type && condition) || type) {
|
||||||
|
this.scoreDataState = false
|
||||||
|
this.performanceData = {}
|
||||||
params.type = params.type || type
|
params.type = params.type || type
|
||||||
axios.get(url, { params }).then(res => {
|
axios.get(url, { params }).then(res => {
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
const data = {
|
this.performanceData = {
|
||||||
establishLatencyMs: _.get(res, 'data.data.result.establishLatencyMsAvg', null),
|
establishLatencyMs: _.get(res, 'data.data.result.establishLatencyMsAvg', null),
|
||||||
httpResponseLatency: _.get(res, 'data.data.result.httpResponseLatencyAvg', null),
|
httpResponseLatency: _.get(res, 'data.data.result.httpResponseLatencyAvg', null),
|
||||||
sslConLatency: _.get(res, 'data.data.result.sslConLatencyAvg', null),
|
sslConLatency: _.get(res, 'data.data.result.sslConLatencyAvg', null),
|
||||||
tcpLostlenPercent: _.get(res, 'data.data.result.tcpLostlenPercentAvg', null),
|
tcpLostlenPercent: _.get(res, 'data.data.result.tcpLostlenPercentAvg', null),
|
||||||
pktRetransPercent: _.get(res, 'data.data.result.pktRetransPercentAvg', null)
|
pktRetransPercent: _.get(res, 'data.data.result.pktRetransPercentAvg', null)
|
||||||
}
|
}
|
||||||
this.score = computeScore(data)
|
|
||||||
}
|
}
|
||||||
|
}).finally(() => {
|
||||||
|
this.scoreDataState = true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
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
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
window.open(href, '_blank')
|
window.open(href, '_blank')
|
||||||
|
},
|
||||||
|
handleScoreData () {
|
||||||
|
this.score = computeScore(this.performanceData, this.$store.getters.getScoreBase)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -27,12 +27,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</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('network.metric')}}:</span>
|
||||||
<div class="line-select__operation">
|
<div class="line-select__operation">
|
||||||
<el-select
|
<el-select
|
||||||
size="mini"
|
size="mini"
|
||||||
v-model="lineMetric"
|
v-model="lineMetric"
|
||||||
|
placeholder=" "
|
||||||
popper-class="common-select"
|
popper-class="common-select"
|
||||||
:popper-append-to-body="false"
|
:popper-append-to-body="false"
|
||||||
@change="metricSelectChange"
|
@change="metricSelectChange"
|
||||||
@@ -40,19 +41,22 @@
|
|||||||
<el-option v-for="item in options1" :key="item.value" :label="item.label" :value="item.value"></el-option>
|
<el-option v-for="item in options1" :key="item.value" :label="item.label" :value="item.value"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</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"
|
||||||
v-model="lineRefer"
|
v-model="lineRefer"
|
||||||
|
placeholder=" "
|
||||||
:disabled="!lineTab"
|
:disabled="!lineTab"
|
||||||
popper-class="common-select"
|
popper-class="common-select"
|
||||||
: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>
|
||||||
@@ -174,6 +178,9 @@ export default {
|
|||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
this.showError = false
|
this.showError = false
|
||||||
this.isNoData = res.data.data.result.length === 0
|
this.isNoData = res.data.data.result.length === 0
|
||||||
|
if (!active) {
|
||||||
|
this.tabs = _.cloneDeep(dataForDnsTrafficLine.tabs)
|
||||||
|
}
|
||||||
if (this.isNoData) {
|
if (this.isNoData) {
|
||||||
this.lineTab = ''
|
this.lineTab = ''
|
||||||
this.tabs = _.cloneDeep(dataForDnsTrafficLine.tabs)
|
this.tabs = _.cloneDeep(dataForDnsTrafficLine.tabs)
|
||||||
@@ -250,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',
|
||||||
@@ -445,6 +460,7 @@ export default {
|
|||||||
this.legendSelectChange(e, 0)
|
this.legendSelectChange(e, 0)
|
||||||
})
|
})
|
||||||
this.tabs = tabs
|
this.tabs = tabs
|
||||||
|
this.lineRefer = 'Average'
|
||||||
this.echartsInit(this.tabs, true)
|
this.echartsInit(this.tabs, true)
|
||||||
} else {
|
} else {
|
||||||
const unit = 'bps'
|
const unit = 'bps'
|
||||||
@@ -464,7 +480,7 @@ export default {
|
|||||||
|
|
||||||
dnsData.forEach(e => {
|
dnsData.forEach(e => {
|
||||||
e.unitType = type
|
e.unitType = type
|
||||||
if (parseFloat(e.analysis.avg) === 0 || isNaN(parseFloat(e.analysis.avg))) {
|
if (parseFloat(e.analysis.max) === 0 || isNaN(parseFloat(e.analysis.max))) {
|
||||||
e.show = false
|
e.show = false
|
||||||
num += 1
|
num += 1
|
||||||
} else {
|
} else {
|
||||||
@@ -474,13 +490,18 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.lineTab === e.class) {
|
if (this.lineTab === e.class) {
|
||||||
if (parseFloat(e.analysis.avg) <= 0) {
|
if (parseFloat(e.analysis.max) <= 0) {
|
||||||
this.lineTab = ''
|
this.lineTab = ''
|
||||||
this.lineRefer = ''
|
this.lineRefer = ''
|
||||||
this.init()
|
// this.init() // 后续多关注
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
const emptyData = dnsData.filter(d => parseFloat(d.analysis.max) === 0)
|
||||||
|
this.isNoData = emptyData.length === dnsData.length
|
||||||
|
if (this.isNoData) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
this.tabs = dnsData
|
this.tabs = dnsData
|
||||||
// 如果三者avg都为0时,至少保证total显示
|
// 如果三者avg都为0时,至少保证total显示
|
||||||
@@ -489,10 +510,10 @@ export default {
|
|||||||
let ingressAvg = 0
|
let ingressAvg = 0
|
||||||
let egressAvg = 0
|
let egressAvg = 0
|
||||||
if (ingressObj) {
|
if (ingressObj) {
|
||||||
ingressAvg = parseFloat(ingressObj.analysis.avg) || 0
|
ingressAvg = parseFloat(ingressObj.analysis.max) || 0
|
||||||
}
|
}
|
||||||
if (egressObj) {
|
if (egressObj) {
|
||||||
egressAvg = parseFloat(egressObj.analysis.avg) || 0
|
egressAvg = parseFloat(egressObj.analysis.max) || 0
|
||||||
}
|
}
|
||||||
if ((ingressAvg + egressAvg) === 0) {
|
if ((ingressAvg + egressAvg) === 0) {
|
||||||
const totalObj = dnsData.find(d => d.name === 'network.total')
|
const totalObj = dnsData.find(d => d.name === 'network.total')
|
||||||
|
|||||||
@@ -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>
|
||||||
@@ -32,7 +32,13 @@
|
|||||||
</el-popover>
|
</el-popover>
|
||||||
</div>
|
</div>
|
||||||
<div class="entity-tags" v-if="!hideTagArea">
|
<div class="entity-tags" v-if="!hideTagArea">
|
||||||
<div v-for="tag in levelTwoTags" :key="tag.value" class="entity-tag" :class="`entity-tag--level-two-${tag.type}`">{{tag.value}}</div>
|
<div v-for="tag in levelTwoTags"
|
||||||
|
:key="tag.value"
|
||||||
|
class="entity-tag"
|
||||||
|
:class="`entity-tag--level-two-${tag.type}`"
|
||||||
|
:style="getTagColor(tag.color)">
|
||||||
|
{{tag.value}}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 分割线-->
|
<!-- 分割线-->
|
||||||
<div class="dividing-line"></div>
|
<div class="dividing-line"></div>
|
||||||
@@ -54,10 +60,11 @@ import {
|
|||||||
drillDownPanelTypeMapping,
|
drillDownPanelTypeMapping,
|
||||||
entityType,
|
entityType,
|
||||||
entityDetailTags,
|
entityDetailTags,
|
||||||
psiphon3IpType,
|
tagValueLabelMapping,
|
||||||
riskLevelMapping
|
riskLevelMapping,
|
||||||
|
entityDefaultColor
|
||||||
} from '@/utils/constants'
|
} from '@/utils/constants'
|
||||||
import { selectElementText, copySelectionText } from '@/utils/tools'
|
import { selectElementText, copySelectionText, getTagColor } from '@/utils/tools'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import i18n from '@/i18n'
|
import i18n from '@/i18n'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
@@ -83,17 +90,34 @@ 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: {
|
||||||
tagValueHandler (k, k2, value) {
|
getTagColor,
|
||||||
if (k === 'psiphon3Ip') {
|
tagValueHandler (value) {
|
||||||
if (k2 === 'type') {
|
const find = tagValueLabelMapping.find(t => t.value === value)
|
||||||
const find = psiphon3IpType.find(t => t.value === value)
|
return find ? find.name : value
|
||||||
if (find) {
|
|
||||||
return find.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value
|
|
||||||
},
|
},
|
||||||
getData () {
|
getData () {
|
||||||
this.toggleLoading(true)
|
this.toggleLoading(true)
|
||||||
@@ -114,13 +138,13 @@ export default {
|
|||||||
Object.keys(res.data[k]).forEach(k2 => {
|
Object.keys(res.data[k]).forEach(k2 => {
|
||||||
const find = entityDetailTags[this.entity.entityType].find(t => t.name === k2)
|
const find = entityDetailTags[this.entity.entityType].find(t => t.name === k2)
|
||||||
if (find) {
|
if (find) {
|
||||||
this.levelTwoTags.push({ key: k2, value: this.tagValueHandler(k, k2, res.data[k][k2]), type: find.type })
|
this.levelTwoTags.push({ key: k2, value: this.tagValueHandler(res.data[k][k2]), type: find.type })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if (_.isArray(res.data.userDefinedTags)) {
|
if (_.isArray(res.data.userDefinedTags)) {
|
||||||
this.levelTwoTags = _.concat(this.levelTwoTags, res.data.userDefinedTags.map(tag => ({ value: tag.tagValue, type: 'normal' })))
|
this.levelTwoTags = _.concat(this.levelTwoTags, res.data.userDefinedTags.map(tag => ({ value: tag.tagValue, color: tag.knowledgeBase ? tag.knowledgeBase.color : entityDefaultColor })))
|
||||||
}
|
}
|
||||||
this.hideTagArea = _.isEmpty(this.levelTwoTags)
|
this.hideTagArea = _.isEmpty(this.levelTwoTags)
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
@@ -258,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
|
||||||
|
|||||||
@@ -50,7 +50,7 @@
|
|||||||
<el-select
|
<el-select
|
||||||
size="mini"
|
size="mini"
|
||||||
v-model="metric"
|
v-model="metric"
|
||||||
placeholder=""
|
placeholder=" "
|
||||||
popper-class="common-select"
|
popper-class="common-select"
|
||||||
:popper-append-to-body="false"
|
:popper-append-to-body="false"
|
||||||
@change="metricChange"
|
@change="metricChange"
|
||||||
@@ -66,6 +66,7 @@
|
|||||||
size="mini"
|
size="mini"
|
||||||
v-model="lineRefer"
|
v-model="lineRefer"
|
||||||
:disabled="!lineTab"
|
:disabled="!lineTab"
|
||||||
|
placeholder=" "
|
||||||
popper-class="common-select"
|
popper-class="common-select"
|
||||||
:popper-append-to-body="false"
|
:popper-append-to-body="false"
|
||||||
@change="referenceSelectChange"
|
@change="referenceSelectChange"
|
||||||
@@ -123,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 {
|
||||||
@@ -226,6 +227,9 @@ export default {
|
|||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
this.isNoData = res.data.result.length === 0
|
this.isNoData = res.data.result.length === 0
|
||||||
this.showError = false
|
this.showError = false
|
||||||
|
if (!active) {
|
||||||
|
this.tabs = _.cloneDeep(this.tabsTemplate)
|
||||||
|
}
|
||||||
if (this.isNoData) {
|
if (this.isNoData) {
|
||||||
this.lineTab = ''
|
this.lineTab = ''
|
||||||
this.tabs = _.cloneDeep(this.tabsTemplate)
|
this.tabs = _.cloneDeep(this.tabsTemplate)
|
||||||
@@ -497,7 +501,7 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data !== undefined && data.length > 0) {
|
if (data && data.length > 0) {
|
||||||
newData.forEach((item) => {
|
newData.forEach((item) => {
|
||||||
item.type = getLineType(item.type)
|
item.type = getLineType(item.type)
|
||||||
if (item.type === val) {
|
if (item.type === val) {
|
||||||
@@ -510,6 +514,24 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
lineData.splice(0, 1)
|
lineData.splice(0, 1)
|
||||||
|
// TODO 下面的逻辑是判断total曲线的尾部数据,从尾往前数0值的个数,若个数大于0,所有曲线都从尾部去掉相同数量的点,最多4个
|
||||||
|
const totalData = lineData[0]
|
||||||
|
if (_.get(totalData, 'values', []).length > 4) {
|
||||||
|
let count = 0
|
||||||
|
for (let i = totalData.values.length - 1; i >= totalData.values.length - 4; i--) {
|
||||||
|
if (totalData.values[i].length > 1 && totalData.values[i][1] === 0) {
|
||||||
|
count++
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (count > 0) {
|
||||||
|
lineData.forEach(l => {
|
||||||
|
l.values.splice(l.values.length - count, count)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (val === 'Sessions/s') {
|
if (val === 'Sessions/s') {
|
||||||
const tabs = _.cloneDeep(this.tabsTemplate)
|
const tabs = _.cloneDeep(this.tabsTemplate)
|
||||||
lineData.forEach((d, i) => {
|
lineData.forEach((d, i) => {
|
||||||
@@ -527,6 +549,7 @@ export default {
|
|||||||
})
|
})
|
||||||
this.tabs = tabs
|
this.tabs = tabs
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
|
this.lineRefer = 'Average'
|
||||||
this.echartsInit(this.tabs, true)
|
this.echartsInit(this.tabs, true)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@@ -544,7 +567,7 @@ export default {
|
|||||||
const self = this
|
const self = this
|
||||||
tabs.forEach(e => {
|
tabs.forEach(e => {
|
||||||
e.unitType = type
|
e.unitType = type
|
||||||
if (e.name !== 'network.total' && parseFloat(e.analysis.avg) === 0) {
|
if (e.name !== 'network.total' && parseFloat(e.analysis.max) === 0) {
|
||||||
e.show = false
|
e.show = false
|
||||||
num += 1
|
num += 1
|
||||||
} else {
|
} else {
|
||||||
@@ -554,13 +577,18 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (self.lineTab === e.class) {
|
if (self.lineTab === e.class) {
|
||||||
if (parseFloat(e.analysis.avg) <= 0) {
|
if (parseFloat(e.analysis.max) <= 0) {
|
||||||
self.lineTab = ''
|
self.lineTab = ''
|
||||||
self.lineRefer = ''
|
self.lineRefer = ''
|
||||||
self.init()
|
// self.init() // 后续多测试关注
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
const emptyData = tabs.filter(d => parseFloat(d.analysis.max) === 0)
|
||||||
|
this.isNoData = emptyData.length === tabs.length
|
||||||
|
if (this.isNoData) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
this.tabs = tabs
|
this.tabs = tabs
|
||||||
if (num === 5) {
|
if (num === 5) {
|
||||||
tabs[0].invertTab = false
|
tabs[0].invertTab = false
|
||||||
|
|||||||
@@ -15,11 +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" @checkTag="setTag"></behavior-pattern>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</div>
|
</div>
|
||||||
@@ -28,24 +29,27 @@
|
|||||||
<script>
|
<script>
|
||||||
import chartMixin from '@/views/charts2/chart-mixin'
|
import chartMixin from '@/views/charts2/chart-mixin'
|
||||||
import i18n from '@/i18n'
|
import i18n from '@/i18n'
|
||||||
import { entityDetailTabsName, entityDetailTags, psiphon3IpType } from '@/utils/constants'
|
import { entityDetailTabsName, entityDetailTags } from '@/utils/constants'
|
||||||
import { reactive, ref } from 'vue'
|
import { reactive, ref } from 'vue'
|
||||||
import InformationAggregation from '@/views/charts2/charts/entityDetail/tabs/InformationAggregation'
|
import InformationAggregation from '@/views/charts2/charts/entityDetail/tabs/InformationAggregation'
|
||||||
import DomainNameResolution from '@/views/charts2/charts/entityDetail/tabs/DomainNameResolution'
|
import DomainNameResolution from '@/views/charts2/charts/entityDetail/tabs/DomainNameResolution'
|
||||||
import SecurityEvent from '@/views/charts2/charts/entityDetail/tabs/SecurityEvent'
|
import SecurityEvent from '@/views/charts2/charts/entityDetail/tabs/SecurityEvent'
|
||||||
import PerformanceEvent from '@/views/charts2/charts/entityDetail/tabs/PerformanceEvent'
|
import PerformanceEvent from '@/views/charts2/charts/entityDetail/tabs/PerformanceEvent'
|
||||||
|
import BehaviorPattern from '@/views/charts2/charts/entityDetail/tabs/BehaviorPattern'
|
||||||
import OpenPort from '@/views/charts2/charts/entityDetail/tabs/OpenPort'
|
import OpenPort from '@/views/charts2/charts/entityDetail/tabs/OpenPort'
|
||||||
import DigitalCertificate from '@/views/charts2/charts/entityDetail/tabs/DigitalCertificate'
|
import DigitalCertificate from '@/views/charts2/charts/entityDetail/tabs/DigitalCertificate'
|
||||||
import { overwriteUrl, urlParamsHandler } from '@/utils/tools'
|
import { overwriteUrl, urlParamsHandler } from '@/utils/tools'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { api } from '@/utils/api'
|
import { api } from '@/utils/api'
|
||||||
|
import { tagValueLabelMapping } from '../../../../utils/constants'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'EntityDetailTabs',
|
name: 'EntityDetailTabs',
|
||||||
mixins: [chartMixin],
|
mixins: [chartMixin],
|
||||||
components: {
|
components: {
|
||||||
PerformanceEvent,
|
PerformanceEvent,
|
||||||
|
BehaviorPattern,
|
||||||
SecurityEvent,
|
SecurityEvent,
|
||||||
InformationAggregation,
|
InformationAggregation,
|
||||||
DomainNameResolution,
|
DomainNameResolution,
|
||||||
@@ -54,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: {
|
||||||
@@ -90,6 +89,9 @@ export default {
|
|||||||
if (entityType !== 'app') {
|
if (entityType !== 'app') {
|
||||||
tabs.unshift({ name: entityDetailTabsName.informationAggregation, label: i18n.global.t('entities.informationAggregation'), icon: 'cn-icon cn-icon-information-aggregation', tag: 0 })
|
tabs.unshift({ name: entityDetailTabsName.informationAggregation, label: i18n.global.t('entities.informationAggregation'), icon: 'cn-icon cn-icon-information-aggregation', tag: 0 })
|
||||||
}
|
}
|
||||||
|
if (entityType === 'ip') {
|
||||||
|
tabs.push({ name: entityDetailTabsName.behaviorPattern, label: i18n.global.t('entities.behaviorPattern'), icon: 'cn-icon cn-icon-behavior', tag: 0 })
|
||||||
|
}
|
||||||
const activeTab = ref(tabs[0].name)
|
const activeTab = ref(tabs[0].name)
|
||||||
|
|
||||||
const { query } = useRoute()
|
const { query } = useRoute()
|
||||||
@@ -107,22 +109,17 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
initData () {
|
initData () {
|
||||||
const params = {
|
|
||||||
resource: this.entity.entityName
|
|
||||||
// startTime: getSecond(this.oneDayTimeFilter.startTime),
|
|
||||||
// endTime: getSecond(this.oneDayTimeFilter.endTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
const url = this.getUrlByEntityType(this.entity.entityType)
|
const url = this.getUrlByEntityType(this.entity.entityType)
|
||||||
const informationAggregation = axios.get(`${api.entity.informationAggregation}/${this.entity.entityType}?resource=${this.entity.entityName}&pageSize=100&pageNo=1`, { params: params })
|
const informationAggregation = axios.get(`${api.entity.informationAggregation}/${this.entity.entityType}?resource=${this.entity.entityName}&pageSize=100&pageNo=1`, { params: this.getParamsByTabType(entityDetailTabsName.informationAggregation) })
|
||||||
const openPort = axios.get(url, { params: params })
|
const openPort = axios.get(url, { params: this.getParamsByTabType(entityDetailTabsName.openPort) })
|
||||||
// const security = axios.get(`${api.entity.security}/${this.entity.entityType}`, { params: params })
|
const security = axios.get(`${api.entity.security}/${this.entity.entityType}`, { params: this.getParamsByTabType(entityDetailTabsName.securityEvent) })
|
||||||
// const performance = axios.get(`${api.entity.performance}/${this.entityType}`, { params: params })
|
const performance = axios.get(`${api.entity.performance}/${this.entityType}`, { params: this.getParamsByTabType(entityDetailTabsName.performanceEvent) })
|
||||||
|
|
||||||
Promise.all([informationAggregation, openPort]).then(response => {
|
Promise.allSettled([informationAggregation, openPort, security, performance]).then(response => {
|
||||||
if (response[0].status === 200) {
|
const informationAggregationResponse = response[0].value
|
||||||
|
if (informationAggregationResponse.status === 200) {
|
||||||
const list = []
|
const list = []
|
||||||
response[0].data.data.result.forEach(r => {
|
informationAggregationResponse.data.data.result.forEach(r => {
|
||||||
Object.keys(r).forEach(k => {
|
Object.keys(r).forEach(k => {
|
||||||
const aggregation = {
|
const aggregation = {
|
||||||
createTime: r[k].createTime,
|
createTime: r[k].createTime,
|
||||||
@@ -136,7 +133,7 @@ export default {
|
|||||||
Object.keys(r[k]).forEach(k2 => {
|
Object.keys(r[k]).forEach(k2 => {
|
||||||
const find = entityDetailTags[this.entity.entityType].find(t => t.name === k2)
|
const find = entityDetailTags[this.entity.entityType].find(t => t.name === k2)
|
||||||
if (find) {
|
if (find) {
|
||||||
aggregation.intelligenceContent.push({ key: k2, value: this.tagValueHandler(k, k2, r[k][k2]), type: find.type })
|
aggregation.intelligenceContent.push({ key: k2, value: this.tagValueHandler(r[k][k2]), type: find.type })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -145,39 +142,42 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
this.initSetTag(entityDetailTabsName.informationAggregation, list.length)
|
this.initSetTag(entityDetailTabsName.informationAggregation, list.length)
|
||||||
}
|
}
|
||||||
if (response[1].status === 200) {
|
const openPortResponse = response[1].value
|
||||||
this.initSetTag(entityDetailTabsName.openPort, response[1].data.data.result.length)
|
if (openPortResponse.status === 200) {
|
||||||
|
this.initSetTag(entityDetailTabsName.openPort, openPortResponse.data.data.result.length)
|
||||||
}
|
}
|
||||||
// if (response[2].status === 200) {
|
const securityResponse = response[2].value
|
||||||
// this.initSetTag(entityDetailTabsName.securityEvent, response[2].data.data.result.length)
|
if (securityResponse.status === 200) {
|
||||||
|
this.initSetTag(entityDetailTabsName.securityEvent, securityResponse.data.data.result.length)
|
||||||
|
}
|
||||||
|
// let performanceResponse = response[3].value
|
||||||
|
// if (performanceResponse.status === 200) {
|
||||||
|
// this.initSetTag(entityDetailTabsName.performanceEvent, performanceResponse.data.data.result.length)
|
||||||
// }
|
// }
|
||||||
// if (response[3].status === 200) {
|
|
||||||
// this.initSetTag(entityDetailTabsName.performanceEvent, response[3].data.data.result.length)
|
|
||||||
// }
|
|
||||||
this.initSetTag(entityDetailTabsName.securityEvent, 0)
|
|
||||||
this.initSetTag(entityDetailTabsName.performanceEvent, 0)
|
this.initSetTag(entityDetailTabsName.performanceEvent, 0)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const relatedEntityParams = this.getParamsByTabType(entityDetailTabsName.relatedEntity)
|
||||||
// 域名解析
|
// 域名解析
|
||||||
if (this.entity.entityType === 'app') {
|
if (this.entity.entityType === 'app') {
|
||||||
const ipsOfApp = axios.get(api.entity.domainNameResolutionAboutIpsOfApp, { params: params })
|
const ipsOfApp = axios.get(api.entity.domainNameResolutionAboutIpsOfApp, { params: relatedEntityParams })
|
||||||
const domainsOfApp = axios.get(api.entity.domainNameResolutionAboutDomainsOfApp, { params: params })
|
const domainsOfApp = axios.get(api.entity.domainNameResolutionAboutDomainsOfApp, { params: relatedEntityParams })
|
||||||
this.promiseData(ipsOfApp, domainsOfApp)
|
this.promiseData(ipsOfApp, domainsOfApp)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.entity.entityType === 'ip') {
|
if (this.entity.entityType === 'ip') {
|
||||||
const appsOfIp = axios.get(api.entity.domainNameResolutionAboutAppsOfIp, { params: params })
|
const appsOfIp = axios.get(api.entity.domainNameResolutionAboutAppsOfIp, { params: relatedEntityParams })
|
||||||
const domainsOfIp = axios.get(api.entity.domainNameResolutionAboutDomainsOfIp, { params: params })
|
const domainsOfIp = axios.get(api.entity.domainNameResolutionAboutDomainsOfIp, { params: relatedEntityParams })
|
||||||
this.promiseData(appsOfIp, domainsOfIp)
|
const behaviorPattern = axios.get(api.entity.behaviorPattern, { params: relatedEntityParams })
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -191,6 +191,18 @@ export default {
|
|||||||
const len1 = res[0].status === 200 ? res0.data.result.length : 0
|
const len1 = res[0].status === 200 ? res0.data.result.length : 0
|
||||||
const len2 = res[1].status === 200 ? res1.data.result.length : 0
|
const len2 = res[1].status === 200 ? res1.data.result.length : 0
|
||||||
this.initSetTag(entityDetailTabsName.relatedEntity, len1 + len2)
|
this.initSetTag(entityDetailTabsName.relatedEntity, len1 + len2)
|
||||||
|
const behaviorPatternData = res[2].status === 200 ? res[2].data.data.result : 0
|
||||||
|
let behaviorPatternLen = 0
|
||||||
|
if (behaviorPatternData && behaviorPatternData[0]) {
|
||||||
|
const dataObject = behaviorPatternData[0]
|
||||||
|
Object.keys(dataObject).forEach(key => {
|
||||||
|
const value = Number(dataObject[key]) ? Number(dataObject[key]) : 0
|
||||||
|
if (value !== 0) {
|
||||||
|
behaviorPatternLen++
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.initSetTag(entityDetailTabsName.behaviorPattern, behaviorPatternLen)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'domain': {
|
case 'domain': {
|
||||||
@@ -251,16 +263,9 @@ export default {
|
|||||||
case 'app': return api.entity.openPortOfApp
|
case 'app': return api.entity.openPortOfApp
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
tagValueHandler (k, k2, value) {
|
tagValueHandler (value) {
|
||||||
if (k === 'psiphon3Ip') {
|
const find = tagValueLabelMapping.find(t => t.value === value)
|
||||||
if (k2 === 'type') {
|
return find ? find.name : value
|
||||||
const find = psiphon3IpType.find(t => t.value === value)
|
|
||||||
if (find) {
|
|
||||||
return find.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeUnmount () {
|
beforeUnmount () {
|
||||||
|
|||||||
190
src/views/charts2/charts/entityDetail/tabs/BehaviorPattern.vue
Normal file
190
src/views/charts2/charts/entityDetail/tabs/BehaviorPattern.vue
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
<template>
|
||||||
|
<chart-error v-if="showError" :content="errorMsg" class="entity-detail-event-error"></chart-error>
|
||||||
|
<chart-no-data v-if="isNoData && !showError"></chart-no-data>
|
||||||
|
|
||||||
|
<div v-if="!isNoData && !showError" class="entity-detail-event-block" style="height: 100%;width: 100%;position: relative;">
|
||||||
|
<div class="behavior-pattern" >
|
||||||
|
<div class="behavior-pattern-legend" >
|
||||||
|
<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-name">{{data.name}}</div>
|
||||||
|
<div class="legend-value" >{{ valueToRangeValue(data.value, unitTypes.number).join('')}}</div>
|
||||||
|
<div class="legend-percent">{{ valueToRangeValue(data.percent, unitTypes.percent).join('') }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="entityIpRoseType" class="behavior-pattern-chart"></div>
|
||||||
|
<div class="chart-bottom-dot__right"></div>
|
||||||
|
<div class="chart-bottom-dot__left"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { dateFormatByAppearance, getNowTime } from '@/utils/date-util'
|
||||||
|
import * as echarts from 'echarts'
|
||||||
|
import { pieChartOption4 } from '@/views/charts2/charts/options/echartOption'
|
||||||
|
import { shallowRef, ref } from 'vue'
|
||||||
|
import { entityDetailTabsName, chartColorForBehaviorPattern, unitTypes } from '@/utils/constants'
|
||||||
|
import { valueToRangeValue } from '@/utils/unit-convert'
|
||||||
|
import axios from 'axios'
|
||||||
|
import { api } from '@/utils/api'
|
||||||
|
import { useRoute } from 'vue-router'
|
||||||
|
import chartMixin from '@/views/charts2/chart-mixin'
|
||||||
|
import ChartError from '@/components/common/Error'
|
||||||
|
import { toUpperCaseByString, reverseSortBy } from '@/utils/tools'
|
||||||
|
import ChartNoData from '@/views/charts/charts/ChartNoData'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'BehaviorPattern',
|
||||||
|
components: { ChartError, ChartNoData },
|
||||||
|
mixins: [chartMixin],
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
showError: false,
|
||||||
|
errorMsg: '',
|
||||||
|
tableData: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setup () {
|
||||||
|
const { query } = useRoute()
|
||||||
|
const entityType = query.entityType
|
||||||
|
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 {
|
||||||
|
entityType,
|
||||||
|
entityName,
|
||||||
|
myChart: shallowRef(null),
|
||||||
|
chartColorForBehaviorPattern,
|
||||||
|
unitTypes,
|
||||||
|
timeFilter
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async mounted () {
|
||||||
|
await this.initData()
|
||||||
|
this.toggleLoading(true)
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
this.toggleLoading(false)
|
||||||
|
clearInterval(timer)
|
||||||
|
}, 200)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
valueToRangeValue,
|
||||||
|
toUpperCaseByString,
|
||||||
|
dateFormatByAppearance,
|
||||||
|
initEcharts () {
|
||||||
|
this.chartOption = pieChartOption4
|
||||||
|
this.chartOption.angleAxis.data = []
|
||||||
|
this.chartOption.series[0].data = []
|
||||||
|
this.tableData.forEach((item, index) => {
|
||||||
|
this.chartOption.angleAxis.data.push(item.name)
|
||||||
|
this.chartOption.series[0].data.push(item.value)
|
||||||
|
})
|
||||||
|
const len = this.tableData.length
|
||||||
|
const endIndex = len + 1
|
||||||
|
this.tableData.forEach((item, i) => {
|
||||||
|
if (i !== endIndex) {
|
||||||
|
this.chartOption.angleAxis.data.push(item.name + '2')
|
||||||
|
this.chartOption.series[0].data.push(0)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const axisLabel = this.chartOption.angleAxis.axisLabel
|
||||||
|
this.chartOption.angleAxis.axisLabel = {
|
||||||
|
...axisLabel,
|
||||||
|
formatter: function (params, index) {
|
||||||
|
if (len > 15) {
|
||||||
|
if (index === 7) {
|
||||||
|
return params + '\n'
|
||||||
|
} else if (index === 8) {
|
||||||
|
return '\n' + params
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (index === endIndex) {
|
||||||
|
return params + '\n'
|
||||||
|
} else {
|
||||||
|
return params
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const self = this
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (self.myChart) {
|
||||||
|
self.myChart.dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
const dom = document.getElementById('entityIpRoseType')
|
||||||
|
if (dom) {
|
||||||
|
self.myChart = echarts.init(dom)
|
||||||
|
self.myChart.setOption(this.chartOption)
|
||||||
|
|
||||||
|
self.myChart.dispatchAction({
|
||||||
|
type: 'takeGlobalCursor',
|
||||||
|
key: 'brush',
|
||||||
|
brushOption: {
|
||||||
|
brushType: 'lineX',
|
||||||
|
xAxisIndex: 'all',
|
||||||
|
brushMode: 'single',
|
||||||
|
throttleType: 'debounce'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async initData () {
|
||||||
|
const params = this.getParams()
|
||||||
|
this.toggleLoading(true)
|
||||||
|
await axios.get(`${api.entity.behaviorPattern}`, { params: params }).then(response => {
|
||||||
|
const res = response.data
|
||||||
|
|
||||||
|
if (response.status === 200) {
|
||||||
|
this.isNoData = res.data.result.length === 0
|
||||||
|
|
||||||
|
this.showError = false
|
||||||
|
if (!this.isNoData) {
|
||||||
|
const data = res.data.result
|
||||||
|
this.tableData = []
|
||||||
|
if (data && data[0]) {
|
||||||
|
const dataObject = data[0]
|
||||||
|
Object.keys(dataObject).forEach(key => {
|
||||||
|
const value = Number(dataObject[key]) ? Number(dataObject[key]) : 0
|
||||||
|
if (value !== 0 && key !== 'total') {
|
||||||
|
this.tableData.push({
|
||||||
|
name: key,
|
||||||
|
value: value,
|
||||||
|
percent: dataObject.total ? value / dataObject.total : '-'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.tableData = this.tableData.sort(reverseSortBy('value'))
|
||||||
|
this.$emit('checkTag', entityDetailTabsName.behaviorPattern, this.tableData.length)
|
||||||
|
if (this.tableData.length === 0) {
|
||||||
|
this.isNoData = true
|
||||||
|
}
|
||||||
|
this.initEcharts()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.httpError(res)
|
||||||
|
}
|
||||||
|
}).catch(e => {
|
||||||
|
console.error(e)
|
||||||
|
this.httpError(e)
|
||||||
|
}).finally(() => {
|
||||||
|
this.toggleLoading(false)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
httpError (e) {
|
||||||
|
this.isNoData = false
|
||||||
|
this.showError = true
|
||||||
|
this.errorMsg = this.errorMsgHandler(e)
|
||||||
|
this.$emit('checkTag', entityDetailTabsName.behaviorPattern, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -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 })
|
||||||
|
|||||||
@@ -71,9 +71,10 @@
|
|||||||
import chartMixin from '@/views/charts2/chart-mixin'
|
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, psiphon3IpType } 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: {
|
||||||
@@ -95,7 +108,7 @@ export default {
|
|||||||
tagValueHandler (k, k2, value) {
|
tagValueHandler (k, k2, value) {
|
||||||
if (k === 'psiphon3Ip') {
|
if (k === 'psiphon3Ip') {
|
||||||
if (k2 === 'type') {
|
if (k2 === 'type') {
|
||||||
const find = psiphon3IpType.find(t => t.value === value)
|
const find = tagValueLabelMapping.find(t => t.value === value)
|
||||||
if (find) {
|
if (find) {
|
||||||
return find.name
|
return find.name
|
||||||
}
|
}
|
||||||
@@ -108,7 +121,12 @@ export default {
|
|||||||
this.showError = false
|
this.showError = false
|
||||||
this.toggleLoading(true)
|
this.toggleLoading(true)
|
||||||
this.informationAggregationList = []
|
this.informationAggregationList = []
|
||||||
axios.get(`${api.entity.informationAggregation}/${this.entity.entityType}?resource=${this.entity.entityName}&pageSize=100&pageNo=1`).then(response => {
|
const params = this.getParams()
|
||||||
|
let timeStr = ''
|
||||||
|
if (params.startTime && params.endTime) {
|
||||||
|
timeStr = '&startTime=' + params.startTime + '&endTime=' + params.endTime
|
||||||
|
}
|
||||||
|
axios.get(`${api.entity.informationAggregation}/${this.entity.entityType}?resource=${this.entity.entityName}&pageSize=100&pageNo=1${timeStr}`).then(response => {
|
||||||
const res = response.data
|
const res = response.data
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
// this.isNoData = res.data.result.length === 0
|
// this.isNoData = res.data.result.length === 0
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<div class="type-data">
|
<div class="type-data">
|
||||||
<div class="type-title">
|
<div class="type-title">
|
||||||
<span class="title-mark"></span>
|
<span class="title-mark"></span>
|
||||||
<span class="type-title-word">{{ $t('entities.tab.currentDevelopmentPortsAndServices') }}</span>({{ openPortList.length }})
|
<span class="type-title-word">{{ $t('entities.tab.currentOpenPortsAndServices') }}</span>({{ openPortList.length }})
|
||||||
</div>
|
</div>
|
||||||
<div class="type-content">
|
<div class="type-content">
|
||||||
<div v-for="(openPort, index) in openPortList.slice(0,showOpenPortListInfo.num)" :key="index" class="data-item">
|
<div v-for="(openPort, index) in openPortList.slice(0,showOpenPortListInfo.num)" :key="index" class="data-item">
|
||||||
@@ -27,6 +27,8 @@ import chartMixin from '@/views/charts2/chart-mixin'
|
|||||||
import { api } from '@/utils/api'
|
import { api } from '@/utils/api'
|
||||||
import chartNoData from '@/views/charts/charts/ChartNoData'
|
import chartNoData from '@/views/charts/charts/ChartNoData'
|
||||||
import { entityDetailTabsName } from '@/utils/constants'
|
import { entityDetailTabsName } from '@/utils/constants'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { getNowTime } from '@/utils/date-util'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'OpenPort',
|
name: 'OpenPort',
|
||||||
@@ -50,16 +52,21 @@ export default {
|
|||||||
mounted () {
|
mounted () {
|
||||||
this.initData()
|
this.initData()
|
||||||
},
|
},
|
||||||
setup () {
|
setup (props) {
|
||||||
|
// range取 config.js 中配置的值
|
||||||
|
const dateRangeValue = DEFAULT_TIME_FILTER_RANGE.entity.openPort
|
||||||
|
const timeFilter = ref({ dateRangeValue })
|
||||||
|
const { startTime, endTime } = getNowTime(dateRangeValue)
|
||||||
|
timeFilter.value.startTime = startTime
|
||||||
|
timeFilter.value.endTime = endTime
|
||||||
|
|
||||||
|
return {
|
||||||
|
timeFilter
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
initData () {
|
initData () {
|
||||||
const params = {
|
const params = this.getParams()
|
||||||
resource: this.entity.entityName
|
|
||||||
// startTime: getSecond(this.timeFilter.startTime),
|
|
||||||
// endTime: getSecond(this.timeFilter.endTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.toggleLoading(true)
|
this.toggleLoading(true)
|
||||||
const url = this.getUrlByEntityType(this.entity.entityType)
|
const url = this.getUrlByEntityType(this.entity.entityType)
|
||||||
axios.get(url, { params: params }).then(response => {
|
axios.get(url, { params: params }).then(response => {
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
<div class="basic-info__item" v-if="item.eventSeverity">
|
<div class="basic-info__item" v-if="item.eventSeverity">
|
||||||
<i class="cn-icon cn-icon-severity-level"></i>
|
<i class="cn-icon cn-icon-severity-level"></i>
|
||||||
<span>{{ $t('network.severity') }} : </span>
|
<span>{{ $t('network.severity') }} : </span>
|
||||||
<span :test-id="`severity${index}`">{{ toUpperCaseByString(item.eventSeverity) || '-' }}</span>
|
<span :test-id="`severity${index}`">{{ changeSecurity(item.eventSeverity) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="basic-info__item">
|
<div class="basic-info__item">
|
||||||
<i class="cn-icon cn-icon-time2"></i>
|
<i class="cn-icon cn-icon-time2"></i>
|
||||||
@@ -50,8 +50,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { dateFormatByAppearance } from '@/utils/date-util'
|
import { dateFormatByAppearance, getNowTime } from '@/utils/date-util'
|
||||||
import { eventSeverityColor, entityDetailTabsName } from '@/utils/constants'
|
import { eventSeverityColor, entityDetailTabsName, securityLevel } from '@/utils/constants'
|
||||||
import unitConvert from '@/utils/unit-convert'
|
import unitConvert from '@/utils/unit-convert'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { api } from '@/utils/api'
|
import { api } from '@/utils/api'
|
||||||
@@ -60,6 +60,7 @@ import chartMixin from '@/views/charts2/chart-mixin'
|
|||||||
import ChartError from '@/components/common/Error'
|
import ChartError from '@/components/common/Error'
|
||||||
import { toUpperCaseByString } from '@/utils/tools'
|
import { toUpperCaseByString } from '@/utils/tools'
|
||||||
import ChartNoData from '@/views/charts/charts/ChartNoData'
|
import ChartNoData from '@/views/charts/charts/ChartNoData'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PerformanceEvent',
|
name: 'PerformanceEvent',
|
||||||
@@ -77,33 +78,36 @@ export default {
|
|||||||
const { query } = useRoute()
|
const { query } = useRoute()
|
||||||
const entityType = query.entityType
|
const entityType = query.entityType
|
||||||
const entityName = query.entityName
|
const entityName = query.entityName
|
||||||
|
// range取 config.js 中配置的值
|
||||||
|
const dateRangeValue = DEFAULT_TIME_FILTER_RANGE.entity.performanceEvent
|
||||||
|
const timeFilter = ref({ dateRangeValue })
|
||||||
|
const { startTime, endTime } = getNowTime(dateRangeValue)
|
||||||
|
timeFilter.value.startTime = startTime
|
||||||
|
timeFilter.value.endTime = endTime
|
||||||
|
|
||||||
return {
|
return {
|
||||||
entityType,
|
entityType,
|
||||||
entityName
|
entityName,
|
||||||
|
timeFilter
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
// this.initData()
|
this.initData()
|
||||||
|
/*
|
||||||
this.isNoData = true
|
this.isNoData = true
|
||||||
this.$emit('checkTag', entityDetailTabsName.performanceEvent, 0)
|
this.$emit('checkTag', entityDetailTabsName.performanceEvent, 0)
|
||||||
this.toggleLoading(true)
|
this.toggleLoading(true)
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
this.toggleLoading(false)
|
this.toggleLoading(false)
|
||||||
clearInterval(timer)
|
clearInterval(timer)
|
||||||
}, 200)
|
}, 200) */
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
unitConvert,
|
unitConvert,
|
||||||
toUpperCaseByString,
|
toUpperCaseByString,
|
||||||
dateFormatByAppearance,
|
dateFormatByAppearance,
|
||||||
initData () {
|
initData () {
|
||||||
const params = {
|
const params = this.getParams()
|
||||||
resource: this.entityName
|
|
||||||
// startTime: getSecond(this.timeFilter.startTime),
|
|
||||||
// endTime: getSecond(this.timeFilter.endTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.toggleLoading(true)
|
this.toggleLoading(true)
|
||||||
axios.get(`${api.entity.performance}/${this.entityType}`, { params: params }).then(response => {
|
axios.get(`${api.entity.performance}/${this.entityType}`, { params: params }).then(response => {
|
||||||
const res = response.data
|
const res = response.data
|
||||||
@@ -130,6 +134,18 @@ export default {
|
|||||||
this.showError = true
|
this.showError = true
|
||||||
this.errorMsg = this.errorMsgHandler(e)
|
this.errorMsg = this.errorMsgHandler(e)
|
||||||
this.$emit('checkTag', entityDetailTabsName.performanceEvent, 0)
|
this.$emit('checkTag', entityDetailTabsName.performanceEvent, 0)
|
||||||
|
},
|
||||||
|
changeSecurity (value) {
|
||||||
|
if (value) {
|
||||||
|
const obj = securityLevel.find(d => d.value === value)
|
||||||
|
let label = value
|
||||||
|
if (obj) {
|
||||||
|
label = this.$t(obj.label)
|
||||||
|
}
|
||||||
|
return label
|
||||||
|
} else {
|
||||||
|
return '-'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
:key="item.eventId">
|
:key="item.eventId">
|
||||||
<div class="cn-detection--list">
|
<div class="cn-detection--list">
|
||||||
<div class="cn-detection__case entity-detail-security">
|
<div class="cn-detection__case entity-detail-security">
|
||||||
<div class="cn-detection__icon" :style="`background-color: ${eventSeverityColor[item.eventSecurity]}`"></div>
|
<div class="cn-detection__icon"></div>
|
||||||
<div class="cn-detection__row">
|
<div class="cn-detection__row">
|
||||||
<div class="cn-detection__header">
|
<div class="cn-detection__header">
|
||||||
<span
|
<span
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
class="detection-event-severity-color-block"
|
class="detection-event-severity-color-block"
|
||||||
:style="`background-color: ${eventSeverityColor[item.eventSeverity]}`">
|
:style="`background-color: ${eventSeverityColor[item.eventSeverity]}`">
|
||||||
</span>
|
</span>
|
||||||
<span class="detection-event-severity-block">{{ toUpperCaseByString(item.securityType) || '-' }}</span>
|
<span class="detection-event-severity-block">{{ item.eventName || '-' }}</span>
|
||||||
<i class="cn-icon cn-icon-attacker"></i>
|
<i class="cn-icon cn-icon-attacker"></i>
|
||||||
<span :test-id="`offender-ip${index}`">{{ item.offenderIp || '-' }}</span>
|
<span :test-id="`offender-ip${index}`">{{ item.offenderIp || '-' }}</span>
|
||||||
<div class="domain">{{ item.offenderDomain }}</div>
|
<div class="domain">{{ item.offenderDomain }}</div>
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
<div class="basic-info__item" v-if="item.eventSeverity">
|
<div class="basic-info__item" v-if="item.eventSeverity">
|
||||||
<i class="cn-icon cn-icon-severity-level"></i>
|
<i class="cn-icon cn-icon-severity-level"></i>
|
||||||
<span>{{ $t('network.severity') }} : </span>
|
<span>{{ $t('network.severity') }} : </span>
|
||||||
<span>{{ toUpperCaseByString(item.eventSeverity) || '-' }}</span>
|
<span>{{ changeSecurity(item.eventSeverity) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="basic-info__item" v-if="item.eventType">
|
<div class="basic-info__item" v-if="item.eventType">
|
||||||
<i class="cn-icon cn-icon-event-type"></i>
|
<i class="cn-icon cn-icon-event-type"></i>
|
||||||
@@ -76,8 +76,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { dateFormatByAppearance } from '@/utils/date-util'
|
import { dateFormatByAppearance, getNowTime } from '@/utils/date-util'
|
||||||
import { eventSeverityColor, entityDetailTabsName } from '@/utils/constants'
|
import { eventSeverityColor, entityDetailTabsName, securityLevel } from '@/utils/constants'
|
||||||
import unitConvert from '@/utils/unit-convert'
|
import unitConvert from '@/utils/unit-convert'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { api } from '@/utils/api'
|
import { api } from '@/utils/api'
|
||||||
@@ -85,6 +85,7 @@ import { useRoute } from 'vue-router'
|
|||||||
import chartMixin from '@/views/charts2/chart-mixin'
|
import chartMixin from '@/views/charts2/chart-mixin'
|
||||||
import { toUpperCaseByString } from '@/utils/tools'
|
import { toUpperCaseByString } from '@/utils/tools'
|
||||||
import chartNoData from '@/views/charts/charts/ChartNoData'
|
import chartNoData from '@/views/charts/charts/ChartNoData'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'SecurityEvent',
|
name: 'SecurityEvent',
|
||||||
@@ -102,33 +103,36 @@ export default {
|
|||||||
const { query } = useRoute()
|
const { query } = useRoute()
|
||||||
const entityType = query.entityType
|
const entityType = query.entityType
|
||||||
const entityName = query.entityName
|
const entityName = query.entityName
|
||||||
|
// range取 config.js 中配置的值
|
||||||
|
const dateRangeValue = DEFAULT_TIME_FILTER_RANGE.entity.securityEvent
|
||||||
|
const timeFilter = ref({ dateRangeValue })
|
||||||
|
const { startTime, endTime } = getNowTime(dateRangeValue)
|
||||||
|
timeFilter.value.startTime = startTime
|
||||||
|
timeFilter.value.endTime = endTime
|
||||||
|
|
||||||
return {
|
return {
|
||||||
entityType,
|
entityType,
|
||||||
entityName
|
entityName,
|
||||||
|
timeFilter
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
// this.initData()
|
this.initData()
|
||||||
|
/*
|
||||||
this.isNoData = true
|
this.isNoData = true
|
||||||
this.$emit('checkTag', entityDetailTabsName.securityEvent, 0)
|
this.$emit('checkTag', entityDetailTabsName.securityEvent, 0)
|
||||||
this.toggleLoading(true)
|
this.toggleLoading(true)
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
this.toggleLoading(false)
|
this.toggleLoading(false)
|
||||||
clearInterval(timer)
|
clearInterval(timer)
|
||||||
}, 200)
|
}, 200) */
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
unitConvert,
|
unitConvert,
|
||||||
toUpperCaseByString,
|
toUpperCaseByString,
|
||||||
dateFormatByAppearance,
|
dateFormatByAppearance,
|
||||||
initData () {
|
initData () {
|
||||||
const params = {
|
const params = this.getParams()
|
||||||
resource: this.entityName
|
|
||||||
// startTime: getSecond(this.timeFilter.startTime),
|
|
||||||
// endTime: getSecond(this.timeFilter.endTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.toggleLoading(true)
|
this.toggleLoading(true)
|
||||||
axios.get(`${api.entity.security}/${this.entityType}`, { params: params }).then(response => {
|
axios.get(`${api.entity.security}/${this.entityType}`, { params: params }).then(response => {
|
||||||
const res = response.data
|
const res = response.data
|
||||||
@@ -155,6 +159,18 @@ export default {
|
|||||||
this.isNoData = false
|
this.isNoData = false
|
||||||
this.showError = true
|
this.showError = true
|
||||||
this.errorMsg = this.errorMsgHandler(e)
|
this.errorMsg = this.errorMsgHandler(e)
|
||||||
|
},
|
||||||
|
changeSecurity (value) {
|
||||||
|
if (value) {
|
||||||
|
const obj = securityLevel.find(d => d.value === value)
|
||||||
|
let label = value
|
||||||
|
if (obj) {
|
||||||
|
label = this.$t(obj.label)
|
||||||
|
}
|
||||||
|
return label
|
||||||
|
} else {
|
||||||
|
return '-'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -355,12 +355,12 @@ export default {
|
|||||||
if (out < 0.0001 && out !== 0) {
|
if (out < 0.0001 && out !== 0) {
|
||||||
outUsage = '< 0.01%'
|
outUsage = '< 0.01%'
|
||||||
} else {
|
} else {
|
||||||
outUsage = JSON.stringify(parseFloat((out * 100).toFixed(2)))
|
outUsage = JSON.stringify(parseFloat(out * 100).toFixed(2))
|
||||||
}
|
}
|
||||||
if (_in < 0.0001 && _in !== 0) {
|
if (_in < 0.0001 && _in !== 0) {
|
||||||
inUsage = '< 0.01%'
|
inUsage = '< 0.01%'
|
||||||
} else {
|
} else {
|
||||||
inUsage = JSON.stringify(parseFloat((_in * 100).toFixed(2)))
|
inUsage = JSON.stringify(parseFloat(_in * 100).toFixed(2))
|
||||||
}
|
}
|
||||||
|
|
||||||
length = outUsage.length + inUsage.length
|
length = outUsage.length + inUsage.length
|
||||||
|
|||||||
@@ -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'
|
||||||
@@ -30,7 +30,8 @@ export default {
|
|||||||
isLinkShowError: false, // 显示左侧链路报错标识
|
isLinkShowError: false, // 显示左侧链路报错标识
|
||||||
linkErrorMsg: '', // 左侧链路的报错信息
|
linkErrorMsg: '', // 左侧链路的报错信息
|
||||||
isNextShowError: false, // 显示右侧下一跳报错标识
|
isNextShowError: false, // 显示右侧下一跳报错标识
|
||||||
nextErrorMsg: '' // 右侧下一跳的报错信息
|
nextErrorMsg: '', // 右侧下一跳的报错信息
|
||||||
|
scoreDataState: false // 评分数据是否加载完成
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
@@ -41,6 +42,23 @@ export default {
|
|||||||
handler () {
|
handler () {
|
||||||
this.init()
|
this.init()
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
scoreBaseState (n) {
|
||||||
|
if (n && this.scoreDataState) {
|
||||||
|
this.handleScoreData(this.linkGridData)
|
||||||
|
this.handleScoreData(this.nextGridData)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
scoreDataState (n) {
|
||||||
|
if (n && this.scoreBaseState) {
|
||||||
|
this.handleScoreData(this.linkGridData)
|
||||||
|
this.handleScoreData(this.nextGridData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
scoreBaseState () {
|
||||||
|
return this.$store.getters.scoreBaseReady
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
@@ -48,6 +66,7 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
init () {
|
init () {
|
||||||
|
this.scoreDataState = false
|
||||||
// 链路基本信息
|
// 链路基本信息
|
||||||
let linkInfo = localStorage.getItem(storageKey.linkInfo)
|
let linkInfo = localStorage.getItem(storageKey.linkInfo)
|
||||||
linkInfo = JSON.parse(linkInfo)
|
linkInfo = JSON.parse(linkInfo)
|
||||||
@@ -117,9 +136,9 @@ export default {
|
|||||||
d.usageMore90 = outUsage >= 0.9 || inUsage >= 0.9
|
d.usageMore90 = outUsage >= 0.9 || inUsage >= 0.9
|
||||||
// 计算npm分数
|
// 计算npm分数
|
||||||
// 分数低于3分,赋红点
|
// 分数低于3分,赋红点
|
||||||
d.score = this.localComputeScore(d)
|
// d.score = this.localComputeScore(d)
|
||||||
|
|
||||||
d.scoreLow3 = d.score < 3 || d.score === '-'
|
// d.scoreLow3 = d.score < 3 || d.score === '-'
|
||||||
|
|
||||||
const xAxis = inLink.linkId.split('Hundredgige').pop() - 1
|
const xAxis = inLink.linkId.split('Hundredgige').pop() - 1
|
||||||
const yAxis = outLink.linkId.split('Hundredgige').pop() - 1
|
const yAxis = outLink.linkId.split('Hundredgige').pop() - 1
|
||||||
@@ -137,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
|
||||||
}
|
}
|
||||||
@@ -159,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
|
||||||
@@ -210,9 +227,9 @@ export default {
|
|||||||
d.usageMore90 = outUsage >= 0.9 || inUsage >= 0.9
|
d.usageMore90 = outUsage >= 0.9 || inUsage >= 0.9
|
||||||
// 计算npm分数
|
// 计算npm分数
|
||||||
// 分数低于3分,赋红点
|
// 分数低于3分,赋红点
|
||||||
d.score = this.localComputeScore(d)
|
// d.score = this.localComputeScore(d)
|
||||||
|
|
||||||
d.scoreLow3 = d.score < 3 || d.score === '-'
|
// d.scoreLow3 = d.score < 3 || d.score === '-'
|
||||||
|
|
||||||
const xAxis = inLink.linkId
|
const xAxis = inLink.linkId
|
||||||
const yAxis = outLink.linkId
|
const yAxis = outLink.linkId
|
||||||
@@ -238,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
|
||||||
@@ -254,6 +269,7 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
|
this.scoreDataState = true
|
||||||
this.toggleLoading(false)
|
this.toggleLoading(false)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -282,6 +298,23 @@ export default {
|
|||||||
score = computeScore(dataScore)
|
score = computeScore(dataScore)
|
||||||
return score
|
return score
|
||||||
},
|
},
|
||||||
|
handleScoreData (data) {
|
||||||
|
data.forEach(d => {
|
||||||
|
if (d.out) {
|
||||||
|
d.out.forEach(t => {
|
||||||
|
const data = {
|
||||||
|
establishLatencyMs: t.establishLatencyMs,
|
||||||
|
httpResponseLatency: t.httpResponseLatency,
|
||||||
|
sslConLatency: t.sslConLatency,
|
||||||
|
tcpLostlenPercent: t.tcpLostlenPercent,
|
||||||
|
pktRetransPercent: t.pktRetransPercent
|
||||||
|
}
|
||||||
|
t.score = computeScore(data, this.$store.getters.getScoreBase)
|
||||||
|
t.scoreLow3 = t.score < 3 || t.score === '-'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* 计算popover弹窗和右侧数据模块的宽度
|
* 计算popover弹窗和右侧数据模块的宽度
|
||||||
* 弹窗最小宽度为360px,右侧数据最小宽度为75px,右侧数据每大一位,popover弹窗宽度增加7px
|
* 弹窗最小宽度为360px,右侧数据最小宽度为75px,右侧数据每大一位,popover弹窗宽度增加7px
|
||||||
@@ -320,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) {
|
||||||
@@ -343,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,11 +37,12 @@
|
|||||||
</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"
|
||||||
v-model="lineMetric"
|
v-model="lineMetric"
|
||||||
|
placeholder=" "
|
||||||
popper-class="common-select"
|
popper-class="common-select"
|
||||||
:popper-append-to-body="false"
|
:popper-append-to-body="false"
|
||||||
@change="metricSelectChange"
|
@change="metricSelectChange"
|
||||||
@@ -156,7 +157,7 @@ export default {
|
|||||||
endTime: getSecond(this.timeFilter.endTime)
|
endTime: getSecond(this.timeFilter.endTime)
|
||||||
}
|
}
|
||||||
if (this.queryCondition) {
|
if (this.queryCondition) {
|
||||||
const condition = this.queryCondition.toLowerCase().split(' or ')
|
const condition = this.queryCondition.split(' or ')
|
||||||
if (condition.length > 1) {
|
if (condition.length > 1) {
|
||||||
params.outParam = condition.find(c => c.indexOf('common_out_link_id') > -1 || c.indexOf('out_link_direction') > -1)
|
params.outParam = condition.find(c => c.indexOf('common_out_link_id') > -1 || c.indexOf('out_link_direction') > -1)
|
||||||
params.inParam = condition.find(c => c.indexOf('common_in_link_id') > -1 || c.indexOf('in_link_direction') > -1)
|
params.inParam = condition.find(c => c.indexOf('common_in_link_id') > -1 || c.indexOf('in_link_direction') > -1)
|
||||||
@@ -168,6 +169,9 @@ export default {
|
|||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
this.showError = false
|
this.showError = false
|
||||||
this.isNoData = res.data.result.length === 0
|
this.isNoData = res.data.result.length === 0
|
||||||
|
if (!active) {
|
||||||
|
this.tabs = dataForLinkTrafficLine.tabs
|
||||||
|
}
|
||||||
if (this.isNoData) {
|
if (this.isNoData) {
|
||||||
this.lineTab = ''
|
this.lineTab = ''
|
||||||
this.tabs = dataForLinkTrafficLine.tabs
|
this.tabs = dataForLinkTrafficLine.tabs
|
||||||
@@ -387,7 +391,7 @@ export default {
|
|||||||
let num = 0
|
let num = 0
|
||||||
linkData.forEach(e => {
|
linkData.forEach(e => {
|
||||||
e.unitType = type
|
e.unitType = type
|
||||||
if (parseFloat(e.analysis.avg) === 0 || isNaN(parseFloat(e.analysis.avg))) {
|
if (parseFloat(e.analysis.max) === 0 || isNaN(parseFloat(e.analysis.max))) {
|
||||||
e.show = false
|
e.show = false
|
||||||
num += 1
|
num += 1
|
||||||
} else {
|
} else {
|
||||||
@@ -397,13 +401,18 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.lineTab === e.class) {
|
if (this.lineTab === e.class) {
|
||||||
if (parseFloat(e.analysis.avg) <= 0) {
|
if (parseFloat(e.analysis.max) <= 0) {
|
||||||
this.lineTab = ''
|
this.lineTab = ''
|
||||||
this.lineRefer = ''
|
this.lineRefer = ''
|
||||||
this.init()
|
// this.init() // 暂时注掉,后续观察
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
const emptyData = linkData.filter(d => parseFloat(d.analysis.max) === 0)
|
||||||
|
this.isNoData = emptyData.length === linkData.length
|
||||||
|
if (this.isNoData) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
this.tabs = linkData
|
this.tabs = linkData
|
||||||
// 如果三者avg都为0时,至少保证total显示
|
// 如果三者avg都为0时,至少保证total显示
|
||||||
const ingressObj = linkData.find(d => d.name === 'linkMonitor.ingress')
|
const ingressObj = linkData.find(d => d.name === 'linkMonitor.ingress')
|
||||||
@@ -411,10 +420,10 @@ export default {
|
|||||||
let ingressAvg = 0
|
let ingressAvg = 0
|
||||||
let egressAvg = 0
|
let egressAvg = 0
|
||||||
if (ingressObj) {
|
if (ingressObj) {
|
||||||
ingressAvg = parseFloat(ingressObj.analysis.avg) || 0
|
ingressAvg = parseFloat(ingressObj.analysis.max) || 0
|
||||||
}
|
}
|
||||||
if (egressObj) {
|
if (egressObj) {
|
||||||
egressAvg = parseFloat(egressObj.analysis.avg) || 0
|
egressAvg = parseFloat(egressObj.analysis.max) || 0
|
||||||
}
|
}
|
||||||
if ((ingressAvg + egressAvg) === 0) {
|
if ((ingressAvg + egressAvg) === 0) {
|
||||||
const totalObj = linkData.find(d => d.name === 'network.total')
|
const totalObj = linkData.find(d => d.name === 'network.total')
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ export default {
|
|||||||
}
|
}
|
||||||
let url = ''
|
let url = ''
|
||||||
if (this.queryCondition) {
|
if (this.queryCondition) {
|
||||||
const condition = this.queryCondition.toLowerCase().split(' or ')
|
const condition = this.queryCondition.split(' or ')
|
||||||
if (condition.length > 1) {
|
if (condition.length > 1) {
|
||||||
if (n === 0) {
|
if (n === 0) {
|
||||||
params.q = condition.find(c => c.indexOf('common_in_link_id') > -1 || c.indexOf('in_link_direction') > -1)
|
params.q = condition.find(c => c.indexOf('common_in_link_id') > -1 || c.indexOf('in_link_direction') > -1)
|
||||||
|
|||||||
@@ -87,7 +87,14 @@ export default {
|
|||||||
bandWidth: 0,
|
bandWidth: 0,
|
||||||
loading: false,
|
loading: false,
|
||||||
showError: false,
|
showError: false,
|
||||||
errorMsg: ''
|
errorMsg: '',
|
||||||
|
scoreDataState: false,
|
||||||
|
performanceData: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
scoreBaseState () {
|
||||||
|
return this.$store.getters.scoreBaseReady
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@@ -95,6 +102,16 @@ export default {
|
|||||||
handler (n) {
|
handler (n) {
|
||||||
this.linkTrafficData()
|
this.linkTrafficData()
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
scoreBaseState (n) {
|
||||||
|
if (n && this.scoreDataState) {
|
||||||
|
this.handleScoreData()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
scoreDataState (n) {
|
||||||
|
if (n && this.scoreBaseState) {
|
||||||
|
this.handleScoreData()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -103,8 +120,11 @@ export default {
|
|||||||
startTime: getSecond(this.timeFilter.startTime),
|
startTime: getSecond(this.timeFilter.startTime),
|
||||||
endTime: getSecond(this.timeFilter.endTime)
|
endTime: getSecond(this.timeFilter.endTime)
|
||||||
}
|
}
|
||||||
|
this.loading = true
|
||||||
|
this.performanceData = {}
|
||||||
|
this.scoreDataState = false
|
||||||
if (this.queryCondition) {
|
if (this.queryCondition) {
|
||||||
const condition = this.queryCondition.toLowerCase().split(' or ')
|
const condition = this.queryCondition.split(' or ')
|
||||||
if (condition.length > 1) {
|
if (condition.length > 1) {
|
||||||
// params.outParam = true
|
// params.outParam = true
|
||||||
params.outParam = condition.find(c => c.indexOf('common_out_link_id') > -1 || c.indexOf('out_link_direction') > -1)
|
params.outParam = condition.find(c => c.indexOf('common_out_link_id') > -1 || c.indexOf('out_link_direction') > -1)
|
||||||
@@ -142,7 +162,6 @@ export default {
|
|||||||
this.bandWidth = bandwidthAll
|
this.bandWidth = bandwidthAll
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.loading = true
|
|
||||||
axios.get(api.linkMonitor.networkAnalysis, { params: params }).then(response => {
|
axios.get(api.linkMonitor.networkAnalysis, { params: params }).then(response => {
|
||||||
const res = response.data
|
const res = response.data
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
@@ -152,7 +171,7 @@ export default {
|
|||||||
this.linkTrafficListData = {}
|
this.linkTrafficListData = {}
|
||||||
this.linkTrafficListData.npmScore = '-'
|
this.linkTrafficListData.npmScore = '-'
|
||||||
} else {
|
} else {
|
||||||
const data = {
|
this.performanceData = {
|
||||||
establishLatencyMs: _.get(res.data.result[0], 'establishLatencyMs', null),
|
establishLatencyMs: _.get(res.data.result[0], 'establishLatencyMs', null),
|
||||||
httpResponseLatency: _.get(res.data.result[0], 'httpResponseLatency', null),
|
httpResponseLatency: _.get(res.data.result[0], 'httpResponseLatency', null),
|
||||||
sslConLatency: _.get(res.data.result[0], 'sslConLatency', null),
|
sslConLatency: _.get(res.data.result[0], 'sslConLatency', null),
|
||||||
@@ -160,19 +179,24 @@ export default {
|
|||||||
pktRetransPercent: _.get(res.data.result[0], 'pktRetransPercent', null)
|
pktRetransPercent: _.get(res.data.result[0], 'pktRetransPercent', null)
|
||||||
}
|
}
|
||||||
this.linkTrafficListData = res.data.result[0]
|
this.linkTrafficListData = res.data.result[0]
|
||||||
this.linkTrafficListData.npmScore = computeScore(data)
|
// this.linkTrafficListData.npmScore = computeScore(data)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.showError = true
|
this.showError = true
|
||||||
this.errorMsg = res.message
|
this.errorMsg = res.message
|
||||||
}
|
}
|
||||||
}).catch(e => {
|
}).catch(e => {
|
||||||
|
console.error(e)
|
||||||
this.showError = true
|
this.showError = true
|
||||||
this.errorMsg = e.message
|
this.errorMsg = e.message
|
||||||
this.isNoData = false
|
this.isNoData = false
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
|
this.scoreDataState = true
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
handleScoreData () {
|
||||||
|
this.linkTrafficListData.npmScore = computeScore(this.performanceData, this.$store.getters.getScoreBase)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
|
|||||||
@@ -1,994 +0,0 @@
|
|||||||
export default [
|
|
||||||
{
|
|
||||||
value: 'Afghanistan',
|
|
||||||
label: 'Afghanistan'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Albania',
|
|
||||||
label: 'Albania'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Algeria',
|
|
||||||
label: 'Algeria'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'American Samoa',
|
|
||||||
label: 'American Samoa'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Andorra',
|
|
||||||
label: 'Andorra'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Angola',
|
|
||||||
label: 'Angola'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Anguilla',
|
|
||||||
label: 'Anguilla'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Antarctica',
|
|
||||||
label: 'Antarctica'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Antigua and Barbuda',
|
|
||||||
label: 'Antigua and Barbuda'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Argentina',
|
|
||||||
label: 'Argentina'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Armenia',
|
|
||||||
label: 'Armenia'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Aruba',
|
|
||||||
label: 'Aruba'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Australia',
|
|
||||||
label: 'Australia'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Austria',
|
|
||||||
label: 'Austria'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Azerbaijan',
|
|
||||||
label: 'Azerbaijan'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Bahamas (the)',
|
|
||||||
label: 'Bahamas (the)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Bahrain',
|
|
||||||
label: 'Bahrain'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Bangladesh',
|
|
||||||
label: 'Bangladesh'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Barbados',
|
|
||||||
label: 'Barbados'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Belarus',
|
|
||||||
label: 'Belarus'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Belgium',
|
|
||||||
label: 'Belgium'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Belize',
|
|
||||||
label: 'Belize'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Benin',
|
|
||||||
label: 'Benin'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Bermuda',
|
|
||||||
label: 'Bermuda'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Åland Islands',
|
|
||||||
label: 'Åland Islands'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Bhutan',
|
|
||||||
label: 'Bhutan'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Bolivia (Plurinational State of)',
|
|
||||||
label: 'Bolivia (Plurinational State of)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Bonaire, Sint Eustatius and Saba',
|
|
||||||
label: 'Bonaire, Sint Eustatius and Saba'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Bosnia and Herzegovina',
|
|
||||||
label: 'Bosnia and Herzegovina'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Botswana',
|
|
||||||
label: 'Botswana'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Bouvet Island',
|
|
||||||
label: 'Bouvet Island'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Brazil',
|
|
||||||
label: 'Brazil'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'British Indian Ocean Territory (the)',
|
|
||||||
label: 'British Indian Ocean Territory (the)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Brunei Darussalam',
|
|
||||||
label: 'Brunei Darussalam'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Bulgaria',
|
|
||||||
label: 'Bulgaria'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Burkina Faso',
|
|
||||||
label: 'Burkina Faso'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Burundi',
|
|
||||||
label: 'Burundi'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Cabo Verde',
|
|
||||||
label: 'Cabo Verde'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Cambodia',
|
|
||||||
label: 'Cambodia'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Cameroon',
|
|
||||||
label: 'Cameroon'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Canada',
|
|
||||||
label: 'Canada'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Cayman Islands (the)',
|
|
||||||
label: 'Cayman Islands (the)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Central African Republic (the)',
|
|
||||||
label: 'Central African Republic (the)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Chad',
|
|
||||||
label: 'Chad'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Chile',
|
|
||||||
label: 'Chile'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'China',
|
|
||||||
label: 'China'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Christmas Island',
|
|
||||||
label: 'Christmas Island'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Cocos (Keeling) Islands (the)',
|
|
||||||
label: 'Cocos (Keeling) Islands (the)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Colombia',
|
|
||||||
label: 'Colombia'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Comoros (the)',
|
|
||||||
label: 'Comoros (the)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Congo (the Democratic Republic of the)',
|
|
||||||
label: 'Congo (the Democratic Republic of the)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Congo (the)',
|
|
||||||
label: 'Congo (the)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Cook Islands (the)',
|
|
||||||
label: 'Cook Islands (the)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Costa Rica',
|
|
||||||
label: 'Costa Rica'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Croatia',
|
|
||||||
label: 'Croatia'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Cuba',
|
|
||||||
label: 'Cuba'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Curaçao',
|
|
||||||
label: 'Curaçao'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Cyprus',
|
|
||||||
label: 'Cyprus'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Czech Republic',
|
|
||||||
label: 'Czech Republic'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: "Côte d'Ivoire",
|
|
||||||
label: "Côte d'Ivoire"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Denmark',
|
|
||||||
label: 'Denmark'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Djibouti',
|
|
||||||
label: 'Djibouti'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Dominica',
|
|
||||||
label: 'Dominica'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Dominican Republic (the)',
|
|
||||||
label: 'Dominican Republic (the)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Ecuador',
|
|
||||||
label: 'Ecuador'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Egypt',
|
|
||||||
label: 'Egypt'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'El Salvador',
|
|
||||||
label: 'El Salvador'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Equatorial Guinea',
|
|
||||||
label: 'Equatorial Guinea'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Eritrea',
|
|
||||||
label: 'Eritrea'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Estonia',
|
|
||||||
label: 'Estonia'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Eswatini',
|
|
||||||
label: 'Eswatini'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Ethiopia',
|
|
||||||
label: 'Ethiopia'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Falkland Islands (the) [Malvinas]',
|
|
||||||
label: 'Falkland Islands (the) [Malvinas]'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Faroe Islands (the)',
|
|
||||||
label: 'Faroe Islands (the)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Fiji',
|
|
||||||
label: 'Fiji'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Finland',
|
|
||||||
label: 'Finland'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'France',
|
|
||||||
label: 'France'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'French Guiana',
|
|
||||||
label: 'French Guiana'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'French Polynesia',
|
|
||||||
label: 'French Polynesia'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'French Southern Territories (the)',
|
|
||||||
label: 'French Southern Territories (the)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Gabon',
|
|
||||||
label: 'Gabon'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Gambia (the)',
|
|
||||||
label: 'Gambia (the)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Georgia',
|
|
||||||
label: 'Georgia'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Germany',
|
|
||||||
label: 'Germany'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Ghana',
|
|
||||||
label: 'Ghana'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Gibraltar',
|
|
||||||
label: 'Gibraltar'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Greece',
|
|
||||||
label: 'Greece'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Greenland',
|
|
||||||
label: 'Greenland'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Grenada',
|
|
||||||
label: 'Grenada'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Guadeloupe',
|
|
||||||
label: 'Guadeloupe'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Guam',
|
|
||||||
label: 'Guam'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Guatemala',
|
|
||||||
label: 'Guatemala'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Guernsey',
|
|
||||||
label: 'Guernsey'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Guinea',
|
|
||||||
label: 'Guinea'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Guinea-Bissau',
|
|
||||||
label: 'Guinea-Bissau'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Guyana',
|
|
||||||
label: 'Guyana'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Haiti',
|
|
||||||
label: 'Haiti'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Heard Island and McDonald Islands',
|
|
||||||
label: 'Heard Island and McDonald Islands'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Holy See (the)',
|
|
||||||
label: 'Holy See (the)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Honduras',
|
|
||||||
label: 'Honduras'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Hong Kong',
|
|
||||||
label: 'Hong Kong'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Hungary',
|
|
||||||
label: 'Hungary'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Iceland',
|
|
||||||
label: 'Iceland'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'India',
|
|
||||||
label: 'India'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Indonesia',
|
|
||||||
label: 'Indonesia'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Iran (Islamic Republic of)',
|
|
||||||
label: 'Iran (Islamic Republic of)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Iraq',
|
|
||||||
label: 'Iraq'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Ireland',
|
|
||||||
label: 'Ireland'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Isle of Man',
|
|
||||||
label: 'Isle of Man'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Israel',
|
|
||||||
label: 'Israel'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Italy',
|
|
||||||
label: 'Italy'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Jamaica',
|
|
||||||
label: 'Jamaica'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Japan',
|
|
||||||
label: 'Japan'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Jersey',
|
|
||||||
label: 'Jersey'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Jordan',
|
|
||||||
label: 'Jordan'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Kazakhstan',
|
|
||||||
label: 'Kazakhstan'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Kenya',
|
|
||||||
label: 'Kenya'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Kiribati',
|
|
||||||
label: 'Kiribati'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Korea',
|
|
||||||
label: 'Korea'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Kuwait',
|
|
||||||
label: 'Kuwait'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Kyrgyzstan',
|
|
||||||
label: 'Kyrgyzstan'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: "Lao People's Democratic Republic (the)",
|
|
||||||
label: "Lao People's Democratic Republic (the)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Latvia',
|
|
||||||
label: 'Latvia'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Lebanon',
|
|
||||||
label: 'Lebanon'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Lesotho',
|
|
||||||
label: 'Lesotho'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Liberia',
|
|
||||||
label: 'Liberia'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Libya',
|
|
||||||
label: 'Libya'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Liechtenstein',
|
|
||||||
label: 'Liechtenstein'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Lithuania',
|
|
||||||
label: 'Lithuania'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Luxembourg',
|
|
||||||
label: 'Luxembourg'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Macao',
|
|
||||||
label: 'Macao'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Madagascar',
|
|
||||||
label: 'Madagascar'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Malawi',
|
|
||||||
label: 'Malawi'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Malaysia',
|
|
||||||
label: 'Malaysia'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Maldives',
|
|
||||||
label: 'Maldives'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Mali',
|
|
||||||
label: 'Mali'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Malta',
|
|
||||||
label: 'Malta'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Marshall Islands (the)',
|
|
||||||
label: 'Marshall Islands (the)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Martinique',
|
|
||||||
label: 'Martinique'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Mauritania',
|
|
||||||
label: 'Mauritania'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Mauritius',
|
|
||||||
label: 'Mauritius'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Mayotte',
|
|
||||||
label: 'Mayotte'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Mexico',
|
|
||||||
label: 'Mexico'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Micronesia (Federated States of)',
|
|
||||||
label: 'Micronesia (Federated States of)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Moldova (the Republic of)',
|
|
||||||
label: 'Moldova (the Republic of)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Monaco',
|
|
||||||
label: 'Monaco'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Mongolia',
|
|
||||||
label: 'Mongolia'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Montenegro',
|
|
||||||
label: 'Montenegro'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Montserrat',
|
|
||||||
label: 'Montserrat'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Morocco',
|
|
||||||
label: 'Morocco'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Mozambique',
|
|
||||||
label: 'Mozambique'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Myanmar',
|
|
||||||
label: 'Myanmar'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Namibia',
|
|
||||||
label: 'Namibia'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Nauru',
|
|
||||||
label: 'Nauru'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Nepal',
|
|
||||||
label: 'Nepal'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Netherlands',
|
|
||||||
label: 'Netherlands'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'New Caledonia',
|
|
||||||
label: 'New Caledonia'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'New Zealand',
|
|
||||||
label: 'New Zealand'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Nicaragua',
|
|
||||||
label: 'Nicaragua'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Niger',
|
|
||||||
label: 'Niger'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Nigeria',
|
|
||||||
label: 'Nigeria'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Niue',
|
|
||||||
label: 'Niue'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Norfolk Island',
|
|
||||||
label: 'Norfolk Island'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'North Macedonia',
|
|
||||||
label: 'North Macedonia'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Northern Mariana Islands (the)',
|
|
||||||
label: 'Northern Mariana Islands (the)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Norway',
|
|
||||||
label: 'Norway'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Oman',
|
|
||||||
label: 'Oman'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Pakistan',
|
|
||||||
label: 'Pakistan'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Palau',
|
|
||||||
label: 'Palau'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Palestine, State of',
|
|
||||||
label: 'Palestine, State of'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Panama',
|
|
||||||
label: 'Panama'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Papua New Guinea',
|
|
||||||
label: 'Papua New Guinea'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Paraguay',
|
|
||||||
label: 'Paraguay'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Peru',
|
|
||||||
label: 'Peru'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Philippines',
|
|
||||||
label: 'Philippines'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Pitcairn',
|
|
||||||
label: 'Pitcairn'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Poland',
|
|
||||||
label: 'Poland'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Portugal',
|
|
||||||
label: 'Portugal'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Puerto Rico',
|
|
||||||
label: 'Puerto Rico'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Qatar',
|
|
||||||
label: 'Qatar'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Romania',
|
|
||||||
label: 'Romania'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Russian Federation',
|
|
||||||
label: 'Russian Federation'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Rwanda',
|
|
||||||
label: 'Rwanda'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Réunion',
|
|
||||||
label: 'Réunion'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Saint Barthélemy',
|
|
||||||
label: 'Saint Barthélemy'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Saint Helena, Ascension and Tristan da Cunha',
|
|
||||||
label: 'Saint Helena, Ascension and Tristan da Cunha'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Saint Kitts and Nevis',
|
|
||||||
label: 'Saint Kitts and Nevis'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Saint Lucia',
|
|
||||||
label: 'Saint Lucia'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Saint Martin',
|
|
||||||
label: 'Saint Martin'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Saint Pierre and Miquelon',
|
|
||||||
label: 'Saint Pierre and Miquelon'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Saint Vincent and the Grenadines',
|
|
||||||
label: 'Saint Vincent and the Grenadines'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Samoa',
|
|
||||||
label: 'Samoa'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'San Marino',
|
|
||||||
label: 'San Marino'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Sao Tome and Principe',
|
|
||||||
label: 'Sao Tome and Principe'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Saudi Arabia',
|
|
||||||
label: 'Saudi Arabia'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Senegal',
|
|
||||||
label: 'Senegal'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Serbia',
|
|
||||||
label: 'Serbia'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Seychelles',
|
|
||||||
label: 'Seychelles'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Sierra Leone',
|
|
||||||
label: 'Sierra Leone'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Singapore',
|
|
||||||
label: 'Singapore'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Sint Maarten',
|
|
||||||
label: 'Sint Maarten'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Slovakia',
|
|
||||||
label: 'Slovakia'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Slovenia',
|
|
||||||
label: 'Slovenia'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Solomon Islands',
|
|
||||||
label: 'Solomon Islands'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Somalia',
|
|
||||||
label: 'Somalia'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'South Africa',
|
|
||||||
label: 'South Africa'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'South Georgia and the South Sandwich Islands',
|
|
||||||
label: 'South Georgia and the South Sandwich Islands'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'South Sudan',
|
|
||||||
label: 'South Sudan'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Spain',
|
|
||||||
label: 'Spain'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Sri Lanka',
|
|
||||||
label: 'Sri Lanka'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Sudan',
|
|
||||||
label: 'Sudan'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Suriname',
|
|
||||||
label: 'Suriname'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Svalbard and Jan Mayen',
|
|
||||||
label: 'Svalbard and Jan Mayen'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Sweden',
|
|
||||||
label: 'Sweden'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Switzerland',
|
|
||||||
label: 'Switzerland'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Syrian Arab Republic',
|
|
||||||
label: 'Syrian Arab Republic'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Taiwan',
|
|
||||||
label: 'Taiwan'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Tajikistan',
|
|
||||||
label: 'Tajikistan'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Tanzania, the United Republic of',
|
|
||||||
label: 'Tanzania, the United Republic of'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Thailand',
|
|
||||||
label: 'Thailand'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Timor-Leste',
|
|
||||||
label: 'Timor-Leste'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Togo',
|
|
||||||
label: 'Togo'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Tokelau',
|
|
||||||
label: 'Tokelau'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Tonga',
|
|
||||||
label: 'Tonga'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Trinidad and Tobago',
|
|
||||||
label: 'Trinidad and Tobago'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Tunisia',
|
|
||||||
label: 'Tunisia'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Turkey',
|
|
||||||
label: 'Turkey'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Turkmenistan',
|
|
||||||
label: 'Turkmenistan'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Turks and Caicos Islands',
|
|
||||||
label: 'Turks and Caicos Islands'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Tuvalu',
|
|
||||||
label: 'Tuvalu'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Uganda',
|
|
||||||
label: 'Uganda'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Ukraine',
|
|
||||||
label: 'Ukraine'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'United Arab Emirates',
|
|
||||||
label: 'United Arab Emirates'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'United Kingdom of Great Britain and Northern Ireland',
|
|
||||||
label: 'United Kingdom of Great Britain and Northern Ireland'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'United States Minor Outlying Islands',
|
|
||||||
label: 'United States Minor Outlying Islands'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'United States',
|
|
||||||
label: 'United States'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Uruguay',
|
|
||||||
label: 'Uruguay'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Uzbekistan',
|
|
||||||
label: 'Uzbekistan'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Vanuatu',
|
|
||||||
label: 'Vanuatu'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Venezuela (Bolivarian Republic of)',
|
|
||||||
label: 'Venezuela (Bolivarian Republic of)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Viet Nam',
|
|
||||||
label: 'Viet Nam'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Virgin Islands (British)',
|
|
||||||
label: 'Virgin Islands (British)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Virgin Islands (U.S.)',
|
|
||||||
label: 'Virgin Islands (U.S.)'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Wallis and Futuna',
|
|
||||||
label: 'Wallis and Futuna'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Western Sahara*',
|
|
||||||
label: 'Western Sahara*'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Yemen',
|
|
||||||
label: 'Yemen'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Zambia',
|
|
||||||
label: 'Zambia'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'Zimbabwe',
|
|
||||||
label: 'Zimbabwe'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
@@ -326,7 +326,7 @@ export default {
|
|||||||
if (tabType) {
|
if (tabType) {
|
||||||
const oldCurTab = this.getUrlParam(this.curTabState.networkOverviewBeforeTab, '')
|
const oldCurTab = this.getUrlParam(this.curTabState.networkOverviewBeforeTab, '')
|
||||||
const curTable = networkTable.networkOverview
|
const curTable = networkTable.networkOverview
|
||||||
const tableType = this.$route.params ? this.$route.params.typeName : 'networkOverview'
|
const tableType = this.$route.path.replace('/panel/', '') || 'networkOverview'
|
||||||
const metric = this.getUrlParam(this.curTabState.tableMetric, 'Bits/s')
|
const metric = this.getUrlParam(this.curTabState.tableMetric, 'Bits/s')
|
||||||
const list = await getUserDrilldownTableConfig(tableType, metric)
|
const list = await getUserDrilldownTableConfig(tableType, metric)
|
||||||
const tabGroup = list.filter(item => item.label === tabType)
|
const tabGroup = list.filter(item => item.label === tabType)
|
||||||
@@ -493,11 +493,9 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
if (val) {
|
if (!show) { // 非滚动滚动条操作,直接覆盖之前的数据
|
||||||
this.providerOptions = res.data.list
|
this.providerOptions = res.data.list
|
||||||
} else if (!val && !show) {
|
} else { // 滚动条操作,则将新数据和之前的数据组合
|
||||||
this.providerOptions = res.data.list
|
|
||||||
} else {
|
|
||||||
this.providerOptions.push(...res.data.list)
|
this.providerOptions.push(...res.data.list)
|
||||||
this.appListData([], this.providerOptions)
|
this.appListData([], this.providerOptions)
|
||||||
}
|
}
|
||||||
@@ -519,11 +517,9 @@ export default {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
if (val) {
|
if (!show) { // 非滚动滚动条操作,直接覆盖之前的数据
|
||||||
this.appOptions = res.data.list
|
this.appOptions = res.data.list
|
||||||
} else if (!val && !show) {
|
} else { // 滚动条操作,则将新数据和之前的数据组合
|
||||||
this.appOptions = res.data.list
|
|
||||||
} else {
|
|
||||||
this.appOptions.push(...res.data.list)
|
this.appOptions.push(...res.data.list)
|
||||||
this.appListData(this.appOptions, [])
|
this.appListData(this.appOptions, [])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ export default {
|
|||||||
startTime: this.timeFilter && this.timeFilter.startTime ? getSecond(this.timeFilter.startTime) : '',
|
startTime: this.timeFilter && this.timeFilter.startTime ? getSecond(this.timeFilter.startTime) : '',
|
||||||
endTime: this.timeFilter && this.timeFilter.endTime ? getSecond(this.timeFilter.endTime) : ''
|
endTime: this.timeFilter && this.timeFilter.endTime ? getSecond(this.timeFilter.endTime) : ''
|
||||||
}
|
}
|
||||||
/*this.toggleLoading(true)
|
/* this.toggleLoading(true)
|
||||||
axios.get(api.netWorkOverview.ddosEventAnalysis, { params: params }).then(response => {
|
axios.get(api.netWorkOverview.ddosEventAnalysis, { params: params }).then(response => {
|
||||||
const res = response.data
|
const res = response.data
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
@@ -85,7 +85,7 @@ export default {
|
|||||||
this.errorMsg = this.errorMsgHandler(e)
|
this.errorMsg = this.errorMsgHandler(e)
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
this.toggleLoading(false)
|
this.toggleLoading(false)
|
||||||
})*/
|
}) */
|
||||||
this.toggleLoading(false)
|
this.toggleLoading(false)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -32,17 +32,20 @@
|
|||||||
</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"
|
||||||
v-model="lineRefer"
|
v-model="lineRefer"
|
||||||
:disabled="!lineTab"
|
:disabled="!lineTab"
|
||||||
|
placeholder=" "
|
||||||
popper-class="common-select"
|
popper-class="common-select"
|
||||||
: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>
|
||||||
@@ -192,6 +195,9 @@ export default {
|
|||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
this.isNoData = res.data.result.length === 0
|
this.isNoData = res.data.result.length === 0
|
||||||
this.showError = false
|
this.showError = false
|
||||||
|
if (!active) {
|
||||||
|
this.tabs = _.cloneDeep(this.tabsTemplate)
|
||||||
|
}
|
||||||
if (this.isNoData) {
|
if (this.isNoData) {
|
||||||
this.lineTab = ''
|
this.lineTab = ''
|
||||||
this.tabs = _.cloneDeep(this.tabsTemplate)
|
this.tabs = _.cloneDeep(this.tabsTemplate)
|
||||||
@@ -270,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',
|
||||||
@@ -464,8 +478,7 @@ export default {
|
|||||||
newData.push(obj)
|
newData.push(obj)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
if (data && data.length > 0) {
|
||||||
if (data !== undefined && data.length > 0) {
|
|
||||||
newData.forEach((item) => {
|
newData.forEach((item) => {
|
||||||
item.type = getLineType(item.type)
|
item.type = getLineType(item.type)
|
||||||
if (item.type === val) {
|
if (item.type === val) {
|
||||||
@@ -478,6 +491,24 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
lineData.splice(0, 1)
|
lineData.splice(0, 1)
|
||||||
|
// TODO 下面的逻辑是判断total曲线的尾部数据,从尾往前数0值的个数,若个数大于0,所有曲线都从尾部去掉相同数量的点,最多4个
|
||||||
|
const totalData = lineData[0]
|
||||||
|
if (_.get(totalData, 'values', []).length > 4) {
|
||||||
|
let count = 0
|
||||||
|
for (let i = totalData.values.length - 1; i >= totalData.values.length - 4; i--) {
|
||||||
|
if (totalData.values[i].length > 1 && totalData.values[i][1] === 0) {
|
||||||
|
count++
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (count > 0) {
|
||||||
|
lineData.forEach(l => {
|
||||||
|
l.values.splice(l.values.length - count, count)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (val === 'Sessions/s') {
|
if (val === 'Sessions/s') {
|
||||||
const tabs = _.cloneDeep(this.tabsTemplate)
|
const tabs = _.cloneDeep(this.tabsTemplate)
|
||||||
lineData.forEach((d, i) => {
|
lineData.forEach((d, i) => {
|
||||||
@@ -495,6 +526,7 @@ export default {
|
|||||||
})
|
})
|
||||||
this.tabs = tabs
|
this.tabs = tabs
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
|
this.lineRefer = 'Average'
|
||||||
this.echartsInit(this.tabs, true)
|
this.echartsInit(this.tabs, true)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@@ -512,7 +544,7 @@ export default {
|
|||||||
const self = this
|
const self = this
|
||||||
tabs.forEach(e => {
|
tabs.forEach(e => {
|
||||||
e.unitType = type
|
e.unitType = type
|
||||||
if (e.name !== 'network.total' && parseFloat(e.analysis.avg) === 0) {
|
if (e.name !== 'network.total' && parseFloat(e.analysis.max) === 0) {
|
||||||
e.show = false
|
e.show = false
|
||||||
num += 1
|
num += 1
|
||||||
} else {
|
} else {
|
||||||
@@ -522,13 +554,18 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (self.lineTab === e.class) {
|
if (self.lineTab === e.class) {
|
||||||
if (parseFloat(e.analysis.avg) <= 0) {
|
if (parseFloat(e.analysis.max) <= 0) {
|
||||||
self.lineTab = ''
|
self.lineTab = ''
|
||||||
self.lineRefer = ''
|
self.lineRefer = ''
|
||||||
self.init()
|
// self.init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
const emptyData = tabs.filter(d => parseFloat(d.analysis.max) === 0)
|
||||||
|
this.isNoData = emptyData.length === tabs.length
|
||||||
|
if (this.isNoData) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
this.tabs = tabs
|
this.tabs = tabs
|
||||||
if (num === 5) {
|
if (num === 5) {
|
||||||
tabs[0].invertTab = false
|
tabs[0].invertTab = false
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user