使用jTopo生成拓扑图

后端数据的获取

public void dashboard() {
    Record user = getSessionAttr("user");
    //获得设备数据
    List<Map<String, Object>> roomAndDeviceList = IndexService.service.getRoomAndDevice();
    setAttr("roomAndDeviceListJson", JsonKit.toJson(roomAndDeviceList));
    render("dashboard.html");
}

获取列表数据roomAndDeviceList内的每个map的keys(机房room和该机房下的设备devices)

public List<Map<String, Object>> getRoomAndDevice(){
   List<Map<String, Object>> list = new ArrayList<>();
   List<Record> rooms = Db.find(Db.getSql("room.queryPageList"));
   for(Record room : rooms){
      Map<String, Object> map = new HashMap<>();
      String roomId = room.getStr("room_id");
      List<Record> devices = Db.find(Db.getSqlPara("device.getDeviceByRoomId", roomId));
      map.put("room", room);
      map.put("devices", devices);
      list.add(map);
   }
   return list;
}

前段页面的数据渲染

目前还双击根节点后隐藏/显示 所有下级的连线和节点  还没完全弄好,待改善

#define room_topology(id)
<script type="text/javascript" src="assets/lib/jtopo/jtopo-0.4.8-min.js" ></script>
<div style="height:100%;width:100%;">
    <canvas id="topology_#(id)" :width="canvasWidth" :height="canvasHeight" style="border: 1px solid rgb(68, 68, 68);background: rgb(32, 95, 181); cursor: default;"></canvas>
    <ul id="contextmenu" style="display:none;">
        <li><a>顺时针旋转</a></li>
        <li><a>逆时针旋转</a></li>
        <li><a>更改颜色</a></li>
        <li><a>放大</a></li>
        <li><a>缩小</a></li>
        <li><a>删除该节点</a></li>
    </ul>
