Authored by qinchao

主机拓扑

... ... @@ -56,40 +56,61 @@ public class HostInfoCtrl {
//初始化数据
Map<String,List<HostGroup>> initDataMap = tmpConstructData();
getJsonAntvData(initDataMap,true, mv);
getJsonAntvData(initDataMap,6, mv);
return mv;
}
private void getJsonAntvData(Map<String,List<HostGroup>> initDataMap,boolean setXyFlag,ModelAndView mv){
//numInRow 第二层的节点一排放几个
private void getJsonAntvData(Map<String,List<HostGroup>> initDataMap,int numInRow,ModelAndView mv){
int beginx=60;
int beginy=60;
int gap_h=100;
int gap_x=300;
int intval=140;
int gap_level_top_h=100;
int gap_h=50;
List<AntvNode> nodes=new ArrayList<>();
List<Map<String,String>> edges=new ArrayList<>();
int count=0;
int maxSize=0;
int last_y=0;
for (Map.Entry<String, List<HostGroup>> entry : initDataMap.entrySet()) {
String topNode = entry.getKey();
AntvNode node=new AntvNode();
node.setLevel(0);
node.setId(topNode);
node.setLabel(topNode);
node.setShape("rect");
if(setXyFlag){
node.setX(beginx+(count*gap_x));
node.setY(beginy);
AntvNode nodeLevelTop=new AntvNode();
nodeLevelTop.setLevel(0);
nodeLevelTop.setId(topNode);
nodeLevelTop.setLabel(topNode);
nodeLevelTop.setShape("rect");
int top_node_x=beginx;
int top_node_y;
if(maxSize==0){
top_node_y=beginy;
}else{
top_node_y=last_y+gap_level_top_h;
}
nodes.add(node);
int secondCount=1;
nodeLevelTop.setX(top_node_x);
nodeLevelTop.setY(top_node_y);
nodes.add(nodeLevelTop);
last_y= nodeLevelTop.getY();
maxSize++;
List<HostGroup> ls=entry.getValue();
if(ls.size()>maxSize){
maxSize = ls.size();
if(ls==null||ls.size()<=0){
nodeLevelTop.setLevel(1);
continue;
}else{
double d=ls.size()*1.0/numInRow;
maxSize +=(int)Math.ceil(d);
}
int secondCount=1;
int row=1;
int GAP_BETWEEN_NODE_X=120;
for(HostGroup secondeNode:ls){
String sndNodeID=""+secondeNode.getId();
AntvNode nodeSnd=new AntvNode();
... ... @@ -97,22 +118,29 @@ public class HostInfoCtrl {
nodeSnd.setId(sndNodeID);
nodeSnd.setLabel(secondeNode.getGroupName());
nodeSnd.setShape("rect");
if(setXyFlag){
nodeSnd.setX(beginx+(count*gap_x)+intval);
nodeSnd.setY(beginy+secondCount*gap_h);
}
nodeSnd.setX(top_node_x+row*GAP_BETWEEN_NODE_X);
nodeSnd.setY(top_node_y+secondCount*gap_h);
nodes.add(nodeSnd);
last_y=nodeSnd.getY();
secondCount++;
//连线
Map<String,String> edgeMap=new HashMap<>();
edgeMap.put("source",topNode);
edgeMap.put("target",sndNodeID);
edges.add(edgeMap);
//第二行,不再加连接线
if(secondCount==1){
Map<String,String> edgeMap=new HashMap<>();
edgeMap.put("source",topNode);
edgeMap.put("target",sndNodeID);
edges.add(edgeMap);
}
if(row<numInRow){
row++;
}else{
row = 1;
secondCount++;
}
}
count++;
}
AntvData data=new AntvData();
... ... @@ -122,7 +150,7 @@ public class HostInfoCtrl {
String jsonString=gson.toJson( data,AntvData.class);
mv.addObject("antvData",jsonString);
mv.addObject("antvHeight",100*(maxSize+1));
mv.addObject("antvHeight",last_y+100);
}
@RequestMapping("/toHostTopoSub")
... ... @@ -132,11 +160,9 @@ public class HostInfoCtrl {
//获取子节点(有可能不存在),比如前台-gateway ,有可能存在,前台-service
String parentLabel="前台";
int number=(int)(Math.random()*10);//[0,10]
boolean subNodeFlag=false;
String currentLabel="gateway";
number=2;
if(number%2==0){
if(id!=null&&!id.endsWith("1")){
subNodeFlag=true;
currentLabel="service";
}
... ... @@ -144,7 +170,7 @@ public class HostInfoCtrl {
Map<String,List<HostGroup>> initDataMap =new LinkedHashMap<>();
initDataMap.put(currentLabel,tmpDetailData(subNodeFlag));
getJsonAntvData(initDataMap,false, mv);
getJsonAntvData(initDataMap,3, mv);
mv.addObject("parentLabel",parentLabel);
return mv;
... ...
... ... @@ -10,4 +10,5 @@ public class AntvNode {
private String label;
private String id;
private int level;
private int[] size={100,30};
}
... ...
... ... @@ -30,16 +30,39 @@
class="icon-home"></i> Home</a> <a href="#" class="current">主机拓扑图</a>
</div>
<div class="container-fluid">
<div class="widget-box">
<div class="widget-title">
<h5>主机管理-主机拓扑图:${parentLabel}</h5>
<div class="widget-box" style="min-height: 600px;">
<div id="hostListTopoDiv" style="width:600px;float:left">
</div>
<div class="widget-content nopadding">
<div class="panel-body" id="hostListTopoDiv">
<div class="widget-content nopadding" style="margin-left: 600px;border-left: 1px solid #E5E5E5;">
<div class="panel-body">
<div>
<div class="form-inline" role="form"
style="float: left;">
<div class="input-group" style="float: left;">
<span class="input-group-addon">云可用区:</span>
<select id="cloudDetailType" name="cloudDetailType" class="form-control">
<option value="0">全部</option>
<%--<option value="1">AWS</option>--%>
<option value="21">腾讯云</option>
<option value="22">腾讯云az2</option>
<option value="23">腾讯云az3</option>
<%--<option value="3">其他</option>--%>
</select>
</div>
<button class="btn btn-primary" style="margin-left: 18px;" onclick="queryHost()">搜索</button>
</div>
<div id="hostInfoTable" style="margin-top:2px;float: left;min-height: 500px;">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
<script src="<%=basePath %>script/common/genarate_left_panel.js?v=<%=ProjectConstant.MENU_VERSION %>"></script>
... ... @@ -50,7 +73,6 @@
<script type="text/javascript">
// 第一步:获取数据
var data=${antvData};
console.log(data);
// 第二步:注册图形
G6.registNode('rect', {
// 设置锚点
... ... @@ -62,12 +84,15 @@
}
});
var nodes = data.nodes;
var edges = data.edges;
/* for(var i=0;i<nodes.length;i++){
nodes[i].size=[100,30];
}*/
var edges = [];//data.edges;
// 第三步:进行布局
var Layout = G6.Layout;
/*var Layout = G6.Layout;
var margin = 60;
var height = 800 - 2 * margin;
var height = 1000 - 2 * margin;
var width = 500 - 2 * margin;
var layout = new Layout.Flow({
... ... @@ -83,13 +108,12 @@
node.y = x;
});
console.log(nodes);
console.log(nodes);*/
// 第四步:初始化图
var net = new G6.Net({
fitView: 'autoZoom' ,// 自动缩放
// fitView: 'autoZoom' // 自动缩放
height: ${antvHeight}, // 此处替换高度
behaviourFilter: ['wheelZoom', 'dragNode','dragBlank', 'dragCanvas'],
//height: ${antvHeight}, // 此处替换高度
// width:1000,
id: "hostListTopoDiv" // 此处替换容器id
});
// 第五步:载入数据
... ... @@ -119,4 +143,117 @@
// 第八步:渲染关系图
net.render();
//dblclick
var checkStyle = {
fill:"#FF0000",
lineWidth: 2
};
var normalStyle = {
fill:"#00A263",
lineWidth: 1
};
var page_selected_node=[];
net.on('click', function(ev){
if(ev.itemType !== 'node'){
return;
}
var model=ev.item.getModel();
if(model.level==0){
return ;
}
var changeStyle={};
if(model.checked){
model.checked=false;
changeStyle =normalStyle;
for(var arri=0;arri<page_selected_node.length;arri++){
if(page_selected_node[arri].id==model.id){
page_selected_node.splice(arri,1);
break;
}
}
}else{
model.checked=true;
changeStyle = checkStyle;
page_selected_node.push(model);
}
var keyShape = ev.item.getKeyShape();
keyShape.attr(changeStyle);
net.refresh();
});
$(function () {
//加载表格
$("#hostInfoTable").table({
columnAutoWidth : false,
striped : true,
title : "主机信息列表",
dataType : "json",
pagination : true,
pageSize : 10,
loadFilter : function(data) {
return defaultLoadFilter(data);
},
columns : [
{
title: 'NO',
width : "40px",
formatter: function (value, row, index) {
return index+1;
}
},
{
title : "IP",
field : "hostIp",
width : "30%"
}, {
title : "云可用区",
field : "cloudDetailType",
formatter : function(value, rowData, rowIndex) {
if(value == 1){
return 'AWS';
} else if(value == 21){
return '腾讯云';
}else if(value == 22){
return '腾讯云az2';
}else if(value == 23){
return '腾讯云az3';
}else{
return value;
}
},
width : "20%"
}, {
title : "标签",
field : "tags",
formatter : function(value, rowData, rowIndex) {
if(value != null && value != ""){
return value.substr(0,value.length-1);
}
}
}]
});
});
function queryHost() {
console.log(page_selected_node);
var opt = $("#hostInfoTable").data("table");
opt.url=contextPath +"hostInfoList/getHostInfos";
var cloudDetailType = $("#cloudDetailType").val();
var param={
'cloudDetailType': cloudDetailType,
tags:'["upstream-switch"]'
};
$("#hostInfoTable").table("load",param);
}
</script>
... ...
... ... @@ -50,18 +50,20 @@
<script type="text/javascript">
// 第一步:获取数据
var data=${antvData};
console.log(data);
// 第二步:注册图形
G6.registNode('rect', {
// 设置锚点
getAnchorPoints: function(){
return [
[0.5, 1], // 右边边的中点
[0, 0.5] // 左边边的中点
[1, 0.1], // 右边边的中点
[0.5, 0] // 左边边的中点
];
}
});
var nodes = data.nodes;
/*for(var i=0;i<nodes.length;i++){
nodes[i].size=[100,30];
}*/
var edges = data.edges;
// 第三步:进行布局
... ... @@ -88,14 +90,14 @@
console.log(node.x,node.y);
});*/
});
console.log(nodes);
console.log(nodes);*/
// 第四步:初始化图
var net = new G6.Net({
// fitView: 'autoZoom' // 自动缩放
behaviourFilter: ['wheelZoom', 'dragNode','dragBlank', 'dragCanvas'],
fitView: 'autoZoom' ,// 自动缩放
height: ${antvHeight}, // 此处替换高度
behaviourFilter: ['wheelZoom', 'dragNode','dragBlank', 'dragCanvas'],
// width:1000,
id: "hostListTopoDiv" // 此处替换容器id
});
... ... @@ -115,10 +117,12 @@
return attrs;
});
net.edge()
.shape('VH')
.shape('HV')
.style({
stroke: "#00A263",
stroke: "#CCC",
strokeOpacity: 0.6,
//lineWidth:1,
// lineDash:[5,5],
arrow: true
});
// 第七步:添加图例
... ...