JS實現網絡拓撲圖

廢話先不多說,先上圖;這是一個模擬設備狀態的拓撲圖;圖中節點右上角的圓形圖標綠色代表正常,紅色代表設備一次;在圖片的左上角 是用來獲取節點的詳細信息的。具體方法在js中有註釋,
因爲這只是個教程,所以在寫代碼上不是很規範。所以希望大家多多見諒。而且因爲本人對這個插件的研究也有限,有什麼不對的也希望多多交流 謝謝!
接着上代碼。這是前端html和js代碼;首先介紹下該功能的實現方法。是利用GoJS插件。 網址http://gojs.net/latest/index.html其中官網的包可以在這裏下載:http://gojs.net/latest/doc/download.html;官網提供的包是英文的包括註釋也是,而且不是很詳細。所有我在本例子中  將關鍵的代碼全部做了註釋。基本上有點基礎應該都能弄明白;爲了直觀,我直接將代碼註釋寫在了代碼所在的位置;這個插件在官網提供了很多例子。也有APS文檔。但是本人覺得他的API文檔寫的有點雜。很難看懂,跟別說那些英語基礎不好的人了。但是沒關係,後面我會介紹一下如何巧妙不看文檔也能做出不同效果的拓撲圖;或者說實現你想要的拓撲圖;
複製代碼
  1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2 
  3 <html>
  4 <head>
  5     <title>安防點位拓撲圖</title>
  6     <!-- /* Copyright ?1998-2013 by Northwoods Software Corporation. */ -->
  7     <link href="goSamples.css" rel="stylesheet" type="text/css" />
  8     <script type="text/javascript" src="go.js"></script>
  9     <!--    <script type="text/javascript" src="goSamples.js"></script>-->
 10     <script src="../resources/scripts/jquery-1.7.1.min.js" type="text/javascript"></script>
 11     <script type="text/javascript">
 12     var AjaxRequestBack=false;
 13     var IdList;
 14        function init() {
 15             if (window.goSamples) goSamples();  
 16             var $ = go.GraphObject.make;  
 17 
 18             myDiagram = $(go.Diagram, "myDiagram",
 19           {
 20               initialContentAlignment: go.Spot.Center //整個拓撲圖的位置
 21           });
 22           //節點的圖片,根據傳進來的參數獲取相對應的圖片
 23             function nodeTypeImage(type) {
 24                 if (type.charAt(0) === "1") return "images/1.png";
 25                 if (type.charAt(0) === "2") return "images/2.png";
 26                 if (type.charAt(0) === "3") return "images/3.png";
 27                 if (type.charAt(0) === "4") return "images/4.png";
 28                 if (type.charAt(0) === "5") return "images/5.png";
 29                 if (type.charAt(0) === "6") return "images/6.png";
 30                 if (type.charAt(0) === "7") return "images/7.png";
 31                 if (type.charAt(0) === "8") return "images/8.png";
 32                 return "images/0.png";
 33             }
 34 
 35             function nodeProblemConverter(msg) {
 36                 if (msg) return "red";
 37                 return null;
 38             }
 39             //判斷節點左邊形狀
 40             function nodeOperationConverter(s) {
 41                 if (s >= 2) return "TriangleDown";
 42                 if (s >= 1) return "Rectangle";
 43                 return "Circle";
 44             }
 45             //判斷節點右邊形狀的顏色
 46             function nodeStatusConverter(s) {
 47                 if (s >= 2) return "red";
 48                 if (s >= 1) return "green";
 49                 return "green";
 50             }
 51             //可以通過 problem控制節點的連線和邊框的顏色
 52             //data.status = 10.1;//控制節點內部圖標的顏色
 53             //data.operation //控制節點內圖標的形狀
 54             myDiagram.nodeTemplate =
 55             $(go.Node, "Vertical",
 56                     { selectable: false,//是否可以選擇節點並移動
 57                         mouseOver: function (e, obj) {//鼠標進入響應的事件方法
 58                            nodeDoubleClick(e, obj) //事件調用方法
 59                        }
 60                     },
 61             //         { doubleClick: nodeDoubleClick },//鼠標雙擊事件函數
 62             //{click: nodeDoubleClick }, //鼠標單擊事件函數
 63           {locationObjectName: "ICON" },
 64             // new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify), //這裏使用節點的位置參數,也可以不知用,不使用的時候,就的使用插件的佈局屬性
 65           $(go.Panel, "Spot",
 66             $(go.Panel, "Auto",
 67               { name: "ICON" }, //這個參數無所謂
 68               $(go.Shape,
 69                 { fill: null, portId: "", 
 70                 strokeWidth: 0,stroke: null },//這兩個屬性和起來去掉邊框
 71                 new go.Binding("background", "problem", nodeProblemConverter)), //這裏使用節點的問題描述 problem值爲空時:控制線條和邊框的顏色,即設備是否出現問題
 72               $(go.Picture,
 73               //{ stroke: ""},
 74                 { margin: 0 }, //這裏控制圖片和外圍邊框的邊距
 75                 { desiredSize: new go.Size(60, 60) },
 76                 new go.Binding("source", "type", nodeTypeImage))), //這裏是用節點的類型,即是用的圖片
 77             //這段代碼是控制節點內部左邊圖標初始顏色 形狀等,位子信息
 78             //            $(go.Shape, "Circle",
 79             //              { alignment: go.Spot.TopLeft, alignmentFocus: go.Spot.TopLeft, //TopLeft顯示的位置
 80             //                  width: 10, height: 10, fill: "Green"//這裏的顏色是控制節點內部左邊圖標的顏色
 81             //              },
 82 
 83             //              new go.Binding("figure", "operation", nodeOperationConverter)) //這裏是用節點形狀參數
 84 
 85             //這段代碼是控制節點內部右邊圖標初始顏色 形狀等,位子信息
 86             $(go.Shape, "Circle",
 87               { alignment: go.Spot.TopRight, alignmentFocus: go.Spot.TopRight, //TopLeft顯示的位置
 88                   width: 15, height: 15, fill: "Green"
 89               },
 90               new go.Binding("fill", "status", nodeStatusConverter)) //這裏是用節點狀態參數
 91               ),
 92               //這裏是節點文字的樣式
 93           $(go.TextBlock,
 94            { font: "bold 7px Helvetica, bold Arial, sans-serif",
 95               stroke: "black", margin: 3 },
 96             new go.Binding("text")));
 97 
 98             //設置線條的顏色
 99             function linkProblemConverter(msg) {
100                 if (msg) return "red";
101                 return "#ccc";
102             }
103 
104 
105 
106             myDiagram.linkTemplate =
107         $(go.Link, go.Link.AvoidsNodes,
108           { corner: 3 }, //控制線的轉彎的弧度值越小 越呈現直角
109           $(go.Shape,
110             { strokeWidth: 1 }, //控制線條的粗細,值越大  線越粗
111             new go.Binding("stroke", "problem", linkProblemConverter)));
112 
113             //節點的佈局                
114             myDiagram.layout = $(go.LayeredDigraphLayout,
115                         { direction: 270, //拓撲圖的方向
116                             layerSpacing: 10,
117                             columnSpacing: 15,
118                             setsPortSpots: false
119                         });
120 
121 
122             //在這裏加載數據
123             load();
124             //利用隨機數隨機設備出現問題的方法
125             function randomProblems() {
126             if(AjaxRequestBack)
127             {
128                
129             
130                 var model = myDiagram.model;
131                 //nodeDataArray
132                 //設置問題節的顏色
133                 var arr = model.nodeDataArray;
134                 for (var i = 0; i < arr.length; i++) {
135                     data = arr[i];
136 
137                     //console.log(data.key);
138                     for(var t=0;t<IdList.length;t++)
139                     {
140                     if(data.key==IdList[t])
141                     {
142                          data.status = 3;
143                     }
144                     else{
145                     //data.status = 1;
146                     }
147                     }
148 
149                     //data.problem = (Math.random() < 0.8) ? "" : "Power loss due to ...";//0.8是一個零界點
150                     //data.problem = ""; //當爲空的時候就是沒問題
151                     //data.problem = "Power loss due to ...";//當這個的時候就是有問題
152                     //data.status = 10.1;//這個數據是用於判斷節點右邊正方形 圓形 三角形還有形狀的顏色(右邊形狀不變)
153                     //data.operation = 0.1; //設置節點左邊正方形 圓形 三角形還有形狀的顏色(左邊的形狀顏色不變)
154                   
155                     //data.operation = 0.3;
156                     model.updateTargetBindings(data);
157                      data.status = 1;
158                 }  
159            
160 
161                 //獲取JSON數據中的linkDataArray
162                 //設置節點之間線的顏色
163                 /*
164                 arr = model.linkDataArray;
165                 for (i = 0; i < arr.length; i++) {
166                     data = arr[i];
167                     data.problem = (0.1 < 0.7) ? "" : "No Power";
168                     model.updateTargetBindings(data);
169                 }
170                 */
171                 AjaxRequestBack=false;
172                 }
173             }
174             //設置間隔時間獲取設備的狀態
175             function loop1()
176             {
177               setTimeout(function () { GetStatus(); loop1(); }, 4000);
178             }
179             loop1();
180             function loop() {
181                 setTimeout(function () { randomProblems(); loop(); }, 5500);
182             }
183             loop();  // start the simulation
184             myDiagram.makeImage({
185                 scale: 1,
186                 background: "AntiqueWhite",
187                 type: "image/jpeg",
188                 details: 0.05
189             });
190         }
191         function load() {
192             var str = <%=Result%>;
193             myDiagram.model = go.Model.fromJson(str);
194 
195             var arr = myDiagram.model.nodeDataArray;
196             for (var i = 0; i < arr.length; i++) {
197                 // alert(arr[i].text);
198             }
199 
200 
201         }
202 
203         function GetStatus() {       
204             $.ajax({
205                 url: 'GetEleStatus.ashx',
206                 type:'post',
207                 success: function (data) {
208                     var result = eval("(" + data + ")");
209                     IdList = result.IdList;
210                   
211                     AjaxRequestBack=true;
212                 }
213             });
214 
215         }
216 
217         function highlightNode(e, node) {
218             alert(node.data.text);
219         }
220 
221         function nodeDoubleClick(e, node) {
222             $("#Loading").html("正在加載...");
223             $.ajax({
224                 url: 'GetElementInfo.ashx',
225                 data: { "ElementID": node.data.key },
226                 success: function (data) {
227                     if (data != "false") {
228                         data = eval("(" + data + ")");
229                         var name = data.name;
230                         var commont = data.commont;
231 
232                        $("#Info").html("<span>點位名稱:"+name+"</span></br><span>點位描述:"+commont+"</span>")
233                       
234                     $("#Info").show();;
235                     tag=true;
236 
237                     }
238                 }
239             });
240         }
241 
242     </script>
243 </head>
244 <body onload="init()">
245     <div id='Info' style="position: fixed; padding-top: 5px; margin: 1px; line-height: 20px;
246         border-radius: 3px; background-color: #FFC435; width: 150px; height: 50px; z-index: 999;
247         border: 1px solid #ccc; top: 7px; left: 7px;">
248         <div id="Loading" style="text-align: center; width: 150px; margin-top: 15px;">
249             選擇點位</div>
250     </div>
251  
252     <div id="myDiagram" style="border: solid 0px black; width: 100%; height: 900px;">
253     </div>
254 
255     <br />
256     <%--</div>--%>
257 </body>
258 </html>
複製代碼
複製代碼
接下來是後臺代碼;後臺代碼的註釋也寫在代碼所在的行了。
複製代碼
  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Web;
  5 using System.Web.UI;
  6 using System.Web.UI.WebControls;
  7 using System.Text;
  8 using System.Data;
  9 
 10 namespace Maticsoft.Web.test
 11 {
 12     public partial class DrowNode : System.Web.UI.Page
 13     {
 14       
 15         public string Result;
 16         protected void Page_Load(object sender, EventArgs e)
 17         {
 18             DataSet set = new DataSet();
 19             set = new Maticsoft.BLL.RD_Element().Query("");//這裏是寫的SQL語句 去獲取你數據庫的數據。這裏我刪除掉了。而是利用下面構造的數據。這裏你獲取的數據必須包含兩個字段,一個是父節點編號,一個是子節點編號。
 20             if (set != null && set.Tables.Count > 0)
 21             {
 22 
 23                 StringBuilder result = new StringBuilder();
 24                 StringBuilder node = new StringBuilder();//這個對象是存放着節點信息
 25                 StringBuilder link = new StringBuilder();//這個節點是存放每個節點的關聯關係
 26                
 27                 //這兩個是節點的位置。但是我用了另一種佈局方式,這裏已經沒用了。
 28                 int y = 0;
 29                 int x = 0;
 30                 Random r = new Random();
 31                 int count = set.Tables[0].Rows.Count;
 32                 // 下面是構造的數據。該插件是利用後臺生成的Json格式數據來解析的;
 33                 //key 是節點編號 text是節點下面的文字。type是節點的類型。在html代碼有一個方法nodeTypeImage就是根據這個來返回圖片路徑的。problem則是用來標識節點數否異常。這裏有一個可能會混淆,那就是節點異常和節點之間的連接異常。具體在js代碼有註釋,當然這裏還有其他的屬性,就不一一介紹了。
 34                 node.Append("{\"key\":\"0\", \"text\":\"北京\", \"type\":\"0\", \"problem\":\"\"},");
 35                 node.Append("{\"key\":\"-1\", \"text\":\"中國\", \"type\":\"0\", \"problem\":\"\"},");
 36                 node.Append("{\"key\":\"-2\", \"text\":\"福建\", \"type\":\"0\", \"problem\":\"\"},");
 37                 node.Append("{\"key\":\"10000\", \"text\":\"風扇\", \"type\":\"2\", \"problem\":\"\"},");
 38                 node.Append("{\"key\":\"10001\", \"text\":\"風扇風扇\", \"type\":\"2\", \"problem\":\"\"},");
 39                 node.Append("{\"key\":\"10002\", \"text\":\"風扇\", \"type\":\"4\", \"problem\":\"\"},");
 40                 node.Append("{\"key\":\"10003\", \"text\":\"風扇\", \"type\":\"5\", \"problem\":\"\"},");
 41                 node.Append("{\"key\":\"10004\", \"text\":\"發電機\", \"type\":\"1\", \"problem\":\"\"},");
 42                 node.Append("{\"key\":\"10005\", \"text\":\"水龍頭\", \"type\":\"5\", \"problem\":\"\"},");
 43                 node.Append("{\"key\":\"10006\", \"text\":\"發電站\", \"type\":\"7\", \"problem\":\"\"},");
 44                 node.Append("{\"key\":\"10007\", \"text\":\"火箭\", \"type\":\"8\", \"problem\":\"\"},");
 45                 node.Append("{\"key\":\"10008\", \"text\":\"衛星\", \"type\":\"3\", \"problem\":\"\"},");
 46                 node.Append("{\"key\":\"10009\", \"text\":\"衛星\", \"type\":\"5\", \"problem\":\"\"},");
 47                 node.Append("{\"key\":\"100010\", \"text\":\"衛星\", \"type\":\"6\", \"problem\":\"\"},");
 48                 node.Append("{\"key\":\"100011\", \"text\":\"火箭\", \"type\":\"3\", \"problem\":\"\"},");
 49                 node.Append("{\"key\":\"100012\", \"text\":\"發電機\", \"type\":\"3\", \"problem\":\"\"},");
 50                 node.Append("{\"key\":\"100013\", \"text\":\"發電機\", \"type\":\"5\", \"problem\":\"\"},");
 51                 node.Append("{\"key\":\"100014\", \"text\":\"風扇\", \"type\":\"6\", \"problem\":\"\"},");
 52                 node.Append("{\"key\":\"100015\", \"text\":\"拖拉機\", \"type\":\"3\", \"problem\":\"\"},");
 53                 node.Append("{\"key\":\"100016\", \"text\":\"公交車\", \"type\":\"5\", \"problem\":\"\"},");
 54                 node.Append("{\"key\":\"100017\", \"text\":\"廣場控燈\", \"type\":\"6\", \"problem\":\"\"},");
 55                 node.Append("{\"key\":\"100018\", \"text\":\"演出屏幕\", \"type\":\"3\", \"problem\":\"\"},");
 56                 node.Append("{\"key\":\"100019\", \"text\":\"話筒\", \"type\":\"3\", \"problem\":\"\"},");
 57                 node.Append("{\"key\":\"100020\", \"text\":\"音箱\", \"type\":\"5\", \"problem\":\"\"},");
 58                 node.Append("{\"key\":\"100021\", \"text\":\"核武器\", \"type\":\"6\", \"problem\":\"\"},");
 59                 //這裏的數據是關聯各個節點的。from是線出來的節點編號,to則是連線到達的節點編號。這樣就能把兩節點關聯起來
 60                 link.Append("{\"from\":\"0\", \"to\":\"-1\",\"problem\":\"\"},");
 61                 link.Append("{\"from\":\"-2\", \"to\":\"-1\",\"problem\":\"\"},");
 62                 link.Append("{\"from\":\"10000\", \"to\":\"0\",\"problem\":\"\"},");
 63                 link.Append("{\"from\":\"10001\", \"to\":\"0\",\"problem\":\"\"},");
 64                 link.Append("{\"from\":\"10002\", \"to\":\"0\",\"problem\":\"\"},");
 65                 link.Append("{\"from\":\"10003\", \"to\":\"10002\",\"problem\":\"\"},");
 66                 link.Append("{\"from\":\"10004\", \"to\":\"10002\",\"problem\":\"\"},");
 67                 link.Append("{\"from\":\"10005\", \"to\":\"-2\",\"problem\":\"\"},");
 68                 link.Append("{\"from\":\"10006\", \"to\":\"-2\",\"problem\":\"\"},");
 69                 link.Append("{\"from\":\"10007\", \"to\":\"-2\",\"problem\":\"\"},");
 70                 link.Append("{\"from\":\"10008\", \"to\":\"100017\",\"problem\":\"\"},");
 71                 link.Append("{\"from\":\"10009\", \"to\":\"-2\",\"problem\":\"\"},");
 72                 link.Append("{\"from\":\"100010\", \"to\":\"-2\",\"problem\":\"\"},");
 73                 link.Append("{\"from\":\"100011\", \"to\":\"100019\",\"problem\":\"\"},");
 74                 link.Append("{\"from\":\"100012\", \"to\":\"10005\",\"problem\":\"\"},");
 75                 link.Append("{\"from\":\"100013\", \"to\":\"10005\",\"problem\":\"\"},");
 76                 link.Append("{\"from\":\"100014\", \"to\":\"10005\",\"problem\":\"\"},");
 77                 link.Append("{\"from\":\"100015\", \"to\":\"10007\",\"problem\":\"\"},");
 78                 link.Append("{\"from\":\"100016\", \"to\":\"10007\",\"problem\":\"\"},");
 79                 link.Append("{\"from\":\"100017\", \"to\":\"10009\",\"problem\":\"\"},");
 80                 link.Append("{\"from\":\"100018\", \"to\":\"10007\",\"problem\":\"\"},");
 81                 link.Append("{\"from\":\"100019\", \"to\":\"10009\",\"problem\":\"\"},");
 82                 link.Append("{\"from\":\"100020\", \"to\":\"100011\",\"problem\":\"\"},");
 83                 link.Append("{\"from\":\"100021\", \"to\":\"100011\",\"problem\":\"\"},");
 84 
 85                 //這段代碼是我本來用來構造數據庫中數據的JSON格式的,但是因爲沒用了。不過來是貼出來,如果你有用可以照着這個寫
 86                 //foreach (DataRow row in set.Tables[0].Rows)
 87                 //{
 88                 //    x = r.Next(count*20)+40;
 89                 //    y = r.Next(count*20)+100;
 90                 //    node.Append("{\"key\":\"" + row["id"] + "\", \"text\":\"" + row["name"] + "\", \"type\":\"" + row["type"] + "\", \"loc\":\"" + x + " "+y+"\",\"problem\":\"\"},");
 91 
 92                 //    //elemodel = new BLL.RD_Element().GetModel(int.Parse(row["parentid"].ToString ()));
 93                 //    link.Append("{\"from\":\"" + row["id"] + "\", \"to\":\"" + row["parentid"].ToString() + "\",\"problem\":\"\"},");
 94                 //}
 95                 string nodestr = node.ToString().Substring(0, node.ToString().Length - 1);
 96                 string linkstr = link.ToString().Substring(0, link.ToString().Length - 1);
 97 
 98 
 99                 result.Append("{\"nodeDataArray\": [ ");
100                 result.Append(nodestr);
101                 result.Append("],\"linkDataArray\": [ ");
102                 result.Append(linkstr);
103                 result.Append("]}");
104                 Result = result.ToString();
105             }
106         }
107         
108     }
109 }
複製代碼