</div>
<script>
    $(function(){
        var dtVue = new Vue({
            el: "#topology_#(id)",
            data: {
                canvasWidth: 0,
                canvasHeight: 0
            },
            computed: {
            },
            mounted: function (){
                var $parent = $(this.$el.parentNode);
                this.canvasWidth = $parent.width();
                this.canvasHeight = $parent.height();
                $parent.css("overflow", "hidden");
            },
            methods: {
                renderTopology: function () {
                    var vThis = this;
                    var canvas = document.getElementById('topology_#(id)');
                    var stage = new JTopo.Stage(canvas);
                    //显示工具栏
                    var scene = new JTopo.Scene(stage);
                    var root = new JTopo.Node("政务数据安全管制系统管控中心");
                    root.font = '14px 微软雅黑'; // 字体
                    var x = this.canvasWidth/2-50;
                    var y = this.canvasHeight/2-50;;
                    root.setLocation(x, y);
                    root.setSize(100, 100);
                    root.setImage("assets/lib/jtopo/icon/vr-selfdefined.png");
                    root.layout = {type: 'circle', radius: 250};
                    root.addEventListener('mouseup', function(event){
                        if(event.button == 2){// 右键
                            // 当前位置弹出菜单(div)
                            $("#contextmenu").css({
                                top: event.pageY,
                                left: event.pageX
                            }).show();
                        }
                    });
                    //root节点双击后将所有连线和子节点设置显示/隐藏  TODO 二级节点device还未设置
                    root.dbclick(function(event){
                        if (root.layout.radius == 0) {
                            root.layout.radius = 250;
                            root.outLinks.forEach(function(item){
                                item.visible = true;
                                item.nodeZ.visible = true;
                            })
                        } else {
                            root.layout.radius = 0;
                            root.outLinks.forEach(function(item){
                                item.visible = false;
                                item.nodeZ.visible = false;
                            })
                        }
                        JTopo.layout.layoutNode(scene, root, true);
                    })
                    scene.add(root);
                    //一级节点 rooms
                    var roomAndDeviceList = #(roomAndDeviceListJson);
                    for(var i=0; i<roomAndDeviceList.length; i++){
                        var room = roomAndDeviceList[i].room;
                        var node = new JTopo.Node(room.room_name);
                        node.setImage("assets/lib/jtopo/icon/mypc.png");
                        node.layout = {type: 'circle', radius: 100};
                        node.setSize(50, 50);
                        node.setLocation(scene.width * Math.random(), scene.height * Math.random());
                        scene.add(node);
                        var link = new JTopo.Link(root, node);
                        scene.add(link);

                        //二级节点 devices
                        var devices = roomAndDeviceList[i].devices;
                        for(var j=0; j<devices.length; j++){
                            var device = devices[j];
                            var deviceNode = new JTopo.Node(device.device_name);
                            deviceNode.setImage("assets/lib/jtopo/icon/py_VM.png");
                            deviceNode.layout = {type: 'circle', radius: 50};
                            deviceNode.setSize(30, 30);
                            deviceNode.setLocation(scene.width * Math.random(), scene.height * Math.random());
                            scene.add(deviceNode);
                            scene.add(new JTopo.Link(node, deviceNode));

                            (function(device){
                                deviceNode.mouseover(function(deviceTarget){
                                    vThis.showDeviceTip(deviceTarget, device)
                                });
                                deviceNode.mouseout(function(){
                                    $("#"+device.device_id).remove();
                                    layer.closeAll();
                                })
                            })(device)
                        }

                        (function(room){
                            node.mouseover(function(event){
                                vThis.showRoomTip(event, room)
                            });
                            node.mouseout(function(){
                                $("#"+room.room_id).remove();
                                layer.closeAll();
                            })
                        })(room)
                    }
                    // 重新渲染拓扑图布局
                    JTopo.layout.layoutNode(scene, root, true);
                    scene.addEventListener('mouseup', function(e){
                        if(e.target && e.target.layout){
                            JTopo.layout.layoutNode(scene, e.target, true);
                        }
                    });
                },
                showRoomTip: function (event, room){
                    var target = $("<div style='width:50px;height:50px;position:fixed;'></div>").attr("id", room.room_id)
                        .css({
                            top: event.target.y + 160,
                            left: event.target.x + 260
                        });
                    $("body").append(target);
                    var content = `<div style="min-width:200px;">
                                    服务器名: ${room.room_name} <br>
                                    省: ${room.province_name} <br>
                                    市: ${room.city_name} <br>
                                    区: ${room.area_name} <br>
                                    具体地址: ${room.room_address} <br>
                                    负责人姓名: ${room.room_contacts} <br>
                                    负责人电话: ${room.room_contacts_phone} <br>
                                    </div>`;
                    layer.tips(content, "#"+room.room_id, {
                        tips: [1, '#3595CC'],
                        time: 0
                    });
                },
                showDeviceTip: function (deviceTarget, device){
                    var deviceTarget = $("<div style='width:50px;height:50px;position:fixed;'></div>").attr("id", device.device_id)
                        .css({
                            top: deviceTarget.target.y + 160,
                            left: deviceTarget.target.x + 260
                        });
                    $("body").append(deviceTarget);
                    var content = `<div style="min-width:200px;">
                                    设备名: ${device.device_name} <br>
                                    设备类型: ${device.device_type_tag} <br>
                                    设备IP: ${device.ip} <br>
                                    设备MAC: ${device.mac} <br>
                                    维护人员姓名: ${device.maintainer_name} <br>
                                    维护人员电话: ${device.maintainer_phone} <br>
                                    所属单位: ${device.maintainer_org_name} <br>
                                    </div>`;
                    layer.tips(content, "#"+device.device_id, {
                        tips: [1, '#3595CC'],
                        time: 0
                    });
                }
            },
            watch: {
                canvasheight: function(){
                    this.renderTopology();
                },
                canvasWidth: function(){
                    this.renderTopology();
                }
            }
        })
    })
</script>
#end

页面效果

鼠标悬停到具体设备上时会出现一个小窗体展示详细信息

使用jTopo生成拓扑图

 

jTopo参考网址:http://www.jtopo.cn/demo/layout-circle.html

具体相关的jTopo用法和文档可到上面官网查看