Showing
4 changed files
with
220 additions
and
52 deletions
@@ -56,40 +56,61 @@ public class HostInfoCtrl { | @@ -56,40 +56,61 @@ public class HostInfoCtrl { | ||
56 | //初始化数据 | 56 | //初始化数据 |
57 | Map<String,List<HostGroup>> initDataMap = tmpConstructData(); | 57 | Map<String,List<HostGroup>> initDataMap = tmpConstructData(); |
58 | 58 | ||
59 | - getJsonAntvData(initDataMap,true, mv); | 59 | + getJsonAntvData(initDataMap,6, mv); |
60 | 60 | ||
61 | return mv; | 61 | return mv; |
62 | } | 62 | } |
63 | 63 | ||
64 | - private void getJsonAntvData(Map<String,List<HostGroup>> initDataMap,boolean setXyFlag,ModelAndView mv){ | 64 | + //numInRow 第二层的节点一排放几个 |
65 | + private void getJsonAntvData(Map<String,List<HostGroup>> initDataMap,int numInRow,ModelAndView mv){ | ||
65 | int beginx=60; | 66 | int beginx=60; |
66 | int beginy=60; | 67 | int beginy=60; |
67 | - int gap_h=100; | ||
68 | - int gap_x=300; | ||
69 | - int intval=140; | 68 | + |
69 | + int gap_level_top_h=100; | ||
70 | + int gap_h=50; | ||
71 | + | ||
70 | List<AntvNode> nodes=new ArrayList<>(); | 72 | List<AntvNode> nodes=new ArrayList<>(); |
71 | List<Map<String,String>> edges=new ArrayList<>(); | 73 | List<Map<String,String>> edges=new ArrayList<>(); |
72 | 74 | ||
73 | - int count=0; | ||
74 | int maxSize=0; | 75 | int maxSize=0; |
76 | + int last_y=0; | ||
75 | for (Map.Entry<String, List<HostGroup>> entry : initDataMap.entrySet()) { | 77 | for (Map.Entry<String, List<HostGroup>> entry : initDataMap.entrySet()) { |
76 | String topNode = entry.getKey(); | 78 | String topNode = entry.getKey(); |
77 | - AntvNode node=new AntvNode(); | ||
78 | - node.setLevel(0); | ||
79 | - node.setId(topNode); | ||
80 | - node.setLabel(topNode); | ||
81 | - node.setShape("rect"); | ||
82 | - if(setXyFlag){ | ||
83 | - node.setX(beginx+(count*gap_x)); | ||
84 | - node.setY(beginy); | 79 | + AntvNode nodeLevelTop=new AntvNode(); |
80 | + nodeLevelTop.setLevel(0); | ||
81 | + nodeLevelTop.setId(topNode); | ||
82 | + nodeLevelTop.setLabel(topNode); | ||
83 | + nodeLevelTop.setShape("rect"); | ||
84 | + | ||
85 | + int top_node_x=beginx; | ||
86 | + int top_node_y; | ||
87 | + if(maxSize==0){ | ||
88 | + top_node_y=beginy; | ||
89 | + }else{ | ||
90 | + top_node_y=last_y+gap_level_top_h; | ||
85 | } | 91 | } |
86 | 92 | ||
87 | - nodes.add(node); | ||
88 | - int secondCount=1; | 93 | + nodeLevelTop.setX(top_node_x); |
94 | + nodeLevelTop.setY(top_node_y); | ||
95 | + nodes.add(nodeLevelTop); | ||
96 | + last_y= nodeLevelTop.getY(); | ||
97 | + | ||
98 | + maxSize++; | ||
99 | + | ||
89 | List<HostGroup> ls=entry.getValue(); | 100 | List<HostGroup> ls=entry.getValue(); |
90 | - if(ls.size()>maxSize){ | ||
91 | - maxSize = ls.size(); | 101 | + if(ls==null||ls.size()<=0){ |
102 | + nodeLevelTop.setLevel(1); | ||
103 | + | ||
104 | + continue; | ||
105 | + }else{ | ||
106 | + double d=ls.size()*1.0/numInRow; | ||
107 | + maxSize +=(int)Math.ceil(d); | ||
92 | } | 108 | } |
109 | + | ||
110 | + | ||
111 | + int secondCount=1; | ||
112 | + int row=1; | ||
113 | + int GAP_BETWEEN_NODE_X=120; | ||
93 | for(HostGroup secondeNode:ls){ | 114 | for(HostGroup secondeNode:ls){ |
94 | String sndNodeID=""+secondeNode.getId(); | 115 | String sndNodeID=""+secondeNode.getId(); |
95 | AntvNode nodeSnd=new AntvNode(); | 116 | AntvNode nodeSnd=new AntvNode(); |
@@ -97,22 +118,29 @@ public class HostInfoCtrl { | @@ -97,22 +118,29 @@ public class HostInfoCtrl { | ||
97 | nodeSnd.setId(sndNodeID); | 118 | nodeSnd.setId(sndNodeID); |
98 | nodeSnd.setLabel(secondeNode.getGroupName()); | 119 | nodeSnd.setLabel(secondeNode.getGroupName()); |
99 | nodeSnd.setShape("rect"); | 120 | nodeSnd.setShape("rect"); |
100 | - if(setXyFlag){ | ||
101 | - nodeSnd.setX(beginx+(count*gap_x)+intval); | ||
102 | - nodeSnd.setY(beginy+secondCount*gap_h); | ||
103 | - } | ||
104 | - | 121 | + nodeSnd.setX(top_node_x+row*GAP_BETWEEN_NODE_X); |
122 | + nodeSnd.setY(top_node_y+secondCount*gap_h); | ||
105 | nodes.add(nodeSnd); | 123 | nodes.add(nodeSnd); |
124 | + last_y=nodeSnd.getY(); | ||
106 | 125 | ||
107 | - secondCount++; | ||
108 | //连线 | 126 | //连线 |
127 | + //第二行,不再加连接线 | ||
128 | + if(secondCount==1){ | ||
109 | Map<String,String> edgeMap=new HashMap<>(); | 129 | Map<String,String> edgeMap=new HashMap<>(); |
110 | edgeMap.put("source",topNode); | 130 | edgeMap.put("source",topNode); |
111 | edgeMap.put("target",sndNodeID); | 131 | edgeMap.put("target",sndNodeID); |
112 | edges.add(edgeMap); | 132 | edges.add(edgeMap); |
133 | + } | ||
134 | + | ||
135 | + | ||
136 | + if(row<numInRow){ | ||
137 | + row++; | ||
138 | + }else{ | ||
139 | + row = 1; | ||
140 | + secondCount++; | ||
141 | + } | ||
113 | 142 | ||
114 | } | 143 | } |
115 | - count++; | ||
116 | } | 144 | } |
117 | 145 | ||
118 | AntvData data=new AntvData(); | 146 | AntvData data=new AntvData(); |
@@ -122,7 +150,7 @@ public class HostInfoCtrl { | @@ -122,7 +150,7 @@ public class HostInfoCtrl { | ||
122 | String jsonString=gson.toJson( data,AntvData.class); | 150 | String jsonString=gson.toJson( data,AntvData.class); |
123 | 151 | ||
124 | mv.addObject("antvData",jsonString); | 152 | mv.addObject("antvData",jsonString); |
125 | - mv.addObject("antvHeight",100*(maxSize+1)); | 153 | + mv.addObject("antvHeight",last_y+100); |
126 | } | 154 | } |
127 | 155 | ||
128 | @RequestMapping("/toHostTopoSub") | 156 | @RequestMapping("/toHostTopoSub") |
@@ -132,11 +160,9 @@ public class HostInfoCtrl { | @@ -132,11 +160,9 @@ public class HostInfoCtrl { | ||
132 | 160 | ||
133 | //获取子节点(有可能不存在),比如前台-gateway ,有可能存在,前台-service | 161 | //获取子节点(有可能不存在),比如前台-gateway ,有可能存在,前台-service |
134 | String parentLabel="前台"; | 162 | String parentLabel="前台"; |
135 | - int number=(int)(Math.random()*10);//[0,10] | ||
136 | boolean subNodeFlag=false; | 163 | boolean subNodeFlag=false; |
137 | String currentLabel="gateway"; | 164 | String currentLabel="gateway"; |
138 | - number=2; | ||
139 | - if(number%2==0){ | 165 | + if(id!=null&&!id.endsWith("1")){ |
140 | subNodeFlag=true; | 166 | subNodeFlag=true; |
141 | currentLabel="service"; | 167 | currentLabel="service"; |
142 | } | 168 | } |
@@ -144,7 +170,7 @@ public class HostInfoCtrl { | @@ -144,7 +170,7 @@ public class HostInfoCtrl { | ||
144 | Map<String,List<HostGroup>> initDataMap =new LinkedHashMap<>(); | 170 | Map<String,List<HostGroup>> initDataMap =new LinkedHashMap<>(); |
145 | initDataMap.put(currentLabel,tmpDetailData(subNodeFlag)); | 171 | initDataMap.put(currentLabel,tmpDetailData(subNodeFlag)); |
146 | 172 | ||
147 | - getJsonAntvData(initDataMap,false, mv); | 173 | + getJsonAntvData(initDataMap,3, mv); |
148 | 174 | ||
149 | mv.addObject("parentLabel",parentLabel); | 175 | mv.addObject("parentLabel",parentLabel); |
150 | return mv; | 176 | return mv; |
@@ -30,12 +30,35 @@ | @@ -30,12 +30,35 @@ | ||
30 | class="icon-home"></i> Home</a> <a href="#" class="current">主机拓扑图</a> | 30 | class="icon-home"></i> Home</a> <a href="#" class="current">主机拓扑图</a> |
31 | </div> | 31 | </div> |
32 | <div class="container-fluid"> | 32 | <div class="container-fluid"> |
33 | - <div class="widget-box"> | ||
34 | - <div class="widget-title"> | ||
35 | - <h5>主机管理-主机拓扑图:${parentLabel}</h5> | 33 | + |
34 | + <div class="widget-box" style="min-height: 600px;"> | ||
35 | + <div id="hostListTopoDiv" style="width:600px;float:left"> | ||
36 | + | ||
37 | + </div> | ||
38 | + <div class="widget-content nopadding" style="margin-left: 600px;border-left: 1px solid #E5E5E5;"> | ||
39 | + <div class="panel-body"> | ||
40 | + | ||
41 | + <div> | ||
42 | + <div class="form-inline" role="form" | ||
43 | + style="float: left;"> | ||
44 | + <div class="input-group" style="float: left;"> | ||
45 | + <span class="input-group-addon">云可用区:</span> | ||
46 | + <select id="cloudDetailType" name="cloudDetailType" class="form-control"> | ||
47 | + <option value="0">全部</option> | ||
48 | + <%--<option value="1">AWS</option>--%> | ||
49 | + <option value="21">腾讯云</option> | ||
50 | + <option value="22">腾讯云az2</option> | ||
51 | + <option value="23">腾讯云az3</option> | ||
52 | + <%--<option value="3">其他</option>--%> | ||
53 | + </select> | ||
54 | + </div> | ||
55 | + <button class="btn btn-primary" style="margin-left: 18px;" onclick="queryHost()">搜索</button> | ||
36 | </div> | 56 | </div> |
37 | - <div class="widget-content nopadding"> | ||
38 | - <div class="panel-body" id="hostListTopoDiv"> | 57 | + <div id="hostInfoTable" style="margin-top:2px;float: left;min-height: 500px;"> |
58 | + | ||
59 | + </div> | ||
60 | + </div> | ||
61 | + | ||
39 | </div> | 62 | </div> |
40 | </div> | 63 | </div> |
41 | </div> | 64 | </div> |
@@ -50,7 +73,6 @@ | @@ -50,7 +73,6 @@ | ||
50 | <script type="text/javascript"> | 73 | <script type="text/javascript"> |
51 | // 第一步:获取数据 | 74 | // 第一步:获取数据 |
52 | var data=${antvData}; | 75 | var data=${antvData}; |
53 | - console.log(data); | ||
54 | // 第二步:注册图形 | 76 | // 第二步:注册图形 |
55 | G6.registNode('rect', { | 77 | G6.registNode('rect', { |
56 | // 设置锚点 | 78 | // 设置锚点 |
@@ -62,12 +84,15 @@ | @@ -62,12 +84,15 @@ | ||
62 | } | 84 | } |
63 | }); | 85 | }); |
64 | var nodes = data.nodes; | 86 | var nodes = data.nodes; |
65 | - var edges = data.edges; | 87 | + /* for(var i=0;i<nodes.length;i++){ |
88 | + nodes[i].size=[100,30]; | ||
89 | + }*/ | ||
90 | + var edges = [];//data.edges; | ||
66 | 91 | ||
67 | // 第三步:进行布局 | 92 | // 第三步:进行布局 |
68 | - var Layout = G6.Layout; | 93 | + /*var Layout = G6.Layout; |
69 | var margin = 60; | 94 | var margin = 60; |
70 | - var height = 800 - 2 * margin; | 95 | + var height = 1000 - 2 * margin; |
71 | var width = 500 - 2 * margin; | 96 | var width = 500 - 2 * margin; |
72 | 97 | ||
73 | var layout = new Layout.Flow({ | 98 | var layout = new Layout.Flow({ |
@@ -83,13 +108,12 @@ | @@ -83,13 +108,12 @@ | ||
83 | node.y = x; | 108 | node.y = x; |
84 | }); | 109 | }); |
85 | 110 | ||
86 | - console.log(nodes); | 111 | + console.log(nodes);*/ |
87 | // 第四步:初始化图 | 112 | // 第四步:初始化图 |
88 | var net = new G6.Net({ | 113 | var net = new G6.Net({ |
89 | - fitView: 'autoZoom' ,// 自动缩放 | 114 | + // fitView: 'autoZoom' // 自动缩放 |
115 | + height: ${antvHeight}, // 此处替换高度 | ||
90 | behaviourFilter: ['wheelZoom', 'dragNode','dragBlank', 'dragCanvas'], | 116 | behaviourFilter: ['wheelZoom', 'dragNode','dragBlank', 'dragCanvas'], |
91 | - //height: ${antvHeight}, // 此处替换高度 | ||
92 | - // width:1000, | ||
93 | id: "hostListTopoDiv" // 此处替换容器id | 117 | id: "hostListTopoDiv" // 此处替换容器id |
94 | }); | 118 | }); |
95 | // 第五步:载入数据 | 119 | // 第五步:载入数据 |
@@ -119,4 +143,117 @@ | @@ -119,4 +143,117 @@ | ||
119 | // 第八步:渲染关系图 | 143 | // 第八步:渲染关系图 |
120 | net.render(); | 144 | net.render(); |
121 | 145 | ||
146 | + //dblclick | ||
147 | + var checkStyle = { | ||
148 | + fill:"#FF0000", | ||
149 | + lineWidth: 2 | ||
150 | + }; | ||
151 | + var normalStyle = { | ||
152 | + fill:"#00A263", | ||
153 | + lineWidth: 1 | ||
154 | + }; | ||
155 | + | ||
156 | + var page_selected_node=[]; | ||
157 | + net.on('click', function(ev){ | ||
158 | + if(ev.itemType !== 'node'){ | ||
159 | + return; | ||
160 | + } | ||
161 | + var model=ev.item.getModel(); | ||
162 | + if(model.level==0){ | ||
163 | + return ; | ||
164 | + } | ||
165 | + | ||
166 | + var changeStyle={}; | ||
167 | + if(model.checked){ | ||
168 | + model.checked=false; | ||
169 | + changeStyle =normalStyle; | ||
170 | + | ||
171 | + for(var arri=0;arri<page_selected_node.length;arri++){ | ||
172 | + if(page_selected_node[arri].id==model.id){ | ||
173 | + page_selected_node.splice(arri,1); | ||
174 | + break; | ||
175 | + } | ||
176 | + } | ||
177 | + }else{ | ||
178 | + model.checked=true; | ||
179 | + changeStyle = checkStyle; | ||
180 | + page_selected_node.push(model); | ||
181 | + } | ||
182 | + | ||
183 | + var keyShape = ev.item.getKeyShape(); | ||
184 | + keyShape.attr(changeStyle); | ||
185 | + net.refresh(); | ||
186 | + }); | ||
187 | + | ||
188 | + $(function () { | ||
189 | + //加载表格 | ||
190 | + $("#hostInfoTable").table({ | ||
191 | + columnAutoWidth : false, | ||
192 | + striped : true, | ||
193 | + title : "主机信息列表", | ||
194 | + dataType : "json", | ||
195 | + pagination : true, | ||
196 | + pageSize : 10, | ||
197 | + loadFilter : function(data) { | ||
198 | + return defaultLoadFilter(data); | ||
199 | + }, | ||
200 | + columns : [ | ||
201 | + { | ||
202 | + title: 'NO', | ||
203 | + width : "40px", | ||
204 | + formatter: function (value, row, index) { | ||
205 | + return index+1; | ||
206 | + } | ||
207 | + }, | ||
208 | + { | ||
209 | + title : "IP", | ||
210 | + field : "hostIp", | ||
211 | + width : "30%" | ||
212 | + }, { | ||
213 | + title : "云可用区", | ||
214 | + field : "cloudDetailType", | ||
215 | + formatter : function(value, rowData, rowIndex) { | ||
216 | + if(value == 1){ | ||
217 | + return 'AWS'; | ||
218 | + } else if(value == 21){ | ||
219 | + return '腾讯云'; | ||
220 | + }else if(value == 22){ | ||
221 | + return '腾讯云az2'; | ||
222 | + }else if(value == 23){ | ||
223 | + return '腾讯云az3'; | ||
224 | + }else{ | ||
225 | + return value; | ||
226 | + } | ||
227 | + }, | ||
228 | + width : "20%" | ||
229 | + }, { | ||
230 | + title : "标签", | ||
231 | + field : "tags", | ||
232 | + formatter : function(value, rowData, rowIndex) { | ||
233 | + if(value != null && value != ""){ | ||
234 | + return value.substr(0,value.length-1); | ||
235 | + } | ||
236 | + | ||
237 | + } | ||
238 | + }] | ||
239 | + }); | ||
240 | + }); | ||
241 | + | ||
242 | + | ||
243 | + | ||
244 | + function queryHost() { | ||
245 | + console.log(page_selected_node); | ||
246 | + | ||
247 | + var opt = $("#hostInfoTable").data("table"); | ||
248 | + opt.url=contextPath +"hostInfoList/getHostInfos"; | ||
249 | + | ||
250 | + var cloudDetailType = $("#cloudDetailType").val(); | ||
251 | + var param={ | ||
252 | + 'cloudDetailType': cloudDetailType, | ||
253 | + tags:'["upstream-switch"]' | ||
254 | + }; | ||
255 | + | ||
256 | + $("#hostInfoTable").table("load",param); | ||
257 | + | ||
258 | + } | ||
122 | </script> | 259 | </script> |
@@ -50,18 +50,20 @@ | @@ -50,18 +50,20 @@ | ||
50 | <script type="text/javascript"> | 50 | <script type="text/javascript"> |
51 | // 第一步:获取数据 | 51 | // 第一步:获取数据 |
52 | var data=${antvData}; | 52 | var data=${antvData}; |
53 | - console.log(data); | ||
54 | // 第二步:注册图形 | 53 | // 第二步:注册图形 |
55 | G6.registNode('rect', { | 54 | G6.registNode('rect', { |
56 | // 设置锚点 | 55 | // 设置锚点 |
57 | getAnchorPoints: function(){ | 56 | getAnchorPoints: function(){ |
58 | return [ | 57 | return [ |
59 | - [0.5, 1], // 右边边的中点 | ||
60 | - [0, 0.5] // 左边边的中点 | 58 | + [1, 0.1], // 右边边的中点 |
59 | + [0.5, 0] // 左边边的中点 | ||
61 | ]; | 60 | ]; |
62 | } | 61 | } |
63 | }); | 62 | }); |
64 | var nodes = data.nodes; | 63 | var nodes = data.nodes; |
64 | + /*for(var i=0;i<nodes.length;i++){ | ||
65 | + nodes[i].size=[100,30]; | ||
66 | + }*/ | ||
65 | var edges = data.edges; | 67 | var edges = data.edges; |
66 | 68 | ||
67 | // 第三步:进行布局 | 69 | // 第三步:进行布局 |
@@ -88,14 +90,14 @@ | @@ -88,14 +90,14 @@ | ||
88 | 90 | ||
89 | 91 | ||
90 | console.log(node.x,node.y); | 92 | console.log(node.x,node.y); |
91 | - });*/ | 93 | + }); |
92 | 94 | ||
93 | - console.log(nodes); | 95 | + console.log(nodes);*/ |
94 | // 第四步:初始化图 | 96 | // 第四步:初始化图 |
95 | var net = new G6.Net({ | 97 | var net = new G6.Net({ |
96 | - // fitView: 'autoZoom' // 自动缩放 | ||
97 | - behaviourFilter: ['wheelZoom', 'dragNode','dragBlank', 'dragCanvas'], | 98 | + fitView: 'autoZoom' ,// 自动缩放 |
98 | height: ${antvHeight}, // 此处替换高度 | 99 | height: ${antvHeight}, // 此处替换高度 |
100 | + behaviourFilter: ['wheelZoom', 'dragNode','dragBlank', 'dragCanvas'], | ||
99 | // width:1000, | 101 | // width:1000, |
100 | id: "hostListTopoDiv" // 此处替换容器id | 102 | id: "hostListTopoDiv" // 此处替换容器id |
101 | }); | 103 | }); |
@@ -115,10 +117,12 @@ | @@ -115,10 +117,12 @@ | ||
115 | return attrs; | 117 | return attrs; |
116 | }); | 118 | }); |
117 | net.edge() | 119 | net.edge() |
118 | - .shape('VH') | 120 | + .shape('HV') |
119 | .style({ | 121 | .style({ |
120 | - stroke: "#00A263", | 122 | + stroke: "#CCC", |
121 | strokeOpacity: 0.6, | 123 | strokeOpacity: 0.6, |
124 | + //lineWidth:1, | ||
125 | + // lineDash:[5,5], | ||
122 | arrow: true | 126 | arrow: true |
123 | }); | 127 | }); |
124 | // 第七步:添加图例 | 128 | // 第七步:添加图例 |
-
Please register or login to post a comment