Compare commits
27 Commits
23.10.demo
...
dev-23.09
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2fe18471fa | ||
|
|
cdd3557bbe | ||
|
|
b44a99f354 | ||
|
|
76c0c081e5 | ||
|
|
6ac9b71b0e | ||
|
|
41f161e301 | ||
|
|
e926163da4 | ||
|
|
7b7c2456e2 | ||
|
|
4fb8ab2996 | ||
|
|
be6a1e9fb6 | ||
|
|
faae781f42 | ||
|
|
216c6eaab2 | ||
|
|
f939d344fa | ||
|
|
7b93068d75 | ||
|
|
5dedc6d12d | ||
|
|
d0cad48f6a | ||
|
|
1fa8f157ed | ||
|
|
9a3e4e07ab | ||
|
|
817d593c78 | ||
|
|
ed8be53798 | ||
|
|
d14f34ec9f | ||
|
|
6cb27b72af | ||
|
|
4abe0ce74c | ||
|
|
272fd2a5d2 | ||
|
|
fc56a1fc0c | ||
|
|
ccd2b3d08b | ||
|
|
60bbb8b165 |
@@ -39,9 +39,9 @@ build_project:
|
||||
stage: build_project
|
||||
script:
|
||||
- echo "npm install ..."
|
||||
- cnpm install --save-dev --unsafe-perm
|
||||
- npm install --save-dev --unsafe-perm
|
||||
- echo "npm run build"
|
||||
- cnpm run build
|
||||
- npm run build
|
||||
artifacts:
|
||||
name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME"
|
||||
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"
|
||||
},
|
||||
"dependencies": {
|
||||
"@amcharts/amcharts4": "^4.10.24",
|
||||
"@amcharts/amcharts4": "~4.10.0",
|
||||
"@amcharts/amcharts4-geodata": "^4.1.20",
|
||||
"@antv/g6": "^4.8.17",
|
||||
"axios": "^0.21.1",
|
||||
"babel-plugin-lodash": "^3.3.4",
|
||||
"babel-plugin-lodash": "~3.3.0",
|
||||
"codemirror": "^5.65.1",
|
||||
"core-js": "^3.6.5",
|
||||
"core-js": "~3.31.0",
|
||||
"dayjs": "^1.10.5",
|
||||
"dexie": "^3.2.2",
|
||||
"dexie": "~3.2.0",
|
||||
"echarts": "^5.1.1",
|
||||
"element-plus": "^1.0.2-beta.44",
|
||||
"element-plus": "~1.0.2-beta.71",
|
||||
"lib-flexible": "^0.3.2",
|
||||
"lodash": "^4.17.21",
|
||||
"mockjs": "^1.1.0",
|
||||
"moment-timezone": "^0.5.33",
|
||||
"node-sass": "^4.14.1",
|
||||
"postcss-plugin-px2rem": "^0.8.1",
|
||||
"node-sass": "~4.14.0",
|
||||
"postcss-plugin-px2rem": "~0.8.1",
|
||||
"postcss-px2rem-exclude": "0.0.6",
|
||||
"sass-loader": "^8.0.2",
|
||||
"sass-resources-loader": "^2.2.1",
|
||||
"sass-loader": "~8.0.2",
|
||||
"sass-resources-loader": "~2.2.5",
|
||||
"tiny-emitter": "^2.1.0",
|
||||
"vue": "^3.0.0",
|
||||
"vue": "~3.3.0",
|
||||
"vue-grid-layout": "^3.0.0-beta1",
|
||||
"vue-i18n": "^9.1.6",
|
||||
"vue-router": "^4.0.8",
|
||||
"vuex": "^4.0.1"
|
||||
"vue-i18n": "~9.2.0",
|
||||
"vue-router": "~4.2.0",
|
||||
"vuex": "~4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.12.1",
|
||||
"@babel/core": "^7.11.4",
|
||||
"@babel/plugin-proposal-class-properties": "^7.12.1",
|
||||
"@babel/plugin-proposal-private-methods": "^7.12.1",
|
||||
"@babel/plugin-transform-runtime": "^7.12.1",
|
||||
"@babel/plugin-proposal-private-property-in-object": "^7.12.1",
|
||||
"@babel/preset-env": "^7.11.5",
|
||||
"@babel/preset-typescript": "^7.10.4",
|
||||
"@babel/cli": "~7.22.0",
|
||||
"@babel/core": "~7.22.5",
|
||||
"@babel/plugin-proposal-class-properties": "~7.18.0",
|
||||
"@babel/plugin-proposal-private-methods": "~7.18.0",
|
||||
"@babel/plugin-transform-runtime": "~7.22.0",
|
||||
"@babel/plugin-proposal-private-property-in-object": "~7.21.0",
|
||||
"@babel/preset-env": "~7.22.0",
|
||||
"@babel/preset-typescript": "~7.22.0",
|
||||
"@commitlint/cli": "^9.1.2",
|
||||
"@commitlint/config-conventional": "^9.1.2",
|
||||
"@highlightjs/vue-plugin": "^2.0.1",
|
||||
"@rollup/plugin-commonjs": "^15.1.0",
|
||||
"@rollup/plugin-node-resolve": "^9.0.0",
|
||||
"@rollup/plugin-typescript": "^6.0.0",
|
||||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@testing-library/user-event": "^14.4.3",
|
||||
"@testing-library/vue": "^6.4.2",
|
||||
"@types/jest": "^26.0.24",
|
||||
"@testing-library/jest-dom": "~5.16.0",
|
||||
"@testing-library/user-event": "~14.4.0",
|
||||
"@testing-library/vue": "~6.6.0",
|
||||
"@types/jest": "~26.0.0",
|
||||
"@types/lodash": "^4.14.161",
|
||||
"@typescript-eslint/eslint-plugin": "^3.10.1",
|
||||
"@typescript-eslint/parser": "^3.10.1",
|
||||
"@vue/babel-plugin-jsx": "^1.0.0",
|
||||
"@vue/babel-preset-app": "^5.0.8",
|
||||
"@vue/babel-plugin-jsx": "~1.1.0",
|
||||
"@vue/babel-preset-app": "~5.0.0",
|
||||
"@vue/cli-plugin-babel": "~4.5.0",
|
||||
"@vue/cli-plugin-eslint": "~4.5.0",
|
||||
"@vue/cli-service": "~4.5.0",
|
||||
"@vue/compiler-sfc": "^3.0.0",
|
||||
"@vue/component-compiler-utils": "^3.2.0",
|
||||
"@vue/test-utils": "^2.2.7",
|
||||
"@vue/compiler-sfc": "~3.3.0",
|
||||
"@vue/component-compiler-utils": "~3.3.0",
|
||||
"@vue/test-utils": "~2.4.0",
|
||||
"@vue/server-renderer": "~3.3.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-jest": "^26.0.0",
|
||||
"compression-webpack-plugin": "^8.0.1",
|
||||
@@ -77,11 +78,10 @@
|
||||
"eslint-plugin-node": "^11.1.0",
|
||||
"eslint-plugin-promise": "^4.3.1",
|
||||
"eslint-plugin-vue": "^7.7.0",
|
||||
"jest": "^26.0.0",
|
||||
"ts-jest": "^26.4.4",
|
||||
"jest": "~26.6.0",
|
||||
"ts-jest": "~26.5.0",
|
||||
"uglifyjs-webpack-plugin": "^2.2.0",
|
||||
"vue-jest": "^5.0.0-alpha.10",
|
||||
"vue3-ace-editor": "^2.0.2"
|
||||
"vue-jest": "^5.0.0-alpha.10"
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
width: 50px;
|
||||
height: 100%;
|
||||
margin-right: 8px;
|
||||
transform: rotate(-45deg) translate(-5px,-15px);
|
||||
transform: translate(0, -15px);
|
||||
color: #353636;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
width: calc(100% - 30px);
|
||||
margin: 0 10px 0 20px;
|
||||
max-height: 265px;
|
||||
min-height: 40px;
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
.entity-list--list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
height: auto;
|
||||
/*overflow: visible;/*overflow: auto;*/
|
||||
|
||||
.cn-entity__shadow {
|
||||
|
||||
@@ -624,6 +624,11 @@ export default {
|
||||
const parser = new Parser(this.columnList)
|
||||
if (q.indexOf('%') === 0 || q.indexOf('%20') > -1 || q.indexOf('%25') > -1) {
|
||||
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
|
||||
}
|
||||
|
||||
@@ -225,6 +225,11 @@ export default {
|
||||
if (q) {
|
||||
if (q.indexOf('%') === 0 || q.indexOf('%20') > -1 || q.indexOf('%25') > -1) {
|
||||
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,解析时不识别导致的语法错误
|
||||
// 如地址栏输入116.178.222.171,此时的q很长,刷新界面时需要把q里的116.178.222.171拿出来进行搜索
|
||||
|
||||
@@ -6,9 +6,10 @@ import { ElMessage } from 'element-plus'
|
||||
import i18n from '@/i18n'
|
||||
|
||||
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.'-_]$/,
|
||||
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(']
|
||||
|
||||
@@ -527,7 +528,9 @@ export default class Parser {
|
||||
}
|
||||
// 在单引号里,又在括号里,则遇到逗号、右括号就报错
|
||||
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))
|
||||
break
|
||||
}
|
||||
@@ -709,6 +712,13 @@ export default class Parser {
|
||||
meta.column.label = token.value
|
||||
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 {
|
||||
errorList.push(new ParserError(token.end, errorTypes.syntaxError, errorDesc.syntaxError.unexpectedString))
|
||||
break
|
||||
|
||||
@@ -58,13 +58,24 @@ export default {
|
||||
*/
|
||||
setup (props) {
|
||||
const { query } = useRoute()
|
||||
const pageSize = ref(defaultPageSize)
|
||||
// pageSize取值顺序:1.url;2.缓存;3.pageObj;4.默认值
|
||||
const urlPageSize = parseInt(query.pageSize)
|
||||
const cachePageSize = parseInt(localStorage.getItem(storageKey.pageSize + '-' + localStorage.getItem(storageKey.username) + '-' + props.tableId))
|
||||
const pageObjPageSize = props.pageObj.pageSize
|
||||
const pageSize = ref(urlPageSize || cachePageSize || pageObjPageSize || defaultPageSize)
|
||||
const currentPageNo = ref(props.storePageNoOnUrl ? (query.pageNo || (props.pageObj.pageNo || 1)) : (props.pageObj.pageNo || 1))
|
||||
return {
|
||||
pageSize,
|
||||
currentPageNo
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
if (this.postPageSizes && this.postPageSizes.length > 0) {
|
||||
this.resetPageSizes()
|
||||
}
|
||||
this.currentPageNo = parseInt(this.currentPageNo)
|
||||
this.current(this.currentPageNo)
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
// pageSize: defaultPageSize,
|
||||
@@ -147,6 +158,7 @@ export default {
|
||||
size (val) {
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
// this.pageObj.pageNo = 1
|
||||
this.$emit('scrollbarToTop')
|
||||
this.$emit('pageSize', val)
|
||||
this.backgroundColor()
|
||||
|
||||
@@ -163,11 +175,12 @@ export default {
|
||||
wrap.scrollTop = 0
|
||||
}
|
||||
})
|
||||
this.$emit('scrollbarToTop')
|
||||
})
|
||||
},
|
||||
resetPageSizes: function () {
|
||||
if (this.postPageSizes) {
|
||||
this.pageSizes = this.postPageSizes.map((item) => {
|
||||
this.pageSizes = this.postPageSizes.map(item => {
|
||||
return {
|
||||
label: item + this.$t('pageSize'),
|
||||
value: item
|
||||
@@ -183,20 +196,6 @@ export default {
|
||||
// }
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
if (this.postPageSizes && this.postPageSizes.length > 0) {
|
||||
this.pageSize = this.postPageSizes[0]
|
||||
this.resetPageSizes()
|
||||
} else {
|
||||
const pageSize = localStorage.getItem(storageKey.pageSize + '-' + localStorage.getItem(storageKey.username) + '-' + this.tableId)
|
||||
if (pageSize != 'undefined' && pageSize != null) {
|
||||
this.pageSize = parseInt(pageSize)
|
||||
}
|
||||
}
|
||||
|
||||
this.currentPageNo = parseInt(this.currentPageNo)
|
||||
this.current(this.currentPageNo)
|
||||
},
|
||||
watch: {
|
||||
postPageSizes: {
|
||||
immediate: true,
|
||||
|
||||
@@ -786,6 +786,7 @@ export default {
|
||||
t: +new Date()
|
||||
}
|
||||
})
|
||||
return
|
||||
} else if (opeType === 3) {
|
||||
this.$router.push({
|
||||
query: {
|
||||
@@ -794,6 +795,7 @@ export default {
|
||||
t: +new Date()
|
||||
}
|
||||
})
|
||||
return
|
||||
} else if (opeType !== 4) {
|
||||
this.$router.push({
|
||||
query: {
|
||||
@@ -803,11 +805,12 @@ export default {
|
||||
t: +new Date()
|
||||
}
|
||||
})
|
||||
}
|
||||
if (route === this.route) {
|
||||
this.refresh()
|
||||
return
|
||||
}
|
||||
/* if (route === this.route) {
|
||||
this.refresh()
|
||||
return
|
||||
} */
|
||||
if (route) {
|
||||
this.$router.push({
|
||||
path: route,
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -92,11 +92,6 @@ const routes = [
|
||||
path: '/i18n',
|
||||
component: () => import('@/views/administration/I18n')
|
||||
},
|
||||
{
|
||||
name: 'Chart',
|
||||
path: '/chart',
|
||||
component: () => import('@/views/administration/Chart')
|
||||
},
|
||||
{
|
||||
path: '/detectionsNew',
|
||||
component: () => import('@/views/detectionsNew/Index')
|
||||
|
||||
@@ -802,22 +802,22 @@ export function computeScore (data) {
|
||||
if (t === 'establishLatencyMs' || t === 'httpResponseLatency' || t === 'sslConLatency') {
|
||||
if (!data[t] && data[t] !== 0) {
|
||||
score = 1
|
||||
} else if (data[t] <= 50) {
|
||||
} else if (data[t] <= 100) {
|
||||
score = 1
|
||||
} else if (data[t] > 200) {
|
||||
} else if (data[t] > 1000) {
|
||||
score = 0
|
||||
} else {
|
||||
score = (data[t] - 200) / (50 - 200)
|
||||
score = (data[t] - 1000) / (100 - 1000)
|
||||
}
|
||||
} else if (t === 'tcpLostlenPercent' || t === 'pktRetransPercent') {
|
||||
if (!data[t] && data[t] !== 0) {
|
||||
score = 1
|
||||
} else if (data[t] <= 0.01) {
|
||||
} else if (data[t] <= 0.001) {
|
||||
score = 1
|
||||
} else if (data[t] > 0.05) {
|
||||
score = 0
|
||||
} else {
|
||||
score = (data[t] - 0.05) / (0.01 - 0.05)
|
||||
score = (data[t] - 0.05) / (0.001 - 0.05)
|
||||
}
|
||||
}
|
||||
scoreArr.push(score * k)
|
||||
|
||||
@@ -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>
|
||||
@@ -122,6 +122,7 @@ import { drillDownPanelTypeMapping, storageKey, unitTypes } from '@/utils/consta
|
||||
import { getSecond } from '@/utils/date-util'
|
||||
import ChartError from '@/components/common/Error'
|
||||
import axios from 'axios'
|
||||
// import { analysis, nextHopAnalysis } from './test-data'
|
||||
|
||||
export default {
|
||||
name: 'LinkBlock',
|
||||
@@ -192,6 +193,8 @@ export default {
|
||||
const res = []
|
||||
res[0] = response[0].data
|
||||
res[1] = response[1].data
|
||||
/*res[0] = analysis.data
|
||||
res[1] = nextHopAnalysis.data*/
|
||||
if (response[0].status === 200) {
|
||||
this.showError1 = false
|
||||
|
||||
@@ -211,6 +214,9 @@ export default {
|
||||
hit.outBandwidth = info.bandwidth
|
||||
} else if (info.direction === 'in') {
|
||||
hit.inBandwidth = info.bandwidth
|
||||
} else if (info.direction === '2') {
|
||||
hit.outBandwidth = info.bandwidth
|
||||
hit.inBandwidth = info.bandwidth
|
||||
}
|
||||
} else {
|
||||
const hit = {
|
||||
@@ -222,6 +228,9 @@ export default {
|
||||
hit.outBandwidth = info.bandwidth
|
||||
} else if (info.direction === 'in') {
|
||||
hit.inBandwidth = info.bandwidth
|
||||
} else if (info.direction === '2') {
|
||||
hit.outBandwidth = info.bandwidth
|
||||
hit.inBandwidth = info.bandwidth
|
||||
}
|
||||
data.push(hit)
|
||||
}
|
||||
@@ -235,6 +244,9 @@ export default {
|
||||
item.outLinkId = info.originalLinkId
|
||||
} else if (info.direction === 'in') {
|
||||
item.inLinkId = info.originalLinkId
|
||||
} else if (info.direction === '2') {
|
||||
item.outLinkId = info.originalLinkId
|
||||
item.inLinkId = info.originalLinkId
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -355,12 +367,12 @@ export default {
|
||||
if (out < 0.0001 && out !== 0) {
|
||||
outUsage = '< 0.01%'
|
||||
} else {
|
||||
outUsage = JSON.stringify(parseFloat((out * 100).toFixed(2)))
|
||||
outUsage = JSON.stringify(parseFloat(out * 100).toFixed(2))
|
||||
}
|
||||
if (_in < 0.0001 && _in !== 0) {
|
||||
inUsage = '< 0.01%'
|
||||
} else {
|
||||
inUsage = JSON.stringify(parseFloat((_in * 100).toFixed(2)))
|
||||
inUsage = JSON.stringify(parseFloat(_in * 100).toFixed(2))
|
||||
}
|
||||
|
||||
length = outUsage.length + inUsage.length
|
||||
|
||||
@@ -17,6 +17,7 @@ import PopoverContent from './LinkDirectionGrid/PopoverContent'
|
||||
import { computeScore } from '@/utils/tools'
|
||||
import axios from 'axios'
|
||||
import _ from 'lodash'
|
||||
// import { bigramAnalysis, bigramNextHopAnalysis } from './test-data'
|
||||
|
||||
export default {
|
||||
name: 'LinkDirectionGrid',
|
||||
@@ -74,6 +75,8 @@ export default {
|
||||
const res = []
|
||||
res[0] = response[0].data
|
||||
res[1] = response[1].data
|
||||
/*res[0] = bigramAnalysis.data
|
||||
res[1] = bigramNextHopAnalysis.data*/
|
||||
if (response[0].status === 200) {
|
||||
this.isLinkShowError = false
|
||||
// 链路流量数据
|
||||
@@ -101,6 +104,12 @@ export default {
|
||||
}
|
||||
})
|
||||
linkGridData.push({ linkId: link.linkId, out: outList })
|
||||
} else if (link.direction === '2') {
|
||||
const outList = []
|
||||
linkInfo.forEach(link1 => {
|
||||
outList.push({ linkId: link1.linkId, noData: true })
|
||||
})
|
||||
linkGridData.push({ linkId: link.linkId, out: outList })
|
||||
}
|
||||
})
|
||||
|
||||
@@ -121,8 +130,11 @@ export default {
|
||||
|
||||
d.scoreLow3 = d.score < 3 || d.score === '-'
|
||||
|
||||
const xAxis = inLink.linkId.split('Hundredgige').pop() - 1
|
||||
const yAxis = outLink.linkId.split('Hundredgige').pop() - 1
|
||||
/*const xAxis = inLink.linkId.split('Hundredgige').pop() - 1
|
||||
const yAxis = outLink.linkId.split('Hundredgige').pop() - 1*/
|
||||
const xAxis = inLink.linkId.split('UFONE-RWP-GI-LANPHY-100G-').pop() - 1
|
||||
const yAxis = outLink.linkId.split('UFONE-RWP-GI-LANPHY-100G-').pop() - 1
|
||||
|
||||
linkGridData[xAxis].out[yAxis] = {
|
||||
noData: false,
|
||||
linkId: outLink.linkId,
|
||||
@@ -137,11 +149,11 @@ export default {
|
||||
})
|
||||
|
||||
// 一行如果无数据,则删除该行,默认10*10矩阵
|
||||
const rowXIndex = 0
|
||||
this.handleXRowNoData(linkGridData, rowXIndex)
|
||||
// const rowXIndex = 0
|
||||
// this.handleXRowNoData(linkGridData, rowXIndex)
|
||||
// 一列如果无数据,则删除该列,默认10*10矩阵
|
||||
const rowYIndex = 0
|
||||
this.handleYRowNoData(linkGridData, rowYIndex)
|
||||
// const rowYIndex = 0
|
||||
// this.handleYRowNoData(linkGridData, rowYIndex)
|
||||
this.isLinkNoData = linkGridData.length === 0
|
||||
this.linkGridData = linkGridData
|
||||
}
|
||||
@@ -166,9 +178,30 @@ export default {
|
||||
|
||||
this.isNextNoData = nextLinkData.length === 0
|
||||
if (!this.isNextNoData) {
|
||||
const inLinkDirections = []
|
||||
const outLinkDirections = []
|
||||
nextLinkData.forEach(l => {
|
||||
if (inLinkDirections.indexOf(l.inLinkDirection) === -1) {
|
||||
inLinkDirections.push(l.inLinkDirection)
|
||||
}
|
||||
if (outLinkDirections.indexOf(l.outLinkDirection) === -1) {
|
||||
outLinkDirections.push(l.outLinkDirection)
|
||||
}
|
||||
})
|
||||
inLinkDirections.sort()
|
||||
outLinkDirections.sort()
|
||||
// 链路下一跳数据
|
||||
let nextGridData = []
|
||||
const nextGridTemplate = [
|
||||
const nextGridData = inLinkDirections.map(inLink => ({ nextHop: inLink }))
|
||||
nextGridData.forEach((link, index) => {
|
||||
link.out = outLinkDirections.map((outLink, index1) => {
|
||||
return {
|
||||
coordinate: `${index}-${index1}`,
|
||||
noData: true,
|
||||
nextHop: outLink
|
||||
}
|
||||
})
|
||||
})
|
||||
/*const nextGridTemplate = [
|
||||
{ linkId: 'Hundredgige2', nextHop: '太原', out: [] },
|
||||
{ linkId: 'Hundredgige1', nextHop: '西安', out: [] },
|
||||
{ linkId: 'Hundredgige4', nextHop: '西宁', out: [] }
|
||||
@@ -181,11 +214,11 @@ export default {
|
||||
link1.coordinate = `${link.linkId}-${link1.linkId}`
|
||||
delete link1.out
|
||||
})
|
||||
})
|
||||
})*/
|
||||
|
||||
nextLinkData.forEach(d => {
|
||||
const inLink = linkInfo.find(l => l.nextHop === d.inLinkDirection && l.direction === 'in')
|
||||
const outLink = linkInfo.find(l => l.nextHop === d.outLinkDirection && l.direction === 'out')
|
||||
const inLink = linkInfo.find(l => l.nextHop === d.inLinkDirection && (l.direction === 'in' || l.direction === '2'))
|
||||
const outLink = linkInfo.find(l => l.nextHop === d.outLinkDirection && (l.direction === 'out' || l.direction === '2'))
|
||||
|
||||
if (inLink && outLink) {
|
||||
// const data = nextGridData.find(g => g.linkId === inLink.linkId)
|
||||
@@ -193,10 +226,10 @@ export default {
|
||||
let outBandwidth = 0
|
||||
let inBandwidth = 0
|
||||
linkInfo.forEach((item) => {
|
||||
if (item.nextHop === d.outLinkDirection && item.direction === 'out') {
|
||||
if (item.nextHop === d.outLinkDirection && (item.direction === 'out' || item.direction === '2')) {
|
||||
outBandwidth += item.bandwidth
|
||||
}
|
||||
if (item.nextHop === d.inLinkDirection && item.direction === 'in') {
|
||||
if (item.nextHop === d.inLinkDirection && (item.direction === 'in' || item.direction === '2')) {
|
||||
inBandwidth += item.bandwidth
|
||||
}
|
||||
})
|
||||
@@ -214,15 +247,15 @@ export default {
|
||||
|
||||
d.scoreLow3 = d.score < 3 || d.score === '-'
|
||||
|
||||
const xAxis = inLink.linkId
|
||||
const yAxis = outLink.linkId
|
||||
const xAxis = inLinkDirections.indexOf(d.inLinkDirection)
|
||||
const yAxis = outLinkDirections.indexOf(d.outLinkDirection)
|
||||
nextGridData.forEach((link, index) => {
|
||||
link.out.forEach((link1, index1) => {
|
||||
if (link1.coordinate === (xAxis + '-' + yAxis)) {
|
||||
nextGridData[index].out[index1] = {
|
||||
coordinate: link1.coordinate,
|
||||
noData: false,
|
||||
linkId: outLink.linkId,
|
||||
// linkId: outLink.linkId,
|
||||
nextHop: outLink.nextHop,
|
||||
outUsage: outUsage,
|
||||
inUsage: inUsage,
|
||||
|
||||
@@ -156,7 +156,7 @@ export default {
|
||||
endTime: getSecond(this.timeFilter.endTime)
|
||||
}
|
||||
if (this.queryCondition) {
|
||||
const condition = this.queryCondition.toLowerCase().split(' or ')
|
||||
const condition = this.queryCondition.split(' or ')
|
||||
if (condition.length > 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)
|
||||
@@ -387,7 +387,7 @@ export default {
|
||||
let num = 0
|
||||
linkData.forEach(e => {
|
||||
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
|
||||
num += 1
|
||||
} else {
|
||||
@@ -397,24 +397,24 @@ export default {
|
||||
}
|
||||
}
|
||||
if (this.lineTab === e.class) {
|
||||
if (parseFloat(e.analysis.avg) <= 0) {
|
||||
if (parseFloat(e.analysis.max) <= 0) {
|
||||
this.lineTab = ''
|
||||
this.lineRefer = ''
|
||||
this.init()
|
||||
// this.init()
|
||||
}
|
||||
}
|
||||
})
|
||||
this.tabs = linkData
|
||||
// 如果三者avg都为0时,至少保证total显示
|
||||
// 如果三者max都为0时,至少保证total显示
|
||||
const ingressObj = linkData.find(d => d.name === 'linkMonitor.ingress')
|
||||
const egressObj = linkData.find(d => d.name === 'linkMonitor.egress')
|
||||
let ingressAvg = 0
|
||||
let egressAvg = 0
|
||||
if (ingressObj) {
|
||||
ingressAvg = parseFloat(ingressObj.analysis.avg) || 0
|
||||
ingressAvg = parseFloat(ingressObj.analysis.max) || 0
|
||||
}
|
||||
if (egressObj) {
|
||||
egressAvg = parseFloat(egressObj.analysis.avg) || 0
|
||||
egressAvg = parseFloat(egressObj.analysis.max) || 0
|
||||
}
|
||||
if ((ingressAvg + egressAvg) === 0) {
|
||||
const totalObj = linkData.find(d => d.name === 'network.total')
|
||||
|
||||
@@ -100,7 +100,7 @@ export default {
|
||||
}
|
||||
let url = ''
|
||||
if (this.queryCondition) {
|
||||
const condition = this.queryCondition.toLowerCase().split(' or ')
|
||||
const condition = this.queryCondition.split(' or ')
|
||||
if (condition.length > 1) {
|
||||
if (n === 0) {
|
||||
params.q = condition.find(c => c.indexOf('common_in_link_id') > -1 || c.indexOf('in_link_direction') > -1)
|
||||
|
||||
@@ -104,7 +104,7 @@ export default {
|
||||
endTime: getSecond(this.timeFilter.endTime)
|
||||
}
|
||||
if (this.queryCondition) {
|
||||
const condition = this.queryCondition.toLowerCase().split(' or ')
|
||||
const condition = this.queryCondition.split(' or ')
|
||||
if (condition.length > 1) {
|
||||
// params.outParam = true
|
||||
params.outParam = condition.find(c => c.indexOf('common_out_link_id') > -1 || c.indexOf('out_link_direction') > -1)
|
||||
|
||||
@@ -464,8 +464,7 @@ export default {
|
||||
newData.push(obj)
|
||||
})
|
||||
}
|
||||
|
||||
if (data !== undefined && data.length > 0) {
|
||||
if (data && data.length > 0) {
|
||||
newData.forEach((item) => {
|
||||
item.type = getLineType(item.type)
|
||||
if (item.type === val) {
|
||||
@@ -478,6 +477,24 @@ export default {
|
||||
})
|
||||
}
|
||||
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') {
|
||||
const tabs = _.cloneDeep(this.tabsTemplate)
|
||||
lineData.forEach((d, i) => {
|
||||
|
||||
@@ -185,6 +185,7 @@ export const stackedLineChartOption = {
|
||||
{
|
||||
type: 'time',
|
||||
splitNumber: 8,
|
||||
minInterval: 60000,
|
||||
axisLabel: {
|
||||
formatter: xAxisTimeFormatter,
|
||||
rich: xAxisTimeRich
|
||||
|
||||
@@ -185,7 +185,6 @@ export default {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
showList: false,
|
||||
listMode: 'list', // entity列表的模式,list|block
|
||||
|
||||
entityAppTotal: '-',
|
||||
@@ -213,28 +212,36 @@ export default {
|
||||
title: this.$t('entity.topCountries'),
|
||||
topColumn: 'ip.country',
|
||||
totalCount: 0,
|
||||
data: []
|
||||
data: [],
|
||||
loading: false,
|
||||
firstLoad: true
|
||||
},
|
||||
{
|
||||
icon: 'cn-icon cn-icon-city',
|
||||
title: this.$t('entity.topCities'),
|
||||
topColumn: 'ip.city',
|
||||
totalCount: 0,
|
||||
data: []
|
||||
data: [],
|
||||
loading: false,
|
||||
firstLoad: true
|
||||
},
|
||||
{
|
||||
icon: 'cn-icon cn-icon-as',
|
||||
title: this.$t('entity.topASNs'),
|
||||
topColumn: 'ip.asn',
|
||||
totalCount: 0,
|
||||
data: []
|
||||
data: [],
|
||||
loading: false,
|
||||
firstLoad: true
|
||||
},
|
||||
{
|
||||
icon: 'cn-icon cn-icon-operator',
|
||||
title: this.$t('entity.topISPs'),
|
||||
topColumn: 'ip.isp',
|
||||
totalCount: 0,
|
||||
data: []
|
||||
data: [],
|
||||
loading: false,
|
||||
firstLoad: true
|
||||
},
|
||||
{
|
||||
icon: 'cn-icon cn-icon-open-port',
|
||||
@@ -242,28 +249,36 @@ export default {
|
||||
topColumn: 'ip.port',
|
||||
topColumn1: 'ip.protocol',
|
||||
totalCount: 0,
|
||||
data: []
|
||||
data: [],
|
||||
loading: false,
|
||||
firstLoad: true
|
||||
},
|
||||
{
|
||||
icon: 'cn-icon cn-icon-FQDN',
|
||||
title: this.$t('entity.topFQDNCategories'),
|
||||
topColumn: 'domain.category',
|
||||
totalCount: 0,
|
||||
data: []
|
||||
data: [],
|
||||
loading: false,
|
||||
firstLoad: true
|
||||
},
|
||||
{
|
||||
icon: 'cn-icon cn-icon-category2',
|
||||
title: this.$t('entity.topAppCategories'),
|
||||
topColumn: 'app.category',
|
||||
totalCount: 0,
|
||||
data: []
|
||||
data: [],
|
||||
loading: false,
|
||||
firstLoad: true
|
||||
},
|
||||
{
|
||||
icon: 'cn-icon cn-icon-tag1',
|
||||
title: this.$t('entity.topTags'),
|
||||
topColumn: 'tag',
|
||||
totalCount: 0,
|
||||
data: []
|
||||
data: [],
|
||||
loading: false,
|
||||
firstLoad: true
|
||||
}
|
||||
],
|
||||
listData: [],
|
||||
@@ -396,16 +411,17 @@ export default {
|
||||
mode: mode,
|
||||
range: this.timeFilter.dateRangeValue,
|
||||
pageNo: this.pageObj.pageNo,
|
||||
pageSize: this.pageObj.pageSize
|
||||
pageSize: this.pageObj.pageSize,
|
||||
showList: true
|
||||
}
|
||||
})
|
||||
this.showList = true
|
||||
// this.showList = true
|
||||
// 跳转页面,则不执行搜索功能
|
||||
return true
|
||||
}
|
||||
|
||||
this.queryFilterNew({ q: this.q, ...this.pageObj, ...this.timeFilter })
|
||||
this.queryList({ q: this.q, ...this.pageObj, ...this.timeFilter })
|
||||
this.queryFilterNew({ q: this.q, ...this.pageObj, ...this.timeFilter })
|
||||
this.queryCount({ q: this.q, ...this.pageObj, ...this.timeFilter })
|
||||
|
||||
// 延时一秒,避免初始化时pageSize为20,pageNo为1也会调用“搜索”的情况
|
||||
@@ -489,8 +505,8 @@ export default {
|
||||
/** 新版查询filter数据 */
|
||||
queryFilterNew (params) {
|
||||
const queryParams = {
|
||||
// startTime: getSecond(params.startTime),
|
||||
// endTime: getSecond(params.endTime),
|
||||
startTime: getSecond(params.startTime),
|
||||
endTime: getSecond(params.endTime),
|
||||
resource: params.q || ''
|
||||
}
|
||||
this.loadingLeft = true
|
||||
@@ -502,8 +518,48 @@ export default {
|
||||
const aggDomain = axios.get(api.entity.entityList.aggDomain, { params: queryParams })
|
||||
const aggAppCategory = axios.get(api.entity.entityList.aggAppCategory, { params: queryParams })
|
||||
const aggTag = axios.get(api.entity.entityList.aggTag, { params: queryParams })
|
||||
|
||||
Promise.all([aggCountry, aggCity, aggIPAsn, aggIPIsp, aggPort, aggDomain, aggAppCategory, aggTag]).then(response => {
|
||||
const requests = [aggCountry, aggCity, aggIPAsn, aggIPIsp, aggPort, aggDomain, aggAppCategory, aggTag]
|
||||
requests.forEach((req, index) => {
|
||||
this.newFilterData[index].loading = true
|
||||
req.then(response => {
|
||||
if (response.status === 200 && response.data.data.list) {
|
||||
if (response.data.data.list.length >= 5) {
|
||||
this.newFilterData[index].showNum = 5
|
||||
} else {
|
||||
this.newFilterData[index].showNum = response.data.data.list.length
|
||||
}
|
||||
this.newFilterData[index].data = []
|
||||
response.data.data.list.forEach((item, i) => {
|
||||
let obj = {
|
||||
label: item.value,
|
||||
topColumn: this.newFilterData[index].topColumn,
|
||||
value: item.uniqueEntities,
|
||||
showNum: 5
|
||||
}
|
||||
if (index === 0) {
|
||||
obj.flag = item.value // 接口字段名称为'China',svg名称为'CN',通过countryNameIdMapping进行转换
|
||||
}
|
||||
if (index === 4) {
|
||||
obj = {
|
||||
topColumn: this.newFilterData[index].topColumn,
|
||||
topColumn1: this.newFilterData[index].topColumn1,
|
||||
port: item.port,
|
||||
l7Protocol: item.l7Protocol,
|
||||
value: item.uniqueEntities,
|
||||
showNum: 5
|
||||
}
|
||||
}
|
||||
this.newFilterData[index].data.push(obj)
|
||||
})
|
||||
}
|
||||
}).catch(e => {
|
||||
this.$message.error(e.response.data.message)
|
||||
}).finally(() => {
|
||||
this.newFilterData[index].loading = false
|
||||
this.newFilterData[index].firstLoad = false
|
||||
})
|
||||
})
|
||||
/*Promise.all([aggCountry, aggCity, aggIPAsn, aggIPIsp, aggPort, aggDomain, aggAppCategory, aggTag]).then(response => {
|
||||
response.forEach((item1, index) => {
|
||||
if (item1.status === 200 && item1.data.data.list) {
|
||||
if (item1.data.data.list.length >= 5) {
|
||||
@@ -540,7 +596,7 @@ export default {
|
||||
this.$message.error(e.response.data.message)
|
||||
}).finally(() => {
|
||||
this.loadingLeft = false
|
||||
})
|
||||
})*/
|
||||
},
|
||||
/** 实体列表查询 */
|
||||
queryList (params) {
|
||||
@@ -548,8 +604,8 @@ export default {
|
||||
const queryParams = {
|
||||
pageSize: params.pageSize,
|
||||
pageNo: params.pageNo,
|
||||
// startTime: getSecond(params.startTime),
|
||||
// endTime: getSecond(params.endTime),
|
||||
startTime: getSecond(params.startTime),
|
||||
endTime: getSecond(params.endTime),
|
||||
resource: params.q || ''
|
||||
}
|
||||
axios.get(api.entity.entityList.list, { params: queryParams }).then(response => {
|
||||
@@ -570,8 +626,8 @@ export default {
|
||||
queryCount (params) {
|
||||
this.loadingCount = true
|
||||
const queryParams = {
|
||||
// startTime: getSecond(params.startTime),
|
||||
// endTime: getSecond(params.endTime),
|
||||
startTime: getSecond(params.startTime),
|
||||
endTime: getSecond(params.endTime),
|
||||
resource: params.q || ''
|
||||
}
|
||||
axios.get(api.entity.entityList.summaryCount, { params: queryParams }).then(response => {
|
||||
@@ -692,19 +748,26 @@ export default {
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
if (!this.showList) {
|
||||
this.getEntityIndexData()
|
||||
} else {
|
||||
let { q, listMode } = this.$route.query
|
||||
|
||||
// 如果地址栏有listMode,即列表页,并非首页,则开始搜索
|
||||
if (listMode) {
|
||||
this.showList = true
|
||||
// %位置为0是输入中文时能解码,%20,25%分别是空格和%的情况
|
||||
if (q && (q.indexOf('%') === 0 || q.indexOf('%20') > -1 || q.indexOf('%25') > -1)) {
|
||||
q = decodeURI(q)
|
||||
}
|
||||
// %位置不为0,即内容包含非英文时
|
||||
const str1 = q.substring(q.indexOf('%'), q.indexOf('%') + 3)
|
||||
if (q && q.indexOf('%') > 0 && (str1 !== '%20' || str1 === '%25')) {
|
||||
q = decodeURI(q)
|
||||
}
|
||||
this.initSearch(q)
|
||||
this.listMode = listMode
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
timeFilter () {
|
||||
@@ -717,11 +780,12 @@ export default {
|
||||
const rangeParam = query.range
|
||||
const startTimeParam = query.startTime
|
||||
const endTimeParam = query.endTime
|
||||
const showList = ref(Boolean(query.showList))
|
||||
// 若url携带了,使用携带的值,否则使用默认值。
|
||||
const dateRangeValue = rangeParam ? parseInt(query.range) : 60
|
||||
const dateRangeValue = rangeParam ? parseInt(query.range) : 60 * 24
|
||||
const timeFilter = ref({ dateRangeValue })
|
||||
if (!startTimeParam || !endTimeParam) {
|
||||
const { startTime, endTime } = getNowTime(60)
|
||||
const { startTime, endTime } = getNowTime(60 * 24)
|
||||
timeFilter.value.startTime = startTime
|
||||
timeFilter.value.endTime = endTime
|
||||
} else {
|
||||
@@ -732,12 +796,13 @@ export default {
|
||||
pageNo: query.pageNo ? parseInt(query.pageNo) : 1,
|
||||
// 是否重置pageNo,在执行新搜索时是true
|
||||
resetPageNo: true,
|
||||
pageSize: query.pageSize ? parseInt(query.pageSize) : defaultPageSize,
|
||||
pageSize: query.pageSize ? parseInt(query.pageSize) : 10, // TODO 23-10-14 默认暂时改为10
|
||||
total: 0
|
||||
})
|
||||
return {
|
||||
timeFilter,
|
||||
pageObj
|
||||
pageObj,
|
||||
showList
|
||||
}
|
||||
},
|
||||
beforeUnmount () {
|
||||
|
||||
@@ -2,16 +2,15 @@
|
||||
<div class="entity-filter-case" style="position: relative">
|
||||
<div class="filter-case__header">{{ $t('entities.filter1') }}</div>
|
||||
|
||||
<div v-if="filterDataLength>0">
|
||||
<div v-if="filterDataLength > 0">
|
||||
<div class="entity-filter" v-for="(item, index) in myFilterData" :key="index">
|
||||
<div v-if="item.data.length>0">
|
||||
<div class="filter__header">
|
||||
<i :class="item.icon"></i>
|
||||
{{ item.title }}
|
||||
</div>
|
||||
|
||||
<div class="filter__body" style="position: relative">
|
||||
<loading :loading="loadingLeft" style="top: -5px;"></loading>
|
||||
<loading :loading="item.loading" style="top: -5px;"></loading>
|
||||
|
||||
<div class="filter__body-item"
|
||||
v-for="(data, i) in item.data.slice(0, item.showNum)"
|
||||
@@ -38,15 +37,14 @@
|
||||
</div>
|
||||
</div>
|
||||
<div @click="showMoreFilter(item, index)"
|
||||
:class="item.showNum === item.data.length ? 'filter-no-show-more' : 'filter-show-more'">
|
||||
:class="item.showNum >= item.data.length || item.data.length <= 5 ? 'filter-no-show-more' : 'filter-show-more'">
|
||||
{{ $t('entity.showMore') }}
|
||||
</div>
|
||||
<div class="filter-hr"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<loading v-else-if="isFirstLoad" :loading="isFirstLoad"></loading>
|
||||
<chart-no-data v-else style="padding-top: 40px"></chart-no-data>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -54,6 +52,7 @@
|
||||
import Loading from '@/components/common/Loading'
|
||||
import ChartNoData from '@/views/charts/charts/ChartNoData'
|
||||
import { countryNameIdMapping } from '@/utils/constants'
|
||||
import _ from 'lodash'
|
||||
export default {
|
||||
name: 'EntityFilter',
|
||||
components: { ChartNoData, Loading },
|
||||
@@ -73,6 +72,9 @@ export default {
|
||||
})
|
||||
|
||||
return length
|
||||
},
|
||||
isFirstLoad () {
|
||||
return this.myFilterData.some(d => d.firstLoad)
|
||||
}
|
||||
},
|
||||
data () {
|
||||
@@ -85,6 +87,14 @@ export default {
|
||||
mounted () {
|
||||
this.myFilterData = this.filterData
|
||||
},
|
||||
watch: {
|
||||
filterData: {
|
||||
deep: true,
|
||||
handler (n) {
|
||||
this.myFilterData = _.cloneDeep(n)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 判断文字是否溢出,超出则鼠标移入tooltip显示,否则鼠标移入不显示
|
||||
@@ -103,17 +113,14 @@ export default {
|
||||
this.$emit('filter', name, data)
|
||||
},
|
||||
showMoreFilter (item, index) {
|
||||
if ((item.data.length - item.showNum) >= 5) {
|
||||
this.myFilterData[index].showNum = item.data.length
|
||||
/*if ((item.data.length - item.showNum) >= 5) {
|
||||
item.shouNum += 5
|
||||
this.myFilterData[index].showNum += 5
|
||||
} else {
|
||||
this.myFilterData[index].showNum += (item.data.length - item.showNum)
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
||||
|
||||
@@ -38,11 +38,13 @@
|
||||
<Pagination
|
||||
ref="pagination"
|
||||
:page-obj="pageObj"
|
||||
:post-page-sizes="[10, 20, 50]"
|
||||
@pageNo='pageNo'
|
||||
@pageSize='pageSize'
|
||||
@size-change="pageSize"
|
||||
@prev-click="prev"
|
||||
@next-click="next"
|
||||
@scrollbarToTop="scrollbarToTop"
|
||||
>
|
||||
</Pagination>
|
||||
</div>
|
||||
@@ -124,6 +126,10 @@ export default {
|
||||
const container = document.getElementById('cnContainer')
|
||||
container.scrollTop += e.deltaY / 2
|
||||
}
|
||||
},
|
||||
scrollbarToTop () {
|
||||
const container = document.getElementById('cnContainer')
|
||||
container.scrollTop = 0
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-country"></i>
|
||||
<span class="row-item-label">{{ $t('overall.country') }} : </span>
|
||||
<span class="row-item-value">{{ entityData.location ? entityData.location.country : '-' }}</span>
|
||||
<span class="row-item-value">{{ $_.get(entityData, 'location.country', '-') || '-' }}</span>
|
||||
</div>
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-position"></i>
|
||||
@@ -36,36 +36,36 @@
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-cloud"></i>
|
||||
<span class="row-item-label">{{ $t('entities.asn') }} : </span>
|
||||
<span class="row-item-value">{{ entityData.asn ? entityData.asn.asn : '-' }}</span>
|
||||
<span class="row-item-value">{{ $_.get(entityData, 'asn.asn', '-') || '-' }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="entityData.entityType === 'domain'">
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-category-group"></i>
|
||||
<span class="row-item-label">{{ $t('entities.category') }} : </span>
|
||||
<span class="row-item-value">{{ entityData.category ? entityData.category.categoryGroup : '-' }}</span>
|
||||
<span class="row-item-value">{{ $_.get(entityData, 'category.categoryGroup', '-') || '-' }}</span>
|
||||
</div>
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-sub-category"></i>
|
||||
<span class="row-item-label">{{ $t('entities.subcategory') }} : </span>
|
||||
<span class="row-item-value">{{ entityData.category ? entityData.category.categoryName : '-' }}</span>
|
||||
<span class="row-item-value">{{ $_.get(entityData, 'category.categoryName', '-') || '-' }}</span>
|
||||
</div>
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-credit-rating"></i>
|
||||
<span class="row-item-label">{{ $t('entities.reputationLevel') }} : </span>
|
||||
<span class="row-item-value">{{ entityData.category ? entityData.category.reputationLevel : '-' }}</span>
|
||||
<span class="row-item-value">{{ $_.get(entityData, 'category.reputationLevel', '-') || '-' }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="entityData.entityType === 'app'">
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-category2"></i>
|
||||
<span class="row-item-label">{{ $t('entities.category') }} : </span>
|
||||
<span class="row-item-value">{{ entityData.category ? entityData.category.appCategory : '-' }}</span>
|
||||
<span class="row-item-value">{{ $_.get(entityData, 'category.appCategory', '-') || '-' }}</span>
|
||||
</div>
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-sub-category"></i>
|
||||
<span class="row-item-label">{{ $t('entities.subcategory') }} : </span>
|
||||
<span class="row-item-value">{{ entityData.category ? entityData.category.appSubcategory : '-' }}</span>
|
||||
<span class="row-item-value">{{ $_.get(entityData, 'category.appSubcategory', '-') || '-' }}</span>
|
||||
</div>
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-credit-rating"></i>
|
||||
@@ -258,7 +258,7 @@ export default {
|
||||
}
|
||||
axios.get(`${url}?resource=${this.entity.entityValue}`).then(response => {
|
||||
this.$nextTick(() => {
|
||||
this.entityData = { ...response.data.data, ...this.entity }
|
||||
this.entityData = { ...this.entityData, ...response.data.data, ...this.entity }
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const path = require('path')
|
||||
const webpack = require('webpack')
|
||||
function resolve (dir) {
|
||||
return path.join(__dirname, dir)
|
||||
}
|
||||
@@ -15,6 +16,9 @@ module.exports = {
|
||||
chainWebpack: (config) => {
|
||||
config.resolve.alias // 路径别名
|
||||
.set('@', resolve('./src'))
|
||||
config.plugin('webpack.DefinePlugin').use(new webpack.DefinePlugin({
|
||||
__INTLIFY_PROD_DEVTOOLS__: JSON.stringify(false)
|
||||
}))
|
||||
},
|
||||
lintOnSave: true,
|
||||
devServer: {
|
||||
|
||||
Reference in New Issue
Block a user