然後是異步獲取設備狀態的C#代碼。這裏因爲沒有真正的設備信息。所以獲取的異常設備都是利用隨機函數構造出來的 代碼如下 其中返回的是json格式的數據,數據爲異常設備的編號

複製代碼
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 
 6 namespace Maticsoft.Web.test
 7 {
 8     /// <summary>
 9     /// GetEleStatus 的摘要說明
10     /// </summary>
11     public class GetEleStatus : IHttpHandler
12     {
13 
14         public void ProcessRequest(HttpContext context)
15         {
16             context.Response.ContentType = "text/plain";
17 
18             string result="{\"IdList\":[";
19           
20             Random r = new Random();
21             for (int i = 0; i < 10; i++)
22             {
23                 result += r.Next(100000,100022)+",";
24             }
25             result = result.Substring(0, result.Length - 1);
26             result += "]}";
27             context.Response.Write(result);
28         }
29 
30         public bool IsReusable
31         {
32             get
33             {
34                 return false;
35             }
36         }
37     }
38 }
複製代碼

最後是獲取設備的詳細信息,這個是在鼠標移動到設備節點上的時候異步請求獲取的。這裏就不詳細說了,大家可以根據自己的需求來做,也不難。

 

然後做一下總結。插件首先是解析你構造的Json數據,然後放在myDiagram.model對象裏。在數據中有兩個數據:nodeDataArray和linkDataArray分別存放節點信息和節點關聯信息;然後js去遍歷迭代這是兩個數組中的數據來構造拓撲圖。那麼在迭代的過程中。我們可以利用自己的需求去添加代碼實現我們想要的拓撲圖!

