diff --git a/nezha-fronted/src/components/common/language/cn.js b/nezha-fronted/src/components/common/language/cn.js index c1d97c780..61db523e4 100644 --- a/nezha-fronted/src/components/common/language/cn.js +++ b/nezha-fronted/src/components/common/language/cn.js @@ -277,6 +277,7 @@ const cn = { title: "系统总览", contentTitle: "Nezha 管理系统", traffic: '流量', + projectTopoLogy:"系统拓扑", asset: { title: "资产", assetType: "资产类型统计", diff --git a/nezha-fronted/src/components/common/language/en.js b/nezha-fronted/src/components/common/language/en.js index d30155736..7f91f7c28 100644 --- a/nezha-fronted/src/components/common/language/en.js +++ b/nezha-fronted/src/components/common/language/en.js @@ -282,6 +282,7 @@ const en = { title:'Overview', contentTitle:'Nezha Management System', traffic: 'Traffic', + projectTopoLogy:"Project TopoLogy", asset:{ title:'Assets', assetType:'Asset type', diff --git a/nezha-fronted/src/components/common/project/overViewTopology.vue b/nezha-fronted/src/components/common/project/overViewTopology.vue new file mode 100644 index 000000000..20ccab8b5 --- /dev/null +++ b/nezha-fronted/src/components/common/project/overViewTopology.vue @@ -0,0 +1,1187 @@ + + + + + diff --git a/nezha-fronted/src/components/page/dashboard/overview/overview2.vue b/nezha-fronted/src/components/page/dashboard/overview/overview2.vue index eaa5fe1be..9f8f0af3e 100644 --- a/nezha-fronted/src/components/page/dashboard/overview/overview2.vue +++ b/nezha-fronted/src/components/page/dashboard/overview/overview2.vue @@ -87,29 +87,44 @@
- {{$t("dashboard.overview.traffic")}} - - - -
- {{$t("dashboard.overview.dataCenter.dataCenter")}} - -
- -
-
+ {{$t("dashboard.overview.projectTopoLogy")}} + + + + + + + + + + + + + + + + + +
-
- -
No Data
+
+ +
+ + + +
+ {{item.name}} + +
+
+
+
+
No Data
@@ -203,9 +218,12 @@ import iconShadow from 'leaflet/dist/images/marker-shadow.png'; import echarts from "echarts"; import chartConfig from './chartConfig' + import overViewTopology from '../../../common/project/overViewTopology' var timeout; //第三行第三个图的dropdown下拉菜单timeout + + var tooltipEndpointChart; var tooltipPrometheusChart; var regNum = /^[0-9]+.?[0-9]*/ @@ -214,7 +232,8 @@ components:{ 'chart-box': chart, 'time-picker': timePicker, - 'vue-countup': VueCountUp + 'vue-countup': VueCountUp, + 'topology':overViewTopology }, data() { return { @@ -224,7 +243,7 @@ sysDate: '', sysWeek: '', systemName: localStorage.getItem('nz-sys-name'), - + topologyLoading:true, //data assetLoading: false, assetTypeLoading: false, //第三行第一个图 @@ -254,7 +273,7 @@ trafficDatacenterData: [], trafficTagData: [], trafficData: [], - + allProject:[], trendSearchParam: {start: '', end: '', dc: [], tag: [], select: [], watch: true}, alertMessageShow: 'asset', //asset/module @@ -324,11 +343,12 @@ this.queryEndpointData(), this.queryAlertMessageData(), this.queryAlertRuleData(), - this.queryAlertTrendData(), + // this.queryAlertTrendData(), this.initMap(), this.queryAlertStatByRule(), this.queryAlertStatByAsset(), - this.getDcTrafficData() + this.getDcTrafficData(), + this.queryAllProjectData(), ] }, setFreshDataTimer:function(){ @@ -359,6 +379,90 @@ }) }) }, + queryAllProjectData(){ + this.$get('/project',{pageSize:-1}).then(res=>{ + this.topologyLoading=true; + let axiosAll=[]; + let promiseArr=[]; + let temp=[]; + if(res.data.list.length===0){ + this.topologyLoading=false; + } + res.data.list.forEach((item)=>{ + axiosAll.push(axios.get(`/project/topo?projectId=${item.id}`)) + }); + axios.all(axiosAll).then(res2=>{ + res2=res2.map((item,index)=>{ + return {...item.data.data,...res.data.list[index]} + }) + res2=res2.filter((item)=>item.topo&&(item.topo.nodes.length ||item.topo.lines.length)); + if(res2.length==0){ + this.topologyLoading=false; + } + res2.forEach(item=>{ + promiseArr.push(this.formatNodesArr(item.topo.nodes)); + item.edgesArray=this.formatEdgesArr(item.topo.lines); + temp.push(item) + }); + Promise.all(promiseArr).then(res=>{ + temp.forEach((item,index)=>{ + item.nodesArray=res[index] + }); + this.allProject=temp; + this.topologyLoading=false; + }); + }) + }) + }, + + formatNodesArr(arr){ + return new Promise(resolve=>{ + let promiseArr=[]; + arr.forEach((item,index)=>{ + item.shape='image'; + item.id=item.moduleId; + this.$get('/module/stat',{id:item.id}).then(res=>{ + item.state=res.data; + }); + promiseArr.push( this.dealImg(`/project/topo/icon/${item.iconId}`)) + }); + Promise.all(promiseArr).then(res=>{ + arr.forEach((item,index)=>{ + item.image=res[index] + }) + resolve(arr) + }); + }) + }, + formatEdgesArr(arr){ + arr.forEach((item)=>{ + item.from=item.source; + item.to=item.target; + item.label=''; + item.title='title'; + item.smooth.roundness=0.4; + }); + return arr + }, + dealImg(url) { + // 处理后端传过来的图片流乱码问题 + if (url) { + return new Promise((resolve)=>{ + this.$axios + .get(url, { + responseType: "arraybuffer" + }) + .then(res => { + return ("data:image/jpeg;base64," +btoa(new Uint8Array(res.data).reduce((data, byte) => data + String.fromCharCode(byte), ""))); + }) + .then(data => { + resolve(data) + }) + .catch(err => { + }); + }) + } + }, queryAssetData() { return new Promise(resolve => { this.assetLoading = true; @@ -1530,6 +1634,45 @@ .leaflet-bottom{ z-index: 409; } + .el-carousel--horizontal{ + height: 100%; + } + .el-carousel__container{ + height: calc(100% - 36px); + } + .el-carousel__item .project-name { + font-size: 18px; + margin: 0; + position: absolute; + } + + .el-carousel__item:nth-child(2n) { + /*background-color: #99a9bf;*/ + } + + .el-carousel__item:nth-child(2n+1) { + /*background-color: #d3dce6;*/ + }