• 使用 jsPlumb 绘制拓扑图 —— 异步载入与绘制的实现



            本文实现的方法能够边异步载入数据边绘制拓扑图。

    有若干点须要说明一下:

            1.  一次性获取全部数据并绘制拓扑图。 请參见文章: <使用 JsPlumb 绘制拓扑图的通用方法> ; 本文实现的终于显示效果与之类似, 所使用的基本方法与之类似。

            2.  在此次实现中, 能够一边异步载入数据一边绘制拓扑图, 是动态可扩展的; 

            3.  全部影响节点位置、布局的配置均放置在最前面, 便于改动。 避免在代码中穿梭, 浪费时间;

            4.  布局算法比之前的实现更加完好。

            5.  此实现因为与业务逻辑绑得比較紧, 可复用的部分不多, 可是能够作为一个模板。 用在读者自己的场景中。 自行改动对应的节点类型、URL等。

            6.  加入了附着点的点击事件处理。 能够刷新显示关联实体;

            7.  主流程非常easy:  发送 AJAX 请求获取数据 ---> 创建节点(实际上就是DIV) ---> 计算节点位置、布局 ---> 加入节点附着点 ---> 缓存节点连接 ---> 连接全部现有的缓存节点连接。  多个 AJAX 请求的处理是异步的。 顺序没有控制。

            8.  代码:

            

    /**
     * 使用 jsPlumb 依据指定的拓扑数据结构绘制拓扑图
     * 使用 drawTopo_asyn(vmName, regionNo, parentDivId) 方法
     */
    /**
     * 初始化拓扑图实例及外观设置
     */
    (function() {
        
        jsPlumb.importDefaults({
            
            DragOptions : { cursor: 'pointer', zIndex:2000 },
        
            EndpointStyles : [{ fillStyle:'#225588' }, { fillStyle:'#558822' }],
        
            Endpoints : [ [ "Dot", { radius:2 } ], [ "Dot", { radius: 2 } ]],
        
            ConnectionOverlays : [
                [ "Label", { location:1 } ],
                [ "Label", { 
                    location:0.1,
                    id:"label",
                    cssClass:"aLabel"
                }]
            ]
        });
        
        var connectorPaintStyle = {
            lineWidth: 1,
            strokeStyle: "#096EBB",
            joinstyle:"round",
            outlineColor: "#096EBB",
            outlineWidth: 1
        };
        
        var connectorHoverStyle = {
            lineWidth: 2,
            strokeStyle: "#5C96BC",
            outlineWidth: 2,
            outlineColor:"white"
        };
        
        var endpointHoverStyle = {
            fillStyle:"#5C96BC"
        };
        
        window.topoDrawUtil = {
                
            sourceEndpoint: {
                endpoint:"Dot",
                paintStyle:{ 
                    strokeStyle:"#1e8151",
                    fillStyle:"transparent",
                    radius: 4,
                    lineWidth:2 
                },                
                isSource:true,
                maxConnections:-1,
                connector:[ "Flowchart", { stub:[40, 60], gap:1, cornerRadius:5, alwaysRespectStubs:true } ],                                                
                connectorStyle: connectorPaintStyle,
                hoverPaintStyle: endpointHoverStyle,
                connectorHoverStyle: connectorHoverStyle,
                dragOptions:{},
                overlays:[
                    [ "Label", { 
                        location:[0.5, 1.5], 
                        label:"",
                        cssClass:"endpointSourceLabel" 
                    } ]
                ]
            },
            
            targetEndpoint: {
                endpoint: "Dot",                    
                paintStyle: { fillStyle:"#1e8151",radius: 2 },
                hoverPaintStyle: endpointHoverStyle,
                maxConnections:-1,
                dropOptions:{ hoverClass:"hover", activeClass:"active" },
                isTarget:true,
                overlays:[
                    [ "Label", { location:[0.5, -0.5], label:"", cssClass:"endpointTargetLabel" } ]
                ]
            },
            
            initConnection: function(connection) {
                connection.getOverlay("label").setLabel(connection.sourceId + "-" + connection.targetId);
                connection.bind("editCompleted", function(o) {
                    if (typeof console != "undefined")
                        console.log("connection edited. path is now ", o.path);
                });
            },    
            
            removeAllEndPoints: function(nodeDivId) {
                jsPlumb.removeAllEndpoints($('#'+nodeDivId)); 
            },
            addEndpoints: function(toId, sourceAnchors, targetAnchors) {
                for (var i = 0; i < sourceAnchors.length; i++) {
                    var sourceUUID = toId + sourceAnchors[i];
                    var endPoint = jsPlumb.addEndpoint(toId, this.sourceEndpoint, { anchor:sourceAnchors[i], uuid:sourceUUID });    
                    endPoint.bind("click", function(endpoint) {
                        var anchorType = endpoint.anchor.type;
                        var nodeType = toId.split('_')[0];
                        var content = toId.split('_')[1];
                        if (nodeType == VM_TYPE) {
                            switch (anchorType) {
                                case 'Right':
                                    cacheKey = 'VM-DEVICE-'+ vmNodeData.key;
                                    cacheConnectionData[cacheKey] = null;
                                    linkDevices(vmNodeData, vmNodeData.key);
                                    break;
                                case 'Top':
                                    cacheKey = 'VM-ACCOUNT-'+ vmNodeData.key;
                                    cacheConnectionData[cacheKey] = null;
                                    vmName = vmNodeData.key;
                                    regionNo = vmNodeData.data.region_no;
                                    linkAccount(vmNodeData, vmName, regionNo);
                                    break;
                                case 'Bottom':
                                    cacheKey = 'VM-NC-'+ vmNodeData.key;
                                    cacheConnectionData[cacheKey] = null;
                                    ncId = vmNodeData.data.nc_id;
                                    regionNo = vmNodeData.data.region_no;
                                    linkNc(vmNodeData, ncId, regionNo);
                                    break;
                                case 'Left':
                                    cacheKey = 'VM-VIP-'+ vmNodeData.key;
                                    cacheConnectionData[cacheKey] = null;
                                    vmInnerIp = vmNodeData.data.vm_inner_ip;
                                    linkVips(vmNodeData, vmInnerIp);
                                    break;
                                default:
                                    break;
                            }
                        }
                        else if (nodeType == DEVICE_TYPE) {
                            if (anchorType == 'Bottom') {
                                cacheKey = 'DEVICE-SNAPSHOT-'+ content;
                                cacheConnectionData[cacheKey] = null;
                                deviceNodeData = deviceNodeDataMapping[content];
                                linkSnapshot(deviceNodeData.data.aliUid, content, deviceNodeData);
                            }
                        }
                    });
                }
                for (var j = 0; j < targetAnchors.length; j++) {
                    var targetUUID = toId + targetAnchors[j];
                    jsPlumb.addEndpoint(toId, this.targetEndpoint, { anchor:targetAnchors[j], uuid:targetUUID });                        
                }
            }
        };
    })();
    //////////////////////////////////////////////////////////////////////////////
    // 这里将全部用到的数据结构汇聚在这里, 避免改动时须要在代码中穿行, 浪费时间
    /**
     * 又一次刷新VM关联实体时须要使用到VM的信息,这里进行全局缓存,避免反复查询
     * 又一次刷新VM关联实体时VM必然存在, vmNodeData 也必然是近期一次查询的结果
     */
    var vmNodeData = {};
    /**
     * 又一次刷新磁盘关联快照实体时须要使用到磁盘的信息,这里进行全局缓存,避免反复查询
     * 又一次刷新磁盘关联快照实体时磁盘必然存在,且必然是近期一次查询的结果
     * eg. {'instanceId': { "ecsInstanceId": "vmName", "houyiDiskId": "102-80012003",
                            "aliUid": aliUidNum,  "instanceId": "d-28ilj8rsf", ... }}
     */
    var deviceNodeDataMapping = {};
    /**
     * 拓扑图中的节点类型
     */
    var nodeTypeArray = ['VM', 'DEVICE', 'NC', 'VIP', 'SNAPSHOT', 'CLUSTER', 'AVZ', 'ACCOUNT'];
    var VM_TYPE = nodeTypeArray[0];
    var DEVICE_TYPE = nodeTypeArray[1];
    var NC_TYPE = nodeTypeArray[2];
    var VIP_TYPE = nodeTypeArray[3];
    var SNAPSHOT_TYPE= nodeTypeArray[4];
    var CLUSTER_TYPE= nodeTypeArray[5];
    var AVZ_TYPE= nodeTypeArray[6];
    var ACCOUNT_TYPE= nodeTypeArray[7];
    /**
     * cacheConnectionData 节点之间的已有连接数目缓存, 在计算节点位置及布局方法 computeLayout 中用到
     * eg. {
     *    'VM-DEVICE-vmkey': 2,  'VM-NC-vmkey':1,  'VM-VIP-vmkey':2 , 'VM-ACCOUNT-vmkey': 1,
     * } 
     * 表示已经有2磁盘/1NC/2VIP/1ACCOUNT 与VM(key 为 vmkey)连接, 这些信息用于计算与VM相连接的同类型的下一个实体的相对位置
     */
    var cacheConnectionData = {};
    /**
     * 连接关系的存储, 在 cacheConnections , reconnectAll 方法中用到
     * 由于反复节点会移动到新的位置,原有连接会出现断连现象, 因此採用"每次刷新拉取新实体时重连全部连线" 的策略, 能够保证实时性, 仅仅要连接数不多反复连接的开销是能够接受的.
     * connections = [[startPoint1, endPoint1], [startPoint2, endPoint2], ..., [startPointN, endPointN]];
     */
    var connections = [];
    /**
     * 实体与实体上附着点方向的设置
     * DEVICE_TYPE: [['Right', 'Bottom'], ['Left']] 的含义是:
     * 对于DEVICE实体: 作为起始节点时, 附着点能够在右方中点(连接CLUSTER), 下方中点(连接快照); 作为终止节点时, 附着点仅在左方中点(连接VM) 
     */
    var entityEndPointsMapping = {
        "VM": [['Top', 'Bottom', 'Right', 'Left'], []],
        "DEVICE": [['Right', 'Bottom'], ['Left']],
        "NC": [['Bottom'], ['Top']],
        "VIP": [[], ['Right']],
        "SNAPSHOT": [[], ['Top']],
        "CLUSTER": [[], ['Left', 'Top']],
        "AVZ": [['Bottom'], ['Top']],
        "ACCOUNT": [[], ['Bottom']]
    };
    /**
     * 连接线附着点方向设置
     * "VM-ACCOUNT": ['Top', 'Bottom'] 的含义是:
     * VM 的上方附着点 与 ACCOUNT 的下方附着点的连接
     */
    var connectionDirectionMapping = {
        "VM-ACCOUNT": ['Top', 'Bottom'],
        "VM-NC": ['Bottom', 'Top'],
        "NC-CLUSTER": ['Bottom', 'Top'],
        "VM-DEVICE": ['Right', 'Left'],
        "DEVICE-CLUSTER": ['Right', 'Left'],
        "VM-VIP": ['Left', 'Right'],
        "DEVICE-SNAPSHOT": ['Bottom', 'Top']
    }
    /**
     * 节点之间的水平与垂直相对位置
     */
    var largeVerticalDistance = 270;
    var verticalDistance = 220;
    var horizontalDistance = 300;
    var shortVerticalDistance = 50;
    var shortHorizontalDistance = 220;
    /**
     * 节点之间的水平或垂直相对位置和距离的设置
     * "VM-DEVICE": [largeVerticalDistance, horizontalDistance] 
     */
    var connectionDistanceMapping = {
        "VM-ACCOUNT": [-verticalDistance, 0],
        "VM-NC": [shortVerticalDistance, 0],
        "NC-CLUSTER": [shortVerticalDistance, 0],
        "VM-DEVICE": [largeVerticalDistance, horizontalDistance],
        "DEVICE-CLUSTER": [-108, horizontalDistance],
        "VM-VIP": [verticalDistance, -horizontalDistance],
        "DEVICE-SNAPSHOT": [shortVerticalDistance, shortHorizontalDistance]
    }
    /**
     * 根节点位置
     */
    rootPosition = [220, 360];
    rootTop = rootPosition[0];
    rootLeft = rootPosition[1];
    var parentDiv = null;
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    function drawtopo_asyn(vmName, regionNo, parentDivId) {
        
        parentDiv = $('#'+parentDivId);
        
        var vmInfoReq = {
            'url':     httpPrefix + '/controllers/vm/obtainVmData',
            'params' : {
                'vm_name' : vmName,
                'region_no': regionNo
            }
        };
        var vmjq = doAjaxRequest(vmInfoReq);
        var vmInfoLoadedAfter = function(resultJson) {
            
            vmNodeData = resultJson.result.data;
            if (vmNodeData == null) {
                alert('没有找到VM的相关信息!');
                return ;
            }
            vmNode = createDiv(vmNodeData);
            
            vmDivId = obtainNodeDivId(vmNodeData);
            $('#'+vmDivId).css('top', rootTop + 'px');
            $('#'+vmDivId).css('left', rootLeft + 'px');
            
            linkAccount(vmNodeData, vmName, regionNo);
            
            ncId = vmNodeData.data.nc_id;
            linkNc(vmNodeData, ncId, regionNo);
            
            // vmName = 'ATX-28n2dhdq8';
            linkDevices(vmNodeData, vmName);
            
            vmInnerIp = vmNodeData.data.vm_inner_ip;
            linkVips(vmNodeData, vmInnerIp);
            
        };
        vmjq.done(vmInfoLoadedAfter);
    }
    function linkAccount(vmNodeData, vmName, regionNo) {
        var accountInfoReq = {
            'url': httpPrefix + '/controllers/vm/obtainAliyunAccountInfo',
            'params': {
                'vm_name' : vmName,
                'region_no': regionNo
            }
        };
        var accountjq = doAjaxRequest(accountInfoReq);
        accountjq.done(function(resultJson) {
            
            // for test
            // resultJson = {"result":{"msg":"successful","code":200,"data":{"errorCode":null,"errorMsg":null,"aliyunID":"it-cloudpc@alibaba-inc.com","kp":null},"success":true}};
            
            if (resultJson.result.success) {
                accountData = resultJson.result.data;
                accountNodeData = createAccountData(accountData);
                accountNode = createDiv(accountNodeData);
                cacheConnections(vmNodeData, accountNodeData, obtainConnectionDirections(vmNodeData, accountNodeData));
                reconnectAll(connections);
            }
            else {
                $('#error').append('获取关联云账号信息失败!

    '); } }).fail(function() { $('#error').append('获取关联云账号信息失败。 '); }); } function linkNc(vmNodeData, ncId, regionNo) { var ncInfoReq = { 'url': httpPrefix + '/controllers/nc/listNc', 'params': { 'region_no': regionNo, 'nc_id': ncId, 'start': 0, 'page': 1, 'limit': 1 } }; var ncjq = doAjaxRequest(ncInfoReq); ncjq.done(function(resultJson) { ncDataList = resultJson.data; if (ncDataList.length > 0) { ncData = ncDataList[0]; ncNodeData = createNcData(ncData); ncNode = createDiv(ncNodeData); cacheConnections(vmNodeData, ncNodeData, obtainConnectionDirections(vmNodeData, ncNodeData)); ncClusterNodeData = createNcClusterData(ncData); ncClusterNode = createDiv(ncClusterNodeData); cacheConnections(ncNodeData, ncClusterNodeData, obtainConnectionDirections(ncNodeData, ncClusterNodeData)); reconnectAll(connections); } else { $('#error').append('获取关联NC实体失败!'); } }).fail(function() { $('#error').append('获取关联NC实体失败!'); }); } function linkDevices(vmNodeData, vmName) { var deviceInfoReq = { 'url' : httpPrefix + '/controllers/disk/search', 'params': { 'vmName': vmName } } var regionPeNickName = vmNodeData.data.region_pe_nickname; var devicejq = doAjaxRequest(deviceInfoReq); devicejq.done(function(resultJson) { total = resultJson.data.total; if (total > 0) { devices = resultJson.data.list; for (var i=0; i<total; i++) { deviceData = devices[i]; deviceData['regionPeNickName'] = regionPeNickName; deviceNodeData = createDeviceData(deviceData); deviceNodeDataMapping[deviceData.instanceId] = deviceNodeData; deviceNode = createDiv(deviceNodeData); cacheConnections(vmNodeData, deviceNodeData, obtainConnectionDirections(vmNodeData, deviceNodeData)); deviceClusterNodeData = createDeviceClusterData(deviceData); deviceClusterNode = createDiv(deviceClusterNodeData); cacheConnections(deviceNodeData, deviceClusterNodeData, obtainConnectionDirections(deviceNodeData,deviceClusterNodeData)); linkSnapshot(devices[i].aliUid, devices[i].instanceId, deviceNodeData); } reconnectAll(connections); } else { $('#error').append('该VM没有关联的磁盘实体!

    '); } }).fail(function() { $('#error').append('获取关联磁盘实体失败!

    '); }); } function linkVips(vmNodeData, vmInnerIp) { var vipInfoReq = { 'url': httpPrefix + '/controllers/slbvip/listVip', 'params': { 'realserver_param': vmInnerIp, 'start': 0, 'page': 1, 'limit': 100 } }; var vipjq = doAjaxRequest(vipInfoReq); vipjq.done(function(resultJson) { total = resultJson.total; vips = resultJson.data; if (total > 0) { for (j=0; j<total; j++) { var vipInfo = vips[j]; vipNodeData = createVipData(vipInfo); vipNode = createDiv(vipNodeData); cacheConnections(vmNodeData, vipNodeData, obtainConnectionDirections(vmNodeData,vipNodeData)); } reconnectAll(connections); } else { $('#error').append('该VM没有关联的VIP实体!'); } }).fail(function() { $('#error').append('获取关联VIP实体失败!

    '); }); } function linkSnapshot(aliUid, diskId, deviceNodeData) { var snapshotInfoReq = { 'url': httpPrefix + '/controllers/snapshot/search', 'params': { 'aliUid': aliUid, 'diskId': diskId } }; var snapshotjq = doAjaxRequest(snapshotInfoReq); snapshotjq.done(function(resultJson) { total = resultJson.total; if (total > 0) { snapshotDataList = resultJson.list; for (k=0; k<total; k++) { snapshotData = snapshotDataList[k]; snapshotNodeData = createSnapshotData(snapshotData); snapshotNode = createDiv(snapshotNodeData); cacheConnections(deviceNodeData, snapshotNodeData, obtainConnectionDirections(deviceNodeData, snapshotNodeData)); } reconnectAll(connections); } else { $('#error').append('磁盘 ' + diskId + ' 没有关联的快照实体!

    '); } }).fail(function() { $('#error').append('磁盘' + diskId + ' 获取关联快照实体失败!'); }); } /** * createXXXData * 创建拓扑图所使用的节点数据 */ function createVmData(vmData) { return { 'type': 'VM', 'key': vmData.vm_name, 'data': vmData } } function createNcData(ncData) { return { 'type': 'NC', 'key': ncData.ip, 'data': ncData } } function createNcClusterData(ncData) { return { 'type': 'CLUSTER', 'key': ncData.regionPeNickName, 'data': { 'regionNo': ncData.regionNo, 'regionNickName': ncData.regionNickName, 'regionPeNickName': ncData.regionPeNickName } } } function createDeviceData(deviceData) { return { 'type': 'DEVICE', 'key': deviceData.instanceId, 'data': deviceData } } function createDeviceClusterData(deviceData) { return { 'type': 'CLUSTER', 'key': deviceData.regionNo, 'data': { 'regionNo': deviceData.regionNo } } } function createSnapshotData(snapshotData) { return { 'type': 'SNAPSHOT', 'key': snapshotData.snapshotId, 'data': snapshotData } } function createSnapshotClusterData(snapshotData) { return { 'type': 'CLUSTER', 'key': snapshotData.regionNo, 'data': { 'regionNo': snapshotData.regionNo } } } function createVipData(vipData) { return { 'type': 'VIP', 'key': vipData.vipAddress, 'data': vipData } } function createAccountData(accountData) { return { 'type': 'ACCOUNT', 'key': accountData.aliyunID, 'data': accountData } } /** * 缓存起始节点 beginNode 和终止节点 endNode 的连接关系 */ function cacheConnections(beginNode, endNode, directions) { computeLayout(beginNode, endNode); var startPoint = obtainNodeDivId(beginNode) + directions[0]; var endPoint = obtainNodeDivId(endNode) + directions[1]; connections.push([startPoint, endPoint]); } /** * 计算节点位置及布局 */ function computeLayout(beginNode, endNode) { var beginDivId = obtainNodeDivId(beginNode); var endDivId = obtainNodeDivId(endNode); var beginNodeType = beginNode.type; var endNodeType = endNode.type; beginNodeTop = $('#'+beginDivId).offset().top; beginNodeLeft = $('#'+beginDivId).offset().left; var key = beginNodeType + '-' + endNodeType + '-' + beginNode.key; if (cacheConnectionData[key] == null) { cacheConnectionData[key] = -1; } else { cacheConnectionData[key] = cacheConnectionData[key]+1; } connNum = cacheConnectionData[key]; var typeKey = beginNodeType + '-' + endNodeType; var relDistance = connectionDistanceMapping[typeKey]; var relVertiDistance = relDistance[0]; var relHoriDistance = relDistance[1]; switch (beginNodeType) { case VM_TYPE: if (endNodeType == VIP_TYPE) { endNodePosition = [beginNodeTop+connNum*relVertiDistance, beginNodeLeft+relHoriDistance]; } else if (endNodeType == DEVICE_TYPE) { endNodePosition = [beginNodeTop+connNum*relVertiDistance, beginNodeLeft+relHoriDistance]; } else if (endNodeType == NC_TYPE) { endNodePosition = [beginNodeTop+relVertiDistance, beginNodeLeft+relHoriDistance]; } else if (endNodeType == ACCOUNT_TYPE) { endNodePosition = [beginNodeTop+relVertiDistance, beginNodeLeft+relHoriDistance]; } break; case DEVICE_TYPE: if (endNodeType == CLUSTER_TYPE) { endNodePosition = [beginNodeTop+relVertiDistance, beginNodeLeft+relHoriDistance]; } else if (endNodeType == SNAPSHOT_TYPE) { endNodePosition = [beginNodeTop+relVertiDistance, beginNodeLeft+(connNum+1)*relHoriDistance]; } break; case VIP_TYPE: break; case NC_TYPE: if (endNodeType == CLUSTER_TYPE) { endNodePosition = [beginNodeTop+relVertiDistance, beginNodeLeft+relHoriDistance]; } break; case SNAPSHOT_TYPE: default: break; } $('#'+endDivId).css('top', endNodePosition[0] + 'px'); $('#'+endDivId).css('left', endNodePosition[1] + 'px'); addEndPoints(beginDivId, beginNodeType); addEndPoints(endDivId, endNodeType); } /** * 为节点加入用于连线的附着点 * @param nodeDivId 节点的 DIV ID * @param type 节点类型 */ function addEndPoints(nodeDivId, type) { var startAttachedPoints = entityEndPointsMapping[type][0]; var endAttachedPoints = entityEndPointsMapping[type][1]; topoDrawUtil.addEndpoints(nodeDivId, startAttachedPoints, endAttachedPoints); } /** * 连接全部连线 */ function reconnectAll(connections) { var i=0; for (i=0; i<connections.length; i++) { jsPlumb.connect({uuids:connections[i], editable: false}); } // 使全部拓扑节点均为可拉拽的 jsPlumb.draggable(jsPlumb.getSelector(".node"), { grid: [5, 5] }); } /** * div id cache , avoid duplicated div. * {'divId': 'divStr'} */ divIdCache = {}; /** * 为节点数据创建节点附着点并返回节点的DIV */ function createDiv(metaNode) { var clickUrl = ''; var display = ''; var type = metaNode.type; var regionPeNickname = ''; if (metaNode.data != null) { regionPeNickname = metaNode.data.regionPeNickName; } nodeDivId = obtainNodeDivId(metaNode); if (divIdCache[nodeDivId] != null) { // 该节点要移动到新的位置, 因此原来的附着点要去掉 topoDrawUtil.removeAllEndPoints(nodeDivId); return divIdCache[nodeDivId]; } switch(type.toUpperCase()) { case VM_TYPE: clickUrl = httpPrefix + '/framehtml/vm_monitor.html?

    vm_name=' + metaNode.key + '&data='+JSON.stringify(metaNode.data).replace(/"/g,"'"); display = metaNode.key; break; case DEVICE_TYPE: displayDevice1 = metaNode.data.instanceId; clickDeviceUrl2 = httpPrefix + '/framehtml/device_monitor.html?device_id=' + metaNode.data.houyiDiskId + '®ion_pe_nickname='+regionPeNickname; displayDevice2 = metaNode.data.houyiDiskId; break; case NC_TYPE: var regionNo = metaNode.data.regionNo; clickUrl = httpPrefix + '/framehtml/nc_monitor.html?nc_ip=' + metaNode.key + '®ion_pe_nickname='+regionPeNickname + '®ion_no='+regionNo; display = metaNode.key; break; case VIP_TYPE: display = metaNode.key + ':' + metaNode.data.port; clickUrl = httpPrefix + '/framehtml/vip_monitor.html?vip=' + display + '®ion_pe_nickname='+regionPeNickname + '&slbdb_configId='+metaNode.data.slbdb_configId; break; case SNAPSHOT_TYPE: display = metaNode.key + '<br/>' + metaNode.data.houyiSnapshotId + '<br/><span style="color:green">'+ metaNode.data.regionNo + '</span>'; break; case CLUSTER_TYPE: case AVZ_TYPE: case ACCOUNT_TYPE: display = metaNode.key; break; default: break; } if (type == VM_TYPE || type == NC_TYPE || type == VIP_TYPE || type == ACCOUNT_TYPE ) { divStr = '<div class="node biggerNode" id="' + nodeDivId + '"><strong>' + metaNode.type + '<br/><a href="' + clickUrl + '" target="_blank">' + display + '</a><br/></strong></div>'; } else if (type == DEVICE_TYPE){ divStr = '<div class="node biggerNode" id="' + nodeDivId + '"><strong>' + metaNode.type + '<br/>' + displayDevice1 + '<br/><a href="' + clickDeviceUrl2 + '" target="_blank">' + displayDevice2 + '</a><br/></strong></div>'; } else { divStr = '<div class="node biggerNode" id="' + nodeDivId + '"><strong>' + metaNode.type + '<br/>' + display + '<br/></strong></div>'; } parentDiv.append(divStr); divIdCache[nodeDivId] = divStr; return divStr; } function obtainConnectionDirections(srcNodeData, destNodeData) { var key = srcNodeData.type + '-' + destNodeData.type; var startDirection = connectionDirectionMapping[key][0]; var endDirection = connectionDirectionMapping[key][1]; return [startDirection, endDirection]; } /** * 生成节点的 DIV id * divId = nodeType.toUpperCase + "_" + key * key 可能为 IP , 当中的 . 将被替换成 ZZZ , 由于 jquery id 选择器中 . 属于转义字符. * eg. {type: 'VM', key: '1.1.1.1' }, divId = 'VM_1ZZZ1ZZZ1ZZZ1' */ function obtainNodeDivId(metaNode) { if (metaNode.type == VIP_TYPE) { return metaNode.type.toUpperCase() + '_' + transferKey(metaNode.key) + '_' + metaNode.data.port; } return metaNode.type.toUpperCase() + '_' + transferKey(metaNode.key); } function transferKey(key) { return key.replace(/./g, 'ZZZ').replace(/@/g,'YYY'); } function revTransferKey(value) { return value.replace(/ZZZ/g, '.').replace('/YYY/g','@'); }


  • 相关阅读:
    如何清除el-dialog中的表单验证
    购物车小球飞入动画
    node的应用场景
    如何在Ubuntu Server 18.04 LTS中配置静态IP地址
    在Ubuntu上启用和禁用NetworkManager
    gcc常用命令
    cmake入门
    模拟实现pwd命令
    模拟实现ls命令
    qmake生成的Makefile在make install时遇到的一次错误
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/5329238.html
Copyright © 2020-2023  润新知