zoukankan      html  css  js  c++  java
  • 配电室监控

    配电室监控可以说是我做的比较杰出的一个功能了,貌似是去年7月份左右做完的,至今也有一年了,要不是今天看到,我都忘了我曾写过这样一个功能。好的东西还是应该记录一下的,今天花点时间简单写个备忘吧。

    首先介绍对象,以及对象的增删改,然后介绍监控页面,最后总结开发经验。

    配电室有1-3个变压器

    一个进线一个出线,进线是一定有的,而出线则可有可无

    新增页面

    列表页面

    变压器可以添加1-3个

    每个变压器有默认的18个检测项目(新增变压器的时候,后台默认添加18个检测项目)

    进线、出线也有固定的检测项目

    进线有固定的8个检测项目

    出线有固定的4个检测项目

    列表页面会列出一个配电室的所有检测项目

    由于(莫斯配电室)添加了3个变压器,且有(出线),此处检测项目会有3个变压器和一个进线一个出线的所有检测项目

    配电室监控的时候,由于用代码临时画线路图页面加载效率会比较低,所以采用的是先画好线路图,监控的时候动态的选择线路图展示的方案,线路图一共有6张,分一个变压器有出线和无出线两张图、两个变压器有出线和无出线两张图、三个变压器有出线和无出线两张图

    道闸的开关由两张道闸的图片切换

    监控页面

    值得一说的有已下三点

    一、首先要说的是,如何动态匹配底图图纸?

    配电室对象根据自己是否有出线及有几个变压器给出对应的类型,js写json,配置不同的类型对应不同的图纸url

    public String getRoomJson() {
        JSONObject data = new JSONObject();
        
        try {
            data.put("name", "[" + area.getName() + "]" + name);
            data.put("id", this.getId());
            data.put("inlinename", this.getIncomingLine().getName());
            
            int num = voltageTransformerList.size();
            if (num == 0) {
                data.put("msg", "配电室结构异常,没有变压器!");
            } else if (num > 3) {
                data.put("msg", "配电室结构异常,有[" + num + "]个变压器!");
            }
            
            if (haveOutgoingLine) {
                data.put("type", num + "out");
            } else {
                data.put("type", num + "v");
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        
        roomJson = data.toString();
        return roomJson;
    }

    二、框里的检测项目,出现的位置怎么控制,怎么能让对应的检测项目出线在底图对应的位置上?

    如下图,红色线标注出来的那些,是怎么控制显示的位置的?

    不同类型的图纸,对应的配电室的检测项目是固定的,只要针对不同的图纸,提前设计好哪些检测项目应该放在哪里展示,然后计算出相对位置,在js里写好json配置,页面加载的时候根据页面的宽高,再结合这个json配置,就可以计算出页面中各个对象展现的位置

    var RoomData = {
        "1v": [
            {A: "inline", B: "U", x: 380.0, y: 360.0, pos: "RB"},
            {A: "inline", B: "I", x: 480.0, y: 360.0, pos: "LB"},
            
            {A: "voltage1", B: "capacity", x: 750, y: 580, pos: "RB", nomenu: true},
            
            {A: "voltage1", B: "IHigh", x: 910, y: 360, pos: "LB"},
            {A: "voltage1", B: "T", x: 840, y: 580, pos: "LB"},
            {A: "voltage1", B: "U", x: 750, y: 630, pos: "RT"},
            {A: "voltage1", B: "ILow", x: 840, y: 630, pos: "LT"}
        ],
        "1out": [
            {A: "inline", B: "U", x: 380.0, y: 360.0, pos: "RB"},
            {A: "inline", B: "I", x: 480.0, y: 360.0, pos: "LB"},
            
            {A: "voltage1", B: "IHigh", x: 820, y: 360, pos: "LB"},
            {A: "voltage1", B: "T", x: 760, y: 580, pos: "LB"},
            {A: "voltage1", B: "U", x: 650, y: 630, pos: "RT"},
            {A: "voltage1", B: "ILow", x: 760, y: 630, pos: "LT"},
            
            {A: "voltage1", B: "capacity", x: 650, y: 580, pos: "RB", nomenu: true},
            
            {A: "outline", B: "I", x: 1130.0, y: 360.0, pos: "LB"}
        ],
        "2v": [
            {A: "inline", B: "U", x: 200.0, y: 360.0, pos: "RB"},
            {A: "inline", B: "I", x: 300.0, y: 360.0, pos: "LB"},
            
            {A: "voltage1", B: "IHigh", x: 650, y: 360, pos: "LB"},
            {A: "voltage1", B: "ILow", x: 490, y: 630, pos: "RT", rely: {B: "U", move: "left"}},
            
            {A: "voltage1", B: "capacity", x: 490, y: 580, pos: "RB", rely: {B: "T", move: "leftB"}, nomenu: true},
            {A: "voltage2", B: "capacity", x: 980, y: 580, pos: "LB", rely: {B: "T", move: "rightB"}, nomenu: true},
            
            {A: "voltage2", B: "IHigh", x: 1050, y: 360, pos: "LB"},
            {A: "voltage2", B: "U", x: 980, y: 630, pos: "LT", rely: {B: "ILow", move: "right"}}
        ],
        "2out": [
            {A: "inline", B: "U", x: 200.0, y: 360.0, pos: "RB"},
            {A: "inline", B: "I", x: 300.0, y: 360.0, pos: "LB"},
            
            {A: "voltage1", B: "IHigh", x: 610, y: 360, pos: "LB"},
            {A: "voltage1", B: "ILow", x: 440, y: 630, pos: "RT", rely: {B: "U", move: "left"}},
            
            {A: "voltage2", B: "IHigh", x: 930, y: 360, pos: "LB"},
            {A: "voltage2", B: "U", x: 870, y: 630, pos: "LT", rely: {B: "ILow", move: "right"}},
            
            {A: "voltage1", B: "capacity", x: 440, y: 580, pos: "RB", rely: {B: "T", move: "leftB"}, nomenu: true},
            {A: "voltage2", B: "capacity", x: 870, y: 580, pos: "LB", rely: {B: "T", move: "rightB"}, nomenu: true},
            
            {A: "outline", B: "I", x: 1190.0, y: 360.0, pos: "LB"}
        ],
        "3v": [
            {A: "inline", B: "U", x: 200.0, y: 360.0, pos: "RB"},
            {A: "inline", B: "I", x: 300.0, y: 360.0, pos: "LB"},
            
            {A: "voltage1", B: "IHigh", x: 560, y: 360, pos: "LB"},
            {A: "voltage1", B: "ILow", x: 400, y: 630, pos: "RT", rely: {B: "U", move: "left"}},
    
            {A: "voltage2", B: "IHigh", x: 880, y: 360, pos: "LB"},
            {A: "voltage2", B: "T", x: 810, y: 580, pos: "LB"},
            {A: "voltage2", B: "U", x: 720, y: 630, pos: "RT"},
            {A: "voltage2", B: "ILow", x: 810, y: 630, pos: "LT"},
            
            {A: "voltage1", B: "capacity", x: 400, y: 580, pos: "RB", rely: {B: "T", move: "leftB"}, nomenu: true},
            {A: "voltage2", B: "capacity", x: 720, y: 580, pos: "RB", nomenu: true},
            {A: "voltage3", B: "capacity", x: 1130, y: 580, pos: "LB", rely: {B: "T", move: "rightB"}, nomenu: true},
    
            {A: "voltage3", B: "IHigh", x: 1200, y: 360, pos: "LB"},
            {A: "voltage3", B: "U", x: 1130, y: 630, pos: "LT", rely: {B: "ILow", move: "right"}}
        ],
        "3out": [
            {A: "inline", B: "U", x: 200.0, y: 360.0, pos: "RB"},
            {A: "inline", B: "I", x: 300.0, y: 360.0, pos: "LB"},
            
            {A: "voltage1", B: "IHigh", x: 530, y: 360, pos: "LB"},
            {A: "voltage1", B: "ILow", x: 380, y: 630, pos: "RT", rely: {B: "U", move: "left"}},
    
            {A: "voltage2", B: "IHigh", x: 820, y: 360, pos: "LB"},
            {A: "voltage2", B: "T", x: 750, y: 580, pos: "LB"},
            {A: "voltage2", B: "U", x: 670, y: 630, pos: "RT"},
            {A: "voltage2", B: "ILow", x: 750, y: 630, pos: "LT"},
    
            {A: "voltage3", B: "IHigh", x: 1100, y: 360, pos: "LB"},
            {A: "voltage3", B: "U", x: 1030, y: 630, pos: "LT", rely: {B: "ILow", move: "right"}},/*move right 表示依赖对象移动到右边*/
            
            {A: "voltage1", B: "capacity", x: 380, y: 580, pos: "RB", rely: {B: "T", move: "leftB"}, nomenu: true},
            {A: "voltage2", B: "capacity", x: 670, y: 580, pos: "RB", nomenu: true},
            {A: "voltage3", B: "capacity", x: 1030, y: 580, pos: "LB", rely: {B: "T", move: "rightB"}, nomenu: true},
            
            {A: "outline", B: "I", x: 1290.0, y: 360.0, pos: "LB"}
        ],
        SW: 1418.0,
        SH: 1000.0
    };

    SW、SH是原图尺寸,x、y是设计的时候,检测项目集合放置的位置,这些数据就可以计算出在图中位置的比例,根据这个比例乘以页面后底图实际的宽高,就可以得出显示的位置。这个pos是说明这个x、y这一点的位置,是这个集合框的四个顶点的哪个顶点的位置,T表示上(top),R表示右(right),B表示底部(bottom),L表示左(left),两两结合,便可以表示一个顶点,比如RB表示右下角的顶点。

    为什么要区分顶点来计算放置集合框?

    举例说吧,比如进线的(电压数据框)和(电流数据框),如下图,就拿电压数据框说,电压框如果记录左上角的位置,如果ua的值变成120.35KV,这个宽度肯定比0KV的宽度宽吧,那么显示后会怎么样呢?很明显,左上角位置不动,宽度增加,就会把进线的图给遮盖了,如下面的第二张图,这个肯定不是想要的结果。

      

    我们肯定希望,无论页面的宽高怎么变,文字的内容怎么变,我都要显示在进线的左方,母线的上方,那么唯一希望它不要变的一个点的位置,就是右下角的位置。

    rely是依赖关系,表示一个数据框的位置,要依赖另一个数据框的位置,move表示移动的方向,比如变压器的电压和电流两个数据框,如下图,电压框的位置是不固定的,他要依赖电流框左上角的位置,来计算自己的位置,也就是说,要先画出电流框,然后根据move的值来判断是显示在电流框的左边、右边、上边还是下边。详细的不说了,太多东西要写了。

    进线名称的位置、道闸的位置也是同一个道理

    /**
     * 进线名称位置
     */
    var InLineTitleData = {
        "1v": {x: 423.0, y: 160.0},
        "1out": {x: 422.0, y: 160.0},
        "2v": {x: 241.0, y: 160.0},
        "2out": {x: 243.0, y: 160.0},
        "3v": {x: 246.0, y: 160.0},
        "3out": {x: 243.0, y: 160.0}
    };
    /**
     * 道闸位置
     * VC: Vertical centering 垂直居中对齐
     */
    var KnifeData = {
        "1v": {
            "inline": {x: 423, y: 280, pos: "VC"},
            "voltage1": {x: 790, y: 800, pos: "VC"},
            "v1-high": {x: 847, y: 280, pos: "VC"}
        },
        "1out": {
            "inline": {x: 422, y: 280, pos: "VC"},
            "voltage1": {x: 710, y: 800, pos: "VC"},
            "v1-high": {x: 768, y: 280, pos: "VC"},
            "outline": {x: 1068, y: 280, pos: "VC"}
        },
        "2v": {
            "inline": {x: 241, y: 280, pos: "VC"},
            "voltage1": {x: 540, y: 800, pos: "VC"},
            "v1-high": {x: 597, y: 280, pos: "VC"},
            "voltage2": {x: 937, y: 800, pos: "VC"},
            "v2-high": {x: 994, y: 280, pos: "VC"}
        },
        "2out": {
            "inline": {x: 243, y: 280, pos: "VC"},
            "voltage1": {x: 497, y: 800, pos: "VC"},
            "v1-high": {x: 555, y: 280, pos: "VC"},
            "voltage2": {x: 814, y: 800, pos: "VC"},
            "v2-high": {x: 872, y: 280, pos: "VC"},
            "outline": {x: 1131, y: 280, pos: "VC"}
        },
        "3v": {
            "inline": {x: 246, y: 280, pos: "VC"},
            "voltage1": {x: 445, y: 800, pos: "VC"},
            "v1-high": {x: 504, y: 280, pos: "VC"},
            "voltage2": {x: 765, y: 800, pos: "VC"},
            "v2-high": {x: 822, y: 280, pos: "VC"},
            "voltage3": {x: 1081, y: 800, pos: "VC"},
            "v3-high": {x: 1138, y: 280, pos: "VC"}
        },
        "3out": {
            "inline": {x: 243, y: 280, pos: "VC"},
            "voltage1": {x: 421, y: 800, pos: "VC"},
            "v1-high": {x: 479, y: 280, pos: "VC"},
            "voltage2": {x: 706, y: 800, pos: "VC"},
            "v2-high": {x: 762, y: 280, pos: "VC"},
            "voltage3": {x: 987, y: 800, pos: "VC"},
            "v3-high": {x: 1045, y: 280, pos: "VC"},
            "outline": {x: 1234, y: 280, pos: "VC"}
        }
    };

    计算位置的代码

    /**
     * 封装有位置关联关系的两个bean
     */
    function MsgCompoundBean(r, data) {
        var MBAR = this;
        
        var H = r.height,
            W = r.width;
            
        var SH = RoomData.SH,
            SW = RoomData.SW;
    
        var x = data.x * W / SW,
            y = data.y * H / SH;
        
        var levelA = data.A,
            levelB = data.B;
    
        var msg = r.room.msg[levelA][levelB];
    
        var nomenu = data.nomenu || false;
        var bean = new MsgBean(r, {x: x, y: y, pos: data.pos, msg: msg, nomenu: nomenu});
        
        var relyBean = null;
        if (data.rely) {
            var move = data.rely.move;
            
            var rx = 0, 
                ry = 0;
                
            var rPos = "";
            
            if (move == "right") {
                rx = bean.x + bean.wi + 10;
                ry = bean.y;
                rPos = "LT";
            } else if (move == "left") {
                rx = bean.x - 10;
                ry = bean.y;
                rPos = "RT";
            } else if (move == "rightB") {
                rx = bean.x + bean.wi + 10;
                ry = bean.y + bean.he;
                rPos = "LB";
            } else if (move == "leftB") {
                rx = bean.x - 10;
                ry = bean.y + bean.he;
                rPos = "RB";
            }
            
            var rLeveB = data.rely.B;
            var rMsg = r.room.msg[levelA][rLeveB];
            
            var nomenu = data.rely.nomenu || false;
            relyBean = new MsgBean(r, {x: rx, y: ry, pos: rPos, msg: rMsg, nomenu: nomenu});
        }
        
        MBAR.remove = function(){
            bean.remove();
            if (relyBean != null) {
                relyBean.remove();
            }
        };
    }
    if (data.rely) 就是判断是否有依赖的数据框要画,下面就是画具体的数据框的封装
    /**
     * 封装单个数据块
     */
    function MsgBean(r, data) {
        var DRB = this;
        var msgset = new MySet(r);
    
        var    msg = data.msg,
            posX = data.x,
            posY = data.y,
            pos = data.pos;
        
        var gap = 25,/*每条信息的高度*/
            marginLR = 10;
            
        var wi = tool_GetMsgWi(r, msg, marginLR, TextStyle), 
            he = msg.length * gap;
        
        var x = 0, 
            y = 0;
            
        if (pos == "RB") {
            x = posX - wi;
            y = posY - he;
        } else if (pos == "LB") {
            x = posX;
            y = posY - he;
        } else if (pos == "RT") {
            x = posX - wi;
            y = posY;
        } else { /*LT*/
            x = posX;
            y = posY;
        }
        
        var myBody = r.rect(x, y, wi, he, 5).attr({fill: "#2B2727", stroke: "gray", "stroke-width": 1});
        
        var texty = y;
        for (var i in msg) {
            var textI = new MyText(r, x, texty, wi, gap, msg[i], marginLR, TextStyle, data.nomenu);
            msgset.push(textI);
            texty = texty + gap;
        }
        
        DRB.wi = wi;
        DRB.he = he;
        DRB.x = x;
        DRB.y = y;
        
        DRB.remove = function(){
            msgset.remove();
            myBody.remove();
        };
    
    }

    整个配电室封装的js

    /**
     * 封装整个配电室对象
     */
    function MyRoom(r, data) {
        var MR = this;
        
        var id = data.id;
        var type = data.type;
        var roomname = data.name;
    
        var H = r.height,
            W = r.width;
        
        var baseimg = BaseMapImg[type];
        var map = r.image(baseimg, 0, 0, W, H);
        
        var title = r.text(W / 2, 30, roomname).attr(TitleTextStyle);
        
        //进线名称
        var inlinedata = InLineTitleData[type];
        var inlinename = data.inlinename || "none";
        var inlinetitle = r.text(0, 0, inlinename).attr(TextStyle);
        
        var data = RoomData[type];
        var beanset = new MySet(r);
    
        var flashData = function() {
            //进线名称
            inlinetitle.remove();
            var SH = RoomData.SH,
                SW = RoomData.SW;
            var inx = inlinedata.x * r.width / SW,
                iny = inlinedata.y * r.height / SH;
            inlinetitle = r.text(inx, iny, inlinename).attr(TextStyle).attr({cursor: "default"});
            
            //监测项目
            beanset.clear();
            for (var i in data) {
                var bean = new MsgCompoundBean(r, data[i]);
                beanset.push(bean);
            }
            
            //刀闸
            var knife = new MyKnifeGate(r);
            beanset.push(knife);
        };
        
        var selectMe = function(){
            r.map = map;
            r.title = title;
            r.type = type;
            r.roomid = id;
            
            map.show();
            title.show();
            
            flashData();
        };
    
        MR.remove = function(){
            beanset.clear();
            inlinetitle.remove();
            
            map.hide();
            title.hide();
        };
        
        MR.flashData = flashData;
        
        MR.selectMe = selectMe;
        
    }
    var flashData = function() 是监控的时候,检测项目值改变后,重新渲染页面(仅仅是局部渲染,仅渲染检测项目,这样效率比较高)

    三、右键菜单功能及右边栏隐藏的功能

        

    这个右键就是在检测项目上加一个半透明的遮罩层,鼠标移动上去后,控制遮罩层的显示和隐藏,有个动态的效果,再有就是计算下右键菜单显示的位置,一般是显示在右下角,除非是超出边界,需要计算下位置。查看曲线查看报表也就是携带检测项目id,去查找检测项目的历史数据,然后出图出报表。

    右边栏隐藏和展示,就是重新渲染一下检测项目的位置

    细节太多,代码就不再贴了,中午了,好饿,吃饭去。

  • 相关阅读:
    一个强悍的强制删除文件的批处理
    禁止用户使用QQ聊天工具
    《项目经理指导手册》附录2项目经理面试题
    《项目经理指导手册》 附录1每日站会评价表
    《项目经理指导手册》调研篇
    《项目经理指导手册》前言
    《项目经理指导手册》 会议篇
    从Log4j2今天的漏洞说起.
    Asp.Net将Excel数据导入Sql Server数据库的的例子
    Winform窗体程序输入法全角问题
  • 原文地址:https://www.cnblogs.com/LcxSummer/p/9335068.html
Copyright © 2011-2022 走看看