這裏的話我分享下我是這麼做的吧。首先 如果你的英語水平很好並且文檔閱讀能力較強,那麼可以不用往下看了。因爲直接去看文檔理解得也深一些,也能明白一些實現原理。

 

首先 你的明白你的需求是什麼。即你要實現什麼樣的拓撲圖。然後 你去官網他的例子裏面找。找到和你想要的差不多的拓撲圖,或者某個拓撲圖有你要的某個樣式或者佈局方式,或者交互方式等等。然後看他的代碼。那麼這裏你有的先了解整個插件的實現過程。你可以通過詳細分析我的代碼和註釋,應該就能大概明白某寫代碼是什麼功能。某個功能是那個方法實現的,因爲整個插件的實現原理都是一樣的。所以一些方法和屬性也是一樣的,只不過根據屬性的值,能得到不同的拓撲圖;比如佈局屬性myDiagram.layout  比如節點連接屬性:myDiagram.linkTemplate 那麼這裏就那佈局屬性說事,可能你想要的佈局不是我這個例子中的樣子,那麼你就可以到其他拓撲圖找到你想要的佈局方式,然後把他的代碼拿過來。替換掉現有的佈局代碼,當然這裏佈局有兩種方式,一種是插件自動給你佈局,就像我這個例子,還有一種是你自己構造每個節點的位置。 其他的也都大同小異。其實這就是一個組裝拼接的過程。有時候一些外國插件沒有什麼文檔的時候,我都是這乾的,而且效果不錯,速度也快。當然可能這樣做對整個插件的理解就沒有那麼透徹了;

(這裏插播一條廣告:http://xiamiwage.taobao.com/這是本人的淘寶店。唉 苦逼的挨踢男。希望大家多多支持吧)

最後  因爲這個插件是帶有水印的。如果要去水印。就得到他的官網註冊購買。當然我這也有一個破解版的,不過如果你真的要用,還是希望支持正版。

下載地址如下:http://pan.baidu.com/share/link?shareid=203307637&uk=370619680

最後 因爲是第一次寫博客,有什麼需要改進的地方請多多批評 多多建議。謝謝,也希望多多交流。哈哈

 

源碼地址:http://files.cnblogs.com/zhijiang/DrowNode.rar

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章